summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS2
-rw-r--r--Zend/zend_API.c132
-rw-r--r--Zend/zend_API.h5
-rw-r--r--Zend/zend_extensions.h2
-rw-r--r--Zend/zend_modules.h31
5 files changed, 149 insertions, 23 deletions
diff --git a/NEWS b/NEWS
index 047794f4d9..5243f9f2f6 100644
--- a/NEWS
+++ b/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)
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;