From: Andi Gutmans Date: Wed, 26 Dec 2001 19:54:20 +0000 (+0000) Subject: - Pretty much finish _clone() support X-Git-Tag: PRE_ISSET_PATCH~400 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=29ea3da2f846ff56669a3ec525bfaad2b295bf42;p=php - Pretty much finish _clone() support --- diff --git a/Zend/zend.c b/Zend/zend.c index 1e945fc9da..8ab5351967 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -252,6 +252,7 @@ static void register_standard_class(void) zend_hash_init_ex(&zend_standard_class_def.class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0); zend_hash_init_ex(&zend_standard_class_def.function_table, 0, NULL, ZEND_FUNCTION_DTOR, 1, 0); zend_standard_class_def.constructor = NULL; + zend_standard_class_def.clone = NULL; zend_standard_class_def.handle_function_call = NULL; zend_standard_class_def.handle_property_get = NULL; zend_standard_class_def.handle_property_set = NULL; diff --git a/Zend/zend.h b/Zend/zend.h index 69d33f3291..88c9214299 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -291,6 +291,7 @@ struct _zend_class_entry { zend_function_entry *builtin_functions; union _zend_function *constructor; + union _zend_function *clone; /* handlers */ void (*handle_function_call)(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference); diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 47cac6466e..8b16c26586 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -88,6 +88,7 @@ class_container.name_length = sizeof(class_name)-1; \ class_container.builtin_functions = functions; \ class_container.constructor = NULL; \ + class_container.clone = NULL; \ class_container.handle_function_call = NULL; \ class_container.handle_property_get = NULL; \ class_container.handle_property_set = NULL; \ @@ -99,6 +100,7 @@ class_container.name_length = sizeof(class_name)-1; \ class_container.builtin_functions = functions; \ class_container.constructor = NULL; \ + class_container.clone = NULL; \ class_container.handle_function_call = handle_fcall; \ class_container.handle_property_get = handle_propget; \ class_container.handle_property_set = handle_propset; \ diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index e1a7e853af..d9aeb00c17 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -761,6 +761,8 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n zend_hash_update(&CG(active_class_entry)->function_table, name, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)); if ((CG(active_class_entry)->name_length == (uint) name_len) && (!memcmp(CG(active_class_entry)->name, name, name_len))) { CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array); + } else if ((function_name->u.constant.value.str.len == sizeof("_clone")-1) && (!memcmp(function_name->u.constant.value.str.val, "_clone", sizeof("_clone")))) { + CG(active_class_entry)->clone = (zend_function *) CG(active_op_array); } } else { zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); @@ -1362,6 +1364,7 @@ static void create_class(HashTable *class_table, char *name, int name_length, ze zend_hash_init(&new_class_entry.constants_table, 10, NULL, ZVAL_PTR_DTOR, 0); new_class_entry.constructor = NULL; + new_class_entry.clone = NULL; new_class_entry.handle_function_call = NULL; new_class_entry.handle_property_set = NULL; @@ -1849,6 +1852,7 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod zend_hash_init(&new_class_entry.constants_table, 10, NULL, ZVAL_PTR_DTOR, 0); new_class_entry.constructor = NULL; + new_class_entry.clone = NULL; new_class_entry.handle_function_call = NULL; new_class_entry.handle_property_set = NULL; @@ -1879,6 +1883,8 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod new_class_entry.constructor = parent_class->constructor; + /* FIXME: What do we do with clone? */ + /* copy overloaded handlers */ new_class_entry.handle_function_call = parent_class->handle_function_call; new_class_entry.handle_property_get = parent_class->handle_property_get; diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c index 581e150bf9..f86148158d 100644 --- a/Zend/zend_objects.c +++ b/Zend/zend_objects.c @@ -1,6 +1,7 @@ #include "zend.h" #include "zend_globals.h" #include "zend_variables.h" +#include "zend_API.h" #define ZEND_DEBUG_OBJECTS 0 @@ -141,9 +142,48 @@ zend_object_value zend_objects_clone_obj(zend_object_handle handle) old_object = &EG(objects).object_buckets[handle].bucket.obj.object; retval = zend_objects_new(&new_object, old_object->ce); - ALLOC_HASHTABLE(new_object->properties); - zend_hash_init(new_object->properties, 0, NULL, ZVAL_PTR_DTOR, 0); - zend_hash_copy(new_object->properties, old_object->properties, (copy_ctor_func_t) zval_add_ref, (void *) NULL /* Not used anymore */, sizeof(zval *)); + + if (old_object->ce->clone) { + zval *old_obj; + zval *new_obj; + zval *clone_func_name; + zval *retval_ptr; + HashTable symbol_table; + + MAKE_STD_ZVAL(new_obj); + new_obj->type = IS_OBJECT; + new_obj->value.obj = retval; + zval_copy_ctor(new_obj); + + MAKE_STD_ZVAL(old_obj); + old_obj->type = IS_OBJECT; + old_obj->value.obj.handle = handle; + old_obj->value.obj.handlers = &zoh; /* If we reached here than the handlers are zoh */ + zval_copy_ctor(old_obj); + + /* FIXME: Optimize this so that we use the old_object->ce->clone function pointer instead of the name */ + MAKE_STD_ZVAL(clone_func_name); + clone_func_name->type = IS_STRING; + clone_func_name->value.str.val = estrndup("_clone", sizeof("_clone")-1); + clone_func_name->value.str.len = sizeof("_clone")-1; + + ALLOC_HASHTABLE(new_object->properties); + zend_hash_init(new_object->properties, 0, NULL, ZVAL_PTR_DTOR, 0); + + ZEND_INIT_SYMTABLE(&symbol_table); + ZEND_SET_SYMBOL(&symbol_table, "clone", old_obj); + + call_user_function_ex(NULL, &new_obj, clone_func_name, &retval_ptr, 0, NULL, 0, &symbol_table TSRMLS_CC); + + zend_hash_destroy(&symbol_table); + zval_ptr_dtor(&new_obj); + zval_ptr_dtor(&clone_func_name); + zval_ptr_dtor(&retval_ptr); + } else { + ALLOC_HASHTABLE(new_object->properties); + zend_hash_init(new_object->properties, 0, NULL, ZVAL_PTR_DTOR, 0); + zend_hash_copy(new_object->properties, old_object->properties, (copy_ctor_func_t) zval_add_ref, (void *) NULL /* Not used anymore */, sizeof(zval *)); + } return retval; }