summaryrefslogtreecommitdiff
path: root/Zend/zend_API.c
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@php.net>2005-06-17 09:36:26 +0000
committerDmitry Stogov <dmitry@php.net>2005-06-17 09:36:26 +0000
commitc0c7a9f0101f5488cbf861390f5a89feaebcc94a (patch)
tree05fb8ff6f7b18688b4f1b7f9279f1645d24f8938 /Zend/zend_API.c
parent61b2fcc3ce43135f024569dddf176ff08533cd19 (diff)
downloadphp-git-c0c7a9f0101f5488cbf861390f5a89feaebcc94a.tar.gz
Improved PHP extension loading mechanism with support for module dependencies and conflicts.
Diffstat (limited to 'Zend/zend_API.c')
-rw-r--r--Zend/zend_API.c132
1 files changed, 116 insertions, 16 deletions
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;
}