cvs: ZendEngine2 / zend_API.c zend_compile.c zend_compile.h zend_execute_API.c zend_language_parser.y
| From: | Dmitry Stogov | Date: | Mon, 20 Aug 2007 09:48:41 +0000 |
| Subject: | cvs: ZendEngine2 / zend_API.c zend_compile.c zend_compile.h zend_execute_API.c zend_language_parser.y | ||
| Groups: | php.zend-engine.cvs | ||
| Request: | Send a blank email to php-zend-engine-cvs+get-5961@lists.php.net to get a copy of this message | ||
dmitry Mon Aug 20 09:48:41 2007 UTC
Modified files:
/ZendEngine2 zend_API.c zend_compile.c zend_compile.h
zend_execute_API.c zend_language_parser.y
Log:
Added namespace related optimizations and comments
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_API.c?r1=1.441&r2=1.442&diff_format=u Index: ZendEngine2/zend_API.c diff -u ZendEngine2/zend_API.c:1.441 ZendEngine2/zend_API.c:1.442 --- ZendEngine2/zend_API.c:1.441 Sat Jul 21 05:27:06 2007 +++ ZendEngine2/zend_API.c Mon Aug 20 09:48:41 2007 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_API.c,v 1.441 2007/07/21 05:27:06 pollita Exp $ */ +/* $Id: zend_API.c,v 1.442 2007/08/20 09:48:41 dmitry Exp $ */ #include "zend.h" #include "zend_execute.h" @@ -801,7 +801,7 @@ fci->size = 0; fcc->initialized = 0; break; - } + } if (zend_fcall_info_init(*arg, fci, fcc, NULL TSRMLS_CC) == SUCCESS) { break; @@ -1001,7 +1001,7 @@ break; } } - + if (T_arg_type == -1) { T_arg_type = ZEND_STR_TYPE; } @@ -1070,7 +1070,7 @@ get_active_function_name(TSRMLS_C), __num_args); \ return FAILURE; \ }\ -} +} ZEND_API int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, char *type_spec, ...) /* {{{ */ { @@ -2084,7 +2084,7 @@ if (UG(unicode)) { zend_arg_info *args; int n = ptr->num_args; - + args = internal_function->arg_info = malloc((n + 1) * sizeof(zend_arg_info)); memcpy(args, ptr->arg_info+1, (n + 1) * sizeof(zend_arg_info)); while (n > 0) { @@ -2175,7 +2175,7 @@ */ unsigned int lc_func_name_len; zstr lc_func_name = zend_u_str_case_fold(ZEND_STR_TYPE, internal_function->function_name, fname_len, 0, &lc_func_name_len); - + if ((lc_func_name_len == lc_class_name_len) && !memcmp(lc_func_name.v, lc_class_name.v, UG(unicode)?UBYTES(lc_class_name_len):lc_class_name_len) && !ctor) { ctor = reg_function; } else if ((fname_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME))) { @@ -2368,7 +2368,7 @@ module->module_shutdown_func(module->type, module->module_number TSRMLS_CC); } - + /* Deinitilaise module globals */ if (module->globals_size) { #ifdef ZTS @@ -2498,7 +2498,7 @@ interface_entry = va_arg(interface_list, zend_class_entry *); zend_do_implement_interface(class_entry, interface_entry TSRMLS_CC); } - + va_end(interface_list); } /* }}} */ @@ -2607,6 +2607,7 @@ *fptr_ptr = NULL; if (!ce_org) { + /* Skip leading :: */ if (Z_TYPE_P(callable) == IS_UNICODE && Z_USTRVAL_P(callable)[0] == ':' && Z_USTRVAL_P(callable)[1] == ':') { @@ -2624,6 +2625,8 @@ } else { lmname = zend_u_str_case_fold(Z_TYPE_P(callable), Z_UNIVAL_P(callable), Z_UNILEN_P(callable), 1, &mlen); } + /* Check if function with given name exists. + This may be a compound name that includes namespace name */ if (zend_u_hash_find(EG(function_table), Z_TYPE_P(callable), lmname, mlen+1, (void**)&fptr) == SUCCESS) { *fptr_ptr = fptr; efree(lmname.v); @@ -2631,6 +2634,7 @@ } efree(lmname.v); } + /* Split name into class/namespace and method/function names */ if (Z_TYPE_P(callable) == IS_UNICODE) { if ((colon.u = u_strrstr(Z_USTRVAL_P(callable), u_doublecolon)) != NULL) { mlen = u_strlen(colon.u+2); @@ -2648,6 +2652,8 @@ } } if (colon.v != NULL) { + /* This is a compound name. + Try to fetch class and then find static method. */ *ce_ptr = zend_u_fetch_class(Z_TYPE_P(callable), Z_UNIVAL_P(callable), clen, ZEND_FETCH_CLASS_AUTO TSRMLS_CC); if (!*ce_ptr) { return 0; @@ -2657,14 +2663,14 @@ return 0; } lmname = zend_u_str_case_fold(Z_TYPE_P(callable), mname, mlen, 1, &mlen); - } else { + } else if (ce_org) { + /* Try to fetch find static method of given class. */ lmname = zend_u_str_case_fold(Z_TYPE_P(callable), Z_UNIVAL_P(callable), Z_UNILEN_P(callable), 1, &mlen); - if (ce_org) { - ftable = &ce_org->function_table; - *ce_ptr = ce_org; - } else { - ftable = EG(function_table); - } + ftable = &ce_org->function_table; + *ce_ptr = ce_org; + } else { + /* We already checked for plain function before. */ + return 0; } retval = zend_u_hash_find(ftable, Z_TYPE_P(callable), lmname, mlen+1, (void**)&fptr) == SUCCESS ? 1 : 0; @@ -2968,7 +2974,7 @@ fci->symbol_table = NULL; if (ZEND_U_CASE_EQUAL(ZEND_STR_TYPE, func->common.function_name, USTR_LEN(func->common.function_name), ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1) || - ZEND_U_CASE_EQUAL(ZEND_STR_TYPE, func->common.function_name, USTR_LEN(func->common.function_name), ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1)) { + ZEND_U_CASE_EQUAL(ZEND_STR_TYPE, func->common.function_name, USTR_LEN(func->common.function_name), ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1)) { fcc->initialized = 0; fcc->function_handler = NULL; fcc->calling_scope = NULL; @@ -3048,13 +3054,13 @@ ZEND_API int zend_fcall_info_argp(zend_fcall_info *fci TSRMLS_DC, int argc, zval ***argv) /* {{{ */ { int i; - + if (argc < 0) { return FAILURE; } - + zend_fcall_info_args_clear(fci, !argc); - + if (argc) { fci->param_count = argc; fci->params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **)); @@ -3064,7 +3070,7 @@ fci->params[i] = argv[i]; } } - + return SUCCESS; } /* }}} */ @@ -3073,24 +3079,24 @@ { int i; zval **arg; - + if (argc < 0) { return FAILURE; } - + zend_fcall_info_args_clear(fci, !argc); - + if (argc) { fci->param_count = argc; fci->params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **)); - + for (i = 0; i < argc; ++i) { arg = va_arg(*argv, zval **); ZVAL_ADDREF(*arg); fci->params[i] = arg; } } - + return SUCCESS; } /* }}} */ @@ -3099,11 +3105,11 @@ { int ret; va_list argv; - + va_start(argv, argc); ret = zend_fcall_info_argv(fci TSRMLS_CC, argc, &argv); va_end(argv); - + return ret; } /* }}} */ @@ -3119,7 +3125,7 @@ zend_fcall_info_args(fci, args TSRMLS_CC); } result = zend_call_function(fci, fcc TSRMLS_CC); - + if (!retval_ptr_ptr && retval) { zval_ptr_dtor(&retval); } @@ -3439,7 +3445,7 @@ { zval *constant; - if (ce->type & ZEND_INTERNAL_CLASS) { + if (ce->type & ZEND_INTERNAL_CLASS) { constant = malloc(sizeof(zval)); if (UG(unicode)) { Z_TYPE_P(constant) = IS_UNICODE; http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_compile.c?r1=1.761&r2=1.762&diff_format=u Index: ZendEngine2/zend_compile.c diff -u ZendEngine2/zend_compile.c:1.761 ZendEngine2/zend_compile.c:1.762 --- ZendEngine2/zend_compile.c:1.761 Fri Aug 17 12:05:19 2007 +++ ZendEngine2/zend_compile.c Mon Aug 20 09:48:41 2007 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_compile.c,v 1.761 2007/08/17 12:05:19 dmitry Exp $ */ +/* $Id: zend_compile.c,v 1.762 2007/08/20 09:48:41 dmitry Exp $ */ #include <zend_language_parser.h> #include "zend.h" @@ -1245,6 +1245,7 @@ zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); if (CG(current_namespace)) { + /* Prefix function name with current namespcae name */ znode tmp; tmp.u.constant = *CG(current_namespace); @@ -1451,8 +1452,11 @@ zend_function *function; unsigned int lcname_len; zstr lcname; + int prefix_len = 0; if (check_namespace && CG(current_namespace)) { + /* We assume we call function from the current namespace + if it is not prefixed. */ znode tmp; tmp.op_type = IS_CONST; @@ -1460,11 +1464,15 @@ zval_copy_ctor(&tmp.u.constant); zend_do_build_namespace_name(&tmp, &tmp, function_name TSRMLS_CC); *function_name = tmp; + + /* In run-time PHP will check for function with full name and + internal function with short name */ + prefix_len = Z_UNILEN_P(CG(current_namespace)) + 2; } lcname = zend_u_str_case_fold(Z_TYPE(function_name->u.constant), Z_UNIVAL(function_name->u.constant), Z_UNILEN(function_name->u.constant), 0, &lcname_len); if (zend_u_hash_find(CG(function_table), Z_TYPE(function_name->u.constant), lcname, lcname_len+1, (void **) &function)==FAILURE) { - zend_do_begin_dynamic_function_call(function_name TSRMLS_CC); + zend_do_begin_dynamic_function_call(function_name, prefix_len TSRMLS_CC); efree(lcname.v); return 1; /* Dynamic */ } @@ -1547,7 +1555,7 @@ } /* }}} */ -void zend_do_begin_dynamic_function_call(znode *function_name TSRMLS_DC) /* {{{ */ +void zend_do_begin_dynamic_function_call(znode *function_name, int prefix_len TSRMLS_DC) /* {{{ */ { unsigned char *ptr = NULL; zend_op *opline; @@ -1557,21 +1565,13 @@ opline->op2 = *function_name; opline->extended_value = 0; - SET_UNUSED(opline->op1); - if (function_name->op_type == IS_CONST) { - if (Z_TYPE(function_name->u.constant) == IS_UNICODE) { - UChar *p = u_memrchr(Z_USTRVAL(function_name->u.constant), ':', Z_USTRLEN(function_name->u.constant)); - if (p) { - opline->op1.op_type = IS_CONST; - ZVAL_LONG(&opline->op1.u.constant, p + 1 - Z_USTRVAL(function_name->u.constant)); - } - } else { - char *p = zend_memrchr(Z_STRVAL(function_name->u.constant), ':', Z_STRLEN(function_name->u.constant)); - if (p) { - opline->op1.op_type = IS_CONST; - ZVAL_LONG(&opline->op1.u.constant, p + 1 - Z_STRVAL(function_name->u.constant)); - } - } + if (prefix_len) { + /* In run-time PHP will check for function with full name and + internal function with short name */ + opline->op1.op_type = IS_CONST; + ZVAL_LONG(&opline->op1.u.constant, prefix_len); + } else { + SET_UNUSED(opline->op1); } zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *)); @@ -1594,15 +1594,18 @@ compound.s = memchr(Z_STRVAL(class_name->u.constant), ':', Z_STRLEN(class_name->u.constant)); } if (compound.v) { + /* This is a compound class name that cotains namespace prefix */ if (Z_TYPE(class_name->u.constant) == IS_UNICODE && Z_USTRVAL(class_name->u.constant)[0] == ':') { + /* The unicode name has "::" prefix */ Z_USTRLEN(class_name->u.constant) -= 2; memmove(Z_USTRVAL(class_name->u.constant), Z_USTRVAL(class_name->u.constant)+2, UBYTES(Z_USTRLEN(class_name->u.constant)+1)); Z_USTRVAL(class_name->u.constant) = eurealloc( Z_USTRVAL(class_name->u.constant), Z_USTRLEN(class_name->u.constant) + 1); } else if (Z_TYPE(class_name->u.constant) == IS_STRING && - Z_STRVAL(class_name->u.constant)[0] == ':') { + Z_STRVAL(class_name->u.constant)[0] == ':') { + /* The STRING name has "::" prefix */ Z_STRLEN(class_name->u.constant) -= 2; memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+2, Z_STRLEN(class_name->u.constant)+1); Z_STRVAL(class_name->u.constant) = erealloc( @@ -1616,7 +1619,9 @@ len = compound.s - Z_STRVAL(class_name->u.constant); lcname = zend_u_str_case_fold(Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant), len , 0, &lcname_len); } + /* Check if first part of compound name is an import name */ if (zend_u_hash_find(CG(current_import), Z_TYPE(class_name->u.constant), lcname, lcname_len+1, (void**)&ns) == SUCCESS) { + /* Substitute import name */ tmp.op_type = IS_CONST; tmp.u.constant = **ns; zval_copy_ctor(&tmp.u.constant); @@ -1631,12 +1636,14 @@ *class_name = tmp; } efree(lcname.v); - } + } } else if (CG(current_import) || CG(current_namespace)) { + /* this is a plain name (without ::) */ lcname = zend_u_str_case_fold(Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant), Z_UNILEN(class_name->u.constant), 0, &lcname_len); if (CG(current_import) && zend_u_hash_find(CG(current_import), Z_TYPE(class_name->u.constant), lcname, lcname_len+1, (void**)&ns) == SUCCESS) { + /* The given name is an import name. Substitute it. */ zval_dtor(&class_name->u.constant); class_name->u.constant = **ns; zval_copy_ctor(&class_name->u.constant); @@ -1649,6 +1656,9 @@ if (ns_lcname_len == lcname_len && memcmp(lcname.v, ns_lcname.v, UG(unicode)?UBYTES(lcname_len):lcname_len) == 0) { + /* The given name is equal to name of current namespace. + PHP will need to perform additional cheks at run-time to + determine if we assume namespace or class name. */ *fetch_type |= ZEND_FETCH_CLASS_RT_NS_NAME; } efree(ns_lcname.v); @@ -1656,6 +1666,10 @@ if (zend_u_hash_find(CG(class_table), Z_TYPE(class_name->u.constant), lcname, lcname_len+1, (void**)&pce) == SUCCESS && (*pce)->type == ZEND_INTERNAL_CLASS) { + /* There is an internal class with the same name exists. + PHP will need to perform additional cheks at run-time to + determine if we assume class in current namespace or + internal one. */ *fetch_type |= ZEND_FETCH_CLASS_RT_NS_CHECK; } tmp.op_type = IS_CONST; @@ -1741,7 +1755,7 @@ unsigned char *ptr = NULL; zend_op *opline; ulong fetch_type = 0; - + if (method_name->op_type == IS_CONST) { zstr lcname; unsigned int lcname_len; @@ -1777,7 +1791,8 @@ if (class_node.op_type == IS_CONST && method_name->op_type == IS_CONST) { - /* Prebuild ns::func name to speedup run-time check */ + /* Prebuild ns::func name to speedup run-time check. + The additional names are stored in additional OP_DATA opcode. */ zstr fname, lcname; unsigned int len, lcname_len; @@ -1785,7 +1800,7 @@ opline->opcode = ZEND_OP_DATA; opline->op1.op_type = IS_CONST; SET_UNUSED(opline->op2); - + len = Z_UNILEN(class_node.u.constant) + 2 + Z_UNILEN(method_name->u.constant); if (UG(unicode)) { fname.u = eumalloc(len + 1); @@ -1813,6 +1828,9 @@ efree(fname.v); if (fetch_type & ZEND_FETCH_CLASS_RT_NS_NAME) { + /* Prebuild name without first part of compound name for cases + when name is equal to current namespace name. This will speedup + runtime check. */ zstr colon; if (UG(unicode) && (colon.u = u_memchr(lcname.u, ':', lcname_len)) && colon.u[1] == ':') { @@ -1823,7 +1841,7 @@ colon.s += 2; opline->op2.op_type = IS_CONST; ZVAL_STRINGL(&opline->op2.u.constant, colon.s, lcname_len - (colon.s - lcname.s), 1); - } + } } } @@ -2125,7 +2143,7 @@ znode catch_class; zend_do_fetch_class(&catch_class, class_name TSRMLS_CC); - + catch_op_number = get_next_op_number(CG(active_op_array)); if (catch_op_number > 0) { opline = &CG(active_op_array)->opcodes[catch_op_number-1]; @@ -3171,12 +3189,14 @@ zend_error(E_COMPILE_ERROR, "Cannot use '%R' as class name as it is reserved", Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant)); } + /* Class name must not conflict with import names */ if (CG(current_import) && zend_u_hash_exists(CG(current_import), Z_TYPE(class_name->u.constant), lcname, lcname_len+1)) { zend_error(E_COMPILE_ERROR, "Class name '%R' coflicts with import name", Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant)); } if (CG(current_namespace)) { + /* Prefix class name with name of current namespace */ znode tmp; tmp.u.constant = *CG(current_namespace); @@ -3731,7 +3751,7 @@ if (constant_container) { zend_do_fetch_class(&class_node, constant_container TSRMLS_CC); - } + } opline = get_next_op(CG(active_op_array) TSRMLS_CC); opline->opcode = ZEND_FETCH_CONSTANT; opline->result.op_type = IS_TMP_VAR; @@ -4916,7 +4936,7 @@ void zend_do_build_namespace_name(znode *result, znode *prefix, znode *name TSRMLS_DC) /* {{{ */ { int len; - + if (prefix) { *result = *prefix; } else { @@ -4955,7 +4975,7 @@ zend_error(E_COMPILE_ERROR, "Namespace declaration statement has to be the very first statement in the script"); } if (CG(current_namespace)) { - zend_error(E_COMPILE_ERROR, "Namespace cannot be declared twice"); + zend_error(E_COMPILE_ERROR, "Namespace cannot be declared twice"); } lcname = zend_u_str_case_fold(Z_TYPE(name->u.constant), Z_UNIVAL(name->u.constant), Z_UNILEN(name->u.constant), 0, &lcname_len); if (((lcname_len == sizeof("self")-1) && @@ -4988,6 +5008,8 @@ if (new_name) { name = &new_name->u.constant; } else { + /* The form "import A::B" is eqivalent to "import A::B as B". + So we extract the last part of compound name ti use as a new_name */ name = &tmp; if (UG(unicode)) { UChar *p = u_memrchr(Z_USTRVAL_P(ns), ':', Z_USTRLEN_P(ns)); @@ -4997,7 +5019,7 @@ *name = *ns; zval_copy_ctor(name); warn = 1; - } + } } else { char *p = zend_memrchr(Z_STRVAL_P(ns), ':', Z_STRLEN_P(ns)); if (p) { @@ -5006,7 +5028,7 @@ *name = *ns; zval_copy_ctor(name); warn = 1; - } + } } } @@ -5018,7 +5040,7 @@ ZEND_U_EQUAL(Z_TYPE_P(name), lcname, lcname_len, "parent", sizeof("parent")-1))) { zend_error(E_COMPILE_ERROR, "Cannot use '%R' as import name", Z_TYPE_P(name), Z_UNIVAL_P(name)); } - + if (zend_u_hash_exists(CG(class_table), Z_TYPE_P(name), lcname, lcname_len+1)) { zend_error(E_COMPILE_ERROR, "Import name '%R' coflicts with defined class", Z_TYPE_P(name), Z_UNIVAL_P(name)); } http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_compile.h?r1=1.362&r2=1.363&diff_format=u Index: ZendEngine2/zend_compile.h diff -u ZendEngine2/zend_compile.h:1.362 ZendEngine2/zend_compile.h:1.363 --- ZendEngine2/zend_compile.h:1.362 Fri Jul 27 13:41:35 2007 +++ ZendEngine2/zend_compile.h Mon Aug 20 09:48:41 2007 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_compile.h,v 1.362 2007/07/27 13:41:35 dmitry Exp $ */ +/* $Id: zend_compile.h,v 1.363 2007/08/20 09:48:41 dmitry Exp $ */ #ifndef ZEND_COMPILE_H #define ZEND_COMPILE_H @@ -414,7 +414,7 @@ int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC); void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC); void zend_do_clone(znode *result, znode *expr TSRMLS_DC); -void zend_do_begin_dynamic_function_call(znode *function_name TSRMLS_DC); +void zend_do_begin_dynamic_function_call(znode *function_name, int prefix_len TSRMLS_DC); void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC); void zend_do_fetch_class_name(znode *result, znode *class_entry, znode *class_name TSRMLS_DC); void zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC); http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_execute_API.c?r1=1.410&r2=1.411&diff_format=u Index: ZendEngine2/zend_execute_API.c diff -u ZendEngine2/zend_execute_API.c:1.410 ZendEngine2/zend_execute_API.c:1.411 --- ZendEngine2/zend_execute_API.c:1.410 Fri Jul 27 13:41:35 2007 +++ ZendEngine2/zend_execute_API.c Mon Aug 20 09:48:41 2007 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_execute_API.c,v 1.410 2007/07/27 13:41:35 dmitry Exp $ */ +/* $Id: zend_execute_API.c,v 1.411 2007/08/20 09:48:41 dmitry Exp $ */ #include <stdio.h> #include <signal.h> @@ -1144,6 +1144,8 @@ lc_name = name; lc_name_len = name_length; } + + /* Ignore leading "::" */ if (type == IS_UNICODE && lc_name.u[0] == ':' && lc_name.u[1] == ':') { http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_language_parser.y?r1=1.187&r2=1.188&diff_format=u Index: ZendEngine2/zend_language_parser.y diff -u ZendEngine2/zend_language_parser.y:1.187 ZendEngine2/zend_language_parser.y:1.188 --- ZendEngine2/zend_language_parser.y:1.187 Thu Aug 2 21:53:53 2007 +++ ZendEngine2/zend_language_parser.y Mon Aug 20 09:48:41 2007 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_language_parser.y,v 1.187 2007/08/02 21:53:53 johannes Exp $ */ +/* $Id: zend_language_parser.y,v 1.188 2007/08/20 09:48:41 dmitry Exp $ */ /* * LALR shift/reduce conflicts and how they are resolved: @@ -658,7 +658,7 @@ | fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); } function_call_parameter_list ')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} - | variable_without_objects '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1 TSRMLS_CC); } + | variable_without_objects '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1, 0 TSRMLS_CC); } function_call_parameter_list ')' { zend_do_end_function_call(&$1, &$$, &$4, 0, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} ;
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_API.c?r1=1.441&r2=1.442&diff_format=u Index: ZendEngine2/zend_API.c diff -u ZendEngine2/zend_API.c:1.441 ZendEngine2/zend_API.c:1.442 --- ZendEngine2/zend_API.c:1.441 Sat Jul 21 05:27:06 2007 +++ ZendEngine2/zend_API.c Mon Aug 20 09:48:41 2007 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_API.c,v 1.441 2007/07/21 05:27:06 pollita Exp $ */ +/* $Id: zend_API.c,v 1.442 2007/08/20 09:48:41 dmitry Exp $ */ #include "zend.h" #include "zend_execute.h" @@ -801,7 +801,7 @@ fci->size = 0; fcc->initialized = 0; break; - } + } if (zend_fcall_info_init(*arg, fci, fcc, NULL TSRMLS_CC) == SUCCESS) { break; @@ -1001,7 +1001,7 @@ break; } } - + if (T_arg_type == -1) { T_arg_type = ZEND_STR_TYPE; } @@ -1070,7 +1070,7 @@ get_active_function_name(TSRMLS_C), __num_args); \ return FAILURE; \ }\ -} +} ZEND_API int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, char *type_spec, ...) /* {{{ */ { @@ -2084,7 +2084,7 @@ if (UG(unicode)) { zend_arg_info *args; int n = ptr->num_args; - + args = internal_function->arg_info = malloc((n + 1) * sizeof(zend_arg_info)); memcpy(args, ptr->arg_info+1, (n + 1) * sizeof(zend_arg_info)); while (n > 0) { @@ -2175,7 +2175,7 @@ */ unsigned int lc_func_name_len; zstr lc_func_name = zend_u_str_case_fold(ZEND_STR_TYPE, internal_function->function_name, fname_len, 0, &lc_func_name_len); - + if ((lc_func_name_len == lc_class_name_len) && !memcmp(lc_func_name.v, lc_class_name.v, UG(unicode)?UBYTES(lc_class_name_len):lc_class_name_len) && !ctor) { ctor = reg_function; } else if ((fname_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME))) { @@ -2368,7 +2368,7 @@ module->module_shutdown_func(module->type, module->module_number TSRMLS_CC); } - + /* Deinitilaise module globals */ if (module->globals_size) { #ifdef ZTS @@ -2498,7 +2498,7 @@ interface_entry = va_arg(interface_list, zend_class_entry *); zend_do_implement_interface(class_entry, interface_entry TSRMLS_CC); } - + va_end(interface_list); } /* }}} */ @@ -2607,6 +2607,7 @@ *fptr_ptr = NULL; if (!ce_org) { + /* Skip leading :: */ if (Z_TYPE_P(callable) == IS_UNICODE && Z_USTRVAL_P(callable)[0] == ':' && Z_USTRVAL_P(callable)[1] == ':') { @@ -2624,6 +2625,8 @@ } else { lmname = zend_u_str_case_fold(Z_TYPE_P(callable), Z_UNIVAL_P(callable), Z_UNILEN_P(callable), 1, &mlen); } + /* Check if function with given name exists. + This may be a compound name that includes namespace name */ if (zend_u_hash_find(EG(function_table), Z_TYPE_P(callable), lmname, mlen+1, (void**)&fptr) == SUCCESS) { *fptr_ptr = fptr; efree(lmname.v); @@ -2631,6 +2634,7 @@ } efree(lmname.v); } + /* Split name into class/namespace and method/function names */ if (Z_TYPE_P(callable) == IS_UNICODE) { if ((colon.u = u_strrstr(Z_USTRVAL_P(callable), u_doublecolon)) != NULL) { mlen = u_strlen(colon.u+2); @@ -2648,6 +2652,8 @@ } } if (colon.v != NULL) { + /* This is a compound name. + Try to fetch class and then find static method. */ *ce_ptr = zend_u_fetch_class(Z_TYPE_P(callable), Z_UNIVAL_P(callable), clen, ZEND_FETCH_CLASS_AUTO TSRMLS_CC); if (!*ce_ptr) { return 0; @@ -2657,14 +2663,14 @@ return 0; } lmname = zend_u_str_case_fold(Z_TYPE_P(callable), mname, mlen, 1, &mlen); - } else { + } else if (ce_org) { + /* Try to fetch find static method of given class. */ lmname = zend_u_str_case_fold(Z_TYPE_P(callable), Z_UNIVAL_P(callable), Z_UNILEN_P(callable), 1, &mlen); - if (ce_org) { - ftable = &ce_org->function_table; - *ce_ptr = ce_org; - } else { - ftable = EG(function_table); - } + ftable = &ce_org->function_table; + *ce_ptr = ce_org; + } else { + /* We already checked for plain function before. */ + return 0; } retval = zend_u_hash_find(ftable, Z_TYPE_P(callable), lmname, mlen+1, (void**)&fptr) == SUCCESS ? 1 : 0; @@ -2968,7 +2974,7 @@ fci->symbol_table = NULL; if (ZEND_U_CASE_EQUAL(ZEND_STR_TYPE, func->common.function_name, USTR_LEN(func->common.function_name), ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1) || - ZEND_U_CASE_EQUAL(ZEND_STR_TYPE, func->common.function_name, USTR_LEN(func->common.function_name), ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1)) { + ZEND_U_CASE_EQUAL(ZEND_STR_TYPE, func->common.function_name, USTR_LEN(func->common.function_name), ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1)) { fcc->initialized = 0; fcc->function_handler = NULL; fcc->calling_scope = NULL; @@ -3048,13 +3054,13 @@ ZEND_API int zend_fcall_info_argp(zend_fcall_info *fci TSRMLS_DC, int argc, zval ***argv) /* {{{ */ { int i; - + if (argc < 0) { return FAILURE; } - + zend_fcall_info_args_clear(fci, !argc); - + if (argc) { fci->param_count = argc; fci->params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **)); @@ -3064,7 +3070,7 @@ fci->params[i] = argv[i]; } } - + return SUCCESS; } /* }}} */ @@ -3073,24 +3079,24 @@ { int i; zval **arg; - + if (argc < 0) { return FAILURE; } - + zend_fcall_info_args_clear(fci, !argc); - + if (argc) { fci->param_count = argc; fci->params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **)); - + for (i = 0; i < argc; ++i) { arg = va_arg(*argv, zval **); ZVAL_ADDREF(*arg); fci->params[i] = arg; } } - + return SUCCESS; } /* }}} */ @@ -3099,11 +3105,11 @@ { int ret; va_list argv; - + va_start(argv, argc); ret = zend_fcall_info_argv(fci TSRMLS_CC, argc, &argv); va_end(argv); - + return ret; } /* }}} */ @@ -3119,7 +3125,7 @@ zend_fcall_info_args(fci, args TSRMLS_CC); } result = zend_call_function(fci, fcc TSRMLS_CC); - + if (!retval_ptr_ptr && retval) { zval_ptr_dtor(&retval); } @@ -3439,7 +3445,7 @@ { zval *constant; - if (ce->type & ZEND_INTERNAL_CLASS) { + if (ce->type & ZEND_INTERNAL_CLASS) { constant = malloc(sizeof(zval)); if (UG(unicode)) { Z_TYPE_P(constant) = IS_UNICODE; http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_compile.c?r1=1.761&r2=1.762&diff_format=u Index: ZendEngine2/zend_compile.c diff -u ZendEngine2/zend_compile.c:1.761 ZendEngine2/zend_compile.c:1.762 --- ZendEngine2/zend_compile.c:1.761 Fri Aug 17 12:05:19 2007 +++ ZendEngine2/zend_compile.c Mon Aug 20 09:48:41 2007 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_compile.c,v 1.761 2007/08/17 12:05:19 dmitry Exp $ */ +/* $Id: zend_compile.c,v 1.762 2007/08/20 09:48:41 dmitry Exp $ */ #include <zend_language_parser.h> #include "zend.h" @@ -1245,6 +1245,7 @@ zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); if (CG(current_namespace)) { + /* Prefix function name with current namespcae name */ znode tmp; tmp.u.constant = *CG(current_namespace); @@ -1451,8 +1452,11 @@ zend_function *function; unsigned int lcname_len; zstr lcname; + int prefix_len = 0; if (check_namespace && CG(current_namespace)) { + /* We assume we call function from the current namespace + if it is not prefixed. */ znode tmp; tmp.op_type = IS_CONST; @@ -1460,11 +1464,15 @@ zval_copy_ctor(&tmp.u.constant); zend_do_build_namespace_name(&tmp, &tmp, function_name TSRMLS_CC); *function_name = tmp; + + /* In run-time PHP will check for function with full name and + internal function with short name */ + prefix_len = Z_UNILEN_P(CG(current_namespace)) + 2; } lcname = zend_u_str_case_fold(Z_TYPE(function_name->u.constant), Z_UNIVAL(function_name->u.constant), Z_UNILEN(function_name->u.constant), 0, &lcname_len); if (zend_u_hash_find(CG(function_table), Z_TYPE(function_name->u.constant), lcname, lcname_len+1, (void **) &function)==FAILURE) { - zend_do_begin_dynamic_function_call(function_name TSRMLS_CC); + zend_do_begin_dynamic_function_call(function_name, prefix_len TSRMLS_CC); efree(lcname.v); return 1; /* Dynamic */ } @@ -1547,7 +1555,7 @@ } /* }}} */ -void zend_do_begin_dynamic_function_call(znode *function_name TSRMLS_DC) /* {{{ */ +void zend_do_begin_dynamic_function_call(znode *function_name, int prefix_len TSRMLS_DC) /* {{{ */ { unsigned char *ptr = NULL; zend_op *opline; @@ -1557,21 +1565,13 @@ opline->op2 = *function_name; opline->extended_value = 0; - SET_UNUSED(opline->op1); - if (function_name->op_type == IS_CONST) { - if (Z_TYPE(function_name->u.constant) == IS_UNICODE) { - UChar *p = u_memrchr(Z_USTRVAL(function_name->u.constant), ':', Z_USTRLEN(function_name->u.constant)); - if (p) { - opline->op1.op_type = IS_CONST; - ZVAL_LONG(&opline->op1.u.constant, p + 1 - Z_USTRVAL(function_name->u.constant)); - } - } else { - char *p = zend_memrchr(Z_STRVAL(function_name->u.constant), ':', Z_STRLEN(function_name->u.constant)); - if (p) { - opline->op1.op_type = IS_CONST; - ZVAL_LONG(&opline->op1.u.constant, p + 1 - Z_STRVAL(function_name->u.constant)); - } - } + if (prefix_len) { + /* In run-time PHP will check for function with full name and + internal function with short name */ + opline->op1.op_type = IS_CONST; + ZVAL_LONG(&opline->op1.u.constant, prefix_len); + } else { + SET_UNUSED(opline->op1); } zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *)); @@ -1594,15 +1594,18 @@ compound.s = memchr(Z_STRVAL(class_name->u.constant), ':', Z_STRLEN(class_name->u.constant)); } if (compound.v) { + /* This is a compound class name that cotains namespace prefix */ if (Z_TYPE(class_name->u.constant) == IS_UNICODE && Z_USTRVAL(class_name->u.constant)[0] == ':') { + /* The unicode name has "::" prefix */ Z_USTRLEN(class_name->u.constant) -= 2; memmove(Z_USTRVAL(class_name->u.constant), Z_USTRVAL(class_name->u.constant)+2, UBYTES(Z_USTRLEN(class_name->u.constant)+1)); Z_USTRVAL(class_name->u.constant) = eurealloc( Z_USTRVAL(class_name->u.constant), Z_USTRLEN(class_name->u.constant) + 1); } else if (Z_TYPE(class_name->u.constant) == IS_STRING && - Z_STRVAL(class_name->u.constant)[0] == ':') { + Z_STRVAL(class_name->u.constant)[0] == ':') { + /* The STRING name has "::" prefix */ Z_STRLEN(class_name->u.constant) -= 2; memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+2, Z_STRLEN(class_name->u.constant)+1); Z_STRVAL(class_name->u.constant) = erealloc( @@ -1616,7 +1619,9 @@ len = compound.s - Z_STRVAL(class_name->u.constant); lcname = zend_u_str_case_fold(Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant), len , 0, &lcname_len); } + /* Check if first part of compound name is an import name */ if (zend_u_hash_find(CG(current_import), Z_TYPE(class_name->u.constant), lcname, lcname_len+1, (void**)&ns) == SUCCESS) { + /* Substitute import name */ tmp.op_type = IS_CONST; tmp.u.constant = **ns; zval_copy_ctor(&tmp.u.constant); @@ -1631,12 +1636,14 @@ *class_name = tmp; } efree(lcname.v); - } + } } else if (CG(current_import) || CG(current_namespace)) { + /* this is a plain name (without ::) */ lcname = zend_u_str_case_fold(Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant), Z_UNILEN(class_name->u.constant), 0, &lcname_len); if (CG(current_import) && zend_u_hash_find(CG(current_import), Z_TYPE(class_name->u.constant), lcname, lcname_len+1, (void**)&ns) == SUCCESS) { + /* The given name is an import name. Substitute it. */ zval_dtor(&class_name->u.constant); class_name->u.constant = **ns; zval_copy_ctor(&class_name->u.constant); @@ -1649,6 +1656,9 @@ if (ns_lcname_len == lcname_len && memcmp(lcname.v, ns_lcname.v, UG(unicode)?UBYTES(lcname_len):lcname_len) == 0) { + /* The given name is equal to name of current namespace. + PHP will need to perform additional cheks at run-time to + determine if we assume namespace or class name. */ *fetch_type |= ZEND_FETCH_CLASS_RT_NS_NAME; } efree(ns_lcname.v); @@ -1656,6 +1666,10 @@ if (zend_u_hash_find(CG(class_table), Z_TYPE(class_name->u.constant), lcname, lcname_len+1, (void**)&pce) == SUCCESS && (*pce)->type == ZEND_INTERNAL_CLASS) { + /* There is an internal class with the same name exists. + PHP will need to perform additional cheks at run-time to + determine if we assume class in current namespace or + internal one. */ *fetch_type |= ZEND_FETCH_CLASS_RT_NS_CHECK; } tmp.op_type = IS_CONST; @@ -1741,7 +1755,7 @@ unsigned char *ptr = NULL; zend_op *opline; ulong fetch_type = 0; - + if (method_name->op_type == IS_CONST) { zstr lcname; unsigned int lcname_len; @@ -1777,7 +1791,8 @@ if (class_node.op_type == IS_CONST && method_name->op_type == IS_CONST) { - /* Prebuild ns::func name to speedup run-time check */ + /* Prebuild ns::func name to speedup run-time check. + The additional names are stored in additional OP_DATA opcode. */ zstr fname, lcname; unsigned int len, lcname_len; @@ -1785,7 +1800,7 @@ opline->opcode = ZEND_OP_DATA; opline->op1.op_type = IS_CONST; SET_UNUSED(opline->op2); - + len = Z_UNILEN(class_node.u.constant) + 2 + Z_UNILEN(method_name->u.constant); if (UG(unicode)) { fname.u = eumalloc(len + 1); @@ -1813,6 +1828,9 @@ efree(fname.v); if (fetch_type & ZEND_FETCH_CLASS_RT_NS_NAME) { + /* Prebuild name without first part of compound name for cases + when name is equal to current namespace name. This will speedup + runtime check. */ zstr colon; if (UG(unicode) && (colon.u = u_memchr(lcname.u, ':', lcname_len)) && colon.u[1] == ':') { @@ -1823,7 +1841,7 @@ colon.s += 2; opline->op2.op_type = IS_CONST; ZVAL_STRINGL(&opline->op2.u.constant, colon.s, lcname_len - (colon.s - lcname.s), 1); - } + } } } @@ -2125,7 +2143,7 @@ znode catch_class; zend_do_fetch_class(&catch_class, class_name TSRMLS_CC); - + catch_op_number = get_next_op_number(CG(active_op_array)); if (catch_op_number > 0) { opline = &CG(active_op_array)->opcodes[catch_op_number-1]; @@ -3171,12 +3189,14 @@ zend_error(E_COMPILE_ERROR, "Cannot use '%R' as class name as it is reserved", Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant)); } + /* Class name must not conflict with import names */ if (CG(current_import) && zend_u_hash_exists(CG(current_import), Z_TYPE(class_name->u.constant), lcname, lcname_len+1)) { zend_error(E_COMPILE_ERROR, "Class name '%R' coflicts with import name", Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant)); } if (CG(current_namespace)) { + /* Prefix class name with name of current namespace */ znode tmp; tmp.u.constant = *CG(current_namespace); @@ -3731,7 +3751,7 @@ if (constant_container) { zend_do_fetch_class(&class_node, constant_container TSRMLS_CC); - } + } opline = get_next_op(CG(active_op_array) TSRMLS_CC); opline->opcode = ZEND_FETCH_CONSTANT; opline->result.op_type = IS_TMP_VAR; @@ -4916,7 +4936,7 @@ void zend_do_build_namespace_name(znode *result, znode *prefix, znode *name TSRMLS_DC) /* {{{ */ { int len; - + if (prefix) { *result = *prefix; } else { @@ -4955,7 +4975,7 @@ zend_error(E_COMPILE_ERROR, "Namespace declaration statement has to be the very first statement in the script"); } if (CG(current_namespace)) { - zend_error(E_COMPILE_ERROR, "Namespace cannot be declared twice"); + zend_error(E_COMPILE_ERROR, "Namespace cannot be declared twice"); } lcname = zend_u_str_case_fold(Z_TYPE(name->u.constant), Z_UNIVAL(name->u.constant), Z_UNILEN(name->u.constant), 0, &lcname_len); if (((lcname_len == sizeof("self")-1) && @@ -4988,6 +5008,8 @@ if (new_name) { name = &new_name->u.constant; } else { + /* The form "import A::B" is eqivalent to "import A::B as B". + So we extract the last part of compound name ti use as a new_name */ name = &tmp; if (UG(unicode)) { UChar *p = u_memrchr(Z_USTRVAL_P(ns), ':', Z_USTRLEN_P(ns)); @@ -4997,7 +5019,7 @@ *name = *ns; zval_copy_ctor(name); warn = 1; - } + } } else { char *p = zend_memrchr(Z_STRVAL_P(ns), ':', Z_STRLEN_P(ns)); if (p) { @@ -5006,7 +5028,7 @@ *name = *ns; zval_copy_ctor(name); warn = 1; - } + } } } @@ -5018,7 +5040,7 @@ ZEND_U_EQUAL(Z_TYPE_P(name), lcname, lcname_len, "parent", sizeof("parent")-1))) { zend_error(E_COMPILE_ERROR, "Cannot use '%R' as import name", Z_TYPE_P(name), Z_UNIVAL_P(name)); } - + if (zend_u_hash_exists(CG(class_table), Z_TYPE_P(name), lcname, lcname_len+1)) { zend_error(E_COMPILE_ERROR, "Import name '%R' coflicts with defined class", Z_TYPE_P(name), Z_UNIVAL_P(name)); } http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_compile.h?r1=1.362&r2=1.363&diff_format=u Index: ZendEngine2/zend_compile.h diff -u ZendEngine2/zend_compile.h:1.362 ZendEngine2/zend_compile.h:1.363 --- ZendEngine2/zend_compile.h:1.362 Fri Jul 27 13:41:35 2007 +++ ZendEngine2/zend_compile.h Mon Aug 20 09:48:41 2007 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_compile.h,v 1.362 2007/07/27 13:41:35 dmitry Exp $ */ +/* $Id: zend_compile.h,v 1.363 2007/08/20 09:48:41 dmitry Exp $ */ #ifndef ZEND_COMPILE_H #define ZEND_COMPILE_H @@ -414,7 +414,7 @@ int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC); void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC); void zend_do_clone(znode *result, znode *expr TSRMLS_DC); -void zend_do_begin_dynamic_function_call(znode *function_name TSRMLS_DC); +void zend_do_begin_dynamic_function_call(znode *function_name, int prefix_len TSRMLS_DC); void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC); void zend_do_fetch_class_name(znode *result, znode *class_entry, znode *class_name TSRMLS_DC); void zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC); http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_execute_API.c?r1=1.410&r2=1.411&diff_format=u Index: ZendEngine2/zend_execute_API.c diff -u ZendEngine2/zend_execute_API.c:1.410 ZendEngine2/zend_execute_API.c:1.411 --- ZendEngine2/zend_execute_API.c:1.410 Fri Jul 27 13:41:35 2007 +++ ZendEngine2/zend_execute_API.c Mon Aug 20 09:48:41 2007 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_execute_API.c,v 1.410 2007/07/27 13:41:35 dmitry Exp $ */ +/* $Id: zend_execute_API.c,v 1.411 2007/08/20 09:48:41 dmitry Exp $ */ #include <stdio.h> #include <signal.h> @@ -1144,6 +1144,8 @@ lc_name = name; lc_name_len = name_length; } + + /* Ignore leading "::" */ if (type == IS_UNICODE && lc_name.u[0] == ':' && lc_name.u[1] == ':') { http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_language_parser.y?r1=1.187&r2=1.188&diff_format=u Index: ZendEngine2/zend_language_parser.y diff -u ZendEngine2/zend_language_parser.y:1.187 ZendEngine2/zend_language_parser.y:1.188 --- ZendEngine2/zend_language_parser.y:1.187 Thu Aug 2 21:53:53 2007 +++ ZendEngine2/zend_language_parser.y Mon Aug 20 09:48:41 2007 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_language_parser.y,v 1.187 2007/08/02 21:53:53 johannes Exp $ */ +/* $Id: zend_language_parser.y,v 1.188 2007/08/20 09:48:41 dmitry Exp $ */ /* * LALR shift/reduce conflicts and how they are resolved: @@ -658,7 +658,7 @@ | fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); } function_call_parameter_list ')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} - | variable_without_objects '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1 TSRMLS_CC); } + | variable_without_objects '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1, 0 TSRMLS_CC); } function_call_parameter_list ')' { zend_do_end_function_call(&$1, &$$, &$4, 0, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} ;