Skip to content

Instantly share code, notes, and snippets.

@brzuchal
Created November 10, 2016 11:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brzuchal/e930ec7792e4efa3f7038cc1b65a4534 to your computer and use it in GitHub Desktop.
Save brzuchal/e930ec7792e4efa3f7038cc1b65a4534 to your computer and use it in GitHub Desktop.
PHP Namespaces Struct
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