]> granicus.if.org Git - php/commitdiff
Namespace patch. Big changes:
authorStanislav Malyshev <stas@php.net>
Sun, 16 Feb 2003 11:12:43 +0000 (11:12 +0000)
committerStanislav Malyshev <stas@php.net>
Sun, 16 Feb 2003 11:12:43 +0000 (11:12 +0000)
1. Nested classes are gone.
2. New syntax for namespaces:
namespace foo {
class X { ... }
function bar { ... }
var x = 1;
const ZZ = 2;
}
3. Namespaced symbol access: $x = new foo::X; - etc.
For now, namespaces are case insensitive, just like classes.
Also, there can be no global class and namespace with the same name
(to avoid ambiguities in :: resolution).

12 files changed:
Zend/zend.c
Zend/zend.h
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_constants.c
Zend/zend_execute.c
Zend/zend_execute.h
Zend/zend_execute_API.c
Zend/zend_globals.h
Zend/zend_language_parser.y
Zend/zend_language_scanner.l
Zend/zend_opcode.c

index c45cc63d1d8fd7e2ef01aa858c61d8e898349fc5..e3b538a3e21c5ba61b0783705788b61456854395 100644 (file)
@@ -29,9 +29,9 @@
 #include "zend_ini.h"
 
 #ifdef ZTS
-#      define GLOBAL_FUNCTION_TABLE    &global_main_class.function_table
-#      define GLOBAL_CLASS_TABLE               &global_main_class.class_table
-#      define GLOBAL_CONSTANTS_TABLE   &global_main_class.constants_table
+#      define GLOBAL_FUNCTION_TABLE    &global_namespace.function_table
+#      define GLOBAL_CLASS_TABLE               &global_namespace.class_table
+#      define GLOBAL_CONSTANTS_TABLE   &global_namespace.constants_table
 #      define GLOBAL_AUTO_GLOBALS_TABLE        global_auto_globals_table
 #else
 #      define GLOBAL_FUNCTION_TABLE    CG(function_table)
@@ -92,6 +92,7 @@ ZEND_API int compiler_globals_id;
 ZEND_API int executor_globals_id;
 ZEND_API int alloc_globals_id;
 zend_class_entry global_main_class;
+zend_namespace global_namespace;
 HashTable *global_auto_globals_table;
 #endif
 
@@ -401,11 +402,11 @@ static void compiler_globals_ctor(zend_compiler_globals *compiler_globals TSRMLS
 
        compiler_globals->compiled_filename = NULL;
 
-       compiler_globals->function_table = &compiler_globals->main_class.function_table;
+       compiler_globals->function_table = &compiler_globals->global_namespace.function_table;
        zend_hash_init_ex(compiler_globals->function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
        zend_hash_copy(compiler_globals->function_table, GLOBAL_FUNCTION_TABLE, NULL, &tmp_func, sizeof(zend_function));
 
-       compiler_globals->class_table = &compiler_globals->main_class.class_table;
+       compiler_globals->class_table = &compiler_globals->global_namespace.class_table;
        zend_hash_init_ex(compiler_globals->class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
        zend_hash_copy(compiler_globals->class_table, GLOBAL_CLASS_TABLE, (copy_ctor_func_t) zend_class_add_ref, &tmp_class, sizeof(zend_class_entry *));
 
@@ -551,8 +552,9 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions, i
        zend_version_info_length = sizeof(ZEND_CORE_VERSION_INFO)-1;
 
 #ifndef ZTS
-       GLOBAL_FUNCTION_TABLE = &compiler_globals.main_class.function_table;
-       GLOBAL_CLASS_TABLE = &compiler_globals.main_class.class_table;
+       GLOBAL_FUNCTION_TABLE = &compiler_globals.global_namespace.function_table;
+       GLOBAL_CLASS_TABLE = &compiler_globals.global_namespace.class_table;
+       compiler_globals.global_namespace.static_members = NULL;
 #endif
        GLOBAL_AUTO_GLOBALS_TABLE = (HashTable *) malloc(sizeof(HashTable));
        zend_hash_init_ex(GLOBAL_FUNCTION_TABLE, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
index ac86552e0ade20de6d8f8eafe7007ea2986bf2a7..c031bce103cd9c60606e65117b831145cee94412 100644 (file)
@@ -262,7 +262,18 @@ struct _zval_struct {
        zend_uchar is_ref;
 };
 
+struct _zend_op_array;
 
+/* typedef struct _zend_namespace {
+       char *name;
+       zend_uint name_length;
+       HashTable function_table;
+       HashTable class_table;
+       HashTable constants_table;
+       HashTable *global_variables;
+       struct _zend_op_array *op_array;
+} zend_namespace;
+*/
 
 typedef struct _zend_function_entry {
        char *fname;
@@ -308,6 +319,7 @@ struct _zend_class_entry {
        HashTable *static_members;
        HashTable constants_table;
        zend_function_entry *builtin_functions;
+       struct _zend_class_entry *namespace;
 
        union _zend_function *constructor;
        union _zend_function *destructor;
@@ -316,6 +328,7 @@ struct _zend_class_entry {
        union _zend_function *__set;
        union _zend_function *__call;
 
+       
        /* handlers */
        zend_object_value (*create_object)(zend_class_entry *class_type TSRMLS_DC);
 
@@ -327,6 +340,7 @@ struct _zend_class_entry {
 #endif
 };
 
+typedef struct _zend_class_entry zend_namespace; /* namespace is the same as class */
 
 typedef struct _zend_utility_functions {
        void (*error_function)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
index e1eaafdbea2761f8c7d65478317373010ffe7129..c103be1cc3bfb1e4599711e4bcc65d7b045db7c1 100644 (file)
@@ -74,7 +74,7 @@ void zend_init_compiler_data_structures(TSRMLS_D)
        zend_stack_init(&CG(object_stack));
        zend_stack_init(&CG(declare_stack));
        CG(active_class_entry) = NULL;
-       CG(active_ce_parent_class_name).value.str.val = NULL;
+       CG(active_namespace) = &CG(global_namespace);
        zend_llist_init(&CG(list_llist), sizeof(list_llist_element), NULL, 0);
        zend_llist_init(&CG(dimension_llist), sizeof(int), NULL, 0);
        zend_stack_init(&CG(list_stack));
@@ -937,6 +937,7 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
        op_array.fn_flags = fn_flags;
 
        op_array.scope = CG(active_class_entry);
+       op_array.namespace = CG(active_namespace);
 
        if (is_method) {
                char *short_class_name = CG(active_class_entry)->name;
@@ -1150,7 +1151,7 @@ void zend_do_begin_dynamic_function_call(znode *function_name TSRMLS_DC)
 }
 
 
-void do_fetch_class(znode *result, znode *class_entry, znode *class_name TSRMLS_DC)
+void do_fetch_class(znode *result, znode *namespace_name, znode *class_name TSRMLS_DC)
 {
        long fetch_class_op_number;
        zend_op *opline;
@@ -1159,8 +1160,9 @@ void do_fetch_class(znode *result, znode *class_entry, znode *class_name TSRMLS_
        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
        opline->opcode = ZEND_FETCH_CLASS;
-       if (class_entry) {
-               opline->op1 = *class_entry;
+       if (namespace_name) {
+               zend_str_tolower(namespace_name->u.constant.value.str.val, namespace_name->u.constant.value.str.len);
+               opline->op1 = *namespace_name;
        } else {
                SET_UNUSED(opline->op1);
                CG(catch_begin) = fetch_class_op_number;
@@ -1675,6 +1677,7 @@ static void create_class(HashTable *class_table, char *name, int name_length, ze
        zend_initialize_class_data(new_class_entry, 1);
 
        zend_str_tolower(new_class_entry->name, new_class_entry->name_length);
+
        if (zend_hash_update(class_table, new_class_entry->name, name_length+1, &new_class_entry, sizeof(zend_class_entry *), NULL) == FAILURE) {
                zend_error(E_COMPILE_ERROR, "Can't create class. Fatal error, please report!");
        }
@@ -1715,7 +1718,7 @@ static int create_nested_class(HashTable *class_table, char *path, zend_class_en
        new_ce->refcount++;
        if (zend_hash_add(&ce->class_table, last, strlen(last)+1, &new_ce, sizeof(zend_class_entry *), NULL) == FAILURE) {
                new_ce->refcount--;
-               zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", last);
+               zend_error(E_COMPILE_ERROR, "Cannot redeclare class '%s' - class or namespace with this name already exist.", last);
                return FAILURE;
        }
        return SUCCESS;
@@ -1726,7 +1729,7 @@ ZEND_API int do_bind_function(zend_op *opline, HashTable *function_table, HashTa
        zend_function *function;
 
        if (opline->opcode != ZEND_DECLARE_FUNCTION) {
-               zend_error(E_ERROR, "Internal compiler error.  Please report!");
+               zend_error(E_COMPILE_ERROR, "Internal compiler error.  Please report!");
        }
 
        zend_hash_find(function_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void *) &function);
@@ -1758,7 +1761,7 @@ ZEND_API int do_bind_class(zend_op *opline, HashTable *function_table, HashTable
        zend_class_entry *ce, **pce;
 
        if (zend_hash_find(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void **) &pce)==FAILURE) {
-               zend_error(E_ERROR, "Internal Zend error - Missing class information for %s", opline->op1.u.constant.value.str.val);
+               zend_error(E_COMPILE_ERROR, "Internal Zend error - Missing class information for %s", opline->op1.u.constant.value.str.val);
                return FAILURE;
        } else {
                ce = *pce;
@@ -1769,7 +1772,7 @@ ZEND_API int do_bind_class(zend_op *opline, HashTable *function_table, HashTable
        ce->refcount++;
        if (zend_hash_add(class_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, &ce, sizeof(zend_class_entry *), NULL)==FAILURE) {
                ce->refcount--;
-               zend_error(E_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val);
+               zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val);
                return FAILURE;
        } else {
                return SUCCESS;
@@ -1784,7 +1787,7 @@ ZEND_API int do_bind_inherited_class(zend_op *opline, HashTable *function_table,
        found_ce = zend_hash_find(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void **) &pce);
 
        if (found_ce == FAILURE) {
-               zend_error(E_ERROR, "Cannot redeclare class %s", (*pce)->name);
+               zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", (*pce)->name);
                return FAILURE;
        } else {
                ce = *pce;
@@ -1800,7 +1803,7 @@ ZEND_API int do_bind_inherited_class(zend_op *opline, HashTable *function_table,
 
        /* Register the derived class */
        if (zend_hash_add(class_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, pce, sizeof(zend_class_entry *), NULL)==FAILURE) {
-               zend_error(E_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val);
+               zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val);
                ce->refcount--;
                zend_hash_destroy(&ce->function_table);
                zend_hash_destroy(&ce->default_properties);
@@ -2114,7 +2117,6 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod
        int doing_inheritance = 0;
        zend_class_entry *new_class_entry = emalloc(sizeof(zend_class_entry));
 
-       class_token->u.previously_active_class_entry = CG(active_class_entry);
        if (!(strcmp(class_name->u.constant.value.str.val, "main") && strcmp(class_name->u.constant.value.str.val, "self") &&
                        strcmp(class_name->u.constant.value.str.val, "parent"))) {
                zend_error(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved", class_name->u.constant.value.str.val);
@@ -2148,7 +2150,7 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod
        opline->op2.op_type = IS_CONST;
        opline->op2.u.constant.type = IS_STRING;
        opline->op2.u.constant.refcount = 1;
-
+       
        if (doing_inheritance) {
                opline->extended_value = parent_class_name->u.var;
                opline->opcode = ZEND_DECLARE_INHERITED_CLASS;
@@ -2158,7 +2160,7 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod
 
        opline->op2.u.constant.value.str.val = estrndup(new_class_entry->name, new_class_entry->name_length);
        opline->op2.u.constant.value.str.len = new_class_entry->name_length;
-
+       
        zend_hash_update(CG(class_table), opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, &new_class_entry, sizeof(zend_class_entry *), NULL);
        CG(active_class_entry) = new_class_entry;
 }
@@ -2167,11 +2169,7 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod
 void zend_do_end_class_declaration(znode *class_token TSRMLS_DC)
 {
        do_inherit_parent_constructor(CG(active_class_entry));
-       CG(active_class_entry) = class_token->u.previously_active_class_entry;
-       if (CG(active_ce_parent_class_name).value.str.val) {
-               efree(CG(active_ce_parent_class_name).value.str.val);
-               CG(active_ce_parent_class_name).value.str.val = NULL;
-       }
+       CG(active_class_entry) = NULL;
 }
 
 void mangle_property_name(char **dest, int *dest_length, char *src1, int src1_length, char *src2, int src2_length)
@@ -3180,6 +3178,116 @@ void zend_destroy_property_info(zend_property_info *property_info)
        efree(property_info->name);
 }
 
+void zend_init_namespace(zend_namespace *ns TSRMLS_DC)
+{
+       zend_hash_init(&ns->function_table, 10, NULL, ZEND_FUNCTION_DTOR, 0);
+       zend_hash_init(&ns->class_table, 10, NULL, ZEND_CLASS_DTOR, 0);
+       zend_hash_init(&ns->constants_table, 10, NULL, ZVAL_PTR_DTOR, 0);
+       ALLOC_HASHTABLE(ns->static_members);
+       zend_hash_init(ns->static_members, 0, NULL, ZVAL_PTR_DTOR, 0);
+       ns->constructor = NULL;
+       ns->type = ZEND_NAMESPACE;
+}
+
+void zend_do_begin_namespace(znode *ns_token, znode *ns_name TSRMLS_DC)
+{
+       zend_namespace *ns = emalloc(sizeof(zend_namespace));
+       zend_op *opline;
+       
+       zend_str_tolower(ns_name->u.constant.value.str.val, ns_name->u.constant.value.str.len);
+       ns->name = ns_name->u.constant.value.str.val;
+       ns->name_length = ns_name->u.constant.value.str.len;
+
+       if(zend_hash_add(&CG(global_namespace).class_table, ns->name, ns->name_length+1, (void **)&ns, sizeof(zend_namespace *), NULL) != SUCCESS) {
+               efree(ns);
+               zend_error(E_COMPILE_ERROR, "Cannot redefine namespace '%s' - class or namespace with this name already defined", ns->name);
+       }
+
+       opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+
+       opline->opcode = ZEND_DECLARE_NAMESPACE;
+       opline->op1.op_type = IS_CONST;
+       opline->op1.u.constant.type = IS_STRING;
+       opline->op1.u.constant.value.str.val = estrndup(ns->name, ns->name_length);
+       opline->op1.u.constant.value.str.len = ns->name_length;
+       opline->op1.u.constant.refcount = 1;
+       SET_UNUSED(opline->op2);
+
+       zend_init_namespace(ns TSRMLS_CC);
+
+       ns->constructor = emalloc(sizeof(zend_op_array));
+       init_op_array((zend_op_array *)ns->constructor, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
+       ns->constructor->op_array.namespace = CG(active_namespace);
+
+       ns_token->u.op_array = CG(active_op_array);     
+       
+       CG(active_op_array) = &ns->constructor->op_array;
+       CG(active_namespace) = ns;
+
+       /* new symbol tables */
+       CG(class_table) = &ns->class_table;
+       CG(function_table) = &ns->function_table;
+       
+       fprintf(stderr, "Start namespace '%s'\n", ns->name);
+}
+
+void zend_do_end_namespace(znode *ns_token TSRMLS_DC)
+{
+       zend_namespace *ns = CG(active_op_array)->namespace;
+       int handle = CG(handle_op_arrays);
+
+       
+       zend_do_return(NULL, 0 TSRMLS_CC);
+       CG(handle_op_arrays) = 0;
+       pass_two(CG(active_op_array) TSRMLS_CC);
+       CG(handle_op_arrays) = handle;
+       
+       CG(active_op_array)->namespace = CG(active_namespace);
+
+       CG(active_namespace) = ns;
+       CG(active_op_array) = ns_token->u.op_array;
+       /* restore symbol tables */
+       CG(class_table) = &CG(active_namespace)->class_table;
+       CG(function_table) = &CG(active_namespace)->function_table;
+       
+       fprintf(stderr, "End namespace\n");
+}
+
+void zend_do_declare_namespace_var(znode *var_name, znode *value TSRMLS_DC)
+{
+       zval *var;
+
+       ALLOC_ZVAL(var);
+
+       if (value) {
+               *var = value->u.constant;
+       } else {
+               INIT_PZVAL(var);
+               var->type = IS_NULL;
+       }
+
+       zend_hash_update(CG(active_namespace)->static_members, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &var, sizeof(zval *), NULL);
+
+       FREE_PNODE(var_name);
+}
+
+void zend_do_declare_namespace_constant(znode *var_name, znode *value TSRMLS_DC)
+{
+       zval *var;
+
+       ALLOC_ZVAL(var);
+
+       if (value) {
+               *var = value->u.constant;
+       } else {
+               INIT_PZVAL(var);
+               var->type = IS_NULL;
+       }
+
+       zend_hash_update(&CG(active_namespace)->constants_table, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &var, sizeof(zval *), NULL);
+
+       FREE_PNODE(var_name);
+}
 
 void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers)
 {
@@ -3211,6 +3319,8 @@ void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers
                ce->__call = NULL;
                ce->create_object = NULL;
        }
+
+       ce->namespace = CG(active_namespace);
 }
 
 /*
index ec82fe727a834a43b34dcbe6f2aa360bf1269068..a43501ad36a334dd9bc6fb9300e0da09b2bbac32 100644 (file)
@@ -53,7 +53,6 @@ typedef struct _znode {
                zend_uint var;
                zend_uint opline_num; /*  Needs to be signed */
                zend_op_array *op_array;
-               zend_class_entry *previously_active_class_entry; /* Used at compile-time */
                zend_op *jmp_addr;
                struct {
                        zend_uint var;  /* dummy */
@@ -119,6 +118,7 @@ struct _zend_op_array {
        char *function_name;            /* MUST be the third element of this struct! */
        zend_class_entry *scope;        /* MUST be the fourth element of this struct! */
        zend_uint fn_flags;                             /* MUST be the fifth element of this struct! */
+       zend_namespace *namespace;
 
        zend_uint *refcount;
 
@@ -154,6 +154,7 @@ typedef struct _zend_internal_function {
        char *function_name;            /* MUST be the third element of this struct! */
        zend_class_entry *scope;        /* MUST be the fourth element of this struct! */
        zend_uint fn_flags;                             /* MUST be the fifth element of this struct! */
+       zend_namespace *namespace;
 
        void (*handler)(INTERNAL_FUNCTION_PARAMETERS);
 } zend_internal_function;
@@ -169,6 +170,7 @@ typedef union _zend_function {
                char *function_name;
                zend_class_entry *scope;
                zend_uint fn_flags;
+               zend_namespace *namespace;
        } common;
        
        zend_op_array op_array;
@@ -322,7 +324,7 @@ void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initia
 int zend_do_begin_function_call(znode *function_name TSRMLS_DC);
 void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC);
 void zend_do_begin_dynamic_function_call(znode *function_name TSRMLS_DC);
-void do_fetch_class(znode *result, znode *class_entry, znode *class_name TSRMLS_DC);
+void do_fetch_class(znode *result, znode *namespace_name, znode *class_name TSRMLS_DC);
 void do_fetch_class_name(znode *result, znode *class_entry, znode *class_name, zend_bool case_sensitive TSRMLS_DC);
 void zend_do_begin_class_member_function_call(znode *class_name, znode *function_name TSRMLS_DC);
 void zend_do_end_function_call(znode *function_name, znode *result, znode *argument_list, int is_method, int is_dynamic_fcall TSRMLS_DC);
@@ -445,12 +447,19 @@ ZEND_API void destroy_zend_function(zend_function *function);
 ZEND_API void destroy_zend_class(zend_class_entry **pce);
 void zend_class_add_ref(zend_class_entry **ce);
 
+void zend_do_begin_namespace(znode *ns_token, znode *ns_name TSRMLS_DC);
+void zend_do_end_namespace(znode *ns_token TSRMLS_DC);
+void zend_init_namespace(zend_namespace *ns TSRMLS_DC);
+void zend_do_declare_namespace_var(znode *name, znode *value TSRMLS_DC);
+void zend_do_declare_namespace_constant(znode *name, znode *value TSRMLS_DC);
+ZEND_API void destroy_zend_namespace(zend_namespace **pns);
 
 void zend_duplicate_property_info(zend_property_info *property_info);
 void zend_destroy_property_info(zend_property_info *property_info);
 
 #define ZEND_FUNCTION_DTOR (void (*)(void *)) destroy_zend_function
 #define ZEND_CLASS_DTOR (void (*)(void *)) destroy_zend_class
+#define ZEND_NAMESPACE_DTOR (void (*)(void *)) destroy_zend_namespace
 
 zend_op *get_next_op(zend_op_array *op_array TSRMLS_DC);
 void init_op(zend_op *op TSRMLS_DC);
@@ -648,6 +657,8 @@ int zendlex(znode *zendlval TSRMLS_DC);
 
 #define ZEND_RAISE_ABSTRACT_ERROR      142
 
+#define ZEND_DECLARE_NAMESPACE  143
+
 /* end of block */
 
 
@@ -664,6 +675,7 @@ int zendlex(znode *zendlval TSRMLS_DC);
 #define ZEND_FETCH_CLASS_SELF          1
 #define ZEND_FETCH_CLASS_PARENT                2
 #define ZEND_FETCH_CLASS_MAIN          3
+#define ZEND_FETCH_CLASS_GLOBAL                4
 
 
 /* variable parsing type (compile-time) */
@@ -694,6 +706,7 @@ int zendlex(znode *zendlval TSRMLS_DC);
 
 #define ZEND_INTERNAL_CLASS            1
 #define ZEND_USER_CLASS                        2
+#define ZEND_NAMESPACE          3
 
 #define ZEND_EVAL                              (1<<0)
 #define ZEND_INCLUDE                   (1<<1)
index 956dfa53a1e50e71fda48b24a6b9549adddfc0c5..826e6071faf34f8d7b23902ecb9012dab2aef7b5 100644 (file)
@@ -80,7 +80,7 @@ void clean_module_constants(int module_number TSRMLS_DC)
 
 int zend_startup_constants(TSRMLS_D)
 {
-       EG(zend_constants) = &CG(main_class).constants_table;
+       EG(zend_constants) = &CG(global_namespace).constants_table;
 
        if (zend_hash_init(EG(zend_constants), 20, NULL, ZEND_CONSTANT_DTOR, 1)==FAILURE) {
                return FAILURE;
index cdb7fa6844322d49fd17acf6bb56d97f3f2cd9d5..4caed9cb1c0dd9db94c1e737c26f9613a889f0de 100644 (file)
@@ -1208,7 +1208,10 @@ ZEND_API void execute(zend_op_array *op_array TSRMLS_DC)
         */
        EX(function_state).function_symbol_table = NULL;
 #endif
-
+       if(EG(active_namespace) != op_array->namespace) {
+               zend_switch_namespace(op_array->namespace TSRMLS_CC);
+       }
+       
        while (1) {
 #ifdef ZEND_WIN32
                if (EG(timed_out)) {
@@ -2299,7 +2302,7 @@ int zend_fetch_class_handler(ZEND_OPCODE_HANDLER_ARGS)
        zval tmp;
        int retval;
        
-       if (EX(opline)->op1.op_type == IS_UNUSED) {
+       if (EX(opline)->op2.op_type == IS_UNUSED) {
                if (EX(opline)->extended_value == ZEND_FETCH_CLASS_SELF) {
                        if (!EG(scope)) {
                                zend_error(E_ERROR, "Cannot access self:: when no class scope is active");
@@ -2307,7 +2310,7 @@ int zend_fetch_class_handler(ZEND_OPCODE_HANDLER_ARGS)
                        EX_T(EX(opline)->result.u.var).EA.class_entry = EG(scope);
                        NEXT_OPCODE();
                } else if (EX(opline)->extended_value == ZEND_FETCH_CLASS_MAIN) {
-                       EX_T(EX(opline)->result.u.var).EA.class_entry = EG(main_class_ptr);
+                       EX_T(EX(opline)->result.u.var).EA.class_entry = EG(global_namespace_ptr);
                        NEXT_OPCODE();
                } else if (EX(opline)->extended_value == ZEND_FETCH_CLASS_PARENT) {
                        if (!EG(scope)) {
@@ -2318,7 +2321,7 @@ int zend_fetch_class_handler(ZEND_OPCODE_HANDLER_ARGS)
                        }
                        EX_T(EX(opline)->result.u.var).EA.class_entry = EG(scope)->parent;
                        NEXT_OPCODE();
-               }
+               } 
        }
 
        is_const = (EX(opline)->op2.op_type == IS_CONST);
@@ -2338,10 +2341,28 @@ int zend_fetch_class_handler(ZEND_OPCODE_HANDLER_ARGS)
                class_name_strlen = tmp.value.str.len;
        }
        
-       if (EX(opline)->op1.op_type == IS_UNUSED) {
+       if (EX(opline)->op1.op_type == IS_UNUSED && EX(opline)->extended_value != ZEND_FETCH_CLASS_GLOBAL) {
                retval = zend_lookup_class(class_name_strval, class_name_strlen, &pce TSRMLS_CC);
+
+               if(retval == FAILURE) {
+                       /* try namespace */
+                       if(zend_hash_find(&EG(global_namespace_ptr)->class_table, class_name_strval, class_name_strlen+1, (void **)&pce) == SUCCESS && (*pce)->type == ZEND_NAMESPACE) {
+                               retval = SUCCESS;
+                       }
+               }
+
        } else {
-               retval = zend_hash_find(&EX_T(EX(opline)->op1.u.var).EA.class_entry->class_table, class_name_strval, class_name_strlen+1, (void **)&pce);
+               zend_namespace *ns;
+               /* Looking for namespace */
+               if(EX(opline)->extended_value == ZEND_FETCH_CLASS_GLOBAL) {
+                       ns = EG(global_namespace_ptr);
+               } else {
+                       if (zend_hash_find(&EG(global_namespace_ptr)->class_table, EX(opline)->op1.u.constant.value.str.val, EX(opline)->op1.u.constant.value.str.len+1, (void **)&pce) == FAILURE || (*pce)->type != ZEND_NAMESPACE) {
+                               zend_error(E_ERROR, "Namespace '%s' not found", EX(opline)->op1.u.constant.value.str.val);
+                       }
+                       ns = *pce;
+               }
+               retval = zend_hash_find(&ns->class_table, class_name_strval, class_name_strlen+1, (void **)&pce);
        }
 
        if (retval == FAILURE) {
@@ -2535,7 +2556,10 @@ int zend_init_fcall_by_name_handler(ZEND_OPCODE_HANDLER_ARGS)
                }
                */
                if (zend_hash_find(EG(function_table), function_name_strval, function_name_strlen+1, (void **) &function)==FAILURE) {
-                       zend_error(E_ERROR, "Call to undefined function:  %s()", function_name_strval);
+                       /* try global space also */
+                       if(zend_hash_find(&EG(global_namespace_ptr)->function_table, function_name_strval, function_name_strlen+1, (void **) &function)==FAILURE) {
+                               zend_error(E_ERROR, "Call to undefined function:  %s()", function_name_strval);
+                       }
                }
                EX(calling_scope) = function->common.scope;
                EX(object) = NULL;
@@ -2557,7 +2581,8 @@ int zend_do_fcall_common_helper(ZEND_OPCODE_HANDLER_ARGS)
        zend_class_entry *current_scope;
        zval *current_this;
        int return_value_used = RETURN_VALUE_USED(EX(opline));
-
+       zend_namespace *active_namespace = EG(active_namespace);
+       
        zend_ptr_stack_n_push(&EG(argument_stack), 2, (void *) EX(opline)->extended_value, NULL);
 
        EX_T(EX(opline)->result.u.var).var.ptr_ptr = &EX_T(EX(opline)->result.u.var).var.ptr;
@@ -2647,6 +2672,9 @@ int zend_do_fcall_common_helper(ZEND_OPCODE_HANDLER_ARGS)
        }
        zend_ptr_stack_n_pop(&EG(arg_types_stack), 3, &EX(calling_scope), &EX(object), &EX(fbc));
        
+       if(EG(active_namespace) != active_namespace) {
+               zend_switch_namespace(active_namespace TSRMLS_CC);
+       }
        EX(function_state).function = (zend_function *) op_array;
        EG(function_state_ptr) = &EX(function_state);
        zend_ptr_stack_clear_multiple(TSRMLS_C);
@@ -3105,7 +3133,7 @@ int zend_clone_handler(ZEND_OPCODE_HANDLER_ARGS)
 
 int zend_fetch_constant_handler(ZEND_OPCODE_HANDLER_ARGS)
 {
-       zend_class_entry *ce;
+       zend_class_entry *ce = NULL;
        zval **value;
 
        if (EX(opline)->op1.op_type == IS_UNUSED) {
@@ -3118,6 +3146,16 @@ int zend_fetch_constant_handler(ZEND_OPCODE_HANDLER_ARGS)
                                NEXT_OPCODE();
                        }
                }
+               if(EG(active_namespace) != EG(global_namespace_ptr)) {
+                       /* if we are not global, go find in local constant table */
+                       if (zend_hash_find(&EG(active_namespace)->constants_table, EX(opline)->op2.u.constant.value.str.val, EX(opline)->op2.u.constant.value.str.len+1, (void **) &value) == SUCCESS) {
+                               zval_update_constant(value, (void *) 1 TSRMLS_CC);
+                               EX_T(EX(opline)->result.u.var).tmp_var = **value;
+                               zval_copy_ctor(&EX_T(EX(opline)->result.u.var).tmp_var);
+                               NEXT_OPCODE();
+                       }
+               }
+               
                if (!zend_get_constant(EX(opline)->op2.u.constant.value.str.val, EX(opline)->op2.u.constant.value.str.len, &EX_T(EX(opline)->result.u.var).tmp_var TSRMLS_CC)) {
                        zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
                                                EX(opline)->op2.u.constant.value.str.val,
@@ -3130,7 +3168,7 @@ int zend_fetch_constant_handler(ZEND_OPCODE_HANDLER_ARGS)
        
        ce = EX_T(EX(opline)->op1.u.var).EA.class_entry;
        
-       if (&ce->constants_table == &EG(main_class_ptr)->constants_table) {
+       if (&ce->constants_table == &EG(global_namespace_ptr)->constants_table) {
                if (!zend_get_constant(EX(opline)->op2.u.constant.value.str.val, EX(opline)->op2.u.constant.value.str.len, &EX_T(EX(opline)->result.u.var).tmp_var TSRMLS_CC)) {
                        zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
                                                EX(opline)->op2.u.constant.value.str.val,
@@ -3308,6 +3346,7 @@ int zend_include_or_eval_handler(ZEND_OPCODE_HANDLER_ARGS)
                                        }       
                                
                                        if (zend_hash_add(&EG(included_files), opened_path, strlen(opened_path)+1, (void *)&dummy, sizeof(int), NULL)==SUCCESS) {
+                                               CG(active_namespace) = EG(active_namespace);
                                                new_op_array = zend_compile_file(&file_handle, (EX(opline)->op2.u.constant.value.lval==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE) TSRMLS_CC);
                                                zend_destroy_file_handle(&file_handle TSRMLS_CC);
                                                opened_path = NULL; /* zend_destroy_file_handle() already frees it */
@@ -3330,11 +3369,13 @@ int zend_include_or_eval_handler(ZEND_OPCODE_HANDLER_ARGS)
                        break;
                case ZEND_INCLUDE:
                case ZEND_REQUIRE:
+                       CG(active_namespace) = EG(active_namespace);
                        new_op_array = compile_filename(EX(opline)->op2.u.constant.value.lval, inc_filename TSRMLS_CC);
                        break;
                case ZEND_EVAL: {
                                char *eval_desc = zend_make_compiled_string_description("eval()'d code" TSRMLS_CC);
 
+                               CG(active_namespace) = EG(active_namespace);
                                new_op_array = compile_string(inc_filename, eval_desc TSRMLS_CC);
                                efree(eval_desc);
                        }
@@ -3349,7 +3390,7 @@ int zend_include_or_eval_handler(ZEND_OPCODE_HANDLER_ARGS)
        if (new_op_array) {
                zval *saved_object;
                zend_function *saved_function;
-
+               zend_namespace *active_namespace = EG(active_namespace);
 
                EG(return_value_ptr_ptr) = EX_T(EX(opline)->result.u.var).var.ptr_ptr;
                EG(active_op_array) = new_op_array;
@@ -3363,6 +3404,9 @@ int zend_include_or_eval_handler(ZEND_OPCODE_HANDLER_ARGS)
                
                zend_execute(new_op_array TSRMLS_CC);
                
+               if(EG(active_namespace) != active_namespace) {
+                       zend_switch_namespace(active_namespace TSRMLS_CC);
+               }
                EX(function_state).function = saved_function;
                EX(object) = saved_object;
                
@@ -3876,6 +3920,57 @@ int zend_nop_handler(ZEND_OPCODE_HANDLER_ARGS)
        NEXT_OPCODE();
 }
 
+int zend_declare_namespace_handler(ZEND_OPCODE_HANDLER_ARGS)
+{
+       zend_op_array *new_op_array=NULL;
+       zval **original_return_value = EG(return_value_ptr_ptr);
+       zval *namespace_name = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
+       zend_namespace **pns;
+       zval *saved_object;
+       zend_function *saved_function;
+       zend_namespace *active_namespace = EG(active_namespace);
+
+       if (Z_TYPE_P(namespace_name) != IS_STRING) {
+               zend_error(E_ERROR, "Internal error: Invalid type in namespace definition - %d", Z_TYPE_P(namespace_name));
+       }
+
+       if(zend_hash_find(&EG(global_namespace_ptr)->class_table, Z_STRVAL_P(namespace_name), Z_STRLEN_P(namespace_name)+1, (void **)&pns) != SUCCESS || (*pns)->type != ZEND_NAMESPACE) {
+               zend_error(E_ERROR, "Internal error: Cannot locate namespace '%s'", Z_STRVAL_P(namespace_name));
+       }
+
+       new_op_array = (*pns)->constructor;
+       
+       FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1));
+       EX_T(EX(opline)->result.u.var).var.ptr_ptr = &EX_T(EX(opline)->result.u.var).var.ptr;
+
+       EG(return_value_ptr_ptr) = EX_T(EX(opline)->result.u.var).var.ptr_ptr;
+       EG(active_op_array) = new_op_array;
+       EX_T(EX(opline)->result.u.var).var.ptr = NULL;
+
+       saved_object = EX(object);
+       saved_function = EX(function_state).function;
+
+       EX(function_state).function = (zend_function *) new_op_array;
+       EX(object) = NULL;
+               
+       zend_execute(new_op_array TSRMLS_CC);
+               
+       if(EG(active_namespace) != active_namespace) {
+               zend_switch_namespace(active_namespace TSRMLS_CC);
+       }
+       EX(function_state).function = saved_function;
+       EX(object) = saved_object;
+       
+       if (EX_T(EX(opline)->result.u.var).var.ptr) {
+               zval_ptr_dtor(&EX_T(EX(opline)->result.u.var).var.ptr);
+       } 
+       
+       EG(opline_ptr) = &EX(opline);
+       EG(active_op_array) = op_array;
+       EG(function_state_ptr) = &EX(function_state);
+       EG(return_value_ptr_ptr) = original_return_value;
+       NEXT_OPCODE();
+}
 
 void zend_init_opcodes_handlers()
 {
@@ -4051,6 +4146,7 @@ void zend_init_opcodes_handlers()
        zend_opcode_handlers[ZEND_DECLARE_FUNCTION] = zend_declare_function_handler;
 
        zend_opcode_handlers[ZEND_RAISE_ABSTRACT_ERROR] = zend_raise_abstract_error_handler;
+       zend_opcode_handlers[ZEND_DECLARE_NAMESPACE] = zend_declare_namespace_handler;
 }
 
 /*
index 4168c2db9273fc352a740bdfb4f597e7e5c8ce7e..252ea0c97babc7fabb32a1afec21a33e8a81e32f 100644 (file)
@@ -69,6 +69,7 @@ static inline void safe_free_zval_ptr(zval *p)
 }
 ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***ce TSRMLS_DC);
 ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC);
+void zend_switch_namespace(zend_namespace *ns TSRMLS_DC);
 
 static inline int i_zend_is_true(zval *op)
 {
index 275278e29df6a793d9bcfe1cb3b4bc5d16a80c7c..77d43788e2f094873ede1a9d63e5c762c0ce9e3a 100644 (file)
@@ -177,9 +177,10 @@ void init_executor(TSRMLS_D)
        EG(exception) = NULL;
 
        EG(scope) = NULL;
+       EG(active_namespace) = &CG(global_namespace);
 
-       EG(main_class_ptr) = &CG(main_class);
-       CG(main_class).static_members = &EG(symbol_table);
+       EG(global_namespace_ptr) = &CG(global_namespace);
+       CG(global_namespace).static_members = &EG(symbol_table);
 
        EG(current_execute_data) = NULL;
 
@@ -191,6 +192,11 @@ void init_executor(TSRMLS_D)
 
 void shutdown_executor(TSRMLS_D)
 {
+       /* return to global namespace here */
+       if(EG(active_namespace) != EG(global_namespace_ptr)) {
+               zend_switch_namespace(EG(global_namespace_ptr));
+       }
+
        zend_try {
                zend_ptr_stack_destroy(&EG(arg_types_stack));
 
@@ -531,7 +537,7 @@ int call_user_function_ex(HashTable *function_table, zval **object_pp, zval *fun
        zend_class_entry *current_scope;
        zend_class_entry *calling_scope = NULL;
        zval *current_this;
-
+       zend_namespace *current_namespace = EG(active_namespace);
        zend_execute_data execute_data;
 
        /* Initialize execute_data */
@@ -708,6 +714,7 @@ int call_user_function_ex(HashTable *function_table, zval **object_pp, zval *fun
        }
        zend_ptr_stack_clear_multiple(TSRMLS_C);
        EG(function_state_ptr) = original_function_state_ptr;
+       EG(active_namespace) = current_namespace;
 
        if (EG(This)) {
                zval_ptr_dtor(&EG(This));
@@ -727,11 +734,6 @@ ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***
        zval *retval_ptr;
        int retval;
 
-       if (EG(scope)) {
-               if (zend_hash_find(&EG(scope)->class_table, name, name_length+1, (void **) ce) == SUCCESS) {
-                       return SUCCESS;
-               }
-       }
        if (zend_hash_find(EG(class_table), name, name_length+1, (void **) ce) == SUCCESS) {
                return SUCCESS;
        }
@@ -1037,6 +1039,17 @@ void zend_unset_timeout(TSRMLS_D)
 #endif
 }
 
+void zend_switch_namespace(zend_namespace *ns TSRMLS_DC)
+{
+       if(NULL == ns) {
+               return;
+       }
+       EG(active_namespace) = ns;
+       EG(function_table) = &ns->function_table;
+       EG(class_table) = &ns->class_table;
+/*     EG(zend_constants) = &ns->constants_table; */
+}
+
 /*
  * Local variables:
  * tab-width: 4
index 0508757c41bd385a1bcb2fcf1d1458cf5d711596..e5c6520787c1cc4cc538fadabfc627cded6e14c5 100644 (file)
@@ -70,7 +70,7 @@ struct _zend_compiler_globals {
        zend_stack declare_stack;
 
        zend_class_entry *active_class_entry;
-       zval active_ce_parent_class_name;
+       zend_namespace *active_namespace;
 
        /* variables for list() compilation */
        zend_llist list_llist;
@@ -88,9 +88,11 @@ struct _zend_compiler_globals {
 
        zend_op_array *active_op_array;
 
-       zend_class_entry main_class;
+       zend_namespace global_namespace;
+       
        HashTable *function_table;      /* function symbol table */
        HashTable *class_table;         /* class table */
+       HashTable namespace_table; /* namespaces */
 
        HashTable filenames_table;
 
@@ -167,7 +169,8 @@ struct _zend_executor_globals {
        HashTable *zend_constants;      /* constants table */
 
        zend_class_entry *scope;
-       zend_class_entry *main_class_ptr;
+       zend_namespace *global_namespace_ptr;
+       zend_namespace *active_namespace;
 
        zval *This;
 
index 4dc5ba8b686b36287bba851a39229cb56033f3df..3d2ebd601fb1682ef6fa4b9948b76ccd38d0746e 100644 (file)
 %token T_CURLY_OPEN
 %token T_PAAMAYIM_NEKUDOTAYIM
 %token T_IMPORT T_FROM
+%token T_NAMESPACE_NAME
+%token T_NAMESPACE
 
 %% /* Rules */
 
@@ -156,6 +158,7 @@ top_statement:
                statement
        |       function_declaration_statement  { zend_do_early_binding(TSRMLS_C); }
        |       class_declaration_statement
+       |   namespace_declaration_statement
 ;
 
 
@@ -211,10 +214,10 @@ unticked_statement:
        |       T_DECLARE { $1.u.opline_num = get_next_op_number(CG(active_op_array)); zend_do_declare_begin(TSRMLS_C); } '(' declare_list ')' declare_statement { zend_do_declare_end(&$1 TSRMLS_CC); }
        |       ';'             /* empty statement */
        |       T_TRY { zend_do_try(&$1 TSRMLS_CC); } '{' inner_statement_list '}'
-               T_CATCH '(' catch_or_import_class_entry T_VARIABLE ')' { zend_do_begin_catch(&$1, &$8, &$9, 1 TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); }
+               T_CATCH '(' catch_class_entry T_VARIABLE ')' { zend_do_begin_catch(&$1, &$8, &$9, 1 TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); }
                additional_catches
        |       T_THROW expr ';' { zend_do_throw(&$2 TSRMLS_CC); }
-       |       T_IMPORT { zend_do_begin_import(TSRMLS_C); } import_rule T_FROM catch_or_import_class_entry { zend_do_end_import(&$5 TSRMLS_CC); } ';'
+       |       T_IMPORT { zend_do_begin_import(TSRMLS_C); } import_rule T_FROM import_namespace { zend_do_end_import(&$5 TSRMLS_CC); } ';'
 ;
 
 
@@ -243,8 +246,8 @@ additional_catches:
 ;
 
 non_empty_additional_catches:
-               non_empty_additional_catches T_CATCH '(' catch_or_import_class_entry T_VARIABLE ')' { zend_do_begin_catch(&$2, &$4, &$5, 0 TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$2 TSRMLS_CC); }
-       |       T_CATCH '(' catch_or_import_class_entry T_VARIABLE ')' { zend_do_begin_catch(&$1, &$3, &$4, 0 TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); }
+               non_empty_additional_catches T_CATCH '(' catch_class_entry T_VARIABLE ')' { zend_do_begin_catch(&$2, &$4, &$5, 0 TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$2 TSRMLS_CC); }
+       |       T_CATCH '(' catch_class_entry T_VARIABLE ')' { zend_do_begin_catch(&$1, &$3, &$4, 0 TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); }
 ;
 
 
@@ -287,13 +290,45 @@ unticked_class_declaration_statement:
                T_CLASS declaration_class_name extends_from '{' { zend_do_begin_class_declaration(&$1, &$2, &$3 TSRMLS_CC); } class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); }
 ;
 
+namespace_declaration_statement:
+               T_NAMESPACE T_STRING '{' { zend_do_begin_namespace(&$1, &$2 TSRMLS_CC); } namespace_statement_list '}' { zend_do_end_namespace(&$1 TSRMLS_CC); }
+;
+
+namespace_statement_list:
+               namespace_statement_list namespace_statement
+       |       /* empty */
+;
+
+namespace_statement:
+               T_VAR namespace_var_declaration_list ';'
+       |       namespace_const_declaration ';'
+       |       function_declaration_statement  { zend_do_early_binding(TSRMLS_C); }
+       |       class_declaration_statement
+       |       namespace_declaration_statement
+;
+
+namespace_var_declaration_list:
+               namespace_var_declaration_list ',' namespace_var_declaration
+       |       namespace_var_declaration
+;
+
+namespace_var_declaration:
+               T_VARIABLE { zend_do_declare_namespace_var(&$1, NULL TSRMLS_CC); }
+       |       T_VARIABLE '=' static_scalar { zend_do_declare_namespace_var(&$1, &$3 TSRMLS_CC); }
+;
+
+namespace_const_declaration:
+               namespace_const_declaration ',' T_STRING '=' static_scalar      { zend_do_declare_namespace_constant(&$3, &$5 TSRMLS_CC); }
+       |       T_CONST T_STRING '=' static_scalar      { zend_do_declare_namespace_constant(&$2, &$4 TSRMLS_CC); }
+;
+
 extends_from:
-               /* empty */                     { $$.op_type = IS_UNUSED; }
-       |       T_EXTENDS catch_or_import_class_entry   { $$ = $2; }
+               /* empty */                                     { $$.op_type = IS_UNUSED; }
+       |       T_EXTENDS catch_class_entry     { $$ = $2; }
 ;
 
 declaration_class_name:
-       |       parse_class_name_entry T_STRING { do_fetch_class_name(&$$, &$1, &$2, 0 TSRMLS_CC); }
+       |       namespace_prefix T_PAAMAYIM_NEKUDOTAYIM T_STRING { do_fetch_class_name(&$$, &$1, &$3, 0 TSRMLS_CC); }
        |       T_STRING { $$ = $1; zend_str_tolower($$.u.constant.value.str.val, $$.u.constant.value.str.len); }
 ;
 
@@ -421,7 +456,7 @@ global_var_list:
 
 global_var:
                T_VARIABLE                      { $$ = $1; }
-       |       '$' r_variable                  { $$ = $2; }
+       |       '$' r_variable          { $$ = $2; }
        |       '$' '{' expr '}'        { $$ = $3; }
 ;
 
@@ -446,7 +481,6 @@ class_statement:
        |       class_constant_declaration ';'
        |       method_modifiers T_FUNCTION { $2.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$5, 1, $4.op_type, $1.u.constant.value.lval TSRMLS_CC); } '(' 
                        parameter_list ')' method_body { zend_do_abstract_method(&$5, &$1, &$10 TSRMLS_CC); zend_do_end_function_declaration(&$2 TSRMLS_CC); }
-       |       T_CLASS T_STRING extends_from '{' { zend_do_begin_class_declaration(&$1, &$2, &$3 TSRMLS_CC); } class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); }
 ;
 
 
@@ -589,32 +623,37 @@ function_call:
 ;
 
 parse_class_entry:
-               parse_class_entry T_STRING T_PAAMAYIM_NEKUDOTAYIM { do_fetch_class(&$$, &$1, &$2 TSRMLS_CC); }
+               T_NAMESPACE_NAME T_PAAMAYIM_NEKUDOTAYIM T_STRING T_PAAMAYIM_NEKUDOTAYIM { do_fetch_class(&$$, &$1, &$3 TSRMLS_CC); }
        |       T_STRING T_PAAMAYIM_NEKUDOTAYIM { do_fetch_class(&$$, NULL, &$1 TSRMLS_CC); }
 ;
 
-parse_class_name_entry:
-               parse_class_name_entry T_STRING T_PAAMAYIM_NEKUDOTAYIM { do_fetch_class_name(&$$, &$1, &$2, 0 TSRMLS_CC); }
-       |       T_STRING T_PAAMAYIM_NEKUDOTAYIM { $$ = $1; zend_str_tolower($$.u.constant.value.str.val, $$.u.constant.value.str.len); }
-;
+catch_class_entry:
+               namespace_prefix T_PAAMAYIM_NEKUDOTAYIM T_STRING { do_fetch_class(&$$, &$1, &$3 TSRMLS_CC); }
+       |       T_STRING { do_fetch_class(&$$, NULL, &$1 TSRMLS_CC); }
+ ;
 
-catch_or_import_class_entry:
-               parse_class_entry T_STRING { do_fetch_class(&$$, &$1, &$2 TSRMLS_CC); }
+import_namespace:
+               T_NAMESPACE_NAME { do_fetch_class(&$$, NULL, &$1 TSRMLS_CC); }
        |       T_STRING { do_fetch_class(&$$, NULL, &$1 TSRMLS_CC); }
 ;
 
 new_class_entry:
-               parse_class_entry static_or_variable_string { do_fetch_class(&$$, &$1, &$2 TSRMLS_CC); }
+               namespace_prefix T_PAAMAYIM_NEKUDOTAYIM static_or_variable_string { do_fetch_class(&$$, &$1, &$3 TSRMLS_CC); }
        |       static_or_variable_string { do_fetch_class(&$$, NULL, &$1 TSRMLS_CC); }
 ;
 
+namespace_prefix:
+       T_NAMESPACE_NAME        { $$ = $1; }
+       | T_STRING                      { $$ = $1; }
+;      
+
 static_or_variable_string:
                T_STRING        { $$ = $1; }
        |       r_variable_without_static_member        { $$ = $1; }
 ;
 
 instanceof_expr:
-               parse_class_entry T_STRING { do_fetch_class(&$$, &$1, &$2 TSRMLS_CC); }
+               namespace_prefix T_PAAMAYIM_NEKUDOTAYIM T_STRING { do_fetch_class(&$$, &$1, &$3 TSRMLS_CC); }
        |       T_STRING { do_fetch_class(&$$, NULL, &$1 TSRMLS_CC); }
 ;
 
@@ -648,7 +687,7 @@ static_scalar: /* compile-time evaluated scalars */
        |       '+' static_scalar       { $$ = $2; }
        |       '-' static_scalar       { zval minus_one;  minus_one.type = IS_LONG; minus_one.value.lval = -1;  mul_function(&$2.u.constant, &$2.u.constant, &minus_one TSRMLS_CC);  $$ = $2; }
        |       T_ARRAY '(' static_array_pair_list ')' { $$ = $3; $$.u.constant.type = IS_CONSTANT_ARRAY; }
-       |       parse_class_name_entry T_STRING { zend_do_fetch_constant(&$$, &$1, &$2, ZEND_CT TSRMLS_CC); }
+       |       namespace_prefix T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_CT TSRMLS_CC); }
 ;
 
 
index 4139f1d8629cac4bad4ca8a58a31cb7f413339c8..6908e153183f4545c983d4d9b196717dbde5624a 100644 (file)
@@ -292,6 +292,7 @@ ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSR
                init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
                CG(in_compilation) = 1;
                CG(active_op_array) = op_array;
+               op_array->namespace = CG(active_namespace);
                compiler_result = zendparse(TSRMLS_C);
                zend_do_return(&retval_znode, 0 TSRMLS_CC);
                CG(in_compilation) = original_in_compilation;
@@ -405,6 +406,7 @@ zend_op_array *compile_string(zval *source_string, char *filename TSRMLS_DC)
        } else {
                init_op_array(op_array, ZEND_EVAL_CODE, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
                CG(active_op_array) = op_array;
+               op_array->namespace = CG(active_namespace);
                BEGIN(ST_IN_SCRIPTING);
                compiler_result = zendparse(TSRMLS_C);
 
@@ -481,6 +483,7 @@ ENCAPSED_TOKENS [\[\]{}$]
 ESCAPED_AND_WHITESPACE [\n\t\r #'.:;,()|^&+-/*=%!~<>?@]+
 ANY_CHAR (.|[\n])
 NEWLINE ("\r"|"\n"|"\r\n")
+NAMESPACE_NAME ({LABEL}":")+{LABEL}
 
 %option noyylineno
 %option noyywrap
@@ -618,6 +621,10 @@ NEWLINE ("\r"|"\n"|"\r\n")
        return T_EXTENDS;
 }
 
+<ST_IN_SCRIPTING>"namespace" {
+       return T_NAMESPACE;
+}
+
 <ST_IN_SCRIPTING,ST_DOUBLE_QUOTES,ST_BACKQUOTE,ST_HEREDOC>"->" {
        yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC);
        return T_OBJECT_OPERATOR;
@@ -1094,6 +1101,21 @@ NEWLINE ("\r"|"\n"|"\r\n")
        return T_STRING;
 }
 
+<ST_IN_SCRIPTING>{NAMESPACE_NAME} {
+       int i;
+
+       zendlval->value.str.val = (char *)estrndup(yytext, yyleng);
+       zendlval->value.str.len = yyleng;
+       zendlval->type = IS_STRING;
+       
+       /* Nuke this code */
+       for (i=0; i<yyleng; i++) {
+               if (zendlval->value.str.val[i] == ':') {
+                       zendlval->value.str.val[i] = '_';
+               }
+       }
+       return T_NAMESPACE_NAME;
+}
 
 <ST_HEREDOC>{ENCAPSED_STRING} {
        zendlval->value.str.val = (char *)estrndup(yytext, yyleng);
index 619c79168e3bc4b249ff7e15ce8363f3dda1f487..32bc40226952c88501dd92f6ae5434f13d24097e 100644 (file)
@@ -78,6 +78,7 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
        op_array->arg_types = NULL;
 
        op_array->scope = NULL;
+       op_array->namespace = NULL;
 
        op_array->brk_cont_array = NULL;
        op_array->last_brk_cont = 0;
@@ -166,9 +167,25 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce)
                        zend_hash_destroy(&ce->class_table);
                        free(ce);
                        break;
+               case ZEND_NAMESPACE:
+                       destroy_zend_namespace(pce);
+                       break;
        }
 }
 
+ZEND_API void destroy_zend_namespace(zend_namespace **pns)
+{
+       zend_namespace *ns = *pns;
+       zend_hash_destroy(&ns->function_table);
+       zend_hash_destroy(&ns->class_table);
+       zend_hash_destroy(&ns->constants_table);
+       zend_hash_destroy(ns->static_members);
+       FREE_HASHTABLE(ns->static_members);
+       destroy_op_array(ns->constructor);
+       efree(ns->constructor);
+       efree(ns->name);
+       efree(ns);
+}
 
 void zend_class_add_ref(zend_class_entry **ce)
 {