summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrei Zmievski <andrei@php.net>2001-03-12 03:08:28 +0000
committerAndrei Zmievski <andrei@php.net>2001-03-12 03:08:28 +0000
commit13148b549121ca0e83f1a9e4a330763257e317c9 (patch)
tree56f909becbcde3aa064eead0db075673ee48ec3f
parentd73ef1242986f84a7bb9e6fa088f19d4f22b05dc (diff)
downloadphp-git-13148b549121ca0e83f1a9e4a330763257e317c9.tar.gz
Improve zend_is_callable() to the point where it's actually useful.
Now it just needs to be invoked everywhere in PHP where a callback is expected.
-rw-r--r--Zend/zend_API.c63
-rw-r--r--Zend/zend_API.h2
2 files changed, 53 insertions, 12 deletions
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 4a14709125..b743e0a58f 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -910,40 +910,81 @@ ZEND_API int zend_disable_function(char *function_name, uint function_name_lengt
return zend_register_functions(disabled_function, CG(function_table), MODULE_PERSISTENT);
}
-ZEND_API zend_bool zend_is_callable(zval *function)
+zend_bool zend_is_callable(zval *callable, zend_bool syntax_only, char **callable_name)
{
char *lcname;
- zend_bool retval = 0;
+ int retval = 0;
ELS_FETCH();
- switch (Z_TYPE_P(function)) {
+ switch (Z_TYPE_P(callable)) {
case IS_STRING:
- lcname = estrndup(Z_STRVAL_P(function), Z_STRLEN_P(function));
- zend_str_tolower(lcname, Z_STRLEN_P(function));
- if (zend_hash_exists(EG(function_table), lcname, Z_STRLEN_P(function)+1))
+ if (syntax_only)
+ return 1;
+
+ lcname = estrndup(Z_STRVAL_P(callable), Z_STRLEN_P(callable));
+ zend_str_tolower(lcname, Z_STRLEN_P(callable));
+ if (zend_hash_exists(EG(function_table), lcname, Z_STRLEN_P(callable)+1))
retval = 1;
efree(lcname);
+ if (!retval && callable_name)
+ *callable_name = estrndup(Z_STRVAL_P(callable), Z_STRLEN_P(callable));
break;
case IS_ARRAY:
{
zval **method;
zval **obj;
+ zend_class_entry *ce;
+ char name_buf[1024];
+ char callable_name_len;
- if (zend_hash_index_find(Z_ARRVAL_P(function), 0, (void **) &obj) == SUCCESS &&
- zend_hash_index_find(Z_ARRVAL_P(function), 1, (void **) &method) == SUCCESS &&
- Z_TYPE_PP(obj) == IS_OBJECT &&
+ if (zend_hash_index_find(Z_ARRVAL_P(callable), 0, (void **) &obj) == SUCCESS &&
+ zend_hash_index_find(Z_ARRVAL_P(callable), 1, (void **) &method) == SUCCESS &&
+ (Z_TYPE_PP(obj) == IS_OBJECT || Z_TYPE_PP(obj) == IS_STRING) &&
Z_TYPE_PP(method) == IS_STRING) {
+
+ if (syntax_only)
+ return 1;
+
+ if (Z_TYPE_PP(obj) == IS_STRING) {
+ int found;
+
+ lcname = estrndup(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj));
+ zend_str_tolower(lcname, Z_STRLEN_PP(obj));
+ found = zend_hash_find(EG(class_table), lcname, Z_STRLEN_PP(obj) + 1, (void**)&ce);
+ efree(lcname);
+ if (found == FAILURE) {
+ if (callable_name) {
+ callable_name_len = snprintf(name_buf, 1024, "%s::%s", Z_STRVAL_PP(obj), Z_STRVAL_PP(method));
+ *callable_name = estrndup(name_buf, callable_name_len);
+ }
+ break;
+ }
+ } else
+ ce = Z_OBJCE_PP(obj);
lcname = estrndup(Z_STRVAL_PP(method), Z_STRLEN_PP(method));
zend_str_tolower(lcname, Z_STRLEN_PP(method));
- if (zend_hash_exists(&Z_OBJCE_PP(obj)->function_table, lcname, Z_STRLEN_PP(method)+1))
+ if (zend_hash_exists(&ce->function_table, lcname, Z_STRLEN_PP(method)+1))
retval = 1;
+ if (!retval && callable_name) {
+ callable_name_len = snprintf(name_buf, 1024, "%s::%s", ce->name, Z_STRVAL_PP(method));
+ *callable_name = estrndup(name_buf, callable_name_len);
+ }
efree(lcname);
- }
+ } else if (callable_name)
+ *callable_name = estrndup("Array", sizeof("Array")-1);
}
break;
default:
+ if (callable_name) {
+ zval expr_copy;
+ int use_copy;
+
+ zend_make_printable_zval(callable, &expr_copy, &use_copy);
+ *callable_name = estrndup(Z_STRVAL(expr_copy), Z_STRLEN(expr_copy));
+ zval_dtor(&expr_copy);
+ }
break;
}
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index 3b88d917ad..2ad161ea6b 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -120,7 +120,7 @@ ZEND_API zend_module_entry *zend_get_module(int module_number);
ZEND_API int zend_disable_function(char *function_name, uint function_name_length);
ZEND_API void wrong_param_count(void);
-ZEND_API zend_bool zend_is_callable(zval *function);
+ZEND_API zend_bool zend_is_callable(zval *callable, zend_bool syntax_only, char **callable_name);
#define getThis() (this_ptr)