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 be NULL 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;
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php