1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

- 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
This commit is contained in:
Zeev Suraski
1999-12-19 18:54:40 +00:00
parent 9947223800
commit 223c674c2a
7 changed files with 99 additions and 70 deletions

View File

@@ -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 */

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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] = &params[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);
}

View File

@@ -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];