Hello.
Some time ago I have posted a patch that would make PHP call __autoload() for unknown functions too.
I didn't get any feedback regarding the patch so I send it to the mailing list once again. The patch
adds two constants AUTOLOAD_CLASS and AUTOLOAD_FUNCTION. The __autoload() definition is changed to :
function __autoload ($name, $type);
where $type is either AUTOLOAD_CLASS or AUTOLOAD_NAME, for backward compatibility thee definition
function __autoload ($name);
if allowed too. I have pasted a diff against the latest development snapshot of PHP-5.1. I'm sending the diff as an attachment too
in case the sending/receiving mail client mangles the diff. Any comments?
diff -ru php5-200411302330.orig/Zend/zend.c php5-200411302330/Zend/zend.c
--- php5-200411302330.orig/Zend/zend.c 2004-09-09 18:30:10.000000000 +0000
+++ php5-200411302330/Zend/zend.c 2004-12-01 04:09:24.000000000 +0000
@@ -477,7 +477,8 @@
EG(user_error_handler) = NULL;
EG(user_exception_handler) = NULL;
EG(in_execution) = 0;
- EG(in_autoload) = NULL;
- EG(in_autoload_class) = NULL;
- EG(in_autoload_function) = NULL;
EG(current_execute_data) = NULL;
EG(current_module) = NULL;
}
diff -ru php5-200411302330.orig/Zend/zend_compile.c php5-200411302330/Zend/zend_compile.c
--- php5-200411302330.orig/Zend/zend_compile.c 2004-10-17 00:30:43.000000000 +0000
+++ php5-200411302330/Zend/zend_compile.c 2004-12-01 04:12:08.000000000 +0000
@@ -1177,8 +1177,8 @@
name_len = strlen(CG(active_op_array)->function_name);
zend_str_tolower_copy(lcname, CG(active_op_array)->function_name, MIN(name_len, sizeof(lcname)-1));
lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
-
if (name_len == sizeof(ZEND_AUTOLOAD_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_AUTOLOAD_FUNC_NAME,
sizeof(ZEND_AUTOLOAD_FUNC_NAME)) && CG(active_op_array)->num_args != 1) {
-
zend_error(E_COMPILE_ERROR, "%s() must take exactly 1 argument", ZEND_AUTOLOAD_FUNC_NAME);
-
if (name_len == sizeof(ZEND_AUTOLOAD_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_AUTOLOAD_FUNC_NAME,
sizeof(ZEND_AUTOLOAD_FUNC_NAME)) && CG(active_op_array)->num_args != 1 && CG(active_op_array)->num_args != 2) {
-
}zend_error(E_COMPILE_ERROR, "%s() must take 1 or 2 arguments", ZEND_AUTOLOAD_FUNC_NAME); }
diff -ru php5-200411302330.orig/Zend/zend_constants.c php5-200411302330/Zend/zend_constants.c
--- php5-200411302330.orig/Zend/zend_constants.c 2004-07-13 20:30:05.000000000 +0000
+++ php5-200411302330/Zend/zend_constants.c 2004-12-01 04:13:31.000000000 +0000
@@ -108,6 +108,9 @@
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 */
{
zend_constant c;
diff -ru php5-200411302330.orig/Zend/zend_constants.h php5-200411302330/Zend/zend_constants.h
--- php5-200411302330.orig/Zend/zend_constants.h 2004-03-04 11:08:13.000000000 +0000
+++ php5-200411302330/Zend/zend_constants.h 2004-12-01 04:14:22.000000000 +0000
@@ -66,6 +66,9 @@
#define ZEND_CONSTANT_DTOR (void (*)(void *)) free_zend_constant
+#define AUTOLOAD_CLASS 0
+#define AUTOLOAD_FUNCTION 1
#endif
/*
diff -ru php5-200411302330.orig/Zend/zend_execute.h php5-200411302330/Zend/zend_execute.h
--- php5-200411302330.orig/Zend/zend_execute.h 2004-09-23 22:30:50.000000000 +0000
+++ php5-200411302330/Zend/zend_execute.h 2004-12-01 04:46:52.000000000 +0000
@@ -65,6 +65,7 @@
}
}
ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***ce TSRMLS_DC);
+ZEND_API int zend_lookup_function(char *name, int name_length, zend_function **function TSRMLS_DC);
ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC);
ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
diff -ru php5-200411302330.orig/Zend/zend_execute_API.c php5-200411302330/Zend/zend_execute_API.c
--- php5-200411302330.orig/Zend/zend_execute_API.c 2004-11-23 17:30:13.000000000 +0000
+++ php5-200411302330/Zend/zend_execute_API.c 2004-12-01 05:05:00.000000000 +0000
@@ -137,7 +137,8 @@
EG(class_table) = CG(class_table);
EG(in_execution) = 0;
- EG(in_autoload) = NULL;
-
EG(in_autoload_class) = NULL;
-
EG(in_autoload_function) = NULL;
EG(autoload_func) = NULL;zend_ptr_stack_init(&EG(argument_stack));
@@ -293,10 +294,14 @@
zend_ptr_stack_destroy(&EG(user_error_handlers));
zend_ptr_stack_destroy(&EG(user_exception_handlers));
zend_objects_store_destroy(&EG(objects_store));
-
if (EG(in_autoload)) {
-
zend_hash_destroy(EG(in_autoload));
-
FREE_HASHTABLE(EG(in_autoload));
-
}
-
if (EG(in_autoload_class)) {
-
zend_hash_destroy(EG(in_autoload_class));
-
FREE_HASHTABLE(EG(in_autoload_class));
-
}
-
if (EG(in_autoload_function)) {
-
zend_hash_destroy(EG(in_autoload_function));
-
FREE_HASHTABLE(EG(in_autoload_function));
-
} zend_end_try();}
}
@@ -870,16 +875,18 @@
}
-ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***ce TSRMLS_DC)
+static int zend_lookup_autoloadable(char *name, int name_length, void **item, HashTable *lookup_table, HashTable
**autoload_table_ptr, long type TSRMLS_DC)
{
- zval **args[1];
- char *lc_name;
- HashTable *autoload_table;
- char dummy = 1;
zval autoload_function;
- zval class_name, *class_name_ptr = &class_name;
- zval **args[2];
- zval autoload_name, *autoload_name_ptr = &autoload_name;
- zval autoload_type, *autoload_type_ptr = &autoload_type;
- zval *exception;
zval *retval_ptr;
int retval;
- char *lc_name;
- zval *exception;
- char dummy = 1;
zend_fcall_info fcall_info;
zend_fcall_info_cache fcall_cache;
@@ -890,7 +897,7 @@
lc_name = do_alloca(name_length + 1);
zend_str_tolower_copy(lc_name, name, name_length);
- if (zend_hash_find(EG(class_table), lc_name, name_length+1, (void **) ce) == SUCCESS) {
- if (zend_hash_find(lookup_table, lc_name, name_length+1, item) == SUCCESS) {
free_alloca(lc_name);
return SUCCESS;
}
@@ -903,29 +910,33 @@
return FAILURE;
}
- if (EG(in_autoload) == NULL) {
-
ALLOC_HASHTABLE(EG(in_autoload));
-
zend_hash_init(EG(in_autoload), 0, NULL, NULL, 0);
- if ((autoload_table = *autoload_table_ptr) == NULL) {
-
ALLOC_HASHTABLE(autoload_table);
-
zend_hash_init(autoload_table, 0, NULL, NULL, 0);
-
}*autoload_table_ptr = autoload_table;
- if (zend_hash_add(EG(in_autoload), lc_name, name_length+1, (void**)&dummy, sizeof(char), NULL) == FAILURE) {
-
if (zend_hash_add(autoload_table, lc_name, name_length+1, (void**)&dummy, sizeof(char), NULL) == FAILURE) {
free_alloca(lc_name);
return FAILURE;
}ZVAL_STRINGL(&autoload_function, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME)-1, 0);
- INIT_PZVAL(class_name_ptr);
- ZVAL_STRINGL(class_name_ptr, name, name_length, 0);
- args[0] = &class_name_ptr;
-
INIT_PZVAL(autoload_name_ptr);
-
ZVAL_STRINGL(autoload_name_ptr, name, name_length, 0);
-
args[0] = &autoload_name_ptr;
-
INIT_PZVAL(autoload_type_ptr);
-
ZVAL_LONG(autoload_type_ptr, type);
-
args[1] = &autoload_type_ptr;
fcall_info.size = sizeof(fcall_info);
fcall_info.function_table = EG(function_table);
fcall_info.function_name = &autoload_function;
fcall_info.symbol_table = NULL;
fcall_info.retval_ptr_ptr = &retval_ptr;
- fcall_info.param_count = 1;
- fcall_info.param_count = 2;
fcall_info.params = args;
fcall_info.object_pp = NULL;
fcall_info.no_separation = 1;
@@ -940,7 +951,7 @@
retval = zend_call_function(&fcall_info, &fcall_cache TSRMLS_CC);
EG(autoload_func) = fcall_cache.function_handler;
- zend_hash_del(EG(in_autoload), lc_name, name_length+1);
-
zend_hash_del(autoload_table, lc_name, name_length+1);
if (retval == FAILURE) {
EG(exception) = exception;
@@ -958,11 +969,21 @@
/* If an exception is thrown retval_ptr will beNULL
but we bailout before we reach this point */
zval_ptr_dtor(&retval_ptr);
- retval = zend_hash_find(EG(class_table), lc_name, name_length + 1, (void **) ce);
- retval = zend_hash_find(lookup_table, lc_name, name_length + 1, item);
free_alloca(lc_name);
return retval;
}
+ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***ce TSRMLS_DC)
+{
- return (zend_lookup_autoloadable (name, name_length, (void **)ce, EG(class_table), &EG(in_autoload_class), AUTOLOAD_CLASS
TSRMLS_CC));
+}
+ZEND_API int zend_lookup_function(char *name, int name_length, zend_function **function TSRMLS_DC)
+{
- return (zend_lookup_autoloadable (name, name_length, (void **)function, EG(function_table), &EG(in_autoload_function),
AUTOLOAD_FUNCTION TSRMLS_CC));
+}
ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC)
{
zval pv;
diff -ru php5-200411302330.orig/Zend/zend_globals.h php5-200411302330/Zend/zend_globals.h
--- php5-200411302330.orig/Zend/zend_globals.h 2004-11-04 01:30:19.000000000 +0000
+++ php5-200411302330/Zend/zend_globals.h 2004-12-01 05:05:49.000000000 +0000
@@ -191,7 +191,8 @@
int ticks_count;
zend_bool in_execution;
- HashTable *in_autoload;
- HashTable *in_autoload_class;
- HashTable *in_autoload_function;
zend_function *autoload_func;
zend_bool bailout_set;
zend_bool full_tables_cleanup;
diff -ru php5-200411302330.orig/Zend/zend_vm_def.h php5-200411302330/Zend/zend_vm_def.h
--- php5-200411302330.orig/Zend/zend_vm_def.h 2004-11-03 09:30:10.000000000 +0000
+++ php5-200411302330/Zend/zend_vm_def.h 2004-12-01 04:40:46.000000000 +0000
@@ -1660,7 +1660,7 @@
zend_op *opline = EX(opline);
zval *function_name;
zend_function *function;
- char *function_name_strval, *lcname;
- char *function_name_strval;
int function_name_strlen;
zend_free_op free_op2;
@@ -1682,13 +1682,10 @@
function_name_strlen = function_name->value.str.len;
}
- lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
- if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
-
efree(lcname);
- if (zend_lookup_function(function_name_strval, function_name_strlen, &function TSRMLS_CC)==FAILURE) {
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
}
-
efree(lcname);
FREE_OP2();EX(calling_scope) = function->common.scope;
diff -ru php5-200411302330.orig/Zend/zend_vm_execute.h php5-200411302330/Zend/zend_vm_execute.h
--- php5-200411302330.orig/Zend/zend_vm_execute.h 2004-11-03 09:30:11.000000000 +0000
+++ php5-200411302330/Zend/zend_vm_execute.h 2004-12-01 04:45:38.000000000 +0000
@@ -572,7 +572,7 @@
zend_op *opline = EX(opline);
zval *function_name;
zend_function *function; -
char *function_name_strval, *lcname;
- char *function_name_strval;
int function_name_strlen;
zend_free_op free_op2;
@@ -594,13 +594,10 @@
function_name_strlen = function_name->value.str.len;
}
- lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
- if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
-
efree(lcname);
- if (zend_lookup_function(function_name_strval, function_name_strlen, &function TSRMLS_CC)==FAILURE) {
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
}
-
efree(lcname);
;EX(calling_scope) = function->common.scope;
@@ -769,7 +766,7 @@
zend_op *opline = EX(opline);
zval *function_name;
zend_function *function; -
char *function_name_strval, *lcname;
- char *function_name_strval;
int function_name_strlen;
zend_free_op free_op2;
@@ -791,13 +788,10 @@
function_name_strlen = function_name->value.str.len;
}
- lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
- if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
-
efree(lcname);
- if (zend_lookup_function(function_name_strval, function_name_strlen, &function TSRMLS_CC)==FAILURE) {
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
}
-
efree(lcname);
zval_dtor(free_op2.var);EX(calling_scope) = function->common.scope;
@@ -924,7 +918,7 @@
zend_op *opline = EX(opline);
zval *function_name;
zend_function *function; -
char *function_name_strval, *lcname;
- char *function_name_strval;
int function_name_strlen;
zend_free_op free_op2;
@@ -946,13 +940,10 @@
function_name_strlen = function_name->value.str.len;
}
- lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
- if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
-
efree(lcname);
- if (zend_lookup_function(function_name_strval, function_name_strlen, &function TSRMLS_CC)==FAILURE) {
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
}
-
efree(lcname);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};EX(calling_scope) = function->common.scope;
@@ -1163,7 +1154,7 @@
zend_op *opline = EX(opline);
zval *function_name;
zend_function *function; -
char *function_name_strval, *lcname;
- char *function_name_strval;
int function_name_strlen;
zend_free_op free_op2;
@@ -1185,13 +1176,10 @@
function_name_strlen = function_name->value.str.len;
}
- lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
- if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
-
efree(lcname);
- if (zend_lookup_function(function_name_strval, function_name_strlen, &function TSRMLS_CC)==FAILURE) {
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
}
-
efree(lcname);
;EX(calling_scope) = function->common.scope;
@@ -29214,7 +29202,7 @@
zend_op *opline = EX(opline);
zval *function_name;
zend_function *function; -
char *function_name_strval, *lcname;
- char *function_name_strval;
int function_name_strlen;
zend_free_op free_op2;
@@ -29236,13 +29224,10 @@
function_name_strlen = function_name->value.str.len;
}
- lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
- if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
-
efree(lcname);
- if (zend_lookup_function(function_name_strval, function_name_strlen, &function TSRMLS_CC)==FAILURE) {
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
}
-
efree(lcname);
FREE_OP(free_op2);EX(calling_scope) = function->common.scope;