MFHing zend_fcall_info_*() to 5.2

From: Date: Sat, 27 May 2006 20:32:13 +0000
Subject: MFHing zend_fcall_info_*() to 5.2
Groups: php.internals 
Request: Send a blank email to internals+get-23725@lists.php.net to get a copy of this message
Hello Andi, Zeev, Ilia, the attached patch adds three new functions that make calling functions a lot easier - at least for me in SPL. And it also does a few things correct which are probably overseen easily. The addition works in HEAD already and paases all memcheck tests idid so far. Best regards, Marcus

Index: Zend/zend_API.c =================================================================== RCS file: /repository/ZendEngine2/zend_API.c,v retrieving revision 1.296.2.27.2.13 diff -u -p -d -r1.296.2.27.2.13 zend_API.c --- Zend/zend_API.c 27 May 2006 20:16:53 -0000 1.296.2.27.2.13 +++ Zend/zend_API.c 27 May 2006 20:17:44 -0000 @@ -548,6 +548,22 @@ static char *zend_parse_arg_impl(int arg 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_CC) == SUCCESS) { + break; + } else if (return_null) { + fci->size = 0; + fcc->initialized = 0; + break; + } else { + return "function"; + } + } + case 'z': { zval **p = va_arg(*va, zval **); @@ -2298,6 +2314,96 @@ ZEND_API zend_bool zend_make_callable(zv } +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, 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) { + while (fci->param_count) { + zval_ptr_dtor(fci->params[--fci->param_count]); + } + 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; + (*arg)->refcount++; + 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, ***org_params; + int result, org_count; + + fci->retval_ptr_ptr = retval_ptr_ptr ? retval_ptr_ptr : &retval; + if (args) { + org_params = fci->params; + org_count = fci->param_count; + 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) { + zend_fcall_info_args(fci, NULL TSRMLS_CC); + fci->params = org_params; + fci->param_count = org_count; + } + return result; +} + + ZEND_API char *zend_get_module_version(char *module_name) { zend_module_entry *module; Index: Zend/zend_API.h =================================================================== RCS file: /repository/ZendEngine2/zend_API.h,v retrieving revision 1.207.2.8.2.2 diff -u -p -d -r1.207.2.8.2.2 zend_API.h --- Zend/zend_API.h 25 May 2006 10:01:06 -0000 1.207.2.8.2.2 +++ Zend/zend_API.h 27 May 2006 20:17:44 -0000 @@ -385,6 +385,26 @@ typedef struct _zend_fcall_info_cache { BEGIN_EXTERN_C() ZEND_API extern zend_fcall_info_cache empty_fcall_info_cache; +/** 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); + +/** Set or clear the arguments in the zend_call_info struct taking care of + * refcount. If args is NULL and arguments are set then those are cleared. + */ +ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC); + +/** Call a function using information created by zend_fcall_info_init()/args(). + * If args is given then those replace the arguement info in fci is temporarily. + */ +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);
« previous php.internals (#23725) next »