RE: [PHP-DEV] Constans in namesapces
| From: | Dmitry Stogov | Date: | Wed, 22 Aug 2007 10:07:02 +0000 |
| Subject: | RE: [PHP-DEV] Constans in namesapces | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-31830@lists.php.net to get a copy of this message | ||
Sorry, The patch was removed.
Resending it.
Dmitry.
> -----Original Message-----
> From: Dmitry Stogov [mailto:dmitry@zend.com]
> Sent: Wednesday, August 22, 2007 1:02 PM
> To: 'PHP Internals List'
> Subject: [PHP-DEV] Constans in namesapces
>
>
> Hi,
>
> The proposed patch implements namespace support for
> constants. It allows to declare constants in namespaces in
> the same way as in classes. And these constants may be used
> in the same may as namespaces' functions.
>
> <?php
> namespace Foo;
> const BAR = 5;
> var_dump(BAR);
> ?>
>
> <?php
> include "foo.php";
> var_dump(Foo::BAR);
> ?>
>
> I am going to commit this patch on Friday.
> Any objections?
>
> Thanks. Dmitry.
>
>
Index: Zend/zend.c =================================================================== RCS file: /repository/ZendEngine2/zend.c,v retrieving revision 1.399 diff -u -p -d -r1.399 zend.c --- Zend/zend.c 21 Jul 2007 00:34:41 -0000 1.399 +++ Zend/zend.c 22 Aug 2007 08:27:42 -0000 @@ -696,7 +696,7 @@ static void zend_set_default_compile_tim static void zval_copy_persistent(zval *zv) /* {{{ */ { - if (Z_TYPE_P(zv) == IS_STRING || Z_TYPE_P(zv) == IS_CONSTANT) { + if (Z_TYPE_P(zv) == IS_STRING || (Z_TYPE_P(zv) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) { UChar *ustr; ustr = malloc(UBYTES(Z_STRLEN_P(zv)+1)); @@ -783,7 +783,7 @@ static void const_to_unicode(zend_consta free(c->name.s); c->name.u = uname; } - if (Z_TYPE(c->value) == IS_STRING || Z_TYPE(c->value) == IS_CONSTANT) { + if (Z_TYPE(c->value) == IS_STRING || (Z_TYPE(c->value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) { UChar *ustr; ustr = malloc(UBYTES(Z_STRLEN(c->value)+1)); Index: Zend/zend.h =================================================================== RCS file: /repository/ZendEngine2/zend.h,v retrieving revision 1.335 diff -u -p -d -r1.335 zend.h --- Zend/zend.h 21 Jul 2007 05:27:06 -0000 1.335 +++ Zend/zend.h 22 Aug 2007 08:27:42 -0000 @@ -467,7 +467,9 @@ typedef int (*zend_write_func_t)(const c #define IS_UNICODE 10 /* Ugly hack to support constants as static array indices */ -#define IS_CONSTANT_INDEX 0x80 +#define IS_CONSTANT_TYPE_MASK 0x0f +#define IS_CONSTANT_RT_NS_CHECK 0x10 +#define IS_CONSTANT_INDEX 0x80 /* overloaded elements data types */ Index: Zend/zend_builtin_functions.c =================================================================== RCS file: /repository/ZendEngine2/zend_builtin_functions.c,v retrieving revision 1.347 diff -u -p -d -r1.347 zend_builtin_functions.c --- Zend/zend_builtin_functions.c 8 Aug 2007 13:32:58 -0000 1.347 +++ Zend/zend_builtin_functions.c 22 Aug 2007 08:27:42 -0000 @@ -575,7 +575,7 @@ ZEND_FUNCTION(defined) } convert_to_text_ex(var); - if (zend_u_get_constant(Z_TYPE_PP(var), Z_UNIVAL_PP(var), Z_UNILEN_PP(var), &c, NULL TSRMLS_CC)) { + if (zend_u_get_constant_ex(Z_TYPE_PP(var), Z_UNIVAL_PP(var), Z_UNILEN_PP(var), &c, NULL, 0 TSRMLS_CC)) { zval_dtor(&c); RETURN_TRUE; } else { @@ -772,7 +772,7 @@ static void add_class_vars(zend_class_en /* this is necessary to make it able to work with default array * properties, returned to user */ - if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || Z_TYPE_P(prop_copy) == IS_CONSTANT) { + if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) { zval_update_constant(&prop_copy, 0 TSRMLS_CC); } Index: Zend/zend_compile.c =================================================================== RCS file: /repository/ZendEngine2/zend_compile.c,v retrieving revision 1.764 diff -u -p -d -r1.764 zend_compile.c --- Zend/zend_compile.c 22 Aug 2007 07:39:37 -0000 1.764 +++ Zend/zend_compile.c 22 Aug 2007 08:27:42 -0000 @@ -3691,7 +3691,7 @@ void zend_do_end_new_object(znode *resul } /* }}} */ -static int zend_constant_ct_subst(znode *result, zval *const_name TSRMLS_DC) /* {{{ */ +static zend_constant* zend_get_ct_const(zval *const_name TSRMLS_DC) /* {{{ */ { zend_constant *c = NULL; @@ -3701,14 +3701,27 @@ static int zend_constant_ct_subst(znode if (zend_u_hash_find(EG(zend_constants), Z_TYPE_P(const_name), lookup_name, lookup_name_len+1, (void **) &c)==SUCCESS) { if ((c->flags & CONST_CS) && memcmp(c->name.v, Z_UNIVAL_P(const_name).v, UG(unicode)?UBYTES(Z_USTRLEN_P(const_name)):Z_STRLEN_P(const_name))!=0) { - c = NULL; + efree(lookup_name.v); + return NULL; } } else { - c = NULL; + efree(lookup_name.v); + return NULL; } efree(lookup_name.v); } - if (c && (c->flags & CONST_CT_SUBST)) { + if (c->flags & CONST_CT_SUBST) { + return c; + } + return NULL; +} +/* }}} */ + +static int zend_constant_ct_subst(znode *result, zval *const_name TSRMLS_DC) /* {{{ */ +{ + zend_constant *c = zend_get_ct_const(const_name TSRMLS_CC); + + if (c) { zval_dtor(const_name); result->op_type = IS_CONST; result->u.constant = c->value; @@ -3720,44 +3733,110 @@ static int zend_constant_ct_subst(znode } /* }}} */ -void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode TSRMLS_DC) /* {{{ */ +void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode, zend_bool check_namespace TSRMLS_DC) /* {{{ */ { + ulong fetch_type = 0; + znode tmp; + switch (mode) { case ZEND_CT: if (constant_container) { - ulong fetch_type; - if (ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_TYPE(constant_container->u.constant), Z_UNIVAL(constant_container->u.constant), Z_UNILEN(constant_container->u.constant))) { zend_resolve_class_name(constant_container, &fetch_type, 1 TSRMLS_CC); } zend_do_fetch_class_name(NULL, constant_container, constant_name TSRMLS_CC); *result = *constant_container; - result->u.constant.type = IS_CONSTANT; + result->u.constant.type = IS_CONSTANT | fetch_type; } else if (!zend_constant_ct_subst(result, &constant_name->u.constant TSRMLS_CC)) { + if (check_namespace && CG(current_namespace)) { + /* We assume we use constant from the current namespace + if it is not prefixed. */ + tmp.op_type = IS_CONST; + tmp.u.constant = *CG(current_namespace); + zval_copy_ctor(&tmp.u.constant); + zend_do_build_namespace_name(&tmp, &tmp, constant_name TSRMLS_CC); + *constant_name = tmp; + fetch_type = IS_CONSTANT_RT_NS_CHECK; + } *result = *constant_name; - result->u.constant.type = IS_CONSTANT; + result->u.constant.type = IS_CONSTANT | fetch_type; } break; case ZEND_RT: if (constant_container || !zend_constant_ct_subst(result, &constant_name->u.constant TSRMLS_CC)) { zend_op *opline; - znode class_node; if (constant_container) { - zend_do_fetch_class(&class_node, constant_container TSRMLS_CC); + if (constant_container->op_type == IS_CONST && + ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_TYPE(constant_container->u.constant), Z_UNIVAL(constant_container->u.constant), Z_UNILEN(constant_container->u.constant))) { + zend_resolve_class_name(constant_container, &fetch_type, 1 TSRMLS_CC); + } else { + zend_do_fetch_class(&tmp, constant_container TSRMLS_CC); + constant_container = &tmp; + } + } else if (check_namespace && CG(current_namespace)) { + /* We assume we use constant from the current namespace + if it is not prefixed. */ + tmp.op_type = IS_CONST; + tmp.u.constant = *CG(current_namespace); + zval_copy_ctor(&tmp.u.constant); + constant_container = &tmp; + fetch_type = IS_CONSTANT_RT_NS_CHECK; } opline = get_next_op(CG(active_op_array) TSRMLS_CC); opline->opcode = ZEND_FETCH_CONSTANT; + opline->extended_value = fetch_type & ~ZEND_FETCH_CLASS_RT_NS_NAME; opline->result.op_type = IS_TMP_VAR; opline->result.u.var = get_temporary_variable(CG(active_op_array)); if (constant_container) { - opline->op1 = class_node; + opline->op1 = *constant_container; } else { SET_UNUSED(opline->op1); } opline->op2 = *constant_name; *result = opline->result; + + if (opline->op1.op_type == IS_CONST) { + /* Prebuild ns::func name to speedup run-time check. + The additional names are stored in additional OP_DATA opcode. */ + zstr nsname; + unsigned int nsname_len; + + opline = get_next_op(CG(active_op_array) TSRMLS_CC); + opline->opcode = ZEND_OP_DATA; + opline->op1.op_type = IS_CONST; + SET_UNUSED(opline->op2); + + nsname = Z_UNIVAL(constant_container->u.constant); + nsname_len = Z_UNILEN(constant_container->u.constant); + if (fetch_type & ZEND_FETCH_CLASS_RT_NS_NAME) { + /* Remove namespace name */ + if (Z_TYPE(constant_container->u.constant) == IS_UNICODE) { + nsname.u = u_memchr(nsname.u, ':', nsname_len) + 2; + nsname_len -= (nsname.u - Z_USTRVAL(constant_container->u.constant)); + } else { + nsname.s = memchr(nsname.s, ':', nsname_len) + 2; + nsname_len -= (nsname.s - Z_STRVAL(constant_container->u.constant)); + } + } + + Z_TYPE(opline->op1.u.constant) = Z_TYPE(constant_container->u.constant); + Z_UNIVAL(opline->op1.u.constant) = zend_u_str_case_fold(Z_TYPE(constant_container->u.constant), nsname, nsname_len, 0, &Z_UNILEN(opline->op1.u.constant)); + if (UG(unicode)) { + Z_USTRVAL(opline->op1.u.constant) = erealloc(Z_USTRVAL(opline->op1.u.constant), UBYTES(Z_USTRLEN(opline->op1.u.constant) + 2 + Z_USTRLEN(constant_name->u.constant) + 1)); + Z_USTRVAL(opline->op1.u.constant)[Z_USTRLEN(opline->op1.u.constant)] = ':'; + Z_USTRVAL(opline->op1.u.constant)[Z_USTRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(Z_USTRVAL(opline->op1.u.constant)+Z_USTRLEN(opline->op1.u.constant)+2, Z_USTRVAL(constant_name->u.constant), UBYTES(Z_USTRLEN(constant_name->u.constant) + 1)); + } else { + Z_STRVAL(opline->op1.u.constant) = erealloc(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant) + 2 + Z_STRLEN(constant_name->u.constant) + 1); + Z_STRVAL(opline->op1.u.constant)[Z_STRLEN(opline->op1.u.constant)] = ':'; + Z_STRVAL(opline->op1.u.constant)[Z_STRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(Z_STRVAL(opline->op1.u.constant)+Z_STRLEN(opline->op1.u.constant)+2, Z_STRVAL(constant_name->u.constant), Z_STRLEN(constant_name->u.constant) + 1); + } + Z_UNILEN(opline->op1.u.constant) += 2 + Z_UNILEN(constant_name->u.constant); + opline->extended_value = zend_u_hash_func(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant) + 1); + } } break; } @@ -3846,7 +3925,7 @@ void zend_do_add_static_array_element(zn if (offset) { zend_uchar utype = Z_TYPE(offset->u.constant); - switch (Z_TYPE(offset->u.constant)) { + switch (Z_TYPE(offset->u.constant) & IS_CONSTANT_TYPE_MASK) { case IS_CONSTANT: /* Ugly hack to denote that this value has a constant index */ Z_TYPE_P(element) |= IS_CONSTANT_INDEX; @@ -5051,6 +5130,37 @@ void zend_do_import(znode *ns_name, znod } /* }}} */ +void zend_do_declare_constant(znode *name, znode *value TSRMLS_DC) /* {{{ */ +{ + zend_op *opline; + + if (zend_get_ct_const(&name->u.constant TSRMLS_CC)) { + zend_error(E_COMPILE_ERROR, "Cannot redeclare constant '%R'", Z_TYPE(name->u.constant), Z_UNIVAL(name->u.constant)); + } + + if (CG(current_namespace)) { + /* Prefix constant name with name of current namespace */ + znode tmp; + zstr lcname; + uint lcname_len; + + tmp.op_type = IS_CONST; + tmp.u.constant = *CG(current_namespace); + lcname = zend_u_str_case_fold(Z_TYPE(tmp.u.constant), Z_UNIVAL(tmp.u.constant), Z_UNILEN(tmp.u.constant), 0, &lcname_len); + Z_UNIVAL(tmp.u.constant) = lcname; + Z_UNILEN(tmp.u.constant) = lcname_len; + zend_do_build_namespace_name(&tmp, &tmp, name TSRMLS_CC); + *name = tmp; + } + + opline = get_next_op(CG(active_op_array) TSRMLS_CC); + opline->opcode = ZEND_DECLARE_CONST; + SET_UNUSED(opline->result); + opline->op1 = *name; + opline->op2 = *value; +} +/* }}} */ + void zend_do_end_compilation(TSRMLS_D) /* {{{ */ { if (CG(current_namespace)) { Index: Zend/zend_compile.h =================================================================== RCS file: /repository/ZendEngine2/zend_compile.h,v retrieving revision 1.363 diff -u -p -d -r1.363 zend_compile.h --- Zend/zend_compile.h 20 Aug 2007 09:48:41 -0000 1.363 +++ Zend/zend_compile.h 22 Aug 2007 08:27:43 -0000 @@ -470,7 +470,7 @@ void zend_do_pop_object(znode *object TS void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC); void zend_do_end_new_object(znode *result, znode *new_token, znode *argument_list TSRMLS_DC); -void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode TSRMLS_DC); +void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode, zend_bool check_namespace TSRMLS_DC); void zend_do_shell_exec(znode *result, znode *cmd TSRMLS_DC); @@ -519,6 +519,7 @@ void zend_do_ticks(TSRMLS_D); void zend_do_abstract_method(znode *function_name, znode *modifiers, znode *body TSRMLS_DC); +void zend_do_declare_constant(znode *name, znode *value TSRMLS_DC); void zend_do_build_namespace_name(znode *result, znode *prefix, znode *name TSRMLS_DC); void zend_do_namespace(znode *name TSRMLS_DC); void zend_do_import(znode *name, znode *new_name TSRMLS_DC); Index: Zend/zend_constants.c =================================================================== RCS file: /repository/ZendEngine2/zend_constants.c,v retrieving revision 1.97 diff -u -p -d -r1.97 zend_constants.c --- Zend/zend_constants.c 27 Jul 2007 16:29:25 -0000 1.97 +++ Zend/zend_constants.c 22 Aug 2007 08:27:43 -0000 @@ -258,21 +258,88 @@ ZEND_API void zend_register_string_const } /* }}} */ -ZEND_API int zend_u_get_constant(zend_uchar type, zstr name, uint name_len, zval *result, zend_class_entry *scope TSRMLS_DC) /* {{{ */ +ZEND_API int zend_u_get_constant(zend_uchar type, zstr name, uint name_len, zval *result TSRMLS_DC) /* {{{ */ { zend_constant *c; int retval = 1; zstr lookup_name; + + if (zend_u_hash_find(EG(zend_constants), type, name, name_len+1, (void **) &c) == FAILURE) { + unsigned int lookup_name_len; + + lookup_name = zend_u_str_case_fold(type, name, name_len, 1, &lookup_name_len); + + if (zend_u_hash_find(EG(zend_constants), type, lookup_name, lookup_name_len+1, (void **) &c)==SUCCESS) { + if ((c->flags & CONST_CS) && memcmp(c->name.v, name.v, UG(unicode)?UBYTES(name_len):name_len)!=0) { + retval=0; + } + } else { + if (!EG(in_execution)) { + retval = 0; + } else if (name_len == sizeof(ZEND_HALT_CONSTANT_NAME)-1 && ZEND_U_EQUAL(type, name, name_len, ZEND_HALT_CONSTANT_NAME, sizeof(ZEND_HALT_CONSTANT_NAME)-1)) { + char *cfilename; + zstr haltname; + int len, clen; + cfilename = zend_get_executed_filename(TSRMLS_C); + clen = strlen(cfilename); + /* check for __COMPILER_HALT_OFFSET__ */ + zend_mangle_property_name(&haltname.s, &len, ZEND_HALT_CONSTANT_NAME, + sizeof(ZEND_HALT_CONSTANT_NAME) - 1, cfilename, clen, 0); + if (zend_u_hash_find(EG(zend_constants), IS_STRING, haltname, len+1, (void **) &c) == SUCCESS) { + retval=1; + } else { + retval=0; + } + pefree(haltname.s, 0); + } else { + retval=0; + } + } + efree(lookup_name.v); + } + + if (retval) { + *result = c->value; + zval_copy_ctor(result); + result->refcount = 1; + result->is_ref = 0; + } + + return retval; +} +/* }}} */ + +ZEND_API int zend_u_get_constant_ex(zend_uchar type, zstr name, uint name_len, zval *result, zend_class_entry *scope, ulong flags TSRMLS_DC) /* {{{ */ +{ + zend_constant *c; + int retval = 1; zstr colon; + /* Skip leading :: */ + if (type == IS_UNICODE && + name.u[0] == ':' && + name.u[1] == ':') { + name.u += 2; + name_len -= 2; + flags = 0; + } else if (type == IS_STRING && + name.s[0] == ':' && + name.s[1] == ':') { + name.s += 2; + name_len -= 2; + flags = 0; + } + if ((UG(unicode) && (colon.u = u_memrchr(name.u, ':', name_len)) && colon.u > name.u && *(colon.u-1) == ':') || (!UG(unicode) && (colon.s = zend_memrchr(name.s, ':', name_len))&& colon.s > name.s && *(colon.s-1) == ':')) { - /* class constant */ + /* compound constant name */ zend_class_entry **ce = NULL; int class_name_len = UG(unicode)?colon.u-name.u-1:colon.s-name.s-1; int const_name_len = name_len - class_name_len - 2; zstr constant_name, class_name; zval **ret_constant; + zstr lcname; + unsigned int lcname_len; if (UG(unicode)) { constant_name.u = colon.u + 1; @@ -294,16 +361,19 @@ ZEND_API int zend_u_get_constant(zend_uc class_name.s = estrndup(name.s, class_name_len); } - if (class_name_len == sizeof("self")-1 && - ZEND_U_EQUAL(type, class_name, class_name_len, "self", sizeof("self")-1)) { + lcname = zend_u_str_case_fold(type, class_name, class_name_len, 0, &lcname_len); + + if (lcname_len == sizeof("self")-1 && + ZEND_U_EQUAL(type, lcname, lcname_len, "self", sizeof("self")-1)) { if (scope) { ce = &scope; } else { zend_error(E_ERROR, "Cannot access self:: when no class scope is active"); retval = 0; } - } else if (class_name_len == sizeof("parent")-1 && - ZEND_U_EQUAL(type, class_name, class_name_len, "parent", sizeof("parent")-1)) { + efree(lcname.v); + } else if (lcname_len == sizeof("parent")-1 && + ZEND_U_EQUAL(type, lcname, lcname_len, "parent", sizeof("parent")-1)) { if (!scope) { zend_error(E_ERROR, "Cannot access parent:: when no class scope is active"); } else if (!scope->parent) { @@ -311,14 +381,57 @@ ZEND_API int zend_u_get_constant(zend_uc } else { ce = &scope->parent; } + efree(lcname.v); } else { - if (zend_u_lookup_class(type, class_name, class_name_len, &ce TSRMLS_CC) != SUCCESS) { + /* Check for namespace constant */ + zstr nsname; + unsigned int nsname_len; + + /* Concatenate lowercase namespace name and constant name */ + if (UG(unicode)) { + lcname.u = erealloc(lcname.u, UBYTES(lcname_len + 2 + const_name_len + 1)); + lcname.u[lcname_len] = ':'; + lcname.u[lcname_len+1] = ':'; + memcpy(lcname.u+lcname_len+2, constant_name.u, UBYTES(const_name_len + 1)); + } else { + lcname.s = erealloc(lcname.s, lcname_len + 2 + const_name_len + 1); + lcname.s[lcname_len] = ':'; + lcname.s[lcname_len+1] = ':'; + memcpy(lcname.s+lcname_len+2, constant_name.s, const_name_len + 1); + } + lcname_len += 2 + const_name_len; + + nsname = lcname; + nsname_len = lcname_len; + if (flags & ZEND_FETCH_CLASS_RT_NS_NAME) { + /* Remove namespace name */ + if (UG(unicode)) { + nsname.u = u_memchr(nsname.u, ':', nsname_len) + 2; + nsname_len -= (nsname.u - lcname.u); + } else { + nsname.s = memchr(nsname.s, ':', nsname_len) + 2; + nsname_len -= (nsname.s - lcname.s); + } + } + + if (zend_u_hash_find(EG(zend_constants), type, nsname, nsname_len+1, (void **) &c) == SUCCESS) { + efree(lcname.v); + efree(class_name.v); + *result = c->value; + zval_update_constant_ex(&result, (void*)1, NULL TSRMLS_CC); + zval_copy_ctor(result); + result->refcount = 1; + result->is_ref = 0; + return 1; + } + efree(lcname.v); + + /* Check for class */ + if (zend_u_lookup_class(type, class_name, class_name_len, &ce TSRMLS_CC) != SUCCESS && + (flags & ZEND_FETCH_CLASS_RT_NS_CHECK) != 0) { retval = 0; if ((UG(unicode) && (colon.u = u_memrchr(class_name.u, ':', class_name_len)) && colon.u > class_name.u && *(colon.u-1) == ':') || (!UG(unicode) && (colon.s = zend_memrchr(class_name.s, ':', class_name_len))&& colon.s > class_name.s && *(colon.s-1) == ':')) { - zend_class_entry **pce; - zstr lcname; - unsigned int lcname_len; if (UG(unicode)) { colon.u++; @@ -342,7 +455,16 @@ ZEND_API int zend_u_get_constant(zend_uc retval = 0; } } else { - zend_error(E_ERROR, "Class '%R' not found", type, class_name); + if ((flags & ZEND_FETCH_CLASS_RT_NS_NAME) == 0) { + if ((flags & IS_CONSTANT_RT_NS_CHECK) != 0) { + name = constant_name; + name_len = const_name_len; + efree(class_name.v); + retval = 1; + return zend_u_get_constant(type, name, name_len, result TSRMLS_CC); + } + zend_error(E_ERROR, "Class '%R' not found", type, class_name); + } retval = 0; } efree(class_name.v); @@ -356,54 +478,13 @@ ZEND_API int zend_u_get_constant(zend_uc return retval; } - if (zend_u_hash_find(EG(zend_constants), type, name, name_len+1, (void **) &c) == FAILURE) { - unsigned int lookup_name_len; - - lookup_name = zend_u_str_case_fold(type, name, name_len, 1, &lookup_name_len); - - if (zend_u_hash_find(EG(zend_constants), type, lookup_name, lookup_name_len+1, (void **) &c)==SUCCESS) { - if ((c->flags & CONST_CS) && memcmp(c->name.v, name.v, UG(unicode)?UBYTES(name_len):name_len)!=0) { - retval=0; - } - } else { - if (!EG(in_execution)) { - retval = 0; - } else if (name_len == sizeof(ZEND_HALT_CONSTANT_NAME)-1 && ZEND_U_EQUAL(type, name, name_len, ZEND_HALT_CONSTANT_NAME, sizeof(ZEND_HALT_CONSTANT_NAME)-1)) { - char *cfilename; - zstr haltname; - int len, clen; - cfilename = zend_get_executed_filename(TSRMLS_C); - clen = strlen(cfilename); - /* check for __COMPILER_HALT_OFFSET__ */ - zend_mangle_property_name(&haltname.s, &len, ZEND_HALT_CONSTANT_NAME, - sizeof(ZEND_HALT_CONSTANT_NAME) - 1, cfilename, clen, 0); - if (zend_u_hash_find(EG(zend_constants), IS_STRING, haltname, len+1, (void **) &c) == SUCCESS) { - retval=1; - } else { - retval=0; - } - pefree(haltname.s, 0); - } else { - retval=0; - } - } - efree(lookup_name.v); - } - - if (retval) { - *result = c->value; - zval_copy_ctor(result); - result->refcount = 1; - result->is_ref = 0; - } - - return retval; + return zend_u_get_constant(type, name, name_len, result TSRMLS_CC); } /* }}} */ ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC) /* {{{ */ { - return zend_u_get_constant(IS_STRING, ZSTR(name), name_len, result, NULL TSRMLS_CC); + return zend_u_get_constant_ex(IS_STRING, ZSTR(name), name_len, result, NULL, 0 TSRMLS_CC); } /* }}} */ @@ -461,7 +542,7 @@ ZEND_API int zend_register_constant(zend free(c->name.s); c->name.u = ustr; } - if (Z_TYPE(c->value) == IS_STRING || Z_TYPE(c->value) == IS_CONSTANT) { + if (Z_TYPE(c->value) == IS_STRING || (Z_TYPE(c->value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) { ustr = pemalloc(UBYTES(Z_STRLEN(c->value)+1), c->flags & CONST_PERSISTENT); u_charsToUChars(Z_STRVAL(c->value), ustr, Z_STRLEN(c->value)+1); pefree(Z_STRVAL(c->value), c->flags & CONST_PERSISTENT); Index: Zend/zend_constants.h =================================================================== RCS file: /repository/ZendEngine2/zend_constants.h,v retrieving revision 1.40 diff -u -p -d -r1.40 zend_constants.h --- Zend/zend_constants.h 3 Aug 2007 18:41:07 -0000 1.40 +++ Zend/zend_constants.h 22 Aug 2007 08:27:43 -0000 @@ -56,7 +56,8 @@ int zend_shutdown_constants(TSRMLS_D); void zend_register_standard_constants(TSRMLS_D); void clean_non_persistent_constants(TSRMLS_D); ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC); -ZEND_API int zend_u_get_constant(zend_uchar type, zstr name, uint name_len, zval *result, zend_class_entry *scope TSRMLS_DC); +ZEND_API int zend_u_get_constant(zend_uchar type, zstr name, uint name_len, zval *result TSRMLS_DC); +ZEND_API int zend_u_get_constant_ex(zend_uchar type, zstr name, uint name_len, zval *result, zend_class_entry *scope, ulong flags TSRMLS_DC); ZEND_API void zend_register_long_constant(char *name, uint name_len, long lval, int flags, int module_number TSRMLS_DC); ZEND_API void zend_register_double_constant(char *name, uint name_len, double dval, int flags, int module_number TSRMLS_DC); ZEND_API void zend_register_string_constant(char *name, uint name_len, char *strval, int flags, int module_number TSRMLS_DC); Index: Zend/zend_execute_API.c =================================================================== RCS file: /repository/ZendEngine2/zend_execute_API.c,v retrieving revision 1.412 diff -u -p -d -r1.412 zend_execute_API.c --- Zend/zend_execute_API.c 22 Aug 2007 07:39:37 -0000 1.412 +++ Zend/zend_execute_API.c 22 Aug 2007 08:27:43 -0000 @@ -485,10 +485,11 @@ ZEND_API int zval_update_constant_ex(zva zend_bool inline_change = (zend_bool) (zend_uintptr_t) arg; zval const_value; zstr colon; + int len; if (IS_CONSTANT_VISITED(p)) { zend_error(E_ERROR, "Cannot declare self-referencing constant '%v'", Z_UNIVAL_P(p)); - } else if (Z_TYPE_P(p) == IS_CONSTANT) { + } else if ((Z_TYPE_P(p) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) { int refcount; zend_uchar is_ref; @@ -500,10 +501,15 @@ ZEND_API int zval_update_constant_ex(zva refcount = p->refcount; is_ref = p->is_ref; - if (!zend_u_get_constant(ZEND_STR_TYPE, Z_UNIVAL_P(p), Z_UNILEN_P(p), &const_value, scope TSRMLS_CC)) { - if ((UG(unicode) && (colon.u = u_memchr(Z_USTRVAL_P(p), ':', Z_USTRLEN_P(p))) && colon.u[1] == ':') || - (!UG(unicode) && (colon.s = memchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p))) && colon.s[1] == ':')) { - zend_error(E_ERROR, "Undefined class constant '%v'", Z_UNIVAL_P(p)); + if (!zend_u_get_constant_ex(ZEND_STR_TYPE, Z_UNIVAL_P(p), Z_UNILEN_P(p), &const_value, scope, Z_TYPE_P(p) TSRMLS_CC)) { + if ((UG(unicode) && (colon.u = u_memrchr(Z_USTRVAL_P(p), ':', Z_USTRLEN_P(p))) && colon.u > Z_USTRVAL_P(p) && *(colon.u-1) == ':') || + (!UG(unicode) && (colon.s = zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p))) && colon.s > Z_STRVAL_P(p) && *(colon.s-1) == ':')) { + if (UG(unicode)) { + colon.u++; + } else { + colon.s++; + } + zend_error(E_ERROR, "Undefined class constant '%v'", colon); } zend_error(E_NOTICE, "Use of undefined constant %v - assumed '%v'", Z_UNIVAL_P(p), @@ -543,7 +549,7 @@ ZEND_API int zval_update_constant_ex(zva zend_hash_move_forward(Z_ARRVAL_P(p)); continue; } - if (!zend_u_get_constant(ZEND_STR_TYPE, str_index, str_index_len-1, &const_value, scope TSRMLS_CC)) { + if (!zend_u_get_constant_ex(ZEND_STR_TYPE, str_index, str_index_len-1, &const_value, scope, 0 TSRMLS_CC)) { if ((UG(unicode) && (colon.u = u_memchr(str_index.u, ':', str_index_len-1)) && colon.u[1] == ':') || (!UG(unicode) && (colon.s = memchr(str_index.s, ':', str_index_len-1)) && colon.s[1] == ':')) { zend_error(E_ERROR, "Undefined class constant '%v'", str_index); Index: Zend/zend_language_parser.y =================================================================== RCS file: /repository/ZendEngine2/zend_language_parser.y,v retrieving revision 1.188 diff -u -p -d -r1.188 zend_language_parser.y --- Zend/zend_language_parser.y 20 Aug 2007 09:48:41 -0000 1.188 +++ Zend/zend_language_parser.y 22 Aug 2007 08:27:43 -0000 @@ -174,8 +174,13 @@ top_statement: | T_NAMESPACE namespace_name ';' { zend_do_namespace(&$2 TSRMLS_CC); } | T_IMPORT namespace_name ';' { zend_do_import(&$2, NULL TSRMLS_CC); } | T_IMPORT namespace_name T_AS T_STRING ';' { zend_do_import(&$2, &$4 TSRMLS_CC); } + | constant_declaration ';' ; +constant_declaration: + constant_declaration ',' T_STRING '=' expr { zend_do_declare_constant(&$3, &$5 TSRMLS_CC); } + | T_CONST T_STRING '=' expr { zend_do_declare_constant(&$2, &$4 TSRMLS_CC); } +; inner_statement_list: inner_statement_list { zend_do_extended_info(TSRMLS_C); } inner_statement { HANDLE_INTERACTIVE(); } @@ -722,7 +727,8 @@ common_scalar: static_scalar: /* compile-time evaluated scalars */ common_scalar { $$ = $1; } - | T_STRING { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT TSRMLS_CC); } + | T_STRING { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT, 1 TSRMLS_CC); } + | T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, NULL, &$2, ZEND_CT, 0 TSRMLS_CC); } | '+' static_scalar { $$ = $2; } | '-' static_scalar { zval minus_one; Z_TYPE(minus_one) = IS_LONG; Z_LVAL(minus_one) = -1; mul_function(&$2.u.constant, &$2.u.constant, &minus_one TSRMLS_CC); $$ = $2; } | T_ARRAY '(' static_array_pair_list ')' { $$ = $3; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; } @@ -730,11 +736,12 @@ static_scalar: /* compile-time evaluated ; static_class_constant: - fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_CT TSRMLS_CC); } + fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_CT, 0 TSRMLS_CC); } ; scalar: - T_STRING { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_RT TSRMLS_CC); } + T_STRING { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_RT, 1 TSRMLS_CC); } + | T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, NULL, &$2, ZEND_RT, 0 TSRMLS_CC); } | T_STRING_VARNAME { $$ = $1; } | class_constant { $$ = $1; } | common_scalar { $$ = $1; } @@ -945,8 +952,8 @@ isset_variables: ; class_constant: - fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT TSRMLS_CC); } - | variable_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT TSRMLS_CC); } + fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT, 0 TSRMLS_CC); } + | variable_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT, 0 TSRMLS_CC); } ; %% Index: Zend/zend_variables.c =================================================================== RCS file: /repository/ZendEngine2/zend_variables.c,v retrieving revision 1.70 diff -u -p -d -r1.70 zend_variables.c --- Zend/zend_variables.c 11 Jul 2007 11:19:58 -0000 1.70 +++ Zend/zend_variables.c 22 Aug 2007 08:27:43 -0000 @@ -28,7 +28,7 @@ ZEND_API void _zval_dtor_func(zval *zvalue ZEND_FILE_LINE_DC) /* {{{ */ { - switch (Z_TYPE_P(zvalue) & ~IS_CONSTANT_INDEX) { + switch (Z_TYPE_P(zvalue) & IS_CONSTANT_TYPE_MASK) { case IS_CONSTANT: { TSRMLS_FETCH(); @@ -81,7 +81,7 @@ dtor_unicode: ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC) /* {{{ */ { - switch (Z_TYPE_P(zvalue) & ~IS_CONSTANT_INDEX) { + switch (Z_TYPE_P(zvalue) & IS_CONSTANT_TYPE_MASK) { case IS_CONSTANT: { TSRMLS_FETCH(); @@ -120,7 +120,7 @@ ZEND_API void zval_add_ref(zval **p) /* ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC) /* {{{ */ { - switch (Z_TYPE_P(zvalue)) { + switch (Z_TYPE_P(zvalue) & IS_CONSTANT_TYPE_MASK) { case IS_RESOURCE: { TSRMLS_FETCH(); Index: Zend/zend_vm_def.h =================================================================== RCS file: /repository/ZendEngine2/zend_vm_def.h,v retrieving revision 1.178 diff -u -p -d -r1.178 zend_vm_def.h --- Zend/zend_vm_def.h 22 Aug 2007 07:39:37 -0000 1.178 +++ Zend/zend_vm_def.h 22 Aug 2007 08:27:43 -0000 @@ -2466,7 +2466,7 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, zend_free_op free_res; if (zend_ptr_stack_get_arg(arg_num, (void **) ¶m TSRMLS_CC)==FAILURE) { - if (Z_TYPE(opline->op2.u.constant) == IS_CONSTANT || Z_TYPE(opline->op2.u.constant)==IS_CONSTANT_ARRAY) { + if ((Z_TYPE(opline->op2.u.constant) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE(opline->op2.u.constant)==IS_CONSTANT_ARRAY) { zval *default_value; ALLOC_ZVAL(default_value); @@ -2700,37 +2700,51 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|T ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|UNUSED, CONST) +ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|UNUSED|CONST, CONST) { zend_op *opline = EX(opline); zend_class_entry *ce = NULL; zval **value; if (OP1_TYPE == IS_UNUSED) { -/* This seems to be a reminant of namespaces - if (EG(scope)) { - ce = EG(scope); - if (zend_hash_find(&ce->constants_table, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { - zval_update_constant(value, (void *) 1 TSRMLS_CC); - EX_T(opline->result.u.var).tmp_var = **value; - zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); - ZEND_VM_NEXT_OPCODE(); - } - } -*/ - if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var, NULL TSRMLS_CC)) { + if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", - Z_TYPE(opline->op2.u.constant), - Z_UNIVAL(opline->op2.u.constant), - Z_TYPE(opline->op2.u.constant), - Z_UNIVAL(opline->op2.u.constant)); + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); } ZEND_VM_NEXT_OPCODE(); - } + } else if (OP1_TYPE == IS_CONST) { + zend_op *op_data = opline + 1; + zend_constant *c; - ce = EX_T(opline->op1.u.var).class_entry; + ZEND_VM_INC_OPCODE(); + + /* try a constant in namespace */ + if (zend_u_hash_quick_find(EG(zend_constants), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) { + EX_T(opline->result.u.var).tmp_var = c->value; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + ZEND_VM_NEXT_OPCODE(); + } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) { + if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { + zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + } + ZEND_VM_NEXT_OPCODE(); + } + + /* no constant found. try a constant in class */ + ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); + if (!ce) { + zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + } + } else { + ce = EX_T(opline->op1.u.var).class_entry; + } if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { zend_class_entry *old_scope = EG(scope); @@ -4116,4 +4130,43 @@ ZEND_VM_HANDLER(151, ZEND_U_NORMALIZE, C ZEND_VM_NEXT_OPCODE(); } +ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST|TMP|VAR|CV) +{ + zend_op *opline = EX(opline); + zend_free_op free_op1, free_op2; + zval *name = GET_OP1_ZVAL_PTR(BP_VAR_R); + zval *val = GET_OP2_ZVAL_PTR(BP_VAR_R); + zend_constant c; + + if ((Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { + zval tmp = *val; + zval *tmp_ptr = &tmp; + + if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { + zval_copy_ctor(&tmp); + } + INIT_PZVAL(&tmp); + zval_update_constant(&tmp_ptr, NULL TSRMLS_CC); + c.value = *tmp_ptr; + } else { + c.value = *val; + zval_copy_ctor(&c.value); + } + c.flags = CONST_CS; /* non persistent, case sensetive */ + if (Z_TYPE_P(name) == IS_UNICODE) { + c.name.u = zend_ustrndup(Z_USTRVAL_P(name), Z_USTRLEN_P(name)); + } else { + c.name.s = zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name)); + } + c.name_len = Z_UNILEN_P(name)+1; + c.module_number = PHP_USER_CONSTANT; + + if (zend_u_register_constant(Z_TYPE_P(name), &c TSRMLS_CC) == FAILURE) { + } + + FREE_OP1(); + FREE_OP2(); + ZEND_VM_NEXT_OPCODE(); +} + ZEND_VM_EXPORT_HELPER(zend_do_fcall, zend_do_fcall_common_helper) Index: Zend/zend_vm_execute.h =================================================================== RCS file: /repository/ZendEngine2/zend_vm_execute.h,v retrieving revision 1.182 diff -u -p -d -r1.182 zend_vm_execute.h --- Zend/zend_vm_execute.h 22 Aug 2007 07:39:37 -0000 1.182 +++ Zend/zend_vm_execute.h 22 Aug 2007 08:27:43 -0000 @@ -757,7 +757,7 @@ static int ZEND_RECV_INIT_SPEC_CONST_HAN zend_free_op free_res; if (zend_ptr_stack_get_arg(arg_num, (void **) ¶m TSRMLS_CC)==FAILURE) { - if (Z_TYPE(opline->op2.u.constant) == IS_CONSTANT || Z_TYPE(opline->op2.u.constant)==IS_CONSTANT_ARRAY) { + if ((Z_TYPE(opline->op2.u.constant) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE(opline->op2.u.constant)==IS_CONSTANT_ARRAY) { zval *default_value; ALLOC_ZVAL(default_value); @@ -2651,6 +2651,67 @@ static int ZEND_CASE_SPEC_CONST_CONST_HA ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *opline = EX(opline); + zend_class_entry *ce = NULL; + zval **value; + + if (IS_CONST == IS_UNUSED) { + if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { + zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + } + ZEND_VM_NEXT_OPCODE(); + } else if (IS_CONST == IS_CONST) { + zend_op *op_data = opline + 1; + zend_constant *c; + + ZEND_VM_INC_OPCODE(); + + /* try a constant in namespace */ + if (zend_u_hash_quick_find(EG(zend_constants), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) { + EX_T(opline->result.u.var).tmp_var = c->value; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + ZEND_VM_NEXT_OPCODE(); + } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) { + if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { + zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + } + ZEND_VM_NEXT_OPCODE(); + } + + /* no constant found. try a constant in class */ + ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); + if (!ce) { + zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + } + } else { + ce = EX_T(opline->op1.u.var).class_entry; + } + + if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { + zend_class_entry *old_scope = EG(scope); + + EG(scope) = ce; + zval_update_constant(value, (void *) 1 TSRMLS_CC); + EG(scope) = old_scope; + EX_T(opline->result.u.var).tmp_var = **value; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + } else { + zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + } + + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -2745,6 +2806,44 @@ static int ZEND_INIT_ARRAY_SPEC_CONST_CO } } +static int ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *opline = EX(opline); + + zval *name = &opline->op1.u.constant; + zval *val = &opline->op2.u.constant; + zend_constant c; + + if ((Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { + zval tmp = *val; + zval *tmp_ptr = &tmp; + + if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { + zval_copy_ctor(&tmp); + } + INIT_PZVAL(&tmp); + zval_update_constant(&tmp_ptr, NULL TSRMLS_CC); + c.value = *tmp_ptr; + } else { + c.value = *val; + zval_copy_ctor(&c.value); + } + c.flags = CONST_CS; /* non persistent, case sensetive */ + if (Z_TYPE_P(name) == IS_UNICODE) { + c.name.u = zend_ustrndup(Z_USTRVAL_P(name), Z_USTRLEN_P(name)); + } else { + c.name.s = zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name)); + } + c.name_len = Z_UNILEN_P(name)+1; + c.module_number = PHP_USER_CONSTANT; + + if (zend_u_register_constant(Z_TYPE_P(name), &c TSRMLS_CC) == FAILURE) { + } + + + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_ADD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -3190,6 +3289,44 @@ static int ZEND_INIT_ARRAY_SPEC_CONST_TM } } +static int ZEND_DECLARE_CONST_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *opline = EX(opline); + zend_free_op free_op2; + zval *name = &opline->op1.u.constant; + zval *val = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + zend_constant c; + + if ((Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { + zval tmp = *val; + zval *tmp_ptr = &tmp; + + if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { + zval_copy_ctor(&tmp); + } + INIT_PZVAL(&tmp); + zval_update_constant(&tmp_ptr, NULL TSRMLS_CC); + c.value = *tmp_ptr; + } else { + c.value = *val; + zval_copy_ctor(&c.value); + } + c.flags = CONST_CS; /* non persistent, case sensetive */ + if (Z_TYPE_P(name) == IS_UNICODE) { + c.name.u = zend_ustrndup(Z_USTRVAL_P(name), Z_USTRLEN_P(name)); + } else { + c.name.s = zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name)); + } + c.name_len = Z_UNILEN_P(name)+1; + c.module_number = PHP_USER_CONSTANT; + + if (zend_u_register_constant(Z_TYPE_P(name), &c TSRMLS_CC) == FAILURE) { + } + + zval_dtor(free_op2.var); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_ADD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -3635,6 +3772,44 @@ static int ZEND_INIT_ARRAY_SPEC_CONST_VA } } +static int ZEND_DECLARE_CONST_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *opline = EX(opline); + zend_free_op free_op2; + zval *name = &opline->op1.u.constant; + zval *val = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + zend_constant c; + + if ((Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { + zval tmp = *val; + zval *tmp_ptr = &tmp; + + if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { + zval_copy_ctor(&tmp); + } + INIT_PZVAL(&tmp); + zval_update_constant(&tmp_ptr, NULL TSRMLS_CC); + c.value = *tmp_ptr; + } else { + c.value = *val; + zval_copy_ctor(&c.value); + } + c.flags = CONST_CS; /* non persistent, case sensetive */ + if (Z_TYPE_P(name) == IS_UNICODE) { + c.name.u = zend_ustrndup(Z_USTRVAL_P(name), Z_USTRLEN_P(name)); + } else { + c.name.s = zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name)); + } + c.name_len = Z_UNILEN_P(name)+1; + c.module_number = PHP_USER_CONSTANT; + + if (zend_u_register_constant(Z_TYPE_P(name), &c TSRMLS_CC) == FAILURE) { + } + + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -4258,6 +4433,44 @@ static int ZEND_INIT_ARRAY_SPEC_CONST_CV } } +static int ZEND_DECLARE_CONST_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *opline = EX(opline); + + zval *name = &opline->op1.u.constant; + zval *val = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); + zend_constant c; + + if ((Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { + zval tmp = *val; + zval *tmp_ptr = &tmp; + + if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { + zval_copy_ctor(&tmp); + } + INIT_PZVAL(&tmp); + zval_update_constant(&tmp_ptr, NULL TSRMLS_CC); + c.value = *tmp_ptr; + } else { + c.value = *val; + zval_copy_ctor(&c.value); + } + c.flags = CONST_CS; /* non persistent, case sensetive */ + if (Z_TYPE_P(name) == IS_UNICODE) { + c.name.u = zend_ustrndup(Z_USTRVAL_P(name), Z_USTRLEN_P(name)); + } else { + c.name.s = zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name)); + } + c.name_len = Z_UNILEN_P(name)+1; + c.module_number = PHP_USER_CONSTANT; + + if (zend_u_register_constant(Z_TYPE_P(name), &c TSRMLS_CC) == FAILURE) { + } + + + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_BW_NOT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -10016,30 +10229,44 @@ static int ZEND_FETCH_CONSTANT_SPEC_VAR_ zval **value; if (IS_VAR == IS_UNUSED) { -/* This seems to be a reminant of namespaces - if (EG(scope)) { - ce = EG(scope); - if (zend_hash_find(&ce->constants_table, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { - zval_update_constant(value, (void *) 1 TSRMLS_CC); - EX_T(opline->result.u.var).tmp_var = **value; - zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); - ZEND_VM_NEXT_OPCODE(); - } - } -*/ - if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var, NULL TSRMLS_CC)) { + if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", - Z_TYPE(opline->op2.u.constant), - Z_UNIVAL(opline->op2.u.constant), - Z_TYPE(opline->op2.u.constant), - Z_UNIVAL(opline->op2.u.constant)); + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); } ZEND_VM_NEXT_OPCODE(); - } + } else if (IS_VAR == IS_CONST) { + zend_op *op_data = opline + 1; + zend_constant *c; - ce = EX_T(opline->op1.u.var).class_entry; + ZEND_VM_INC_OPCODE(); + + /* try a constant in namespace */ + if (zend_u_hash_quick_find(EG(zend_constants), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) { + EX_T(opline->result.u.var).tmp_var = c->value; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + ZEND_VM_NEXT_OPCODE(); + } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) { + if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { + zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + } + ZEND_VM_NEXT_OPCODE(); + } + + /* no constant found. try a constant in class */ + ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); + if (!ce) { + zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + } + } else { + ce = EX_T(opline->op1.u.var).class_entry; + } if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { zend_class_entry *old_scope = EG(scope); @@ -16724,30 +16951,44 @@ static int ZEND_FETCH_CONSTANT_SPEC_UNUS zval **value; if (IS_UNUSED == IS_UNUSED) { -/* This seems to be a reminant of namespaces - if (EG(scope)) { - ce = EG(scope); - if (zend_hash_find(&ce->constants_table, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { - zval_update_constant(value, (void *) 1 TSRMLS_CC); - EX_T(opline->result.u.var).tmp_var = **value; - zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); - ZEND_VM_NEXT_OPCODE(); - } - } -*/ - if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var, NULL TSRMLS_CC)) { + if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", - Z_TYPE(opline->op2.u.constant), - Z_UNIVAL(opline->op2.u.constant), - Z_TYPE(opline->op2.u.constant), - Z_UNIVAL(opline->op2.u.constant)); + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); } ZEND_VM_NEXT_OPCODE(); - } + } else if (IS_UNUSED == IS_CONST) { + zend_op *op_data = opline + 1; + zend_constant *c; - ce = EX_T(opline->op1.u.var).class_entry; + ZEND_VM_INC_OPCODE(); + + /* try a constant in namespace */ + if (zend_u_hash_quick_find(EG(zend_constants), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) { + EX_T(opline->result.u.var).tmp_var = c->value; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + ZEND_VM_NEXT_OPCODE(); + } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) { + if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { + zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + } + ZEND_VM_NEXT_OPCODE(); + } + + /* no constant found. try a constant in class */ + ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); + if (!ce) { + zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + } + } else { + ce = EX_T(opline->op1.u.var).class_entry; + } if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { zend_class_entry *old_scope = EG(scope); @@ -30882,7 +31123,7 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, + ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -31982,11 +32223,11 @@ void zend_init_opcodes_handlers(void) ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, + ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER, + ZEND_DECLARE_CONST_SPEC_CONST_TMP_HANDLER, + ZEND_DECLARE_CONST_SPEC_CONST_VAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, + ZEND_DECLARE_CONST_SPEC_CONST_CV_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, Index: Zend/zend_vm_opcodes.h =================================================================== RCS file: /repository/ZendEngine2/zend_vm_opcodes.h,v retrieving revision 1.69 diff -u -p -d -r1.69 zend_vm_opcodes.h --- Zend/zend_vm_opcodes.h 8 Mar 2007 17:30:28 -0000 1.69 +++ Zend/zend_vm_opcodes.h 22 Aug 2007 08:27:43 -0000 @@ -142,6 +142,7 @@ #define ZEND_DECLARE_INHERITED_CLASS 140 #define ZEND_DECLARE_FUNCTION 141 #define ZEND_RAISE_ABSTRACT_ERROR 142 +#define ZEND_DECLARE_CONST 143 #define ZEND_ADD_INTERFACE 144 #define ZEND_VERIFY_ABSTRACT_CLASS 146 #define ZEND_ASSIGN_DIM 147 Index: Zend/tests/bug41633_2.phpt =================================================================== RCS file: /repository/ZendEngine2/tests/bug41633_2.phpt,v retrieving revision 1.2 diff -u -p -d -r1.2 bug41633_2.phpt --- Zend/tests/bug41633_2.phpt 13 Jun 2007 14:50:33 -0000 1.2 +++ Zend/tests/bug41633_2.phpt 22 Aug 2007 08:27:43 -0000 @@ -8,4 +8,4 @@ class Foo { echo Foo::A."\n"; ?> --EXPECTF-- -Fatal error: Undefined class constant 'self::B' in %sbug41633_2.php on line 5 +Fatal error: Undefined class constant 'B' in %sbug41633_2.php on line 5 Index: Zend/tests/ns_039.phpt =================================================================== RCS file: Zend/tests/ns_039.phpt diff -N Zend/tests/ns_039.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_039.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,23 @@ +--TEST-- +039: Constant declaration +--FILE-- +<?php +const A = "ok"; +const B = A; +const C = array("ok"); +const D = array(B); +echo A . "\n"; +echo B . "\n"; +print_r(C); +print_r(D); +--EXPECT-- +ok +ok +Array +( + [0] => ok +) +Array +( + [0] => ok +) Index: Zend/tests/ns_040.phpt =================================================================== RCS file: Zend/tests/ns_040.phpt diff -N Zend/tests/ns_040.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_040.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,68 @@ +--TEST-- +040: Constant declaration and usage in namespace +--FILE-- +<?php +namespace X; +import X as Y; +const A = "ok\n"; +const B = A; +const C = array(A); +const D = array("aaa"=>A); +const E = array(A=>"aaa\n"); +function f1($x=A) { + echo $x; +} +function f2($x=X::A) { + echo $x; +} +function f3($x=Y::A) { + echo $x; +} +function f4($x=::X::A) { + echo $x; +} +function f5($x=B) { + echo $x; +} +function f6($x=array(A)) { + echo $x[0]; +} +function f7($x=array("aaa"=>A)) { + echo $x["aaa"]; +} +function f8($x=array(A=>"aaa\n")) { + echo $x["ok\n"]; +} +echo A; +echo X::A; +echo Y::A; +echo ::X::A; +f1(); +f2(); +f3(); +f4(); +echo B; +$x = C; echo $x[0]; +$x = D; echo $x["aaa"]; +$x = E; echo $x["ok\n"]; +f5(); +f6(); +f7(); +f8(); +--EXPECT-- +ok +ok +ok +ok +ok +ok +ok +ok +ok +ok +ok +aaa +ok +ok +ok +aaa Index: Zend/tests/ns_041.phpt =================================================================== RCS file: Zend/tests/ns_041.phpt diff -N Zend/tests/ns_041.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_041.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,22 @@ +--TEST-- +041: Constants in namespace +--FILE-- +<?php +namespace test::ns1; + +const FOO = "ok\n"; + +echo(FOO); +echo(test::ns1::FOO); +echo(::test::ns1::FOO); +echo(BAR); + +const BAR = "ok\n"; + +--EXPECTF-- +ok +ok +ok + +Notice: Use of undefined constant BAR - assumed 'BAR' in %sns_041.php on line 9 +BAR Index: Zend/tests/ns_042.phpt =================================================================== RCS file: Zend/tests/ns_042.phpt diff -N Zend/tests/ns_042.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_042.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,22 @@ +--TEST-- +042: Import in namespace and constants +--FILE-- +<?php +namespace test::ns1; + +const FOO = "ok\n"; + +import test::ns1 as ns2; +import test as ns3; + +echo FOO; +echo test::ns1::FOO; +echo ::test::ns1::FOO; +echo ns2::FOO; +echo ns3::ns1::FOO; +--EXPECT-- +ok +ok +ok +ok +ok Index: Zend/tests/ns_043.phpt =================================================================== RCS file: Zend/tests/ns_043.phpt diff -N Zend/tests/ns_043.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_043.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,11 @@ +--TEST-- +043: Name conflict and constants (ns name) +--FILE-- +<?php +namespace test::ns1; + +const INI_ALL = 0; + +var_dump(INI_ALL); +--EXPECT-- +int(0) Index: Zend/tests/ns_044.phpt =================================================================== RCS file: Zend/tests/ns_044.phpt diff -N Zend/tests/ns_044.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_044.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,9 @@ +--TEST-- +044: Name conflict and constants (php name) +--FILE-- +<?php +namespace test::ns1; + +var_dump(INI_ALL); +--EXPECT-- +int(7) Index: Zend/tests/ns_045.phpt =================================================================== RCS file: Zend/tests/ns_045.phpt diff -N Zend/tests/ns_045.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_045.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,11 @@ +--TEST-- +045: Name conflict and constants (php name in case if ns name exists) +--FILE-- +<?php +namespace test::ns1; + +const INI_ALL = 0; + +var_dump(::INI_ALL); +--EXPECT-- +int(7) Index: Zend/tests/ns_046.phpt =================================================================== RCS file: Zend/tests/ns_046.phpt diff -N Zend/tests/ns_046.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_046.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,11 @@ +--TEST-- +046: Run-time name conflict and constants (ns name) +--FILE-- +<?php +namespace test::ns1; + +const INI_ALL = 0; + +var_dump(constant("test::ns1::INI_ALL")); +--EXPECT-- +int(0) Index: Zend/tests/ns_047.phpt =================================================================== RCS file: Zend/tests/ns_047.phpt diff -N Zend/tests/ns_047.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_047.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,11 @@ +--TEST-- +047: Run-time name conflict and constants (php name) +--FILE-- +<?php +namespace test::ns1; + +const INI_ALL = 0; + +var_dump(constant("INI_ALL")); +--EXPECT-- +int(7) Index: Zend/tests/ns_048.phpt =================================================================== RCS file: Zend/tests/ns_048.phpt diff -N Zend/tests/ns_048.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_048.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,11 @@ +--TEST-- +048: __NAMESPACE__ constant and runtime names (ns name) +--FILE-- +<?php +namespace test::ns1; + +const FOO = 0; + +var_dump(constant(__NAMESPACE__ . "::FOO")); +--EXPECT-- +int(0) Index: Zend/tests/ns_049.phpt =================================================================== RCS file: Zend/tests/ns_049.phpt diff -N Zend/tests/ns_049.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_049.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,9 @@ +--TEST-- +049: __NAMESPACE__ constant and runtime names (php name) +--FILE-- +<?php +const FOO = 0; + +var_dump(constant(__NAMESPACE__ . "::FOO")); +--EXPECT-- +int(0) Index: Zend/tests/ns_050.phpt =================================================================== RCS file: Zend/tests/ns_050.phpt diff -N Zend/tests/ns_050.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_050.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,14 @@ +--TEST-- +050: Name conflict and compile-time constants (ns name) +--FILE-- +<?php +namespace test::ns1; + +const INI_ALL = 0; + +function foo($x = INI_ALL) { + var_dump($x); +} +foo(); +--EXPECT-- +int(0) Index: Zend/tests/ns_051.phpt =================================================================== RCS file: Zend/tests/ns_051.phpt diff -N Zend/tests/ns_051.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_051.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,12 @@ +--TEST-- +051: Name conflict and compile-time constants (php name) +--FILE-- +<?php +namespace test::ns1; + +function foo($x = INI_ALL) { + var_dump($x); +} +foo(); +--EXPECT-- +int(7) Index: Zend/tests/ns_052.phpt =================================================================== RCS file: Zend/tests/ns_052.phpt diff -N Zend/tests/ns_052.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_052.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,14 @@ +--TEST-- +052: Name conflict and compile-time constants (php name in case if ns name exists) +--FILE-- +<?php +namespace test::ns1; + +const INI_ALL = 0; + +function foo($x = ::INI_ALL) { + var_dump($x); +} +foo(); +--EXPECT-- +int(7) Index: ext/standard/basic_functions.c =================================================================== RCS file: /repository/php-src/ext/standard/basic_functions.c,v retrieving revision 1.868 diff -u -p -d -r1.868 basic_functions.c --- ext/standard/basic_functions.c 19 Jul 2007 15:56:33 -0000 1.868 +++ ext/standard/basic_functions.c 22 Aug 2007 08:27:43 -0000 @@ -4188,7 +4188,7 @@ PHP_FUNCTION(constant) return; } - if (!zend_u_get_constant(const_type, const_name, const_name_len, return_value, NULL TSRMLS_CC)) { + if (!zend_u_get_constant_ex(const_type, const_name, const_name_len, return_value, NULL, 0 TSRMLS_CC)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't find constant %R", const_type, const_name); RETURN_NULL(); }
Index: Zend/zend.c =================================================================== RCS file: /repository/ZendEngine2/zend.c,v retrieving revision 1.399 diff -u -p -d -r1.399 zend.c --- Zend/zend.c 21 Jul 2007 00:34:41 -0000 1.399 +++ Zend/zend.c 22 Aug 2007 08:27:42 -0000 @@ -696,7 +696,7 @@ static void zend_set_default_compile_tim static void zval_copy_persistent(zval *zv) /* {{{ */ { - if (Z_TYPE_P(zv) == IS_STRING || Z_TYPE_P(zv) == IS_CONSTANT) { + if (Z_TYPE_P(zv) == IS_STRING || (Z_TYPE_P(zv) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) { UChar *ustr; ustr = malloc(UBYTES(Z_STRLEN_P(zv)+1)); @@ -783,7 +783,7 @@ static void const_to_unicode(zend_consta free(c->name.s); c->name.u = uname; } - if (Z_TYPE(c->value) == IS_STRING || Z_TYPE(c->value) == IS_CONSTANT) { + if (Z_TYPE(c->value) == IS_STRING || (Z_TYPE(c->value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) { UChar *ustr; ustr = malloc(UBYTES(Z_STRLEN(c->value)+1)); Index: Zend/zend.h =================================================================== RCS file: /repository/ZendEngine2/zend.h,v retrieving revision 1.335 diff -u -p -d -r1.335 zend.h --- Zend/zend.h 21 Jul 2007 05:27:06 -0000 1.335 +++ Zend/zend.h 22 Aug 2007 08:27:42 -0000 @@ -467,7 +467,9 @@ typedef int (*zend_write_func_t)(const c #define IS_UNICODE 10 /* Ugly hack to support constants as static array indices */ -#define IS_CONSTANT_INDEX 0x80 +#define IS_CONSTANT_TYPE_MASK 0x0f +#define IS_CONSTANT_RT_NS_CHECK 0x10 +#define IS_CONSTANT_INDEX 0x80 /* overloaded elements data types */ Index: Zend/zend_builtin_functions.c =================================================================== RCS file: /repository/ZendEngine2/zend_builtin_functions.c,v retrieving revision 1.347 diff -u -p -d -r1.347 zend_builtin_functions.c --- Zend/zend_builtin_functions.c 8 Aug 2007 13:32:58 -0000 1.347 +++ Zend/zend_builtin_functions.c 22 Aug 2007 08:27:42 -0000 @@ -575,7 +575,7 @@ ZEND_FUNCTION(defined) } convert_to_text_ex(var); - if (zend_u_get_constant(Z_TYPE_PP(var), Z_UNIVAL_PP(var), Z_UNILEN_PP(var), &c, NULL TSRMLS_CC)) { + if (zend_u_get_constant_ex(Z_TYPE_PP(var), Z_UNIVAL_PP(var), Z_UNILEN_PP(var), &c, NULL, 0 TSRMLS_CC)) { zval_dtor(&c); RETURN_TRUE; } else { @@ -772,7 +772,7 @@ static void add_class_vars(zend_class_en /* this is necessary to make it able to work with default array * properties, returned to user */ - if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || Z_TYPE_P(prop_copy) == IS_CONSTANT) { + if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) { zval_update_constant(&prop_copy, 0 TSRMLS_CC); } Index: Zend/zend_compile.c =================================================================== RCS file: /repository/ZendEngine2/zend_compile.c,v retrieving revision 1.764 diff -u -p -d -r1.764 zend_compile.c --- Zend/zend_compile.c 22 Aug 2007 07:39:37 -0000 1.764 +++ Zend/zend_compile.c 22 Aug 2007 08:27:42 -0000 @@ -3691,7 +3691,7 @@ void zend_do_end_new_object(znode *resul } /* }}} */ -static int zend_constant_ct_subst(znode *result, zval *const_name TSRMLS_DC) /* {{{ */ +static zend_constant* zend_get_ct_const(zval *const_name TSRMLS_DC) /* {{{ */ { zend_constant *c = NULL; @@ -3701,14 +3701,27 @@ static int zend_constant_ct_subst(znode if (zend_u_hash_find(EG(zend_constants), Z_TYPE_P(const_name), lookup_name, lookup_name_len+1, (void **) &c)==SUCCESS) { if ((c->flags & CONST_CS) && memcmp(c->name.v, Z_UNIVAL_P(const_name).v, UG(unicode)?UBYTES(Z_USTRLEN_P(const_name)):Z_STRLEN_P(const_name))!=0) { - c = NULL; + efree(lookup_name.v); + return NULL; } } else { - c = NULL; + efree(lookup_name.v); + return NULL; } efree(lookup_name.v); } - if (c && (c->flags & CONST_CT_SUBST)) { + if (c->flags & CONST_CT_SUBST) { + return c; + } + return NULL; +} +/* }}} */ + +static int zend_constant_ct_subst(znode *result, zval *const_name TSRMLS_DC) /* {{{ */ +{ + zend_constant *c = zend_get_ct_const(const_name TSRMLS_CC); + + if (c) { zval_dtor(const_name); result->op_type = IS_CONST; result->u.constant = c->value; @@ -3720,44 +3733,110 @@ static int zend_constant_ct_subst(znode } /* }}} */ -void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode TSRMLS_DC) /* {{{ */ +void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode, zend_bool check_namespace TSRMLS_DC) /* {{{ */ { + ulong fetch_type = 0; + znode tmp; + switch (mode) { case ZEND_CT: if (constant_container) { - ulong fetch_type; - if (ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_TYPE(constant_container->u.constant), Z_UNIVAL(constant_container->u.constant), Z_UNILEN(constant_container->u.constant))) { zend_resolve_class_name(constant_container, &fetch_type, 1 TSRMLS_CC); } zend_do_fetch_class_name(NULL, constant_container, constant_name TSRMLS_CC); *result = *constant_container; - result->u.constant.type = IS_CONSTANT; + result->u.constant.type = IS_CONSTANT | fetch_type; } else if (!zend_constant_ct_subst(result, &constant_name->u.constant TSRMLS_CC)) { + if (check_namespace && CG(current_namespace)) { + /* We assume we use constant from the current namespace + if it is not prefixed. */ + tmp.op_type = IS_CONST; + tmp.u.constant = *CG(current_namespace); + zval_copy_ctor(&tmp.u.constant); + zend_do_build_namespace_name(&tmp, &tmp, constant_name TSRMLS_CC); + *constant_name = tmp; + fetch_type = IS_CONSTANT_RT_NS_CHECK; + } *result = *constant_name; - result->u.constant.type = IS_CONSTANT; + result->u.constant.type = IS_CONSTANT | fetch_type; } break; case ZEND_RT: if (constant_container || !zend_constant_ct_subst(result, &constant_name->u.constant TSRMLS_CC)) { zend_op *opline; - znode class_node; if (constant_container) { - zend_do_fetch_class(&class_node, constant_container TSRMLS_CC); + if (constant_container->op_type == IS_CONST && + ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_TYPE(constant_container->u.constant), Z_UNIVAL(constant_container->u.constant), Z_UNILEN(constant_container->u.constant))) { + zend_resolve_class_name(constant_container, &fetch_type, 1 TSRMLS_CC); + } else { + zend_do_fetch_class(&tmp, constant_container TSRMLS_CC); + constant_container = &tmp; + } + } else if (check_namespace && CG(current_namespace)) { + /* We assume we use constant from the current namespace + if it is not prefixed. */ + tmp.op_type = IS_CONST; + tmp.u.constant = *CG(current_namespace); + zval_copy_ctor(&tmp.u.constant); + constant_container = &tmp; + fetch_type = IS_CONSTANT_RT_NS_CHECK; } opline = get_next_op(CG(active_op_array) TSRMLS_CC); opline->opcode = ZEND_FETCH_CONSTANT; + opline->extended_value = fetch_type & ~ZEND_FETCH_CLASS_RT_NS_NAME; opline->result.op_type = IS_TMP_VAR; opline->result.u.var = get_temporary_variable(CG(active_op_array)); if (constant_container) { - opline->op1 = class_node; + opline->op1 = *constant_container; } else { SET_UNUSED(opline->op1); } opline->op2 = *constant_name; *result = opline->result; + + if (opline->op1.op_type == IS_CONST) { + /* Prebuild ns::func name to speedup run-time check. + The additional names are stored in additional OP_DATA opcode. */ + zstr nsname; + unsigned int nsname_len; + + opline = get_next_op(CG(active_op_array) TSRMLS_CC); + opline->opcode = ZEND_OP_DATA; + opline->op1.op_type = IS_CONST; + SET_UNUSED(opline->op2); + + nsname = Z_UNIVAL(constant_container->u.constant); + nsname_len = Z_UNILEN(constant_container->u.constant); + if (fetch_type & ZEND_FETCH_CLASS_RT_NS_NAME) { + /* Remove namespace name */ + if (Z_TYPE(constant_container->u.constant) == IS_UNICODE) { + nsname.u = u_memchr(nsname.u, ':', nsname_len) + 2; + nsname_len -= (nsname.u - Z_USTRVAL(constant_container->u.constant)); + } else { + nsname.s = memchr(nsname.s, ':', nsname_len) + 2; + nsname_len -= (nsname.s - Z_STRVAL(constant_container->u.constant)); + } + } + + Z_TYPE(opline->op1.u.constant) = Z_TYPE(constant_container->u.constant); + Z_UNIVAL(opline->op1.u.constant) = zend_u_str_case_fold(Z_TYPE(constant_container->u.constant), nsname, nsname_len, 0, &Z_UNILEN(opline->op1.u.constant)); + if (UG(unicode)) { + Z_USTRVAL(opline->op1.u.constant) = erealloc(Z_USTRVAL(opline->op1.u.constant), UBYTES(Z_USTRLEN(opline->op1.u.constant) + 2 + Z_USTRLEN(constant_name->u.constant) + 1)); + Z_USTRVAL(opline->op1.u.constant)[Z_USTRLEN(opline->op1.u.constant)] = ':'; + Z_USTRVAL(opline->op1.u.constant)[Z_USTRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(Z_USTRVAL(opline->op1.u.constant)+Z_USTRLEN(opline->op1.u.constant)+2, Z_USTRVAL(constant_name->u.constant), UBYTES(Z_USTRLEN(constant_name->u.constant) + 1)); + } else { + Z_STRVAL(opline->op1.u.constant) = erealloc(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant) + 2 + Z_STRLEN(constant_name->u.constant) + 1); + Z_STRVAL(opline->op1.u.constant)[Z_STRLEN(opline->op1.u.constant)] = ':'; + Z_STRVAL(opline->op1.u.constant)[Z_STRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(Z_STRVAL(opline->op1.u.constant)+Z_STRLEN(opline->op1.u.constant)+2, Z_STRVAL(constant_name->u.constant), Z_STRLEN(constant_name->u.constant) + 1); + } + Z_UNILEN(opline->op1.u.constant) += 2 + Z_UNILEN(constant_name->u.constant); + opline->extended_value = zend_u_hash_func(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant) + 1); + } } break; } @@ -3846,7 +3925,7 @@ void zend_do_add_static_array_element(zn if (offset) { zend_uchar utype = Z_TYPE(offset->u.constant); - switch (Z_TYPE(offset->u.constant)) { + switch (Z_TYPE(offset->u.constant) & IS_CONSTANT_TYPE_MASK) { case IS_CONSTANT: /* Ugly hack to denote that this value has a constant index */ Z_TYPE_P(element) |= IS_CONSTANT_INDEX; @@ -5051,6 +5130,37 @@ void zend_do_import(znode *ns_name, znod } /* }}} */ +void zend_do_declare_constant(znode *name, znode *value TSRMLS_DC) /* {{{ */ +{ + zend_op *opline; + + if (zend_get_ct_const(&name->u.constant TSRMLS_CC)) { + zend_error(E_COMPILE_ERROR, "Cannot redeclare constant '%R'", Z_TYPE(name->u.constant), Z_UNIVAL(name->u.constant)); + } + + if (CG(current_namespace)) { + /* Prefix constant name with name of current namespace */ + znode tmp; + zstr lcname; + uint lcname_len; + + tmp.op_type = IS_CONST; + tmp.u.constant = *CG(current_namespace); + lcname = zend_u_str_case_fold(Z_TYPE(tmp.u.constant), Z_UNIVAL(tmp.u.constant), Z_UNILEN(tmp.u.constant), 0, &lcname_len); + Z_UNIVAL(tmp.u.constant) = lcname; + Z_UNILEN(tmp.u.constant) = lcname_len; + zend_do_build_namespace_name(&tmp, &tmp, name TSRMLS_CC); + *name = tmp; + } + + opline = get_next_op(CG(active_op_array) TSRMLS_CC); + opline->opcode = ZEND_DECLARE_CONST; + SET_UNUSED(opline->result); + opline->op1 = *name; + opline->op2 = *value; +} +/* }}} */ + void zend_do_end_compilation(TSRMLS_D) /* {{{ */ { if (CG(current_namespace)) { Index: Zend/zend_compile.h =================================================================== RCS file: /repository/ZendEngine2/zend_compile.h,v retrieving revision 1.363 diff -u -p -d -r1.363 zend_compile.h --- Zend/zend_compile.h 20 Aug 2007 09:48:41 -0000 1.363 +++ Zend/zend_compile.h 22 Aug 2007 08:27:43 -0000 @@ -470,7 +470,7 @@ void zend_do_pop_object(znode *object TS void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC); void zend_do_end_new_object(znode *result, znode *new_token, znode *argument_list TSRMLS_DC); -void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode TSRMLS_DC); +void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode, zend_bool check_namespace TSRMLS_DC); void zend_do_shell_exec(znode *result, znode *cmd TSRMLS_DC); @@ -519,6 +519,7 @@ void zend_do_ticks(TSRMLS_D); void zend_do_abstract_method(znode *function_name, znode *modifiers, znode *body TSRMLS_DC); +void zend_do_declare_constant(znode *name, znode *value TSRMLS_DC); void zend_do_build_namespace_name(znode *result, znode *prefix, znode *name TSRMLS_DC); void zend_do_namespace(znode *name TSRMLS_DC); void zend_do_import(znode *name, znode *new_name TSRMLS_DC); Index: Zend/zend_constants.c =================================================================== RCS file: /repository/ZendEngine2/zend_constants.c,v retrieving revision 1.97 diff -u -p -d -r1.97 zend_constants.c --- Zend/zend_constants.c 27 Jul 2007 16:29:25 -0000 1.97 +++ Zend/zend_constants.c 22 Aug 2007 08:27:43 -0000 @@ -258,21 +258,88 @@ ZEND_API void zend_register_string_const } /* }}} */ -ZEND_API int zend_u_get_constant(zend_uchar type, zstr name, uint name_len, zval *result, zend_class_entry *scope TSRMLS_DC) /* {{{ */ +ZEND_API int zend_u_get_constant(zend_uchar type, zstr name, uint name_len, zval *result TSRMLS_DC) /* {{{ */ { zend_constant *c; int retval = 1; zstr lookup_name; + + if (zend_u_hash_find(EG(zend_constants), type, name, name_len+1, (void **) &c) == FAILURE) { + unsigned int lookup_name_len; + + lookup_name = zend_u_str_case_fold(type, name, name_len, 1, &lookup_name_len); + + if (zend_u_hash_find(EG(zend_constants), type, lookup_name, lookup_name_len+1, (void **) &c)==SUCCESS) { + if ((c->flags & CONST_CS) && memcmp(c->name.v, name.v, UG(unicode)?UBYTES(name_len):name_len)!=0) { + retval=0; + } + } else { + if (!EG(in_execution)) { + retval = 0; + } else if (name_len == sizeof(ZEND_HALT_CONSTANT_NAME)-1 && ZEND_U_EQUAL(type, name, name_len, ZEND_HALT_CONSTANT_NAME, sizeof(ZEND_HALT_CONSTANT_NAME)-1)) { + char *cfilename; + zstr haltname; + int len, clen; + cfilename = zend_get_executed_filename(TSRMLS_C); + clen = strlen(cfilename); + /* check for __COMPILER_HALT_OFFSET__ */ + zend_mangle_property_name(&haltname.s, &len, ZEND_HALT_CONSTANT_NAME, + sizeof(ZEND_HALT_CONSTANT_NAME) - 1, cfilename, clen, 0); + if (zend_u_hash_find(EG(zend_constants), IS_STRING, haltname, len+1, (void **) &c) == SUCCESS) { + retval=1; + } else { + retval=0; + } + pefree(haltname.s, 0); + } else { + retval=0; + } + } + efree(lookup_name.v); + } + + if (retval) { + *result = c->value; + zval_copy_ctor(result); + result->refcount = 1; + result->is_ref = 0; + } + + return retval; +} +/* }}} */ + +ZEND_API int zend_u_get_constant_ex(zend_uchar type, zstr name, uint name_len, zval *result, zend_class_entry *scope, ulong flags TSRMLS_DC) /* {{{ */ +{ + zend_constant *c; + int retval = 1; zstr colon; + /* Skip leading :: */ + if (type == IS_UNICODE && + name.u[0] == ':' && + name.u[1] == ':') { + name.u += 2; + name_len -= 2; + flags = 0; + } else if (type == IS_STRING && + name.s[0] == ':' && + name.s[1] == ':') { + name.s += 2; + name_len -= 2; + flags = 0; + } + if ((UG(unicode) && (colon.u = u_memrchr(name.u, ':', name_len)) && colon.u > name.u && *(colon.u-1) == ':') || (!UG(unicode) && (colon.s = zend_memrchr(name.s, ':', name_len))&& colon.s > name.s && *(colon.s-1) == ':')) { - /* class constant */ + /* compound constant name */ zend_class_entry **ce = NULL; int class_name_len = UG(unicode)?colon.u-name.u-1:colon.s-name.s-1; int const_name_len = name_len - class_name_len - 2; zstr constant_name, class_name; zval **ret_constant; + zstr lcname; + unsigned int lcname_len; if (UG(unicode)) { constant_name.u = colon.u + 1; @@ -294,16 +361,19 @@ ZEND_API int zend_u_get_constant(zend_uc class_name.s = estrndup(name.s, class_name_len); } - if (class_name_len == sizeof("self")-1 && - ZEND_U_EQUAL(type, class_name, class_name_len, "self", sizeof("self")-1)) { + lcname = zend_u_str_case_fold(type, class_name, class_name_len, 0, &lcname_len); + + if (lcname_len == sizeof("self")-1 && + ZEND_U_EQUAL(type, lcname, lcname_len, "self", sizeof("self")-1)) { if (scope) { ce = &scope; } else { zend_error(E_ERROR, "Cannot access self:: when no class scope is active"); retval = 0; } - } else if (class_name_len == sizeof("parent")-1 && - ZEND_U_EQUAL(type, class_name, class_name_len, "parent", sizeof("parent")-1)) { + efree(lcname.v); + } else if (lcname_len == sizeof("parent")-1 && + ZEND_U_EQUAL(type, lcname, lcname_len, "parent", sizeof("parent")-1)) { if (!scope) { zend_error(E_ERROR, "Cannot access parent:: when no class scope is active"); } else if (!scope->parent) { @@ -311,14 +381,57 @@ ZEND_API int zend_u_get_constant(zend_uc } else { ce = &scope->parent; } + efree(lcname.v); } else { - if (zend_u_lookup_class(type, class_name, class_name_len, &ce TSRMLS_CC) != SUCCESS) { + /* Check for namespace constant */ + zstr nsname; + unsigned int nsname_len; + + /* Concatenate lowercase namespace name and constant name */ + if (UG(unicode)) { + lcname.u = erealloc(lcname.u, UBYTES(lcname_len + 2 + const_name_len + 1)); + lcname.u[lcname_len] = ':'; + lcname.u[lcname_len+1] = ':'; + memcpy(lcname.u+lcname_len+2, constant_name.u, UBYTES(const_name_len + 1)); + } else { + lcname.s = erealloc(lcname.s, lcname_len + 2 + const_name_len + 1); + lcname.s[lcname_len] = ':'; + lcname.s[lcname_len+1] = ':'; + memcpy(lcname.s+lcname_len+2, constant_name.s, const_name_len + 1); + } + lcname_len += 2 + const_name_len; + + nsname = lcname; + nsname_len = lcname_len; + if (flags & ZEND_FETCH_CLASS_RT_NS_NAME) { + /* Remove namespace name */ + if (UG(unicode)) { + nsname.u = u_memchr(nsname.u, ':', nsname_len) + 2; + nsname_len -= (nsname.u - lcname.u); + } else { + nsname.s = memchr(nsname.s, ':', nsname_len) + 2; + nsname_len -= (nsname.s - lcname.s); + } + } + + if (zend_u_hash_find(EG(zend_constants), type, nsname, nsname_len+1, (void **) &c) == SUCCESS) { + efree(lcname.v); + efree(class_name.v); + *result = c->value; + zval_update_constant_ex(&result, (void*)1, NULL TSRMLS_CC); + zval_copy_ctor(result); + result->refcount = 1; + result->is_ref = 0; + return 1; + } + efree(lcname.v); + + /* Check for class */ + if (zend_u_lookup_class(type, class_name, class_name_len, &ce TSRMLS_CC) != SUCCESS && + (flags & ZEND_FETCH_CLASS_RT_NS_CHECK) != 0) { retval = 0; if ((UG(unicode) && (colon.u = u_memrchr(class_name.u, ':', class_name_len)) && colon.u > class_name.u && *(colon.u-1) == ':') || (!UG(unicode) && (colon.s = zend_memrchr(class_name.s, ':', class_name_len))&& colon.s > class_name.s && *(colon.s-1) == ':')) { - zend_class_entry **pce; - zstr lcname; - unsigned int lcname_len; if (UG(unicode)) { colon.u++; @@ -342,7 +455,16 @@ ZEND_API int zend_u_get_constant(zend_uc retval = 0; } } else { - zend_error(E_ERROR, "Class '%R' not found", type, class_name); + if ((flags & ZEND_FETCH_CLASS_RT_NS_NAME) == 0) { + if ((flags & IS_CONSTANT_RT_NS_CHECK) != 0) { + name = constant_name; + name_len = const_name_len; + efree(class_name.v); + retval = 1; + return zend_u_get_constant(type, name, name_len, result TSRMLS_CC); + } + zend_error(E_ERROR, "Class '%R' not found", type, class_name); + } retval = 0; } efree(class_name.v); @@ -356,54 +478,13 @@ ZEND_API int zend_u_get_constant(zend_uc return retval; } - if (zend_u_hash_find(EG(zend_constants), type, name, name_len+1, (void **) &c) == FAILURE) { - unsigned int lookup_name_len; - - lookup_name = zend_u_str_case_fold(type, name, name_len, 1, &lookup_name_len); - - if (zend_u_hash_find(EG(zend_constants), type, lookup_name, lookup_name_len+1, (void **) &c)==SUCCESS) { - if ((c->flags & CONST_CS) && memcmp(c->name.v, name.v, UG(unicode)?UBYTES(name_len):name_len)!=0) { - retval=0; - } - } else { - if (!EG(in_execution)) { - retval = 0; - } else if (name_len == sizeof(ZEND_HALT_CONSTANT_NAME)-1 && ZEND_U_EQUAL(type, name, name_len, ZEND_HALT_CONSTANT_NAME, sizeof(ZEND_HALT_CONSTANT_NAME)-1)) { - char *cfilename; - zstr haltname; - int len, clen; - cfilename = zend_get_executed_filename(TSRMLS_C); - clen = strlen(cfilename); - /* check for __COMPILER_HALT_OFFSET__ */ - zend_mangle_property_name(&haltname.s, &len, ZEND_HALT_CONSTANT_NAME, - sizeof(ZEND_HALT_CONSTANT_NAME) - 1, cfilename, clen, 0); - if (zend_u_hash_find(EG(zend_constants), IS_STRING, haltname, len+1, (void **) &c) == SUCCESS) { - retval=1; - } else { - retval=0; - } - pefree(haltname.s, 0); - } else { - retval=0; - } - } - efree(lookup_name.v); - } - - if (retval) { - *result = c->value; - zval_copy_ctor(result); - result->refcount = 1; - result->is_ref = 0; - } - - return retval; + return zend_u_get_constant(type, name, name_len, result TSRMLS_CC); } /* }}} */ ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC) /* {{{ */ { - return zend_u_get_constant(IS_STRING, ZSTR(name), name_len, result, NULL TSRMLS_CC); + return zend_u_get_constant_ex(IS_STRING, ZSTR(name), name_len, result, NULL, 0 TSRMLS_CC); } /* }}} */ @@ -461,7 +542,7 @@ ZEND_API int zend_register_constant(zend free(c->name.s); c->name.u = ustr; } - if (Z_TYPE(c->value) == IS_STRING || Z_TYPE(c->value) == IS_CONSTANT) { + if (Z_TYPE(c->value) == IS_STRING || (Z_TYPE(c->value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) { ustr = pemalloc(UBYTES(Z_STRLEN(c->value)+1), c->flags & CONST_PERSISTENT); u_charsToUChars(Z_STRVAL(c->value), ustr, Z_STRLEN(c->value)+1); pefree(Z_STRVAL(c->value), c->flags & CONST_PERSISTENT); Index: Zend/zend_constants.h =================================================================== RCS file: /repository/ZendEngine2/zend_constants.h,v retrieving revision 1.40 diff -u -p -d -r1.40 zend_constants.h --- Zend/zend_constants.h 3 Aug 2007 18:41:07 -0000 1.40 +++ Zend/zend_constants.h 22 Aug 2007 08:27:43 -0000 @@ -56,7 +56,8 @@ int zend_shutdown_constants(TSRMLS_D); void zend_register_standard_constants(TSRMLS_D); void clean_non_persistent_constants(TSRMLS_D); ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC); -ZEND_API int zend_u_get_constant(zend_uchar type, zstr name, uint name_len, zval *result, zend_class_entry *scope TSRMLS_DC); +ZEND_API int zend_u_get_constant(zend_uchar type, zstr name, uint name_len, zval *result TSRMLS_DC); +ZEND_API int zend_u_get_constant_ex(zend_uchar type, zstr name, uint name_len, zval *result, zend_class_entry *scope, ulong flags TSRMLS_DC); ZEND_API void zend_register_long_constant(char *name, uint name_len, long lval, int flags, int module_number TSRMLS_DC); ZEND_API void zend_register_double_constant(char *name, uint name_len, double dval, int flags, int module_number TSRMLS_DC); ZEND_API void zend_register_string_constant(char *name, uint name_len, char *strval, int flags, int module_number TSRMLS_DC); Index: Zend/zend_execute_API.c =================================================================== RCS file: /repository/ZendEngine2/zend_execute_API.c,v retrieving revision 1.412 diff -u -p -d -r1.412 zend_execute_API.c --- Zend/zend_execute_API.c 22 Aug 2007 07:39:37 -0000 1.412 +++ Zend/zend_execute_API.c 22 Aug 2007 08:27:43 -0000 @@ -485,10 +485,11 @@ ZEND_API int zval_update_constant_ex(zva zend_bool inline_change = (zend_bool) (zend_uintptr_t) arg; zval const_value; zstr colon; + int len; if (IS_CONSTANT_VISITED(p)) { zend_error(E_ERROR, "Cannot declare self-referencing constant '%v'", Z_UNIVAL_P(p)); - } else if (Z_TYPE_P(p) == IS_CONSTANT) { + } else if ((Z_TYPE_P(p) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) { int refcount; zend_uchar is_ref; @@ -500,10 +501,15 @@ ZEND_API int zval_update_constant_ex(zva refcount = p->refcount; is_ref = p->is_ref; - if (!zend_u_get_constant(ZEND_STR_TYPE, Z_UNIVAL_P(p), Z_UNILEN_P(p), &const_value, scope TSRMLS_CC)) { - if ((UG(unicode) && (colon.u = u_memchr(Z_USTRVAL_P(p), ':', Z_USTRLEN_P(p))) && colon.u[1] == ':') || - (!UG(unicode) && (colon.s = memchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p))) && colon.s[1] == ':')) { - zend_error(E_ERROR, "Undefined class constant '%v'", Z_UNIVAL_P(p)); + if (!zend_u_get_constant_ex(ZEND_STR_TYPE, Z_UNIVAL_P(p), Z_UNILEN_P(p), &const_value, scope, Z_TYPE_P(p) TSRMLS_CC)) { + if ((UG(unicode) && (colon.u = u_memrchr(Z_USTRVAL_P(p), ':', Z_USTRLEN_P(p))) && colon.u > Z_USTRVAL_P(p) && *(colon.u-1) == ':') || + (!UG(unicode) && (colon.s = zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p))) && colon.s > Z_STRVAL_P(p) && *(colon.s-1) == ':')) { + if (UG(unicode)) { + colon.u++; + } else { + colon.s++; + } + zend_error(E_ERROR, "Undefined class constant '%v'", colon); } zend_error(E_NOTICE, "Use of undefined constant %v - assumed '%v'", Z_UNIVAL_P(p), @@ -543,7 +549,7 @@ ZEND_API int zval_update_constant_ex(zva zend_hash_move_forward(Z_ARRVAL_P(p)); continue; } - if (!zend_u_get_constant(ZEND_STR_TYPE, str_index, str_index_len-1, &const_value, scope TSRMLS_CC)) { + if (!zend_u_get_constant_ex(ZEND_STR_TYPE, str_index, str_index_len-1, &const_value, scope, 0 TSRMLS_CC)) { if ((UG(unicode) && (colon.u = u_memchr(str_index.u, ':', str_index_len-1)) && colon.u[1] == ':') || (!UG(unicode) && (colon.s = memchr(str_index.s, ':', str_index_len-1)) && colon.s[1] == ':')) { zend_error(E_ERROR, "Undefined class constant '%v'", str_index); Index: Zend/zend_language_parser.y =================================================================== RCS file: /repository/ZendEngine2/zend_language_parser.y,v retrieving revision 1.188 diff -u -p -d -r1.188 zend_language_parser.y --- Zend/zend_language_parser.y 20 Aug 2007 09:48:41 -0000 1.188 +++ Zend/zend_language_parser.y 22 Aug 2007 08:27:43 -0000 @@ -174,8 +174,13 @@ top_statement: | T_NAMESPACE namespace_name ';' { zend_do_namespace(&$2 TSRMLS_CC); } | T_IMPORT namespace_name ';' { zend_do_import(&$2, NULL TSRMLS_CC); } | T_IMPORT namespace_name T_AS T_STRING ';' { zend_do_import(&$2, &$4 TSRMLS_CC); } + | constant_declaration ';' ; +constant_declaration: + constant_declaration ',' T_STRING '=' expr { zend_do_declare_constant(&$3, &$5 TSRMLS_CC); } + | T_CONST T_STRING '=' expr { zend_do_declare_constant(&$2, &$4 TSRMLS_CC); } +; inner_statement_list: inner_statement_list { zend_do_extended_info(TSRMLS_C); } inner_statement { HANDLE_INTERACTIVE(); } @@ -722,7 +727,8 @@ common_scalar: static_scalar: /* compile-time evaluated scalars */ common_scalar { $$ = $1; } - | T_STRING { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT TSRMLS_CC); } + | T_STRING { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT, 1 TSRMLS_CC); } + | T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, NULL, &$2, ZEND_CT, 0 TSRMLS_CC); } | '+' static_scalar { $$ = $2; } | '-' static_scalar { zval minus_one; Z_TYPE(minus_one) = IS_LONG; Z_LVAL(minus_one) = -1; mul_function(&$2.u.constant, &$2.u.constant, &minus_one TSRMLS_CC); $$ = $2; } | T_ARRAY '(' static_array_pair_list ')' { $$ = $3; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; } @@ -730,11 +736,12 @@ static_scalar: /* compile-time evaluated ; static_class_constant: - fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_CT TSRMLS_CC); } + fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_CT, 0 TSRMLS_CC); } ; scalar: - T_STRING { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_RT TSRMLS_CC); } + T_STRING { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_RT, 1 TSRMLS_CC); } + | T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, NULL, &$2, ZEND_RT, 0 TSRMLS_CC); } | T_STRING_VARNAME { $$ = $1; } | class_constant { $$ = $1; } | common_scalar { $$ = $1; } @@ -945,8 +952,8 @@ isset_variables: ; class_constant: - fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT TSRMLS_CC); } - | variable_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT TSRMLS_CC); } + fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT, 0 TSRMLS_CC); } + | variable_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT, 0 TSRMLS_CC); } ; %% Index: Zend/zend_variables.c =================================================================== RCS file: /repository/ZendEngine2/zend_variables.c,v retrieving revision 1.70 diff -u -p -d -r1.70 zend_variables.c --- Zend/zend_variables.c 11 Jul 2007 11:19:58 -0000 1.70 +++ Zend/zend_variables.c 22 Aug 2007 08:27:43 -0000 @@ -28,7 +28,7 @@ ZEND_API void _zval_dtor_func(zval *zvalue ZEND_FILE_LINE_DC) /* {{{ */ { - switch (Z_TYPE_P(zvalue) & ~IS_CONSTANT_INDEX) { + switch (Z_TYPE_P(zvalue) & IS_CONSTANT_TYPE_MASK) { case IS_CONSTANT: { TSRMLS_FETCH(); @@ -81,7 +81,7 @@ dtor_unicode: ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC) /* {{{ */ { - switch (Z_TYPE_P(zvalue) & ~IS_CONSTANT_INDEX) { + switch (Z_TYPE_P(zvalue) & IS_CONSTANT_TYPE_MASK) { case IS_CONSTANT: { TSRMLS_FETCH(); @@ -120,7 +120,7 @@ ZEND_API void zval_add_ref(zval **p) /* ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC) /* {{{ */ { - switch (Z_TYPE_P(zvalue)) { + switch (Z_TYPE_P(zvalue) & IS_CONSTANT_TYPE_MASK) { case IS_RESOURCE: { TSRMLS_FETCH(); Index: Zend/zend_vm_def.h =================================================================== RCS file: /repository/ZendEngine2/zend_vm_def.h,v retrieving revision 1.178 diff -u -p -d -r1.178 zend_vm_def.h --- Zend/zend_vm_def.h 22 Aug 2007 07:39:37 -0000 1.178 +++ Zend/zend_vm_def.h 22 Aug 2007 08:27:43 -0000 @@ -2466,7 +2466,7 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, zend_free_op free_res; if (zend_ptr_stack_get_arg(arg_num, (void **) ¶m TSRMLS_CC)==FAILURE) { - if (Z_TYPE(opline->op2.u.constant) == IS_CONSTANT || Z_TYPE(opline->op2.u.constant)==IS_CONSTANT_ARRAY) { + if ((Z_TYPE(opline->op2.u.constant) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE(opline->op2.u.constant)==IS_CONSTANT_ARRAY) { zval *default_value; ALLOC_ZVAL(default_value); @@ -2700,37 +2700,51 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|T ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|UNUSED, CONST) +ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|UNUSED|CONST, CONST) { zend_op *opline = EX(opline); zend_class_entry *ce = NULL; zval **value; if (OP1_TYPE == IS_UNUSED) { -/* This seems to be a reminant of namespaces - if (EG(scope)) { - ce = EG(scope); - if (zend_hash_find(&ce->constants_table, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { - zval_update_constant(value, (void *) 1 TSRMLS_CC); - EX_T(opline->result.u.var).tmp_var = **value; - zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); - ZEND_VM_NEXT_OPCODE(); - } - } -*/ - if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var, NULL TSRMLS_CC)) { + if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", - Z_TYPE(opline->op2.u.constant), - Z_UNIVAL(opline->op2.u.constant), - Z_TYPE(opline->op2.u.constant), - Z_UNIVAL(opline->op2.u.constant)); + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); } ZEND_VM_NEXT_OPCODE(); - } + } else if (OP1_TYPE == IS_CONST) { + zend_op *op_data = opline + 1; + zend_constant *c; - ce = EX_T(opline->op1.u.var).class_entry; + ZEND_VM_INC_OPCODE(); + + /* try a constant in namespace */ + if (zend_u_hash_quick_find(EG(zend_constants), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) { + EX_T(opline->result.u.var).tmp_var = c->value; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + ZEND_VM_NEXT_OPCODE(); + } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) { + if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { + zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + } + ZEND_VM_NEXT_OPCODE(); + } + + /* no constant found. try a constant in class */ + ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); + if (!ce) { + zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + } + } else { + ce = EX_T(opline->op1.u.var).class_entry; + } if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { zend_class_entry *old_scope = EG(scope); @@ -4116,4 +4130,43 @@ ZEND_VM_HANDLER(151, ZEND_U_NORMALIZE, C ZEND_VM_NEXT_OPCODE(); } +ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST|TMP|VAR|CV) +{ + zend_op *opline = EX(opline); + zend_free_op free_op1, free_op2; + zval *name = GET_OP1_ZVAL_PTR(BP_VAR_R); + zval *val = GET_OP2_ZVAL_PTR(BP_VAR_R); + zend_constant c; + + if ((Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { + zval tmp = *val; + zval *tmp_ptr = &tmp; + + if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { + zval_copy_ctor(&tmp); + } + INIT_PZVAL(&tmp); + zval_update_constant(&tmp_ptr, NULL TSRMLS_CC); + c.value = *tmp_ptr; + } else { + c.value = *val; + zval_copy_ctor(&c.value); + } + c.flags = CONST_CS; /* non persistent, case sensetive */ + if (Z_TYPE_P(name) == IS_UNICODE) { + c.name.u = zend_ustrndup(Z_USTRVAL_P(name), Z_USTRLEN_P(name)); + } else { + c.name.s = zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name)); + } + c.name_len = Z_UNILEN_P(name)+1; + c.module_number = PHP_USER_CONSTANT; + + if (zend_u_register_constant(Z_TYPE_P(name), &c TSRMLS_CC) == FAILURE) { + } + + FREE_OP1(); + FREE_OP2(); + ZEND_VM_NEXT_OPCODE(); +} + ZEND_VM_EXPORT_HELPER(zend_do_fcall, zend_do_fcall_common_helper) Index: Zend/zend_vm_execute.h =================================================================== RCS file: /repository/ZendEngine2/zend_vm_execute.h,v retrieving revision 1.182 diff -u -p -d -r1.182 zend_vm_execute.h --- Zend/zend_vm_execute.h 22 Aug 2007 07:39:37 -0000 1.182 +++ Zend/zend_vm_execute.h 22 Aug 2007 08:27:43 -0000 @@ -757,7 +757,7 @@ static int ZEND_RECV_INIT_SPEC_CONST_HAN zend_free_op free_res; if (zend_ptr_stack_get_arg(arg_num, (void **) ¶m TSRMLS_CC)==FAILURE) { - if (Z_TYPE(opline->op2.u.constant) == IS_CONSTANT || Z_TYPE(opline->op2.u.constant)==IS_CONSTANT_ARRAY) { + if ((Z_TYPE(opline->op2.u.constant) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE(opline->op2.u.constant)==IS_CONSTANT_ARRAY) { zval *default_value; ALLOC_ZVAL(default_value); @@ -2651,6 +2651,67 @@ static int ZEND_CASE_SPEC_CONST_CONST_HA ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *opline = EX(opline); + zend_class_entry *ce = NULL; + zval **value; + + if (IS_CONST == IS_UNUSED) { + if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { + zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + } + ZEND_VM_NEXT_OPCODE(); + } else if (IS_CONST == IS_CONST) { + zend_op *op_data = opline + 1; + zend_constant *c; + + ZEND_VM_INC_OPCODE(); + + /* try a constant in namespace */ + if (zend_u_hash_quick_find(EG(zend_constants), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) { + EX_T(opline->result.u.var).tmp_var = c->value; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + ZEND_VM_NEXT_OPCODE(); + } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) { + if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { + zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + } + ZEND_VM_NEXT_OPCODE(); + } + + /* no constant found. try a constant in class */ + ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); + if (!ce) { + zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + } + } else { + ce = EX_T(opline->op1.u.var).class_entry; + } + + if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { + zend_class_entry *old_scope = EG(scope); + + EG(scope) = ce; + zval_update_constant(value, (void *) 1 TSRMLS_CC); + EG(scope) = old_scope; + EX_T(opline->result.u.var).tmp_var = **value; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + } else { + zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + } + + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -2745,6 +2806,44 @@ static int ZEND_INIT_ARRAY_SPEC_CONST_CO } } +static int ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *opline = EX(opline); + + zval *name = &opline->op1.u.constant; + zval *val = &opline->op2.u.constant; + zend_constant c; + + if ((Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { + zval tmp = *val; + zval *tmp_ptr = &tmp; + + if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { + zval_copy_ctor(&tmp); + } + INIT_PZVAL(&tmp); + zval_update_constant(&tmp_ptr, NULL TSRMLS_CC); + c.value = *tmp_ptr; + } else { + c.value = *val; + zval_copy_ctor(&c.value); + } + c.flags = CONST_CS; /* non persistent, case sensetive */ + if (Z_TYPE_P(name) == IS_UNICODE) { + c.name.u = zend_ustrndup(Z_USTRVAL_P(name), Z_USTRLEN_P(name)); + } else { + c.name.s = zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name)); + } + c.name_len = Z_UNILEN_P(name)+1; + c.module_number = PHP_USER_CONSTANT; + + if (zend_u_register_constant(Z_TYPE_P(name), &c TSRMLS_CC) == FAILURE) { + } + + + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_ADD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -3190,6 +3289,44 @@ static int ZEND_INIT_ARRAY_SPEC_CONST_TM } } +static int ZEND_DECLARE_CONST_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *opline = EX(opline); + zend_free_op free_op2; + zval *name = &opline->op1.u.constant; + zval *val = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + zend_constant c; + + if ((Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { + zval tmp = *val; + zval *tmp_ptr = &tmp; + + if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { + zval_copy_ctor(&tmp); + } + INIT_PZVAL(&tmp); + zval_update_constant(&tmp_ptr, NULL TSRMLS_CC); + c.value = *tmp_ptr; + } else { + c.value = *val; + zval_copy_ctor(&c.value); + } + c.flags = CONST_CS; /* non persistent, case sensetive */ + if (Z_TYPE_P(name) == IS_UNICODE) { + c.name.u = zend_ustrndup(Z_USTRVAL_P(name), Z_USTRLEN_P(name)); + } else { + c.name.s = zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name)); + } + c.name_len = Z_UNILEN_P(name)+1; + c.module_number = PHP_USER_CONSTANT; + + if (zend_u_register_constant(Z_TYPE_P(name), &c TSRMLS_CC) == FAILURE) { + } + + zval_dtor(free_op2.var); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_ADD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -3635,6 +3772,44 @@ static int ZEND_INIT_ARRAY_SPEC_CONST_VA } } +static int ZEND_DECLARE_CONST_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *opline = EX(opline); + zend_free_op free_op2; + zval *name = &opline->op1.u.constant; + zval *val = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + zend_constant c; + + if ((Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { + zval tmp = *val; + zval *tmp_ptr = &tmp; + + if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { + zval_copy_ctor(&tmp); + } + INIT_PZVAL(&tmp); + zval_update_constant(&tmp_ptr, NULL TSRMLS_CC); + c.value = *tmp_ptr; + } else { + c.value = *val; + zval_copy_ctor(&c.value); + } + c.flags = CONST_CS; /* non persistent, case sensetive */ + if (Z_TYPE_P(name) == IS_UNICODE) { + c.name.u = zend_ustrndup(Z_USTRVAL_P(name), Z_USTRLEN_P(name)); + } else { + c.name.s = zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name)); + } + c.name_len = Z_UNILEN_P(name)+1; + c.module_number = PHP_USER_CONSTANT; + + if (zend_u_register_constant(Z_TYPE_P(name), &c TSRMLS_CC) == FAILURE) { + } + + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -4258,6 +4433,44 @@ static int ZEND_INIT_ARRAY_SPEC_CONST_CV } } +static int ZEND_DECLARE_CONST_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *opline = EX(opline); + + zval *name = &opline->op1.u.constant; + zval *val = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); + zend_constant c; + + if ((Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { + zval tmp = *val; + zval *tmp_ptr = &tmp; + + if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { + zval_copy_ctor(&tmp); + } + INIT_PZVAL(&tmp); + zval_update_constant(&tmp_ptr, NULL TSRMLS_CC); + c.value = *tmp_ptr; + } else { + c.value = *val; + zval_copy_ctor(&c.value); + } + c.flags = CONST_CS; /* non persistent, case sensetive */ + if (Z_TYPE_P(name) == IS_UNICODE) { + c.name.u = zend_ustrndup(Z_USTRVAL_P(name), Z_USTRLEN_P(name)); + } else { + c.name.s = zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name)); + } + c.name_len = Z_UNILEN_P(name)+1; + c.module_number = PHP_USER_CONSTANT; + + if (zend_u_register_constant(Z_TYPE_P(name), &c TSRMLS_CC) == FAILURE) { + } + + + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_BW_NOT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -10016,30 +10229,44 @@ static int ZEND_FETCH_CONSTANT_SPEC_VAR_ zval **value; if (IS_VAR == IS_UNUSED) { -/* This seems to be a reminant of namespaces - if (EG(scope)) { - ce = EG(scope); - if (zend_hash_find(&ce->constants_table, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { - zval_update_constant(value, (void *) 1 TSRMLS_CC); - EX_T(opline->result.u.var).tmp_var = **value; - zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); - ZEND_VM_NEXT_OPCODE(); - } - } -*/ - if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var, NULL TSRMLS_CC)) { + if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", - Z_TYPE(opline->op2.u.constant), - Z_UNIVAL(opline->op2.u.constant), - Z_TYPE(opline->op2.u.constant), - Z_UNIVAL(opline->op2.u.constant)); + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); } ZEND_VM_NEXT_OPCODE(); - } + } else if (IS_VAR == IS_CONST) { + zend_op *op_data = opline + 1; + zend_constant *c; - ce = EX_T(opline->op1.u.var).class_entry; + ZEND_VM_INC_OPCODE(); + + /* try a constant in namespace */ + if (zend_u_hash_quick_find(EG(zend_constants), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) { + EX_T(opline->result.u.var).tmp_var = c->value; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + ZEND_VM_NEXT_OPCODE(); + } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) { + if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { + zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + } + ZEND_VM_NEXT_OPCODE(); + } + + /* no constant found. try a constant in class */ + ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); + if (!ce) { + zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + } + } else { + ce = EX_T(opline->op1.u.var).class_entry; + } if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { zend_class_entry *old_scope = EG(scope); @@ -16724,30 +16951,44 @@ static int ZEND_FETCH_CONSTANT_SPEC_UNUS zval **value; if (IS_UNUSED == IS_UNUSED) { -/* This seems to be a reminant of namespaces - if (EG(scope)) { - ce = EG(scope); - if (zend_hash_find(&ce->constants_table, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { - zval_update_constant(value, (void *) 1 TSRMLS_CC); - EX_T(opline->result.u.var).tmp_var = **value; - zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); - ZEND_VM_NEXT_OPCODE(); - } - } -*/ - if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var, NULL TSRMLS_CC)) { + if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", - Z_TYPE(opline->op2.u.constant), - Z_UNIVAL(opline->op2.u.constant), - Z_TYPE(opline->op2.u.constant), - Z_UNIVAL(opline->op2.u.constant)); + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); } ZEND_VM_NEXT_OPCODE(); - } + } else if (IS_UNUSED == IS_CONST) { + zend_op *op_data = opline + 1; + zend_constant *c; - ce = EX_T(opline->op1.u.var).class_entry; + ZEND_VM_INC_OPCODE(); + + /* try a constant in namespace */ + if (zend_u_hash_quick_find(EG(zend_constants), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) { + EX_T(opline->result.u.var).tmp_var = c->value; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + ZEND_VM_NEXT_OPCODE(); + } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) { + if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { + zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + } + ZEND_VM_NEXT_OPCODE(); + } + + /* no constant found. try a constant in class */ + ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); + if (!ce) { + zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + } + } else { + ce = EX_T(opline->op1.u.var).class_entry; + } if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { zend_class_entry *old_scope = EG(scope); @@ -30882,7 +31123,7 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, + ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -31982,11 +32223,11 @@ void zend_init_opcodes_handlers(void) ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, + ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER, + ZEND_DECLARE_CONST_SPEC_CONST_TMP_HANDLER, + ZEND_DECLARE_CONST_SPEC_CONST_VAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, + ZEND_DECLARE_CONST_SPEC_CONST_CV_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, Index: Zend/zend_vm_opcodes.h =================================================================== RCS file: /repository/ZendEngine2/zend_vm_opcodes.h,v retrieving revision 1.69 diff -u -p -d -r1.69 zend_vm_opcodes.h --- Zend/zend_vm_opcodes.h 8 Mar 2007 17:30:28 -0000 1.69 +++ Zend/zend_vm_opcodes.h 22 Aug 2007 08:27:43 -0000 @@ -142,6 +142,7 @@ #define ZEND_DECLARE_INHERITED_CLASS 140 #define ZEND_DECLARE_FUNCTION 141 #define ZEND_RAISE_ABSTRACT_ERROR 142 +#define ZEND_DECLARE_CONST 143 #define ZEND_ADD_INTERFACE 144 #define ZEND_VERIFY_ABSTRACT_CLASS 146 #define ZEND_ASSIGN_DIM 147 Index: Zend/tests/bug41633_2.phpt =================================================================== RCS file: /repository/ZendEngine2/tests/bug41633_2.phpt,v retrieving revision 1.2 diff -u -p -d -r1.2 bug41633_2.phpt --- Zend/tests/bug41633_2.phpt 13 Jun 2007 14:50:33 -0000 1.2 +++ Zend/tests/bug41633_2.phpt 22 Aug 2007 08:27:43 -0000 @@ -8,4 +8,4 @@ class Foo { echo Foo::A."\n"; ?> --EXPECTF-- -Fatal error: Undefined class constant 'self::B' in %sbug41633_2.php on line 5 +Fatal error: Undefined class constant 'B' in %sbug41633_2.php on line 5 Index: Zend/tests/ns_039.phpt =================================================================== RCS file: Zend/tests/ns_039.phpt diff -N Zend/tests/ns_039.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_039.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,23 @@ +--TEST-- +039: Constant declaration +--FILE-- +<?php +const A = "ok"; +const B = A; +const C = array("ok"); +const D = array(B); +echo A . "\n"; +echo B . "\n"; +print_r(C); +print_r(D); +--EXPECT-- +ok +ok +Array +( + [0] => ok +) +Array +( + [0] => ok +) Index: Zend/tests/ns_040.phpt =================================================================== RCS file: Zend/tests/ns_040.phpt diff -N Zend/tests/ns_040.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_040.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,68 @@ +--TEST-- +040: Constant declaration and usage in namespace +--FILE-- +<?php +namespace X; +import X as Y; +const A = "ok\n"; +const B = A; +const C = array(A); +const D = array("aaa"=>A); +const E = array(A=>"aaa\n"); +function f1($x=A) { + echo $x; +} +function f2($x=X::A) { + echo $x; +} +function f3($x=Y::A) { + echo $x; +} +function f4($x=::X::A) { + echo $x; +} +function f5($x=B) { + echo $x; +} +function f6($x=array(A)) { + echo $x[0]; +} +function f7($x=array("aaa"=>A)) { + echo $x["aaa"]; +} +function f8($x=array(A=>"aaa\n")) { + echo $x["ok\n"]; +} +echo A; +echo X::A; +echo Y::A; +echo ::X::A; +f1(); +f2(); +f3(); +f4(); +echo B; +$x = C; echo $x[0]; +$x = D; echo $x["aaa"]; +$x = E; echo $x["ok\n"]; +f5(); +f6(); +f7(); +f8(); +--EXPECT-- +ok +ok +ok +ok +ok +ok +ok +ok +ok +ok +ok +aaa +ok +ok +ok +aaa Index: Zend/tests/ns_041.phpt =================================================================== RCS file: Zend/tests/ns_041.phpt diff -N Zend/tests/ns_041.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_041.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,22 @@ +--TEST-- +041: Constants in namespace +--FILE-- +<?php +namespace test::ns1; + +const FOO = "ok\n"; + +echo(FOO); +echo(test::ns1::FOO); +echo(::test::ns1::FOO); +echo(BAR); + +const BAR = "ok\n"; + +--EXPECTF-- +ok +ok +ok + +Notice: Use of undefined constant BAR - assumed 'BAR' in %sns_041.php on line 9 +BAR Index: Zend/tests/ns_042.phpt =================================================================== RCS file: Zend/tests/ns_042.phpt diff -N Zend/tests/ns_042.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_042.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,22 @@ +--TEST-- +042: Import in namespace and constants +--FILE-- +<?php +namespace test::ns1; + +const FOO = "ok\n"; + +import test::ns1 as ns2; +import test as ns3; + +echo FOO; +echo test::ns1::FOO; +echo ::test::ns1::FOO; +echo ns2::FOO; +echo ns3::ns1::FOO; +--EXPECT-- +ok +ok +ok +ok +ok Index: Zend/tests/ns_043.phpt =================================================================== RCS file: Zend/tests/ns_043.phpt diff -N Zend/tests/ns_043.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_043.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,11 @@ +--TEST-- +043: Name conflict and constants (ns name) +--FILE-- +<?php +namespace test::ns1; + +const INI_ALL = 0; + +var_dump(INI_ALL); +--EXPECT-- +int(0) Index: Zend/tests/ns_044.phpt =================================================================== RCS file: Zend/tests/ns_044.phpt diff -N Zend/tests/ns_044.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_044.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,9 @@ +--TEST-- +044: Name conflict and constants (php name) +--FILE-- +<?php +namespace test::ns1; + +var_dump(INI_ALL); +--EXPECT-- +int(7) Index: Zend/tests/ns_045.phpt =================================================================== RCS file: Zend/tests/ns_045.phpt diff -N Zend/tests/ns_045.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_045.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,11 @@ +--TEST-- +045: Name conflict and constants (php name in case if ns name exists) +--FILE-- +<?php +namespace test::ns1; + +const INI_ALL = 0; + +var_dump(::INI_ALL); +--EXPECT-- +int(7) Index: Zend/tests/ns_046.phpt =================================================================== RCS file: Zend/tests/ns_046.phpt diff -N Zend/tests/ns_046.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_046.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,11 @@ +--TEST-- +046: Run-time name conflict and constants (ns name) +--FILE-- +<?php +namespace test::ns1; + +const INI_ALL = 0; + +var_dump(constant("test::ns1::INI_ALL")); +--EXPECT-- +int(0) Index: Zend/tests/ns_047.phpt =================================================================== RCS file: Zend/tests/ns_047.phpt diff -N Zend/tests/ns_047.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_047.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,11 @@ +--TEST-- +047: Run-time name conflict and constants (php name) +--FILE-- +<?php +namespace test::ns1; + +const INI_ALL = 0; + +var_dump(constant("INI_ALL")); +--EXPECT-- +int(7) Index: Zend/tests/ns_048.phpt =================================================================== RCS file: Zend/tests/ns_048.phpt diff -N Zend/tests/ns_048.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_048.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,11 @@ +--TEST-- +048: __NAMESPACE__ constant and runtime names (ns name) +--FILE-- +<?php +namespace test::ns1; + +const FOO = 0; + +var_dump(constant(__NAMESPACE__ . "::FOO")); +--EXPECT-- +int(0) Index: Zend/tests/ns_049.phpt =================================================================== RCS file: Zend/tests/ns_049.phpt diff -N Zend/tests/ns_049.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_049.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,9 @@ +--TEST-- +049: __NAMESPACE__ constant and runtime names (php name) +--FILE-- +<?php +const FOO = 0; + +var_dump(constant(__NAMESPACE__ . "::FOO")); +--EXPECT-- +int(0) Index: Zend/tests/ns_050.phpt =================================================================== RCS file: Zend/tests/ns_050.phpt diff -N Zend/tests/ns_050.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_050.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,14 @@ +--TEST-- +050: Name conflict and compile-time constants (ns name) +--FILE-- +<?php +namespace test::ns1; + +const INI_ALL = 0; + +function foo($x = INI_ALL) { + var_dump($x); +} +foo(); +--EXPECT-- +int(0) Index: Zend/tests/ns_051.phpt =================================================================== RCS file: Zend/tests/ns_051.phpt diff -N Zend/tests/ns_051.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_051.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,12 @@ +--TEST-- +051: Name conflict and compile-time constants (php name) +--FILE-- +<?php +namespace test::ns1; + +function foo($x = INI_ALL) { + var_dump($x); +} +foo(); +--EXPECT-- +int(7) Index: Zend/tests/ns_052.phpt =================================================================== RCS file: Zend/tests/ns_052.phpt diff -N Zend/tests/ns_052.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/ns_052.phpt 22 Aug 2007 08:27:43 -0000 @@ -0,0 +1,14 @@ +--TEST-- +052: Name conflict and compile-time constants (php name in case if ns name exists) +--FILE-- +<?php +namespace test::ns1; + +const INI_ALL = 0; + +function foo($x = ::INI_ALL) { + var_dump($x); +} +foo(); +--EXPECT-- +int(7) Index: ext/standard/basic_functions.c =================================================================== RCS file: /repository/php-src/ext/standard/basic_functions.c,v retrieving revision 1.868 diff -u -p -d -r1.868 basic_functions.c --- ext/standard/basic_functions.c 19 Jul 2007 15:56:33 -0000 1.868 +++ ext/standard/basic_functions.c 22 Aug 2007 08:27:43 -0000 @@ -4188,7 +4188,7 @@ PHP_FUNCTION(constant) return; } - if (!zend_u_get_constant(const_type, const_name, const_name_len, return_value, NULL TSRMLS_CC)) { + if (!zend_u_get_constant_ex(const_type, const_name, const_name_len, return_value, NULL, 0 TSRMLS_CC)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't find constant %R", const_type, const_name); RETURN_NULL(); }