diff options
author | Marcus Boerger <helly@php.net> | 2006-06-07 09:43:54 +0000 |
---|---|---|
committer | Marcus Boerger <helly@php.net> | 2006-06-07 09:43:54 +0000 |
commit | 64c353ab79e3a49ae2aba533d353d4a93fe4b099 (patch) | |
tree | c462411f5fbb0d02143964910563642c93c1b9a3 /Zend/zend_API.c | |
parent | 1f93575c88fff9e05e1904ba02d0975ab33f0c67 (diff) | |
download | php-git-64c353ab79e3a49ae2aba533d353d4a93fe4b099.tar.gz |
- MFH zend_fcall_info_*() and parameter parsing option 'f'
# Right now i see this as the best option but we might shuffle code around
# later if someone comes up with a better solution.
Diffstat (limited to 'Zend/zend_API.c')
-rw-r--r-- | Zend/zend_API.c | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 31faa25e7a..57892f3b99 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -566,6 +566,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_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 **); @@ -2309,6 +2325,96 @@ 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) +{ + 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; |