Index: tests/lang/040.phpt =================================================================== RCS file: tests/lang/040.phpt diff -N tests/lang/040.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ tests/lang/040.phpt 31 Aug 2004 23:17:10 -0000 @@ -0,0 +1,90 @@ +--TEST-- +ifsetor +--FILE-- +v, 'default')); +var_dump(ifsetor($o->w, 'default')); +?> +--EXPECTF-- +string(7) "default" +int(42) +string(5) "Hello" +string(1) "H" +string(5) "Hello" +string(1) "H" +string(1) "o" +string(7) "default" +string(7) "default" +string(0) "" +string(7) "default" +array(0) { +} +string(7) "default" +array(1) { + [0]=> + int(1) +} +int(1) +string(7) "default" +array(0) { +} +string(7) "default" +array(1) { + [0]=> + array(1) { + [0]=> + int(42) + } +} +array(1) { + [0]=> + int(42) +} +int(42) +string(7) "default" +object(Test)#%d (1) { + ["v"]=> + int(123) +} +int(123) +string(7) "default" Index: Zend/zend_compile.c =================================================================== RCS file: /repository/ZendEngine2/zend_compile.c,v retrieving revision 1.585 diff -u -p -d -r1.585 zend_compile.c --- Zend/zend_compile.c 29 Aug 2004 13:28:03 -0000 1.585 +++ Zend/zend_compile.c 31 Aug 2004 23:17:11 -0000 @@ -3224,13 +3224,41 @@ void zend_do_isset_or_isempty(int type, last_op->opcode = ZEND_ISSET_ISEMPTY_PROP_OBJ; break; } - last_op->result.op_type = IS_TMP_VAR; + last_op->result.op_type = (type == ZEND_IFSETOR) ? IS_VAR : IS_TMP_VAR; last_op->extended_value = type; *result = last_op->result; } +void zend_do_jmp_set(znode *result, znode *value, znode *jmp_token TSRMLS_DC) +{ + int op_number = get_next_op_number(CG(active_op_array)); + zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); + + opline->opcode = ZEND_JMP_SET; + opline->result.op_type = IS_TMP_VAR; + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + opline->op1 = *value; + SET_UNUSED(opline->op2); + + *result = opline->result; + jmp_token->u.opline_num = op_number; +} + + +void zend_do_end_ifsetor(znode *result, znode *value, znode *jmp_token, znode *default_value TSRMLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); + + CG(active_op_array)->opcodes[jmp_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array)); + + opline->opcode = ZEND_QM_ASSIGN; + opline->result = *result; + opline->op1 = *default_value; + SET_UNUSED(opline->op2); +} + void zend_do_instanceof(znode *result, znode *expr, znode *class_znode, int type TSRMLS_DC) { zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); Index: Zend/zend_compile.h =================================================================== RCS file: /repository/ZendEngine2/zend_compile.h,v retrieving revision 1.289 diff -u -p -d -r1.289 zend_compile.h --- Zend/zend_compile.h 19 Aug 2004 20:03:06 -0000 1.289 +++ Zend/zend_compile.h 31 Aug 2004 23:17:12 -0000 @@ -444,6 +444,8 @@ void zend_do_include_or_eval(int type, z void zend_do_unset(znode *variable TSRMLS_DC); void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC); +void zend_do_jmp_set(znode *result, znode *value, znode *jmp_token TSRMLS_DC); +void zend_do_end_ifsetor(znode *result, znode *value, znode *jmp_token, znode *default_value TSRMLS_DC); void zend_do_instanceof(znode *result, znode *expr, znode *class_znode, int type TSRMLS_DC); @@ -713,6 +715,8 @@ int zendlex(znode *zendlval TSRMLS_DC); #define ZEND_HANDLE_EXCEPTION 149 +#define ZEND_JMP_SET 150 + /* end of block */ /* END: OPCODES */ @@ -778,6 +782,7 @@ int zendlex(znode *zendlval TSRMLS_DC); #define ZEND_ISSET (1<<0) #define ZEND_ISEMPTY (1<<1) +#define ZEND_IFSETOR (1<<2) #define ZEND_CT (1<<0) #define ZEND_RT (1<<1) Index: Zend/zend_execute.c =================================================================== RCS file: /repository/ZendEngine2/zend_execute.c,v retrieving revision 1.671 diff -u -p -d -r1.671 zend_execute.c --- Zend/zend_execute.c 30 Aug 2004 08:57:40 -0000 1.671 +++ Zend/zend_execute.c 31 Aug 2004 23:17:13 -0000 @@ -4256,6 +4256,33 @@ int zend_fe_fetch_handler(ZEND_OPCODE_HA } +int zend_jmp_set_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *opline = EX(opline); + zend_free_op free_op1; + zval **val = EX_T(opline->op1.u.var).var.ptr_ptr; + + if (val && Z_TYPE_PP(val) != IS_NULL) { + val = get_zval_ptr_ptr(&opline->op1, EX(Ts), &free_op1, BP_VAR_R); + EX_T(opline->result.u.var).tmp_var = **val; + zendi_zval_copy_ctor(EX_T(opline->result.u.var).tmp_var); + FREE_OP(free_op1); + +#if DEBUG_ZEND>=2 + printf("Jumping to %d\n", opline->op2.u.opline_num); +#endif + SET_OPCODE(EX(opline)->op2.u.jmp_addr); + return 0; + } else { + if (val) { + zval_ptr_dtor(EX_T(opline->op1.u.var).var.ptr_ptr); + } + } + + NEXT_OPCODE(); +} + + int zend_jmp_no_ctor_handler(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -4313,10 +4340,9 @@ int zend_isset_isempty_var_handler(ZEND_ } } - EX_T(opline->result.u.var).tmp_var.type = IS_BOOL; - switch (opline->extended_value) { case ZEND_ISSET: + EX_T(opline->result.u.var).tmp_var.type = IS_BOOL; if (isset && Z_TYPE_PP(value) == IS_NULL) { EX_T(opline->result.u.var).tmp_var.value.lval = 0; } else { @@ -4324,12 +4350,23 @@ int zend_isset_isempty_var_handler(ZEND_ } break; case ZEND_ISEMPTY: + EX_T(opline->result.u.var).tmp_var.type = IS_BOOL; if (!isset || !zend_is_true(*value)) { EX_T(opline->result.u.var).tmp_var.value.lval = 1; } else { EX_T(opline->result.u.var).tmp_var.value.lval = 0; } break; + case ZEND_IFSETOR: + if (isset) { + EX_T(opline->result.u.var).var.ptr_ptr = value; + PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); + AI_USE_PTR(EX_T(opline->result.u.var).var); + } else { + EX_T(opline->result.u.var).var.ptr_ptr = NULL; + AI_USE_PTR(EX_T(opline->result.u.var).var); + } + break; } if (varname == &tmp) { @@ -4389,6 +4426,7 @@ static int zend_isset_isempty_dim_prop_o } switch (opline->extended_value) { + case ZEND_IFSETOR: case ZEND_ISSET: if (isset && Z_TYPE_PP(value) == IS_NULL) { result = 0; @@ -4410,6 +4448,19 @@ static int zend_isset_isempty_dim_prop_o } else { result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC); } + if (result && opline->extended_value == ZEND_IFSETOR) { + if (prop_dim) { + EX_T(opline->result.u.var).var.ptr = Z_OBJ_HT_P(*container)->read_property(*container, offset, BP_VAR_R TSRMLS_CC); + } else { + EX_T(opline->result.u.var).var.ptr = Z_OBJ_HT_P(*container)->read_dimension(*container, offset, BP_VAR_R TSRMLS_CC); + } + EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; + + FREE_OP(free_op2); + FREE_OP_VAR_PTR(free_op1); + + NEXT_OPCODE(); + } } else if ((*container)->type == IS_STRING) { /* string offsets */ switch (opline->extended_value) { case ZEND_ISSET: @@ -4422,19 +4473,44 @@ static int zend_isset_isempty_dim_prop_o result = 1; } break; + case ZEND_IFSETOR: + if ((int)offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) { + zval *value; + + MAKE_STD_ZVAL(value); + ZVAL_STRINGL(value, Z_STRVAL_PP(container)+offset->value.lval, 1, 1); + EX_T(opline->result.u.var).var.ptr = value; + EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; + + FREE_OP(free_op2); + FREE_OP_VAR_PTR(free_op1); + + NEXT_OPCODE(); + } + break; } } } - EX_T(opline->result.u.var).tmp_var.type = IS_BOOL; - switch (opline->extended_value) { case ZEND_ISSET: + EX_T(opline->result.u.var).tmp_var.type = IS_BOOL; EX_T(opline->result.u.var).tmp_var.value.lval = result; break; case ZEND_ISEMPTY: + EX_T(opline->result.u.var).tmp_var.type = IS_BOOL; EX_T(opline->result.u.var).tmp_var.value.lval = !result; break; + case ZEND_IFSETOR: + if (result) { + EX_T(opline->result.u.var).var.ptr_ptr = value; + PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); + AI_USE_PTR(EX_T(opline->result.u.var).var); + } else { + EX_T(opline->result.u.var).var.ptr_ptr = NULL; + AI_USE_PTR(EX_T(opline->result.u.var).var); + } + break; } FREE_OP(free_op2); @@ -4455,6 +4531,7 @@ int zend_isset_isempty_prop_obj_handler( return zend_isset_isempty_dim_prop_obj_handler(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } + int zend_exit_handler(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -4847,6 +4924,7 @@ void zend_init_opcodes_handlers() zend_opcode_handlers[ZEND_HANDLE_EXCEPTION] = zend_handle_exception_handler; + zend_opcode_handlers[ZEND_JMP_SET] = zend_jmp_set_handler; } /* Index: Zend/zend_language_parser.y =================================================================== RCS file: /repository/ZendEngine2/zend_language_parser.y,v retrieving revision 1.148 diff -u -p -d -r1.148 zend_language_parser.y --- Zend/zend_language_parser.y 2 Aug 2004 16:38:09 -0000 1.148 +++ Zend/zend_language_parser.y 31 Aug 2004 23:17:14 -0000 @@ -142,6 +142,7 @@ %token T_DOLLAR_OPEN_CURLY_BRACES %token T_CURLY_OPEN %token T_PAAMAYIM_NEKUDOTAYIM +%token T_IFSETOR %% /* Rules */ @@ -893,6 +894,8 @@ encaps_var_offset: internal_functions_in_yacc: T_ISSET '(' isset_variables ')' { $$ = $3; } | T_EMPTY '(' variable ')' { zend_do_isset_or_isempty(ZEND_ISEMPTY, &$$, &$3 TSRMLS_CC); } + | T_IFSETOR '(' variable ',' { zend_do_isset_or_isempty(ZEND_IFSETOR, &$1, &$3 TSRMLS_CC); zend_do_jmp_set(&$1, &$1, &$4 TSRMLS_CC); } + expr ')' { zend_do_end_ifsetor(&$$, &$1, &$4, &$6 TSRMLS_CC); } | T_INCLUDE expr { zend_do_include_or_eval(ZEND_INCLUDE, &$$, &$2 TSRMLS_CC); } | T_INCLUDE_ONCE expr { zend_do_include_or_eval(ZEND_INCLUDE_ONCE, &$$, &$2 TSRMLS_CC); } | T_EVAL '(' expr ')' { zend_do_include_or_eval(ZEND_EVAL, &$$, &$3 TSRMLS_CC); } Index: Zend/zend_language_scanner.l =================================================================== RCS file: /repository/ZendEngine2/zend_language_scanner.l,v retrieving revision 1.115 diff -u -p -d -r1.115 zend_language_scanner.l --- Zend/zend_language_scanner.l 2 Aug 2004 16:38:09 -0000 1.115 +++ Zend/zend_language_scanner.l 31 Aug 2004 23:17:14 -0000 @@ -991,6 +991,10 @@ NEWLINE ("\r"|"\n"|"\r\n") return T_GLOBAL; } +"ifsetor" { + return T_IFSETOR; +} + "isset" { return T_ISSET; } Index: Zend/zend_opcode.c =================================================================== RCS file: /repository/ZendEngine2/zend_opcode.c,v retrieving revision 1.105 diff -u -p -d -r1.105 zend_opcode.c --- Zend/zend_opcode.c 29 Jul 2004 17:45:31 -0000 1.105 +++ Zend/zend_opcode.c 31 Aug 2004 23:17:15 -0000 @@ -358,6 +358,7 @@ int pass_two(zend_op_array *op_array TSR case ZEND_JMPNZ: case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: + case ZEND_JMP_SET: opline->op2.u.jmp_addr = &op_array->opcodes[opline->op2.u.opline_num]; break; }