Hello. This patch allows __autoload to be called to not only for classes but for functions too. It adds two defines: AUTOLOAD_CLASS and AUTOLOAD_FUNCTION. The prototype for __autoload becomes: function autoload ($autoload_name, $autoload_type); where $autoload_type is AUTOLOAD_CLASS or AUTOLOAD_FUNCTION.
vesselin diff -ru php5-200308212130.orig/Zend/zend_constants.c php5-200308212130/Zend/zend_constants.c --- php5-200308212130.orig/Zend/zend_constants.c 2003-07-27 13:06:49.000000000 +0000 +++ php5-200308212130/Zend/zend_constants.c 2003-08-22 05:43:25.000000000 +0000 @@ -106,6 +106,9 @@ REGISTER_MAIN_LONG_CONSTANT("E_USER_NOTICE", E_USER_NOTICE, CONST_PERSISTENT | CONST_CS); REGISTER_MAIN_LONG_CONSTANT("E_ALL", E_ALL, CONST_PERSISTENT | CONST_CS); + + REGISTER_MAIN_LONG_CONSTANT("AUTOLOAD_CLASS", AUTOLOAD_CLASS, CONST_PERSISTENT | CONST_CS); + REGISTER_MAIN_LONG_CONSTANT("AUTOLOAD_FUNCTION", AUTOLOAD_FUNCTION, CONST_PERSISTENT | CONST_CS); /* true/false constants */ { diff -ru php5-200308212130.orig/Zend/zend_constants.h php5-200308212130/Zend/zend_constants.h --- php5-200308212130.orig/Zend/zend_constants.h 2003-06-10 20:07:17.000000000 +0000 +++ php5-200308212130/Zend/zend_constants.h 2003-08-22 05:42:45.000000000 +0000 @@ -64,6 +64,9 @@ #define ZEND_CONSTANT_DTOR (void (*)(void *)) free_zend_constant +#define AUTOLOAD_CLASS 0 +#define AUTOLOAD_FUNCTION 1 + #endif /* diff -ru php5-200308212130.orig/Zend/zend_execute.c php5-200308212130/Zend/zend_execute.c --- php5-200308212130.orig/Zend/zend_execute.c 2003-08-19 02:07:34.000000000 +0000 +++ php5-200308212130/Zend/zend_execute.c 2003-08-22 06:42:08.000000000 +0000 @@ -2449,6 +2449,17 @@ NEXT_OPCODE(); } +static inline int zend_lookup_function (char *name, int name_length, zend_function **function) +{ + if (zend_hash_find(EG(function_table), name, name_length+1, (void **) function) == SUCCESS) { + return SUCCESS; + } + if (zend_autoload_name(name, name_length, AUTOLOAD_FUNCTION) == FAILURE) { + return FAILURE; + } + return zend_hash_find(EG(function_table), name, name_length+1, (void **) function); +} + int zend_init_fcall_by_name_handler(ZEND_OPCODE_HANDLER_ARGS) { zval *function_name; @@ -2473,8 +2484,8 @@ function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len); function_name_strlen = function_name->value.str.len; } - - if (zend_hash_find(EG(function_table), function_name_strval, function_name_strlen+1, (void **) &function)==FAILURE) { + + if (zend_lookup_function(function_name_strval, function_name_strlen, &function) == FAILURE) { zend_error(E_ERROR, "Call to undefined function: %s()", function_name_strval); } diff -ru php5-200308212130.orig/Zend/zend_execute.h php5-200308212130/Zend/zend_execute.h --- php5-200308212130.orig/Zend/zend_execute.h 2003-08-03 09:07:21.000000000 +0000 +++ php5-200308212130/Zend/zend_execute.h 2003-08-22 06:26:14.000000000 +0000 @@ -148,6 +148,8 @@ ZEND_API void zend_unset_timeout(TSRMLS_D); ZEND_API void zend_timeout(int dummy); ZEND_API zend_class_entry *zend_fetch_class(char *class_name, uint class_name_len, int fetch_type TSRMLS_DC); +ZEND_API int zend_autoload_name(char *name, int name_length, long type); + #ifdef ZEND_WIN32 void zend_init_timeout_thread(); diff -ru php5-200308212130.orig/Zend/zend_execute_API.c php5-200308212130/Zend/zend_execute_API.c --- php5-200308212130.orig/Zend/zend_execute_API.c 2003-08-07 08:06:15.000000000 +0000 +++ php5-200308212130/Zend/zend_execute_API.c 2003-08-22 06:26:17.000000000 +0000 @@ -757,39 +757,13 @@ ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***ce TSRMLS_DC) { - zval **args[1]; - zval *autoload_function; - zval *class_name; - zval *retval_ptr; - int retval; if (zend_hash_find(EG(class_table), name, name_length+1, (void **) ce) == SUCCESS) { return SUCCESS; } - - MAKE_STD_ZVAL(autoload_function); - ZVAL_STRINGL(autoload_function, "__autoload", sizeof("__autoload")-1, 1); - - MAKE_STD_ZVAL(class_name); - ZVAL_STRINGL(class_name, name, name_length, 1); - args[0] = &class_name; - - retval = call_user_function_ex(EG(function_table), NULL, autoload_function, &retval_ptr, 1, args, 0, NULL TSRMLS_CC); - - zval_ptr_dtor(&autoload_function); - zval_ptr_dtor(&class_name); - - if (retval == FAILURE) { + if (zend_autoload_name(name, name_length, AUTOLOAD_CLASS) == FAILURE) { return FAILURE; } - - if (EG(exception)) { - zend_error(E_ERROR, "__autoload threw an exception"); - } - - /* If an exception is thrown retval_ptr will be NULL but we bailout before we reach this point */ - zval_ptr_dtor(&retval_ptr); - return zend_hash_find(EG(class_table), name, name_length + 1, (void **) ce); } @@ -1104,6 +1078,46 @@ return *pce; } +int zend_autoload_name(char *name, int name_length, long type) +{ + zval **args[2]; + zval *autoload_function; + zval *autoload_name; + zval *autoload_type; + zval *retval_ptr; + int retval; + + MAKE_STD_ZVAL(autoload_function); + ZVAL_STRINGL(autoload_function, "__autoload", sizeof("__autoload")-1, 1); + + MAKE_STD_ZVAL(autoload_name); + ZVAL_STRINGL(autoload_name, name, name_length, 1); + args[0] = &autoload_name; + + MAKE_STD_ZVAL(autoload_type); + ZVAL_LONG(autoload_type, type); + args[1] = &autoload_type; + + retval = call_user_function_ex(EG(function_table), NULL, autoload_function, &retval_ptr, 2, args, 0, NULL TSRMLS_CC); + + zval_ptr_dtor(&autoload_function); + zval_ptr_dtor(&autoload_name); + zval_ptr_dtor(&autoload_type); + + if (retval == FAILURE) { + return FAILURE; + } + + if (EG(exception)) { + zend_error(E_ERROR, "__autoload threw an exception"); + } + + /* If an exception is thrown retval_ptr will be NULL but we bailout before we reach this point */ + zval_ptr_dtor(&retval_ptr); + + return SUCCESS; +} + /* * Local variables: * tab-width: 4 -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php