summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/zend-parser.y5
-rw-r--r--Zend/zend-scanner.l4
-rw-r--r--Zend/zend.c7
-rw-r--r--Zend/zend.h11
-rw-r--r--Zend/zend_API.c32
-rw-r--r--Zend/zend_API.h15
-rw-r--r--Zend/zend_builtin_functions.c1
-rw-r--r--Zend/zend_compile.c4
-rw-r--r--Zend/zend_constants.c15
-rw-r--r--Zend/zend_execute.c62
-rw-r--r--Zend/zend_execute_API.c3
-rw-r--r--Zend/zend_operators.c58
-rw-r--r--Zend/zend_operators.h1
-rw-r--r--Zend/zend_variables.c14
14 files changed, 149 insertions, 83 deletions
diff --git a/Zend/zend-parser.y b/Zend/zend-parser.y
index 378ab4f276..246a988385 100644
--- a/Zend/zend-parser.y
+++ b/Zend/zend-parser.y
@@ -67,7 +67,7 @@
%left T_SL T_SR
%left '+' '-' '.'
%left '*' '/' '%'
-%right '!' '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST '@'
+%right '!' '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@'
%right '['
%nonassoc T_NEW
%token T_EXIT
@@ -294,12 +294,10 @@ non_empty_parameter_list:
| '&' T_VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$2, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_FORCE CLS_CC); }
| T_CONST T_VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$2, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_NONE CLS_CC); }
| T_VARIABLE '=' static_scalar { znode tmp; fetch_simple_variable(&tmp, &$1, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$3, BYREF_NONE CLS_CC); }
- | T_VARIABLE '=' T_UNSET { znode tmp; fetch_simple_variable(&tmp, &$1, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, NULL, BYREF_NONE CLS_CC); }
| non_empty_parameter_list ',' T_VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$3, 0 CLS_CC); $$=$1; $$.u.constant.value.lval++; do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_NONE CLS_CC); }
| non_empty_parameter_list ',' '&' T_VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$4, 0 CLS_CC); $$=$1; $$.u.constant.value.lval++; do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_FORCE CLS_CC); }
| non_empty_parameter_list ',' T_CONST T_VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$4, 0 CLS_CC); $$=$1; $$.u.constant.value.lval++; do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_NONE CLS_CC); }
| non_empty_parameter_list ',' T_VARIABLE '=' static_scalar { znode tmp; fetch_simple_variable(&tmp, &$3, 0 CLS_CC); $$=$1; $$.u.constant.value.lval++; do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$5, BYREF_NONE CLS_CC); }
- | non_empty_parameter_list ',' T_VARIABLE '=' T_UNSET { znode tmp; fetch_simple_variable(&tmp, &$3, 0 CLS_CC); $$=$1; $$.u.constant.value.lval++; do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, NULL, BYREF_NONE CLS_CC); }
;
@@ -444,6 +442,7 @@ expr_without_variable:
| T_ARRAY_CAST expr { do_cast(&$$, &$2, IS_ARRAY CLS_CC); }
| T_OBJECT_CAST expr { do_cast(&$$, &$2, IS_OBJECT CLS_CC); }
| T_BOOL_CAST expr { do_cast(&$$, &$2, IS_BOOL CLS_CC); }
+ | T_UNSET_CAST expr { do_cast(&$$, &$2, IS_UNSET CLS_CC); }
| T_EXIT exit_expr { do_exit(&$$, &$2 CLS_CC); }
| '@' { do_begin_silence(&$1 CLS_CC); } expr { do_end_silence(&$1 CLS_CC); $$ = $3; }
| scalar { $$ = $1; }
diff --git a/Zend/zend-scanner.l b/Zend/zend-scanner.l
index fea3149a79..42d9c90c85 100644
--- a/Zend/zend-scanner.l
+++ b/Zend/zend-scanner.l
@@ -879,6 +879,10 @@ ESCAPED_AND_WHITESPACE [\n\t\r #'.:;,()|^&+-/*=%!~<>?@]+
return T_BOOL_CAST;
}
+<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("unset"){TABS_AND_SPACES}")" {
+ return T_UNSET_CAST;
+}
+
<ST_IN_SCRIPTING>"eval" {
return T_EVAL;
}
diff --git a/Zend/zend.c b/Zend/zend.c
index 2aa5cbb0d1..5297d8ef9a 100644
--- a/Zend/zend.c
+++ b/Zend/zend.c
@@ -117,6 +117,9 @@ ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_cop
return;
}
switch (expr->type) {
+ case IS_UNSET:
+ expr_copy->value.str.len = 0;
+ expr_copy->value.str.val = empty_string;
case IS_BOOL:
#if 1
if (expr->value.lval) {
@@ -336,9 +339,7 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions)
/* This zval can be used to initialize allocate zval's to an uninit'ed value */
zval_used_for_init.is_ref = 0;
zval_used_for_init.refcount = 1;
- zval_used_for_init.type = IS_STRING;
- zval_used_for_init.value.str.val = undefined_variable_string;
- zval_used_for_init.value.str.len = 0;
+ zval_used_for_init.type = IS_UNSET;
#ifdef ZTS
global_constants_table = NULL;
diff --git a/Zend/zend.h b/Zend/zend.h
index b066b47e12..dff61e48d9 100644
--- a/Zend/zend.h
+++ b/Zend/zend.h
@@ -199,8 +199,12 @@ typedef struct _zend_utility_values {
#undef MAX
#define MAX(a,b) (((a)>(b))?(a):(b))
#define MIN(a,b) (((a)<(b))?(a):(b))
+#define ZEND_STRL(str) (str), (sizeof(str)-1)
+#define ZEND_STRS(str) (str), (sizeof(str)
+
/* data types */
+#define IS_UNSET 0
#define IS_LONG 1
#define IS_DOUBLE 2
#define IS_STRING 3
@@ -226,13 +230,12 @@ ZEND_API int zend_print_zval(zval *expr, int indent);
ZEND_API void zend_print_zval_r(zval *expr, int indent);
ZEND_API extern char *empty_string;
-ZEND_API extern char *undefined_variable_string;
-#define STR_FREE(ptr) if (ptr && ptr!=empty_string && ptr!=undefined_variable_string) { efree(ptr); }
-#define STR_FREE_REL(ptr) if (ptr && ptr!=empty_string && ptr!=undefined_variable_string) { efree_rel(ptr); }
+#define STR_FREE(ptr) if (ptr && ptr!=empty_string) { efree(ptr); }
+#define STR_FREE_REL(ptr) if (ptr && ptr!=empty_string) { efree_rel(ptr); }
#define STR_REALLOC(ptr, size) \
- if (ptr!=empty_string && ptr!=undefined_variable_string) { \
+ if (ptr!=empty_string) { \
ptr = (char *) erealloc(ptr, size); \
} else { \
ptr = (char *) emalloc(size); \
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 3ec6fac259..6822e299b2 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -242,6 +242,16 @@ ZEND_API inline int add_assoc_long(zval *arg, char *key, long n)
}
+ZEND_API inline int add_assoc_unset(zval *arg, char *key)
+{
+ zval *tmp;
+
+ ALLOC_ZVAL(tmp);
+ tmp->type = IS_UNSET;
+ INIT_PZVAL(tmp);
+ return zend_hash_update(arg->value.ht, key, strlen(key)+1, (void *) &tmp, sizeof(zval *), NULL);
+}
+
ZEND_API inline int add_assoc_bool(zval *arg, char *key, int b)
{
zval *tmp;
@@ -324,6 +334,17 @@ ZEND_API inline int add_index_long(zval *arg, uint index, long n)
}
+ZEND_API inline int add_index_unset(zval *arg, uint index)
+{
+ zval *tmp;
+
+ ALLOC_ZVAL(tmp);
+ tmp->type = IS_UNSET;
+ INIT_PZVAL(tmp);
+ return zend_hash_index_update(arg->value.ht, index, (void *) &tmp, sizeof(zval *), NULL);
+}
+
+
ZEND_API inline int add_index_bool(zval *arg, uint index, int b)
{
zval *tmp;
@@ -406,6 +427,17 @@ ZEND_API inline int add_next_index_long(zval *arg, long n)
}
+ZEND_API inline int add_next_index_unset(zval *arg)
+{
+ zval *tmp;
+
+ ALLOC_ZVAL(tmp);
+ tmp->type = IS_UNSET;
+ INIT_PZVAL(tmp);
+ return zend_hash_next_index_insert(arg->value.ht, &tmp, sizeof(zval *), NULL);
+}
+
+
ZEND_API inline int add_next_index_bool(zval *arg, int b)
{
zval *tmp;
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index 36d1c95469..8079b5be8d 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -98,6 +98,7 @@ ZEND_API int object_init_ex(zval *arg, zend_class_entry *ce);
ZEND_API int add_assoc_function(zval *arg, char *key,void (*function_ptr)(INTERNAL_FUNCTION_PARAMETERS));
ZEND_API int add_assoc_long(zval *arg, char *key, long n);
+ZEND_API int add_assoc_unset(zval *arg, char *key);
ZEND_API int add_assoc_bool(zval *arg, char *key, int b);
ZEND_API int add_assoc_resource(zval *arg, char *key, int r);
ZEND_API int add_assoc_double(zval *arg, char *key, double d);
@@ -105,6 +106,7 @@ ZEND_API int add_assoc_string(zval *arg, char *key, char *str, int duplicate);
ZEND_API int add_assoc_stringl(zval *arg, char *key, char *str, uint length, int duplicate);
ZEND_API int add_index_long(zval *arg, uint idx, long n);
+ZEND_API int add_index_unset(zval *arg, uint idx);
ZEND_API int add_index_bool(zval *arg, uint idx, int b);
ZEND_API int add_index_resource(zval *arg, uint idx, int r);
ZEND_API int add_index_double(zval *arg, uint idx, double d);
@@ -112,6 +114,7 @@ ZEND_API int add_index_string(zval *arg, uint idx, char *str, int duplicate);
ZEND_API int add_index_stringl(zval *arg, uint idx, char *str, uint length, int duplicate);
ZEND_API int add_next_index_long(zval *arg, long n);
+ZEND_API int add_next_index_unset(zval *arg);
ZEND_API int add_next_index_bool(zval *arg, int b);
ZEND_API int add_next_index_resource(zval *arg, int r);
ZEND_API int add_next_index_double(zval *arg, double d);
@@ -147,6 +150,9 @@ ZEND_API int zend_set_hash_symbol(zval *symbol, char *name, int name_length,
return_value->type = IS_BOOL; \
return_value->value.lval = b; \
}
+#define RETVAL_UNSET() { \
+ return_value->type = IS_UNSET; \
+ }
#define RETVAL_LONG(l) { \
return_value->type = IS_LONG; \
return_value->value.lval = l; \
@@ -183,6 +189,11 @@ ZEND_API int zend_set_hash_symbol(zval *symbol, char *name, int name_length,
return; \
}
+#define RETURN_UNSET() { \
+ return_value->type = IS_UNSET; \
+ return; \
+ }
+
#define RETURN_LONG(l) { \
return_value->type = IS_LONG; \
return_value->value.lval = l; \
@@ -211,10 +222,6 @@ ZEND_API int zend_set_hash_symbol(zval *symbol, char *name, int name_length,
#define RETURN_FALSE { RETVAL_FALSE; return; }
#define RETURN_TRUE { RETVAL_TRUE; return; }
-#define RETURN_SQLNULL RETURN_LONG(0)
-#define RETVAL_SQLNULL RETVAL_LONG(0)
-#define IS_SQLNULL(p) ((p)->type==IS_LONG && ((p)->value.lval == 0))
-
#define SET_VAR_STRING(n,v) { \
{ \
zval *var; \
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index 22fe6b1b0c..2303316450 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -325,6 +325,7 @@ ZEND_FUNCTION(define)
case IS_STRING:
case IS_BOOL:
case IS_RESOURCE:
+ case IS_UNSET:
break;
default:
zend_error(E_WARNING,"Constants may only evaluate to scalar values");
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 45e6c5372e..66176f2c72 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -741,10 +741,8 @@ void do_receive_arg(int op, znode *var, znode *offset, znode *initialization, un
opline->opcode = op;
opline->result = *var;
opline->op1 = *offset;
- if ((op == ZEND_RECV_INIT) && initialization) {
+ if ((op == ZEND_RECV_INIT)) {
opline->op2 = *initialization;
- } else {
- SET_UNUSED(opline->op2);
}
if (pass_type==BYREF_FORCE && !CG(active_op_array)->arg_types) {
int i;
diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c
index 1aec33130d..69d08c3428 100644
--- a/Zend/zend_constants.c
+++ b/Zend/zend_constants.c
@@ -118,22 +118,21 @@ void zend_register_standard_constants(ELS_D)
c.flags = CONST_PERSISTENT;
c.module_number = 0;
- c.name = zend_strndup("TRUE",4);
- c.name_len = 5;
+ c.name = zend_strndup(ZEND_STRL("TRUE"));
+ c.name_len = sizeof("TRUE");
c.value.value.lval = 1;
c.value.type = IS_BOOL;
zend_register_constant(&c ELS_CC);
- c.name = zend_strndup("FALSE",5);
- c.name_len = 6;
+ c.name = zend_strndup(ZEND_STRL("FALSE"));
+ c.name_len = sizeof("FALSE");
c.value.value.lval = 0;
c.value.type = IS_BOOL;
zend_register_constant(&c ELS_CC);
- c.name = zend_strndup("SQL_NULL",8);
- c.name_len = 9;
- c.value.value.lval = 0;
- c.value.type = IS_LONG;
+ c.name = zend_strndup(ZEND_STRL("NULL"));
+ c.name_len = sizeof("NULL");
+ c.value.type = IS_UNSET;
zend_register_constant(&c ELS_CC);
}
}
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 2087252d17..156a139cd5 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -656,7 +656,7 @@ static inline void zend_fetch_dimension_address(znode *result, znode *op1, znode
return;
}
- if (container->type == IS_STRING && container->value.str.len==0) {
+ if (container->type == IS_UNSET) {
switch (type) {
case BP_VAR_RW:
case BP_VAR_W:
@@ -695,36 +695,35 @@ static inline void zend_fetch_dimension_address(znode *result, znode *op1, znode
SEPARATE_ON_READ_OBJECT(*retval, type);
SELECTIVE_PZVAL_LOCK(**retval, result);
break;
+ case IS_UNSET:
+ /* for read-mode only */
+ *retval = &EG(uninitialized_zval_ptr);
+ SELECTIVE_PZVAL_LOCK(**retval, result);
+ FREE_OP(op2, free_op2);
+ break;
case IS_STRING: {
zval *offset;
- offset = get_zval_ptr(op2, Ts, &free_op2, BP_VAR_R);
+ zval tmp;
- if (container->value.str.val == undefined_variable_string) {
- /* for read-mode only */
- *retval = &EG(uninitialized_zval_ptr);
- SELECTIVE_PZVAL_LOCK(**retval, result);
- FREE_OP(op2, free_op2);
- } else {
- zval tmp;
+ offset = get_zval_ptr(op2, Ts, &free_op2, BP_VAR_R);
- if (offset->type != IS_LONG) {
- tmp = *offset;
- zval_copy_ctor(&tmp);
- convert_to_long(&tmp);
- offset = &tmp;
- }
- if (!container->is_ref && type!=BP_VAR_R && type!=BP_VAR_IS) {
- SEPARATE_ZVAL(container_ptr);
- }
- container = *container_ptr;
- Ts[result->u.var].EA.str = container;
- PZVAL_LOCK(container);
- Ts[result->u.var].EA.offset = offset->value.lval;
- Ts[result->u.var].EA.type = IS_STRING_OFFSET;
- FREE_OP(op2, free_op2);
- *retval = NULL;
- return;
+ if (offset->type != IS_LONG) {
+ tmp = *offset;
+ zval_copy_ctor(&tmp);
+ convert_to_long(&tmp);
+ offset = &tmp;
+ }
+ if (!container->is_ref && type!=BP_VAR_R && type!=BP_VAR_IS) {
+ SEPARATE_ZVAL(container_ptr);
}
+ container = *container_ptr;
+ Ts[result->u.var].EA.str = container;
+ PZVAL_LOCK(container);
+ Ts[result->u.var].EA.offset = offset->value.lval;
+ Ts[result->u.var].EA.type = IS_STRING_OFFSET;
+ FREE_OP(op2, free_op2);
+ *retval = NULL;
+ return;
}
break;
default: {
@@ -1720,12 +1719,6 @@ send_by_ref:
zval **param, *assignment_value;
if (zend_ptr_stack_get_arg(opline->op1.u.constant.value.lval, (void **) &param ELS_CC)==FAILURE) {
- if (opline->op2.op_type == IS_UNUSED) {
- if (opline->result.op_type == IS_VAR) {
- PZVAL_UNLOCK(*Ts[opline->result.u.var].var.ptr_ptr);
- }
- break;
- }
if (opline->op2.u.constant.type == IS_CONSTANT) {
zval *default_value;
zval tmp;
@@ -1949,6 +1942,9 @@ send_by_ref:
zendi_zval_copy_ctor(*result);
}
switch (opline->op2.u.constant.type) {
+ case IS_UNSET:
+ convert_to_unset(result);
+ break;
case IS_BOOL:
convert_to_boolean(result);
break;
@@ -2161,7 +2157,7 @@ send_by_ref:
isset = 1;
}
} else if (*var==EG(uninitialized_zval_ptr)
- || ((*var)->type == IS_STRING && (*var)->value.str.val == undefined_variable_string)) {
+ || ((*var)->type == IS_UNSET)) {
isset = 0;
} else {
isset = 1;
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 88662d3b1e..7bcd211e96 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -225,6 +225,9 @@ ZEND_API inline int i_zend_is_true(zval *op)
int result;
switch (op->type) {
+ case IS_UNSET:
+ result = 0;
+ break;
case IS_LONG:
case IS_BOOL:
case IS_RESOURCE:
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index 11064c0087..b4a007c60c 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -45,9 +45,6 @@ ZEND_API void convert_scalar_to_number(zval *op)
case IS_DOUBLE:
case IS_LONG:
break;
- case IS_BOOL:
- op->type = IS_LONG;
- break;
#if WITH_BCMATH
case IS_BC:
op->type = IS_DOUBLE; /* may have lost significant digits */
@@ -61,6 +58,9 @@ ZEND_API void convert_scalar_to_number(zval *op)
STR_FREE(strval);
} else if (op->type==IS_BOOL || op->type==IS_RESOURCE) {
op->type = IS_LONG;
+ } else if (op->type==IS_UNSET) {
+ op->type = IS_LONG;
+ op->value.lval = 0;
}
}
@@ -85,6 +85,9 @@ ZEND_API void convert_scalar_to_number(zval *op)
(holder).value.lval = (op)->value.lval; \
(holder).type = IS_LONG; \
(op) = &(holder); \
+ } else if ((op)->type==IS_UNSET) { \
+ (holder).type = IS_UNSET; \
+ (op) = &(holder); \
}
@@ -98,6 +101,9 @@ ZEND_API void convert_scalar_to_number(zval *op)
(op) = &(holder); \
} else if ((op)->type != IS_LONG) { \
switch ((op)->type) { \
+ case IS_UNSET: \
+ (holder).value.lval = 0; \
+ break; \
case IS_DOUBLE: \
(holder).value.lval = (long) (op)->value.dval; \
break; \
@@ -125,6 +131,9 @@ ZEND_API void convert_scalar_to_number(zval *op)
convert_to_boolean(op); \
} else if ((op)->type != IS_BOOL) { \
switch ((op)->type) { \
+ case IS_UNSET: \
+ (holder).value.lval = 0; \
+ break; \
case IS_RESOURCE: \
case IS_LONG: \
(holder).value.lval = ((op)->value.lval ? 1 : 0); \
@@ -167,6 +176,9 @@ ZEND_API void convert_to_long_base(zval *op, int base)
long tmp;
switch (op->type) {
+ case IS_UNSET:
+ op->value.lval = 0;
+ break;
case IS_RESOURCE:
case IS_BOOL:
case IS_LONG:
@@ -206,11 +218,13 @@ ZEND_API void convert_to_double(zval *op)
double tmp;
switch (op->type) {
+ case IS_UNSET:
+ op->value.dval = 0.0;
+ break;
case IS_RESOURCE:
case IS_BOOL:
case IS_LONG:
op->value.dval = (double) op->value.lval;
- op->type = IS_DOUBLE;
break;
case IS_DOUBLE:
break;
@@ -218,28 +232,32 @@ ZEND_API void convert_to_double(zval *op)
strval = op->value.str.val;
op->value.dval = strtod(strval, NULL);
- op->type = IS_DOUBLE;
STR_FREE(strval);
break;
case IS_ARRAY:
tmp = (zend_hash_num_elements(op->value.ht)?1:0);
zval_dtor(op);
op->value.dval = tmp;
- op->type = IS_DOUBLE;
break;
case IS_OBJECT:
tmp = (zend_hash_num_elements(op->value.obj.properties)?1:0);
zval_dtor(op);
op->value.dval = tmp;
- op->type = IS_DOUBLE;
break;
default:
zend_error(E_WARNING, "Cannot convert to real value (type=%d)", op->type);
zval_dtor(op);
op->value.dval = 0;
- op->type = IS_DOUBLE;
break;
}
+ op->type = IS_DOUBLE;
+}
+
+
+ZEND_API void convert_to_unset(zval *op)
+{
+ zval_dtor(op);
+ op->type = IS_UNSET;
}
@@ -251,6 +269,9 @@ ZEND_API void convert_to_boolean(zval *op)
switch (op->type) {
case IS_BOOL:
break;
+ case IS_UNSET:
+ op->value.lval = 0;
+ break;
case IS_RESOURCE:
case IS_LONG:
op->value.lval = (op->value.lval ? 1 : 0);
@@ -295,6 +316,10 @@ ZEND_API void convert_to_string(zval *op)
ELS_FETCH();
switch (op->type) {
+ case IS_UNSET:
+ op->value.str.val = empty_string;
+ op->value.str.len = 0;
+ break;
case IS_STRING:
break;
case IS_BOOL:
@@ -893,6 +918,7 @@ ZEND_API int compare_function(zval *result, zval *op1, zval *op2)
result->value.lval = op1->value.lval - op2->value.lval;
return SUCCESS;
}
+
zendi_convert_scalar_to_number(op1, op1_copy, result);
zendi_convert_scalar_to_number(op2, op2_copy, result);
@@ -924,6 +950,10 @@ ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2)
return SUCCESS;
}
switch (op1->type) {
+ case IS_UNSET:
+ result->value.lval = (op2->type==IS_UNSET);
+ return SUCCESS;
+ break;
case IS_BOOL:
case IS_LONG:
case IS_RESOURCE:
@@ -1120,14 +1150,12 @@ ZEND_API int increment_function(zval *op1)
case IS_DOUBLE:
op1->value.dval = op1->value.dval + 1;
break;
+ case IS_UNSET:
+ op1->value.lval = 1;
+ op1->type = IS_LONG;
+ break;
case IS_STRING: /* Perl style string increment */
- if (op1->value.str.len==0) { /* consider as 0 */
- STR_FREE(op1->value.str.val);
- op1->value.lval = 1;
- op1->type = IS_LONG;
- } else {
- increment_string(op1);
- }
+ increment_string(op1);
break;
default:
return FAILURE;
diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h
index 727d1c9d21..a4378305b8 100644
--- a/Zend/zend_operators.h
+++ b/Zend/zend_operators.h
@@ -56,6 +56,7 @@ ZEND_API void convert_scalar_to_number(zval *op);
ZEND_API void convert_to_string(zval *op);
ZEND_API void convert_to_long(zval *op);
ZEND_API void convert_to_long_base(zval *op, int base);
+ZEND_API void convert_to_unset(zval *op);
ZEND_API void convert_to_boolean(zval *op);
ZEND_API void convert_to_array(zval *op);
ZEND_API void convert_to_object(zval *op);
diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c
index f2cb9a1388..71a9861345 100644
--- a/Zend/zend_variables.c
+++ b/Zend/zend_variables.c
@@ -32,8 +32,6 @@ ZEND_API char *empty_string = ""; /* in order to save emalloc() and efree() time
* The macro STR_FREE() will not efree() it.
*/
-ZEND_API char *undefined_variable_string = "\0";
-
/* this function MUST set the value for the variable to an empty string */
/* and empty strings must be evaluated as FALSE */
ZEND_API inline void var_reset(zval *var)
@@ -50,9 +48,7 @@ ZEND_API inline void var_reset(zval *var)
ZEND_API inline void var_uninit(zval *var)
{
- var->type = IS_STRING;
- var->value.str.val = undefined_variable_string;
- var->value.str.len = 0;
+ var->type = IS_UNSET;
}
@@ -86,6 +82,7 @@ ZEND_API int _zval_dtor(zval *zvalue ZEND_FILE_LINE_DC)
case IS_LONG:
case IS_DOUBLE:
case IS_BOOL:
+ case IS_UNSET:
default:
return 1;
break;
@@ -118,15 +115,12 @@ ZEND_API int _zval_copy_ctor(zval *zvalue ZEND_FILE_LINE_DC)
break;
case IS_BOOL:
case IS_LONG:
+ case IS_UNSET:
break;
case IS_STRING:
if (zvalue->value.str.val) {
if (zvalue->value.str.len==0) {
- if (zvalue->value.str.val==undefined_variable_string) {
- zvalue->value.str.val = undefined_variable_string;
- } else {
- zvalue->value.str.val = empty_string;
- }
+ zvalue->value.str.val = empty_string;
return SUCCESS;
}
}