Skip to content

Commit

Permalink
- MFH zend_fcall_info_*() and parameter parsing option 'f'
Browse files Browse the repository at this point in the history
# Right now i see this as the best option but we might shuffle code around
# later if someone comes up with a better solution.
  • Loading branch information
helly25 committed Jun 7, 2006
1 parent 1f93575 commit 64c353a
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 0 deletions.
106 changes: 106 additions & 0 deletions Zend/zend_API.c
Expand Up @@ -566,6 +566,22 @@ static char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, char **sp
} }
break; 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': case 'z':
{ {
zval **p = va_arg(*va, zval **); zval **p = va_arg(*va, zval **);
Expand Down Expand Up @@ -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_API char *zend_get_module_version(char *module_name)
{ {
zend_module_entry *module; zend_module_entry *module;
Expand Down
20 changes: 20 additions & 0 deletions Zend/zend_API.h
Expand Up @@ -385,6 +385,26 @@ typedef struct _zend_fcall_info_cache {
BEGIN_EXTERN_C() BEGIN_EXTERN_C()
ZEND_API extern zend_fcall_info_cache empty_fcall_info_cache; 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); ZEND_API int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC);




Expand Down

0 comments on commit 64c353a

Please sign in to comment.