]> granicus.if.org Git - php/commitdiff
- Initial support for _clone()
authorAndi Gutmans <andi@php.net>
Wed, 26 Dec 2001 17:49:22 +0000 (17:49 +0000)
committerAndi Gutmans <andi@php.net>
Wed, 26 Dec 2001 17:49:22 +0000 (17:49 +0000)
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_language_parser.y

index c37dafc79a61b36c559f19feb3612055e1c009b9..e1a7e853af1fd6630b5faf6cd2145141b6561996 100644 (file)
@@ -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;
index a7c8b9159a4ede8f4562669a457b68394573a396..6813fa6dd876b5bef83487a25a26298a1ff250b7 100644 (file)
@@ -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 */
 
 
index efa0d08c9db6b8fd493df0d2850508259bef360a..5af6971af133578a5f7bb99950f8be22135a93d2 100644 (file)
@@ -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;
index 377c185f3a58e4bb74a662c9abc1f7131d0b4aec..d0224885912de91d11dbab52c64fdaf652ead80b 100644 (file)
@@ -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; }
 ;