# [PATCH] Autoloading of functions

- Thread: https://externals.io/message/4123
- Original archive: https://news-web.php.net/php.internals/4123
- Started by Vesselin Atanasov on 2003-08-22T03:53:41+00:00
- Messages: 1
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #4123 — Vesselin Atanasov — 2003-08-22T03:53:41+00:00

URL: https://externals.io/message/4123#4123

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
