cvs: ZendEngine2 / zend_API.c zend_API.h zend_builtin_functions.c zend_compile.c zend_compile.h zend_execute.c zend_execute.h zend_language_parser.y
zend_object_handlers.c
| From: | Andi Gutmans | Date: | Sat, 23 Nov 2002 20:44:13 +0000 |
| Subject: | cvs: ZendEngine2 / zend_API.c zend_API.h zend_builtin_functions.c zend_compile.c zend_compile.h zend_execute.c zend_execute.h zend_language_parser.y zend_object_handlers.c |
||
| Groups: | php.zend-engine.cvs | ||
| Request: | Send a blank email to php-zend-engine-cvs+get-655@lists.php.net to get a copy of this message | ||
andi Sat Nov 23 15:44:13 2002 EDT
Modified files:
/ZendEngine2 zend_API.c zend_API.h zend_builtin_functions.c
zend_compile.c zend_compile.h zend_execute.c
zend_execute.h zend_language_parser.y
zend_object_handlers.c
Log:
- Commit Marcus' cleanup of abstract and static inheritance and improve
- error messages
Index: ZendEngine2/zend_API.c diff -u ZendEngine2/zend_API.c:1.135 ZendEngine2/zend_API.c:1.136 --- ZendEngine2/zend_API.c:1.135 Fri Nov 22 05:49:46 2002 +++ ZendEngine2/zend_API.c Sat Nov 23 15:44:12 2002 @@ -1030,7 +1030,7 @@ /* registers all functions in *library_functions in the function hash */ -int zend_register_functions(zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC) +int zend_register_functions(zend_class_entry *scope, zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC) { zend_function_entry *ptr = functions; zend_function function; @@ -1054,8 +1054,8 @@ internal_function->handler = ptr->handler; internal_function->arg_types = ptr->func_arg_types; internal_function->function_name = ptr->fname; - internal_function->scope = NULL; - internal_function->is_static = 0; + internal_function->scope = scope; + internal_function->fn_flags = 0; if (!internal_function->handler) { zend_error(error_type, "Null function defined as active function"); zend_unregister_functions(functions, count, target_function_table TSRMLS_CC); @@ -1114,7 +1114,7 @@ #if 0 zend_printf("%s: Registering module %d\n", module->name, module->module_number); #endif - if (module->functions && zend_register_functions(module->functions, NULL, module->type TSRMLS_CC)==FAILURE) { + if (module->functions && zend_register_functions(NULL, module->functions, NULL, module->type TSRMLS_CC)==FAILURE) { zend_error(E_CORE_WARNING,"%s: Unable to register functions, unable to load", module->name); return FAILURE; } @@ -1246,7 +1246,7 @@ zend_hash_init(&class_entry->class_table, 10, NULL, ZEND_CLASS_DTOR, 1); if (class_entry->builtin_functions) { - zend_register_functions(class_entry->builtin_functions, &class_entry->function_table, MODULE_PERSISTENT TSRMLS_CC); + zend_register_functions(class_entry, class_entry->builtin_functions, &class_entry->function_table, MODULE_PERSISTENT TSRMLS_CC); } zend_hash_update(CG(class_table), lowercase_name, class_entry->name_length+1, &class_entry, sizeof(zend_class_entry *), NULL); @@ -1309,7 +1309,7 @@ return FAILURE; } disabled_function[0].fname = function_name; - return zend_register_functions(disabled_function, CG(function_table), MODULE_PERSISTENT TSRMLS_CC); + return zend_register_functions(NULL, disabled_function, CG(function_table), MODULE_PERSISTENT TSRMLS_CC); } zend_bool zend_is_callable(zval *callable, zend_bool syntax_only, char **callable_name) Index: ZendEngine2/zend_API.h diff -u ZendEngine2/zend_API.h:1.120 ZendEngine2/zend_API.h:1.121 --- ZendEngine2/zend_API.h:1.120 Sun Sep 15 21:36:48 2002 +++ ZendEngine2/zend_API.h Sat Nov 23 15:44:12 2002 @@ -124,7 +124,7 @@ /* End of parameter parsing API -- andrei */ -int zend_register_functions(zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC); +int zend_register_functions(zend_class_entry *scope, zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC); void zend_unregister_functions(zend_function_entry *functions, int count, HashTable *function_table TSRMLS_DC); ZEND_API int zend_register_module(zend_module_entry *module_entry); Index: ZendEngine2/zend_builtin_functions.c diff -u ZendEngine2/zend_builtin_functions.c:1.156 ZendEngine2/zend_builtin_functions.c:1.157 --- ZendEngine2/zend_builtin_functions.c:1.156 Wed Nov 20 14:44:37 2002 +++ ZendEngine2/zend_builtin_functions.c Sat Nov 23 15:44:12 2002 @@ -141,7 +141,7 @@ int zend_startup_builtin_functions(TSRMLS_D) { - return zend_register_functions(builtin_functions, NULL, MODULE_PERSISTENT TSRMLS_CC); + return zend_register_functions(NULL, builtin_functions, NULL, MODULE_PERSISTENT TSRMLS_CC); } Index: ZendEngine2/zend_compile.c diff -u ZendEngine2/zend_compile.c:1.324 ZendEngine2/zend_compile.c:1.325 --- ZendEngine2/zend_compile.c:1.324 Wed Nov 20 13:00:21 2002 +++ ZendEngine2/zend_compile.c Sat Nov 23 15:44:12 2002 @@ -909,7 +909,7 @@ } } -void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, int is_static TSRMLS_DC) +void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, int fn_flags TSRMLS_DC) { zend_op_array op_array; char *name = function_name->u.constant.value.str.val; @@ -924,7 +924,7 @@ op_array.function_name = name; op_array.arg_types = NULL; op_array.return_reference = return_reference; - op_array.is_static = is_static; + op_array.fn_flags = fn_flags; op_array.scope = CG(active_class_entry); @@ -1529,9 +1529,29 @@ ce->__call = ce->parent->__call; } +static zend_bool do_inherit_method_check(zend_function *child, zend_function *parent) { + register zend_uint child_flags = child->common.fn_flags; + register zend_uint parent_flags = parent->common.fn_flags; + + /* You cannot change from static to non static and vice versa. + */ + if ((child_flags&FN_IS_STATIC) != (parent_flags&FN_IS_STATIC)) { + if (child->common.fn_flags & FN_IS_STATIC) { + zend_error(E_COMPILE_ERROR, "Cannot make non static method %s::%s() static in class %s", FN_SCOPE_NAME(parent), child->common.function_name, FN_SCOPE_NAME(child)); + } else { + zend_error(E_COMPILE_ERROR, "Cannot make static method %s::%s() non static in class %s", FN_SCOPE_NAME(parent), child->common.function_name, FN_SCOPE_NAME(child)); + } + } + /* Disallow makeing an inherited method abstract. + */ + if (child_flags & FN_ABSTRACT) { + zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::%s() abstract in class %s", FN_SCOPE_NAME(parent), child->common.function_name, FN_SCOPE_NAME(child)); + } + return SUCCESS; +} + void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce) { - zend_function tmp_zend_function; zval *tmp; /* Perform inheritance */ @@ -1540,7 +1560,7 @@ /* STATIC_MEMBERS_FIXME */ /* zend_hash_merge(ce->static_members, parent_ce->static_members, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0); */ zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0); - zend_hash_merge(&ce->function_table, &parent_ce->function_table, (void (*)(void *)) function_add_ref, &tmp_zend_function, sizeof(zend_function), 0); + zend_hash_merge_ex(&ce->function_table, &parent_ce->function_table, (void (*)(void *)) function_add_ref, sizeof(zend_function), (zend_bool (*)(void *, void *))do_inherit_method_check); ce->parent = parent_ce; if (!ce->handle_property_get) ce->handle_property_get = parent_ce->handle_property_get; Index: ZendEngine2/zend_compile.h diff -u ZendEngine2/zend_compile.h:1.194 ZendEngine2/zend_compile.h:1.195 --- ZendEngine2/zend_compile.h:1.194 Thu Nov 21 09:16:57 2002 +++ ZendEngine2/zend_compile.h Sat Nov 23 15:44:12 2002 @@ -88,13 +88,17 @@ } zend_brk_cont_element; +#define FN_IS_STATIC 0x00000001 + +#define FN_ABSTRACT 0x00000002 + struct _zend_op_array { zend_uchar type; /* MUST be the first element of this struct! */ zend_uchar *arg_types; /* MUST be the second element of this struct! */ char *function_name; /* MUST be the third element of this struct! */ zend_class_entry *scope; /* MUST be the fourth element of this struct! */ - zend_bool is_static; /* MUST be the fifth element of this struct! */ + int fn_flags; /* MUST be the fifth element of this struct! */ zend_uint *refcount; @@ -129,11 +133,13 @@ zend_uchar *arg_types; /* MUST be the second element of this struct! */ char *function_name; /* MUST be the third element of this struct! */ zend_class_entry *scope; /* MUST be the fourth element of this struct! */ - zend_bool is_static; /* MUST be the fifth element of this struct! */ + int fn_flags; /* MUST be the fifth element of this struct! */ void (*handler)(INTERNAL_FUNCTION_PARAMETERS); } zend_internal_function; +#define FN_SCOPE_NAME(function) ((function) && (function)->common.scope ? (function)->common.scope->name : "") + typedef union _zend_function { zend_uchar type; /* MUST be the first element of this struct! */ @@ -142,7 +148,7 @@ zend_uchar *arg_types; char *function_name; zend_class_entry *scope; - zend_bool is_static; + int fn_flags; } common; zend_op_array op_array; @@ -289,7 +295,7 @@ void zend_do_add_string(znode *result, znode *op1, znode *op2 TSRMLS_DC); void zend_do_add_variable(znode *result, znode *op1, znode *op2 TSRMLS_DC); -void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, int is_static TSRMLS_DC); +void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, int fn_flags TSRMLS_DC); void zend_do_end_function_declaration(znode *function_token TSRMLS_DC); void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initialization, zend_uchar pass_type TSRMLS_DC); int zend_do_begin_function_call(znode *function_name TSRMLS_DC); Index: ZendEngine2/zend_execute.c diff -u ZendEngine2/zend_execute.c:1.397 ZendEngine2/zend_execute.c:1.398 --- ZendEngine2/zend_execute.c:1.397 Fri Nov 22 01:19:04 2002 +++ ZendEngine2/zend_execute.c Sat Nov 23 15:44:12 2002 @@ -2269,14 +2269,14 @@ if (EX(object) && EX(object)->type == IS_OBJECT) { EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(EX(object), function_name_strval, function_name_strlen TSRMLS_CC); + if (!EX(fbc)) { + zend_error(E_ERROR, "Call to undefined function: %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + } } else { - zend_error(E_ERROR, "Call to a member function on a non-object"); - } - if (!EX(fbc)) { - zend_error(E_ERROR, "Call to undefined function: %s()", function_name_strval); + zend_error(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if (EX(fbc)->common.is_static) { + if (EX(fbc)->common.fn_flags & FN_IS_STATIC) { EX(object) = NULL; } else { if (!PZVAL_IS_REF(EX(object))) { @@ -2336,7 +2336,7 @@ EX(calling_scope) = ce; if (zend_hash_find(&ce->function_table, function_name_strval, function_name_strlen+1, (void **) &function)==FAILURE) { - zend_error(E_ERROR, "Call to undefined function: %s()", function_name_strval); + zend_error(E_ERROR, "Call to undefined function: %s::%s()", ce->name, function_name_strval); } if (!is_const) { @@ -2346,7 +2346,7 @@ EX(fbc) = function; - if (function->common.is_static) { + if (function->common.fn_flags & FN_IS_STATIC) { EX(object) = NULL; } else { if ((EX(object) = EG(This))) { Index: ZendEngine2/zend_execute.h diff -u ZendEngine2/zend_execute.h:1.47 ZendEngine2/zend_execute.h:1.48 --- ZendEngine2/zend_execute.h:1.47 Sun Jun 16 14:25:05 2002 +++ ZendEngine2/zend_execute.h Sat Nov 23 15:44:12 2002 @@ -162,6 +162,11 @@ #define IS_OVERLOADED_OBJECT 1 #define IS_STRING_OFFSET 2 +/* The following tries to resolve the classname of a zval of type object. + * Since it is slow it should be only used in error messages. + */ +#define Z_OBJ_CLASS_NAME_P(zval) ((zval) && (zval)->type == IS_OBJECT && Z_OBJ_HT_P(zval)->get_class_entry != NULL && Z_OBJ_HT_P(zval)->get_class_entry(zval TSRMLS_CC) ? Z_OBJ_HT_P(zval)->get_class_entry(zval TSRMLS_CC)->name : "") + END_EXTERN_C() #endif /* ZEND_EXECUTE_H */ Index: ZendEngine2/zend_language_parser.y diff -u ZendEngine2/zend_language_parser.y:1.77 ZendEngine2/zend_language_parser.y:1.78 --- ZendEngine2/zend_language_parser.y:1.77 Wed Nov 20 13:00:23 2002 +++ ZendEngine2/zend_language_parser.y Sat Nov 23 15:44:12 2002 @@ -442,12 +442,12 @@ | is_static T_FUNCTION { $2.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$5, 1, $4.op_type, $1.u.constant.value.lval TSRMLS_CC); } '(' parameter_list ')' '{' inner_statement_list '}' { zend_do_end_function_declaration(&$2 TSRMLS_CC); } | T_CLASS T_STRING extends_from '{' { zend_do_begin_class_declaration(&$1, &$2, &$3 TSRMLS_CC); } class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); } - | T_ABSTRACT T_FUNCTION { $2.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$5, 1, $4.op_type, $1.u.constant.value.lval TSRMLS_CC); } '(' + | T_ABSTRACT T_FUNCTION { $2.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$5, 1, $4.op_type, FN_ABSTRACT TSRMLS_CC); } '(' parameter_list ')' { zend_do_abstract_method(TSRMLS_C); zend_do_end_function_declaration(&$2 TSRMLS_CC); } ; is_static: - T_STATIC { $$.u.constant.value.lval = 1; } + T_STATIC { $$.u.constant.value.lval = FN_IS_STATIC; } | /* empty */ { $$.u.constant.value.lval = 0; } ; Index: ZendEngine2/zend_object_handlers.c diff -u ZendEngine2/zend_object_handlers.c:1.21 ZendEngine2/zend_object_handlers.c:1.22 --- ZendEngine2/zend_object_handlers.c:1.21 Tue Nov 12 10:06:51 2002 +++ ZendEngine2/zend_object_handlers.c Sat Nov 23 15:44:12 2002 @@ -397,8 +397,8 @@ call_user_call->type = ZEND_INTERNAL_FUNCTION; call_user_call->handler = zend_std_call_user_call; call_user_call->arg_types = NULL; - call_user_call->scope = NULL; - call_user_call->is_static = 0; + call_user_call->scope = zobj->ce; + call_user_call->fn_flags = 0; call_user_call->function_name = estrndup(method_name, method_len); free_alloca(lc_method_name);
Index: ZendEngine2/zend_API.c diff -u ZendEngine2/zend_API.c:1.135 ZendEngine2/zend_API.c:1.136 --- ZendEngine2/zend_API.c:1.135 Fri Nov 22 05:49:46 2002 +++ ZendEngine2/zend_API.c Sat Nov 23 15:44:12 2002 @@ -1030,7 +1030,7 @@ /* registers all functions in *library_functions in the function hash */ -int zend_register_functions(zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC) +int zend_register_functions(zend_class_entry *scope, zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC) { zend_function_entry *ptr = functions; zend_function function; @@ -1054,8 +1054,8 @@ internal_function->handler = ptr->handler; internal_function->arg_types = ptr->func_arg_types; internal_function->function_name = ptr->fname; - internal_function->scope = NULL; - internal_function->is_static = 0; + internal_function->scope = scope; + internal_function->fn_flags = 0; if (!internal_function->handler) { zend_error(error_type, "Null function defined as active function"); zend_unregister_functions(functions, count, target_function_table TSRMLS_CC); @@ -1114,7 +1114,7 @@ #if 0 zend_printf("%s: Registering module %d\n", module->name, module->module_number); #endif - if (module->functions && zend_register_functions(module->functions, NULL, module->type TSRMLS_CC)==FAILURE) { + if (module->functions && zend_register_functions(NULL, module->functions, NULL, module->type TSRMLS_CC)==FAILURE) { zend_error(E_CORE_WARNING,"%s: Unable to register functions, unable to load", module->name); return FAILURE; } @@ -1246,7 +1246,7 @@ zend_hash_init(&class_entry->class_table, 10, NULL, ZEND_CLASS_DTOR, 1); if (class_entry->builtin_functions) { - zend_register_functions(class_entry->builtin_functions, &class_entry->function_table, MODULE_PERSISTENT TSRMLS_CC); + zend_register_functions(class_entry, class_entry->builtin_functions, &class_entry->function_table, MODULE_PERSISTENT TSRMLS_CC); } zend_hash_update(CG(class_table), lowercase_name, class_entry->name_length+1, &class_entry, sizeof(zend_class_entry *), NULL); @@ -1309,7 +1309,7 @@ return FAILURE; } disabled_function[0].fname = function_name; - return zend_register_functions(disabled_function, CG(function_table), MODULE_PERSISTENT TSRMLS_CC); + return zend_register_functions(NULL, disabled_function, CG(function_table), MODULE_PERSISTENT TSRMLS_CC); } zend_bool zend_is_callable(zval *callable, zend_bool syntax_only, char **callable_name) Index: ZendEngine2/zend_API.h diff -u ZendEngine2/zend_API.h:1.120 ZendEngine2/zend_API.h:1.121 --- ZendEngine2/zend_API.h:1.120 Sun Sep 15 21:36:48 2002 +++ ZendEngine2/zend_API.h Sat Nov 23 15:44:12 2002 @@ -124,7 +124,7 @@ /* End of parameter parsing API -- andrei */ -int zend_register_functions(zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC); +int zend_register_functions(zend_class_entry *scope, zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC); void zend_unregister_functions(zend_function_entry *functions, int count, HashTable *function_table TSRMLS_DC); ZEND_API int zend_register_module(zend_module_entry *module_entry); Index: ZendEngine2/zend_builtin_functions.c diff -u ZendEngine2/zend_builtin_functions.c:1.156 ZendEngine2/zend_builtin_functions.c:1.157 --- ZendEngine2/zend_builtin_functions.c:1.156 Wed Nov 20 14:44:37 2002 +++ ZendEngine2/zend_builtin_functions.c Sat Nov 23 15:44:12 2002 @@ -141,7 +141,7 @@ int zend_startup_builtin_functions(TSRMLS_D) { - return zend_register_functions(builtin_functions, NULL, MODULE_PERSISTENT TSRMLS_CC); + return zend_register_functions(NULL, builtin_functions, NULL, MODULE_PERSISTENT TSRMLS_CC); } Index: ZendEngine2/zend_compile.c diff -u ZendEngine2/zend_compile.c:1.324 ZendEngine2/zend_compile.c:1.325 --- ZendEngine2/zend_compile.c:1.324 Wed Nov 20 13:00:21 2002 +++ ZendEngine2/zend_compile.c Sat Nov 23 15:44:12 2002 @@ -909,7 +909,7 @@ } } -void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, int is_static TSRMLS_DC) +void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, int fn_flags TSRMLS_DC) { zend_op_array op_array; char *name = function_name->u.constant.value.str.val; @@ -924,7 +924,7 @@ op_array.function_name = name; op_array.arg_types = NULL; op_array.return_reference = return_reference; - op_array.is_static = is_static; + op_array.fn_flags = fn_flags; op_array.scope = CG(active_class_entry); @@ -1529,9 +1529,29 @@ ce->__call = ce->parent->__call; } +static zend_bool do_inherit_method_check(zend_function *child, zend_function *parent) { + register zend_uint child_flags = child->common.fn_flags; + register zend_uint parent_flags = parent->common.fn_flags; + + /* You cannot change from static to non static and vice versa. + */ + if ((child_flags&FN_IS_STATIC) != (parent_flags&FN_IS_STATIC)) { + if (child->common.fn_flags & FN_IS_STATIC) { + zend_error(E_COMPILE_ERROR, "Cannot make non static method %s::%s() static in class %s", FN_SCOPE_NAME(parent), child->common.function_name, FN_SCOPE_NAME(child)); + } else { + zend_error(E_COMPILE_ERROR, "Cannot make static method %s::%s() non static in class %s", FN_SCOPE_NAME(parent), child->common.function_name, FN_SCOPE_NAME(child)); + } + } + /* Disallow makeing an inherited method abstract. + */ + if (child_flags & FN_ABSTRACT) { + zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::%s() abstract in class %s", FN_SCOPE_NAME(parent), child->common.function_name, FN_SCOPE_NAME(child)); + } + return SUCCESS; +} + void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce) { - zend_function tmp_zend_function; zval *tmp; /* Perform inheritance */ @@ -1540,7 +1560,7 @@ /* STATIC_MEMBERS_FIXME */ /* zend_hash_merge(ce->static_members, parent_ce->static_members, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0); */ zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0); - zend_hash_merge(&ce->function_table, &parent_ce->function_table, (void (*)(void *)) function_add_ref, &tmp_zend_function, sizeof(zend_function), 0); + zend_hash_merge_ex(&ce->function_table, &parent_ce->function_table, (void (*)(void *)) function_add_ref, sizeof(zend_function), (zend_bool (*)(void *, void *))do_inherit_method_check); ce->parent = parent_ce; if (!ce->handle_property_get) ce->handle_property_get = parent_ce->handle_property_get; Index: ZendEngine2/zend_compile.h diff -u ZendEngine2/zend_compile.h:1.194 ZendEngine2/zend_compile.h:1.195 --- ZendEngine2/zend_compile.h:1.194 Thu Nov 21 09:16:57 2002 +++ ZendEngine2/zend_compile.h Sat Nov 23 15:44:12 2002 @@ -88,13 +88,17 @@ } zend_brk_cont_element; +#define FN_IS_STATIC 0x00000001 + +#define FN_ABSTRACT 0x00000002 + struct _zend_op_array { zend_uchar type; /* MUST be the first element of this struct! */ zend_uchar *arg_types; /* MUST be the second element of this struct! */ char *function_name; /* MUST be the third element of this struct! */ zend_class_entry *scope; /* MUST be the fourth element of this struct! */ - zend_bool is_static; /* MUST be the fifth element of this struct! */ + int fn_flags; /* MUST be the fifth element of this struct! */ zend_uint *refcount; @@ -129,11 +133,13 @@ zend_uchar *arg_types; /* MUST be the second element of this struct! */ char *function_name; /* MUST be the third element of this struct! */ zend_class_entry *scope; /* MUST be the fourth element of this struct! */ - zend_bool is_static; /* MUST be the fifth element of this struct! */ + int fn_flags; /* MUST be the fifth element of this struct! */ void (*handler)(INTERNAL_FUNCTION_PARAMETERS); } zend_internal_function; +#define FN_SCOPE_NAME(function) ((function) && (function)->common.scope ? (function)->common.scope->name : "") + typedef union _zend_function { zend_uchar type; /* MUST be the first element of this struct! */ @@ -142,7 +148,7 @@ zend_uchar *arg_types; char *function_name; zend_class_entry *scope; - zend_bool is_static; + int fn_flags; } common; zend_op_array op_array; @@ -289,7 +295,7 @@ void zend_do_add_string(znode *result, znode *op1, znode *op2 TSRMLS_DC); void zend_do_add_variable(znode *result, znode *op1, znode *op2 TSRMLS_DC); -void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, int is_static TSRMLS_DC); +void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, int fn_flags TSRMLS_DC); void zend_do_end_function_declaration(znode *function_token TSRMLS_DC); void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initialization, zend_uchar pass_type TSRMLS_DC); int zend_do_begin_function_call(znode *function_name TSRMLS_DC); Index: ZendEngine2/zend_execute.c diff -u ZendEngine2/zend_execute.c:1.397 ZendEngine2/zend_execute.c:1.398 --- ZendEngine2/zend_execute.c:1.397 Fri Nov 22 01:19:04 2002 +++ ZendEngine2/zend_execute.c Sat Nov 23 15:44:12 2002 @@ -2269,14 +2269,14 @@ if (EX(object) && EX(object)->type == IS_OBJECT) { EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(EX(object), function_name_strval, function_name_strlen TSRMLS_CC); + if (!EX(fbc)) { + zend_error(E_ERROR, "Call to undefined function: %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + } } else { - zend_error(E_ERROR, "Call to a member function on a non-object"); - } - if (!EX(fbc)) { - zend_error(E_ERROR, "Call to undefined function: %s()", function_name_strval); + zend_error(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if (EX(fbc)->common.is_static) { + if (EX(fbc)->common.fn_flags & FN_IS_STATIC) { EX(object) = NULL; } else { if (!PZVAL_IS_REF(EX(object))) { @@ -2336,7 +2336,7 @@ EX(calling_scope) = ce; if (zend_hash_find(&ce->function_table, function_name_strval, function_name_strlen+1, (void **) &function)==FAILURE) { - zend_error(E_ERROR, "Call to undefined function: %s()", function_name_strval); + zend_error(E_ERROR, "Call to undefined function: %s::%s()", ce->name, function_name_strval); } if (!is_const) { @@ -2346,7 +2346,7 @@ EX(fbc) = function; - if (function->common.is_static) { + if (function->common.fn_flags & FN_IS_STATIC) { EX(object) = NULL; } else { if ((EX(object) = EG(This))) { Index: ZendEngine2/zend_execute.h diff -u ZendEngine2/zend_execute.h:1.47 ZendEngine2/zend_execute.h:1.48 --- ZendEngine2/zend_execute.h:1.47 Sun Jun 16 14:25:05 2002 +++ ZendEngine2/zend_execute.h Sat Nov 23 15:44:12 2002 @@ -162,6 +162,11 @@ #define IS_OVERLOADED_OBJECT 1 #define IS_STRING_OFFSET 2 +/* The following tries to resolve the classname of a zval of type object. + * Since it is slow it should be only used in error messages. + */ +#define Z_OBJ_CLASS_NAME_P(zval) ((zval) && (zval)->type == IS_OBJECT && Z_OBJ_HT_P(zval)->get_class_entry != NULL && Z_OBJ_HT_P(zval)->get_class_entry(zval TSRMLS_CC) ? Z_OBJ_HT_P(zval)->get_class_entry(zval TSRMLS_CC)->name : "") + END_EXTERN_C() #endif /* ZEND_EXECUTE_H */ Index: ZendEngine2/zend_language_parser.y diff -u ZendEngine2/zend_language_parser.y:1.77 ZendEngine2/zend_language_parser.y:1.78 --- ZendEngine2/zend_language_parser.y:1.77 Wed Nov 20 13:00:23 2002 +++ ZendEngine2/zend_language_parser.y Sat Nov 23 15:44:12 2002 @@ -442,12 +442,12 @@ | is_static T_FUNCTION { $2.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$5, 1, $4.op_type, $1.u.constant.value.lval TSRMLS_CC); } '(' parameter_list ')' '{' inner_statement_list '}' { zend_do_end_function_declaration(&$2 TSRMLS_CC); } | T_CLASS T_STRING extends_from '{' { zend_do_begin_class_declaration(&$1, &$2, &$3 TSRMLS_CC); } class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); } - | T_ABSTRACT T_FUNCTION { $2.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$5, 1, $4.op_type, $1.u.constant.value.lval TSRMLS_CC); } '(' + | T_ABSTRACT T_FUNCTION { $2.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$5, 1, $4.op_type, FN_ABSTRACT TSRMLS_CC); } '(' parameter_list ')' { zend_do_abstract_method(TSRMLS_C); zend_do_end_function_declaration(&$2 TSRMLS_CC); } ; is_static: - T_STATIC { $$.u.constant.value.lval = 1; } + T_STATIC { $$.u.constant.value.lval = FN_IS_STATIC; } | /* empty */ { $$.u.constant.value.lval = 0; } ; Index: ZendEngine2/zend_object_handlers.c diff -u ZendEngine2/zend_object_handlers.c:1.21 ZendEngine2/zend_object_handlers.c:1.22 --- ZendEngine2/zend_object_handlers.c:1.21 Tue Nov 12 10:06:51 2002 +++ ZendEngine2/zend_object_handlers.c Sat Nov 23 15:44:12 2002 @@ -397,8 +397,8 @@ call_user_call->type = ZEND_INTERNAL_FUNCTION; call_user_call->handler = zend_std_call_user_call; call_user_call->arg_types = NULL; - call_user_call->scope = NULL; - call_user_call->is_static = 0; + call_user_call->scope = zobj->ce; + call_user_call->fn_flags = 0; call_user_call->function_name = estrndup(method_name, method_len); free_alloca(lc_method_name);