diff options
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | Zend/zend_API.c | 132 | ||||
-rw-r--r-- | Zend/zend_API.h | 5 | ||||
-rw-r--r-- | Zend/zend_extensions.h | 2 | ||||
-rw-r--r-- | Zend/zend_modules.h | 31 |
5 files changed, 149 insertions, 23 deletions
@@ -1,6 +1,8 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? Jun 2005, PHP 5.1 Beta 2 +- Improved PHP extension loading mechanism with support for module dependencies + and conflicts. (Jani, Dmitry) - Allowed return by reference from internal functions. (Marcus, Andi, Dmitry) - Rewrote strtotime() with support for timezones and tons of new formats. (Derick) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index dac58559d8..b4c66bf5ce 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1212,6 +1212,94 @@ ZEND_API int add_property_zval_ex(zval *arg, char *key, uint key_len, zval *valu return SUCCESS; } +ZEND_API int zend_startup_module(zend_module_entry *module TSRMLS_DC) +{ + int name_len; + char *lcname; + + if (module->module_started) { + return SUCCESS; + } + module->module_started = 1; + + /* Check module dependencies */ + if (module->deps) { + zend_module_dep *dep = module->deps; + + while (dep->name) { + if (dep->type == MODULE_DEP_REQUIRED) { + zend_module_entry *req_mod; + + name_len = strlen(dep->name); + lcname = zend_str_tolower_dup(dep->name, name_len); + + if (zend_hash_find(&module_registry, lcname, name_len+1, (void**)&req_mod) == FAILURE || + !req_mod->module_started) { + efree(lcname); + /* TODO: Check version relationship */ + zend_error(E_CORE_WARNING, "Cannot load module '%s' because required module '%s' is not loaded", module->name, req_mod->name); + module->module_started = 0; + return FAILURE; + } + efree(lcname); + } + ++dep; + } + } + + if (module->module_startup_func) { + EG(current_module) = module; + if (module->module_startup_func(module->type, module->module_number TSRMLS_CC)==FAILURE) { + zend_error(E_CORE_ERROR,"Unable to start %s module", module->name); + EG(current_module) = NULL; + return FAILURE; + } + EG(current_module) = NULL; + } + return SUCCESS; +} + +static void zend_sort_modules(void *base, size_t count, size_t siz, compare_func_t compare TSRMLS_DC) +{ + Bucket **b1 = base; + Bucket **b2; + Bucket **end = b1 + count; + Bucket *tmp; + zend_module_entry *m, *r; + + while (b1 < end) { +try_again: + m = (zend_module_entry*)(*b1)->pData; + if (!m->module_started && m->deps) { + zend_module_dep *dep = m->deps; + while (dep->name) { + if (dep->type == MODULE_DEP_REQUIRED || dep->type == MODULE_DEP_OPTIONAL) { + b2 = b1 + 1; + while (b2 < end) { + r = (zend_module_entry*)(*b2)->pData; + if (strcasecmp(dep->name, r->name) == 0) { + tmp = *b1; + *b1 = *b2; + *b2 = tmp; + goto try_again; + } + b2++; + } + } + dep++; + } + } + b1++; + } +} + +ZEND_API int zend_startup_modules(TSRMLS_D) +{ + zend_hash_sort(&module_registry, zend_sort_modules, NULL, 0 TSRMLS_CC); + zend_hash_apply(&module_registry, (apply_func_t)zend_startup_module TSRMLS_CC); + return SUCCESS; +} + ZEND_API int zend_register_module_ex(zend_module_entry *module TSRMLS_DC) { int name_len; @@ -1225,6 +1313,28 @@ ZEND_API int zend_register_module_ex(zend_module_entry *module TSRMLS_DC) #if 0 zend_printf("%s: Registering module %d\n", module->name, module->module_number); #endif + + /* Check module dependencies */ + if (module->deps) { + 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 FAILURE; + } + efree(lcname); + } + ++dep; + } + } + name_len = strlen(module->name); lcname = zend_str_tolower_dup(module->name, name_len); @@ -1241,25 +1351,11 @@ ZEND_API int zend_register_module_ex(zend_module_entry *module TSRMLS_DC) return FAILURE; } - if (!module->module_started && module->module_startup_func) { - EG(current_module) = module; - if (module->module_startup_func(module->type, module->module_number TSRMLS_CC)==FAILURE) { - zend_error(E_CORE_ERROR,"Unable to start %s module", module->name); - EG(current_module) = NULL; - return FAILURE; - } - EG(current_module) = NULL; - } - - module->module_started=1; - return SUCCESS; } -ZEND_API int zend_startup_module(zend_module_entry *module) +ZEND_API int zend_register_internal_module(zend_module_entry *module TSRMLS_DC) { - TSRMLS_FETCH(); - module->module_number = zend_next_free_module(); module->type = MODULE_PERSISTENT; return zend_register_module_ex(module TSRMLS_CC); @@ -1510,7 +1606,11 @@ ZEND_API int zend_register_module(zend_module_entry *module) { TSRMLS_FETCH(); - return zend_register_module_ex(module TSRMLS_CC); + if (zend_register_module_ex(module TSRMLS_CC) == SUCCESS && + zend_startup_module(module TSRMLS_CC) == SUCCESS) { + return SUCCESS; + } + return FAILURE; } diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 06a29246b6..ee6b6d3bf5 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -173,7 +173,10 @@ ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args TSRMLS_DC, ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC); ZEND_API void zend_unregister_functions(zend_function_entry *functions, int count, HashTable *function_table TSRMLS_DC); ZEND_API int zend_register_module(zend_module_entry *module_entry); +ZEND_API int zend_register_internal_module(zend_module_entry *module_entry TSRMLS_DC); ZEND_API int zend_register_module_ex(zend_module_entry *module TSRMLS_DC); +ZEND_API int zend_startup_module(zend_module_entry *module TSRMLS_DC); +ZEND_API int zend_startup_modules(TSRMLS_D); ZEND_API void zend_check_magic_method_implementation(zend_class_entry *ce, zend_function *fptr, int error_type TSRMLS_DC); ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *class_entry TSRMLS_DC); @@ -228,8 +231,6 @@ ZEND_API zend_class_entry *zend_get_class_entry(zval *zobject TSRMLS_DC); #define DLEXPORT #endif -ZEND_API int zend_startup_module(zend_module_entry *module); - #define array_init(arg) _array_init((arg) ZEND_FILE_LINE_CC) #define object_init(arg) _object_init((arg) ZEND_FILE_LINE_CC TSRMLS_CC) #define object_init_ex(arg, ce) _object_init_ex((arg), (ce) ZEND_FILE_LINE_CC TSRMLS_CC) diff --git a/Zend/zend_extensions.h b/Zend/zend_extensions.h index 19b091f48b..d93c2f5ff6 100644 --- a/Zend/zend_extensions.h +++ b/Zend/zend_extensions.h @@ -27,7 +27,7 @@ /* The first number is the engine version and the rest is the date. * This way engine 2 API no. is always greater than engine 1 API no.. */ -#define ZEND_EXTENSION_API_NO 220050615 +#define ZEND_EXTENSION_API_NO 220050617 typedef struct _zend_extension_version_info { int zend_extension_api_no; diff --git a/Zend/zend_modules.h b/Zend/zend_modules.h index 9223383fff..446f22254a 100644 --- a/Zend/zend_modules.h +++ b/Zend/zend_modules.h @@ -38,15 +38,18 @@ extern struct _zend_arg_info third_arg_force_ref[4]; extern struct _zend_arg_info fourth_arg_force_ref[5]; extern struct _zend_arg_info all_args_by_ref[1]; -#define ZEND_MODULE_API_NO 20050615 +#define ZEND_MODULE_API_NO 20050617 #ifdef ZTS #define USING_ZTS 1 #else #define USING_ZTS 0 #endif -#define STANDARD_MODULE_HEADER sizeof(zend_module_entry), ZEND_MODULE_API_NO, ZEND_DEBUG, USING_ZTS, NULL -#define ZE2_STANDARD_MODULE_HEADER sizeof(zend_module_entry), ZEND_MODULE_API_NO, ZEND_DEBUG, USING_ZTS, ini_entries +#define STANDARD_MODULE_HEADER_EX sizeof(zend_module_entry), ZEND_MODULE_API_NO, ZEND_DEBUG, USING_ZTS +#define STANDARD_MODULE_HEADER \ + STANDARD_MODULE_HEADER_EX, NULL, NULL +#define ZE2_STANDARD_MODULE_HEADER \ + STANDARD_MODULE_HEADER_EX, ini_entries, NULL #define STANDARD_MODULE_PROPERTIES_EX 0, 0, 0, NULL, 0 @@ -60,13 +63,15 @@ extern struct _zend_arg_info all_args_by_ref[1]; struct _zend_ini_entry; typedef struct _zend_module_entry zend_module_entry; +typedef struct _zend_module_dep zend_module_dep; struct _zend_module_entry { - unsigned short size; + unsigned short size; unsigned int zend_api; unsigned char zend_debug; unsigned char zts; struct _zend_ini_entry *ini_entry; + struct _zend_module_dep *deps; char *name; struct _zend_function_entry *functions; int (*module_startup_func)(INIT_FUNC_ARGS); @@ -83,6 +88,24 @@ struct _zend_module_entry { int module_number; }; +#define MODULE_DEP_REQUIRED 1 +#define MODULE_DEP_CONFLICTS 2 +#define MODULE_DEP_OPTIONAL 3 + +#define ZEND_MOD_REQUIRED_EX(name, rel, ver) { name, rel, ver, MODULE_DEP_REQUIRED }, +#define ZEND_MOD_CONFLICTS_EX(name, rel, ver) { name, rel, ver, MODULE_DEP_CONFLICTS }, +#define ZEND_MOD_OPTIONAL_EX(name, rel, ver) { name, rel, ver, MODULE_DEP_OPTIONAL }, + +#define ZEND_MOD_REQUIRED(name) ZEND_MOD_REQUIRED_EX(name, NULL, NULL) +#define ZEND_MOD_CONFLICTS(name) ZEND_MOD_CONFLICTS_EX(name, NULL, NULL) +#define ZEND_MOD_OPTIONAL(name) ZEND_MOD_OPTIONAL_EX(name, NULL, NULL) + +struct _zend_module_dep { + char *name; /* module name */ + char *rel; /* version relationship: NULL (exists), lt|le|eq|ge|gt (to given version) */ + char *version; /* version */ + unsigned char type; /* dependency type */ +}; extern ZEND_API HashTable module_registry; |