// main实现在文件 php-5.6.26\sapi\cgi\cgi_main.c
int main(int argc, char *argv[])
{
....
cgi_sapi_module->startup(){
// php_cgi_startup实现在文件 php-5.6.26\sapi\cgi\cgi_main.c
static int php_cgi_startup(sapi_module_struct *sapi_module)
{
// php_module_startup实现在文件 php-5.6.26\main\main.c
if (php_module_startup(sapi_module, &cgi_module_entry, 1){
....
// 启动zend引擎(创建“全局函数表”、“全局类表”、“全局常量表”、“模块注册表”......)
zend_startup(&zuf, NULL TSRMLS_CC); // !!!!
...
// 注册常量
REGISTER_MAIN_STRINGL_CONSTANT("PHP_VERSION", PHP_VERSION, sizeof(PHP_VERSION)-1, CONST_PERSISTENT | CONST_CS); // 注册到 EG(zend_constants)
REGISTER_MAIN_LONG_CONSTANT("PHP_MAJOR_VERSION", PHP_MAJOR_VERSION, CONST_PERSISTENT | CONST_CS);
REGISTER_MAIN_LONG_CONSTANT("PHP_MINOR_VERSION", PHP_MINOR_VERSION, CONST_PERSISTENT | CONST_CS);
REGISTER_MAIN_LONG_CONSTANT("PHP_RELEASE_VERSION", PHP_RELEASE_VERSION, CONST_PERSISTENT | CONST_CS);
REGISTER_MAIN_STRINGL_CONSTANT("PHP_EXTRA_VERSION", PHP_EXTRA_VERSION, sizeof(PHP_EXTRA_VERSION) - 1, CONST_PERSISTENT | CONST_CS);
REGISTER_MAIN_LONG_CONSTANT("PHP_VERSION_ID", PHP_VERSION_ID, CONST_PERSISTENT | CONST_CS);
...
php_binary_init(TSRMLS_C); // 执行文件的地址放入 PG(php_binary) = sapi_module.executable_location
...
php_output_register_constants(TSRMLS_C); // 注册常量 PHP_OUTPUT_HANDLER_START 等...
php_rfc1867_register_constants(TSRMLS_C); // 注册常量 UPLOAD_ERR_OK 等...
/* this will read in php.ini, set up the configuration parameters,
load zend extensions and register php function extensions
to be loaded later */
if (php_init_config(TSRMLS_C) == FAILURE) { // !!!! 解析 php.ini 文件,加载zend扩展
return FAILURE;
}
/* Register PHP core ini entries */
REGISTER_INI_ENTRIES(); // 设置php核心的ini配置 zend_register_ini_entries(ini_entries, module_number TSRMLS_CC)
/* Register Zend ini entries */
zend_register_standard_ini_entries(TSRMLS_C); // 设置zend的ini的配置
....
php_startup_auto_globals(TSRMLS_C); // 注册"_GET"、"_POST"、"_COOKIE"、"_SERVER"的处理函数到CG(auto_globals)
zend_set_utility_values(&zuv);
php_startup_sapi_content_types(TSRMLS_C); // 设置sapi_module.default_post_reader sapi_module.xxx 的值
/* startup extensions statically compiled in */
// php_register_internal_extensions php_register_extensions
if (php_register_internal_extensions_func(TSRMLS_C) == FAILURE) { // 迭代“内建模块列表”,添加内建模块信息到“模块注册表module_registry”、注册“模块的函数”到 CG(function_table)
php_printf("Unable to start builtin modules\n");
return FAILURE;
}
/* start additional PHP extensions */
php_register_extensions_bc(additional_modules, num_additional_modules TSRMLS_CC); // 添加additional_modules模块信息到“模块注册表module_registry”、注册“模块的函数”到 CG(function_table)
/* load and startup extensions compiled as shared objects (aka DLLs)
as requested by php.ini entries
theese are loaded after initialization of internal extensions
as extensions *might* rely on things from ext/standard
which is always an internal extension and to be initialized
ahead of all other internals
*/
// php_ini_register_extensions实现在文件 php-5.6.26\main\php_ini.c
php_ini_register_extensions(TSRMLS_C); // 1、加载引擎的扩展模块,并把扩展信息添加到链表 zend_extensions 中(php.ini中以zend_extension开头的配置,如zend_extension=test.so) 2、加载extension_dir用户扩展模块,并把模块信息添加到模块注册表module_registry中 (php.ini中以extension开头的配置,如extension=test.so)
{
// 加载引擎的扩展模块,并把扩展信息添加到链表 zend_extensions 中(php.ini中以zend_extension开头的配置,如zend_extension=test.so)
zend_llist_apply(&extension_lists.engine, php_load_zend_extension_cb TSRMLS_CC);
{
// php_ini_register_extensions实现在文件 php-5.6.26\main\php_ini.c
static void php_load_zend_extension_cb(void *arg TSRMLS_DC)
{
char *filename = *((char **) arg); // 扩展名
int length = strlen(filename);
if (IS_ABSOLUTE_PATH(filename, length)) {
// zend_load_extension实现在文件 php-5.6.26\Zend\zend_extensions.c
zend_load_extension(filename); // 把扩展添加到链表zend_extensions中
{
int zend_load_extension(const char *path)
{
#if ZEND_EXTENSIONS_SUPPORT
DL_HANDLE handle;
zend_extension *new_extension;
zend_extension_version_info *extension_version_info;
handle = DL_LOAD(path); // 加载动态链接库
if (!handle) {
#ifndef ZEND_WIN32
fprintf(stderr, "Failed loading %s: %s\n", path, DL_ERROR());
/* See http://support.microsoft.com/kb/190351 */
#ifdef PHP_WIN32
fflush(stderr);
#endif
#else
fprintf(stderr, "Failed loading %s\n", path);
#endif
return FAILURE;
}
extension_version_info = (zend_extension_version_info *) DL_FETCH_SYMBOL(handle, "extension_version_info"); // 获取扩展版本信息
if (!extension_version_info) {
extension_version_info = (zend_extension_version_info *) DL_FETCH_SYMBOL(handle, "_extension_version_info");
}
new_extension = (zend_extension *) DL_FETCH_SYMBOL(handle, "zend_extension_entry"); // !!! 扩展的固定入口
if (!new_extension) {
new_extension = (zend_extension *) DL_FETCH_SYMBOL(handle, "_zend_extension_entry");
}
if (!extension_version_info || !new_extension) {
fprintf(stderr, "%s doesn't appear to be a valid Zend extension\n", path);
/* See http://support.microsoft.com/kb/190351 */
#ifdef PHP_WIN32
fflush(stderr);
#endif
DL_UNLOAD(handle);
return FAILURE;
}
/* allow extension to proclaim compatibility with any Zend version */ // 扩展的版本信息
if (extension_version_info->zend_extension_api_no != ZEND_EXTENSION_API_NO &&(!new_extension->api_no_check || new_extension->api_no_check(ZEND_EXTENSION_API_NO) != SUCCESS)) {
if (extension_version_info->zend_extension_api_no > ZEND_EXTENSION_API_NO) {
fprintf(stderr, "%s requires Zend Engine API version %d.\n"
"The Zend Engine API version %d which is installed, is outdated.\n\n",
new_extension->name,
extension_version_info->zend_extension_api_no,
ZEND_EXTENSION_API_NO);
/* See http://support.microsoft.com/kb/190351 */
#ifdef PHP_WIN32
fflush(stderr);
#endif
DL_UNLOAD(handle);
return FAILURE;
} else if (extension_version_info->zend_extension_api_no < ZEND_EXTENSION_API_NO) {
fprintf(stderr, "%s requires Zend Engine API version %d.\n"
"The Zend Engine API version %d which is installed, is newer.\n"
"Contact %s at %s for a later version of %s.\n\n",
new_extension->name, // 扩展名称
extension_version_info->zend_extension_api_no,
ZEND_EXTENSION_API_NO,
new_extension->author, // 扩展作者
new_extension->URL, // 扩展地址
new_extension->name);
/* See http://support.microsoft.com/kb/190351 */
#ifdef PHP_WIN32
fflush(stderr);
#endif
DL_UNLOAD(handle);
return FAILURE;
}
} else if (strcmp(ZEND_EXTENSION_BUILD_ID, extension_version_info->build_id) &&
(!new_extension->build_id_check || new_extension->build_id_check(ZEND_EXTENSION_BUILD_ID) != SUCCESS)) {
fprintf(stderr, "Cannot load %s - it was built with configuration %s, whereas running engine is %s\n",
new_extension->name, extension_version_info->build_id, ZEND_EXTENSION_BUILD_ID);
/* See http://support.microsoft.com/kb/190351 */
#ifdef PHP_WIN32
fflush(stderr);
#endif
DL_UNLOAD(handle);
return FAILURE;
} else if (zend_get_extension(new_extension->name)) {
fprintf(stderr, "Cannot load %s - extension already loaded\n", new_extension->name);
/* See http://support.microsoft.com/kb/190351 */
#ifdef PHP_WIN32
fflush(stderr);
#endif
DL_UNLOAD(handle);
return FAILURE;
}
return zend_register_extension(new_extension, handle); // !!!注册扩展信息,并迭代执行“类似zend_extension=test.so模块”的 message_handler 方法
#else
fprintf(stderr, "Extensions are not supported on this platform.\n");
/* See http://support.microsoft.com/kb/190351 */
#ifdef PHP_WIN32
fflush(stderr);
#endif
return FAILURE;
#endif
}
}
} else {
char *libpath;
char *extension_dir = INI_STR("extension_dir"); // 扩展目录
int extension_dir_len = strlen(extension_dir);
if (IS_SLASH(extension_dir[extension_dir_len-1])) {
spprintf(&libpath, 0, "%s%s", extension_dir, filename);
} else {
spprintf(&libpath, 0, "%s%c%s", extension_dir, DEFAULT_SLASH, filename);
}
zend_load_extension(libpath);
efree(libpath);
}
}
}
// 加载extension_dir用户扩展模块,并把模块信息添加到模块注册表module_registry中 (php.ini中以extension开头的配置,如extension=test.so)
zend_llist_apply(&extension_lists.functions, php_load_php_extension_cb TSRMLS_CC);
{
// php_load_php_extension_cb 实现在文件 php-5.6.26\main\php_ini.c
static void php_load_php_extension_cb(void *arg TSRMLS_DC)
{
#ifdef HAVE_LIBDL
// php_load_extension 实现在文件 php-5.6.26\ext\standard\dl.c
php_load_extension(*((char **) arg), MODULE_PERSISTENT, 0 TSRMLS_CC);
#endif
{
void *handle;
char *libpath;
zend_module_entry *module_entry;
zend_module_entry *(*get_module)(void);
int error_type;
char *extension_dir;
if (type == MODULE_PERSISTENT) {
extension_dir = INI_STR("extension_dir"); // 扩展目录
} else {
extension_dir = PG(extension_dir);
}
if (type == MODULE_TEMPORARY) {
error_type = E_WARNING;
} else {
error_type = E_CORE_WARNING;
}
/* Check if passed filename contains directory separators */
if (strchr(filename, '/') != NULL || strchr(filename, DEFAULT_SLASH) != NULL) {
/* Passing modules with full path is not supported for dynamically loaded extensions */
if (type == MODULE_TEMPORARY) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Temporary module name should contain only filename");
return FAILURE;
}
libpath = estrdup(filename);
} else if (extension_dir && extension_dir[0]) {
int extension_dir_len = strlen(extension_dir);
if (IS_SLASH(extension_dir[extension_dir_len-1])) {
spprintf(&libpath, 0, "%s%s", extension_dir, filename); /* SAFE */
} else {
spprintf(&libpath, 0, "%s%c%s", extension_dir, DEFAULT_SLASH, filename); /* SAFE */
}
} else {
return FAILURE; /* Not full path given or extension_dir is not set */
}
/* load dynamic symbol */
handle = DL_LOAD(libpath); // 加载test.so文件
if (!handle) {
#if PHP_WIN32
char *err = GET_DL_ERROR();
if (err && (*err != "")) {
php_error_docref(NULL TSRMLS_CC, error_type, "Unable to load dynamic library '%s' - %s", libpath, err);
LocalFree(err);
} else {
php_error_docref(NULL TSRMLS_CC, error_type, "Unable to load dynamic library '%s' - %s", libpath, "Unknown reason");
}
#else
php_error_docref(NULL TSRMLS_CC, error_type, "Unable to load dynamic library '%s' - %s", libpath, GET_DL_ERROR());
GET_DL_ERROR(); /* free the buffer storing the error */
#endif
efree(libpath);
return FAILURE;
}
efree(libpath);
get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, "get_module"); // 模块的固定入口
/* Some OS prepend _ to symbol names while their dynamic linker
* does not do that automatically. Thus we check manually for
* _get_module. */
if (!get_module) {
get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, "_get_module");
}
if (!get_module) {
if (DL_FETCH_SYMBOL(handle, "zend_extension_entry") || DL_FETCH_SYMBOL(handle, "_zend_extension_entry")) {
DL_UNLOAD(handle);
php_error_docref(NULL TSRMLS_CC, error_type, "Invalid library (appears to be a Zend Extension, try loading using zend_extension=%s from php.ini)", filename);
return FAILURE;
}
DL_UNLOAD(handle);
php_error_docref(NULL TSRMLS_CC, error_type, "Invalid library (maybe not a PHP library) '%s'", filename);
return FAILURE;
}
module_entry = get_module(); // 取得模块信息
if (module_entry->zend_api != ZEND_MODULE_API_NO) {
/* Check for pre-4.1.0 module which has a slightly different module_entry structure :( */
struct pre_4_1_0_module_entry {
char *name;
zend_function_entry *functions;
int (*module_startup_func)(INIT_FUNC_ARGS);
int (*module_shutdown_func)(SHUTDOWN_FUNC_ARGS);
int (*request_startup_func)(INIT_FUNC_ARGS);
int (*request_shutdown_func)(SHUTDOWN_FUNC_ARGS);
void (*info_func)(ZEND_MODULE_INFO_FUNC_ARGS);
int (*global_startup_func)(void);
int (*global_shutdown_func)(void);
int globals_id;
int module_started;
unsigned char type;
void *handle;
int module_number;
unsigned char zend_debug;
unsigned char zts;
unsigned int zend_api;
};
const char *name;
int zend_api;
if ((((struct pre_4_1_0_module_entry *)module_entry)->zend_api > 20000000) &&
(((struct pre_4_1_0_module_entry *)module_entry)->zend_api < 20010901)
) {
name = ((struct pre_4_1_0_module_entry *)module_entry)->name;
zend_api = ((struct pre_4_1_0_module_entry *)module_entry)->zend_api;
} else {
name = module_entry->name;
zend_api = module_entry->zend_api;
}
php_error_docref(NULL TSRMLS_CC, error_type,
"%s: Unable to initialize module\n"
"Module compiled with module API=%d\n"
"PHP compiled with module API=%d\n"
"These options need to match\n",
name, zend_api, ZEND_MODULE_API_NO);
DL_UNLOAD(handle);
return FAILURE;
}
if(strcmp(module_entry->build_id, ZEND_MODULE_BUILD_ID)) {
php_error_docref(NULL TSRMLS_CC, error_type,
"%s: Unable to initialize module\n"
"Module compiled with build ID=%s\n"
"PHP compiled with build ID=%s\n"
"These options need to match\n",
module_entry->name, module_entry->build_id, ZEND_MODULE_BUILD_ID);
DL_UNLOAD(handle);
return FAILURE;
}
module_entry->type = type;
module_entry->module_number = zend_next_free_module();
module_entry->handle = handle;
if ((module_entry = zend_register_module_ex(module_entry TSRMLS_CC)){
// zend_register_module_ex 实现在文件 php-5.6.26\Zend\zend_API.c
ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module TSRMLS_DC) /* {{{ */
{
int name_len;
char *lcname;
zend_module_entry *module_ptr;
if (!module) {
return NULL;
}
#if 0
zend_printf("%s: Registering module %d\n", module->name, module->module_number);
#endif
/* Check module dependencies */
if (module->deps) { // 模块依赖
const zend_module_dep *dep = module->deps;
while (dep->name) { // 依赖名称
if (dep->type == MODULE_DEP_CONFLICTS) {
name_len = strlen(dep->name);
lcname = zend_str_tolower_dup(dep->name, name_len);
if (zend_hash_exists(&module_registry, lcname, name_len+1)) { // 模块是否已经注册
efree(lcname);
/* TODO: Check version relationship */
zend_error(E_CORE_WARNING, "Cannot load module '%s' because conflicting module '%s' is already loaded", module->name, dep->name);
return NULL;
}
efree(lcname);
}
++dep;
}
}
name_len = strlen(module->name);
lcname = zend_str_tolower_dup(module->name, name_len);
if (zend_hash_add(&module_registry, lcname, name_len+1, (void *)module, sizeof(zend_module_entry), (void**)&module_ptr)==FAILURE) { // 添加模块信息到“模块注册表module_registry”
zend_error(E_CORE_WARNING, "Module '%s' already loaded", module->name);
efree(lcname);
return NULL;
}
efree(lcname);
module = module_ptr;
EG(current_module) = module; // 当前模块
// 注册扩展模块的函数
if (module->functions && zend_register_functions(NULL, module->functions, NULL, module->type TSRMLS_CC){
ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC) /* {{{ */
{
const zend_function_entry *ptr = functions; // 要注册的“模块的函数列表”
zend_function function, *reg_function; // zend_function联合体
zend_internal_function *internal_function = (zend_internal_function *)&function; // internal_function描述扩展模块中每个函数的信息
int count=0, unload=0;
HashTable *target_function_table = function_table;
int error_type;
zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL, *__callstatic = NULL, *__tostring = NULL, *__debugInfo = NULL;
const char *lowercase_name;
int fname_len;
const char *lc_class_name = NULL;
int class_name_len = 0;
zend_ulong hash;
if (type==MODULE_PERSISTENT) {
error_type = E_CORE_WARNING;
} else {
error_type = E_WARNING;
}
if (!target_function_table) { // 如果没有指定target_function_table,那么默认填充到CG(v)
target_function_table = CG(function_table); // !!!
}
internal_function->type = ZEND_INTERNAL_FUNCTION; // 函数类型
internal_function->module = EG(current_module); // 所属模块
if (scope) {
class_name_len = strlen(scope->name); // 类名
if ((lc_class_name = zend_memrchr(scope->name, '\\', class_name_len))) {
++lc_class_name;
class_name_len -= (lc_class_name - scope->name);
lc_class_name = zend_str_tolower_dup(lc_class_name, class_name_len);
} else {
lc_class_name = zend_str_tolower_dup(scope->name, class_name_len);
}
}
while (ptr->fname) { // 函数名称
internal_function->handler = ptr->handler; // 函数指针,等价function->handler = ptr->handler;
internal_function->function_name = (char*)ptr->fname; // 函数名
internal_function->scope = scope; // 函数的作用域
internal_function->prototype = NULL;
if (ptr->flags) {
if (!(ptr->flags & ZEND_ACC_PPP_MASK)) {
if (ptr->flags != ZEND_ACC_DEPRECATED || scope) {
zend_error(error_type, "Invalid access level for %s%s%s() - access must be exactly one of public, protected or private", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
}
internal_function->fn_flags = ZEND_ACC_PUBLIC | ptr->flags;
} else {
internal_function->fn_flags = ptr->flags;
}
} else {
internal_function->fn_flags = ZEND_ACC_PUBLIC;
}
if (ptr->arg_info) { // 函数的参数信息
zend_internal_function_info *info = (zend_internal_function_info*)ptr->arg_info;
internal_function->arg_info = (zend_arg_info*)ptr->arg_info+1;
internal_function->num_args = ptr->num_args;
/* Currently you cannot denote that the function can accept less arguments than num_args */
if (info->required_num_args == -1) {
internal_function->required_num_args = ptr->num_args;
} else {
internal_function->required_num_args = info->required_num_args;
}
if (info->return_reference) {
internal_function->fn_flags |= ZEND_ACC_RETURN_REFERENCE;
}
if (ptr->arg_info[ptr->num_args].is_variadic) {
internal_function->fn_flags |= ZEND_ACC_VARIADIC;
}
} else {
internal_function->arg_info = NULL;
internal_function->num_args = 0;
internal_function->required_num_args = 0;
}
if (ptr->flags & ZEND_ACC_ABSTRACT) {
if (scope) {
/* This is a class that must be abstract itself. Here we set the check info. */
scope->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
if (!(scope->ce_flags & ZEND_ACC_INTERFACE)) {
/* Since the class is not an interface it needs to be declared as a abstract class. */
/* Since here we are handling internal functions only we can add the keyword flag. */
/* This time we set the flag for the keyword 'abstract'. */
scope->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
}
}
if (ptr->flags & ZEND_ACC_STATIC && (!scope || !(scope->ce_flags & ZEND_ACC_INTERFACE))) {
zend_error(error_type, "Static function %s%s%s() cannot be abstract", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
}
} else {
if (scope && (scope->ce_flags & ZEND_ACC_INTERFACE)) {
efree((char*)lc_class_name);
zend_error(error_type, "Interface %s cannot contain non abstract method %s()", scope->name, ptr->fname);
return FAILURE;
}
if (!internal_function->handler) {
if (scope) {
efree((char*)lc_class_name);
}
zend_error(error_type, "Method %s%s%s() cannot be a NULL function", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
zend_unregister_functions(functions, count, target_function_table TSRMLS_CC);
return FAILURE;
}
}
fname_len = strlen(ptr->fname); // 函数名称
lowercase_name = zend_new_interned_string(zend_str_tolower_dup(ptr->fname, fname_len), fname_len + 1, 1 TSRMLS_CC);
hash = str_hash(lowercase_name, fname_len); // 生成hash值
// 注册函数到HashTable 类型的CG(function_table)中
if (zend_hash_quick_add(target_function_table, lowercase_name, fname_len+1, hash, &function, sizeof(zend_function), (void**)®_function) == FAILURE) {
unload=1;
str_efree(lowercase_name);
break;
}
/* If types of arguments have to be checked */
if (reg_function->common.arg_info && reg_function->common.num_args) {
int i;
for (i = 0; i < reg_function->common.num_args; i++) {
if (reg_function->common.arg_info[i].class_name ||
reg_function->common.arg_info[i].type_hint) {
reg_function->common.fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
break;
}
}
}
if (scope) {
/* Look for ctor, dtor, clone
* If it's an old-style constructor, store it only if we don't have
* a constructor already.
*/
if ((fname_len == class_name_len) && !ctor && !memcmp(lowercase_name, lc_class_name, class_name_len+1)) {
ctor = reg_function; // 函数名是"类名"
} else if ((fname_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME) - 1)) {
ctor = reg_function; // 函数名是"__construct"
} else if ((fname_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME) - 1)) {
dtor = reg_function; // 函数名是"__destruct"
if (internal_function->num_args) {
zend_error(error_type, "Destructor %s::%s() cannot take arguments", scope->name, ptr->fname);
}
} else if ((fname_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME) - 1)) {
clone = reg_function; // 函数名是"__clone"
} else if ((fname_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME) - 1)) {
__call = reg_function;
} else if ((fname_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME) - 1)) {
__callstatic = reg_function;
} else if ((fname_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME) - 1)) {
__tostring = reg_function;
} else if ((fname_len == sizeof(ZEND_GET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME) - 1)) {
__get = reg_function;
} else if ((fname_len == sizeof(ZEND_SET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME) - 1)) {
__set = reg_function;
} else if ((fname_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME) - 1)) {
__unset = reg_function;
} else if ((fname_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME) - 1)) {
__isset = reg_function;
} else if ((fname_len == sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_DEBUGINFO_FUNC_NAME, sizeof(ZEND_DEBUGINFO_FUNC_NAME) - 1)) {
__debugInfo = reg_function;
} else {
reg_function = NULL;
}
if (reg_function) {
zend_check_magic_method_implementation(scope, reg_function, error_type TSRMLS_CC);
}
}
ptr++;
count++;
str_efree(lowercase_name);
}
if (unload) { /* before unloading, display all remaining bad function in the module */
if (scope) {
efree((char*)lc_class_name);
}
while (ptr->fname) {
fname_len = strlen(ptr->fname);
lowercase_name = zend_str_tolower_dup(ptr->fname, fname_len);
if (zend_hash_exists(target_function_table, lowercase_name, fname_len+1)) {
zend_error(error_type, "Function registration failed - duplicate name - %s%s%s", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
}
efree((char*)lowercase_name);
ptr++;
}
zend_unregister_functions(functions, count, target_function_table TSRMLS_CC);
return FAILURE;
}
if (scope) { // 有指定作用域
scope->constructor = ctor; // 构造函数
scope->destructor = dtor; // 析构函数
scope->clone = clone; // clone函数
scope->__call = __call; // __call函数
scope->__callstatic = __callstatic;
scope->__tostring = __tostring;
scope->__get = __get;
scope->__set = __set;
scope->__unset = __unset;
scope->__isset = __isset;
scope->__debugInfo = __debugInfo;
if (ctor) {
ctor->common.fn_flags |= ZEND_ACC_CTOR;
if (ctor->common.fn_flags & ZEND_ACC_STATIC) {
zend_error(error_type, "Constructor %s::%s() cannot be static", scope->name, ctor->common.function_name);
}
ctor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
}
if (dtor) {
dtor->common.fn_flags |= ZEND_ACC_DTOR;
if (dtor->common.fn_flags & ZEND_ACC_STATIC) {
zend_error(error_type, "Destructor %s::%s() cannot be static", scope->name, dtor->common.function_name);
}
dtor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
}
if (clone) {
clone->common.fn_flags |= ZEND_ACC_CLONE;
if (clone->common.fn_flags & ZEND_ACC_STATIC) {
zend_error(error_type, "Constructor %s::%s() cannot be static", scope->name, clone->common.function_name);
}
clone->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
}
if (__call) {
if (__call->common.fn_flags & ZEND_ACC_STATIC) {
zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __call->common.function_name);
}
__call->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
}
if (__callstatic) {
if (!(__callstatic->common.fn_flags & ZEND_ACC_STATIC)) {
zend_error(error_type, "Method %s::%s() must be static", scope->name, __callstatic->common.function_name);
}
__callstatic->common.fn_flags |= ZEND_ACC_STATIC;
}
if (__tostring) {
if (__tostring->common.fn_flags & ZEND_ACC_STATIC) {
zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __tostring->common.function_name);
}
__tostring->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
}
if (__get) {
if (__get->common.fn_flags & ZEND_ACC_STATIC) {
zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __get->common.function_name);
}
__get->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
}
if (__set) {
if (__set->common.fn_flags & ZEND_ACC_STATIC) {
zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __set->common.function_name);
}
__set->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
}
if (__unset) {
if (__unset->common.fn_flags & ZEND_ACC_STATIC) {
zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __unset->common.function_name);
}
__unset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
}
if (__isset) {
if (__isset->common.fn_flags & ZEND_ACC_STATIC) {
zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __isset->common.function_name);
}
__isset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
}
if (__debugInfo) {
if (__debugInfo->common.fn_flags & ZEND_ACC_STATIC) {
zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __debugInfo->common.function_name);
}
}
efree((char*)lc_class_name);
}
return SUCCESS;
}
}==FAILURE) { // 注册模块的函数到 CG(function_table)
EG(current_module) = NULL;
zend_error(E_CORE_WARNING,"%s: Unable to register functions, unable to load", module->name);
return NULL;
}
EG(current_module) = NULL;
return module;
}
} == NULL) { // 把模块信息添加到模块注册表module_registry中
DL_UNLOAD(handle);
return FAILURE;
}
if ((type == MODULE_TEMPORARY || start_now) && zend_startup_module_ex(module_entry TSRMLS_CC) == FAILURE) {
DL_UNLOAD(handle);
return FAILURE;
}
if ((type == MODULE_TEMPORARY || start_now) && module_entry->request_startup_func) {
if (module_entry->request_startup_func(type, module_entry->module_number TSRMLS_CC) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, error_type, "Unable to initialize module '%s'", module_entry->name);
DL_UNLOAD(handle);
return FAILURE;
}
}
return SUCCESS;
}
}
}
}
...
}
...
}
...
}
...
}