From: Michael Wallner Date: Mon, 15 Feb 2016 10:45:27 +0000 (+0100) Subject: extract psi_callback() X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=e472b48ff23ab19da6a8719db243ac8788eb34f4;p=m6w6%2Fext-psi extract psi_callback() --- diff --git a/src/engine.c b/src/engine.c index a78f9ff..447e0d7 100644 --- a/src/engine.c +++ b/src/engine.c @@ -488,7 +488,7 @@ static inline impl_vararg *psi_do_varargs(impl *impl) { return va; } -void psi_call(zend_execute_data *execute_data, zval *return_value, impl *impl) +ZEND_RESULT_CODE psi_call(zend_execute_data *execute_data, zval *return_value, impl *impl) { size_t i; impl_vararg *va = NULL; @@ -496,7 +496,7 @@ void psi_call(zend_execute_data *execute_data, zval *return_value, impl *impl) memset(impl->decl->func->ptr, 0, sizeof(impl_val)); if (SUCCESS != psi_parse_args(execute_data, impl)) { - return; + return FAILURE; } for (i = 0; i < impl->stmts->let.count; ++i) { @@ -505,7 +505,7 @@ void psi_call(zend_execute_data *execute_data, zval *return_value, impl *impl) if (!psi_do_let(let)) { psi_do_return(return_value, impl->stmts->ret.list[0]); psi_do_clean(impl); - return; + return FAILURE; } } @@ -534,4 +534,54 @@ void psi_call(zend_execute_data *execute_data, zval *return_value, impl *impl) psi_do_free(fre); } psi_do_clean(impl); + + return SUCCESS; +} + +ZEND_RESULT_CODE psi_callback(let_callback *cb, void *retval, unsigned argc, void **argv) +{ + size_t i; + decl *decl_cb = cb->decl; + impl_arg *iarg = cb->func->var->arg; + zval return_value, *zargv = calloc(argc, sizeof(*zargv)); + void *result, *to_free = NULL; + + ZEND_ASSERT(argc == cb->decl->args->count); + + /* prepare args for the userland call */ + for (i = 0; i < argc; ++i) { + cb->decl->args->args[i]->let = argv[i]; + } + for (i = 0; i < cb->args->count; ++i) { + psi_do_set(&zargv[i], cb->args->vals[i]); + } + zend_fcall_info_argp(&iarg->val.zend.cb->fci, cb->args->count, zargv); + + /* callback into userland */ + ZVAL_UNDEF(&return_value); + iarg->_zv = &return_value; + zend_fcall_info_call(&iarg->val.zend.cb->fci, &iarg->val.zend.cb->fcc, iarg->_zv, NULL); + + /* marshal return value of the userland call */ + switch (iarg->type->type) { + case PSI_T_BOOL: zend_parse_arg_bool(iarg->_zv, &iarg->val.zend.bval, NULL, 0); break; + case PSI_T_LONG: zend_parse_arg_long(iarg->_zv, &iarg->val.zend.lval, NULL, 0, 1); break; + case PSI_T_FLOAT: + case PSI_T_DOUBLE: zend_parse_arg_double(iarg->_zv, &iarg->val.dval, NULL, 0); break; + case PSI_T_STRING: zend_parse_arg_str(iarg->_zv, &iarg->val.zend.str, 0); break; + } + result = cb->func->handler(retval, decl_cb->func->type, iarg, &to_free); + + if (result != retval) { + *(void **)retval = result; + } + + zend_fcall_info_args_clear(&iarg->val.zend.cb->fci, 0); + for (i = 0; i < cb->args->count; ++i) { + zval_ptr_dtor(&zargv[i]); + } + free(zargv); + + return SUCCESS; + } diff --git a/src/engine.h b/src/engine.h index 62e1689..3aa78a4 100644 --- a/src/engine.h +++ b/src/engine.h @@ -28,6 +28,7 @@ int psi_internal_type(impl_type *type); zend_internal_arg_info *psi_internal_arginfo(impl *impl); size_t psi_num_min_args(impl *impl); -void psi_call(zend_execute_data *execute_data, zval *return_value, impl *impl); +ZEND_RESULT_CODE psi_call(zend_execute_data *execute_data, zval *return_value, impl *impl); +ZEND_RESULT_CODE psi_callback(let_callback *cb, void *retval, unsigned argc, void **argv); #endif diff --git a/src/libffi.c b/src/libffi.c index 78b0239..81dc238 100644 --- a/src/libffi.c +++ b/src/libffi.c @@ -78,50 +78,7 @@ static void psi_ffi_handler(ffi_cif *_sig, void *_result, void **_args, void *_d static void psi_ffi_callback(ffi_cif *_sig, void *_result, void **_args, void *_data) { - size_t i; - unsigned argc = _sig->nargs; - void **argv = _args; - let_callback *cb = _data; - decl *decl_cb = cb->decl; - impl_arg *iarg = cb->func->var->arg; - zval return_value, *zargv = calloc(argc, sizeof(*zargv)); - void *result, *to_free = NULL; - - ZEND_ASSERT(argc == cb->decl->args->count); - - /* prepare args for the userland call */ - for (i = 0; i < argc; ++i) { - cb->decl->args->args[i]->let = argv[i]; - } - for (i = 0; i < cb->args->count; ++i) { - psi_do_set(&zargv[i], cb->args->vals[i]); - } - zend_fcall_info_argp(&iarg->val.zend.cb->fci, cb->args->count, zargv); - - /* callback into userland */ - ZVAL_UNDEF(&return_value); - iarg->_zv = &return_value; - zend_fcall_info_call(&iarg->val.zend.cb->fci, &iarg->val.zend.cb->fcc, iarg->_zv, NULL); - - /* marshal return value of the userland call */ - switch (iarg->type->type) { - case PSI_T_BOOL: zend_parse_arg_bool(iarg->_zv, &iarg->val.zend.bval, NULL, 0); break; - case PSI_T_LONG: zend_parse_arg_long(iarg->_zv, &iarg->val.zend.lval, NULL, 0, 1); break; - case PSI_T_FLOAT: - case PSI_T_DOUBLE: zend_parse_arg_double(iarg->_zv, &iarg->val.dval, NULL, 0); break; - case PSI_T_STRING: zend_parse_arg_str(iarg->_zv, &iarg->val.zend.str, 0); break; - } - result = cb->func->handler(_result, decl_cb->func->type, iarg, &to_free); - - if (result != _result) { - *(void **)_result = result; - } - - zend_fcall_info_args_clear(&iarg->val.zend.cb->fci, 0); - for (i = 0; i < cb->args->count; ++i) { - zval_ptr_dtor(&zargv[i]); - } - free(zargv); + psi_callback(_data, _result, _sig->nargs, _args); } static inline ffi_type *psi_ffi_decl_arg_type(decl_arg *darg);