Browse Source

Namespace patch. Big changes:

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).
PHP-5
Stanislav Malyshev 23 years ago
parent
commit
a4c3b2ce80
  1. 16
      Zend/zend.c
  2. 14
      Zend/zend.h
  3. 146
      Zend/zend_compile.c
  4. 17
      Zend/zend_compile.h
  5. 2
      Zend/zend_constants.c
  6. 118
      Zend/zend_execute.c
  7. 1
      Zend/zend_execute.h
  8. 29
      Zend/zend_execute_API.c
  9. 9
      Zend/zend_globals.h
  10. 77
      Zend/zend_language_parser.y
  11. 22
      Zend/zend_language_scanner.l
  12. 17
      Zend/zend_opcode.c

16
Zend/zend.c

@ -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);

14
Zend/zend.h

@ -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);

146
Zend/zend_compile.c

@ -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);
}
/*

17
Zend/zend_compile.h

@ -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)

2
Zend/zend_constants.c

@ -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;

118
Zend/zend_execute.c

@ -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;
}
/*

1
Zend/zend_execute.h

@ -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)
{

29
Zend/zend_execute_API.c

@ -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

9
Zend/zend_globals.h

@ -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;

77
Zend/zend_language_parser.y

@ -139,6 +139,8 @@
%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); }
;

22
Zend/zend_language_scanner.l

@ -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);

17
Zend/zend_opcode.c

@ -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)
{

Loading…
Cancel
Save