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:
+10
-10
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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; }
|
||||
;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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:
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user