%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
| '&' 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); }
;
| 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; }
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;
}
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) {
/* 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;
#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
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); \
}
+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;
}
+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;
}
+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;
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);
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);
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);
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; \
return; \
}
+#define RETURN_UNSET() { \
+ return_value->type = IS_UNSET; \
+ return; \
+ }
+
#define RETURN_LONG(l) { \
return_value->type = IS_LONG; \
return_value->value.lval = l; \
#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; \
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");
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;
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);
}
}
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:
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: {
zval **param, *assignment_value;
if (zend_ptr_stack_get_arg(opline->op1.u.constant.value.lval, (void **) ¶m 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;
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;
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;
int result;
switch (op->type) {
+ case IS_UNSET:
+ result = 0;
+ break;
case IS_LONG:
case IS_BOOL:
case IS_RESOURCE:
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 */
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;
}
}
(holder).value.lval = (op)->value.lval; \
(holder).type = IS_LONG; \
(op) = &(holder); \
+ } else if ((op)->type==IS_UNSET) { \
+ (holder).type = IS_UNSET; \
+ (op) = &(holder); \
}
(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; \
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); \
long tmp;
switch (op->type) {
+ case IS_UNSET:
+ op->value.lval = 0;
+ break;
case IS_RESOURCE:
case IS_BOOL:
case IS_LONG:
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;
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;
}
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);
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:
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);
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:
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;
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);
* 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)
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;
}
case IS_LONG:
case IS_DOUBLE:
case IS_BOOL:
+ case IS_UNSET:
default:
return 1;
break;
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;
}
}