Index: Zend/zend_API.c =================================================================== RCS file: /repository/ZendEngine2/zend_API.c,v retrieving revision 1.465 diff -u -r1.465 zend_API.c --- Zend/zend_API.c 5 Mar 2008 14:39:05 -0000 1.465 +++ Zend/zend_API.c 13 Mar 2008 03:39:15 -0000 @@ -2644,7 +2644,7 @@ } /* }}} */ -static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, zend_class_entry *ce_org, zval *callable, zend_class_entry **ce_ptr, zend_function **fptr_ptr, char **error TSRMLS_DC) /* {{{ */ +static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, zend_class_entry *ce_org, zval *callable, zend_class_entry **ce_ptr, zend_uint *fetch_type, zend_function **fptr_ptr, char **error TSRMLS_DC) /* {{{ */ { int retval; zstr lmname, mname, colon = NULL_ZSTR; @@ -2727,6 +2727,7 @@ EG(scope) = ce_org; } *ce_ptr = zend_u_fetch_class(Z_TYPE_P(callable), Z_UNIVAL_P(callable), clen, ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_SILENT TSRMLS_CC); + *fetch_type = zend_get_class_fetch_type(Z_TYPE_P(callable), Z_UNIVAL_P(callable), clen); EG(scope) = last_scope; if (!*ce_ptr) { if (error) { @@ -2829,11 +2830,12 @@ } /* }}} */ -ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, zval *callable_name, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zval ***zobj_ptr_ptr, char **error TSRMLS_DC) /* {{{ */ +ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, zval *callable_name, zend_class_entry **ce_ptr, zend_uint *fetch_type, zend_function **fptr_ptr, zval ***zobj_ptr_ptr, char **error TSRMLS_DC) /* {{{ */ { zstr lcname; unsigned int lcname_len; zend_class_entry *ce_local, **pce; + zend_uint fetch_type_local; zend_function *fptr_local; zval **zobj_ptr_local; @@ -2852,7 +2854,12 @@ if (error) { *error = NULL; } + if (fetch_type == NULL) { + fetch_type = &fetch_type_local; + } + *ce_ptr = NULL; + *fetch_type = 0; *fptr_ptr = NULL; *zobj_ptr_ptr = NULL; @@ -2868,7 +2875,7 @@ return 1; } - return zend_is_callable_check_func(check_flags, zobj_ptr_ptr, NULL, callable, ce_ptr, fptr_ptr, error TSRMLS_CC); + return zend_is_callable_check_func(check_flags, zobj_ptr_ptr, NULL, callable, ce_ptr, fetch_type, fptr_ptr, error TSRMLS_CC); case IS_ARRAY: { @@ -2952,13 +2959,16 @@ lcname_len == sizeof("self")-1 && ZEND_U_EQUAL(Z_TYPE_PP(obj), lcname, lcname_len, "self", sizeof("self")-1)) { ce = EG(active_op_array)->scope; + *fetch_type = ZEND_FETCH_CLASS_SELF; } else if (EG(active_op_array) && EG(active_op_array)->scope && lcname_len == sizeof("parent")-1 && ZEND_U_EQUAL(Z_TYPE_PP(obj), lcname, lcname_len, "parent", sizeof("parent")-1)) { ce = EG(active_op_array)->scope->parent; + *fetch_type = ZEND_FETCH_CLASS_PARENT; } else if (lcname_len == sizeof("static")-1 && ZEND_U_EQUAL(Z_TYPE_PP(obj), lcname, lcname_len, "static", sizeof("static")-1)) { ce = EG(called_scope); + *fetch_type = ZEND_FETCH_CLASS_STATIC; } else if (zend_u_lookup_class(Z_TYPE_PP(obj), Z_UNIVAL_PP(obj), Z_UNILEN_PP(obj), &pce TSRMLS_CC) == SUCCESS) { ce = *pce; } @@ -3013,7 +3023,7 @@ } if (ce) { - return zend_is_callable_check_func(check_flags, zobj_ptr_ptr, ce, *method, ce_ptr, fptr_ptr, error TSRMLS_CC); + return zend_is_callable_check_func(check_flags, zobj_ptr_ptr, ce, *method, ce_ptr, fetch_type, fptr_ptr, error TSRMLS_CC); } else { if (error) zend_spprintf(error, 0, "first array member is not a valid %s", (Z_TYPE_PP(obj) == IS_STRING || Z_TYPE_PP(obj) == IS_UNICODE) ? "class name" : "object"); } @@ -3051,7 +3061,7 @@ { TSRMLS_FETCH(); - return zend_is_callable_ex(callable, check_flags, callable_name, NULL, NULL, NULL, NULL TSRMLS_CC); + return zend_is_callable_ex(callable, check_flags, callable_name, NULL, NULL, NULL, NULL, NULL TSRMLS_CC); } /* }}} */ @@ -3061,7 +3071,7 @@ zend_function *fptr; zval **zobj_ptr; - if (zend_is_callable_ex(callable, IS_CALLABLE_STRICT, callable_name, &ce, &fptr, &zobj_ptr, NULL TSRMLS_CC)) { + if (zend_is_callable_ex(callable, IS_CALLABLE_STRICT, callable_name, &ce, NULL, &fptr, &zobj_ptr, NULL TSRMLS_CC)) { if ((Z_TYPE_P(callable) == IS_STRING || Z_TYPE_P(callable) == IS_UNICODE) && ce) { zval_dtor(callable); array_init(callable); @@ -3079,8 +3089,9 @@ zend_class_entry *ce; zend_function *func; zval **obj; + zend_uint fetch_type; - if (!zend_is_callable_ex(callable, check_flags, callable_name, &ce, &func, &obj, error TSRMLS_CC)) { + if (!zend_is_callable_ex(callable, check_flags, callable_name, &ce, &fetch_type, &func, &obj, error TSRMLS_CC)) { return FAILURE; } @@ -3104,7 +3115,11 @@ } else { fcc->initialized = 1; fcc->function_handler = func; - fcc->calling_scope = ce; + if (fetch_type == ZEND_FETCH_CLASS_PARENT) { + fcc->calling_scope = EG(called_scope); + } else { + fcc->calling_scope = ce; + } fcc->object_pp = obj; } Index: Zend/zend_API.h =================================================================== RCS file: /repository/ZendEngine2/zend_API.h,v retrieving revision 1.298 diff -u -r1.298 zend_API.h --- Zend/zend_API.h 28 Feb 2008 13:30:43 -0000 1.298 +++ Zend/zend_API.h 13 Mar 2008 03:39:16 -0000 @@ -235,7 +235,7 @@ #define IS_CALLABLE_STRICT (IS_CALLABLE_CHECK_IS_STATIC) -ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, zval *callable_name, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zval ***zobj_ptr_ptr, char **error TSRMLS_DC); +ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, zval *callable_name, zend_class_entry **ce_ptr, zend_uint *fetch_type, zend_function **fptr_ptr, zval ***zobj_ptr_ptr, char **error TSRMLS_DC); ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, zval *callable_name); ZEND_API zend_bool zend_make_callable(zval *callable, zval *callable_name TSRMLS_DC); ZEND_API const char *zend_get_module_version(const char *module_name); Index: Zend/zend_execute_API.c =================================================================== RCS file: /repository/ZendEngine2/zend_execute_API.c,v retrieving revision 1.440 diff -u -r1.440 zend_execute_API.c --- Zend/zend_execute_API.c 7 Mar 2008 00:51:02 -0000 1.440 +++ Zend/zend_execute_API.c 13 Mar 2008 03:39:16 -0000 @@ -829,6 +829,7 @@ found = (*ce != NULL?SUCCESS:FAILURE); fci->object_pp = EG(This)?&EG(This):NULL; EX(object) = EG(This); + calling_scope = *ce; } else if (EG(active_op_array) && Z_UNILEN_PP(fci->object_pp) == sizeof("parent") - 1 && ZEND_U_EQUAL(Z_TYPE_PP(fci->object_pp), Z_UNIVAL_PP(fci->object_pp), Z_UNILEN_PP(fci->object_pp), "parent", sizeof("parent") - 1) @@ -843,6 +844,11 @@ found = (*ce != NULL?SUCCESS:FAILURE); fci->object_pp = EG(This)?&EG(This):NULL; EX(object) = EG(This); + if (EG(called_scope)) { + calling_scope = EG(called_scope); + } else { + calling_scope = *ce; + } } else if (Z_UNILEN_PP(fci->object_pp) == sizeof("static") - 1 && ZEND_U_EQUAL(Z_TYPE_PP(fci->object_pp), Z_UNIVAL_PP(fci->object_pp), Z_UNILEN_PP(fci->object_pp), "static", sizeof("static") - 1) ) { @@ -853,6 +859,7 @@ found = (*ce != NULL?SUCCESS:FAILURE); fci->object_pp = EG(This)?&EG(This):NULL; EX(object) = EG(This); + calling_scope = *ce; } else { zend_class_entry *scope; scope = EG(active_op_array) ? EG(active_op_array)->scope : NULL; @@ -869,12 +876,12 @@ } else { fci->object_pp = NULL; } + calling_scope = *ce; } if (found == FAILURE) return FAILURE; fci->function_table = &(*ce)->function_table; - calling_scope = *ce; } else { zend_error(E_NOTICE, "Non-callable array passed to zend_call_function()"); return FAILURE; Index: Zend/zend_vm_def.h =================================================================== RCS file: /repository/ZendEngine2/zend_vm_def.h,v retrieving revision 1.220 diff -u -r1.220 zend_vm_def.h --- Zend/zend_vm_def.h 12 Mar 2008 10:32:39 -0000 1.220 +++ Zend/zend_vm_def.h 13 Mar 2008 03:39:17 -0000 @@ -1991,8 +1991,15 @@ if (!ce) { zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant)); } + EX(called_scope) = ce; } else { ce = EX_T(opline->op1.u.var).class_entry; + + if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT) { + EX(called_scope) = EG(called_scope); + } else { + EX(called_scope) = ce; + } } if(OP2_TYPE != IS_UNUSED) { zstr function_name_strval; @@ -2034,8 +2041,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { Index: Zend/zend_vm_execute.h =================================================================== RCS file: /repository/ZendEngine2/zend_vm_execute.h,v retrieving revision 1.224 diff -u -r1.224 zend_vm_execute.h --- Zend/zend_vm_execute.h 12 Mar 2008 10:32:39 -0000 1.224 +++ Zend/zend_vm_execute.h 13 Mar 2008 03:39:25 -0000 @@ -2462,8 +2462,15 @@ if (!ce) { zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant)); } + EX(called_scope) = ce; } else { ce = EX_T(opline->op1.u.var).class_entry; + + if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT) { + EX(called_scope) = EG(called_scope); + } else { + EX(called_scope) = ce; + } } if(IS_CONST != IS_UNUSED) { zstr function_name_strval; @@ -2505,8 +2512,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -3040,8 +3045,15 @@ if (!ce) { zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant)); } + EX(called_scope) = ce; } else { ce = EX_T(opline->op1.u.var).class_entry; + + if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT) { + EX(called_scope) = EG(called_scope); + } else { + EX(called_scope) = ce; + } } if(IS_TMP_VAR != IS_UNUSED) { zstr function_name_strval; @@ -3083,8 +3095,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -3509,8 +3519,15 @@ if (!ce) { zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant)); } + EX(called_scope) = ce; } else { ce = EX_T(opline->op1.u.var).class_entry; + + if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT) { + EX(called_scope) = EG(called_scope); + } else { + EX(called_scope) = ce; + } } if(IS_VAR != IS_UNUSED) { zstr function_name_strval; @@ -3552,8 +3569,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -3734,8 +3749,15 @@ if (!ce) { zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant)); } + EX(called_scope) = ce; } else { ce = EX_T(opline->op1.u.var).class_entry; + + if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT) { + EX(called_scope) = EG(called_scope); + } else { + EX(called_scope) = ce; + } } if(IS_UNUSED != IS_UNUSED) { zstr function_name_strval; @@ -3777,8 +3799,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -4171,8 +4191,15 @@ if (!ce) { zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant)); } + EX(called_scope) = ce; } else { ce = EX_T(opline->op1.u.var).class_entry; + + if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT) { + EX(called_scope) = EG(called_scope); + } else { + EX(called_scope) = ce; + } } if(IS_CV != IS_UNUSED) { zstr function_name_strval; @@ -4214,8 +4241,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -10304,8 +10329,15 @@ if (!ce) { zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant)); } + EX(called_scope) = ce; } else { ce = EX_T(opline->op1.u.var).class_entry; + + if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT) { + EX(called_scope) = EG(called_scope); + } else { + EX(called_scope) = ce; + } } if(IS_CONST != IS_UNUSED) { zstr function_name_strval; @@ -10347,8 +10379,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -12192,8 +12222,15 @@ if (!ce) { zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant)); } + EX(called_scope) = ce; } else { ce = EX_T(opline->op1.u.var).class_entry; + + if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT) { + EX(called_scope) = EG(called_scope); + } else { + EX(called_scope) = ce; + } } if(IS_TMP_VAR != IS_UNUSED) { zstr function_name_strval; @@ -12235,8 +12272,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -14050,8 +14085,15 @@ if (!ce) { zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant)); } + EX(called_scope) = ce; } else { ce = EX_T(opline->op1.u.var).class_entry; + + if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT) { + EX(called_scope) = EG(called_scope); + } else { + EX(called_scope) = ce; + } } if(IS_VAR != IS_UNUSED) { zstr function_name_strval; @@ -14093,8 +14135,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -15006,8 +15046,15 @@ if (!ce) { zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant)); } + EX(called_scope) = ce; } else { ce = EX_T(opline->op1.u.var).class_entry; + + if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT) { + EX(called_scope) = EG(called_scope); + } else { + EX(called_scope) = ce; + } } if(IS_UNUSED != IS_UNUSED) { zstr function_name_strval; @@ -15049,8 +15096,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -16514,8 +16559,15 @@ if (!ce) { zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant)); } + EX(called_scope) = ce; } else { ce = EX_T(opline->op1.u.var).class_entry; + + if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT) { + EX(called_scope) = EG(called_scope); + } else { + EX(called_scope) = ce; + } } if(IS_CV != IS_UNUSED) { zstr function_name_strval; @@ -16557,8 +16609,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { Index: ext/spl/php_spl.c =================================================================== RCS file: /repository/php-src/ext/spl/php_spl.c,v retrieving revision 1.127 diff -u -r1.127 php_spl.c --- ext/spl/php_spl.c 29 Feb 2008 13:48:09 -0000 1.127 +++ ext/spl/php_spl.c 13 Mar 2008 03:39:29 -0000 @@ -430,7 +430,7 @@ zval_dtor(&ztmp); } - if (!zend_is_callable_ex(zcallable, IS_CALLABLE_STRICT, &zfunc_name, &alfi.ce, &alfi.func_ptr, &obj_ptr, &error TSRMLS_CC)) { + if (!zend_is_callable_ex(zcallable, IS_CALLABLE_STRICT, &zfunc_name, &alfi.ce, NULL, &alfi.func_ptr, &obj_ptr, &error TSRMLS_CC)) { if (Z_TYPE_P(zcallable) == IS_ARRAY) { if (!obj_ptr && alfi.func_ptr && !(alfi.func_ptr->common.fn_flags & ZEND_ACC_STATIC)) { if (do_throw) { @@ -545,7 +545,7 @@ return; } - if (!zend_is_callable_ex(zcallable, IS_CALLABLE_CHECK_SYNTAX_ONLY, &zfunc_name, NULL, NULL, &obj_ptr, &error TSRMLS_CC)) { + if (!zend_is_callable_ex(zcallable, IS_CALLABLE_CHECK_SYNTAX_ONLY, &zfunc_name, NULL, NULL, NULL, &obj_ptr, &error TSRMLS_CC)) { zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "Unable to unregister invalid function (%s)", error); if (error) { efree(error); Index: ext/standard/basic_functions.c =================================================================== RCS file: /repository/php-src/ext/standard/basic_functions.c,v retrieving revision 1.890 diff -u -r1.890 basic_functions.c --- ext/standard/basic_functions.c 28 Feb 2008 14:16:14 -0000 1.890 +++ ext/standard/basic_functions.c 13 Mar 2008 03:39:30 -0000 @@ -809,6 +809,19 @@ ZEND_END_ARG_INFO() static +ZEND_BEGIN_ARG_INFO_EX(arginfo_forward_static_call, 0, 0, 1) + ZEND_ARG_INFO(0, function_name) + ZEND_ARG_INFO(0, parameter) + ZEND_ARG_INFO(0, ...) +ZEND_END_ARG_INFO() + +static +ZEND_BEGIN_ARG_INFO_EX(arginfo_forward_static_call_array, 0, 0, 2) + ZEND_ARG_INFO(0, function_name) + ZEND_ARG_INFO(0, parameters) /* ARRAY_INFO(0, parameters, 1) */ +ZEND_END_ARG_INFO() + +static ZEND_BEGIN_ARG_INFO(arginfo_register_shutdown_function, 0) ZEND_ARG_INFO(0, function_name) ZEND_END_ARG_INFO() @@ -3398,6 +3411,8 @@ PHP_FE(call_user_func_array, arginfo_call_user_func_array) PHP_DEP_FE(call_user_method, arginfo_call_user_method) PHP_DEP_FE(call_user_method_array, arginfo_call_user_method_array) + PHP_FE(forward_static_call, arginfo_forward_static_call) + PHP_FE(forward_static_call_array, arginfo_forward_static_call_array) PHP_FE(serialize, arginfo_serialize) PHP_FE(unserialize, arginfo_unserialize) @@ -5193,6 +5208,67 @@ } /* }}} */ +/* {{{ proto mixed forward_static_call(mixed function_name [, mixed parmeter] [, mixed ...]) U + Call a user function which is the first parameter */ +PHP_FUNCTION(forward_static_call) +{ + zval *retval_ptr = NULL; + zend_fcall_info fci; + zend_fcall_info_cache fci_cache; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f*", &fci, &fci_cache, &fci.params, &fci.param_count) == FAILURE) { + return; + } + + if (!EG(active_op_array)->scope) { + zend_error(E_ERROR, "Cannot call forward_static_call() when no class scope is active"); + } + + fci.retval_ptr_ptr = &retval_ptr; + + if (EG(called_scope) && + instanceof_function(EG(called_scope), fci_cache.calling_scope TSRMLS_CC)) { + fci_cache.calling_scope = EG(called_scope); + } + + if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS && fci.retval_ptr_ptr && *fci.retval_ptr_ptr) { + COPY_PZVAL_TO_ZVAL(*return_value, *fci.retval_ptr_ptr); + } + + if (fci.params) { + efree(fci.params); + } +} +/* }}} */ + +/* {{{ proto mixed call_user_func_array(string function_name, array parameters) U + Call a user function which is the first parameter with the arguments contained in array */ +PHP_FUNCTION(forward_static_call_array) +{ + zval *params, *retval_ptr = NULL; + zend_fcall_info fci; + zend_fcall_info_cache fci_cache; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "fa/", &fci, &fci_cache, ¶ms) == FAILURE) { + return; + } + + zend_fcall_info_args(&fci, params TSRMLS_CC); + fci.retval_ptr_ptr = &retval_ptr; + + if (EG(called_scope) && + instanceof_function(EG(called_scope), fci_cache.calling_scope TSRMLS_CC)) { + fci_cache.calling_scope = EG(called_scope); + } + + if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS && fci.retval_ptr_ptr && *fci.retval_ptr_ptr) { + COPY_PZVAL_TO_ZVAL(*return_value, *fci.retval_ptr_ptr); + } + + zend_fcall_info_args_clear(&fci, 1); +} +/* }}} */ + void user_shutdown_function_dtor(php_shutdown_function_entry *shutdown_function_entry) /* {{{ */ { int i; Index: ext/standard/basic_functions.h =================================================================== RCS file: /repository/php-src/ext/standard/basic_functions.h,v retrieving revision 1.161 diff -u -r1.161 basic_functions.h --- ext/standard/basic_functions.h 3 Feb 2008 14:44:30 -0000 1.161 +++ ext/standard/basic_functions.h 13 Mar 2008 03:39:30 -0000 @@ -84,6 +84,8 @@ PHP_FUNCTION(call_user_func_array); PHP_FUNCTION(call_user_method); PHP_FUNCTION(call_user_method_array); +PHP_FUNCTION(forward_static_call); +PHP_FUNCTION(forward_static_call_array); PHP_FUNCTION(register_shutdown_function); PHP_FUNCTION(highlight_file);