Skip to content

Commit

Permalink
- Initial support for _clone()
Browse files Browse the repository at this point in the history
  • Loading branch information
Andi Gutmans committed Dec 26, 2001
1 parent e72d606 commit 2ce4b47
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 5 deletions.
26 changes: 24 additions & 2 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -879,7 +879,7 @@ int zend_do_begin_function_call(znode *function_name TSRMLS_DC)



void zend_do_begin_method_call(znode *object, znode *function_name TSRMLS_DC)
void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC)
{
zend_op *last_op;
int last_op_number;
Expand All @@ -890,8 +890,18 @@ void zend_do_begin_method_call(znode *object, znode *function_name TSRMLS_DC)

last_op_number = get_next_op_number(CG(active_op_array))-1;
last_op = &CG(active_op_array)->opcodes[last_op_number];

if ((last_op->op2.op_type == IS_CONST) && (last_op->op2.u.constant.value.str.len == sizeof("_clone")-1)
&& !memcmp(last_op->op2.u.constant.value.str.val, "_clone", sizeof("_clone"))) {
last_op->opcode = ZEND_CLONE;
left_bracket->u.constant.value.lval = ZEND_CLONE;
zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
zend_do_extended_fcall_begin(TSRMLS_C);
return;
}
last_op->opcode = ZEND_INIT_FCALL_BY_NAME;
last_op->extended_value = ZEND_MEMBER_FUNC_CALL;
left_bracket->u.constant.value.lval = ZEND_INIT_FCALL_BY_NAME;

/*opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_INIT_FCALL_BY_NAME;
Expand Down Expand Up @@ -1004,8 +1014,20 @@ void zend_do_begin_class_member_function_call(znode *class_name, znode *function

void zend_do_end_function_call(znode *function_name, znode *result, znode *argument_list, int is_method, int is_dynamic_fcall TSRMLS_DC)
{
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
zend_op *opline;

if (is_method && function_name && function_name->u.constant.value.lval == ZEND_CLONE) {
if (argument_list->u.constant.value.lval > 0) {
zend_error(E_ERROR, "Can't pass arguments to _clone()");
}
/* FIXME: throw_list */
zend_stack_del_top(&CG(function_call_stack));
*result = CG(active_op_array)->opcodes[get_next_op_number(CG(active_op_array))-1].result;
return;
}

opline = get_next_op(CG(active_op_array) TSRMLS_CC);

if (!is_method && !is_dynamic_fcall && function_name->op_type==IS_CONST) {
opline->opcode = ZEND_DO_FCALL;
opline->op1 = *function_name;
Expand Down
4 changes: 3 additions & 1 deletion Zend/zend_compile.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
void zend_do_end_function_declaration(znode *function_token TSRMLS_DC);
void zend_do_receive_arg(int op, znode *var, znode *offset, znode *initialization, unsigned char pass_type TSRMLS_DC);
int zend_do_begin_function_call(znode *function_name TSRMLS_DC);
void zend_do_begin_method_call(znode *object, znode *function_name TSRMLS_DC);
void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC);
void zend_do_begin_dynamic_function_call(znode *function_name TSRMLS_DC);
void do_fetch_class(znode *result, znode *class_entry, znode *class_name TSRMLS_DC);
void do_fetch_class_name(znode *result, znode *class_entry, znode *class_name TSRMLS_DC);
Expand Down Expand Up @@ -542,6 +542,8 @@ int zendlex(znode *zendlval TSRMLS_DC);

#define ZEND_NAMESPACE 109
#define ZEND_FETCH_CLASS 110

#define ZEND_CLONE 111
/* end of block */


Expand Down
12 changes: 12 additions & 0 deletions Zend/zend_execute.c
Original file line number Diff line number Diff line change
Expand Up @@ -2087,6 +2087,18 @@ binary_assign_op_addr: {
EX(Ts)[EX(opline)->result.u.var].var.ptr->is_ref=1;
}
NEXT_OPCODE();
case ZEND_CLONE:
{
zval *obj = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);

EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr = &EX(Ts)[EX(opline)->result.u.var].var.ptr;
ALLOC_ZVAL(EX(Ts)[EX(opline)->result.u.var].var.ptr);
EX(Ts)[EX(opline)->result.u.var].var.ptr->value.obj = obj->value.obj.handlers->clone_obj(obj->value.obj.handle);
EX(Ts)[EX(opline)->result.u.var].var.ptr->type = IS_OBJECT;
EX(Ts)[EX(opline)->result.u.var].var.ptr->refcount=1;
EX(Ts)[EX(opline)->result.u.var].var.ptr->is_ref=1;
NEXT_OPCODE();
}
case ZEND_FETCH_CONSTANT:
{
zend_class_entry *ce;
Expand Down
4 changes: 2 additions & 2 deletions Zend/zend_language_parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -650,9 +650,9 @@ variable_property:
;

method_or_not:
'(' { zend_do_pop_object(&$1 TSRMLS_CC); zend_do_begin_method_call(NULL, &$1 TSRMLS_CC); }
'(' { zend_do_pop_object(&$1 TSRMLS_CC); zend_do_begin_method_call(&$1 TSRMLS_CC); }
function_call_parameter_list ')'
{ zend_do_end_function_call(&$1, &$$, &$3, 0, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);
{ zend_do_end_function_call(&$1, &$$, &$3, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);
zend_do_push_object(&$$ TSRMLS_CC); $$.u.EA.type = ZEND_PARSED_METHOD_CALL; }
| /* empty */ { $$.u.EA.type = ZEND_PARSED_MEMBER; }
;
Expand Down

0 comments on commit 2ce4b47

Please sign in to comment.