From: Andi Gutmans Date: Wed, 26 Dec 2001 17:49:22 +0000 (+0000) Subject: - Initial support for _clone() X-Git-Tag: PRE_ISSET_PATCH~402 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2ce4b47657ab53f7125edf76497cfcf44907f534;p=php - Initial support for _clone() --- diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index c37dafc79a..e1a7e853af 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -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; @@ -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; @@ -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; diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index a7c8b9159a..6813fa6dd8 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -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); @@ -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 */ diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index efa0d08c9d..5af6971af1 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -2087,6 +2087,18 @@ send_by_ref: 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; diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 377c185f3a..d022488591 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -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; } ;