static UBool enumCharNames_callback(enumCharNames_data *context, UChar32 code, UCharNameChoice nameChoice, const char *name, int32_t length) { zval retval; zval args[3]; ZVAL_NULL(&retval); ZVAL_LONG(&args[0], code); ZVAL_LONG(&args[1], nameChoice); ZVAL_STRINGL(&args[2], name, length); context->fci.retval = &retval; context->fci.param_count = 3; context->fci.params = args; if (zend_call_function(&context->fci, &context->fci_cache) == FAILURE) { intl_error_set_code(NULL, U_INTERNAL_PROGRAM_ERROR); intl_error_set_custom_msg(NULL, "enumCharNames callback failed", 0); zval_ptr_dtor(&retval); zval_ptr_dtor_str(&args[2]); return 0; } zval_ptr_dtor(&retval); zval_ptr_dtor_str(&args[2]); return 1; }
ZEND_RESULT_CODE php_http_object_method_call(php_http_object_method_t *cb, zval *zobject, zval *retval_ptr, int argc, zval *args) { ZEND_RESULT_CODE rv; zval retval; ZVAL_UNDEF(&retval); Z_ADDREF_P(zobject); cb->fci.object = Z_OBJ_P(zobject); cb->fcc.object = Z_OBJ_P(zobject); cb->fci.retval = retval_ptr ? retval_ptr : &retval; cb->fci.param_count = argc; cb->fci.params = args; if (cb->fcc.called_scope != Z_OBJCE_P(zobject)) { cb->fcc.called_scope = Z_OBJCE_P(zobject); cb->fcc.function_handler = Z_OBJ_HT_P(zobject)->get_method(&Z_OBJ_P(zobject), Z_STR(cb->fci.function_name), NULL); } rv = zend_call_function(&cb->fci, &cb->fcc); zval_ptr_dtor(zobject); if (!retval_ptr && !Z_ISUNDEF(retval)) { zval_ptr_dtor(&retval); } return rv; }
static UBool enumCharType_callback(enumCharType_data *context, UChar32 start, UChar32 limit, UCharCategory type) { zval retval; zval args[3]; ZVAL_NULL(&retval); /* Note that $start is INclusive, whiel $limit is EXclusive * Therefore (0, 32, 15) means CPs 0..31 are of type 15 */ ZVAL_LONG(&args[0], start); ZVAL_LONG(&args[1], limit); ZVAL_LONG(&args[2], type); context->fci.retval = &retval; context->fci.param_count = 3; context->fci.params = args; if (zend_call_function(&context->fci, &context->fci_cache) == FAILURE) { intl_error_set_code(NULL, U_INTERNAL_PROGRAM_ERROR); intl_errors_set_custom_msg(NULL, "enumCharTypes callback failed", 0); zval_dtor(&retval); return 0; } zval_dtor(&retval); return 1; }
static ZEND_NAMED_FUNCTION(zend_closure_call_magic) /* {{{ */ { zend_fcall_info fci; zend_fcall_info_cache fcc; zval params[2]; memset(&fci, 0, sizeof(zend_fcall_info)); memset(&fci, 0, sizeof(zend_fcall_info_cache)); fci.size = sizeof(zend_fcall_info); fci.retval = return_value; fcc.initialized = 1; fcc.function_handler = (zend_function *) EX(func)->common.arg_info; fci.params = params; fci.param_count = 2; ZVAL_STR(&fci.params[0], EX(func)->common.function_name); array_init(&fci.params[1]); zend_copy_parameters_array(ZEND_NUM_ARGS(), &fci.params[1]); fci.object = Z_OBJ(EX(This)); fcc.object = Z_OBJ(EX(This)); fcc.calling_scope = zend_get_executed_scope(); zend_call_function(&fci, &fcc); zval_ptr_dtor(&fci.params[0]); zval_ptr_dtor(&fci.params[1]); }
static void glib_source_callback_helper(zval *retval, zval *source_zval, const char *name, zval *params, uint32_t param_count) { zend_fcall_info fci; zend_fcall_info_cache fci_cache; zval caller; array_init(&caller); add_index_zval(&caller, 0, source_zval); add_index_string(&caller, 1, name); char * callback_error; if(FAILURE == zend_fcall_info_init(&caller, IS_CALLABLE_STRICT, &fci, &fci_cache, NULL, &callback_error)) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Could not call %s source handler, %s", name, callback_error); zval_dtor(&caller); return; } /* Handle arguments if necessary */ fci.param_count = param_count; if(param_count > 0) { fci.params = params; } fci.retval = retval; if(FAILURE == zend_call_function(&fci, &fci_cache)) { zend_throw_exception_ex(spl_ce_BadFunctionCallException, 0, "Could not call %s source handler", name); } zval_dtor(&caller); }
/* {{{ */ void pthreads_write_property(PTHREADS_WRITE_PROPERTY_PASSTHRU_D) { pthreads_object_t* threaded = PTHREADS_FETCH_FROM(Z_OBJ_P(object)); zend_bool nulled = 0; rebuild_object_properties(&threaded->std); switch(Z_TYPE_P(value)){ case IS_UNDEF: case IS_STRING: case IS_LONG: case IS_ARRAY: case IS_OBJECT: case IS_NULL: case IS_DOUBLE: case IS_RESOURCE: case IS_TRUE: case IS_FALSE: { zend_long *guard = NULL; if ((member && Z_TYPE_P(member) != IS_NULL) && Z_OBJCE_P(object)->__set && (guard = pthreads_get_guard(&threaded->std, member)) && !((*guard) & IN_SET)) { zend_fcall_info fci = empty_fcall_info; zend_fcall_info_cache fcc = empty_fcall_info_cache; zval rv; ZVAL_UNDEF(&rv); fci.size = sizeof(zend_fcall_info); fci.retval = &rv; fci.object = &threaded->std; zend_fcall_info_argn(&fci, 2, member, value); fcc.initialized = 1; fcc.function_handler = Z_OBJCE_P(object)->__set; fcc.object = &threaded->std; (*guard) |= IN_SET; zend_call_function(&fci, &fcc); (*guard) &= ~IN_SET; if (Z_TYPE(rv) != IS_UNDEF) zval_dtor(&rv); zend_fcall_info_args_clear(&fci, 1); } else { pthreads_store_write(object, member, value); } } break; default: { zend_throw_exception_ex( spl_ce_RuntimeException, 0, "pthreads detected an attempt to use unsupported data (%s) for %s::$%s", zend_get_type_by_const(Z_TYPE_P(value)), ZSTR_VAL(Z_OBJCE_P(object)->name), Z_STRVAL_P(member)); } } }
int php_print_r_zval_and_key(zval **val,int num_args,va_list args,zend_hash_key *hash_key) { //重新copy一个zval,防止破坏原数据 zval tmpcopy = **val; zval *tmpcopy_ptr = &tmpcopy; /* tsrm_ls is needed by output functions */ TSRMLS_FETCH(); zval_copy_ctor(&tmpcopy); INIT_PZVAL(&tmpcopy); //执行输出 php_printf("The value of "); if (hash_key->nKeyLength){ //如果是字符串类型的key PHPWRITE(hash_key->arKey, hash_key->nKeyLength); }else{ //如果是数字类型的key php_printf("%ld", hash_key->h); } php_printf(" is: "); //调用print_r函数 zval *function,*ret = NULL; //函数名 MAKE_STD_ZVAL(function); ZVAL_STRING(function, "print_r", 0); //参数是一个zval* 数组 zval **params[1] = {&tmpcopy_ptr}; zend_fcall_info fci = { sizeof(fci), EG(function_table), function, NULL, &ret, 1, (zval ***)params, NULL, 1 }; zend_call_function(&fci, NULL TSRMLS_CC); php_printf("\n"); zval_dtor(function); //毁尸灭迹 zval_dtor(&tmpcopy); /* continue; */ return ZEND_HASH_APPLY_KEEP; }
/* {{{ proto mixed Closure::call(object $to [, mixed $parameter] [, mixed $...] ) Call closure, binding to a given object with its class as the scope */ ZEND_METHOD(Closure, call) { zval *zclosure, *newthis, closure_result; zend_closure *closure; zend_fcall_info fci; zend_fcall_info_cache fci_cache; zval *my_params; int my_param_count = 0; zend_function my_function; if (zend_parse_parameters(ZEND_NUM_ARGS(), "o*", &newthis, &my_params, &my_param_count) == FAILURE) { return; } zclosure = getThis(); closure = (zend_closure *)Z_OBJ_P(zclosure); if (closure->func.common.fn_flags & ZEND_ACC_STATIC) { zend_error(E_WARNING, "Cannot bind an instance to a static closure"); return; } if (closure->func.type == ZEND_INTERNAL_FUNCTION) { /* verify that we aren't binding internal function to a wrong object */ if ((closure->func.common.fn_flags & ZEND_ACC_STATIC) == 0 && !instanceof_function(Z_OBJCE_P(newthis), closure->func.common.scope)) { zend_error(E_WARNING, "Cannot bind function %s::%s to object of class %s", closure->func.common.scope->name->val, closure->func.common.function_name->val, Z_OBJCE_P(newthis)->name->val); return; } } /* This should never happen as closures will always be callable */ if (zend_fcall_info_init(zclosure, 0, &fci, &fci_cache, NULL, NULL) != SUCCESS) { ZEND_ASSERT(0); } fci.retval = &closure_result; fci.params = my_params; fci.param_count = my_param_count; fci.object = fci_cache.object = Z_OBJ_P(newthis); fci_cache.initialized = 1; my_function = *fci_cache.function_handler; /* use scope of passed object */ my_function.common.scope = Z_OBJCE_P(newthis); fci_cache.function_handler = &my_function; if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(closure_result) != IS_UNDEF) { ZVAL_COPY_VALUE(return_value, &closure_result); } }
int static edge_register_autoload(zval *loader, const char *fname) { zval *z_function; zval *arg; zval **args[1] = {&arg}; zval *method; zval *ret = NULL; MAKE_STD_ZVAL(z_function); ZVAL_STRING(z_function, "spl_autoload_register", 0); MAKE_STD_ZVAL(method); ZVAL_STRING(method, fname, 1); MAKE_STD_ZVAL(arg); array_init(arg); zend_hash_next_index_insert(Z_ARRVAL_P(arg), &loader, sizeof(zval *), NULL); zend_hash_next_index_insert(Z_ARRVAL_P(arg), &method, sizeof(zval *), NULL); zend_fcall_info fci = { sizeof(fci), EG(function_table), z_function, NULL, &ret, 1, (zval ***)args, NULL, 1 }; if(zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE) { if(ret) { zval_ptr_dtor(&ret); } zval_ptr_dtor(&z_function); zval_ptr_dtor(&arg); return 0; } if(ret) { zval_ptr_dtor(&ret); } Z_ADDREF_P(loader); efree(z_function); zval_ptr_dtor(&arg); return 1; }
zval * util_array_map_deep(zval* arr, zend_fcall_info* fci, zend_fcall_info_cache* fci_cache, zend_bool on_nonscalar) { zval *result, **zvalue; char *key; uint keylen; ulong idx; int type, value_type; HashTable* arr_hash; HashPosition pointer; zval **args[1]; zval **arr_value; MAKE_STD_ZVAL(result); array_init(result); TSRMLS_FETCH(); // Copy a temp array zval temp; temp = *arr; zval_copy_ctor(&temp); arr_hash = Z_ARRVAL_P(&temp); zend_hash_internal_pointer_reset_ex(arr_hash, &pointer); while (zend_hash_get_current_data_ex(arr_hash, (void**) &zvalue, &pointer) == SUCCESS) { type = zend_hash_get_current_key_ex(arr_hash, &key, &keylen, &idx, 0, &pointer); value_type = Z_TYPE_P(*zvalue); if (value_type == IS_ARRAY) { if (type == HASH_KEY_IS_LONG) { add_index_zval(result, idx, util_array_map_deep(*zvalue, fci, fci_cache, on_nonscalar)); } else { add_assoc_zval(result, key, util_array_map_deep(*zvalue, fci, fci_cache, on_nonscalar)); } } else if (value_type == IS_BOOL || value_type == IS_LONG || value_type == IS_DOUBLE || value_type == IS_STRING || on_nonscalar) { zval *retval_ptr = NULL; args[0] = zvalue; (*fci).retval_ptr_ptr = &retval_ptr; (*fci).params = args; if (zend_call_function(fci, fci_cache TSRMLS_CC) == SUCCESS && retval_ptr) { if (type == HASH_KEY_IS_LONG) { add_index_zval(result, idx, retval_ptr); } else { add_assoc_zval(result, key, retval_ptr); } } } zend_hash_move_forward_ex(arr_hash, &pointer); } return result; }
VALUE php_value_call(int argc, VALUE *argv, VALUE self) { char *is_callable_error; zend_fcall_info fci; zend_fcall_info_cache fcc; zval ***call_args; zval **zval_array; zval *retval_ptr = NULL; int i, call_result; VALUE args, retval; rb_scan_args(argc, argv, "*", &args); if (zend_fcall_info_init(get_zval(self), 0, &fci, &fcc, NULL, &is_callable_error TSRMLS_CC) == FAILURE) { VALUE err = rb_str_new2(is_callable_error); efree(is_callable_error); rb_raise(rb_eRuntimeError, "no callable: %s", err); } zval_array = (zval**)malloc(sizeof(zval*) * argc); call_args = (zval***)malloc(sizeof(zval**) * argc); for(i=0; i<argc; ++i) { zval_array[i] = value_to_zval(RARRAY_PTR(args)[i]); call_args[i] = &zval_array[i]; } fci.retval_ptr_ptr = &retval_ptr; fci.param_count = argc; fci.params = call_args; call_result = zend_call_function(&fci, &fcc TSRMLS_CC); retval = new_php_embed_value(retval_ptr); free(call_args); for(i=0; i<argc-1; ++i) { zval_dtor(zval_array[i]); FREE_ZVAL(zval_array[i]); } free(zval_array); if (FAILURE == call_result) { rb_raise(rb_eRuntimeError, "function call fairure"); } return retval; }
/* {{{ proto lmDB\\Env::tnx_begin(parent, flags) Create a transaction for use with the environment. */ PHP_METHOD(lmdb_env, tnx_begin) { printf("lmdb_env,tnx_begin\n"); zval *zptr = 0; zval **params[3]; zval z_fname; ZVAL_STRING(&z_fname, "__construct",1); long p_flags = 0; unsigned int flags = 0; zend_fcall_info fci; lmdb_txn_object * txn; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z!l", &zptr, &p_flags) == FAILURE) { return; } params[0] = &getThis(); if(zptr == NULL) printf("NULL...***\n"); params[1] = &zptr; //flags = (unsigned int) p_flags; //ZVAL_LONG(params[2], p_flags); object_init_ex(return_value, php_lmdb_txn_class_entry); fci.size = sizeof(fci); fci.function_table = php_lmdb_txn_class_entry; fci.object_ptr = return_value; fci.function_name = &z_fname; fci.retval_ptr_ptr = &return_value; fci.param_count = 2; fci.params = params; fci.no_separation = 1; fci.symbol_table = NULL; if(zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE){ //TODO: throw a new Exception printf("Error .... \n"); }else{ printf("OK! .... \n"); } //TODO : return the function's result or throw an exception if return non-zero. }
static int php_sqlite3_collation_callback(void *context, int string1_len, const void *string1, int string2_len, const void *string2) { int ret; zval zargs[2]; zval retval; struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context; collation->fc.fci.size = sizeof(collation->fc.fci); collation->fc.fci.function_table = EG(function_table); ZVAL_COPY_VALUE(&collation->fc.fci.function_name, &collation->callback); collation->fc.fci.symbol_table = NULL; collation->fc.fci.object = NULL; collation->fc.fci.retval = &retval; // Prepare the arguments. ZVAL_STRINGL(&zargs[0], (char *) string1, string1_len); ZVAL_STRINGL(&zargs[1], (char *) string2, string2_len); collation->fc.fci.param_count = 2; collation->fc.fci.params = zargs; if ((ret = zend_call_function(&collation->fc.fci, &collation->fc.fcc)) == FAILURE) { php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback"); } else if (!Z_ISUNDEF(retval)) { if (Z_TYPE(retval) != IS_LONG) { convert_to_long_ex(&retval); } ret = 0; if (Z_LVAL(retval) > 0) { ret = 1; } else if (Z_LVAL(retval) < 0) { ret = -1; } zval_ptr_dtor(&retval); } zval_ptr_dtor(&zargs[0]); zval_ptr_dtor(&zargs[1]); return ret; }
int yaf_loader_register(yaf_loader_t *loader) /* {{{ */ { zval autoload, function, method, ret; array_init(&autoload); ZVAL_STRING(&method, YAF_AUTOLOAD_FUNC_NAME); zend_hash_next_index_insert(Z_ARRVAL(autoload), loader); zend_hash_next_index_insert(Z_ARRVAL(autoload), &method); ZVAL_STRING(&function, YAF_SPL_AUTOLOAD_REGISTER_NAME); do { zend_fcall_info fci = { sizeof(fci), #if PHP_VERSION_ID < 70100 EG(function_table), #endif function, #if PHP_VERSION_ID < 70100 NULL, #endif &ret, &autoload, NULL, 1, 1 }; if (zend_call_function(&fci, NULL) == FAILURE) { zval_ptr_dtor(&function); zval_ptr_dtor(&autoload); php_error_docref(NULL, E_WARNING, "Unable to register autoload function %s", YAF_AUTOLOAD_FUNC_NAME); return 0; } zval_ptr_dtor(&function); zval_ptr_dtor(&autoload); } while (0); return 1; }
/* {{{ wingdi_window_construction_wrapper wraps around the constructor to make sure parent::__construct is always called */ static void wingdi_window_construction_wrapper(INTERNAL_FUNCTION_PARAMETERS) { zval *this = getThis(); wingdi_window_object *tobj; zend_class_entry *this_ce; zend_function *zf; zend_fcall_info fci = {0}; zend_fcall_info_cache fci_cache = {0}; zval *retval_ptr = NULL; unsigned i; tobj = zend_object_store_get_object(this TSRMLS_CC); zf = zend_get_std_object_handlers()->get_constructor(this TSRMLS_CC); this_ce = Z_OBJCE_P(this); fci.size = sizeof(fci); fci.function_table = &this_ce->function_table; fci.object_ptr = this; /* fci.function_name = ; not necessary to bother */ fci.retval_ptr_ptr = &retval_ptr; fci.param_count = ZEND_NUM_ARGS(); fci.params = emalloc(fci.param_count * sizeof *fci.params); /* Or use _zend_get_parameters_array_ex instead of loop: */ for (i = 0; i < fci.param_count; i++) { fci.params[i] = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (fci.param_count - i)); } fci.object_ptr = this; fci.no_separation = 0; fci_cache.initialized = 1; fci_cache.called_scope = EG(current_execute_data)->called_scope; fci_cache.calling_scope = EG(current_execute_data)->current_scope; fci_cache.function_handler = zf; fci_cache.object_ptr = this; zend_call_function(&fci, &fci_cache TSRMLS_CC); if (!EG(exception) && tobj->is_constructed == 0) zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "parent::__construct() must be called in %s::__construct()", this_ce->name); efree(fci.params); zval_ptr_dtor(&retval_ptr); }
PHP_APCU_API void apc_cache_entry(apc_cache_t *cache, zval *key, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_long ttl, zval *return_value) { apc_cache_entry_t *entry = NULL; if(!cache || apc_cache_busy(cache)) { return; } if (!key || Z_TYPE_P(key) != IS_STRING) { /* only strings, for now */ return; } #ifndef APC_LOCK_RECURSIVE if (APCG(recursion)++ == 0) { APC_LOCK(cache->header); } #else APC_LOCK(cache->header); #endif entry = apc_cache_find_internal( cache, Z_STR_P(key), ttl, 0); if (!entry) { int result = 0; fci->retval = return_value; zend_fcall_info_argn(fci, 1, key); zend_try { result = zend_call_function(fci, fcc); } zend_end_try (); if (result == SUCCESS) { zend_fcall_info_args_clear(fci, 1); if (!EG(exception)) { apc_cache_store_internal( cache, Z_STR_P(key), return_value, (uint32_t) ttl, 1); } } } else apc_cache_fetch_internal(cache, Z_STR_P(key), entry, ttl, &return_value);
static void oop_indirection_func(INTERNAL_FUNCTION_PARAMETERS) { indirection_function *ind = (indirection_function *) execute_data->func; zval *obj = &ind->obj; zval *params = safe_emalloc(sizeof(zval), ZEND_NUM_ARGS() + 1, 0); zval result; zend_class_entry *ce = ind->fn.scope; zend_fcall_info fci; zend_fcall_info_cache fcc; fci.size = sizeof(fci); fci.param_count = ZEND_NUM_ARGS() + 1; fci.params = params; fci.no_separation = 1; fcc.initialized = 1; fcc.calling_scope = ce; fcc.function_handler = ind->fbc; zend_get_parameters_array_ex(ZEND_NUM_ARGS(), ¶ms[1]); ZVAL_COPY_VALUE(¶ms[0], obj); ZVAL_STR(&fci.function_name, ind->fn.function_name); fci.retval = &result; fci.object = NULL; fcc.object = NULL; fcc.called_scope = ce; if (zend_call_function(&fci, &fcc TSRMLS_CC) == SUCCESS && !Z_ISUNDEF(result)) { ZVAL_COPY_VALUE(return_value, &result); } zval_ptr_dtor(obj); execute_data->func = NULL; zval_ptr_dtor(&fci.function_name); efree(params); efree(ind); }
/* {{{ xml_call_handler() */ static void xml_call_handler(xml_parser *parser, zval *handler, zend_function *function_ptr, int argc, zval *argv, zval *retval) { int i; ZVAL_UNDEF(retval); if (parser && handler && !EG(exception)) { int result; zend_fcall_info fci; fci.size = sizeof(fci); fci.function_table = EG(function_table); ZVAL_COPY_VALUE(&fci.function_name, handler); fci.symbol_table = NULL; fci.object = Z_OBJ(parser->object); fci.retval = retval; fci.param_count = argc; fci.params = argv; fci.no_separation = 0; /*fci.function_handler_cache = &function_ptr;*/ result = zend_call_function(&fci, NULL); if (result == FAILURE) { zval *method; zval *obj; if (Z_TYPE_P(handler) == IS_STRING) { php_error_docref(NULL, E_WARNING, "Unable to call handler %s()", Z_STRVAL_P(handler)); } else if ((obj = zend_hash_index_find(Z_ARRVAL_P(handler), 0)) != NULL && (method = zend_hash_index_find(Z_ARRVAL_P(handler), 1)) != NULL && Z_TYPE_P(obj) == IS_OBJECT && Z_TYPE_P(method) == IS_STRING) { php_error_docref(NULL, E_WARNING, "Unable to call handler %s::%s()", Z_OBJCE_P(obj)->name->val, Z_STRVAL_P(method)); } else php_error_docref(NULL, E_WARNING, "Unable to call handler"); } } for (i = 0; i < argc; i++) { zval_ptr_dtor(&argv[i]); } }
/* {{{ */ int pthreads_has_property(PTHREADS_HAS_PROPERTY_PASSTHRU_D) { int isset = 0; zend_long *guard = NULL; pthreads_object_t* threaded = PTHREADS_FETCH_FROM(Z_OBJ_P(object)); cache = NULL; if (Z_OBJCE_P(object)->__isset && (guard = pthreads_get_guard(&threaded->std, member)) && !((*guard) & IN_ISSET)) { zend_fcall_info fci = empty_fcall_info; zend_fcall_info_cache fcc = empty_fcall_info_cache; zval rv; ZVAL_UNDEF(&rv); fci.size = sizeof(zend_fcall_info); fci.retval = &rv; fci.object = &threaded->std; zend_fcall_info_argn(&fci, 1, member); fcc.initialized = 1; fcc.function_handler = Z_OBJCE_P(object)->__isset; fcc.object = &threaded->std; (*guard) |= IN_ISSET; zend_call_function(&fci, &fcc); (*guard) &= ~IN_ISSET; if (Z_TYPE(rv) != IS_UNDEF) { isset = zend_is_true(&rv); zval_dtor(&rv); } zend_fcall_info_args_clear(&fci, 1); } else { isset = pthreads_store_isset(object, member, has_set_exists); } return isset; }
ZEND_METHOD(myclass_ce, call_self){ zval *this,*ret = NULL; this = getThis(); zval *function_name; // //函数名 MAKE_STD_ZVAL(function_name); ZVAL_STRING(function_name, "public_method", 1); zend_fcall_info fci; // zend_fcall_info fci = { // sizeof(fci), // &Z_OBJCE_P(this)->function_table, // function_name, // NULL, // &ret, // 0, // NULL, // this, // 1 // }; fci.size =sizeof(fci); fci.function_table = &Z_OBJCE_P(this)->function_table; fci.function_name = function_name; fci.symbol_table = NULL; fci.retval_ptr_ptr = &ret; fci.param_count = 0; fci.params = NULL; fci.object_ptr = this; fci.no_separation =1; zend_call_function(&fci, NULL TSRMLS_CC); zval_dtor(function_name); efree(function_name); efree(ret); }
void call_user_watch_callback(int watch_index) { Watch *watch_ret; watch_ret = &FSEVENTS_GLOBAL(watches)[watch_index]; zval *retval = NULL; zval params[1]; zval *event_array; ZVAL_NEW_ARR(retval); ZVAL_NEW_ARR(event_array); array_init(event_array); params[0] = *event_array; watch_ret->fci.params = params; watch_ret->fci.param_count = 1; watch_ret->fci.retval = retval; watch_ret->fci.no_separation = 0; zend_call_function(&watch_ret->fci, NULL TSRMLS_CC); }
PHP_METHOD(Searcher,search) { char *str = NULL; int str_len,level; zval *cvalue, *self ,*retval_ptr,*arg1,*arg2,*arg3,*arg4; zval **params[4]; zend_fcall_info callback; zend_fcall_info_cache callback_cache; void* c = NULL; long ret = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|f", &str,&str_len, &level,&callback,&callback_cache, &callback.params, &callback.param_count) == FAILURE) { WRONG_PARAM_COUNT; } //if(Z_TYPE_P(rulefile_zval) != IS_NULL){} callback.retval_ptr_ptr = &retval_ptr; void callback_embed(unsigned char* s,int start,int end,int level){ MAKE_STD_ZVAL(arg1); ZVAL_STRING(arg1, s, strlen(s)); params[0] = &arg1; MAKE_STD_ZVAL(arg2); ZVAL_LONG(arg2, start); params[0] = &arg2; MAKE_STD_ZVAL(arg3); ZVAL_LONG(arg3, end); params[0] = &arg3; MAKE_STD_ZVAL(arg4); ZVAL_LONG(arg4,level); params[0] = &arg4; callback.params = params; zend_call_function(&callback, &callback_cache TSRMLS_CC); }
/* {{{ */ void pthreads_unset_property(PTHREADS_UNSET_PROPERTY_PASSTHRU_D) { zend_long *guard = NULL; pthreads_object_t* threaded = PTHREADS_FETCH_FROM(Z_OBJ_P(object)); cache = NULL; rebuild_object_properties(&threaded->std); if (Z_OBJCE_P(object)->__unset && (guard = pthreads_get_guard(&threaded->std, member)) && !((*guard) & IN_UNSET)) { zend_fcall_info fci = empty_fcall_info; zend_fcall_info_cache fcc = empty_fcall_info_cache; zval rv; ZVAL_UNDEF(&rv); fci.size = sizeof(zend_fcall_info); fci.retval = &rv; fci.object = &threaded->std; zend_fcall_info_argn(&fci, 1, member); fcc.initialized = 1; fcc.function_handler = Z_OBJCE_P(object)->__unset; fcc.object = &threaded->std; (*guard) |= IN_UNSET; zend_call_function(&fci, &fcc); (*guard) &= ~IN_UNSET; if (Z_TYPE(rv) != IS_UNDEF) { zval_dtor(&rv); } zend_fcall_info_args_clear(&fci, 1); } else { if (pthreads_store_delete(object, member) == SUCCESS){ } } }
static int ds_zval_user_compare_func(const void *a, const void *b) { zval params[2]; zval retval; zval *x = (zval*) a; zval *y = (zval*) b; ZVAL_COPY_VALUE(¶ms[0], x); ZVAL_COPY_VALUE(¶ms[1], y); DSG(user_compare_fci).param_count = 2; DSG(user_compare_fci).params = params; DSG(user_compare_fci).retval = &retval; if (zend_call_function( &DSG(user_compare_fci), &DSG(user_compare_fci_cache)) == SUCCESS) { return (int) zval_get_long(&retval); } return 0; }
int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { zend_class_entry *ce, **pce; TSRMLS_FETCH(); switch (Z_TYPE_P(tpl)) { case IS_STRING: if (zend_lookup_class( Z_STRVAL_P(tpl), Z_STRLEN_P(tpl), &pce TSRMLS_CC) != SUCCESS) { MSGPACK_ERROR("[msgpack] (%s) Class '%s' not found", __FUNCTION__, Z_STRVAL_P(tpl)); return FAILURE; } ce = *pce; break; case IS_OBJECT: ce = zend_get_class_entry(tpl TSRMLS_CC); break; default: MSGPACK_ERROR("[msgpack] (%s) object type is unsupported", __FUNCTION__); return FAILURE; } if (Z_TYPE_PP(value) == IS_OBJECT) { zend_class_entry *vce; vce = zend_get_class_entry(*value TSRMLS_CC); if (strcmp(ce->name, vce->name) == 0) { *return_value = **value; zval_copy_ctor(return_value); zval_ptr_dtor(value); return SUCCESS; } } object_init_ex(return_value, ce); /* Run the constructor if there is one */ if (ce->constructor && (ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC)) { zval *retval_ptr = NULL; zval ***params = NULL; int num_args = 0; zend_fcall_info fci; zend_fcall_info_cache fcc; #if ZEND_MODULE_API_NO >= 20090626 fci.size = sizeof(fci); fci.function_table = EG(function_table); fci.function_name = NULL; fci.symbol_table = NULL; fci.object_ptr = return_value; fci.retval_ptr_ptr = &retval_ptr; fci.param_count = num_args; fci.params = params; fci.no_separation = 1; fcc.initialized = 1; fcc.function_handler = ce->constructor; fcc.calling_scope = EG(scope); fcc.called_scope = Z_OBJCE_P(return_value); fcc.object_ptr = return_value; #else fci.size = sizeof(fci); fci.function_table = EG(function_table); fci.function_name = NULL; fci.symbol_table = NULL; fci.object_pp = &return_value; fci.retval_ptr_ptr = &retval_ptr; fci.param_count = num_args; fci.params = params; fci.no_separation = 1; fcc.initialized = 1; fcc.function_handler = ce->constructor; fcc.calling_scope = EG(scope); fcc.object_pp = &return_value; #endif if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) { if (params) { efree(params); } if (retval_ptr) { zval_ptr_dtor(&retval_ptr); } MSGPACK_WARNING( "[msgpack] (%s) Invocation of %s's constructor failed", __FUNCTION__, ce->name); return FAILURE; } if (retval_ptr) { zval_ptr_dtor(&retval_ptr); } if (params) { efree(params); } } switch (Z_TYPE_PP(value)) { case IS_ARRAY: { char *key; uint key_len; int key_type; ulong key_index; zval **data; HashPosition pos; HashTable *ht, *ret; HashTable *var = NULL; int num; ht = HASH_OF(*value); ret = HASH_OF(return_value); num = zend_hash_num_elements(ht); if (num <= 0) { zval_ptr_dtor(value); break; } /* string - php_only mode? */ if (ht->nNumOfElements != ht->nNextFreeElement || ht->nNumOfElements != ret->nNumOfElements) { HashTable *properties = NULL; HashPosition prop_pos; ALLOC_HASHTABLE(var); zend_hash_init(var, num, NULL, NULL, 0); zend_hash_internal_pointer_reset_ex(ht, &pos); for (;; zend_hash_move_forward_ex(ht, &pos)) { key_type = zend_hash_get_current_key_ex( ht, &key, &key_len, &key_index, 0, &pos); if (key_type == HASH_KEY_NON_EXISTANT) { break; } if (zend_hash_get_current_data_ex( ht, (void *)&data, &pos) != SUCCESS) { continue; } if (key_type == HASH_KEY_IS_STRING) { zval *val; MSGPACK_CONVERT_COPY_ZVAL(val, data); if (msgpack_convert_string_to_properties( return_value, key, key_len, val, var) != SUCCESS) { zval_ptr_dtor(&val); MSGPACK_WARNING( "[msgpack] (%s) " "illegal offset type, skip this decoding", __FUNCTION__); } } } /* index */ properties = Z_OBJ_HT_P(return_value)->get_properties( return_value TSRMLS_CC); if (HASH_OF(tpl)) { properties = HASH_OF(tpl); } zend_hash_internal_pointer_reset_ex(properties, &prop_pos); zend_hash_internal_pointer_reset_ex(ht, &pos); for (;; zend_hash_move_forward_ex(ht, &pos)) { key_type = zend_hash_get_current_key_ex( ht, &key, &key_len, &key_index, 0, &pos); if (key_type == HASH_KEY_NON_EXISTANT) { break; } if (zend_hash_get_current_data_ex( ht, (void *)&data, &pos) != SUCCESS) { continue; } switch (key_type) { case HASH_KEY_IS_LONG: { zval *val; MSGPACK_CONVERT_COPY_ZVAL(val, data); if (msgpack_convert_long_to_properties( ret, &properties, &prop_pos, key_index, val, var) != SUCCESS) { zval_ptr_dtor(&val); MSGPACK_WARNING( "[msgpack] (%s) " "illegal offset type, skip this decoding", __FUNCTION__); } break; } case HASH_KEY_IS_STRING: break; default: MSGPACK_WARNING( "[msgpack] (%s) key is not string nor array", __FUNCTION__); break; } } zend_hash_destroy(var); FREE_HASHTABLE(var); } else { HashPosition valpos; int (*convert_function)(zval *, zval *, zval **) = NULL; zval **arydata, *aryval; /* index */ zend_hash_internal_pointer_reset_ex(ret, &pos); zend_hash_internal_pointer_reset_ex(ht, &valpos); for (;; zend_hash_move_forward_ex(ret, &pos), zend_hash_move_forward_ex(ht, &valpos)) { key_type = zend_hash_get_current_key_ex( ret, &key, &key_len, &key_index, 0, &pos); if (key_type == HASH_KEY_NON_EXISTANT) { break; } if (zend_hash_get_current_data_ex( ret, (void *)&data, &pos) != SUCCESS) { continue; } switch (Z_TYPE_PP(data)) { case IS_ARRAY: convert_function = msgpack_convert_array; break; case IS_OBJECT: //case IS_STRING: -- may have default values of // class members, so it's not wise to allow convert_function = msgpack_convert_object; break; default: break; } if (zend_hash_get_current_data_ex( ht, (void *)&arydata, &valpos) != SUCCESS) { MSGPACK_WARNING( "[msgpack] (%s) can't get data value by index", __FUNCTION__); return FAILURE; } MSGPACK_CONVERT_COPY_ZVAL(aryval, arydata); if (convert_function) { zval *rv; ALLOC_INIT_ZVAL(rv); if (convert_function(rv, *data, &aryval) != SUCCESS) { zval_ptr_dtor(&aryval); MSGPACK_WARNING( "[msgpack] (%s) " "convert failure in convert_object", __FUNCTION__); return FAILURE; } zend_symtable_update( ret, key, key_len, &rv, sizeof(rv), NULL); } else { zend_symtable_update( ret, key, key_len, &aryval, sizeof(aryval), NULL); } } } zval_ptr_dtor(value); break; } default: { HashTable *properties = NULL; HashPosition prop_pos; properties = Z_OBJ_HT_P(return_value)->get_properties( return_value TSRMLS_CC); zend_hash_internal_pointer_reset_ex(properties, &prop_pos); if (msgpack_convert_long_to_properties( HASH_OF(return_value), &properties, &prop_pos, 0, *value, NULL) != SUCCESS) { MSGPACK_WARNING( "[msgpack] (%s) illegal offset type, skip this decoding", __FUNCTION__); } break; } } return SUCCESS; }
/* {{{ proto mixed Closure::call(object to [, mixed parameter] [, mixed ...] ) Call closure, binding to a given object with its class as the scope */ ZEND_METHOD(Closure, call) { zval *zclosure, *newthis, closure_result; zend_closure *closure; zend_fcall_info fci; zend_fcall_info_cache fci_cache; zend_function my_function; zend_object *newobj; fci.param_count = 0; fci.params = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS(), "o*", &newthis, &fci.params, &fci.param_count) == FAILURE) { return; } zclosure = getThis(); closure = (zend_closure *) Z_OBJ_P(zclosure); newobj = Z_OBJ_P(newthis); if (!zend_valid_closure_binding(closure, newthis, Z_OBJCE_P(newthis))) { return; } if (closure->func.common.fn_flags & ZEND_ACC_GENERATOR) { zval new_closure; zend_create_closure(&new_closure, &closure->func, Z_OBJCE_P(newthis), closure->called_scope, newthis); closure = (zend_closure *) Z_OBJ(new_closure); fci_cache.function_handler = &closure->func; } else { memcpy(&my_function, &closure->func, closure->func.type == ZEND_USER_FUNCTION ? sizeof(zend_op_array) : sizeof(zend_internal_function)); my_function.common.fn_flags &= ~ZEND_ACC_CLOSURE; /* use scope of passed object */ my_function.common.scope = Z_OBJCE_P(newthis); fci_cache.function_handler = &my_function; /* Runtime cache relies on bound scope to be immutable, hence we need a separate rt cache in case scope changed */ if (ZEND_USER_CODE(my_function.type) && closure->func.common.scope != Z_OBJCE_P(newthis)) { my_function.op_array.run_time_cache = emalloc(my_function.op_array.cache_size); memset(my_function.op_array.run_time_cache, 0, my_function.op_array.cache_size); } } fci_cache.called_scope = newobj->ce; fci_cache.object = fci.object = newobj; fci.size = sizeof(fci); ZVAL_COPY_VALUE(&fci.function_name, zclosure); fci.retval = &closure_result; fci.no_separation = 1; if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(closure_result) != IS_UNDEF) { if (Z_ISREF(closure_result)) { zend_unwrap_reference(&closure_result); } ZVAL_COPY_VALUE(return_value, &closure_result); } if (fci_cache.function_handler->common.fn_flags & ZEND_ACC_GENERATOR) { /* copied upon generator creation */ GC_DELREF(&closure->std); } else if (ZEND_USER_CODE(my_function.type) && closure->func.common.scope != Z_OBJCE_P(newthis)) { efree(my_function.op_array.run_time_cache); } }
static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int type) /* {{{ */ { xsltTransformContextPtr tctxt; zval *args; zval retval; int result, i; int error = 0; zend_fcall_info fci; zval handler; xmlXPathObjectPtr obj; char *str; xsl_object *intern; zend_string *callable = NULL; if (! zend_is_executing()) { xsltGenericError(xsltGenericErrorContext, "xsltExtFunctionTest: Function called from outside of PHP\n"); error = 1; } else { tctxt = xsltXPathGetTransformContext(ctxt); if (tctxt == NULL) { xsltGenericError(xsltGenericErrorContext, "xsltExtFunctionTest: failed to get the transformation context\n"); error = 1; } else { intern = (xsl_object*)tctxt->_private; if (intern == NULL) { xsltGenericError(xsltGenericErrorContext, "xsltExtFunctionTest: failed to get the internal object\n"); error = 1; } else if (intern->registerPhpFunctions == 0) { xsltGenericError(xsltGenericErrorContext, "xsltExtFunctionTest: PHP Object did not register PHP functions\n"); error = 1; } } } if (error == 1) { for (i = nargs - 1; i >= 0; i--) { obj = valuePop(ctxt); xmlXPathFreeObject(obj); } return; } fci.param_count = nargs - 1; if (fci.param_count > 0) { args = safe_emalloc(fci.param_count, sizeof(zval), 0); } /* Reverse order to pop values off ctxt stack */ for (i = nargs - 2; i >= 0; i--) { obj = valuePop(ctxt); switch (obj->type) { case XPATH_STRING: ZVAL_STRING(&args[i], (char *)obj->stringval); break; case XPATH_BOOLEAN: ZVAL_BOOL(&args[i], obj->boolval); break; case XPATH_NUMBER: ZVAL_DOUBLE(&args[i], obj->floatval); break; case XPATH_NODESET: if (type == 1) { str = (char*)xmlXPathCastToString(obj); ZVAL_STRING(&args[i], str); xmlFree(str); } else if (type == 2) { int j; dom_object *domintern = (dom_object *)intern->doc; array_init(&args[i]); if (obj->nodesetval && obj->nodesetval->nodeNr > 0) { for (j = 0; j < obj->nodesetval->nodeNr; j++) { xmlNodePtr node = obj->nodesetval->nodeTab[j]; zval child; /* not sure, if we need this... it's copied from xpath.c */ if (node->type == XML_NAMESPACE_DECL) { xmlNsPtr curns; xmlNodePtr nsparent; nsparent = node->_private; curns = xmlNewNs(NULL, node->name, NULL); if (node->children) { curns->prefix = xmlStrdup((char *)node->children); } if (node->children) { node = xmlNewDocNode(node->doc, NULL, (char *) node->children, node->name); } else { node = xmlNewDocNode(node->doc, NULL, (const xmlChar *) "xmlns", node->name); } node->type = XML_NAMESPACE_DECL; node->parent = nsparent; node->ns = curns; } else { node = xmlDocCopyNodeList(domintern->document->ptr, node); } php_dom_create_object(node, &child, domintern); add_next_index_zval(&args[i], &child); } } } break; default: str = (char *) xmlXPathCastToString(obj); ZVAL_STRING(&args[i], str); xmlFree(str); } xmlXPathFreeObject(obj); } fci.size = sizeof(fci); fci.function_table = EG(function_table); if (fci.param_count > 0) { fci.params = args; } else { fci.params = NULL; } obj = valuePop(ctxt); if (obj->stringval == NULL) { php_error_docref(NULL, E_WARNING, "Handler name must be a string"); xmlXPathFreeObject(obj); valuePush(ctxt, xmlXPathNewString((const xmlChar *) "")); if (fci.param_count > 0) { for (i = 0; i < nargs - 1; i++) { zval_ptr_dtor(&args[i]); } efree(args); } return; } ZVAL_STRING(&handler, (char *) obj->stringval); xmlXPathFreeObject(obj); ZVAL_COPY_VALUE(&fci.function_name, &handler); fci.symbol_table = NULL; fci.object = NULL; fci.retval = &retval; fci.no_separation = 0; /*fci.function_handler_cache = &function_ptr;*/ if (!zend_make_callable(&handler, &callable)) { php_error_docref(NULL, E_WARNING, "Unable to call handler %s()", ZSTR_VAL(callable)); valuePush(ctxt, xmlXPathNewString((const xmlChar *) "")); } else if ( intern->registerPhpFunctions == 2 && zend_hash_exists(intern->registered_phpfunctions, callable) == 0) { php_error_docref(NULL, E_WARNING, "Not allowed to call handler '%s()'", ZSTR_VAL(callable)); /* Push an empty string, so that we at least have an xslt result... */ valuePush(ctxt, xmlXPathNewString((const xmlChar *) "")); } else { result = zend_call_function(&fci, NULL); if (result == FAILURE) { if (Z_TYPE(handler) == IS_STRING) { php_error_docref(NULL, E_WARNING, "Unable to call handler %s()", Z_STRVAL(handler)); valuePush(ctxt, xmlXPathNewString((const xmlChar *) "")); } /* retval is == NULL, when an exception occurred, don't report anything, because PHP itself will handle that */ } else if (Z_ISUNDEF(retval)) { } else { if (Z_TYPE(retval) == IS_OBJECT && instanceof_function(Z_OBJCE(retval), dom_node_class_entry)) { xmlNode *nodep; dom_object *obj; if (intern->node_list == NULL) { ALLOC_HASHTABLE(intern->node_list); zend_hash_init(intern->node_list, 0, NULL, ZVAL_PTR_DTOR, 0); } Z_ADDREF(retval); zend_hash_next_index_insert(intern->node_list, &retval); obj = Z_DOMOBJ_P(&retval); nodep = dom_object_get_node(obj); valuePush(ctxt, xmlXPathNewNodeSet(nodep)); } else if (Z_TYPE(retval) == IS_TRUE || Z_TYPE(retval) == IS_FALSE) { valuePush(ctxt, xmlXPathNewBoolean(Z_LVAL(retval))); } else if (Z_TYPE(retval) == IS_OBJECT) { php_error_docref(NULL, E_WARNING, "A PHP Object cannot be converted to a XPath-string"); valuePush(ctxt, xmlXPathNewString((const xmlChar *) "")); } else { convert_to_string_ex(&retval); valuePush(ctxt, xmlXPathNewString((xmlChar *) Z_STRVAL(retval))); } zval_ptr_dtor(&retval); } } zend_string_release(callable); zval_ptr_dtor(&handler); if (fci.param_count > 0) { for (i = 0; i < nargs - 1; i++) { zval_ptr_dtor(&args[i]); } efree(args); } }
/* {{{ proto mixed Closure::call(object to [, mixed parameter] [, mixed ...] ) Call closure, binding to a given object with its class as the scope */ ZEND_METHOD(Closure, call) { zval *zclosure, *newthis, closure_result; zend_closure *closure; zend_fcall_info fci; zend_fcall_info_cache fci_cache; zval *my_params; int my_param_count = 0; zend_function my_function; zend_object *newobj; if (zend_parse_parameters(ZEND_NUM_ARGS(), "o*", &newthis, &my_params, &my_param_count) == FAILURE) { return; } zclosure = getThis(); closure = (zend_closure *) Z_OBJ_P(zclosure); newobj = Z_OBJ_P(newthis); if (!zend_valid_closure_binding(closure, newthis, Z_OBJCE_P(newthis))) { return; } /* This should never happen as closures will always be callable */ if (zend_fcall_info_init(zclosure, 0, &fci, &fci_cache, NULL, NULL) != SUCCESS) { ZEND_ASSERT(0); } fci.retval = &closure_result; fci.params = my_params; fci.param_count = my_param_count; fci.object = fci_cache.object = newobj; fci_cache.initialized = 1; fci_cache.called_scope = Z_OBJCE_P(newthis); if (fci_cache.function_handler->common.fn_flags & ZEND_ACC_GENERATOR) { zval new_closure; zend_create_closure(&new_closure, fci_cache.function_handler, Z_OBJCE_P(newthis), closure->called_scope, newthis); closure = (zend_closure *) Z_OBJ(new_closure); fci_cache.function_handler = &closure->func; } else { memcpy(&my_function, fci_cache.function_handler, fci_cache.function_handler->type == ZEND_USER_FUNCTION ? sizeof(zend_op_array) : sizeof(zend_internal_function)); /* use scope of passed object */ my_function.common.scope = Z_OBJCE_P(newthis); fci_cache.function_handler = &my_function; /* Runtime cache relies on bound scope to be immutable, hence we need a separate rt cache in case scope changed */ if (ZEND_USER_CODE(my_function.type) && closure->func.common.scope != Z_OBJCE_P(newthis)) { my_function.op_array.run_time_cache = emalloc(my_function.op_array.cache_size); memset(my_function.op_array.run_time_cache, 0, my_function.op_array.cache_size); } } if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(closure_result) != IS_UNDEF) { ZVAL_COPY_VALUE(return_value, &closure_result); } if (fci_cache.function_handler->common.fn_flags & ZEND_ACC_GENERATOR) { /* copied upon generator creation */ --GC_REFCOUNT(&closure->std); } else if (ZEND_USER_CODE(my_function.type) && closure->func.common.scope != Z_OBJCE_P(newthis)) { efree(my_function.op_array.run_time_cache); } }
static void dom_xpath_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int type) /* {{{ */ { zval retval; int result, i; int error = 0; zend_fcall_info fci; xmlXPathObjectPtr obj; char *str; zend_string *callable = NULL; dom_xpath_object *intern; if (! zend_is_executing()) { xmlGenericError(xmlGenericErrorContext, "xmlExtFunctionTest: Function called from outside of PHP\n"); error = 1; } else { intern = (dom_xpath_object *) ctxt->context->userData; if (intern == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlExtFunctionTest: failed to get the internal object\n"); error = 1; } else if (intern->registerPhpFunctions == 0) { xmlGenericError(xmlGenericErrorContext, "xmlExtFunctionTest: PHP Object did not register PHP functions\n"); error = 1; } } if (error == 1) { for (i = nargs - 1; i >= 0; i--) { obj = valuePop(ctxt); xmlXPathFreeObject(obj); } return; } fci.param_count = nargs - 1; if (fci.param_count > 0) { fci.params = safe_emalloc(fci.param_count, sizeof(zval), 0); } /* Reverse order to pop values off ctxt stack */ for (i = nargs - 2; i >= 0; i--) { obj = valuePop(ctxt); switch (obj->type) { case XPATH_STRING: ZVAL_STRING(&fci.params[i], (char *)obj->stringval); break; case XPATH_BOOLEAN: ZVAL_BOOL(&fci.params[i], obj->boolval); break; case XPATH_NUMBER: ZVAL_DOUBLE(&fci.params[i], obj->floatval); break; case XPATH_NODESET: if (type == 1) { str = (char *)xmlXPathCastToString(obj); ZVAL_STRING(&fci.params[i], str); xmlFree(str); } else if (type == 2) { int j; array_init(&fci.params[i]); if (obj->nodesetval && obj->nodesetval->nodeNr > 0) { for (j = 0; j < obj->nodesetval->nodeNr; j++) { xmlNodePtr node = obj->nodesetval->nodeTab[j]; zval child; /* not sure, if we need this... it's copied from xpath.c */ if (node->type == XML_NAMESPACE_DECL) { xmlNsPtr curns; xmlNodePtr nsparent; nsparent = node->_private; curns = xmlNewNs(NULL, node->name, NULL); if (node->children) { curns->prefix = xmlStrdup((xmlChar *) node->children); } if (node->children) { node = xmlNewDocNode(node->doc, NULL, (xmlChar *) node->children, node->name); } else { node = xmlNewDocNode(node->doc, NULL, (xmlChar *) "xmlns", node->name); } node->type = XML_NAMESPACE_DECL; node->parent = nsparent; node->ns = curns; } php_dom_create_object(node, &child, &intern->dom); add_next_index_zval(&fci.params[i], &child); } } } break; default: ZVAL_STRING(&fci.params[i], (char *)xmlXPathCastToString(obj)); } xmlXPathFreeObject(obj); } fci.size = sizeof(fci); fci.function_table = EG(function_table); obj = valuePop(ctxt); if (obj->stringval == NULL) { php_error_docref(NULL, E_WARNING, "Handler name must be a string"); xmlXPathFreeObject(obj); if (fci.param_count > 0) { for (i = 0; i < nargs - 1; i++) { zval_ptr_dtor(&fci.params[i]); } efree(fci.params); } return; } ZVAL_STRING(&fci.function_name, (char *) obj->stringval); xmlXPathFreeObject(obj); fci.symbol_table = NULL; fci.object = NULL; fci.retval = &retval; fci.no_separation = 0; if (!zend_make_callable(&fci.function_name, &callable)) { php_error_docref(NULL, E_WARNING, "Unable to call handler %s()", callable->val); } else if (intern->registerPhpFunctions == 2 && zend_hash_exists(intern->registered_phpfunctions, callable) == 0) { php_error_docref(NULL, E_WARNING, "Not allowed to call handler '%s()'.", callable->val); /* Push an empty string, so that we at least have an xslt result... */ valuePush(ctxt, xmlXPathNewString((xmlChar *)"")); } else { result = zend_call_function(&fci, NULL); if (result == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { if (Z_TYPE(retval) == IS_OBJECT && instanceof_function(Z_OBJCE(retval), dom_node_class_entry)) { xmlNode *nodep; dom_object *obj; if (intern->node_list == NULL) { ALLOC_HASHTABLE(intern->node_list); zend_hash_init(intern->node_list, 0, NULL, ZVAL_PTR_DTOR, 0); } GC_REFCOUNT(&retval)++; zend_hash_next_index_insert(intern->node_list, &retval); obj = Z_DOMOBJ_P(&retval); nodep = dom_object_get_node(obj); valuePush(ctxt, xmlXPathNewNodeSet(nodep)); } else if (Z_TYPE(retval) == IS_FALSE || Z_TYPE(retval) == IS_TRUE) { valuePush(ctxt, xmlXPathNewBoolean(Z_TYPE(retval) == IS_TRUE)); } else if (Z_TYPE(retval) == IS_OBJECT) { php_error_docref(NULL, E_WARNING, "A PHP Object cannot be converted to a XPath-string"); valuePush(ctxt, xmlXPathNewString((xmlChar *)"")); } else { zend_string *str = zval_get_string(&retval); valuePush(ctxt, xmlXPathNewString((xmlChar *) str->val)); zend_string_release(str); } zval_ptr_dtor(&retval); } } zend_string_release(callable); zval_dtor(&fci.function_name); if (fci.param_count > 0) { for (i = 0; i < nargs - 1; i++) { zval_ptr_dtor(&fci.params[i]); } efree(fci.params); } }
/* {{{ zend_call_method Only returns the returned zval if retval_ptr != NULL */ ZEND_API zval* zend_call_method(zval *object, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, size_t function_name_len, zval *retval_ptr, int param_count, zval* arg1, zval* arg2) { int result; zend_fcall_info fci; zval retval; HashTable *function_table; zval params[2]; if (param_count > 0) { ZVAL_COPY_VALUE(¶ms[0], arg1); } if (param_count > 1) { ZVAL_COPY_VALUE(¶ms[1], arg2); } fci.size = sizeof(fci); /*fci.function_table = NULL; will be read form zend_class_entry of object if needed */ fci.object = (object && Z_TYPE_P(object) == IS_OBJECT) ? Z_OBJ_P(object) : NULL; ZVAL_STRINGL(&fci.function_name, function_name, function_name_len); fci.retval = retval_ptr ? retval_ptr : &retval; fci.param_count = param_count; fci.params = params; fci.no_separation = 1; fci.symbol_table = NULL; if (!fn_proxy && !obj_ce) { /* no interest in caching and no information already present that is * needed later inside zend_call_function. */ fci.function_table = !object ? EG(function_table) : NULL; result = zend_call_function(&fci, NULL); zval_ptr_dtor(&fci.function_name); } else { zend_fcall_info_cache fcic; fcic.initialized = 1; if (!obj_ce) { obj_ce = object ? Z_OBJCE_P(object) : NULL; } if (obj_ce) { function_table = &obj_ce->function_table; } else { function_table = EG(function_table); } if (!fn_proxy || !*fn_proxy) { if ((fcic.function_handler = zend_hash_find_ptr(function_table, Z_STR(fci.function_name))) == NULL) { /* error at c-level */ zend_error_noreturn(E_CORE_ERROR, "Couldn't find implementation for method %s%s%s", obj_ce ? obj_ce->name->val : "", obj_ce ? "::" : "", function_name); } if (fn_proxy) { *fn_proxy = fcic.function_handler; } } else { fcic.function_handler = *fn_proxy; } fcic.calling_scope = obj_ce; if (object) { fcic.called_scope = Z_OBJCE_P(object); } else { zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data)); if (obj_ce && (!called_scope || !instanceof_function(called_scope, obj_ce))) { fcic.called_scope = obj_ce; } else { fcic.called_scope = called_scope; } } fcic.object = object ? Z_OBJ_P(object) : NULL; result = zend_call_function(&fci, &fcic); zval_ptr_dtor(&fci.function_name); } if (result == FAILURE) { /* error at c-level */ if (!obj_ce) { obj_ce = object ? Z_OBJCE_P(object) : NULL; } if (!EG(exception)) { zend_error_noreturn(E_CORE_ERROR, "Couldn't execute method %s%s%s", obj_ce ? obj_ce->name->val : "", obj_ce ? "::" : "", function_name); } } /* copy arguments back, they might be changed by references */ if (param_count > 0 && Z_ISREF(params[0]) && !Z_ISREF_P(arg1)) { ZVAL_COPY_VALUE(arg1, ¶ms[0]); } if (param_count > 1 && Z_ISREF(params[1]) && !Z_ISREF_P(arg2)) { ZVAL_COPY_VALUE(arg2, ¶ms[1]); } if (!retval_ptr) { zval_ptr_dtor(&retval); return NULL; } return retval_ptr; }