1
0
mirror of https://github.com/php/php-src.git synced 2026-04-28 18:53:33 +02:00

Constant expressions refactoring

This commit is contained in:
Dmitry Stogov
2013-11-06 22:21:07 +04:00
parent af600c240d
commit 9647c61dc1
17 changed files with 677 additions and 427 deletions
+10 -10
View File
@@ -579,18 +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_CONSTANT_AST 10
#define IS_CALLABLE 11
#define IS_CALLABLE 11
/* Ugly hack to support constants as static array indices */
#define IS_CONSTANT_TYPE_MASK 0x00f
+292 -93
View File
@@ -13,118 +13,317 @@
| license@zend.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Bob Weinand <bwoebi@php.net> |
| Dmitry Stogov <dmitry@zend.com> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#include "zend_ast.h"
#include "zend_execute.h"
#include "zend_API.h"
#include "zend_operators.h"
#define COPY_ZVAL_TO_OP(nr) \
if (op##nr) { \
Z_AST_P(result)->ops[nr] = emalloc(sizeof(zval)); \
*Z_AST_P(result)->ops[nr] = *op##nr; \
} else { \
Z_AST_P(result)->ops[nr] = NULL; \
}
void zend_ast_add(zval *result, intermediary_ast_function_type func, char op_count) {
zend_ast *ast = emalloc(sizeof(zend_ast) + op_count * sizeof(zval *));
ast->op_count = op_count;
ast->ops = (zval **)(ast + 1);
ast->refcount = 1;
ast->func = func;
Z_AST_P(result) = ast;
Z_TYPE_P(result) = IS_CONSTANT_AST;
ZEND_API zend_ast *zend_ast_create_constant_node(zval *zv)
{
zend_ast *node = emalloc(sizeof(zend_ast) + sizeof(zval));
node->kind = ZEND_CONST;
node->children = 0;
node->u.val = (zval*)(node + 1);
INIT_PZVAL_COPY(node->u.val, zv);
return node;
}
/* Do operations on constant operators at compile time (AST building time) */
void zend_ast_add_unary(zval *result, unary_ast_func func, zval *op0 TSRMLS_DC) {
if (!op0 || !IS_CONSTANT_TYPE(Z_TYPE_P(op0))) {
func(result, op0 TSRMLS_CC);
if (op0) zval_dtor(op0);
return;
}
zend_ast_add(result, (intermediary_ast_function_type)func, 1);
COPY_ZVAL_TO_OP(0)
ZEND_API zend_ast* zend_ast_create_node1(uint kind, zend_ast *op0)
{
zend_ast *node = emalloc(sizeof(zend_ast));
node->kind = kind;
node->children = 1;
node->u.child[0] = op0;
return node;
}
void zend_ast_add_binary(zval *result, binary_ast_func func, zval *op0, zval *op1 TSRMLS_DC) {
if ((!op0 || !IS_CONSTANT_TYPE(Z_TYPE_P(op0))) && (!op1 || !IS_CONSTANT_TYPE(Z_TYPE_P(op1)))) {
func(result, op0, op1 TSRMLS_CC);
if (op0) zval_dtor(op0);
if (op1) zval_dtor(op1);
return;
}
zend_ast_add(result, (intermediary_ast_function_type)func, 2);
COPY_ZVAL_TO_OP(0)
COPY_ZVAL_TO_OP(1)
ZEND_API zend_ast* zend_ast_create_node2(uint kind, zend_ast *op0, zend_ast *op1)
{
zend_ast *node = emalloc(sizeof(zend_ast) + sizeof(zend_ast*));
node->kind = kind;
node->children = 2;
node->u.child[0] = op0;
node->u.child[1] = op1;
return node;
}
void zend_ast_add_ternary(zval *result, ternary_ast_func func, zval *op0, zval *op1, zval *op2 TSRMLS_DC) {
if ((!op0 || !IS_CONSTANT_TYPE(Z_TYPE_P(op0))) && (!op1 || !IS_CONSTANT_TYPE(Z_TYPE_P(op1))) && (!op2 || !IS_CONSTANT_TYPE(Z_TYPE_P(op2)))) {
func(result, op0, op1, op2 TSRMLS_CC);
if (op0) zval_dtor(op0);
if (op1) zval_dtor(op1);
if (op2) zval_dtor(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)
ZEND_API zend_ast* zend_ast_create_node3(uint kind, zend_ast *op0, zend_ast *op1, zend_ast *op2)
{
zend_ast *node = emalloc(sizeof(zend_ast) + sizeof(zend_ast*) * 2);
node->kind = kind;
node->children = 3;
node->u.child[0] = op0;
node->u.child[1] = op1;
node->u.child[2] = op2;
return node;
}
void zend_ast_evaluate(zval *result, zend_ast *ast TSRMLS_DC) {
int i;
zval **ops = emalloc((sizeof(zval *) + sizeof(zval)) * ast->op_count);
for (i = ast->op_count; i--;) {
if (ast->ops[i] && IS_CONSTANT_TYPE(Z_TYPE_P(ast->ops[i]))) {
ops[i] = ((zval *)(ops + ast->op_count)) + i;
*ops[i] = *ast->ops[i];
zval_copy_ctor(ops[i]);
zval_update_constant_ex(&ops[i], (void *)1, NULL TSRMLS_CC);
} else {
ops[i] = ast->ops[i];
}
}
switch (ast->op_count) {
case 1:
((unary_ast_func)ast->func)(result, ops[0] TSRMLS_CC);
break;
case 2:
((binary_ast_func)ast->func)(result, ops[0], ops[1] TSRMLS_CC);
break;
case 3:
((ternary_ast_func)ast->func)(result, ops[0], ops[1], ops[2] TSRMLS_CC);
break;
}
for (i = ast->op_count; i--;) {
if (ast->ops[i] != ops[i]) {
zval_dtor(ops[i]);
}
}
efree(ops);
}
void zend_ast_destroy(zend_ast *ast TSRMLS_DC) {
ZEND_API int zend_ast_is_ct_constant(zend_ast *ast)
{
int i;
for (i = ast->op_count; i--;) {
if (ast->ops[i] && !Z_DELREF_P(ast->ops[i])) {
zval_dtor(ast->ops[i]);
efree(ast->ops[i]);
if (ast->kind == ZEND_CONST) {
return !IS_CONSTANT_TYPE(Z_TYPE_P(ast->u.val));
} else {
for (i = 0; i < ast->children; i++) {
if (ast->u.child[i]) {
if (!zend_ast_is_ct_constant(ast->u.child[i])) {
return 0;
}
}
}
return 1;
}
}
ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast TSRMLS_DC)
{
zval op1, op2;
switch (ast->kind) {
case ZEND_ADD:
zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
add_function(result, &op1, &op2 TSRMLS_CC);
zval_dtor(&op1);
zval_dtor(&op2);
break;
case ZEND_SUB:
zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
sub_function(result, &op1, &op2 TSRMLS_CC);
zval_dtor(&op1);
zval_dtor(&op2);
break;
case ZEND_MUL:
zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
mul_function(result, &op1, &op2 TSRMLS_CC);
zval_dtor(&op1);
zval_dtor(&op2);
break;
case ZEND_DIV:
zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
div_function(result, &op1, &op2 TSRMLS_CC);
zval_dtor(&op1);
zval_dtor(&op2);
break;
case ZEND_MOD:
zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
mod_function(result, &op1, &op2 TSRMLS_CC);
zval_dtor(&op1);
zval_dtor(&op2);
break;
case ZEND_SL:
zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
shift_left_function(result, &op1, &op2 TSRMLS_CC);
zval_dtor(&op1);
zval_dtor(&op2);
break;
case ZEND_SR:
zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
shift_right_function(result, &op1, &op2 TSRMLS_CC);
zval_dtor(&op1);
zval_dtor(&op2);
break;
case ZEND_CONCAT:
zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
concat_function(result, &op1, &op2 TSRMLS_CC);
zval_dtor(&op1);
zval_dtor(&op2);
break;
case ZEND_BW_OR:
zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
bitwise_or_function(result, &op1, &op2 TSRMLS_CC);
zval_dtor(&op1);
zval_dtor(&op2);
break;
case ZEND_BW_AND:
zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
bitwise_and_function(result, &op1, &op2 TSRMLS_CC);
zval_dtor(&op1);
zval_dtor(&op2);
break;
case ZEND_BW_XOR:
zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
bitwise_xor_function(result, &op1, &op2 TSRMLS_CC);
zval_dtor(&op1);
zval_dtor(&op2);
break;
case ZEND_BW_NOT:
zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
bitwise_not_function(result, &op1 TSRMLS_CC);
zval_dtor(&op1);
break;
case ZEND_BOOL_NOT:
zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
boolean_not_function(result, &op1 TSRMLS_CC);
zval_dtor(&op1);
break;
case ZEND_BOOL_XOR:
zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
boolean_xor_function(result, &op1, &op2 TSRMLS_CC);
zval_dtor(&op1);
zval_dtor(&op2);
break;
case ZEND_IS_IDENTICAL:
zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
is_identical_function(result, &op1, &op2 TSRMLS_CC);
zval_dtor(&op1);
zval_dtor(&op2);
break;
case ZEND_IS_NOT_IDENTICAL:
zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
is_not_identical_function(result, &op1, &op2 TSRMLS_CC);
zval_dtor(&op1);
zval_dtor(&op2);
break;
case ZEND_IS_EQUAL:
zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
is_equal_function(result, &op1, &op2 TSRMLS_CC);
zval_dtor(&op1);
zval_dtor(&op2);
break;
case ZEND_IS_NOT_EQUAL:
zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
is_not_equal_function(result, &op1, &op2 TSRMLS_CC);
zval_dtor(&op1);
zval_dtor(&op2);
break;
case ZEND_IS_SMALLER:
zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
is_smaller_function(result, &op1, &op2 TSRMLS_CC);
zval_dtor(&op1);
zval_dtor(&op2);
break;
case ZEND_IS_SMALLER_OR_EQUAL:
zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
is_smaller_or_equal_function(result, &op1, &op2 TSRMLS_CC);
zval_dtor(&op1);
zval_dtor(&op2);
break;
case ZEND_CONST:
*result = *ast->u.val;
zval_copy_ctor(result);
if (IS_CONSTANT_TYPE(Z_TYPE_P(result))) {
zval_update_constant(&result, (void *) 1 TSRMLS_CC);
}
break;
case ZEND_BOOL_AND:
zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
if (zend_is_true(&op1)) {
zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
ZVAL_BOOL(result, zend_is_true(&op2));
zval_dtor(&op2);
} else {
ZVAL_BOOL(result, 0);
}
zval_dtor(&op1);
break;
case ZEND_BOOL_OR:
zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
if (zend_is_true(&op1)) {
ZVAL_BOOL(result, 1);
} else {
zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
ZVAL_BOOL(result, zend_is_true(&op2));
zval_dtor(&op2);
}
zval_dtor(&op1);
break;
case ZEND_TERNARY:
zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
if (zend_is_true(&op1)) {
if (!ast->u.child[1]) {
*result = op1;
} else {
zend_ast_evaluate(result, ast->u.child[1] TSRMLS_CC);
zval_dtor(&op1);
}
} else {
zend_ast_evaluate(result, ast->u.child[2] TSRMLS_CC);
zval_dtor(&op1);
}
break;
case ZEND_UNARY_PLUS:
ZVAL_LONG(&op1, 0);
zend_ast_evaluate(&op2, ast->u.child[0] TSRMLS_CC);
add_function(result, &op1, &op2 TSRMLS_CC);
zval_dtor(&op2);
break;
case ZEND_UNARY_MINUS:
ZVAL_LONG(&op1, 0);
zend_ast_evaluate(&op2, ast->u.child[0] TSRMLS_CC);
sub_function(result, &op1, &op2 TSRMLS_CC);
zval_dtor(&op2);
break;
default:
zend_error(E_ERROR, "Unsupported constant expression");
}
}
ZEND_API zend_ast *zend_ast_copy(zend_ast *ast)
{
if (ast == NULL) {
return NULL;
} else if (ast->kind == ZEND_CONST) {
zend_ast *node = zend_ast_create_constant_node(ast->u.val);
zval_copy_ctor(node->u.val);
return node;
} else {
switch (ast->children) {
case 1:
return zend_ast_create_node1(
ast->kind,
zend_ast_copy(ast->u.child[0]));
case 2:
return zend_ast_create_node2(
ast->kind,
zend_ast_copy(ast->u.child[0]),
zend_ast_copy(ast->u.child[1]));
case 3:
return zend_ast_create_node3(
ast->kind,
zend_ast_copy(ast->u.child[0]),
zend_ast_copy(ast->u.child[1]),
zend_ast_copy(ast->u.child[2]));
}
}
return NULL;
}
ZEND_API void zend_ast_destroy(zend_ast *ast)
{
int i;
if (ast->kind == ZEND_CONST) {
zval_dtor(ast->u.val);
} else {
for (i = 0; i < ast->children; i++) {
if (ast->u.child[i]) {
zend_ast_destroy(ast->u.child[i]);
}
}
}
efree(ast);
}
+24 -23
View File
@@ -13,6 +13,7 @@
| license@zend.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Bob Weinand <bwoebi@php.net> |
| Dmitry Stogov <dmitry@zend.com> |
+----------------------------------------------------------------------+
*/
@@ -25,36 +26,36 @@ 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 TSRMLS_DC);
typedef int(*binary_ast_func)(zval *result, zval *op0, zval *op1 TSRMLS_DC);
typedef int(*ternary_ast_func)(zval *result, zval *op0, zval *op1, zval *op2 TSRMLS_DC);
typedef enum _zend_ast_node_kind {
/* first 256 node kinds are reserved for opcodes */
ZEND_CONST = 256,
ZEND_BOOL_AND,
ZEND_BOOL_OR,
ZEND_TERNARY,
ZEND_UNARY_PLUS,
ZEND_UNARY_MINUS,
} zend_ast_ode_kind;
struct _zend_ast {
char op_count;
zval **ops;
intermediary_ast_function_type func;
int refcount;
unsigned short kind;
unsigned short children;
union {
zval *val;
zend_ast *child[1];
} u;
};
void zend_ast_add_unary(zval *result, unary_ast_func func, zval *op0 TSRMLS_DC);
void zend_ast_add_binary(zval *result, binary_ast_func func, zval *op0, zval *op1 TSRMLS_DC);
void zend_ast_add_ternary(zval *result, ternary_ast_func func, zval *op0, zval *op1, zval *op2 TSRMLS_DC);
ZEND_API zend_ast *zend_ast_create_constant_node(zval *zv);
void zend_ast_evaluate(zval *result, zend_ast *ast TSRMLS_DC);
ZEND_API zend_ast *zend_ast_create_node1(uint kind, zend_ast *op0);
ZEND_API zend_ast *zend_ast_create_node2(uint kind, zend_ast *op0, zend_ast *op1);
ZEND_API zend_ast *zend_ast_create_node3(uint kind, zend_ast *op0, zend_ast *op1, zend_ast *op2);
void zend_ast_destroy(zend_ast *ast TSRMLS_DC);
ZEND_API int zend_ast_is_ct_constant(zend_ast *ast);
#define ZEND_AST_ADD_REF(ast) ++ast->refcount
ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast TSRMLS_DC);
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;
}
ZEND_API zend_ast *zend_ast_copy(zend_ast *ast);
ZEND_API void zend_ast_destroy(zend_ast *ast);
#endif
+1 -1
View File
@@ -946,7 +946,7 @@ 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 */
switch (IS_CONSTANT_TYPE(Z_TYPE_P(prop_copy))) {
if (IS_CONSTANT_TYPE(Z_TYPE_P(prop_copy))) {
zval_update_constant(&prop_copy, 0 TSRMLS_CC);
}
+16 -1
View File
@@ -5793,8 +5793,8 @@ void zend_do_add_static_array_element(znode *result, znode *offset, const znode
key[len + 1] = 0;
zend_symtable_update(Z_ARRVAL(result->u.constant), key, len + 2, &element, sizeof(zval *), NULL);
efree(key);
break;
}
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);
@@ -7133,6 +7133,21 @@ void zend_do_end_compilation(TSRMLS_D) /* {{{ */
}
/* }}} */
void zend_do_constant_expression(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
{
if (ast->kind == ZEND_CONST) {
result->u.constant = *ast->u.val;
efree(ast);
} else if (zend_ast_is_ct_constant(ast)) {
zend_ast_evaluate(&result->u.constant, ast TSRMLS_CC);
zend_ast_destroy(ast);
} else {
Z_TYPE(result->u.constant) = IS_CONSTANT_AST;
Z_AST(result->u.constant) = ast;
}
}
/* }}} */
/* {{{ zend_dirname
Returns directory name component of path */
ZEND_API size_t zend_dirname(char *path, size_t len)
+2 -4
View File
@@ -93,6 +93,7 @@ typedef struct _znode { /* used only during compilation */
znode_op op;
zval constant; /* replaced by literal/zv */
zend_op_array *op_array;
zend_ast *ast;
} u;
zend_uint EA; /* extended attributes */
} znode;
@@ -639,6 +640,7 @@ void zend_do_end_namespace(TSRMLS_D);
void zend_verify_namespace(TSRMLS_D);
void zend_do_use(znode *name, znode *new_name, int is_global TSRMLS_DC);
void zend_do_end_compilation(TSRMLS_D);
void zend_do_constant_expression(znode *result, zend_ast *ast TSRMLS_DC);
void zend_do_resolve_class_name(znode *result, znode *class_name, int is_static TSRMLS_DC);
@@ -722,10 +724,6 @@ int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC);
#define ZEND_OP_DATA 137
/* Pseudo-opcodes for internal object overloading */
#define ZEND_BOOL_AND -1
#define ZEND_BOOL_OR -2
/* END: OPCODES */
/* class fetches */
+176 -181
View File
@@ -478,205 +478,200 @@ 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));
return FAILURE;
}
switch (Z_TYPE_P(p) & IS_CONSTANT_TYPE_MASK) {
case IS_CONSTANT: {
int refcount;
zend_uchar is_ref;
} else if ((Z_TYPE_P(p) & IS_CONSTANT_TYPE_MASK) == 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;
}
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 {
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 (actual[0] == '\\') {
if (inline_change) {
memmove(Z_STRVAL_P(p), Z_STRVAL_P(p)+1, Z_STRLEN_P(p)--);
} else {
++actual;
}
--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);
}
Z_STRVAL_P(p) = colon + 1;
}
} 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);
}
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 TSRMLS_CC);
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);
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;
}
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;
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;
}
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 ((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 (ret == SUCCESS) {
zend_hash_move_forward(Z_ARRVAL_P(p));
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);
}
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 (inline_change) {
str_efree(Z_STRVAL_P(p));
}
*p = const_value;
}
break;
case IS_CONSTANT_AST: {
zend_ast *ast = Z_AST_P(p);
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;
zend_ast_evaluate(p, ast TSRMLS_CC);
ZEND_AST_DEL_REF(ast);
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 TSRMLS_CC);
zend_ast_destroy(*(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));
} else if (Z_TYPE_P(p) == IS_CONSTANT_AST) {
SEPARATE_ZVAL_IF_NOT_REF(pp);
p = *pp;
zend_ast_evaluate(&const_value, Z_AST_P(p) TSRMLS_CC);
if (inline_change) {
zend_ast_destroy(Z_AST_P(p));
}
ZVAL_COPY_VALUE(p, &const_value);
}
return 0;
}
+1 -1
View File
@@ -28,7 +28,7 @@
/* The first number is the engine version and the rest is the date.
* This way engine 2/3 API no. is always greater than engine 1 API no..
*/
#define ZEND_EXTENSION_API_NO 220121212
#define ZEND_EXTENSION_API_NO 220131106
typedef struct _zend_extension_version_info {
int zend_extension_api_no;
+40 -40
View File
@@ -952,53 +952,53 @@ static_class_constant:
;
static_scalar: /* compile-time evaluated scalars */
static_scalar_value { $$ = $1; }
| 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_scalar_value { zend_do_constant_expression(&$$, $1.u.ast TSRMLS_CC); }
;
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_class_constant { $$ = $1; }
| T_CLASS_C { $$ = $1; }
common_scalar { $$.u.ast = zend_ast_create_constant_node(&$1.u.constant); }
| static_class_name_scalar { $$.u.ast = zend_ast_create_constant_node(&$1.u.constant); }
| namespace_name { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT, 1 TSRMLS_CC); $$.u.ast = zend_ast_create_constant_node(&$$.u.constant); }
| 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); $$.u.ast = zend_ast_create_constant_node(&$$.u.constant); }
| 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); $$.u.ast = zend_ast_create_constant_node(&$$.u.constant); }
| static_class_constant { $$.u.ast = zend_ast_create_constant_node(&$1.u.constant); }
| T_CLASS_C { $$.u.ast = zend_ast_create_constant_node(&$1.u.constant); }
| T_ARRAY '(' static_array_pair_list ')' { $$ = $3; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; $$.u.ast = zend_ast_create_constant_node(&$$.u.constant); }
| '[' static_array_pair_list ']' { $$ = $2; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; $$.u.ast = zend_ast_create_constant_node(&$$.u.constant); }
| static_operation { $$ = $1; }
;
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 T_LOGICAL_XOR static_scalar_value { zend_ast_add_binary(&$$.u.constant, boolean_xor_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
| static_scalar_value T_LOGICAL_AND static_scalar_value { zend_ast_add_binary(&$$.u.constant, boolean_and_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
| static_scalar_value T_LOGICAL_OR static_scalar_value { zend_ast_add_binary(&$$.u.constant, boolean_or_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
| static_scalar_value T_BOOLEAN_AND static_scalar_value { zend_ast_add_binary(&$$.u.constant, boolean_and_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
| static_scalar_value T_BOOLEAN_OR static_scalar_value { zend_ast_add_binary(&$$.u.constant, boolean_or_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
| static_scalar_value T_IS_IDENTICAL static_scalar_value { zend_ast_add_binary(&$$.u.constant, is_identical_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
| static_scalar_value T_IS_NOT_IDENTICAL static_scalar_value { zend_ast_add_binary(&$$.u.constant, is_not_identical_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
| static_scalar_value T_IS_EQUAL static_scalar_value { zend_ast_add_binary(&$$.u.constant, is_equal_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
| static_scalar_value T_IS_NOT_EQUAL static_scalar_value { zend_ast_add_binary(&$$.u.constant, is_not_equal_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
| static_scalar_value '<' static_scalar_value { zend_ast_add_binary(&$$.u.constant, is_smaller_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
| static_scalar_value '>' static_scalar_value { zend_ast_add_binary(&$$.u.constant, is_smaller_function, &$3.u.constant, &$1.u.constant TSRMLS_CC); }
| static_scalar_value T_IS_SMALLER_OR_EQUAL static_scalar_value { zend_ast_add_binary(&$$.u.constant, is_smaller_or_equal_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
| static_scalar_value T_IS_GREATER_OR_EQUAL static_scalar_value { zend_ast_add_binary(&$$.u.constant, is_smaller_or_equal_function, &$3.u.constant, &$1.u.constant TSRMLS_CC); }
| static_scalar_value '?' ':' static_scalar_value { zend_ast_add_ternary(&$$.u.constant, ternary_function, &$1.u.constant, NULL, &$4.u.constant TSRMLS_CC); }
| static_scalar_value '?' static_scalar_value ':' static_scalar_value { zend_ast_add_ternary(&$$.u.constant, ternary_function, &$1.u.constant, &$3.u.constant, &$5.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 '+' static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_ADD, $1.u.ast, $3.u.ast); }
| static_scalar_value '-' static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_SUB, $1.u.ast, $3.u.ast); }
| static_scalar_value '*' static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_MUL, $1.u.ast, $3.u.ast); }
| static_scalar_value '/' static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_DIV, $1.u.ast, $3.u.ast); }
| static_scalar_value '%' static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_MOD, $1.u.ast, $3.u.ast); }
| '!' static_scalar_value { $$.u.ast = zend_ast_create_node1(ZEND_BOOL_NOT, $2.u.ast); }
| '~' static_scalar_value { $$.u.ast = zend_ast_create_node1(ZEND_BW_NOT, $2.u.ast); }
| static_scalar_value '|' static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_BW_OR, $1.u.ast, $3.u.ast); }
| static_scalar_value '&' static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_BW_AND, $1.u.ast, $3.u.ast); }
| static_scalar_value '^' static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_BW_XOR, $1.u.ast, $3.u.ast); }
| static_scalar_value T_SL static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_SL, $1.u.ast, $3.u.ast); }
| static_scalar_value T_SR static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_SR, $1.u.ast, $3.u.ast); }
| static_scalar_value '.' static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_CONCAT, $1.u.ast, $3.u.ast); }
| static_scalar_value T_LOGICAL_XOR static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_BOOL_XOR, $1.u.ast, $3.u.ast); }
| static_scalar_value T_LOGICAL_AND static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_BOOL_AND, $1.u.ast, $3.u.ast); }
| static_scalar_value T_LOGICAL_OR static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_BOOL_OR, $1.u.ast, $3.u.ast); }
| static_scalar_value T_BOOLEAN_AND static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_BOOL_AND, $1.u.ast, $3.u.ast); }
| static_scalar_value T_BOOLEAN_OR static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_BOOL_OR, $1.u.ast, $3.u.ast); }
| static_scalar_value T_IS_IDENTICAL static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_IS_IDENTICAL, $1.u.ast, $3.u.ast); }
| static_scalar_value T_IS_NOT_IDENTICAL static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_IS_NOT_IDENTICAL, $1.u.ast, $3.u.ast); }
| static_scalar_value T_IS_EQUAL static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_IS_EQUAL, $1.u.ast, $3.u.ast); }
| static_scalar_value T_IS_NOT_EQUAL static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_IS_NOT_EQUAL, $1.u.ast, $3.u.ast); }
| static_scalar_value '<' static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_IS_SMALLER, $1.u.ast, $3.u.ast); }
| static_scalar_value '>' static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_IS_SMALLER, $3.u.ast, $1.u.ast); }
| static_scalar_value T_IS_SMALLER_OR_EQUAL static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_IS_SMALLER_OR_EQUAL, $1.u.ast, $3.u.ast); }
| static_scalar_value T_IS_GREATER_OR_EQUAL static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_IS_SMALLER_OR_EQUAL, $3.u.ast, $1.u.ast); }
| static_scalar_value '?' ':' static_scalar_value { $$.u.ast = zend_ast_create_node3(ZEND_TERNARY, $1.u.ast, NULL, $4.u.ast); }
| static_scalar_value '?' static_scalar_value ':' static_scalar_value { $$.u.ast = zend_ast_create_node3(ZEND_TERNARY, $1.u.ast, $3.u.ast, $5.u.ast); }
| '+' static_scalar_value { $$.u.ast = zend_ast_create_node1(ZEND_UNARY_PLUS, $2.u.ast); }
| '-' static_scalar_value { $$.u.ast = zend_ast_create_node1(ZEND_UNARY_MINUS, $2.u.ast); }
| '(' static_scalar_value ')' { $$ = $2; }
;
-62
View File
@@ -1082,46 +1082,6 @@ ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
}
/* }}} */
ZEND_API int boolean_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
zval op1_copy, op2_copy;
long op1_lval;
if (Z_TYPE_P(op1) != IS_BOOL || Z_TYPE_P(op2) != IS_BOOL) {
ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_BOOL_AND);
zendi_convert_to_boolean(op1, op1_copy, result);
op1_lval = Z_LVAL_P(op1);
zendi_convert_to_boolean(op2, op2_copy, result);
} else {
op1_lval = Z_LVAL_P(op1);
}
ZVAL_BOOL(result, op1_lval & Z_LVAL_P(op2));
return SUCCESS;
}
/* }}} */
ZEND_API int boolean_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
zval op1_copy, op2_copy;
long op1_lval;
if (Z_TYPE_P(op1) != IS_BOOL || Z_TYPE_P(op2) != IS_BOOL) {
ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_BOOL_OR);
zendi_convert_to_boolean(op1, op1_copy, result);
op1_lval = Z_LVAL_P(op1);
zendi_convert_to_boolean(op2, op2_copy, result);
} else {
op1_lval = Z_LVAL_P(op1);
}
ZVAL_BOOL(result, op1_lval | Z_LVAL_P(op2));
return SUCCESS;
}
/* }}} */
ZEND_API int boolean_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */
{
zval op1_copy;
@@ -2363,28 +2323,6 @@ ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC) /* {{{ */
}
/* }}} */
#define PREVENT_DTOR_IF_REFCOUNT_1_AND_ASSIGN_TO_RESULT(var) \
*result = *var; \
if (Z_REFCOUNT_P(var) == 1) { \
Z_TYPE_P(var) = IS_NULL; \
}
ZEND_API int ternary_function(zval *result, zval *condition, zval *then, zval *if_not TSRMLS_DC) /* {{{ */
{
if (i_zend_is_true(condition)) {
if (then) {
PREVENT_DTOR_IF_REFCOUNT_1_AND_ASSIGN_TO_RESULT(then);
} else {
PREVENT_DTOR_IF_REFCOUNT_1_AND_ASSIGN_TO_RESULT(condition);
}
} else {
PREVENT_DTOR_IF_REFCOUNT_1_AND_ASSIGN_TO_RESULT(if_not);
}
return SUCCESS;
}
/* }}} */
/*
* Local variables:
* tab-width: 4
-4
View File
@@ -50,8 +50,6 @@ ZEND_API int mul_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
ZEND_API int div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
ZEND_API int mod_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
ZEND_API int boolean_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
ZEND_API int boolean_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
ZEND_API int boolean_not_function(zval *result, zval *op1 TSRMLS_DC);
ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC);
ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
@@ -378,8 +376,6 @@ ZEND_API int zend_atoi(const char *str, int str_len);
ZEND_API long zend_atol(const char *str, int str_len);
ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC);
ZEND_API int ternary_function(zval *result, zval *condition, zval *then, zval *if_not TSRMLS_DC);
END_EXTERN_C()
#define convert_to_ex_master(ppzv, lower_type, upper_type) \
+3 -5
View File
@@ -49,7 +49,7 @@ 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));
zend_ast_destroy(Z_AST_P(zvalue));
break;
case IS_OBJECT:
{
@@ -85,11 +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_CONSTANT_AST:
case IS_OBJECT:
case IS_RESOURCE:
zend_error(E_CORE_ERROR, "Internal zval's can't be arrays, objects or resources");
@@ -147,7 +145,7 @@ ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC)
}
break;
case IS_CONSTANT_AST:
ZEND_AST_ADD_REF(Z_AST_P(zvalue));
Z_AST_P(zvalue) = zend_ast_copy(Z_AST_P(zvalue));
break;
case IS_OBJECT:
{
-1
View File
@@ -5200,7 +5200,6 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST)
INIT_PZVAL_COPY(&c.value, val);
zval_copy_ctor(&c.value);
}
c.flags = CONST_CS; /* non persistent, case sensetive */
c.name = str_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
c.name_len = Z_STRLEN_P(name)+1;
-1
View File
@@ -4102,7 +4102,6 @@ static int ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCOD
INIT_PZVAL_COPY(&c.value, val);
zval_copy_ctor(&c.value);
}
c.flags = CONST_CS; /* non persistent, case sensetive */
c.name = str_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
c.name_len = Z_STRLEN_P(name)+1;
+56
View File
@@ -222,6 +222,52 @@ static void zend_destroy_property_info(zend_property_info *property_info)
}
}
#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
static zend_ast *zend_ast_clone(zend_ast *ast TSRMLS_DC)
{
int i;
zend_ast *node;
if (ast->kind == ZEND_CONST) {
node = emalloc(sizeof(zend_ast) + sizeof(zval));
node->kind = ZEND_CONST;
node->children = 0;
node->u.val = (zval*)(node + 1);
*node->u.val = *ast->u.val;
if ((Z_TYPE_P(ast->u.val) & IS_CONSTANT_TYPE_MASK) >= IS_ARRAY) {
switch ((Z_TYPE_P(ast->u.val) & IS_CONSTANT_TYPE_MASK)) {
case IS_STRING:
case IS_CONSTANT:
Z_STRVAL_P(node->u.val) = (char *) interned_estrndup(Z_STRVAL_P(ast->u.val), Z_STRLEN_P(ast->u.val));
break;
case IS_ARRAY:
case IS_CONSTANT_ARRAY:
if (ast->u.val->value.ht && ast->u.val->value.ht != &EG(symbol_table)) {
ALLOC_HASHTABLE(node->u.val->value.ht);
zend_hash_clone_zval(node->u.val->value.ht, ast->u.val->value.ht, 0);
}
break;
case IS_CONSTANT_AST:
Z_AST_P(node->u.val) = zend_ast_clone(Z_AST_P(ast->u.val) TSRMLS_CC);
break;
}
}
} else {
node = emalloc(sizeof(zend_ast) + sizeof(zend_ast*) * (ast->children - 1));
node->kind = ast->kind;
node->children = ast->children;
for (i = 0; i < ast->children; i++) {
if (ast->u.child[i]) {
node->u.child[i] = zend_ast_clone(ast->u.child[i] TSRMLS_CC);
} else {
node->u.child[i] = NULL;
}
}
}
return node;
}
#endif
static inline zval* zend_clone_zval(zval *src, int bind TSRMLS_DC)
{
zval *ret, **ret_ptr = NULL;
@@ -259,6 +305,11 @@ static inline zval* zend_clone_zval(zval *src, int bind TSRMLS_DC)
zend_hash_clone_zval(ret->value.ht, src->value.ht, 0);
}
break;
#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
case IS_CONSTANT_AST:
Z_AST_P(ret) = zend_ast_clone(Z_AST_P(ret) TSRMLS_CC);
break;
#endif
}
}
return ret;
@@ -376,6 +427,11 @@ static void zend_hash_clone_zval(HashTable *ht, HashTable *source, int bind)
zend_hash_clone_zval(ppz->value.ht, ((zval*)p->pDataPtr)->value.ht, 0);
}
break;
#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
case IS_CONSTANT_AST:
Z_AST_P(ppz) = zend_ast_clone(Z_AST_P(ppz) TSRMLS_CC);
break;
#endif
}
}
+29
View File
@@ -51,6 +51,7 @@
typedef void (*zend_persist_func_t)(void * TSRMLS_DC);
static void zend_persist_zval_ptr(zval **zp TSRMLS_DC);
static void zend_persist_zval(zval *z TSRMLS_DC);
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
static const Bucket *uninitialized_bucket = NULL;
@@ -138,6 +139,29 @@ static void zend_hash_persist(HashTable *ht, void (*pPersistElement)(void *pElem
#endif
}
#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
static zend_ast *zend_persist_ast(zend_ast *ast TSRMLS_DC)
{
int i;
zend_ast *node;
if (ast->kind == ZEND_CONST) {
node = zend_accel_memdup(ast, sizeof(zend_ast) + sizeof(zval));
node->u.val = (zval*)(node + 1);
zend_persist_zval(node->u.val TSRMLS_CC);
} else {
node = zend_accel_memdup(ast, sizeof(zend_ast) + sizeof(zend_ast*) * (ast->children - 1));
for (i = 0; i < ast->children; i++) {
if (node->u.child[i]) {
node->u.child[i] = zend_persist_ast(node->u.child[i] TSRMLS_CC);
}
}
}
efree(ast);
return node;
}
#endif
static void zend_persist_zval(zval *z TSRMLS_DC)
{
#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
@@ -154,6 +178,11 @@ static void zend_persist_zval(zval *z TSRMLS_DC)
zend_accel_store(z->value.ht, sizeof(HashTable));
zend_hash_persist(z->value.ht, (zend_persist_func_t) zend_persist_zval_ptr, sizeof(zval**) TSRMLS_CC);
break;
#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
case IS_CONSTANT_AST:
Z_AST_P(z) = zend_persist_ast(Z_AST_P(z) TSRMLS_CC);
break;
#endif
}
}
+27
View File
@@ -45,6 +45,7 @@
#endif
static uint zend_persist_zval_ptr_calc(zval **zp TSRMLS_DC);
static uint zend_persist_zval_calc(zval *z TSRMLS_DC);
static uint zend_hash_persist_calc(HashTable *ht, int (*pPersistElement)(void *pElement TSRMLS_DC), size_t el_size TSRMLS_DC)
{
@@ -91,6 +92,27 @@ static uint zend_hash_persist_calc(HashTable *ht, int (*pPersistElement)(void *p
RETURN_SIZE();
}
#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
static uint zend_persist_ast_calc(zend_ast *ast TSRMLS_DC)
{
int i;
START_SIZE();
if (ast->kind == ZEND_CONST) {
ADD_SIZE(sizeof(zend_ast) + sizeof(zval));
ADD_SIZE(zend_persist_zval_calc(ast->u.val TSRMLS_CC));
} else {
ADD_SIZE(sizeof(zend_ast) + sizeof(zend_ast*) * (ast->children - 1));
for (i = 0; i < ast->children; i++) {
if (ast->u.child[i]) {
ADD_SIZE(zend_persist_ast_calc(ast->u.child[i] TSRMLS_CC));
}
}
}
RETURN_SIZE();
}
#endif
static uint zend_persist_zval_calc(zval *z TSRMLS_DC)
{
START_SIZE();
@@ -109,6 +131,11 @@ static uint zend_persist_zval_calc(zval *z TSRMLS_DC)
ADD_DUP_SIZE(z->value.ht, sizeof(HashTable));
ADD_SIZE(zend_hash_persist_calc(z->value.ht, (int (*)(void* TSRMLS_DC)) zend_persist_zval_ptr_calc, sizeof(zval**) TSRMLS_CC));
break;
#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
case IS_CONSTANT_AST:
ADD_SIZE(zend_persist_ast_calc(Z_AST_P(z) TSRMLS_CC));
break;
#endif
}
RETURN_SIZE();
}