Browse Source

- For Andrei. Implement references in array() initializations

experimetnal/RETURN_REF_PATCH
Andi Gutmans 27 years ago
parent
commit
03d354dcf9
  1. 15
      Zend/zend-parser.y
  2. 6
      Zend/zend_compile.c
  3. 4
      Zend/zend_compile.h
  4. 46
      Zend/zend_execute.c

15
Zend/zend-parser.y

@ -602,18 +602,21 @@ assignment_list_element:
array_pair_list:
/* empty */ { do_init_array(&$$, NULL, NULL CLS_CC); }
/* empty */ { do_init_array(&$$, NULL, NULL, 0 CLS_CC); }
| non_empty_array_pair_list { $$ = $1; }
;
non_empty_array_pair_list:
non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr { do_add_array_element(&$$, &$5, &$3 CLS_CC); }
| non_empty_array_pair_list ',' expr { do_add_array_element(&$$, &$3, NULL CLS_CC); }
| expr T_DOUBLE_ARROW expr { do_init_array(&$$, &$3, &$1 CLS_CC); }
| expr { do_init_array(&$$, &$1, NULL CLS_CC); }
non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr { do_add_array_element(&$$, &$5, &$3, 0 CLS_CC); }
| non_empty_array_pair_list ',' expr { do_add_array_element(&$$, &$3, NULL, 0 CLS_CC); }
| expr T_DOUBLE_ARROW expr { do_init_array(&$$, &$3, &$1, 0 CLS_CC); }
| expr { do_init_array(&$$, &$1, NULL, 0 CLS_CC); }
| non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_cvar { do_add_array_element(&$$, &$6, &$3, 1 CLS_CC); }
| non_empty_array_pair_list ',' '&' w_cvar { do_add_array_element(&$$, &$4, NULL, 1 CLS_CC); }
| expr T_DOUBLE_ARROW '&' w_cvar { do_init_array(&$$, &$4, &$1, 1 CLS_CC); }
| '&' w_cvar { do_init_array(&$$, &$2, NULL, 1 CLS_CC); }
;
encaps_list:
encaps_list encaps_var { do_end_variable_parse(BP_VAR_R, 0 CLS_CC); do_add_variable(&$$, &$1, &$2 CLS_CC); }
| encaps_list T_STRING { do_add_string(&$$, &$1, &$2 CLS_CC); }

6
Zend/zend_compile.c

@ -1602,7 +1602,7 @@ void do_shell_exec(znode *result, znode *cmd CLS_DC)
void do_init_array(znode *result, znode *expr, znode *offset CLS_DC)
void do_init_array(znode *result, znode *expr, znode *offset, int is_ref CLS_DC)
{
zend_op *opline = get_next_op(CG(active_op_array) CLS_CC);
@ -1621,10 +1621,11 @@ void do_init_array(znode *result, znode *expr, znode *offset CLS_DC)
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
}
opline->extended_value = is_ref;
}
void do_add_array_element(znode *result, znode *expr, znode *offset CLS_DC)
void do_add_array_element(znode *result, znode *expr, znode *offset, int is_ref CLS_DC)
{
zend_op *opline = get_next_op(CG(active_op_array) CLS_CC);
@ -1636,6 +1637,7 @@ void do_add_array_element(znode *result, znode *expr, znode *offset CLS_DC)
} else {
SET_UNUSED(opline->op2);
}
opline->extended_value = is_ref;
}

4
Zend/zend_compile.h

@ -304,8 +304,8 @@ void do_fetch_constant(znode *result, znode *constant_name, int mode CLS_DC);
void do_shell_exec(znode *result, znode *cmd CLS_DC);
void do_init_array(znode *result, znode *expr, znode *offset CLS_DC);
void do_add_array_element(znode *result, znode *expr, znode *offset CLS_DC);
void do_init_array(znode *result, znode *expr, znode *offset, int is_ref CLS_DC);
void do_add_array_element(znode *result, znode *expr, znode *offset, int is_ref CLS_DC);
void do_add_static_array_element(znode *result, znode *offset, znode *expr);
void do_list_init();
void do_list_end(znode *result, znode *expr CLS_DC);

46
Zend/zend_execute.c

@ -1804,43 +1804,57 @@ send_by_ref:
case ZEND_INIT_ARRAY:
case ZEND_ADD_ARRAY_ELEMENT: {
zval *array_ptr = &Ts[opline->result.u.var].tmp_var;
zval *expr=get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R);
zval *expr_ptr, **expr_ptr_ptr;
zval *offset=get_zval_ptr(&opline->op2, Ts, &EG(free_op2), BP_VAR_R);
if (opline->extended_value) {
expr_ptr_ptr=get_zval_ptr_ptr(&opline->op1, Ts, BP_VAR_R);
expr_ptr = *expr_ptr_ptr;
} else {
expr_ptr=get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R);
}
if (opline->opcode==ZEND_INIT_ARRAY) {
array_init(array_ptr);
if (!expr) {
if (!expr_ptr) {
break;
}
}
if (EG(free_op1)) { /* temporary variable */
if (opline->op1.op_type == IS_TMP_VAR) { /* temporary variable */
zval *new_expr = (zval *) emalloc(sizeof(zval));
*new_expr = *expr;
expr = new_expr;
INIT_PZVAL(expr);
*new_expr = *expr_ptr;
expr_ptr = new_expr;
INIT_PZVAL(expr_ptr);
} else {
if (PZVAL_IS_REF(expr)) {
if (opline->extended_value) {
if (!PZVAL_IS_REF(expr_ptr)) {
SEPARATE_ZVAL(expr_ptr_ptr);
expr_ptr = *expr_ptr_ptr;
expr_ptr->EA.is_ref = 1;
}
expr_ptr->refcount++;
} else if (PZVAL_IS_REF(expr_ptr)) {
zval *new_expr = (zval *) emalloc(sizeof(zval));
*new_expr = *expr;
expr = new_expr;
zendi_zval_copy_ctor(*expr);
INIT_PZVAL(expr);
*new_expr = *expr_ptr;
expr_ptr = new_expr;
zendi_zval_copy_ctor(*expr_ptr);
INIT_PZVAL(expr_ptr);
} else {
expr->refcount++;
expr_ptr->refcount++;
}
}
if (offset) {
switch(offset->type) {
case IS_DOUBLE:
zend_hash_index_update(array_ptr->value.ht, (long) offset->value.lval, &expr, sizeof(zval *), NULL);
zend_hash_index_update(array_ptr->value.ht, (long) offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_LONG:
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr, sizeof(zval *), NULL);
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
zend_hash_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr, sizeof(zval *), NULL);
zend_hash_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
break;
default:
/* do nothing */
@ -1848,7 +1862,7 @@ send_by_ref:
}
FREE_OP(&opline->op2, EG(free_op2));
} else {
zend_hash_next_index_insert(array_ptr->value.ht, &expr, sizeof(zval *), NULL);
zend_hash_next_index_insert(array_ptr->value.ht, &expr_ptr, sizeof(zval *), NULL);
}
}
break;

Loading…
Cancel
Save