From a332f826a7219c6aa8dda0df538c932963ef0573 Mon Sep 17 00:00:00 2001 From: Andi Gutmans Date: Sun, 4 Nov 2001 19:30:49 +0000 Subject: [PATCH] - Support instantiation of nested class. The following script now should - work: -bar(); - - $obj = new foo::barbara(); - $obj->bar(); - --- Zend/zend_compile.c | 18 +++++++++--------- Zend/zend_compile.h | 4 ++-- Zend/zend_execute.c | 38 +++++++++++++++++++------------------ Zend/zend_language_parser.y | 7 ++++--- 4 files changed, 35 insertions(+), 32 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 2185ed4fb7..a9f0a09e7a 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -914,6 +914,7 @@ void do_fetch_class(znode *result, znode *class_entry, znode *class_name TSRMLS_ } else { SET_UNUSED(opline->op1); } + zend_str_tolower(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len); opline->op2 = *class_name; opline->result.u.var = get_temporary_variable(CG(active_op_array)); opline->result.op_type = IS_CONST; /* FIXME: Hack so that INIT_FCALL_BY_NAME still knows this is a class */ @@ -948,12 +949,14 @@ void zend_do_end_function_call(znode *function_name, znode *result, znode *argum { zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); - if (function_name->op_type==IS_CONST && !is_method && !is_dynamic_fcall) { + if (!is_method && !is_dynamic_fcall && function_name->op_type==IS_CONST) { opline->opcode = ZEND_DO_FCALL; + opline->op1 = *function_name; } else { opline->opcode = ZEND_DO_FCALL_BY_NAME; + SET_UNUSED(opline->op1); } - opline->op1 = *function_name; + opline->result.u.var = get_temporary_variable(CG(active_op_array)); opline->result.op_type = IS_VAR; *result = opline->result; @@ -1824,7 +1827,7 @@ void zend_do_pop_object(znode *object TSRMLS_DC) } -void zend_do_begin_new_object(znode *new_token, znode *class_name TSRMLS_DC) +void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC) { zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); unsigned char *ptr = NULL; @@ -1832,7 +1835,7 @@ void zend_do_begin_new_object(znode *new_token, znode *class_name TSRMLS_DC) opline->opcode = ZEND_NEW; opline->result.op_type = IS_VAR; opline->result.u.var = get_temporary_variable(CG(active_op_array)); - opline->op1 = *class_name; + opline->op1 = *class_type; SET_UNUSED(opline->op2); new_token->u.opline_num = get_next_op_number(CG(active_op_array)); @@ -1851,14 +1854,11 @@ void zend_do_begin_new_object(znode *new_token, znode *class_name TSRMLS_DC) } -void zend_do_end_new_object(znode *result, znode *class_name, znode *new_token, znode *argument_list TSRMLS_DC) +void zend_do_end_new_object(znode *result, znode *new_token, znode *argument_list TSRMLS_DC) { znode ctor_result; - if (class_name->op_type == IS_CONST) { - zval_copy_ctor(&class_name->u.constant); - } - zend_do_end_function_call(class_name, &ctor_result, argument_list, 1, 0 TSRMLS_CC); + zend_do_end_function_call(NULL, &ctor_result, argument_list, 1, 0 TSRMLS_CC); zend_do_free(&ctor_result TSRMLS_CC); CG(active_op_array)->opcodes[new_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array)); diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 17d88c85e9..b371cdc5eb 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -313,8 +313,8 @@ void zend_do_push_object(znode *object TSRMLS_DC); void zend_do_pop_object(znode *object TSRMLS_DC); -void zend_do_begin_new_object(znode *new_token, znode *class_name TSRMLS_DC); -void zend_do_end_new_object(znode *result, znode *class_name, znode *new_token, znode *argument_list TSRMLS_DC); +void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC); +void zend_do_end_new_object(znode *result, znode *new_token, znode *argument_list TSRMLS_DC); void zend_do_fetch_constant(znode *result, znode *constant_name, int mode TSRMLS_DC); diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index d63a13e21c..efc82dfc5f 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1487,9 +1487,24 @@ binary_assign_op_addr: { case ZEND_FETCH_CLASS: { if (EX(opline)->op1.op_type == IS_UNUSED) { - if (zend_hash_find(EG(class_table), EX(opline)->op2.u.constant.value.str.val, EX(opline)->op2.u.constant.value.str.len+1, &EX(Ts)[EX(opline)->result.u.var].EA.class_entry) == FAILURE) { - zend_error(E_ERROR, "Class '%s' not found", EX(opline)->op2.u.constant.value.str.val); + zval tmp; + zval *class_name = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R); + + if (class_name->type != IS_STRING) { + tmp = *class_name; + zval_copy_ctor(&tmp); + convert_to_string(&tmp); + class_name = &tmp; + zend_str_tolower(tmp.value.str.val, tmp.value.str.len); + } + + if (zend_hash_find(EG(class_table), class_name->value.str.val, class_name->value.str.len+1, &EX(Ts)[EX(opline)->result.u.var].EA.class_entry) == FAILURE) { + zend_error(E_ERROR, "Class '%s' not found", class_name->value.str.val); + } + if (class_name == &tmp) { + zval_dtor(&tmp); } + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); } else { if (zend_hash_find(&EX(Ts)[EX(opline)->op1.u.var].EA.class_entry->class_table, EX(opline)->op2.u.constant.value.str.val, EX(opline)->op2.u.constant.value.str.len+1, &EX(Ts)[EX(opline)->result.u.var].EA.class_entry) == FAILURE) { zend_error(E_ERROR, "Class '%s' not found", EX(opline)->op2.u.constant.value.str.val); @@ -2015,26 +2030,13 @@ send_by_ref: case ZEND_SWITCH_FREE: zend_switch_free(EX(opline), EX(Ts) TSRMLS_CC); NEXT_OPCODE(); - case ZEND_NEW: { - zval *tmp = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); - zval class_name; - zend_class_entry *ce; - - class_name = *tmp; - zval_copy_ctor(&class_name); - convert_to_string(&class_name); - zend_str_tolower(class_name.value.str.val, class_name.value.str.len); - - if (zend_hash_find(EG(class_table), class_name.value.str.val, class_name.value.str.len+1, (void **) &ce)==FAILURE) { - zend_error(E_ERROR, "Cannot instantiate non-existent class: %s", class_name.value.str.val); - } + case ZEND_NEW: + { EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr = &EX(Ts)[EX(opline)->result.u.var].var.ptr; ALLOC_ZVAL(EX(Ts)[EX(opline)->result.u.var].var.ptr); - object_init_ex(EX(Ts)[EX(opline)->result.u.var].var.ptr, ce); + object_init_ex(EX(Ts)[EX(opline)->result.u.var].var.ptr, EX(Ts)[EX(opline)->op1.u.var].EA.class_entry); EX(Ts)[EX(opline)->result.u.var].var.ptr->refcount=1; EX(Ts)[EX(opline)->result.u.var].var.ptr->is_ref=1; - zval_dtor(&class_name); - FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); } NEXT_OPCODE(); case ZEND_FETCH_CONSTANT: diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 67b6af8f99..a32234e3ec 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -429,8 +429,8 @@ expr_without_variable: | cvar '=' expr { zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign(&$$, &$1, &$3 TSRMLS_CC); } | cvar '=' '&' w_cvar { zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$4 TSRMLS_CC); } | cvar '=' '&' function_call { zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$4 TSRMLS_CC); } - | cvar '=' '&' T_NEW static_or_variable_string { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$5, &$4, &$7 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); } - | T_NEW static_or_variable_string { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$2, &$1, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} + | cvar '=' '&' T_NEW parse_class_entry { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$4, &$7 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); } + | T_NEW parse_class_entry { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$1, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} | cvar T_PLUS_EQUAL expr { zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 TSRMLS_CC); } | cvar T_MINUS_EQUAL expr { zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 TSRMLS_CC); } | cvar T_MUL_EQUAL expr { zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_MUL, &$$, &$1, &$3 TSRMLS_CC); } @@ -509,7 +509,8 @@ function_call: parse_class_entry: parse_class_entry T_PAAMAYIM_NEKUDOTAYIM T_STRING { do_fetch_class(&$$, &$1, &$3 TSRMLS_CC); } - | T_STRING { do_fetch_class(&$$, NULL, &$1 TSRMLS_CC); } + | static_or_variable_string { /* Using static_or_variable_string and not T_STRING because NEW supported $var */ + do_fetch_class(&$$, NULL, &$1 TSRMLS_CC); } ; static_or_variable_string: -- 2.40.0