diff options
author | Dmitry Stogov <dmitry@php.net> | 2007-09-29 08:52:40 +0000 |
---|---|---|
committer | Dmitry Stogov <dmitry@php.net> | 2007-09-29 08:52:40 +0000 |
commit | b20ed0d2e01861d5691395062e2167c5e9e9e1c9 (patch) | |
tree | d4b26d975d308eda244ae531a6df8ee15309d926 /Zend/zend_API.c | |
parent | c560a968482060382176bb299ef886c45dd66464 (diff) | |
download | php-git-b20ed0d2e01861d5691395062e2167c5e9e9e1c9.tar.gz |
Added support for __callstatic() magic method. (Sara)
Diffstat (limited to 'Zend/zend_API.c')
-rw-r--r-- | Zend/zend_API.c | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 184812941e..bce509d24a 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1623,6 +1623,16 @@ ZEND_API void zend_check_magic_method_implementation(zend_class_entry *ce, zend_ } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) { zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_CALL_FUNC_NAME); } + } else if (name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME) - 1 && + !memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1)) { + if (fptr->common.num_args != 2) { + zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_CALLSTATIC_FUNC_NAME); + } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) { + zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_CALLSTATIC_FUNC_NAME); + } + } else if (name_len == sizeof(ZEND_TOSTRING_FUNC_NAME) - 1 && + !memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && fptr->common.num_args != 0) { + zend_error(error_type, "Method %s::%s() cannot take arguments", ce->name, ZEND_TOSTRING_FUNC_NAME); } } @@ -1635,7 +1645,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio int count=0, unload=0; HashTable *target_function_table = function_table; int error_type; - zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL, *__tostring = NULL; + zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL, *__callstatic = NULL, *__tostring = NULL; char *lowercase_name; int fname_len; char *lc_class_name = NULL; @@ -1748,6 +1758,8 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio clone = reg_function; } else if ((fname_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME))) { __call = reg_function; + } else if ((fname_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME))) { + __callstatic = reg_function; } else if ((fname_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME))) { __tostring = reg_function; } else if ((fname_len == sizeof(ZEND_GET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME))) { @@ -1787,6 +1799,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio scope->destructor = dtor; scope->clone = clone; scope->__call = __call; + scope->__callstatic = __callstatic; scope->__tostring = __tostring; scope->__get = __get; scope->__set = __set; @@ -1819,6 +1832,12 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio } __call->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } + if (__callstatic) { + if (!(__callstatic->common.fn_flags & ZEND_ACC_STATIC)) { + zend_error(error_type, "Method %s::%s() must be static", scope->name, __callstatic->common.function_name); + } + __callstatic->common.fn_flags |= ZEND_ACC_STATIC; + } if (__tostring) { if (__tostring->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __tostring->common.function_name); @@ -2202,6 +2221,9 @@ static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, ze if (*zobj_ptr_ptr && *ce_ptr && (*ce_ptr)->__call != 0) { retval = (*ce_ptr)->__call != NULL; *fptr_ptr = (*ce_ptr)->__call; + } else if (!*zobj_ptr_ptr && *ce_ptr && (*ce_ptr)->__callstatic) { + retval = 1; + *fptr_ptr = (*ce_ptr)->__callstatic; } } else { *fptr_ptr = fptr; @@ -2397,6 +2419,7 @@ ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRML ZEND_API int zend_fcall_info_init(zval *callable, zend_fcall_info *fci, zend_fcall_info_cache *fcc TSRMLS_DC) { + int len; zend_class_entry *ce; zend_function *func; zval **obj; @@ -2415,7 +2438,11 @@ ZEND_API int zend_fcall_info_init(zval *callable, zend_fcall_info *fci, zend_fca fci->no_separation = 1; fci->symbol_table = NULL; - if (strlen(func->common.function_name) == sizeof(ZEND_CALL_FUNC_NAME) - 1 && !memcmp(func->common.function_name, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME))) { + len = strlen(func->common.function_name); + if ((len == sizeof(ZEND_CALL_FUNC_NAME) - 1 && + !memcmp(func->common.function_name, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1)) || + (len == sizeof(ZEND_CALLSTATIC_FUNC_NAME) - 1 && + !memcmp(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; |