From 9114bc25c3b78e46f1cab137b6f25b9749f53269 Mon Sep 17 00:00:00 2001 From: Marcus Boerger Date: Thu, 25 May 2006 22:20:13 +0000 Subject: [PATCH] - Ease writing functions that deal with php function 'pointers' --- Zend/zend_API.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++- Zend/zend_API.h | 13 +++++- 2 files changed, 112 insertions(+), 3 deletions(-) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 2ab16741a4..d500c0cec2 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -751,6 +751,22 @@ static char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, char **sp } break; + case 'f': + { + zend_fcall_info *fci = va_arg(*va, zend_fcall_info *); + zend_fcall_info_cache *fcc = va_arg(*va, zend_fcall_info_cache *); + + if (zend_fcall_info_init(*arg, fci, fcc TSRMLS_DC) == SUCCESS) { + break; + } else if (return_null) { + fci->size = 0; + fcc->initialized = 0; + break; + } else { + return "function"; + } + } + case 'z': { zval **p = va_arg(*va, zval **); @@ -828,7 +844,7 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl case 't': case 'y': case 'u': case 'C': case 'h': case 'U': - case 'S': + case 'S': case 'f': max_num_args++; break; @@ -2824,7 +2840,7 @@ ZEND_API zend_bool zend_make_callable(zval *callable, zval *callable_name TSRMLS zend_class_entry **pce; int class_name_len; - if (zend_is_callable_ex(callable, 0, callable_name, NULL, NULL, NULL TSRMLS_CC)) { + if (zend_is_callable_ex(callable, IS_CALLABLE_STRICT, callable_name, NULL, NULL, NULL TSRMLS_CC)) { return 1; } switch (Z_TYPE_P(callable)) { @@ -2852,6 +2868,88 @@ ZEND_API zend_bool zend_make_callable(zval *callable, zval *callable_name TSRMLS } +ZEND_API int zend_fcall_info_init(zval *callable, zend_fcall_info *fci, zend_fcall_info_cache *fcc TSRMLS_DC) +{ + zend_class_entry *ce; + zend_function *func; + zval **obj; + + if (!zend_is_callable_ex(callable, IS_CALLABLE_STRICT, NULL, &ce, &func, &obj TSRMLS_CC)) { + return FAILURE; + } + + fci->size = sizeof(*fci); + fci->function_table = ce ? &ce->function_table : EG(function_table); + fci->object_pp = obj; + fci->function_name = NULL; + fci->retval_ptr_ptr = NULL; + fci->param_count = 0; + fci->params = NULL; + fci->no_separation = 1; + fci->symbol_table = NULL; + + fcc->initialized = 1; + fcc->function_handler = func; + fcc->calling_scope = ce; + fcc->object_pp = obj; + + return SUCCESS; +} + + +ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC) +{ + HashPosition pos; + zval **arg, ***params; + + if (fci->params) { + efree(fci->params); + } + fci->params = NULL; + fci->param_count = 0; + + if (!args) { + return SUCCESS; + } + + if (Z_TYPE_P(args) != IS_ARRAY) { + return FAILURE; + } + + fci->param_count = zend_hash_num_elements(Z_ARRVAL_P(args)); + fci->params = params = (zval***)safe_emalloc(sizeof(zval**), fci->param_count, 0); + + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(args), &pos); + + while (zend_hash_get_current_data_ex(Z_ARRVAL_P(args), (void **) &arg, &pos) == SUCCESS) { + *params++ = arg; + zend_hash_move_forward_ex(Z_ARRVAL_P(args), &pos); + } + return SUCCESS; +} + + +ZEND_API int zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval **retval_ptr_ptr, zval *args TSRMLS_DC) +{ + zval *retval; + int result; + + fci->retval_ptr_ptr = retval_ptr_ptr ? retval_ptr_ptr : &retval; + if (args) { + 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); + } + if (args && fci->params) { + efree(fci->params); + } + return result; +} + + ZEND_API char *zend_get_module_version(char *module_name) { zend_module_entry *module; diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 1ef01368a3..541218b676 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -653,8 +653,19 @@ typedef struct _zend_fcall_info_cache { BEGIN_EXTERN_C() ZEND_API extern zend_fcall_info_cache empty_fcall_info_cache; -ZEND_API int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC); +/* Build zend_call_info/cache from a zval* + * + * Caller is responsible to provide a return value, otherwise the we will crash. + * fci->retval_ptr_ptr = NULL; + * In order to pass parameters the following members need to be set: + * fci->param_count = 0; + * fci->params = NULL; + */ +ZEND_API int zend_fcall_info_init(zval *callable, zend_fcall_info *fci, zend_fcall_info_cache *fcc TSRMLS_DC); +ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC); +ZEND_API int zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval **retval, zval *args TSRMLS_DC); +ZEND_API int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC); ZEND_API int zend_set_hash_symbol(zval *symbol, char *name, int name_length, zend_bool is_ref, int num_symbol_tables, ...); -- 2.40.0