Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:13965 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 28333 invoked by uid 1010); 1 Dec 2004 06:25:54 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 28280 invoked from network); 1 Dec 2004 06:25:52 -0000 Received: from unknown (HELO worldnetweb.com) (209.135.140.102) by pb1.pair.com with SMTP; 1 Dec 2004 06:25:52 -0000 Received: from damagegqsaogpp (unknown [217.30.221.203]) by worldnetweb.com (Postfix) with ESMTP id DBB3B894783 for ; Wed, 1 Dec 2004 00:25:33 -0600 (CST) Sender: "Vesselin Atanasov" To: Date: Wed, 1 Dec 2004 08:27:14 +0200 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_0003_01C4D77F.90F63710" X-Mailer: Microsoft Office Outlook, Build 11.0.5510 Thread-Index: AcTXbswKFTFWT5B0R/mq/vPKuuZgwQ== X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1106 Message-ID: <20041201062533.DBB3B894783@worldnetweb.com> Subject: [PATCH] Autoloading of functions From: vma1@abv.bg ("Vesselin Atanasov") ------=_NextPart_000_0003_01C4D77F.90F63710 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 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; ------=_NextPart_000_0003_01C4D77F.90F63710--