|
|
|
@ -592,6 +592,124 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas |
|
|
|
} |
|
|
|
|
|
|
|
if (Z_REFCOUNTED_P(p)) Z_SET_REFCOUNT_P(p, refcount); |
|
|
|
} else if (Z_TYPE_P(p) == IS_CONSTANT_ARRAY) { |
|
|
|
zval *element, new_val; |
|
|
|
zend_string *str_index; |
|
|
|
ulong num_index; |
|
|
|
int ret; |
|
|
|
|
|
|
|
SEPARATE_ZVAL_IF_NOT_REF(p); |
|
|
|
|
|
|
|
Z_TYPE_INFO_P(p) = IS_ARRAY_EX; |
|
|
|
if (!inline_change) { |
|
|
|
HashTable *ht = Z_ARRVAL_P(p); |
|
|
|
ZVAL_NEW_ARR(p); |
|
|
|
zend_hash_init(Z_ARRVAL_P(p), zend_hash_num_elements(ht), NULL, ZVAL_PTR_DTOR, 0); |
|
|
|
zend_hash_copy(Z_ARRVAL_P(p), ht, ZVAL_COPY_CTOR); |
|
|
|
} |
|
|
|
|
|
|
|
/* First go over the array and see if there are any constant indices */ |
|
|
|
zend_hash_internal_pointer_reset(Z_ARRVAL_P(p)); |
|
|
|
while ((element = zend_hash_get_current_data(Z_ARRVAL_P(p))) != NULL) { |
|
|
|
if (zend_hash_get_current_key(Z_ARRVAL_P(p), &str_index, &num_index, 0) != HASH_KEY_IS_STRING) { |
|
|
|
zend_hash_move_forward(Z_ARRVAL_P(p)); |
|
|
|
continue; |
|
|
|
} |
|
|
|
if (!(GC_FLAGS(str_index) & (IS_STR_CONSTANT | IS_STR_AST))) { |
|
|
|
zend_hash_move_forward(Z_ARRVAL_P(p)); |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
if (GC_FLAGS(str_index) & IS_STR_AST) { |
|
|
|
zend_ast_ref *ast = *(zend_ast_ref **)str_index->val; |
|
|
|
|
|
|
|
zend_ast_evaluate(&tmp, ast->ast, scope TSRMLS_CC); |
|
|
|
zend_ast_destroy(ast->ast); |
|
|
|
efree(ast); |
|
|
|
const_value = &tmp; |
|
|
|
} else if (!(const_value = zend_get_constant_ex(str_index, scope, GC_FLAGS(str_index) & ~(IS_STR_PERSISTENT | IS_STR_INTERNED |IS_STR_PERMANENT) TSRMLS_CC))) { |
|
|
|
char *actual, *str; |
|
|
|
const char *save = str_index->val; |
|
|
|
int len; |
|
|
|
|
|
|
|
str = str_index->val; |
|
|
|
len = str_index->len; |
|
|
|
if ((colon = (char*)zend_memrchr(str, ':', len))) { |
|
|
|
zend_error(E_ERROR, "Undefined class constant '%s'", str); |
|
|
|
len -= ((colon - str) + 1); |
|
|
|
str = colon; |
|
|
|
} else { |
|
|
|
if (GC_FLAGS(str_index) & IS_STR_CONSTANT_UNQUALIFIED) { |
|
|
|
if ((actual = (char *)zend_memrchr(str, '\\', len))) { |
|
|
|
actual++; |
|
|
|
len -= (actual - str); |
|
|
|
str = actual; |
|
|
|
} |
|
|
|
} |
|
|
|
if (str[0] == '\\') { |
|
|
|
++str; |
|
|
|
--len; |
|
|
|
} |
|
|
|
if (save[0] == '\\') { |
|
|
|
++save; |
|
|
|
} |
|
|
|
if (!(GC_FLAGS(str_index) & IS_STR_CONSTANT_UNQUALIFIED)) { |
|
|
|
zend_error(E_ERROR, "Undefined constant '%s'", save); |
|
|
|
} |
|
|
|
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", str, str); |
|
|
|
} |
|
|
|
if (str == str_index->val && len == str_index->len) { |
|
|
|
ZVAL_STR(&tmp, STR_COPY(str_index)); |
|
|
|
} else { |
|
|
|
ZVAL_STRINGL(&tmp, str, len); |
|
|
|
} |
|
|
|
const_value = &tmp; |
|
|
|
} else { |
|
|
|
//???! |
|
|
|
ZVAL_COPY_VALUE(&tmp, const_value); |
|
|
|
if (Z_OPT_CONSTANT(tmp)) { |
|
|
|
zval_update_constant_ex(&tmp, 1, NULL TSRMLS_CC); |
|
|
|
} |
|
|
|
zval_opt_copy_ctor(&tmp); |
|
|
|
const_value = &tmp; |
|
|
|
} |
|
|
|
|
|
|
|
if (Z_REFCOUNTED_P(element) && Z_REFCOUNT_P(element) > 1) { |
|
|
|
ZVAL_DUP(&new_val, element); |
|
|
|
zval_ptr_dtor(element); |
|
|
|
ZVAL_COPY_VALUE(element, &new_val); |
|
|
|
} |
|
|
|
|
|
|
|
switch (Z_TYPE_P(const_value)) { |
|
|
|
case IS_STRING: |
|
|
|
ret = zend_symtable_update_current_key_ex(Z_ARRVAL_P(p), Z_STR_P(const_value), HASH_UPDATE_KEY_IF_BEFORE); |
|
|
|
break; |
|
|
|
case IS_FALSE: |
|
|
|
ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, HASH_UPDATE_KEY_IF_BEFORE); |
|
|
|
break; |
|
|
|
case IS_TRUE: |
|
|
|
ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 1, HASH_UPDATE_KEY_IF_BEFORE); |
|
|
|
break; |
|
|
|
case IS_LONG: |
|
|
|
ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, Z_LVAL_P(const_value), HASH_UPDATE_KEY_IF_BEFORE); |
|
|
|
break; |
|
|
|
case IS_DOUBLE: |
|
|
|
ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, zend_dval_to_lval(Z_DVAL_P(const_value)), HASH_UPDATE_KEY_IF_BEFORE); |
|
|
|
break; |
|
|
|
case IS_NULL: |
|
|
|
ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, STR_EMPTY_ALLOC(), 0, HASH_UPDATE_KEY_IF_BEFORE); |
|
|
|
break; |
|
|
|
default: |
|
|
|
ret = SUCCESS; |
|
|
|
break; |
|
|
|
} |
|
|
|
if (ret == SUCCESS) { |
|
|
|
zend_hash_move_forward(Z_ARRVAL_P(p)); |
|
|
|
} |
|
|
|
zval_dtor(const_value); |
|
|
|
} |
|
|
|
zend_hash_apply_with_argument(Z_ARRVAL_P(p), (apply_func_arg_t) zval_update_constant_inline_change, (void *) scope TSRMLS_CC); |
|
|
|
zend_hash_internal_pointer_reset(Z_ARRVAL_P(p)); |
|
|
|
} else if (Z_TYPE_P(p) == IS_CONSTANT_AST) { |
|
|
|
SEPARATE_ZVAL_IF_NOT_REF(p); |
|
|
|
|
|
|
|
|