ZEND_API void (*zend_execute_ex)(zend_execute_data *execute_data);
ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data, zval *return_value);
+ZEND_API zend_class_entry *(*zend_autoload)(zend_string *name, zend_string *lc_name);
/* true globals */
ZEND_API const zend_fcall_info empty_fcall_info = {0};
EG(class_table) = CG(class_table);
EG(in_autoload) = NULL;
- EG(autoload_func) = NULL;
EG(error_handling) = EH_NORMAL;
EG(flags) = EG_FLAGS_INITIAL;
ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string *key, uint32_t flags) /* {{{ */
{
zend_class_entry *ce = NULL;
- zval args[1], *zv;
- zval local_retval;
+ zval *zv;
zend_string *lc_name;
- zend_fcall_info fcall_info;
- zend_fcall_info_cache fcall_cache;
+ zend_string *autoload_name;
if (key) {
lc_name = key;
return ce;
}
- /* The compiler is not-reentrant. Make sure we __autoload() only during run-time
- * (doesn't impact functionality of __autoload()
- */
+ /* The compiler is not-reentrant. Make sure we autoload only during run-time. */
if ((flags & ZEND_FETCH_CLASS_NO_AUTOLOAD) || zend_is_compiling()) {
if (!key) {
zend_string_release_ex(lc_name, 0);
return NULL;
}
- if (!EG(autoload_func)) {
+ if (!zend_autoload) {
if (!key) {
zend_string_release_ex(lc_name, 0);
}
return NULL;
-
}
- /* Verify class name before passing it to __autoload() */
+ /* Verify class name before passing it to the autoloader. */
if (!key && strspn(ZSTR_VAL(name), "0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377\\") != ZSTR_LEN(name)) {
zend_string_release_ex(lc_name, 0);
return NULL;
return NULL;
}
- ZVAL_UNDEF(&local_retval);
-
if (ZSTR_VAL(name)[0] == '\\') {
- ZVAL_STRINGL(&args[0], ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
+ autoload_name = zend_string_init(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1, 0);
} else {
- ZVAL_STR_COPY(&args[0], name);
+ autoload_name = zend_string_copy(name);
}
- fcall_info.size = sizeof(fcall_info);
- ZVAL_STR_COPY(&fcall_info.function_name, EG(autoload_func)->common.function_name);
- fcall_info.retval = &local_retval;
- fcall_info.param_count = 1;
- fcall_info.params = args;
- fcall_info.object = NULL;
- fcall_info.no_separation = 1;
-
- fcall_cache.function_handler = EG(autoload_func);
- fcall_cache.called_scope = NULL;
- fcall_cache.object = NULL;
-
zend_exception_save();
- if ((zend_call_function(&fcall_info, &fcall_cache) == SUCCESS) && !EG(exception)) {
- ce = zend_hash_find_ptr(EG(class_table), lc_name);
- }
+ ce = zend_autoload(autoload_name, lc_name);
zend_exception_restore();
- zval_ptr_dtor(&args[0]);
- zval_ptr_dtor_str(&fcall_info.function_name);
-
+ zend_string_release_ex(autoload_name, 0);
zend_hash_del(EG(in_autoload), lc_name);
- zval_ptr_dtor(&local_retval);
-
if (!key) {
zend_string_release_ex(lc_name, 0);
}
#define SPL_DEFAULT_FILE_EXTENSIONS ".inc,.php"
-static zend_function *spl_autoload_fn = NULL;
-static zend_function *spl_autoload_call_fn = NULL;
-
/* {{{ PHP_GINIT_FUNCTION
*/
static PHP_GINIT_FUNCTION(spl)
{
- spl_globals->autoload_extensions = NULL;
- spl_globals->autoload_functions = NULL;
- spl_globals->autoload_running = 0;
+ spl_globals->autoload_extensions = NULL;
+ spl_globals->autoload_functions = NULL;
+ spl_globals->autoload_running = 0;
}
/* }}} */
efree(alfi);
}
-/* {{{ proto void spl_autoload_call(string class_name)
- Try all registered autoload function to load the requested class */
-PHP_FUNCTION(spl_autoload_call)
-{
- zend_string *class_name, *lc_name, *func_name;
- autoload_func_info *alfi;
- zval retval, params[1];
-
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &class_name) == FAILURE) {
- RETURN_THROWS();
+static zend_class_entry *spl_perform_autoload(zend_string *class_name, zend_string *lc_name) {
+ if (!SPL_G(autoload_functions)) {
+ return NULL;
}
+ HashPosition pos;
+ zend_ulong num_idx;
+ zend_function *func;
+ zend_fcall_info fci;
+ zend_fcall_info_cache fcic;
+ zval params[1];
+ zval retval;
+ zend_string *func_name;
+ zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data));
+ int l_autoload_running = SPL_G(autoload_running);
+
+ SPL_G(autoload_running) = 1;
+
+ fci.size = sizeof(fci);
+ fci.retval = &retval;
+ fci.param_count = 1;
+ fci.params = params;
+ fci.no_separation = 1;
ZVAL_STR(¶ms[0], class_name);
- if (SPL_G(autoload_functions)) {
- HashPosition pos;
- zend_ulong num_idx;
- zend_function *func;
- zend_fcall_info fci;
- zend_fcall_info_cache fcic;
- zend_class_entry *called_scope = zend_get_called_scope(execute_data);
- int l_autoload_running = SPL_G(autoload_running);
-
- SPL_G(autoload_running) = 1;
- lc_name = zend_string_tolower(class_name);
-
- fci.size = sizeof(fci);
- fci.retval = &retval;
- fci.param_count = 1;
- fci.params = params;
- fci.no_separation = 1;
-
- ZVAL_UNDEF(&fci.function_name); /* Unused */
-
- zend_hash_internal_pointer_reset_ex(SPL_G(autoload_functions), &pos);
- while (zend_hash_get_current_key_ex(SPL_G(autoload_functions), &func_name, &num_idx, &pos) == HASH_KEY_IS_STRING) {
- alfi = zend_hash_get_current_data_ptr_ex(SPL_G(autoload_functions), &pos);
- func = alfi->func_ptr;
- if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
- func = emalloc(sizeof(zend_op_array));
- memcpy(func, alfi->func_ptr, sizeof(zend_op_array));
- zend_string_addref(func->op_array.function_name);
- }
- ZVAL_UNDEF(&retval);
- fcic.function_handler = func;
- if (Z_ISUNDEF(alfi->obj)) {
- fci.object = NULL;
- fcic.object = NULL;
- if (alfi->ce &&
- (!called_scope ||
- !instanceof_function(called_scope, alfi->ce))) {
- fcic.called_scope = alfi->ce;
- } else {
- fcic.called_scope = called_scope;
- }
+ ZVAL_UNDEF(&fci.function_name); /* Unused */
+
+ zend_hash_internal_pointer_reset_ex(SPL_G(autoload_functions), &pos);
+ while (zend_hash_get_current_key_ex(SPL_G(autoload_functions), &func_name, &num_idx, &pos) == HASH_KEY_IS_STRING) {
+ autoload_func_info *alfi =
+ zend_hash_get_current_data_ptr_ex(SPL_G(autoload_functions), &pos);
+ func = alfi->func_ptr;
+ if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
+ func = emalloc(sizeof(zend_op_array));
+ memcpy(func, alfi->func_ptr, sizeof(zend_op_array));
+ zend_string_addref(func->op_array.function_name);
+ }
+ ZVAL_UNDEF(&retval);
+ fcic.function_handler = func;
+ if (Z_ISUNDEF(alfi->obj)) {
+ fci.object = NULL;
+ fcic.object = NULL;
+ if (alfi->ce &&
+ (!called_scope ||
+ !instanceof_function(called_scope, alfi->ce))) {
+ fcic.called_scope = alfi->ce;
} else {
- fci.object = Z_OBJ(alfi->obj);
- fcic.object = Z_OBJ(alfi->obj);
- fcic.called_scope = Z_OBJCE(alfi->obj);
+ fcic.called_scope = called_scope;
}
+ } else {
+ fci.object = Z_OBJ(alfi->obj);
+ fcic.object = Z_OBJ(alfi->obj);
+ fcic.called_scope = Z_OBJCE(alfi->obj);
+ }
- zend_call_function(&fci, &fcic);
- zval_ptr_dtor(&retval);
-
- if (EG(exception)) {
- break;
- }
+ zend_call_function(&fci, &fcic);
+ zval_ptr_dtor(&retval);
- if (pos + 1 == SPL_G(autoload_functions)->nNumUsed ||
- zend_hash_exists(EG(class_table), lc_name)) {
- break;
- }
- zend_hash_move_forward_ex(SPL_G(autoload_functions), &pos);
+ if (EG(exception)) {
+ break;
}
- zend_string_release_ex(lc_name, 0);
- SPL_G(autoload_running) = l_autoload_running;
- } else {
- /* do not use or overwrite &EG(autoload_func) here */
- zend_fcall_info fcall_info;
- zend_fcall_info_cache fcall_cache;
- ZVAL_UNDEF(&retval);
+ zend_class_entry *ce = zend_hash_find_ptr(EG(class_table), lc_name);
+ if (ce) {
+ SPL_G(autoload_running) = l_autoload_running;
+ return ce;
+ }
- fcall_info.size = sizeof(fcall_info);
- ZVAL_UNDEF(&fcall_info.function_name);
- fcall_info.retval = &retval;
- fcall_info.param_count = 1;
- fcall_info.params = params;
- fcall_info.object = NULL;
- fcall_info.no_separation = 1;
+ zend_hash_move_forward_ex(SPL_G(autoload_functions), &pos);
+ }
+ SPL_G(autoload_running) = l_autoload_running;
+ return NULL;
+}
- fcall_cache.function_handler = spl_autoload_fn;
- fcall_cache.called_scope = NULL;
- fcall_cache.object = NULL;
+/* {{{ proto void spl_autoload_call(string class_name)
+ Try all registered autoload function to load the requested class */
+PHP_FUNCTION(spl_autoload_call)
+{
+ zend_string *class_name;
- zend_call_function(&fcall_info, &fcall_cache);
- zval_ptr_dtor(&retval);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &class_name) == FAILURE) {
+ RETURN_THROWS();
}
+
+ zend_string *lc_name = zend_string_tolower(class_name);
+ spl_perform_autoload(class_name, lc_name);
+ zend_string_release(lc_name);
} /* }}} */
#define HT_MOVE_TAIL_TO_HEAD(ht) \
zend_string *lc_name;
zend_bool do_throw = 1;
zend_bool prepend = 0;
- zend_function *spl_func_ptr;
autoload_func_info alfi;
zend_object *obj_ptr;
zend_fcall_info fci = {0};
"spl_autoload_register() will always throw");
}
+ if (!SPL_G(autoload_functions)) {
+ ALLOC_HASHTABLE(SPL_G(autoload_functions));
+ zend_hash_init(SPL_G(autoload_functions), 1, NULL, autoload_func_info_dtor, 0);
+ }
+
/* If first arg is not null */
if (ZEND_FCI_INITIALIZED(fci)) {
alfi.ce = fcc.calling_scope;
}
zend_string_release(func_name);
- if (SPL_G(autoload_functions) && zend_hash_exists(SPL_G(autoload_functions), lc_name)) {
+ if (zend_hash_exists(SPL_G(autoload_functions), lc_name)) {
if (!Z_ISUNDEF(alfi.closure)) {
Z_DELREF_P(&alfi.closure);
}
ZVAL_UNDEF(&alfi.obj);
}
- if (!SPL_G(autoload_functions)) {
- ALLOC_HASHTABLE(SPL_G(autoload_functions));
- zend_hash_init(SPL_G(autoload_functions), 1, NULL, autoload_func_info_dtor, 0);
- }
-
- spl_func_ptr = spl_autoload_fn;
-
- if (EG(autoload_func) == spl_func_ptr) { /* registered already, so we insert that first */
- autoload_func_info spl_alfi;
-
- spl_alfi.func_ptr = spl_func_ptr;
- ZVAL_UNDEF(&spl_alfi.obj);
- ZVAL_UNDEF(&spl_alfi.closure);
- spl_alfi.ce = NULL;
- zend_hash_add_mem(SPL_G(autoload_functions), spl_autoload_fn->common.function_name,
- &spl_alfi, sizeof(autoload_func_info));
- if (prepend && SPL_G(autoload_functions)->nNumOfElements > 1) {
- /* Move the newly created element to the head of the hashtable */
- HT_MOVE_TAIL_TO_HEAD(SPL_G(autoload_functions));
- }
- }
-
if (UNEXPECTED(alfi.func_ptr == &EG(trampoline))) {
zend_function *copy = emalloc(sizeof(zend_op_array));
}
skip:
zend_string_release_ex(lc_name, 0);
- }
-
- if (SPL_G(autoload_functions)) {
- EG(autoload_func) = spl_autoload_call_fn;
} else {
- EG(autoload_func) = spl_autoload_fn;
+ autoload_func_info spl_alfi;
+ spl_alfi.func_ptr = zend_hash_str_find_ptr(
+ CG(function_table), "spl_autoload", sizeof("spl_autoload") - 1);
+ ZVAL_UNDEF(&spl_alfi.obj);
+ ZVAL_UNDEF(&spl_alfi.closure);
+ spl_alfi.ce = NULL;
+ zend_hash_add_mem(SPL_G(autoload_functions), spl_alfi.func_ptr->common.function_name,
+ &spl_alfi, sizeof(autoload_func_info));
+ if (prepend && SPL_G(autoload_functions)->nNumOfElements > 1) {
+ /* Move the newly created element to the head of the hashtable */
+ HT_MOVE_TAIL_TO_HEAD(SPL_G(autoload_functions));
+ }
}
RETURN_TRUE;
zend_string *lc_name;
zval *zcallable;
int success = FAILURE;
- zend_function *spl_func_ptr;
zend_object *obj_ptr;
zend_fcall_info_cache fcc;
zend_string_release_ex(func_name, 0);
if (SPL_G(autoload_functions)) {
- if (zend_string_equals(lc_name, spl_autoload_call_fn->common.function_name)) {
+ if (zend_string_equals_literal(lc_name, "spl_autoload_call")) {
/* remove all */
if (!SPL_G(autoload_running)) {
zend_hash_destroy(SPL_G(autoload_functions));
FREE_HASHTABLE(SPL_G(autoload_functions));
SPL_G(autoload_functions) = NULL;
- EG(autoload_func) = NULL;
} else {
zend_hash_clean(SPL_G(autoload_functions));
}
success = zend_hash_del(SPL_G(autoload_functions), lc_name);
}
}
- } else if (zend_string_equals(lc_name, spl_autoload_fn->common.function_name)) {
- /* register single spl_autoload() */
- spl_func_ptr = spl_autoload_fn;
-
- if (EG(autoload_func) == spl_func_ptr) {
- success = SUCCESS;
- EG(autoload_func) = NULL;
- }
}
zend_string_release_ex(lc_name, 0);
Return all registered autoloader functions */
PHP_FUNCTION(spl_autoload_functions)
{
- zend_function *fptr;
autoload_func_info *alfi;
if (zend_parse_parameters_none() == FAILURE) {
RETURN_THROWS();
}
- if (!EG(autoload_func)) {
- RETURN_FALSE;
- }
-
- fptr = spl_autoload_call_fn;
-
- if (EG(autoload_func) == fptr) {
- array_init(return_value);
+ array_init(return_value);
+ if (SPL_G(autoload_functions)) {
ZEND_HASH_FOREACH_PTR(SPL_G(autoload_functions), alfi) {
if (!Z_ISUNDEF(alfi->closure)) {
Z_ADDREF(alfi->closure);
add_next_index_str(return_value, zend_string_copy(alfi->func_ptr->common.function_name));
}
} ZEND_HASH_FOREACH_END();
- return;
}
-
- array_init(return_value);
- add_next_index_str(return_value, zend_string_copy(EG(autoload_func)->common.function_name));
} /* }}} */
/* {{{ proto string spl_object_hash(object obj)
*/
PHP_MINIT_FUNCTION(spl)
{
+ zend_autoload = spl_perform_autoload;
+
PHP_MINIT(spl_exceptions)(INIT_FUNC_ARGS_PASSTHRU);
PHP_MINIT(spl_iterators)(INIT_FUNC_ARGS_PASSTHRU);
PHP_MINIT(spl_array)(INIT_FUNC_ARGS_PASSTHRU);
PHP_MINIT(spl_fixedarray)(INIT_FUNC_ARGS_PASSTHRU);
PHP_MINIT(spl_observer)(INIT_FUNC_ARGS_PASSTHRU);
- spl_autoload_fn = zend_hash_str_find_ptr(CG(function_table), "spl_autoload", sizeof("spl_autoload") - 1);
- spl_autoload_call_fn = zend_hash_str_find_ptr(CG(function_table), "spl_autoload_call", sizeof("spl_autoload_call") - 1);
- ZEND_ASSERT(spl_autoload_fn != NULL && spl_autoload_call_fn != NULL);
-
return SUCCESS;
}
/* }}} */