mirror of
https://github.com/php/php-src.git
synced 2024-11-24 02:15:04 +08:00
Improved PHP extension loading mechanism with support for module dependencies and conflicts.
This commit is contained in:
parent
61b2fcc3ce
commit
c0c7a9f010
2
NEWS
2
NEWS
@ -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)
|
||||
|
132
Zend/zend_API.c
132
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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user