mirror of
https://github.com/php/php-src.git
synced 2026-04-27 18:23:26 +02:00
Working commit for constant scalar expressions (with constants).
Tests will follow.
This commit is contained in:
+2
-1
@@ -18,7 +18,8 @@ libZend_la_SOURCES=\
|
||||
zend_default_classes.c \
|
||||
zend_iterators.c zend_interfaces.c zend_exceptions.c \
|
||||
zend_strtod.c zend_closures.c zend_float.c zend_string.c zend_signal.c \
|
||||
zend_generators.c
|
||||
zend_generators.c \
|
||||
zend_ast.c
|
||||
|
||||
libZend_la_LDFLAGS =
|
||||
libZend_la_LIBADD = @ZEND_EXTRA_LIBS@
|
||||
|
||||
@@ -119,6 +119,10 @@ SOURCE=.\zend_API.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zend_ast.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zend_builtin_functions.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
@@ -140,6 +140,10 @@ SOURCE=.\zend_alloc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zend_ast.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zend_API.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
+13
-10
@@ -317,6 +317,7 @@ typedef struct _zend_object {
|
||||
} zend_object;
|
||||
|
||||
#include "zend_object_handlers.h"
|
||||
#include "zend_ast.h"
|
||||
|
||||
typedef union _zvalue_value {
|
||||
long lval; /* long value */
|
||||
@@ -327,6 +328,7 @@ typedef union _zvalue_value {
|
||||
} str;
|
||||
HashTable *ht; /* hash table value */
|
||||
zend_object_value obj;
|
||||
zend_ast *ast;
|
||||
} zvalue_value;
|
||||
|
||||
struct _zval_struct {
|
||||
@@ -577,17 +579,18 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length);
|
||||
|
||||
/* data types */
|
||||
/* All data types <= IS_BOOL have their constructor/destructors skipped */
|
||||
#define IS_NULL 0
|
||||
#define IS_LONG 1
|
||||
#define IS_DOUBLE 2
|
||||
#define IS_BOOL 3
|
||||
#define IS_ARRAY 4
|
||||
#define IS_OBJECT 5
|
||||
#define IS_STRING 6
|
||||
#define IS_RESOURCE 7
|
||||
#define IS_CONSTANT 8
|
||||
#define IS_NULL 0
|
||||
#define IS_LONG 1
|
||||
#define IS_DOUBLE 2
|
||||
#define IS_BOOL 3
|
||||
#define IS_ARRAY 4
|
||||
#define IS_OBJECT 5
|
||||
#define IS_STRING 6
|
||||
#define IS_RESOURCE 7
|
||||
#define IS_CONSTANT 8
|
||||
#define IS_CONSTANT_ARRAY 9
|
||||
#define IS_CALLABLE 10
|
||||
#define IS_CONSTANT_AST 10
|
||||
#define IS_CALLABLE 11
|
||||
|
||||
/* Ugly hack to support constants as static array indices */
|
||||
#define IS_CONSTANT_TYPE_MASK 0x00f
|
||||
|
||||
+28
-25
@@ -1053,34 +1053,37 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destro
|
||||
|
||||
static int zval_update_class_constant(zval **pp, int is_static, int offset TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
if ((Z_TYPE_PP(pp) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT ||
|
||||
(Z_TYPE_PP(pp) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT_ARRAY) {
|
||||
zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry);
|
||||
switch (Z_TYPE_PP(pp) & IS_CONSTANT_TYPE_MASK) {
|
||||
case IS_CONSTANT:
|
||||
case IS_CONSTANT_ARRAY:
|
||||
case IS_CONSTANT_AST: {
|
||||
zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry);
|
||||
|
||||
if ((*scope)->parent) {
|
||||
zend_class_entry *ce = *scope;
|
||||
HashPosition pos;
|
||||
zend_property_info *prop_info;
|
||||
if ((*scope)->parent) {
|
||||
zend_class_entry *ce = *scope;
|
||||
HashPosition pos;
|
||||
zend_property_info *prop_info;
|
||||
|
||||
do {
|
||||
for (zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
|
||||
zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop_info, &pos) == SUCCESS;
|
||||
zend_hash_move_forward_ex(&ce->properties_info, &pos)) {
|
||||
if (is_static == ((prop_info->flags & ZEND_ACC_STATIC) != 0) &&
|
||||
offset == prop_info->offset) {
|
||||
int ret;
|
||||
zend_class_entry *old_scope = *scope;
|
||||
*scope = prop_info->ce;
|
||||
ret = zval_update_constant(pp, (void*)1 TSRMLS_CC);
|
||||
*scope = old_scope;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
ce = ce->parent;
|
||||
} while (ce);
|
||||
|
||||
do {
|
||||
for (zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
|
||||
zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop_info, &pos) == SUCCESS;
|
||||
zend_hash_move_forward_ex(&ce->properties_info, &pos)) {
|
||||
if (is_static == ((prop_info->flags & ZEND_ACC_STATIC) != 0) &&
|
||||
offset == prop_info->offset) {
|
||||
int ret;
|
||||
zend_class_entry *old_scope = *scope;
|
||||
*scope = prop_info->ce;
|
||||
ret = zval_update_constant(pp, (void*)1 TSRMLS_CC);
|
||||
*scope = old_scope;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
ce = ce->parent;
|
||||
} while (ce);
|
||||
|
||||
}
|
||||
return zval_update_constant(pp, (void*)1 TSRMLS_CC);
|
||||
}
|
||||
return zval_update_constant(pp, (void*)1 TSRMLS_CC);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Zend Engine |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 2.00 of the Zend license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.zend.com/license/2_00.txt. |
|
||||
| If you did not receive a copy of the Zend license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@zend.com so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Bob Weinand <bwoebi@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "zend_ast.h"
|
||||
#include "zend_execute.h"
|
||||
|
||||
#define OP_IS_CONST_THEN(op, do_code) \
|
||||
switch (Z_TYPE_P(op) & IS_CONSTANT_TYPE_MASK) { \
|
||||
case IS_CONSTANT: \
|
||||
case IS_CONSTANT_ARRAY: \
|
||||
case IS_CONSTANT_AST: { \
|
||||
do_code \
|
||||
} \
|
||||
}
|
||||
|
||||
#define OP_IS_NOT_CONST_THEN(op, do_code) \
|
||||
switch (Z_TYPE_P(op) & IS_CONSTANT_TYPE_MASK) { \
|
||||
case IS_CONSTANT: \
|
||||
case IS_CONSTANT_ARRAY: \
|
||||
case IS_CONSTANT_AST: \
|
||||
break; \
|
||||
\
|
||||
default: { \
|
||||
do_code \
|
||||
} \
|
||||
}
|
||||
|
||||
#define COPY_ZVAL_TO_OP(nr) \
|
||||
Z_AST_P(result)->ops[nr] = emalloc(sizeof(zval)); \
|
||||
*Z_AST_P(result)->ops[nr] = *op##nr;
|
||||
|
||||
void zend_ast_add(zval *result, intermediary_ast_function_type func, char op_count) {
|
||||
zend_ast *ast = emalloc(sizeof(zend_ast));
|
||||
ast->op_count = op_count;
|
||||
ast->ops = emalloc(op_count * sizeof(zval *));
|
||||
ast->refcount = 1;
|
||||
ast->func = func;
|
||||
Z_AST_P(result) = ast;
|
||||
Z_TYPE_P(result) = IS_CONSTANT_AST;
|
||||
}
|
||||
|
||||
/* Do operations on constant operators at compile time (AST building time) */
|
||||
|
||||
void zend_ast_add_unary(zval *result, unary_ast_func func, zval *op0) {
|
||||
OP_IS_NOT_CONST_THEN(op0,
|
||||
func(result, op0);
|
||||
return;
|
||||
)
|
||||
|
||||
zend_ast_add(result, (intermediary_ast_function_type)func, 1);
|
||||
COPY_ZVAL_TO_OP(0)
|
||||
}
|
||||
|
||||
void zend_ast_add_binary(zval *result, binary_ast_func func, zval *op0, zval *op1) {
|
||||
OP_IS_NOT_CONST_THEN(op0, OP_IS_NOT_CONST_THEN(op1,
|
||||
func(result, op0, op1);
|
||||
return;
|
||||
))
|
||||
|
||||
zend_ast_add(result, (intermediary_ast_function_type)func, 2);
|
||||
COPY_ZVAL_TO_OP(0)
|
||||
COPY_ZVAL_TO_OP(1)
|
||||
}
|
||||
|
||||
void zend_ast_add_ternary(zval *result, ternary_ast_func func, zval *op0, zval *op1, zval *op2) {
|
||||
OP_IS_NOT_CONST_THEN(op0, OP_IS_NOT_CONST_THEN(op1, OP_IS_NOT_CONST_THEN(op2,
|
||||
func(result, op0, op1, op2);
|
||||
return;
|
||||
)))
|
||||
|
||||
zend_ast_add(result, (intermediary_ast_function_type)func, 3);
|
||||
COPY_ZVAL_TO_OP(0)
|
||||
COPY_ZVAL_TO_OP(1)
|
||||
COPY_ZVAL_TO_OP(2)
|
||||
}
|
||||
|
||||
void zend_ast_evaluate(zval *result, zend_ast *ast TSRMLS_DC) {
|
||||
int i;
|
||||
|
||||
for (i = ast->op_count; i--;) {
|
||||
OP_IS_CONST_THEN(ast->ops[i],
|
||||
zval_update_constant_ex(&ast->ops[i], (void *)1, NULL TSRMLS_CC);
|
||||
)
|
||||
}
|
||||
|
||||
switch (ast->op_count) {
|
||||
case 1:
|
||||
((unary_ast_func)ast->func)(result, ast->ops[0]);
|
||||
break;
|
||||
case 2:
|
||||
((binary_ast_func)ast->func)(result, ast->ops[0], ast->ops[1]);
|
||||
break;
|
||||
case 3:
|
||||
((ternary_ast_func)ast->func)(result, ast->ops[0], ast->ops[1], ast->ops[2]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void zend_ast_destroy(zend_ast *ast TSRMLS_DC) {
|
||||
int i;
|
||||
|
||||
for (i = ast->op_count; i--;) {
|
||||
if (!Z_DELREF_P(ast->ops[i])) {
|
||||
zval_dtor(ast->ops[i]);
|
||||
efree(ast->ops[i]);
|
||||
}
|
||||
}
|
||||
|
||||
efree(ast->ops);
|
||||
efree(ast);
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Zend Engine |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 2.00 of the Zend license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.zend.com/license/2_00.txt. |
|
||||
| If you did not receive a copy of the Zend license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@zend.com so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Bob Weinand <bwoebi@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef ZEND_AST_H
|
||||
#define ZEND_AST_H
|
||||
|
||||
typedef struct _zend_ast zend_ast;
|
||||
|
||||
#include "zend.h"
|
||||
|
||||
typedef void(*intermediary_ast_function_type)(zval *, ...);
|
||||
typedef int(*unary_ast_func)(zval *result, zval *op0);
|
||||
typedef int(*binary_ast_func)(zval *result, zval *op0, zval *op1);
|
||||
typedef int(*ternary_ast_func)(zval *result, zval *op0, zval *op1, zval *op2);
|
||||
|
||||
struct _zend_ast {
|
||||
char op_count;
|
||||
zval **ops;
|
||||
intermediary_ast_function_type func;
|
||||
int refcount;
|
||||
};
|
||||
|
||||
void zend_ast_add_unary(zval *result, unary_ast_func func, zval *op0);
|
||||
void zend_ast_add_binary(zval *result, binary_ast_func func, zval *op0, zval *op1);
|
||||
void zend_ast_add_ternary(zval *result, ternary_ast_func func, zval *op0, zval *op1, zval *op2);
|
||||
|
||||
void zend_ast_evaluate(zval *result, zend_ast *ast TSRMLS_DC);
|
||||
|
||||
void zend_ast_destroy(zend_ast *ast TSRMLS_DC);
|
||||
|
||||
#define ZEND_AST_ADD_REF(ast) ++ast->refcount
|
||||
|
||||
static inline int ZEND_AST_DEL_REF(zend_ast *ast) {
|
||||
if (ast->refcount == 1) {
|
||||
TSRMLS_FETCH();
|
||||
|
||||
zend_ast_destroy(ast TSRMLS_CC);
|
||||
return 0;
|
||||
}
|
||||
return --ast->refcount;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -946,8 +946,11 @@ static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value
|
||||
|
||||
/* 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_TYPE_MASK) == IS_CONSTANT) {
|
||||
zval_update_constant(&prop_copy, 0 TSRMLS_CC);
|
||||
switch (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) {
|
||||
case IS_CONSTANT:
|
||||
case IS_CONSTANT_ARRAY:
|
||||
case IS_CONSTANT_AST:
|
||||
zval_update_constant(&prop_copy, 0 TSRMLS_CC);
|
||||
}
|
||||
|
||||
add_assoc_zval(return_value, key, prop_copy);
|
||||
|
||||
+20
-5
@@ -1891,7 +1891,7 @@ void zend_do_receive_param(zend_uchar op, znode *varname, const znode *initializ
|
||||
if (class_type->u.constant.type == IS_ARRAY) {
|
||||
cur_arg_info->type_hint = IS_ARRAY;
|
||||
if (op == ZEND_RECV_INIT) {
|
||||
if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
|
||||
if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL")) || Z_TYPE(initialization->u.constant) == IS_CONSTANT_AST) {
|
||||
cur_arg_info->allow_null = 1;
|
||||
} else if (Z_TYPE(initialization->u.constant) != IS_ARRAY && Z_TYPE(initialization->u.constant) != IS_CONSTANT_ARRAY) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with array type hint can only be an array or NULL");
|
||||
@@ -1900,7 +1900,7 @@ void zend_do_receive_param(zend_uchar op, znode *varname, const znode *initializ
|
||||
} else if (class_type->u.constant.type == IS_CALLABLE) {
|
||||
cur_arg_info->type_hint = IS_CALLABLE;
|
||||
if (op == ZEND_RECV_INIT) {
|
||||
if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
|
||||
if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL")) || Z_TYPE(initialization->u.constant) == IS_CONSTANT_AST) {
|
||||
cur_arg_info->allow_null = 1;
|
||||
} else {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with callable type hint can only be NULL");
|
||||
@@ -1915,7 +1915,7 @@ void zend_do_receive_param(zend_uchar op, znode *varname, const znode *initializ
|
||||
cur_arg_info->class_name = Z_STRVAL(class_type->u.constant);
|
||||
cur_arg_info->class_name_len = Z_STRLEN(class_type->u.constant);
|
||||
if (op == ZEND_RECV_INIT) {
|
||||
if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
|
||||
if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL")) || Z_TYPE(initialization->u.constant) == IS_CONSTANT_AST) {
|
||||
cur_arg_info->allow_null = 1;
|
||||
} else {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with a class type hint can only be NULL");
|
||||
@@ -5530,7 +5530,8 @@ static zend_constant* zend_get_ct_const(const zval *const_name, int all_internal
|
||||
(c->flags & CONST_PERSISTENT) &&
|
||||
!(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION) &&
|
||||
Z_TYPE(c->value) != IS_CONSTANT &&
|
||||
Z_TYPE(c->value) != IS_CONSTANT_ARRAY) {
|
||||
Z_TYPE(c->value) != IS_CONSTANT_ARRAY &&
|
||||
Z_TYPE(c->value) != IS_CONSTANT_AST) {
|
||||
return c;
|
||||
}
|
||||
return NULL;
|
||||
@@ -5772,7 +5773,7 @@ void zend_do_add_static_array_element(znode *result, znode *offset, const znode
|
||||
ALLOC_ZVAL(element);
|
||||
*element = expr->u.constant;
|
||||
if (offset) {
|
||||
switch (offset->u.constant.type & IS_CONSTANT_TYPE_MASK) {
|
||||
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;
|
||||
@@ -5782,6 +5783,20 @@ void zend_do_add_static_array_element(znode *result, znode *offset, const znode
|
||||
zend_symtable_update(Z_ARRVAL(result->u.constant), Z_STRVAL(offset->u.constant), Z_STRLEN(offset->u.constant)+3, &element, sizeof(zval *), NULL);
|
||||
zval_dtor(&offset->u.constant);
|
||||
break;
|
||||
case IS_CONSTANT_AST: {
|
||||
/* Another ugly hack to store the data about the AST in the array */
|
||||
char* key;
|
||||
int len = sizeof(zend_ast *);
|
||||
Z_TYPE_P(element) |= IS_CONSTANT_INDEX;
|
||||
|
||||
key = emalloc(len + 2);
|
||||
*(zend_ast **)key = Z_AST(offset->u.constant);
|
||||
key[len] = Z_TYPE(offset->u.constant);
|
||||
key[len + 1] = 0;
|
||||
zend_symtable_update(Z_ARRVAL(result->u.constant), key, len + 2, &element, sizeof(zval *), NULL);
|
||||
efree(key);
|
||||
}
|
||||
break;
|
||||
case IS_STRING:
|
||||
zend_symtable_update(Z_ARRVAL(result->u.constant), Z_STRVAL(offset->u.constant), Z_STRLEN(offset->u.constant)+1, &element, sizeof(zval *), NULL);
|
||||
zval_dtor(&offset->u.constant);
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#define ZEND_COMPILE_H
|
||||
|
||||
#include "zend.h"
|
||||
#include "zend_ast.h"
|
||||
|
||||
#ifdef HAVE_STDARG_H
|
||||
# include <stdarg.h>
|
||||
|
||||
+184
-164
@@ -478,188 +478,208 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
|
||||
|
||||
if (IS_CONSTANT_VISITED(p)) {
|
||||
zend_error(E_ERROR, "Cannot declare self-referencing constant '%s'", Z_STRVAL_P(p));
|
||||
} else if ((Z_TYPE_P(p) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
|
||||
int refcount;
|
||||
zend_uchar is_ref;
|
||||
return FAILURE;
|
||||
}
|
||||
switch (Z_TYPE_P(p) & IS_CONSTANT_TYPE_MASK) {
|
||||
case IS_CONSTANT: {
|
||||
int refcount;
|
||||
zend_uchar is_ref;
|
||||
|
||||
SEPARATE_ZVAL_IF_NOT_REF(pp);
|
||||
p = *pp;
|
||||
SEPARATE_ZVAL_IF_NOT_REF(pp);
|
||||
p = *pp;
|
||||
|
||||
MARK_CONSTANT_VISITED(p);
|
||||
MARK_CONSTANT_VISITED(p);
|
||||
|
||||
refcount = Z_REFCOUNT_P(p);
|
||||
is_ref = Z_ISREF_P(p);
|
||||
refcount = Z_REFCOUNT_P(p);
|
||||
is_ref = Z_ISREF_P(p);
|
||||
|
||||
if (!zend_get_constant_ex(p->value.str.val, p->value.str.len, &const_value, scope, Z_REAL_TYPE_P(p) TSRMLS_CC)) {
|
||||
char *actual = Z_STRVAL_P(p);
|
||||
if (!zend_get_constant_ex(p->value.str.val, p->value.str.len, &const_value, scope, Z_REAL_TYPE_P(p) TSRMLS_CC)) {
|
||||
char *actual = Z_STRVAL_P(p);
|
||||
|
||||
if ((colon = (char*)zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) {
|
||||
zend_error(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p));
|
||||
Z_STRLEN_P(p) -= ((colon - Z_STRVAL_P(p)) + 1);
|
||||
if (inline_change) {
|
||||
colon = estrndup(colon, Z_STRLEN_P(p));
|
||||
str_efree(Z_STRVAL_P(p));
|
||||
Z_STRVAL_P(p) = colon;
|
||||
} else {
|
||||
Z_STRVAL_P(p) = colon + 1;
|
||||
}
|
||||
} else {
|
||||
char *save = actual, *slash;
|
||||
int actual_len = Z_STRLEN_P(p);
|
||||
if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) && (slash = (char *)zend_memrchr(actual, '\\', actual_len))) {
|
||||
actual = slash + 1;
|
||||
actual_len -= (actual - Z_STRVAL_P(p));
|
||||
if ((colon = (char*)zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) {
|
||||
zend_error(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p));
|
||||
Z_STRLEN_P(p) -= ((colon - Z_STRVAL_P(p)) + 1);
|
||||
if (inline_change) {
|
||||
actual = estrndup(actual, actual_len);
|
||||
Z_STRVAL_P(p) = actual;
|
||||
Z_STRLEN_P(p) = actual_len;
|
||||
}
|
||||
}
|
||||
if (actual[0] == '\\') {
|
||||
if (inline_change) {
|
||||
memmove(Z_STRVAL_P(p), Z_STRVAL_P(p)+1, Z_STRLEN_P(p));
|
||||
--Z_STRLEN_P(p);
|
||||
colon = estrndup(colon, Z_STRLEN_P(p));
|
||||
str_efree(Z_STRVAL_P(p));
|
||||
Z_STRVAL_P(p) = colon;
|
||||
} else {
|
||||
++actual;
|
||||
Z_STRVAL_P(p) = colon + 1;
|
||||
}
|
||||
--actual_len;
|
||||
}
|
||||
if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) == 0) {
|
||||
int fix_save = 0;
|
||||
if (save[0] == '\\') {
|
||||
save++;
|
||||
fix_save = 1;
|
||||
}
|
||||
zend_error(E_ERROR, "Undefined constant '%s'", save);
|
||||
if (fix_save) {
|
||||
save--;
|
||||
}
|
||||
if (inline_change) {
|
||||
str_efree(save);
|
||||
}
|
||||
save = NULL;
|
||||
}
|
||||
if (inline_change && save && save != actual) {
|
||||
str_efree(save);
|
||||
}
|
||||
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual);
|
||||
p->type = IS_STRING;
|
||||
if (!inline_change) {
|
||||
Z_STRVAL_P(p) = actual;
|
||||
Z_STRLEN_P(p) = actual_len;
|
||||
zval_copy_ctor(p);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (inline_change) {
|
||||
str_efree(Z_STRVAL_P(p));
|
||||
}
|
||||
*p = const_value;
|
||||
}
|
||||
|
||||
Z_SET_REFCOUNT_P(p, refcount);
|
||||
Z_SET_ISREF_TO_P(p, is_ref);
|
||||
} else if (Z_TYPE_P(p) == IS_CONSTANT_ARRAY) {
|
||||
zval **element, *new_val;
|
||||
char *str_index;
|
||||
uint str_index_len;
|
||||
ulong num_index;
|
||||
int ret;
|
||||
|
||||
SEPARATE_ZVAL_IF_NOT_REF(pp);
|
||||
p = *pp;
|
||||
Z_TYPE_P(p) = IS_ARRAY;
|
||||
|
||||
if (!inline_change) {
|
||||
zval *tmp;
|
||||
HashTable *tmp_ht = NULL;
|
||||
|
||||
ALLOC_HASHTABLE(tmp_ht);
|
||||
zend_hash_init(tmp_ht, zend_hash_num_elements(Z_ARRVAL_P(p)), NULL, ZVAL_PTR_DTOR, 0);
|
||||
zend_hash_copy(tmp_ht, Z_ARRVAL_P(p), (copy_ctor_func_t) zval_deep_copy, (void *) &tmp, sizeof(zval *));
|
||||
Z_ARRVAL_P(p) = tmp_ht;
|
||||
}
|
||||
|
||||
/* First go over the array and see if there are any constant indices */
|
||||
zend_hash_internal_pointer_reset(Z_ARRVAL_P(p));
|
||||
while (zend_hash_get_current_data(Z_ARRVAL_P(p), (void **) &element) == SUCCESS) {
|
||||
if (!(Z_TYPE_PP(element) & IS_CONSTANT_INDEX)) {
|
||||
zend_hash_move_forward(Z_ARRVAL_P(p));
|
||||
continue;
|
||||
}
|
||||
Z_TYPE_PP(element) &= ~IS_CONSTANT_INDEX;
|
||||
if (zend_hash_get_current_key_ex(Z_ARRVAL_P(p), &str_index, &str_index_len, &num_index, 0, NULL) != HASH_KEY_IS_STRING) {
|
||||
zend_hash_move_forward(Z_ARRVAL_P(p));
|
||||
continue;
|
||||
}
|
||||
if (!zend_get_constant_ex(str_index, str_index_len - 3, &const_value, scope, str_index[str_index_len - 2] TSRMLS_CC)) {
|
||||
char *actual;
|
||||
const char *save = str_index;
|
||||
if ((colon = (char*)zend_memrchr(str_index, ':', str_index_len - 3))) {
|
||||
zend_error(E_ERROR, "Undefined class constant '%s'", str_index);
|
||||
str_index_len -= ((colon - str_index) + 1);
|
||||
str_index = colon;
|
||||
} else {
|
||||
if (str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) {
|
||||
if ((actual = (char *)zend_memrchr(str_index, '\\', str_index_len - 3))) {
|
||||
actual++;
|
||||
str_index_len -= (actual - str_index);
|
||||
str_index = actual;
|
||||
char *save = actual, *slash;
|
||||
int actual_len = Z_STRLEN_P(p);
|
||||
if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) && (slash = (char *)zend_memrchr(actual, '\\', actual_len))) {
|
||||
actual = slash + 1;
|
||||
actual_len -= (actual - Z_STRVAL_P(p));
|
||||
if (inline_change) {
|
||||
actual = estrndup(actual, actual_len);
|
||||
Z_STRVAL_P(p) = actual;
|
||||
Z_STRLEN_P(p) = actual_len;
|
||||
}
|
||||
}
|
||||
if (str_index[0] == '\\') {
|
||||
++str_index;
|
||||
--str_index_len;
|
||||
if (actual[0] == '\\') {
|
||||
if (inline_change) {
|
||||
memmove(Z_STRVAL_P(p), Z_STRVAL_P(p)+1, Z_STRLEN_P(p));
|
||||
--Z_STRLEN_P(p);
|
||||
} else {
|
||||
++actual;
|
||||
}
|
||||
--actual_len;
|
||||
}
|
||||
if (save[0] == '\\') {
|
||||
++save;
|
||||
}
|
||||
if ((str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) == 0) {
|
||||
if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) == 0) {
|
||||
int fix_save = 0;
|
||||
if (save[0] == '\\') {
|
||||
save++;
|
||||
fix_save = 1;
|
||||
}
|
||||
zend_error(E_ERROR, "Undefined constant '%s'", save);
|
||||
if (fix_save) {
|
||||
save--;
|
||||
}
|
||||
if (inline_change) {
|
||||
str_efree(save);
|
||||
}
|
||||
save = NULL;
|
||||
}
|
||||
if (inline_change && save && save != actual) {
|
||||
str_efree(save);
|
||||
}
|
||||
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual);
|
||||
p->type = IS_STRING;
|
||||
if (!inline_change) {
|
||||
Z_STRVAL_P(p) = actual;
|
||||
Z_STRLEN_P(p) = actual_len;
|
||||
zval_copy_ctor(p);
|
||||
}
|
||||
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", str_index, str_index);
|
||||
}
|
||||
ZVAL_STRINGL(&const_value, str_index, str_index_len-3, 1);
|
||||
} else {
|
||||
if (inline_change) {
|
||||
str_efree(Z_STRVAL_P(p));
|
||||
}
|
||||
*p = const_value;
|
||||
}
|
||||
|
||||
if (Z_REFCOUNT_PP(element) > 1) {
|
||||
ALLOC_ZVAL(new_val);
|
||||
*new_val = **element;
|
||||
zval_copy_ctor(new_val);
|
||||
Z_SET_REFCOUNT_P(new_val, 1);
|
||||
Z_UNSET_ISREF_P(new_val);
|
||||
|
||||
/* preserve this bit for inheritance */
|
||||
Z_TYPE_PP(element) |= IS_CONSTANT_INDEX;
|
||||
zval_ptr_dtor(element);
|
||||
*element = new_val;
|
||||
}
|
||||
|
||||
switch (Z_TYPE(const_value)) {
|
||||
case IS_STRING:
|
||||
ret = zend_symtable_update_current_key(Z_ARRVAL_P(p), Z_STRVAL(const_value), Z_STRLEN(const_value) + 1, HASH_UPDATE_KEY_IF_BEFORE);
|
||||
break;
|
||||
case IS_BOOL:
|
||||
case IS_LONG:
|
||||
ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, Z_LVAL(const_value), HASH_UPDATE_KEY_IF_BEFORE, NULL);
|
||||
break;
|
||||
case IS_DOUBLE:
|
||||
ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, zend_dval_to_lval(Z_DVAL(const_value)), HASH_UPDATE_KEY_IF_BEFORE, NULL);
|
||||
break;
|
||||
case IS_NULL:
|
||||
ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, "", 1, 0, HASH_UPDATE_KEY_IF_BEFORE, NULL);
|
||||
break;
|
||||
default:
|
||||
ret = SUCCESS;
|
||||
break;
|
||||
}
|
||||
if (ret == SUCCESS) {
|
||||
zend_hash_move_forward(Z_ARRVAL_P(p));
|
||||
}
|
||||
zval_dtor(&const_value);
|
||||
Z_SET_REFCOUNT_P(p, refcount);
|
||||
Z_SET_ISREF_TO_P(p, is_ref);
|
||||
}
|
||||
break;
|
||||
|
||||
case IS_CONSTANT_ARRAY: {
|
||||
zval **element, *new_val;
|
||||
char *str_index;
|
||||
uint str_index_len;
|
||||
ulong num_index;
|
||||
int ret;
|
||||
|
||||
SEPARATE_ZVAL_IF_NOT_REF(pp);
|
||||
p = *pp;
|
||||
Z_TYPE_P(p) = IS_ARRAY;
|
||||
|
||||
if (!inline_change) {
|
||||
zval *tmp;
|
||||
HashTable *tmp_ht = NULL;
|
||||
|
||||
ALLOC_HASHTABLE(tmp_ht);
|
||||
zend_hash_init(tmp_ht, zend_hash_num_elements(Z_ARRVAL_P(p)), NULL, ZVAL_PTR_DTOR, 0);
|
||||
zend_hash_copy(tmp_ht, Z_ARRVAL_P(p), (copy_ctor_func_t) zval_deep_copy, (void *) &tmp, sizeof(zval *));
|
||||
Z_ARRVAL_P(p) = tmp_ht;
|
||||
}
|
||||
|
||||
/* First go over the array and see if there are any constant indices */
|
||||
zend_hash_internal_pointer_reset(Z_ARRVAL_P(p));
|
||||
while (zend_hash_get_current_data(Z_ARRVAL_P(p), (void **) &element) == SUCCESS) {
|
||||
if (!(Z_TYPE_PP(element) & IS_CONSTANT_INDEX)) {
|
||||
zend_hash_move_forward(Z_ARRVAL_P(p));
|
||||
continue;
|
||||
}
|
||||
Z_TYPE_PP(element) &= ~IS_CONSTANT_INDEX;
|
||||
if (zend_hash_get_current_key_ex(Z_ARRVAL_P(p), &str_index, &str_index_len, &num_index, 0, NULL) != HASH_KEY_IS_STRING) {
|
||||
zend_hash_move_forward(Z_ARRVAL_P(p));
|
||||
continue;
|
||||
}
|
||||
if (str_index[str_index_len - 2] == IS_CONSTANT_AST) {
|
||||
zend_ast_evaluate(&const_value, *(zend_ast **)str_index);
|
||||
ZEND_AST_DEL_REF(*(zend_ast **)str_index);
|
||||
} else if (!zend_get_constant_ex(str_index, str_index_len - 3, &const_value, scope, str_index[str_index_len - 2] TSRMLS_CC)) {
|
||||
char *actual;
|
||||
const char *save = str_index;
|
||||
if ((colon = (char*)zend_memrchr(str_index, ':', str_index_len - 3))) {
|
||||
zend_error(E_ERROR, "Undefined class constant '%s'", str_index);
|
||||
str_index_len -= ((colon - str_index) + 1);
|
||||
str_index = colon;
|
||||
} else {
|
||||
if (str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) {
|
||||
if ((actual = (char *)zend_memrchr(str_index, '\\', str_index_len - 3))) {
|
||||
actual++;
|
||||
str_index_len -= (actual - str_index);
|
||||
str_index = actual;
|
||||
}
|
||||
}
|
||||
if (str_index[0] == '\\') {
|
||||
++str_index;
|
||||
--str_index_len;
|
||||
}
|
||||
if (save[0] == '\\') {
|
||||
++save;
|
||||
}
|
||||
if ((str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) == 0) {
|
||||
zend_error(E_ERROR, "Undefined constant '%s'", save);
|
||||
}
|
||||
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", str_index, str_index);
|
||||
}
|
||||
ZVAL_STRINGL(&const_value, str_index, str_index_len-3, 1);
|
||||
}
|
||||
|
||||
if (Z_REFCOUNT_PP(element) > 1) {
|
||||
ALLOC_ZVAL(new_val);
|
||||
*new_val = **element;
|
||||
zval_copy_ctor(new_val);
|
||||
Z_SET_REFCOUNT_P(new_val, 1);
|
||||
Z_UNSET_ISREF_P(new_val);
|
||||
|
||||
/* preserve this bit for inheritance */
|
||||
Z_TYPE_PP(element) |= IS_CONSTANT_INDEX;
|
||||
zval_ptr_dtor(element);
|
||||
*element = new_val;
|
||||
}
|
||||
|
||||
switch (Z_TYPE(const_value)) {
|
||||
case IS_STRING:
|
||||
ret = zend_symtable_update_current_key(Z_ARRVAL_P(p), Z_STRVAL(const_value), Z_STRLEN(const_value) + 1, HASH_UPDATE_KEY_IF_BEFORE);
|
||||
break;
|
||||
case IS_BOOL:
|
||||
case IS_LONG:
|
||||
ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, Z_LVAL(const_value), HASH_UPDATE_KEY_IF_BEFORE, NULL);
|
||||
break;
|
||||
case IS_DOUBLE:
|
||||
ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, zend_dval_to_lval(Z_DVAL(const_value)), HASH_UPDATE_KEY_IF_BEFORE, NULL);
|
||||
break;
|
||||
case IS_NULL:
|
||||
ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, "", 1, 0, HASH_UPDATE_KEY_IF_BEFORE, NULL);
|
||||
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));
|
||||
}
|
||||
break;
|
||||
|
||||
case IS_CONSTANT_AST: {
|
||||
zend_ast *ast = Z_AST_P(p);
|
||||
|
||||
MARK_CONSTANT_VISITED(p);
|
||||
|
||||
zend_ast_evaluate(p, ast TSRMLS_CC);
|
||||
ZEND_AST_DEL_REF(ast);
|
||||
}
|
||||
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));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -947,25 +947,47 @@ common_scalar:
|
||||
| T_START_HEREDOC T_END_HEREDOC { ZVAL_EMPTY_STRING(&$$.u.constant); INIT_PZVAL(&$$.u.constant); $$.op_type = IS_CONST; }
|
||||
;
|
||||
|
||||
static_class_constant:
|
||||
class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_CT, 0 TSRMLS_CC); }
|
||||
;
|
||||
|
||||
static_scalar: /* compile-time evaluated scalars */
|
||||
common_scalar { $$ = $1; }
|
||||
static_scalar_value { $$ = $1; }
|
||||
;
|
||||
|
||||
static_scalar_value:
|
||||
common_scalar { $$ = $1; }
|
||||
| static_class_name_scalar { $$ = $1; }
|
||||
| namespace_name { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT, 1 TSRMLS_CC); }
|
||||
| T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); $3 = $$; zend_do_fetch_constant(&$$, NULL, &$3, ZEND_CT, 0 TSRMLS_CC); }
|
||||
| T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRLEN($2.u.constant); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_CT, 0 TSRMLS_CC); }
|
||||
| '+' static_scalar { ZVAL_LONG(&$1.u.constant, 0); add_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; }
|
||||
| '-' static_scalar { ZVAL_LONG(&$1.u.constant, 0); sub_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; }
|
||||
| T_ARRAY '(' static_array_pair_list ')' { $$ = $3; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; }
|
||||
| '[' static_array_pair_list ']' { $$ = $2; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; }
|
||||
| static_class_constant { $$ = $1; }
|
||||
| T_CLASS_C { $$ = $1; }
|
||||
| static_operation { $$ = $1; }
|
||||
;
|
||||
|
||||
static_class_constant:
|
||||
class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_CT, 0 TSRMLS_CC); }
|
||||
static_operation:
|
||||
static_scalar_value '+' static_scalar_value { zend_ast_add_binary(&$$.u.constant, add_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
|
||||
| static_scalar_value '-' static_scalar_value { zend_ast_add_binary(&$$.u.constant, sub_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
|
||||
| static_scalar_value '*' static_scalar_value { zend_ast_add_binary(&$$.u.constant, mul_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
|
||||
| static_scalar_value '/' static_scalar_value { zend_ast_add_binary(&$$.u.constant, div_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
|
||||
| static_scalar_value '%' static_scalar_value { zend_ast_add_binary(&$$.u.constant, mod_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
|
||||
| '!' static_scalar_value { zend_ast_add_unary(&$$.u.constant, boolean_not_function, &$2.u.constant TSRMLS_CC); }
|
||||
| '~' static_scalar_value { zend_ast_add_unary(&$$.u.constant, bitwise_not_function, &$2.u.constant TSRMLS_CC); }
|
||||
| static_scalar_value '|' static_scalar_value { zend_ast_add_binary(&$$.u.constant, bitwise_or_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
|
||||
| static_scalar_value '&' static_scalar_value { zend_ast_add_binary(&$$.u.constant, bitwise_and_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
|
||||
| static_scalar_value '^' static_scalar_value { zend_ast_add_binary(&$$.u.constant, bitwise_xor_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
|
||||
| static_scalar_value T_SL static_scalar_value { zend_ast_add_binary(&$$.u.constant, shift_left_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
|
||||
| static_scalar_value T_SR static_scalar_value { zend_ast_add_binary(&$$.u.constant, shift_right_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
|
||||
| static_scalar_value '.' static_scalar_value { zend_ast_add_binary(&$$.u.constant, concat_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
|
||||
| '+' static_scalar_value { ZVAL_LONG(&$1.u.constant, 0); zend_ast_add_binary(&$$.u.constant, add_function, &$1.u.constant, &$2.u.constant TSRMLS_CC); }
|
||||
| '-' static_scalar_value { ZVAL_LONG(&$1.u.constant, 0); zend_ast_add_binary(&$$.u.constant, sub_function, &$1.u.constant, &$2.u.constant TSRMLS_CC); }
|
||||
| '(' static_scalar_value ')' { $$ = $2; }
|
||||
;
|
||||
|
||||
|
||||
scalar:
|
||||
T_STRING_VARNAME { $$ = $1; }
|
||||
| class_name_scalar { $$ = $1; }
|
||||
|
||||
@@ -443,6 +443,7 @@ END_EXTERN_C()
|
||||
#define Z_STRVAL(zval) (zval).value.str.val
|
||||
#define Z_STRLEN(zval) (zval).value.str.len
|
||||
#define Z_ARRVAL(zval) (zval).value.ht
|
||||
#define Z_AST(zval) (zval).value.ast
|
||||
#define Z_OBJVAL(zval) (zval).value.obj
|
||||
#define Z_OBJ_HANDLE(zval) Z_OBJVAL(zval).handle
|
||||
#define Z_OBJ_HT(zval) Z_OBJVAL(zval).handlers
|
||||
@@ -458,6 +459,7 @@ END_EXTERN_C()
|
||||
#define Z_STRVAL_P(zval_p) Z_STRVAL(*zval_p)
|
||||
#define Z_STRLEN_P(zval_p) Z_STRLEN(*zval_p)
|
||||
#define Z_ARRVAL_P(zval_p) Z_ARRVAL(*zval_p)
|
||||
#define Z_AST_P(zval_p) Z_AST(*zval_p)
|
||||
#define Z_OBJPROP_P(zval_p) Z_OBJPROP(*zval_p)
|
||||
#define Z_OBJCE_P(zval_p) Z_OBJCE(*zval_p)
|
||||
#define Z_RESVAL_P(zval_p) Z_RESVAL(*zval_p)
|
||||
@@ -473,6 +475,7 @@ END_EXTERN_C()
|
||||
#define Z_STRVAL_PP(zval_pp) Z_STRVAL(**zval_pp)
|
||||
#define Z_STRLEN_PP(zval_pp) Z_STRLEN(**zval_pp)
|
||||
#define Z_ARRVAL_PP(zval_pp) Z_ARRVAL(**zval_pp)
|
||||
#define Z_AST_PP(zval_p) Z_AST(**zval_p)
|
||||
#define Z_OBJPROP_PP(zval_pp) Z_OBJPROP(**zval_pp)
|
||||
#define Z_OBJCE_PP(zval_pp) Z_OBJCE(**zval_pp)
|
||||
#define Z_RESVAL_PP(zval_pp) Z_RESVAL(**zval_pp)
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <stdio.h>
|
||||
#include "zend.h"
|
||||
#include "zend_API.h"
|
||||
#include "zend_ast.h"
|
||||
#include "zend_globals.h"
|
||||
#include "zend_constants.h"
|
||||
#include "zend_list.h"
|
||||
@@ -47,6 +48,9 @@ ZEND_API void _zval_dtor_func(zval *zvalue ZEND_FILE_LINE_DC)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IS_CONSTANT_AST:
|
||||
ZEND_AST_DEL_REF(Z_AST_P(zvalue));
|
||||
break;
|
||||
case IS_OBJECT:
|
||||
{
|
||||
TSRMLS_FETCH();
|
||||
@@ -81,6 +85,9 @@ ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC)
|
||||
CHECK_ZVAL_STRING_REL(zvalue);
|
||||
str_free(zvalue->value.str.val);
|
||||
break;
|
||||
case IS_CONSTANT_AST:
|
||||
ZEND_AST_DEL_REF(Z_AST_P(zvalue));
|
||||
break;
|
||||
case IS_ARRAY:
|
||||
case IS_CONSTANT_ARRAY:
|
||||
case IS_OBJECT:
|
||||
@@ -139,6 +146,9 @@ ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC)
|
||||
zvalue->value.ht = tmp_ht;
|
||||
}
|
||||
break;
|
||||
case IS_CONSTANT_AST:
|
||||
ZEND_AST_ADD_REF(Z_AST_P(zvalue));
|
||||
break;
|
||||
case IS_OBJECT:
|
||||
{
|
||||
TSRMLS_FETCH();
|
||||
|
||||
+38
-24
@@ -3252,12 +3252,16 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
|
||||
if (param == NULL) {
|
||||
ALLOC_ZVAL(assignment_value);
|
||||
*assignment_value = *opline->op2.zv;
|
||||
if ((Z_TYPE_P(assignment_value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT ||
|
||||
Z_TYPE_P(assignment_value)==IS_CONSTANT_ARRAY) {
|
||||
Z_SET_REFCOUNT_P(assignment_value, 1);
|
||||
zval_update_constant(&assignment_value, 0 TSRMLS_CC);
|
||||
} else {
|
||||
zval_copy_ctor(assignment_value);
|
||||
switch (Z_TYPE_P(assignment_value) & IS_CONSTANT_TYPE_MASK) {
|
||||
case IS_CONSTANT:
|
||||
case IS_CONSTANT_ARRAY:
|
||||
case IS_CONSTANT_AST:
|
||||
Z_SET_REFCOUNT_P(assignment_value, 1);
|
||||
zval_update_constant(&assignment_value, 0 TSRMLS_CC);
|
||||
break;
|
||||
default:
|
||||
zval_copy_ctor(assignment_value);
|
||||
break;
|
||||
}
|
||||
INIT_PZVAL(assignment_value);
|
||||
} else {
|
||||
@@ -3580,13 +3584,16 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
|
||||
}
|
||||
|
||||
if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) {
|
||||
if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY ||
|
||||
(Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
|
||||
zend_class_entry *old_scope = EG(scope);
|
||||
switch (Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) {
|
||||
case IS_CONSTANT:
|
||||
case IS_CONSTANT_ARRAY:
|
||||
case IS_CONSTANT_AST: {
|
||||
zend_class_entry *old_scope = EG(scope);
|
||||
|
||||
EG(scope) = ce;
|
||||
zval_update_constant(value, (void *) 1 TSRMLS_CC);
|
||||
EG(scope) = old_scope;
|
||||
EG(scope) = ce;
|
||||
zval_update_constant(value, (void *) 1 TSRMLS_CC);
|
||||
EG(scope) = old_scope;
|
||||
}
|
||||
}
|
||||
if (OP1_TYPE == IS_CONST) {
|
||||
CACHE_PTR(opline->op2.literal->cache_slot, value);
|
||||
@@ -5187,20 +5194,27 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST)
|
||||
name = GET_OP1_ZVAL_PTR(BP_VAR_R);
|
||||
val = GET_OP2_ZVAL_PTR(BP_VAR_R);
|
||||
|
||||
if ((Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
|
||||
zval tmp;
|
||||
zval *tmp_ptr = &tmp;
|
||||
switch (Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) {
|
||||
case IS_CONSTANT:
|
||||
case IS_CONSTANT_ARRAY:
|
||||
case IS_CONSTANT_AST: {
|
||||
zval tmp;
|
||||
zval *tmp_ptr = &tmp;
|
||||
|
||||
ZVAL_COPY_VALUE(&tmp, val);
|
||||
if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
|
||||
zval_copy_ctor(&tmp);
|
||||
ZVAL_COPY_VALUE(&tmp, val);
|
||||
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;
|
||||
}
|
||||
INIT_PZVAL(&tmp);
|
||||
zval_update_constant(&tmp_ptr, NULL TSRMLS_CC);
|
||||
c.value = *tmp_ptr;
|
||||
} else {
|
||||
INIT_PZVAL_COPY(&c.value, val);
|
||||
zval_copy_ctor(&c.value);
|
||||
break;
|
||||
|
||||
default:
|
||||
INIT_PZVAL_COPY(&c.value, val);
|
||||
zval_copy_ctor(&c.value);
|
||||
break;
|
||||
}
|
||||
c.flags = CONST_CS; /* non persistent, case sensetive */
|
||||
c.name = str_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
|
||||
|
||||
+56
-36
@@ -1435,12 +1435,16 @@ static int ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_
|
||||
if (param == NULL) {
|
||||
ALLOC_ZVAL(assignment_value);
|
||||
*assignment_value = *opline->op2.zv;
|
||||
if ((Z_TYPE_P(assignment_value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT ||
|
||||
Z_TYPE_P(assignment_value)==IS_CONSTANT_ARRAY) {
|
||||
Z_SET_REFCOUNT_P(assignment_value, 1);
|
||||
zval_update_constant(&assignment_value, 0 TSRMLS_CC);
|
||||
} else {
|
||||
zval_copy_ctor(assignment_value);
|
||||
switch (Z_TYPE_P(assignment_value) & IS_CONSTANT_TYPE_MASK) {
|
||||
case IS_CONSTANT:
|
||||
case IS_CONSTANT_ARRAY:
|
||||
case IS_CONSTANT_AST:
|
||||
Z_SET_REFCOUNT_P(assignment_value, 1);
|
||||
zval_update_constant(&assignment_value, 0 TSRMLS_CC);
|
||||
break;
|
||||
default:
|
||||
zval_copy_ctor(assignment_value);
|
||||
break;
|
||||
}
|
||||
INIT_PZVAL(assignment_value);
|
||||
} else {
|
||||
@@ -3792,13 +3796,16 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO
|
||||
}
|
||||
|
||||
if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) {
|
||||
if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY ||
|
||||
(Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
|
||||
zend_class_entry *old_scope = EG(scope);
|
||||
switch (Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) {
|
||||
case IS_CONSTANT:
|
||||
case IS_CONSTANT_ARRAY:
|
||||
case IS_CONSTANT_AST: {
|
||||
zend_class_entry *old_scope = EG(scope);
|
||||
|
||||
EG(scope) = ce;
|
||||
zval_update_constant(value, (void *) 1 TSRMLS_CC);
|
||||
EG(scope) = old_scope;
|
||||
EG(scope) = ce;
|
||||
zval_update_constant(value, (void *) 1 TSRMLS_CC);
|
||||
EG(scope) = old_scope;
|
||||
}
|
||||
}
|
||||
if (IS_CONST == IS_CONST) {
|
||||
CACHE_PTR(opline->op2.literal->cache_slot, value);
|
||||
@@ -4089,20 +4096,27 @@ static int ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCOD
|
||||
name = opline->op1.zv;
|
||||
val = opline->op2.zv;
|
||||
|
||||
if ((Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
|
||||
zval tmp;
|
||||
zval *tmp_ptr = &tmp;
|
||||
switch (Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) {
|
||||
case IS_CONSTANT:
|
||||
case IS_CONSTANT_ARRAY:
|
||||
case IS_CONSTANT_AST: {
|
||||
zval tmp;
|
||||
zval *tmp_ptr = &tmp;
|
||||
|
||||
ZVAL_COPY_VALUE(&tmp, val);
|
||||
if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
|
||||
zval_copy_ctor(&tmp);
|
||||
ZVAL_COPY_VALUE(&tmp, val);
|
||||
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;
|
||||
}
|
||||
INIT_PZVAL(&tmp);
|
||||
zval_update_constant(&tmp_ptr, NULL TSRMLS_CC);
|
||||
c.value = *tmp_ptr;
|
||||
} else {
|
||||
INIT_PZVAL_COPY(&c.value, val);
|
||||
zval_copy_ctor(&c.value);
|
||||
break;
|
||||
|
||||
default:
|
||||
INIT_PZVAL_COPY(&c.value, val);
|
||||
zval_copy_ctor(&c.value);
|
||||
break;
|
||||
}
|
||||
c.flags = CONST_CS; /* non persistent, case sensetive */
|
||||
c.name = str_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
|
||||
@@ -15635,13 +15649,16 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE
|
||||
}
|
||||
|
||||
if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) {
|
||||
if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY ||
|
||||
(Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
|
||||
zend_class_entry *old_scope = EG(scope);
|
||||
switch (Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) {
|
||||
case IS_CONSTANT:
|
||||
case IS_CONSTANT_ARRAY:
|
||||
case IS_CONSTANT_AST: {
|
||||
zend_class_entry *old_scope = EG(scope);
|
||||
|
||||
EG(scope) = ce;
|
||||
zval_update_constant(value, (void *) 1 TSRMLS_CC);
|
||||
EG(scope) = old_scope;
|
||||
EG(scope) = ce;
|
||||
zval_update_constant(value, (void *) 1 TSRMLS_CC);
|
||||
EG(scope) = old_scope;
|
||||
}
|
||||
}
|
||||
if (IS_VAR == IS_CONST) {
|
||||
CACHE_PTR(opline->op2.literal->cache_slot, value);
|
||||
@@ -25171,13 +25188,16 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC
|
||||
}
|
||||
|
||||
if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) {
|
||||
if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY ||
|
||||
(Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
|
||||
zend_class_entry *old_scope = EG(scope);
|
||||
switch (Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) {
|
||||
case IS_CONSTANT:
|
||||
case IS_CONSTANT_ARRAY:
|
||||
case IS_CONSTANT_AST: {
|
||||
zend_class_entry *old_scope = EG(scope);
|
||||
|
||||
EG(scope) = ce;
|
||||
zval_update_constant(value, (void *) 1 TSRMLS_CC);
|
||||
EG(scope) = old_scope;
|
||||
EG(scope) = ce;
|
||||
zval_update_constant(value, (void *) 1 TSRMLS_CC);
|
||||
EG(scope) = old_scope;
|
||||
}
|
||||
}
|
||||
if (IS_UNUSED == IS_CONST) {
|
||||
CACHE_PTR(opline->op2.literal->cache_slot, value);
|
||||
|
||||
+3
-1
@@ -1475,7 +1475,9 @@ PHP_ADD_SOURCES(Zend, \
|
||||
zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
|
||||
zend_ini.c zend_qsort.c zend_multibyte.c zend_ts_hash.c zend_stream.c \
|
||||
zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c zend_gc.c \
|
||||
zend_closures.c zend_float.c zend_string.c zend_signal.c zend_generators.c)
|
||||
zend_closures.c zend_float.c zend_string.c zend_signal.c \
|
||||
zend_generators.c \
|
||||
zend_ast.c)
|
||||
|
||||
if test -r "$abs_srcdir/Zend/zend_objects.c"; then
|
||||
PHP_ADD_SOURCES(Zend, zend_objects.c zend_object_handlers.c zend_objects_API.c zend_default_classes.c)
|
||||
|
||||
@@ -2599,9 +2599,14 @@ ZEND_METHOD(reflection_parameter, getDefaultValue)
|
||||
|
||||
*return_value = *precv->op2.zv;
|
||||
INIT_PZVAL(return_value);
|
||||
if ((Z_TYPE_P(return_value) & IS_CONSTANT_TYPE_MASK) != IS_CONSTANT
|
||||
&& (Z_TYPE_P(return_value) & IS_CONSTANT_TYPE_MASK) != IS_CONSTANT_ARRAY) {
|
||||
zval_copy_ctor(return_value);
|
||||
switch (Z_TYPE_P(return_value) & IS_CONSTANT_TYPE_MASK) {
|
||||
case IS_CONSTANT:
|
||||
case IS_CONSTANT_ARRAY:
|
||||
case IS_CONSTANT_AST:
|
||||
break;
|
||||
|
||||
default:
|
||||
zval_copy_ctor(return_value);
|
||||
}
|
||||
zval_update_constant_ex(&return_value, (void*)0, param->fptr->common.scope TSRMLS_CC);
|
||||
}
|
||||
@@ -3414,8 +3419,11 @@ static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value
|
||||
|
||||
/* 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_TYPE_MASK) == IS_CONSTANT) {
|
||||
zval_update_constant(&prop_copy, (void *) 1 TSRMLS_CC);
|
||||
switch (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) {
|
||||
case IS_CONSTANT:
|
||||
case IS_CONSTANT_ARRAY:
|
||||
case IS_CONSTANT_AST:
|
||||
zval_update_constant(&prop_copy, (void *) 1 TSRMLS_CC);
|
||||
}
|
||||
|
||||
add_assoc_zval(return_value, key, prop_copy);
|
||||
|
||||
@@ -364,7 +364,9 @@ ADD_SOURCES("Zend", "zend_language_parser.c zend_language_scanner.c \
|
||||
zend_stream.c zend_iterators.c zend_interfaces.c zend_objects.c \
|
||||
zend_object_handlers.c zend_objects_API.c \
|
||||
zend_default_classes.c zend_execute.c zend_strtod.c zend_gc.c zend_closures.c \
|
||||
zend_float.c zend_string.c zend_generators.c");
|
||||
zend_float.c zend_string.c \
|
||||
zend_generators.c \
|
||||
zend_ast.c");
|
||||
|
||||
if (VCVERS == 1200) {
|
||||
AC_DEFINE('ZEND_DVAL_TO_LVAL_CAST_OK', 1);
|
||||
|
||||
Reference in New Issue
Block a user