summaryrefslogtreecommitdiff
path: root/Zend/zend_API.c
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@php.net>2007-09-29 08:52:40 +0000
committerDmitry Stogov <dmitry@php.net>2007-09-29 08:52:40 +0000
commitb20ed0d2e01861d5691395062e2167c5e9e9e1c9 (patch)
treed4b26d975d308eda244ae531a6df8ee15309d926 /Zend/zend_API.c
parentc560a968482060382176bb299ef886c45dd66464 (diff)
downloadphp-git-b20ed0d2e01861d5691395062e2167c5e9e9e1c9.tar.gz
Added support for __callstatic() magic method. (Sara)
Diffstat (limited to 'Zend/zend_API.c')
-rw-r--r--Zend/zend_API.c31
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;