diff options
author | Zeev Suraski <zeev@php.net> | 1999-12-19 18:54:40 +0000 |
---|---|---|
committer | Zeev Suraski <zeev@php.net> | 1999-12-19 18:54:40 +0000 |
commit | 223c674c2a6f014e013c2ff0737febd22b19f96d (patch) | |
tree | e3ad2d9f0ec5d70a529eafc52b73415f61d29ce9 | |
parent | 99472238003e87d7d1d0b0513cb571b543753217 (diff) | |
download | php-git-223c674c2a6f014e013c2ff0737febd22b19f96d.tar.gz |
- Made things work again (Thies, everybody - please check the latest CVS and see if you're
still getting any problems)
- Changed the interface of call_user_function_ex() to support returning of references
-rw-r--r-- | Zend/zend.h | 14 | ||||
-rw-r--r-- | Zend/zend_API.h | 4 | ||||
-rw-r--r-- | Zend/zend_compile.c | 2 | ||||
-rw-r--r-- | Zend/zend_execute.c | 65 | ||||
-rw-r--r-- | Zend/zend_execute.h | 2 | ||||
-rw-r--r-- | Zend/zend_execute_API.c | 76 | ||||
-rw-r--r-- | Zend/zend_globals.h | 6 |
7 files changed, 99 insertions, 70 deletions
diff --git a/Zend/zend.h b/Zend/zend.h index 8533a2d5c1..0f41887a58 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -276,6 +276,10 @@ END_EXTERN_C() #define INIT_ZVAL(z) z = zval_used_for_init; +#define ALLOC_INIT_ZVAL(zp) \ + (zp) = (zval *) emalloc(sizeof(zval)); \ + INIT_ZVAL(*zp); + #define MAKE_STD_ZVAL(zv) \ zv = (zval *) emalloc(sizeof(zval)); \ INIT_PZVAL(zv); @@ -290,10 +294,18 @@ END_EXTERN_C() **(ppzv) = *orig_ptr; \ zval_copy_ctor(*(ppzv)); \ (*(ppzv))->refcount=1; \ - (*(ppzv))->is_ref = 0; \ + (*(ppzv))->is_ref = 0; \ } \ } +#define COPY_PZVAL_TO_ZVAL(zv, pzv) \ + (zv) = *(pzv); \ + if ((pzv)->refcount>1) { \ + zval_copy_ctor(&(zv)); \ + (pzv)->refcount--; \ + } \ + INIT_PZVAL(&(zv)); + #define ZEND_MAX_RESERVED_RESOURCES 1 #endif /* _ZEND_H */ diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 3c475d0b67..886da00de8 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -124,8 +124,8 @@ ZEND_API int add_get_assoc_stringl(zval *arg, char *key, char *str, uint length, ZEND_API int add_get_index_string(zval *arg, uint idx, char *str, void **dest, int duplicate); ZEND_API int add_get_index_stringl(zval *arg, uint idx, char *str, uint length, void **dest, int duplicate); -ZEND_API int call_user_function(HashTable *function_table, zval *object, zval *function_name, zval *retval, int param_count, zval *params[]); -ZEND_API int call_user_function_ex(HashTable *function_table, zval *object, zval *function_name, zval *retval, int param_count, zval **params[], int no_separation); +ZEND_API int call_user_function(HashTable *function_table, zval *object, zval *function_name, zval *retval_ptr, int param_count, zval *params[]); +ZEND_API int call_user_function_ex(HashTable *function_table, zval *object, zval *function_name, zval **retval_ptr_ptr, int param_count, zval **params[], int no_separation); ZEND_API int add_property_long(zval *arg, char *key, long l); ZEND_API int add_property_resource(zval *arg, char *key, long r); diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 5f16d23580..45410dae02 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1854,7 +1854,7 @@ void do_include_or_eval(int type, znode *result, znode *op1 CLS_DC) zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); opline->opcode = ZEND_INCLUDE_OR_EVAL; - opline->result.op_type = IS_TMP_VAR; + opline->result.op_type = IS_VAR; opline->result.u.var = get_temporary_variable(CG(active_op_array)); opline->op1 = *op1; SET_UNUSED(opline->op2); diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index c20d9fe98b..1cea3fed48 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1473,26 +1473,28 @@ overloaded_function_call_cont: do_fcall_common: { zval **original_return_value; - int return_value_not_used = (opline->result.u.EA.type & EXT_TYPE_UNUSED); - + int return_value_used = !(opline->result.u.EA.type & EXT_TYPE_UNUSED); zend_ptr_stack_push(&EG(argument_stack), (void *) opline->extended_value); + Ts[opline->result.u.var].var.ptr_ptr = &Ts[opline->result.u.var].var.ptr; - /* The emalloc() could be optimized out for call user function but it - creates a problem with include() */ - Ts[opline->result.u.var].var.ptr = (zval *)emalloc(sizeof(zval)); - INIT_ZVAL(*(Ts[opline->result.u.var].var.ptr)); if (function_state.function->type==ZEND_INTERNAL_FUNCTION) { - ((zend_internal_function *) function_state.function)->handler(opline->extended_value, Ts[opline->result.u.var].var.ptr, &EG(regular_list), &EG(persistent_list), object.ptr, !return_value_not_used); + Ts[opline->result.u.var].var.ptr = (zval *)emalloc(sizeof(zval)); + INIT_ZVAL(*(Ts[opline->result.u.var].var.ptr)); + ((zend_internal_function *) function_state.function)->handler(opline->extended_value, Ts[opline->result.u.var].var.ptr, &EG(regular_list), &EG(persistent_list), object.ptr, return_value_used); if (object.ptr) { object.ptr->refcount--; } Ts[opline->result.u.var].var.ptr->is_ref = 0; Ts[opline->result.u.var].var.ptr->refcount = 1; + if (!return_value_used) { + zval_ptr_dtor(&Ts[opline->result.u.var].var.ptr); + } } else if (function_state.function->type==ZEND_USER_FUNCTION) { HashTable *calling_symbol_table; + Ts[opline->result.u.var].var.ptr = NULL; if (EG(symtable_cache_ptr)>=EG(symtable_cache)) { /*printf("Cache hit! Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/ function_state.function_symbol_table = *(EG(symtable_cache_ptr)--); @@ -1518,7 +1520,15 @@ do_fcall_common: original_return_value = EG(return_value_ptr_ptr); EG(return_value_ptr_ptr) = Ts[opline->result.u.var].var.ptr_ptr; EG(active_op_array) = (zend_op_array *) function_state.function; + zend_execute(EG(active_op_array) ELS_CC); + + if (return_value_used && !Ts[opline->result.u.var].var.ptr) { + Ts[opline->result.u.var].var.ptr = (zval *) emalloc(sizeof(zval)); + INIT_ZVAL(*Ts[opline->result.u.var].var.ptr); + } else if (!return_value_used && Ts[opline->result.u.var].var.ptr) { + zval_ptr_dtor(&Ts[opline->result.u.var].var.ptr); + } EG(opline_ptr) = &opline; EG(active_op_array) = op_array; EG(return_value_ptr_ptr)=original_return_value; @@ -1531,11 +1541,13 @@ do_fcall_common: } EG(active_symbol_table) = calling_symbol_table; } else { /* ZEND_OVERLOADED_FUNCTION */ + Ts[opline->result.u.var].var.ptr = (zval *)emalloc(sizeof(zval)); + INIT_ZVAL(*(Ts[opline->result.u.var].var.ptr)); call_overloaded_function(opline->extended_value, Ts[opline->result.u.var].var.ptr, &EG(regular_list), &EG(persistent_list) ELS_CC); efree(fbc); - } - if (return_value_not_used) { - zval_ptr_dtor(&Ts[opline->result.u.var].var.ptr); + if (!return_value_used) { + zval_ptr_dtor(&Ts[opline->result.u.var].var.ptr); + } } object.ptr = zend_ptr_stack_pop(&EG(arg_types_stack)); if (opline->opcode == ZEND_DO_FCALL_BY_NAME) { @@ -1561,25 +1573,23 @@ do_fcall_common: (*retval_ptr_ptr)->is_ref = 1; } (*retval_ptr_ptr)->refcount++; - efree(*EG(return_value_ptr_ptr)); (*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr); } else { retval_ptr = get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R); if (!EG(free_op1)) { /* Not a temp var */ if (PZVAL_IS_REF(retval_ptr) && retval_ptr->refcount > 0) { - /**(EG(return_value_ptr_ptr)) = (zval *)emalloc(sizeof(zval));*/ + *(EG(return_value_ptr_ptr)) = (zval *)emalloc(sizeof(zval)); **EG(return_value_ptr_ptr) = *retval_ptr; (*EG(return_value_ptr_ptr))->is_ref = 0; (*EG(return_value_ptr_ptr))->refcount = 1; zval_copy_ctor(*EG(return_value_ptr_ptr)); } else { - efree(*EG(return_value_ptr_ptr)); *EG(return_value_ptr_ptr) = retval_ptr; retval_ptr->refcount++; } } else { - /**(EG(return_value_ptr_ptr))= (zval *)emalloc(sizeof(zval));*/ + *(EG(return_value_ptr_ptr))= (zval *)emalloc(sizeof(zval)); **EG(return_value_ptr_ptr) = *retval_ptr; (*EG(return_value_ptr_ptr))->refcount = 1; (*EG(return_value_ptr_ptr))->is_ref = 0; @@ -1940,26 +1950,20 @@ send_by_ref: break; } FREE_OP(&opline->op1, EG(free_op1)); - + Ts[opline->result.u.var].var.ptr = NULL; + Ts[opline->result.u.var].var.ptr_ptr = &Ts[opline->result.u.var].var.ptr; if (new_op_array) { - zval *return_value_ptr; - /*Ts[opline->result.u.var].tmp_var.value.lval = 1; - Ts[opline->result.u.var].tmp_var.type = IS_LONG; - EG(return_value) = &Ts[opline->result.u.var].tmp_var; - */ - return_value_ptr = emalloc(sizeof(zval)); - - INIT_PZVAL(return_value_ptr); - return_value_ptr->value.lval = 1; - return_value_ptr->type = IS_LONG; - EG(return_value_ptr_ptr) = &return_value_ptr; + EG(return_value_ptr_ptr) = Ts[opline->result.u.var].var.ptr_ptr; EG(active_op_array) = new_op_array; zend_execute(new_op_array ELS_CC); - Ts[opline->result.u.var].tmp_var = *return_value_ptr; - zval_copy_ctor(&Ts[opline->result.u.var].tmp_var); - zval_ptr_dtor(&return_value_ptr); + if (!Ts[opline->result.u.var].var.ptr) { /* there was no return statement */ + Ts[opline->result.u.var].var.ptr = (zval *) emalloc(sizeof(zval)); + INIT_PZVAL(Ts[opline->result.u.var].var.ptr); + Ts[opline->result.u.var].var.ptr->value.lval = 1; + Ts[opline->result.u.var].var.ptr->type = IS_LONG; + } EG(opline_ptr) = &opline; EG(active_op_array) = op_array; @@ -1967,7 +1971,8 @@ send_by_ref: destroy_op_array(new_op_array); efree(new_op_array); } else { - INIT_ZVAL(Ts[opline->result.u.var].tmp_var); + Ts[opline->result.u.var].var.ptr = (zval *) emalloc(sizeof(zval)); + INIT_ZVAL(*Ts[opline->result.u.var].var.ptr); } EG(return_value_ptr_ptr) = original_return_value; } diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 4075588703..0eb61c0771 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -47,7 +47,7 @@ void shutdown_executor(ELS_D); void execute(zend_op_array *op_array ELS_DC); ZEND_API int zend_is_true(zval *op); ZEND_API inline void safe_free_zval_ptr(zval *p); -ZEND_API void zend_eval_string(char *str, zval *retval CLS_DC ELS_DC); +ZEND_API void zend_eval_string(char *str, zval *retval_ptr CLS_DC ELS_DC); ZEND_API inline int i_zend_is_true(zval *op); ZEND_API int zval_update_constant(zval **pp); ZEND_API inline void zend_assign_to_variable_reference(znode *result, zval **variable_ptr_ptr, zval **value_ptr_ptr, temp_variable *Ts ELS_DC); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 938b11e235..6325b57f2d 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -88,19 +88,12 @@ void init_executor(CLS_D ELS_DC) zend_ptr_stack_init(&EG(arg_types_stack)); zend_stack_init(&EG(overloaded_objects_stack)); /* destroys stack frame, therefore makes core dumps worthless */ -#if 0 -#if ZEND_DEBUG +#if 0&&ZEND_DEBUG original_sigsegv_handler = signal(SIGSEGV, zend_handle_sigsegv); #endif -#endif - /* - EG(return_value) = &EG(global_return_value); - var_reset(EG(return_value)); - */ - EG(return_value_ptr_ptr) = &EG(global_return_value); - EG(global_return_value) = emalloc(sizeof(zval)); - INIT_PZVAL(EG(global_return_value)); - var_reset(EG(global_return_value)); + EG(return_value_ptr_ptr) = &EG(global_return_value_ptr); + EG(global_return_value_ptr) = &EG(global_return_value); + INIT_ZVAL(EG(global_return_value)); EG(symtable_cache_ptr) = EG(symtable_cache)-1; EG(symtable_cache_limit)=EG(symtable_cache)+SYMTABLE_CACHE_SIZE-1; @@ -126,8 +119,7 @@ void init_executor(CLS_D ELS_DC) void shutdown_executor(ELS_D) { - zval_ptr_dtor(&EG(global_return_value)); - /*zval_dtor(&EG(global_return_value));*/ + zval_dtor(&EG(global_return_value)); zend_ptr_stack_destroy(&EG(arg_types_stack)); zend_stack_destroy(&EG(overloaded_objects_stack)); @@ -295,25 +287,31 @@ ZEND_API int zval_update_constant(zval **pp) } -int call_user_function(HashTable *function_table, zval *object, zval *function_name, zval *retval, int param_count, zval *params[]) +int call_user_function(HashTable *function_table, zval *object, zval *function_name, zval *retval_ptr, int param_count, zval *params[]) { zval ***params_array = (zval ***) emalloc(sizeof(zval **)*param_count); int i; int ex_retval; + zval *local_retval_ptr; for (i=0; i<param_count; i++) { params_array[i] = ¶ms[i]; } - ex_retval = call_user_function_ex(function_table, object, function_name, retval, param_count, params_array, 1); + ex_retval = call_user_function_ex(function_table, object, function_name, &local_retval_ptr, param_count, params_array, 1); + if (local_retval_ptr) { + COPY_PZVAL_TO_ZVAL(*retval_ptr, local_retval_ptr); + } else { + INIT_ZVAL(*retval_ptr); + } efree(params_array); return ex_retval; } -int call_user_function_ex(HashTable *function_table, zval *object, zval *function_name, zval *retval, int param_count, zval **params[], int no_separation) +int call_user_function_ex(HashTable *function_table, zval *object, zval *function_name, zval **retval_ptr_ptr, int param_count, zval **params[], int no_separation) { int i; - zval *original_return_value; + zval **original_return_value; HashTable *calling_symbol_table; zend_function_state function_state; zend_function_state *original_function_state_ptr; @@ -369,7 +367,7 @@ int call_user_function_ex(HashTable *function_table, zval *object, zval *functio zend_ptr_stack_push(&EG(argument_stack), (void *) (long) param_count); - var_uninit(retval); + *retval_ptr_ptr = NULL; if (function_state.function->type == ZEND_USER_FUNCTION) { calling_symbol_table = EG(active_symbol_table); EG(active_symbol_table) = (HashTable *) emalloc(sizeof(HashTable)); @@ -382,20 +380,22 @@ int call_user_function_ex(HashTable *function_table, zval *object, zval *functio zend_hash_update_ptr(EG(active_symbol_table), "this", sizeof("this"), dummy, sizeof(zval *), (void **) &this_ptr); zend_assign_to_variable_reference(NULL, this_ptr, &object, NULL ELS_CC); } - original_return_value = EG(return_value); + original_return_value = EG(return_value_ptr_ptr); original_op_array = EG(active_op_array); - EG(return_value) = retval; + EG(return_value_ptr_ptr) = retval_ptr_ptr; EG(active_op_array) = (zend_op_array *) function_state.function; - original_opline_ptr = EG(opline_ptr); + original_opline_ptr = EG(opline_ptr); zend_execute(EG(active_op_array) ELS_CC); zend_hash_destroy(EG(active_symbol_table)); efree(EG(active_symbol_table)); EG(active_symbol_table) = calling_symbol_table; EG(active_op_array) = original_op_array; - EG(return_value)=original_return_value; + EG(return_value_ptr_ptr)=original_return_value; EG(opline_ptr) = original_opline_ptr; } else { - ((zend_internal_function *) function_state.function)->handler(param_count, retval, &EG(regular_list), &EG(persistent_list), object, 1); + ALLOC_INIT_ZVAL(*retval_ptr_ptr); + ((zend_internal_function *) function_state.function)->handler(param_count, *retval_ptr_ptr, &EG(regular_list), &EG(persistent_list), object, 1); + INIT_PZVAL(*retval_ptr_ptr); } zend_ptr_stack_clear_multiple(ELS_C); EG(function_state_ptr) = original_function_state_ptr; @@ -404,7 +404,7 @@ int call_user_function_ex(HashTable *function_table, zval *object, zval *functio } -ZEND_API void zend_eval_string(char *str, zval *retval CLS_DC ELS_DC) +ZEND_API void zend_eval_string(char *str, zval *retval_ptr CLS_DC ELS_DC) { zval pv; zend_op_array *new_op_array; @@ -412,7 +412,7 @@ ZEND_API void zend_eval_string(char *str, zval *retval CLS_DC ELS_DC) zend_function_state *original_function_state_ptr = EG(function_state_ptr); int original_handle_op_arrays; - if (retval) { + if (retval_ptr) { pv.value.str.len = strlen(str)+sizeof("return ;")-1; pv.value.str.val = emalloc(pv.value.str.len+1); strcpy(pv.value.str.val, "return "); @@ -432,25 +432,35 @@ ZEND_API void zend_eval_string(char *str, zval *retval CLS_DC ELS_DC) CG(handle_op_arrays) = original_handle_op_arrays; if (new_op_array) { - zval dummy_retval; - zval *original_return_value = EG(return_value); + zval *local_retval_ptr=NULL; + zval **original_return_value_ptr_ptr = EG(return_value_ptr_ptr); zend_op **original_opline_ptr = EG(opline_ptr); - EG(return_value) = (retval?retval:&dummy_retval); - var_reset(EG(return_value)); + EG(return_value_ptr_ptr) = &local_retval_ptr; EG(active_op_array) = new_op_array; EG(no_extensions)=1; + zend_execute(new_op_array ELS_CC); + + if (local_retval_ptr) { + if (retval_ptr) { + COPY_PZVAL_TO_ZVAL(*retval_ptr, local_retval_ptr); + } else { + zval_ptr_dtor(&local_retval_ptr); + } + } else { + if (retval_ptr) { + INIT_ZVAL(*retval_ptr); + } + } + EG(no_extensions)=0; EG(opline_ptr) = original_opline_ptr; EG(active_op_array) = original_active_op_array; EG(function_state_ptr) = original_function_state_ptr; destroy_op_array(new_op_array); efree(new_op_array); - EG(return_value) = original_return_value; - if (!retval) { - zval_dtor(&dummy_retval); - } + EG(return_value_ptr_ptr) = original_return_value_ptr_ptr; } else { printf("Failed executing:\n%s\n", str); } diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 2cd1009603..c2e61115dd 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -110,7 +110,6 @@ struct _zend_compiler_globals { struct _zend_executor_globals { - zval *return_value; zval **return_value_ptr_ptr; zval uninitialized_zval; @@ -122,7 +121,10 @@ struct _zend_executor_globals { zend_function_state *function_state_ptr; zend_ptr_stack arg_types_stack; zend_stack overloaded_objects_stack; - zval *global_return_value; + + /* for global return() support */ + zval *global_return_value_ptr; + zval global_return_value; /* symbol table cache */ HashTable *symtable_cache[SYMTABLE_CACHE_SIZE]; |