Created
November 10, 2016 11:46
-
-
Save brzuchal/e930ec7792e4efa3f7038cc1b65a4534 to your computer and use it in GitHub Desktop.
PHP Namespaces Struct
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/Zend/zend.c b/Zend/zend.c | |
index 44a73ba..60ff916 100644 | |
--- a/Zend/zend.c | |
+++ b/Zend/zend.c | |
@@ -36,11 +36,13 @@ | |
#ifdef ZTS | |
# define GLOBAL_FUNCTION_TABLE global_function_table | |
# define GLOBAL_CLASS_TABLE global_class_table | |
+# define GLOBAL_NAMESPACE_TABLE global_namespace_table | |
# define GLOBAL_CONSTANTS_TABLE global_constants_table | |
# define GLOBAL_AUTO_GLOBALS_TABLE global_auto_globals_table | |
#else | |
# define GLOBAL_FUNCTION_TABLE CG(function_table) | |
# define GLOBAL_CLASS_TABLE CG(class_table) | |
+# define GLOBAL_NAMESPACE_TABLE CG(namespace_table) | |
# define GLOBAL_AUTO_GLOBALS_TABLE CG(auto_globals) | |
# define GLOBAL_CONSTANTS_TABLE EG(zend_constants) | |
#endif | |
@@ -145,6 +147,7 @@ ZEND_API int compiler_globals_id; | |
ZEND_API int executor_globals_id; | |
static HashTable *global_function_table = NULL; | |
static HashTable *global_class_table = NULL; | |
+static HashTable *global_namespace_table = NULL; | |
static HashTable *global_constants_table = NULL; | |
static HashTable *global_auto_globals_table = NULL; | |
static HashTable *global_persistent_list = NULL; | |
@@ -499,6 +502,10 @@ static void compiler_globals_ctor(zend_compiler_globals *compiler_globals) /* {{ | |
zend_hash_init_ex(compiler_globals->class_table, 64, NULL, ZEND_CLASS_DTOR, 1, 0); | |
zend_hash_copy(compiler_globals->class_table, global_class_table, zend_class_add_ref); | |
+ compiler_globals->namespace_table = (HashTable *) malloc(sizeof(HashTable)); | |
+ zend_hash_init_ex(compiler_globals->namespace_table, 64, NULL, ZEND_NAMESPACE_DTOR, 1, 0); | |
+ zend_hash_copy(compiler_globals->namespace_table, global_namespace_table); | |
+ | |
zend_set_default_compile_time_values(); | |
compiler_globals->auto_globals = (HashTable *) malloc(sizeof(HashTable)); | |
@@ -531,6 +538,10 @@ static void compiler_globals_dtor(zend_compiler_globals *compiler_globals) /* {{ | |
zend_hash_destroy(compiler_globals->class_table); | |
free(compiler_globals->class_table); | |
} | |
+ if (compiler_globals->namespace_table != GLOBAL_NAMESPACE_TABLE) { | |
+ zend_hash_destroy(compiler_globals->namespace_table); | |
+ free(compiler_globals->namespace_table); | |
+ } | |
if (compiler_globals->auto_globals != GLOBAL_AUTO_GLOBALS_TABLE) { | |
zend_hash_destroy(compiler_globals->auto_globals); | |
free(compiler_globals->auto_globals); | |
@@ -715,11 +726,13 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions) / | |
GLOBAL_FUNCTION_TABLE = (HashTable *) malloc(sizeof(HashTable)); | |
GLOBAL_CLASS_TABLE = (HashTable *) malloc(sizeof(HashTable)); | |
+ GLOBAL_NAMESPACE_TABLE = (HashTable *) malloc(sizeof(HashTable)); | |
GLOBAL_AUTO_GLOBALS_TABLE = (HashTable *) malloc(sizeof(HashTable)); | |
GLOBAL_CONSTANTS_TABLE = (HashTable *) malloc(sizeof(HashTable)); | |
zend_hash_init_ex(GLOBAL_FUNCTION_TABLE, 1024, NULL, ZEND_FUNCTION_DTOR, 1, 0); | |
zend_hash_init_ex(GLOBAL_CLASS_TABLE, 64, NULL, ZEND_CLASS_DTOR, 1, 0); | |
+ zend_hash_init_ex(GLOBAL_NAMESPACE_TABLE, 64, NULL, ZEND_NAMESPACE_DTOR, 1, 0); | |
zend_hash_init_ex(GLOBAL_AUTO_GLOBALS_TABLE, 8, NULL, auto_global_dtor, 1, 0); | |
zend_hash_init_ex(GLOBAL_CONSTANTS_TABLE, 128, NULL, ZEND_CONSTANT_DTOR, 1, 0); | |
@@ -802,6 +815,7 @@ void zend_post_startup(void) /* {{{ */ | |
*GLOBAL_FUNCTION_TABLE = *compiler_globals->function_table; | |
*GLOBAL_CLASS_TABLE = *compiler_globals->class_table; | |
+ *GLOBAL_NAMESPACE_TABLE = *compiler_globals->namespace_table; | |
*GLOBAL_CONSTANTS_TABLE = *executor_globals->zend_constants; | |
short_tags_default = CG(short_tags); | |
@@ -810,6 +824,7 @@ void zend_post_startup(void) /* {{{ */ | |
zend_destroy_rsrc_list(&EG(persistent_list)); | |
free(compiler_globals->function_table); | |
free(compiler_globals->class_table); | |
+ free(compiler_globals->namespace_table); | |
if ((script_encoding_list = (zend_encoding **)compiler_globals->script_encoding_list)) { | |
compiler_globals_ctor(compiler_globals); | |
compiler_globals->script_encoding_list = (const zend_encoding **)script_encoding_list; | |
@@ -840,6 +855,7 @@ void zend_shutdown(void) /* {{{ */ | |
*/ | |
zend_function *func; | |
zend_class_entry *ce; | |
+ zend_namespace_entry *ne; | |
ZEND_HASH_REVERSE_FOREACH_PTR(GLOBAL_FUNCTION_TABLE, func) { | |
if (func->type == ZEND_USER_FUNCTION) { | |
@@ -856,6 +872,7 @@ void zend_shutdown(void) /* {{{ */ | |
zend_cleanup_internal_classes(); | |
zend_hash_reverse_apply(GLOBAL_FUNCTION_TABLE, (apply_func_t) clean_non_persistent_function_full); | |
zend_hash_reverse_apply(GLOBAL_CLASS_TABLE, (apply_func_t) clean_non_persistent_class_full); | |
+ zend_hash_reverse_apply(GLOBAL_NAMESPACE_TABLE, (apply_func_t) clean_non_persistent_namespace_full); | |
} | |
zend_destroy_modules(); | |
@@ -864,6 +881,7 @@ void zend_shutdown(void) /* {{{ */ | |
zend_hash_destroy(GLOBAL_FUNCTION_TABLE); | |
zend_hash_destroy(GLOBAL_CLASS_TABLE); | |
+ zend_hash_destroy(GLOBAL_NAMESPACE_TABLE); | |
zend_hash_destroy(GLOBAL_AUTO_GLOBALS_TABLE); | |
free(GLOBAL_AUTO_GLOBALS_TABLE); | |
@@ -873,6 +891,7 @@ void zend_shutdown(void) /* {{{ */ | |
free(GLOBAL_FUNCTION_TABLE); | |
free(GLOBAL_CLASS_TABLE); | |
+ free(GLOBAL_NAMESPACE_TABLE); | |
zend_hash_destroy(GLOBAL_CONSTANTS_TABLE); | |
free(GLOBAL_CONSTANTS_TABLE); | |
@@ -881,6 +900,7 @@ void zend_shutdown(void) /* {{{ */ | |
#ifdef ZTS | |
GLOBAL_FUNCTION_TABLE = NULL; | |
GLOBAL_CLASS_TABLE = NULL; | |
+ GLOBAL_NAMESPACE_TABLE = NULL; | |
GLOBAL_AUTO_GLOBALS_TABLE = NULL; | |
GLOBAL_CONSTANTS_TABLE = NULL; | |
#endif | |
diff --git a/Zend/zend.h b/Zend/zend.h | |
index 94f2fbdc..d71c464 100644 | |
--- a/Zend/zend.h | |
+++ b/Zend/zend.h | |
@@ -175,6 +175,23 @@ struct _zend_class_entry { | |
struct _zend_module_entry *module; | |
} internal; | |
} info; | |
+ zend_namespace_entry *namespace; | |
+}; | |
+ | |
+struct _zend_namespace_entry { | |
+ char type; | |
+ zend_string *name; | |
+ struct _zend_namespace_entry *parent; | |
+ uint32_t ne_flags; | |
+ | |
+ HashTable children; | |
+ | |
+// uint32_t num_children; | |
+// uint32_t num_classes; | |
+// zend_namespace_entry **children; | |
+// zend_class_entry **classes; | |
+ | |
+ // @TODO: may need info field like zend_class_entry | |
}; | |
typedef struct _zend_utility_functions { | |
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c | |
index 241b3c4..a81c0aa 100644 | |
--- a/Zend/zend_builtin_functions.c | |
+++ b/Zend/zend_builtin_functions.c | |
@@ -78,6 +78,7 @@ static ZEND_FUNCTION(set_error_handler); | |
static ZEND_FUNCTION(restore_error_handler); | |
static ZEND_FUNCTION(set_exception_handler); | |
static ZEND_FUNCTION(restore_exception_handler); | |
+static ZEND_FUNCTION(get_declared_namespaces); | |
static ZEND_FUNCTION(get_declared_classes); | |
static ZEND_FUNCTION(get_declared_traits); | |
static ZEND_FUNCTION(get_declared_interfaces); | |
@@ -352,6 +353,7 @@ static const zend_function_entry builtin_functions[] = { /* {{{ */ | |
ZEND_FE(restore_error_handler, arginfo_zend__void) | |
ZEND_FE(set_exception_handler, arginfo_set_exception_handler) | |
ZEND_FE(restore_exception_handler, arginfo_zend__void) | |
+ ZEND_FE(get_declared_namespaces, arginfo_zend__void) | |
ZEND_FE(get_declared_classes, arginfo_zend__void) | |
ZEND_FE(get_declared_traits, arginfo_zend__void) | |
ZEND_FE(get_declared_interfaces, arginfo_zend__void) | |
@@ -1943,6 +1945,28 @@ static int copy_class_or_interface_name(zval *el, int num_args, va_list args, ze | |
} | |
/* }}} */ | |
+static int copy_namespace_name(zval *el, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */ | |
+{ | |
+ zend_namespace_entry *ne = (zend_namespace_entry *)Z_PTR_P(el); | |
+ zval *array = va_arg(args, zval *); | |
+// uint32_t mask = va_arg(args, uint32_t); | |
+// uint32_t comply = va_arg(args, uint32_t); | |
+// uint32_t comply_mask = (comply)? mask:0; | |
+ | |
+ if ((hash_key->key && ZSTR_VAL(hash_key->key)[0] != 0) | |
+// && (comply_mask == (ne->ne_flags & mask)) // @TODO: not implemented yet | |
+ ) { | |
+// if (ce->refcount > 1 && | |
+// !same_name(hash_key->key, ce->name)) { | |
+// add_next_index_str(array, zend_string_copy(hash_key->key)); | |
+// } else { | |
+ add_next_index_str(array, zend_string_copy(ne->name)); | |
+// } | |
+ } | |
+ return ZEND_HASH_APPLY_KEEP; | |
+} | |
+/* }}} */ | |
+ | |
/* {{{ proto array get_declared_traits() | |
Returns an array of all declared traits. */ | |
ZEND_FUNCTION(get_declared_traits) | |
@@ -1959,6 +1983,22 @@ ZEND_FUNCTION(get_declared_traits) | |
} | |
/* }}} */ | |
+/* {{{ proto array get_declared_namespaces() | |
+ Returns an array of all declared namespaces. */ | |
+ZEND_FUNCTION(get_declared_namespaces) | |
+{ | |
+ uint32_t mask = 0; | |
+ uint32_t comply = 0; | |
+ | |
+ if (zend_parse_parameters_none() == FAILURE) { | |
+ return; | |
+ } | |
+ | |
+ array_init(return_value); | |
+ zend_hash_apply_with_arguments(EG(namespace_table), copy_namespace_name, 3, return_value, mask, comply); | |
+} | |
+/* }}} */ | |
+ | |
/* {{{ proto array get_declared_classes() | |
Returns an array of all declared classes. */ | |
ZEND_FUNCTION(get_declared_classes) | |
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h | |
index d0ba4de..7d107a6 100644 | |
--- a/Zend/zend_compile.h | |
+++ b/Zend/zend_compile.h | |
@@ -767,10 +767,12 @@ ZEND_API void zend_cleanup_internal_classes(void); | |
ZEND_API void zend_cleanup_op_array_data(zend_op_array *op_array); | |
ZEND_API int clean_non_persistent_function_full(zval *zv); | |
ZEND_API int clean_non_persistent_class_full(zval *zv); | |
+ZEND_API int clean_non_persistent_namespace_full(zval *zv); | |
ZEND_API void destroy_zend_function(zend_function *function); | |
ZEND_API void zend_function_dtor(zval *zv); | |
ZEND_API void destroy_zend_class(zval *zv); | |
+ZEND_API void destroy_zend_namespace(zval *zv); | |
void zend_class_add_ref(zval *zv); | |
ZEND_API zend_string *zend_mangle_property_name(const char *src1, size_t src1_length, const char *src2, size_t src2_length, int internal); | |
@@ -780,6 +782,7 @@ ZEND_API int zend_unmangle_property_name_ex(const zend_string *name, const char | |
#define ZEND_FUNCTION_DTOR zend_function_dtor | |
#define ZEND_CLASS_DTOR destroy_zend_class | |
+#define ZEND_NAMESPACE_DTOR destroy_zend_namespace | |
zend_op *get_next_op(zend_op_array *op_array); | |
void init_op(zend_op *op); | |
@@ -870,6 +873,9 @@ ZEND_API void zend_assert_valid_class_name(const zend_string *const_name); | |
#define ZEND_INTERNAL_CLASS 1 | |
#define ZEND_USER_CLASS 2 | |
+#define ZEND_INTERNAL_NAMESPACE 1 | |
+#define ZEND_USER_NAMESPACE 2 | |
+ | |
#define ZEND_EVAL (1<<0) | |
#define ZEND_INCLUDE (1<<1) | |
#define ZEND_INCLUDE_ONCE (1<<2) | |
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c | |
index 14883d0..a5419b5 100644 | |
--- a/Zend/zend_execute_API.c | |
+++ b/Zend/zend_execute_API.c | |
@@ -128,6 +128,13 @@ ZEND_API int clean_non_persistent_class_full(zval *zv) /* {{{ */ | |
} | |
/* }}} */ | |
+ZEND_API int clean_non_persistent_namespace_full(zval *zv) /* {{{ */ | |
+{ | |
+ zend_namespace_entry *ne = Z_PTR_P(zv); | |
+ return (ne->type == ZEND_INTERNAL_NAMESPACE) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE; | |
+} | |
+/* }}} */ | |
+ | |
void init_executor(void) /* {{{ */ | |
{ | |
zend_init_fpu(); | |
@@ -145,6 +152,7 @@ void init_executor(void) /* {{{ */ | |
EG(function_table) = CG(function_table); | |
EG(class_table) = CG(class_table); | |
+ EG(namespace_table) = CG(namespace_table); | |
EG(in_autoload) = NULL; | |
EG(autoload_func) = NULL; | |
@@ -368,7 +376,7 @@ void shutdown_executor(void) /* {{{ */ | |
zend_hash_reverse_apply(EG(function_table), clean_non_persistent_function); | |
zend_hash_reverse_apply(EG(class_table), clean_non_persistent_class); | |
} | |
- | |
+// @TODO: add destruct of namespace_table | |
while (EG(symtable_cache_ptr)>=EG(symtable_cache)) { | |
zend_hash_destroy(*EG(symtable_cache_ptr)); | |
FREE_HASHTABLE(*EG(symtable_cache_ptr)); | |
diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h | |
index d056ce7..eaf2184 100644 | |
--- a/Zend/zend_globals.h | |
+++ b/Zend/zend_globals.h | |
@@ -80,6 +80,7 @@ struct _zend_compiler_globals { | |
HashTable *function_table; /* function symbol table */ | |
HashTable *class_table; /* class table */ | |
+ HashTable *namespace_table; /* namespace table */ | |
HashTable filenames_table; | |
@@ -157,6 +158,7 @@ struct _zend_executor_globals { | |
HashTable *function_table; /* function symbol table */ | |
HashTable *class_table; /* class table */ | |
+ HashTable *namespace_table; /* namespace table */ | |
HashTable *zend_constants; /* constants table */ | |
zval *vm_stack_top; | |
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c | |
index bffe9e2..2c86f38 100644 | |
--- a/Zend/zend_opcode.c | |
+++ b/Zend/zend_opcode.c | |
@@ -351,6 +351,80 @@ ZEND_API void destroy_zend_class(zval *zv) | |
} | |
} | |
+ZEND_API void destroy_zend_namespace(zval *zv) | |
+{ | |
+ zend_namespace_entry *ne = Z_PTR_P(zv); | |
+ | |
+ switch (ne->type) { | |
+ case ZEND_USER_NAMESPACE: | |
+ zend_string_release(ne->name); | |
+// zend_hash_destroy(&ce->function_table); | |
+// if (zend_hash_num_elements(&ce->constants_table)) { | |
+// zend_class_constant *c; | |
+// | |
+// ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) { | |
+// if (c->ce == ce) { | |
+// zval_ptr_dtor(&c->value); | |
+// if (c->doc_comment) { | |
+// zend_string_release(c->doc_comment); | |
+// } | |
+// } | |
+// } ZEND_HASH_FOREACH_END(); | |
+// zend_hash_destroy(&ce->constants_table); | |
+// } | |
+// if (ce->num_interfaces > 0 && ce->interfaces) { | |
+// efree(ce->interfaces); | |
+// } | |
+// if (ce->info.user.doc_comment) { | |
+// zend_string_release(ce->info.user.doc_comment); | |
+// } | |
+ | |
+// _destroy_zend_class_traits_info(ce); | |
+ | |
+ break; | |
+ case ZEND_INTERNAL_NAMESPACE: | |
+// if (ce->default_properties_table) { | |
+// zval *p = ce->default_properties_table; | |
+// zval *end = p + ce->default_properties_count; | |
+// | |
+// while (p != end) { | |
+// zval_internal_ptr_dtor(p); | |
+// p++; | |
+// } | |
+// free(ce->default_properties_table); | |
+// } | |
+// if (ce->default_static_members_table) { | |
+// zval *p = ce->default_static_members_table; | |
+// zval *end = p + ce->default_static_members_count; | |
+// | |
+// while (p != end) { | |
+// zval_internal_ptr_dtor(p); | |
+// p++; | |
+// } | |
+// free(ce->default_static_members_table); | |
+// } | |
+// zend_hash_destroy(&ce->properties_info); | |
+ zend_string_release(ne->name); | |
+// zend_hash_destroy(&ce->function_table); | |
+// if (zend_hash_num_elements(&ce->constants_table)) { | |
+// zend_class_constant *c; | |
+// | |
+// ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) { | |
+// zval_internal_ptr_dtor(&c->value); | |
+// if (c->doc_comment && c->ce == ce) { | |
+// zend_string_release(c->doc_comment); | |
+// } | |
+// } ZEND_HASH_FOREACH_END(); | |
+// zend_hash_destroy(&ce->constants_table); | |
+// } | |
+// if (ce->num_interfaces > 0) { | |
+// free(ce->interfaces); | |
+// } | |
+ free(ne); | |
+ break; | |
+ } | |
+} | |
+ | |
void zend_class_add_ref(zval *zv) | |
{ | |
zend_class_entry *ce = Z_PTR_P(zv); | |
diff --git a/Zend/zend_types.h b/Zend/zend_types.h | |
index 29dec8e..26956c5 100644 | |
--- a/Zend/zend_types.h | |
+++ b/Zend/zend_types.h | |
@@ -78,6 +78,7 @@ typedef uintptr_t zend_uintptr_t; | |
typedef struct _zend_object_handlers zend_object_handlers; | |
typedef struct _zend_class_entry zend_class_entry; | |
+typedef struct _zend_namespace_entry zend_namespace_entry; | |
typedef union _zend_function zend_function; | |
typedef struct _zend_execute_data zend_execute_data; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment