diff --git a/NEWS b/NEWS index 9341043962510..8e74bada9e1c1 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,7 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? Jun 2005, PHP 5.1 Beta 2 +- Allowed return by refrence from internal functions. (Marcus, Andi, Dmitry) - Added bindto socket context option. (Ilia) - Rewrote strtotime() with support for timezones and tons of new formats. (Derick) diff --git a/Zend/zend.h b/Zend/zend.h index 65a91f696d244..eb06003029937 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -247,8 +247,8 @@ char *alloca (); #include "zend_ts_hash.h" #include "zend_llist.h" -#define INTERNAL_FUNCTION_PARAMETERS int ht, zval *return_value, zval *this_ptr, int return_value_used TSRMLS_DC -#define INTERNAL_FUNCTION_PARAM_PASSTHRU ht, return_value, this_ptr, return_value_used TSRMLS_CC +#define INTERNAL_FUNCTION_PARAMETERS int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC +#define INTERNAL_FUNCTION_PARAM_PASSTHRU ht, return_value, return_value_ptr, this_ptr, return_value_used TSRMLS_CC #if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(DARWIN) # define ZEND_VM_ALWAYS_INLINE __attribute__ ((always_inline)) diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 9896e4f22f642..06a29246b6e17 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -65,7 +65,7 @@ typedef struct _zend_function_entry { zend_arg_info name[] = { \ { NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args }, #define ZEND_BEGIN_ARG_INFO(name, pass_rest_by_reference) \ - ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, ZEND_RETURN_REFERENCE_AGNOSTIC, -1) + ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, ZEND_RETURN_VALUE, -1) #define ZEND_END_ARG_INFO() }; /* Name macros */ diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index d569fa86088fb..8d741604b22c6 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1855,12 +1855,8 @@ static zend_bool zend_do_perform_implementation_check(zend_function *fe, zend_fu return 0; } - if (proto->common.return_reference != ZEND_RETURN_REFERENCE_AGNOSTIC - && fe->common.return_reference != proto->common.return_reference) { - /* atm we cannot let internal function return by ref */ - if (fe->type == proto->type || fe->type != ZEND_INTERNAL_FUNCTION) { - return 0; - } + if (fe->common.return_reference != proto->common.return_reference) { + return 0; } for (i=0; i < proto->common.num_args; i++) { diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index fe84bd3b3531a..fe2bfe8163b63 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -219,7 +219,6 @@ struct _zend_op_array { #define ZEND_RETURN_VALUE 0 #define ZEND_RETURN_REFERENCE 1 -#define ZEND_RETURN_REFERENCE_AGNOSTIC 2 typedef struct _zend_internal_function { /* Common elements */ diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 98547a1a17884..9e79761f4f34f 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1291,7 +1291,8 @@ ZEND_API opcode_handler_t *zend_opcode_handlers; ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC) { - ((zend_internal_function *) execute_data_ptr->function_state.function)->handler(execute_data_ptr->opline->extended_value, (*(temp_variable *)((char *) execute_data_ptr->Ts + execute_data_ptr->opline->result.u.var)).var.ptr, execute_data_ptr->object, return_value_used TSRMLS_CC); + zval **return_value_ptr = &(*(temp_variable *)((char *) execute_data_ptr->Ts + execute_data_ptr->opline->result.u.var)).var.ptr; + ((zend_internal_function *) execute_data_ptr->function_state.function)->handler(execute_data_ptr->opline->extended_value, *return_value_ptr, execute_data_ptr->function_state.function->common.return_reference?return_value_ptr:NULL, execute_data_ptr->object, return_value_used TSRMLS_CC); } #define ZEND_VM_NEXT_OPCODE() \ diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 597a89e2f23d7..8c527ec591c70 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -864,7 +864,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS if (EX(function_state).function->common.scope) { EG(scope) = EX(function_state).function->common.scope; } - ((zend_internal_function *) EX(function_state).function)->handler(fci->param_count, *fci->retval_ptr_ptr, (fci->object_pp?*fci->object_pp:NULL), 1 TSRMLS_CC); + ((zend_internal_function *) EX(function_state).function)->handler(fci->param_count, *fci->retval_ptr_ptr, EX(function_state).function->common.return_reference?fci->retval_ptr_ptr:NULL, (fci->object_pp?*fci->object_pp:NULL), 1 TSRMLS_CC); INIT_PZVAL(*fci->retval_ptr_ptr); } zend_ptr_stack_clear_multiple(TSRMLS_C); diff --git a/Zend/zend_extensions.h b/Zend/zend_extensions.h index a937430d88e17..19b091f48b899 100644 --- a/Zend/zend_extensions.h +++ b/Zend/zend_extensions.h @@ -27,7 +27,7 @@ /* The first number is the engine version and the rest is the date. * This way engine 2 API no. is always greater than engine 1 API no.. */ -#define ZEND_EXTENSION_API_NO 220050610 +#define ZEND_EXTENSION_API_NO 220050615 typedef struct _zend_extension_version_info { int zend_extension_api_no; diff --git a/Zend/zend_modules.h b/Zend/zend_modules.h index ac2f0430c2b2e..9223383fffff9 100644 --- a/Zend/zend_modules.h +++ b/Zend/zend_modules.h @@ -38,7 +38,7 @@ extern struct _zend_arg_info third_arg_force_ref[4]; extern struct _zend_arg_info fourth_arg_force_ref[5]; extern struct _zend_arg_info all_args_by_ref[1]; -#define ZEND_MODULE_API_NO 20041031 +#define ZEND_MODULE_API_NO 20050615 #ifdef ZTS #define USING_ZTS 1 #else diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index dd86080e6d17c..dd80e0d6ec497 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -658,6 +658,8 @@ static union _zend_function *zend_std_get_method(zval **object_ptr, char *method call_user_call->scope = zobj->ce; call_user_call->fn_flags = 0; call_user_call->function_name = estrndup(method_name, method_len); + call_user_call->pass_rest_by_reference = 0; + call_user_call->return_reference = ZEND_RETURN_VALUE; return (union _zend_function *)call_user_call; } else { diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 419098a6a3549..03d983a1e8345 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1830,7 +1830,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY) } if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ - ((zend_internal_function *) EX(function_state).function)->handler(opline->extended_value, EX_T(opline->result.u.var).var.ptr, EX(object), return_value_used TSRMLS_CC); + ((zend_internal_function *) EX(function_state).function)->handler(opline->extended_value, EX_T(opline->result.u.var).var.ptr, EX(function_state).function->common.return_reference?&EX_T(opline->result.u.var).var.ptr:NULL, EX(object), return_value_used TSRMLS_CC); } else { zend_execute_internal(EXECUTE_DATA, return_value_used TSRMLS_CC); } @@ -1890,7 +1890,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY) /* Not sure what should be done here if it's a static method */ if (EX(object)) { - Z_OBJ_HT_P(EX(object))->call_method(EX(fbc)->common.function_name, opline->extended_value, EX_T(opline->result.u.var).var.ptr, EX(object), return_value_used TSRMLS_CC); + Z_OBJ_HT_P(EX(object))->call_method(EX(fbc)->common.function_name, opline->extended_value, EX_T(opline->result.u.var).var.ptr, &EX_T(opline->result.u.var).var.ptr, EX(object), return_value_used TSRMLS_CC); } else { zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object"); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index d91900a6f0e69..44dd975743bea 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -181,7 +181,7 @@ static int zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) } if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ - ((zend_internal_function *) EX(function_state).function)->handler(opline->extended_value, EX_T(opline->result.u.var).var.ptr, EX(object), return_value_used TSRMLS_CC); + ((zend_internal_function *) EX(function_state).function)->handler(opline->extended_value, EX_T(opline->result.u.var).var.ptr, EX(function_state).function->common.return_reference?&EX_T(opline->result.u.var).var.ptr:NULL, EX(object), return_value_used TSRMLS_CC); } else { zend_execute_internal(execute_data, return_value_used TSRMLS_CC); } @@ -241,7 +241,7 @@ static int zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) /* Not sure what should be done here if it's a static method */ if (EX(object)) { - Z_OBJ_HT_P(EX(object))->call_method(EX(fbc)->common.function_name, opline->extended_value, EX_T(opline->result.u.var).var.ptr, EX(object), return_value_used TSRMLS_CC); + Z_OBJ_HT_P(EX(object))->call_method(EX(fbc)->common.function_name, opline->extended_value, EX_T(opline->result.u.var).var.ptr, &EX_T(opline->result.u.var).var.ptr, EX(object), return_value_used TSRMLS_CC); } else { zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object"); } diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index d8f672cc369fa..71ad2fc9ee3a2 100755 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -1499,7 +1499,7 @@ SPL_METHOD(CachingRecursiveIterator, getChildren) } /* }}} */ static -ZEND_BEGIN_ARG_INFO_EX(arginfo_caching_rec_it___construct, 0, ZEND_RETURN_REFERENCE_AGNOSTIC, 2) +ZEND_BEGIN_ARG_INFO_EX(arginfo_caching_rec_it___construct, 0, ZEND_RETURN_VALUE, 2) ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0) ZEND_ARG_INFO(0, flags) ZEND_END_ARG_INFO();