summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
authorAndi Gutmans <andi@php.net>2001-11-04 19:30:49 +0000
committerAndi Gutmans <andi@php.net>2001-11-04 19:30:49 +0000
commita332f826a7219c6aa8dda0df538c932963ef0573 (patch)
tree62e2e4e913ebd0c638aa5982370ae53e11566175 /Zend
parentbddb9539f71cfcfd5d13a721903ae54f8a08bfea (diff)
downloadphp-git-a332f826a7219c6aa8dda0df538c932963ef0573.tar.gz
- Support instantiation of nested class. The following script now should
- work: -<?php - class foo - { - function bar() - { - print "bar() in class bar\n"; - } - - class barbara - { - function bar() - { - print "bar() in class foo::barbara\n"; - } - } - } - - $obj = new foo(); - $obj->bar(); - - $obj = new foo::barbara(); - $obj->bar(); -
Diffstat (limited to 'Zend')
-rw-r--r--Zend/zend_compile.c18
-rw-r--r--Zend/zend_compile.h4
-rw-r--r--Zend/zend_execute.c38
-rw-r--r--Zend/zend_language_parser.y7
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: