From cb1a40f39912f7612886cf82b79ab589e5b3ec0e Mon Sep 17 00:00:00 2001 From: Andi Gutmans Date: Wed, 8 Aug 2001 15:07:11 +0000 Subject: [PATCH] - Preliminary patch for method() dereferencing --- Zend/zend_compile.c | 116 +++++++++++++++++++++--------------- Zend/zend_compile.h | 1 + Zend/zend_language_parser.y | 14 +++-- 3 files changed, 78 insertions(+), 53 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index b34e6ff93a..c0f068a409 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -508,6 +508,15 @@ void zend_do_if_end(TSRMLS_D) } +zend_bool zend_variable_buffer_empty(TSRMLS_D) +{ + zend_llist *fetch_list_ptr; + + zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr); + return !fetch_list_ptr->head; +} + + void zend_do_begin_variable_parse(TSRMLS_D) { zend_llist fetch_list; @@ -561,27 +570,6 @@ void zend_do_end_variable_parse(int type, int arg_offset TSRMLS_DC) } -static zend_bool is_method_call(TSRMLS_D) -{ - zend_llist *fetch_list_ptr; - zend_llist_element *cur; - zend_op *cur_opline; - - zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr); - - cur = fetch_list_ptr->head; - /* There is always at least one node in the list */ - while (cur->next) { - cur = cur->next; - } - cur_opline = (zend_op *)cur->data; - if (cur_opline->opcode == ZEND_FETCH_OBJ_W) { - return 1; - } - return 0; -} - - void zend_do_init_string(znode *result TSRMLS_DC) { zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); @@ -837,31 +825,47 @@ int zend_do_begin_function_call(znode *function_name TSRMLS_DC) } -void zend_do_begin_dynamic_function_call(znode *function_name TSRMLS_DC) + +void zend_do_begin_method_call(znode *object, znode *function_name TSRMLS_DC) { + zend_op *opline; unsigned char *ptr = NULL; - int last_op_number; - zend_op *last_op; - if (function_name->op_type != IS_CONST && is_method_call(TSRMLS_C)) { - zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); - last_op_number = get_next_op_number(CG(active_op_array))-1; - last_op = &CG(active_op_array)->opcodes[last_op_number]; - last_op->opcode = ZEND_INIT_FCALL_BY_NAME; - last_op->extended_value = ZEND_MEMBER_FUNC_CALL; - } else { - zend_op *opline; - - if (function_name->op_type != IS_CONST) { - zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); - } + zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); + zend_do_begin_variable_parse(TSRMLS_C); + + opline = get_next_op(CG(active_op_array) TSRMLS_CC); + opline->opcode = ZEND_INIT_FCALL_BY_NAME; + opline->extended_value = ZEND_MEMBER_FUNC_CALL; + opline->op1 = *object; + opline->op2 = *function_name; + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + opline->result.op_type = IS_VAR; + - opline = get_next_op(CG(active_op_array) TSRMLS_CC); - opline->opcode = ZEND_INIT_FCALL_BY_NAME; - opline->op2 = *function_name; - opline->extended_value = 0; - SET_UNUSED(opline->op1); + *function_name = opline->result; +/* + if (function_name->op_type == IS_CONST) { + zval_copy_ctor(&function_name->u.constant); } +*/ + + zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *)); + zend_do_extended_fcall_begin(TSRMLS_C); +} + + +void zend_do_begin_dynamic_function_call(znode *function_name TSRMLS_DC) +{ + unsigned char *ptr = NULL; + zend_op *opline; + + opline = get_next_op(CG(active_op_array) TSRMLS_CC); + opline->opcode = ZEND_INIT_FCALL_BY_NAME; + opline->op2 = *function_name; + opline->extended_value = 0; + SET_UNUSED(opline->op1); + zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *)); zend_do_extended_fcall_begin(TSRMLS_C); } @@ -941,8 +945,12 @@ void zend_do_pass_param(znode *param, int op, int offset TSRMLS_DC) send_by_reference = ARG_SHOULD_BE_SENT_BY_REF(offset, 1, arg_types)?ZEND_ARG_SEND_BY_REF:0; - if (op == ZEND_SEND_VAL && param->op_type == IS_VAR) { - op = ZEND_SEND_VAR_NO_REF; + + if (op == ZEND_SEND_VAR && zend_variable_buffer_empty(TSRMLS_C)) { + /* Method call */ + op = ZEND_SEND_VAR_NO_REF; + } else if (op == ZEND_SEND_VAL && param->op_type == IS_VAR) { + op = ZEND_SEND_VAR_NO_REF; } if (op!=ZEND_SEND_VAR_NO_REF && send_by_reference == ZEND_ARG_SEND_BY_REF) { @@ -2060,7 +2068,21 @@ void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC void zend_do_foreach_begin(znode *foreach_token, znode *array, znode *open_brackets_token, znode *as_token, int variable TSRMLS_DC) { - zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); + zend_op *opline; + zend_bool is_variable; + + if (variable) { + if (zend_variable_buffer_empty(TSRMLS_C)) { + is_variable = 0; + } else { + is_variable = 1; + } + zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); + } else { + is_variable = 0; + } + + opline = get_next_op(CG(active_op_array) TSRMLS_CC); /* Preform array reset */ opline->opcode = ZEND_FE_RESET; @@ -2068,11 +2090,7 @@ void zend_do_foreach_begin(znode *foreach_token, znode *array, znode *open_brack opline->result.u.var = get_temporary_variable(CG(active_op_array)); opline->op1 = *array; SET_UNUSED(opline->op2); - if (variable) { - opline->extended_value = 1; - } else { - opline->extended_value = 0; - } + opline->extended_value = is_variable; *open_brackets_token = opline->result; zend_stack_push(&CG(foreach_copy_stack), (void *) &opline->result, sizeof(znode)); diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 3fd85e527a..4089309d62 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -275,6 +275,7 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n void zend_do_end_function_declaration(znode *function_token TSRMLS_DC); void zend_do_receive_arg(int op, znode *var, znode *offset, znode *initialization, unsigned char pass_type TSRMLS_DC); int zend_do_begin_function_call(znode *function_name TSRMLS_DC); +void zend_do_begin_method_call(znode *object, znode *function_name TSRMLS_DC); void zend_do_begin_dynamic_function_call(znode *function_name TSRMLS_DC); void zend_do_begin_class_member_function_call(znode *class_name, znode *function_name TSRMLS_DC); void zend_do_end_function_call(znode *function_name, znode *result, znode *argument_list, int is_method, int is_dynamic_fcall TSRMLS_DC); diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index d5ea4d14f0..a3679d4677 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -197,7 +197,7 @@ unticked_statement: | expr ';' { zend_do_free(&$1 TSRMLS_CC); } | T_USE use_filename ';' { zend_error(E_COMPILE_ERROR,"use: Not yet supported. Please use include_once() or require_once()"); zval_dtor(&$2.u.constant); } | T_UNSET '(' unset_variables ')' ';' - | T_FOREACH '(' w_cvar T_AS { zend_do_foreach_begin(&$1, &$3, &$2, &$4, 1 TSRMLS_CC); } w_cvar foreach_optional_arg ')' { zend_do_foreach_cont(&$6, &$7, &$4 TSRMLS_CC); } foreach_statement { zend_do_foreach_end(&$1, &$2 TSRMLS_CC); } + | T_FOREACH '(' cvar T_AS { zend_do_foreach_begin(&$1, &$3, &$2, &$4, 1 TSRMLS_CC); } w_cvar foreach_optional_arg ')' { zend_do_foreach_cont(&$6, &$7, &$4 TSRMLS_CC); } foreach_statement { zend_do_foreach_end(&$1, &$2 TSRMLS_CC); } | T_FOREACH '(' expr_without_variable T_AS { zend_do_foreach_begin(&$1, &$3, &$2, &$4, 0 TSRMLS_CC); } w_cvar foreach_optional_arg ')' { zend_do_foreach_cont(&$6, &$7, &$4 TSRMLS_CC); } foreach_statement { zend_do_foreach_end(&$1, &$2 TSRMLS_CC); } | T_DECLARE { zend_do_declare_begin(TSRMLS_C); } '(' declare_list ')' declare_statement { zend_do_declare_end(TSRMLS_C); } | ';' /* empty statement */ @@ -490,12 +490,13 @@ function_call: T_STRING '(' { $2.u.opline_num = zend_do_begin_function_call(&$1 TSRMLS_CC); } function_call_parameter_list ')' { zend_do_end_function_call(&$1, &$$, &$4, 0, $2.u.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); } - | cvar '(' { zend_do_begin_dynamic_function_call(&$1 TSRMLS_CC); } - function_call_parameter_list - ')' { zend_do_end_function_call(&$1, &$$, &$4, 0, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} | T_STRING T_PAAMAYIM_NEKUDOTAYIM static_or_variable_string '(' { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); } function_call_parameter_list ')' { zend_do_end_function_call(&$3, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} + | cvar_without_objects '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1 TSRMLS_CC); } + function_call_parameter_list ')' + { zend_do_end_function_call(&$1, &$$, &$4, 0, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} + ; @@ -621,6 +622,11 @@ ref_list: object_property: object_dim_list { $$ = $1; } | cvar_without_objects { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); } { znode tmp_znode; zend_do_pop_object(&tmp_znode TSRMLS_CC); zend_do_fetch_property(&$$, &tmp_znode, &$1 TSRMLS_CC);} + | cvar_without_objects '(' { znode tmp_znode; zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_pop_object(&tmp_znode TSRMLS_CC); zend_do_begin_method_call(&tmp_znode, &$1 TSRMLS_CC); } + function_call_parameter_list ')' { zend_do_end_function_call(&$1, &$$, &$4, 0, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} + | variable_name '(' { znode tmp_znode; zend_do_pop_object(&tmp_znode TSRMLS_CC); zend_do_begin_method_call(&tmp_znode, &$1 TSRMLS_CC); } + function_call_parameter_list ')' { zend_do_end_function_call(&$1, &$$, &$4, 0, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} + ; object_dim_list: -- 2.40.0