LTP GCOV extension - code coverage report
Current view: directory - Zend - zend_objects.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 90
Code covered: 42.2 % Executed lines: 38
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | Zend Engine                                                          |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1998-2007 Zend Technologies Ltd. (http://www.zend.com) |
       6                 :    +----------------------------------------------------------------------+
       7                 :    | This source file is subject to version 2.00 of the Zend license,     |
       8                 :    | that is bundled with this package in the file LICENSE, and is        |
       9                 :    | available through the world-wide-web at the following url:           |
      10                 :    | http://www.zend.com/license/2_00.txt.                                |
      11                 :    | If you did not receive a copy of the Zend license and are unable to  |
      12                 :    | obtain it through the world-wide-web, please send a note to          |
      13                 :    | license@zend.com so we can mail you a copy immediately.              |
      14                 :    +----------------------------------------------------------------------+
      15                 :    | Authors: Andi Gutmans <andi@zend.com>                                |
      16                 :    |          Zeev Suraski <zeev@zend.com>                                |
      17                 :    +----------------------------------------------------------------------+
      18                 : */
      19                 : 
      20                 : /* $Id: zend_objects.c,v 1.56.2.3.2.6 2007/01/01 09:35:47 sebastian Exp $ */
      21                 : 
      22                 : #include "zend.h"
      23                 : #include "zend_globals.h"
      24                 : #include "zend_variables.h"
      25                 : #include "zend_API.h"
      26                 : #include "zend_interfaces.h"
      27                 : #include "zend_exceptions.h"
      28                 : 
      29                 : ZEND_API void zend_object_std_init(zend_object *object, zend_class_entry *ce TSRMLS_DC)
      30               0 : {
      31               0 :         ALLOC_HASHTABLE(object->properties);
      32               0 :         zend_hash_init(object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
      33                 : 
      34               0 :         object->ce = ce;     
      35               0 :         object->guards = NULL;
      36               0 : }
      37                 : 
      38                 : ZEND_API void zend_object_std_dtor(zend_object *object TSRMLS_DC)
      39              91 : {
      40              91 :         if (object->guards) {
      41               0 :                 zend_hash_destroy(object->guards);
      42               0 :                 FREE_HASHTABLE(object->guards);              
      43                 :         }
      44              91 :         if (object->properties) {
      45              91 :                 zend_hash_destroy(object->properties);
      46              91 :                 FREE_HASHTABLE(object->properties);
      47                 :         }
      48              91 : }
      49                 : 
      50                 : ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handle handle TSRMLS_DC)
      51             336 : {
      52             336 :         zend_function *destructor = object->ce->destructor;
      53                 : 
      54             336 :         if (destructor) {
      55                 :                 zval *obj;
      56                 :                 zval *old_exception;
      57                 : 
      58               9 :                 if (destructor->op_array.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED)) {
      59               0 :                         if (destructor->op_array.fn_flags & ZEND_ACC_PRIVATE) {
      60                 :                                 /* Ensure that if we're calling a private function, we're allowed to do so.
      61                 :                                  */
      62               0 :                                 if (object->ce != EG(scope)) {
      63               0 :                                         zend_class_entry *ce = object->ce;
      64                 : 
      65               0 :                                         zend_error(EG(in_execution) ? E_ERROR : E_WARNING, 
      66                 :                                                 "Call to private %s::__destruct() from context '%s'%s", 
      67                 :                                                 ce->name, 
      68                 :                                                 EG(scope) ? EG(scope)->name : "", 
      69                 :                                                 EG(in_execution) ? "" : " during shutdown ignored");
      70               0 :                                         return;
      71                 :                                 }
      72                 :                         } else {
      73                 :                                 /* Ensure that if we're calling a protected function, we're allowed to do so.
      74                 :                                  */
      75               0 :                                 if (!zend_check_protected(destructor->common.scope, EG(scope))) {
      76               0 :                                         zend_class_entry *ce = object->ce;
      77                 : 
      78               0 :                                         zend_error(EG(in_execution) ? E_ERROR : E_WARNING, 
      79                 :                                                 "Call to protected %s::__destruct() from context '%s'%s", 
      80                 :                                                 ce->name, 
      81                 :                                                 EG(scope) ? EG(scope)->name : "", 
      82                 :                                                 EG(in_execution) ? "" : " during shutdown ignored");
      83               0 :                                         return;
      84                 :                                 }
      85                 :                         }
      86                 :                 }
      87                 : 
      88               9 :                 MAKE_STD_ZVAL(obj);
      89               9 :                 Z_TYPE_P(obj) = IS_OBJECT;
      90               9 :                 Z_OBJ_HANDLE_P(obj) = handle;
      91                 :                 /* TODO: We cannot set proper handlers. */
      92               9 :                 Z_OBJ_HT_P(obj) = &std_object_handlers; 
      93               9 :                 zval_copy_ctor(obj);
      94                 : 
      95                 :                 /* Make sure that destructors are protected from previously thrown exceptions.
      96                 :                  * For example, if an exception was thrown in a function and when the function's
      97                 :                  * local variable destruction results in a destructor being called.
      98                 :                  */
      99               9 :                 old_exception = EG(exception);
     100               9 :                 EG(exception) = NULL;
     101               9 :                 zend_call_method_with_0_params(&obj, object->ce, &destructor, ZEND_DESTRUCTOR_FUNC_NAME, NULL);
     102               9 :                 if (old_exception) {
     103               0 :                         if (EG(exception)) {
     104               0 :                                 zend_class_entry *default_exception_ce = zend_exception_get_default(TSRMLS_C);
     105               0 :                                 zval *file = zend_read_property(default_exception_ce, old_exception, "file", sizeof("file")-1, 1 TSRMLS_CC);
     106               0 :                                 zval *line = zend_read_property(default_exception_ce, old_exception, "line", sizeof("line")-1, 1 TSRMLS_CC);
     107                 : 
     108               0 :                                 zval_ptr_dtor(&obj);
     109               0 :                                 zval_ptr_dtor(&EG(exception));
     110               0 :                                 EG(exception) = old_exception;
     111               0 :                                 zend_error(E_ERROR, "Ignoring exception from %s::__destruct() while an exception is already active (Uncaught %s in %s on line %ld)", 
     112                 :                                         object->ce->name, Z_OBJCE_P(old_exception)->name, Z_STRVAL_P(file), Z_LVAL_P(line));
     113                 :                         }
     114               0 :                         EG(exception) = old_exception;
     115                 :                 }
     116               9 :                 zval_ptr_dtor(&obj);
     117                 :         }
     118                 : }
     119                 : 
     120                 : ZEND_API void zend_objects_free_object_storage(zend_object *object TSRMLS_DC)
     121              91 : {
     122              91 :         zend_object_std_dtor(object TSRMLS_CC);
     123              91 :         efree(object);
     124              91 : }
     125                 : 
     126                 : ZEND_API zend_object_value zend_objects_new(zend_object **object, zend_class_entry *class_type TSRMLS_DC)
     127              91 : {       
     128                 :         zend_object_value retval;
     129                 : 
     130              91 :         *object = emalloc(sizeof(zend_object));
     131              91 :         (*object)->ce = class_type;
     132              91 :         retval.handle = zend_objects_store_put(*object, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) zend_objects_free_object_storage, NULL TSRMLS_CC);
     133              91 :         retval.handlers = &std_object_handlers;
     134              91 :         (*object)->guards = NULL;
     135              91 :         return retval;
     136                 : }
     137                 : 
     138                 : ZEND_API zend_object *zend_objects_get_address(zval *zobject TSRMLS_DC)
     139            4481 : {
     140            4481 :         return (zend_object *)zend_object_store_get_object(zobject TSRMLS_CC);
     141                 : }
     142                 : 
     143                 : static void zval_add_ref_or_clone(zval **p)
     144               0 : {
     145               0 :         if (Z_TYPE_PP(p) == IS_OBJECT && !PZVAL_IS_REF(*p)) {
     146                 :                 TSRMLS_FETCH();
     147                 : 
     148               0 :                 if (Z_OBJ_HANDLER_PP(p, clone_obj) == NULL) {
     149               0 :                         zend_error(E_ERROR, "Trying to clone an uncloneable object of class %s",  Z_OBJCE_PP(p)->name);
     150                 :                 } else {
     151               0 :                         zval *orig = *p;
     152                 : 
     153               0 :                         ALLOC_ZVAL(*p);
     154               0 :                         **p = *orig;
     155               0 :                         INIT_PZVAL(*p);
     156               0 :                         (*p)->value.obj = Z_OBJ_HT_PP(p)->clone_obj(orig TSRMLS_CC);
     157                 :                 }
     158                 :         } else {
     159               0 :                 (*p)->refcount++;
     160                 :         }
     161               0 : }
     162                 : 
     163                 : ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object_value new_obj_val, zend_object *old_object, zend_object_handle handle TSRMLS_DC)
     164               1 : {
     165               1 :         if (EG(ze1_compatibility_mode)) {
     166               0 :                 zend_hash_copy(new_object->properties, old_object->properties, (copy_ctor_func_t) zval_add_ref_or_clone, (void *) NULL /* Not used anymore */, sizeof(zval *));
     167                 :         } else {
     168               1 :                 zend_hash_copy(new_object->properties, old_object->properties, (copy_ctor_func_t) zval_add_ref, (void *) NULL /* Not used anymore */, sizeof(zval *));
     169                 :         }
     170               1 :         if (old_object->ce->clone) {
     171                 :                 zval *new_obj;
     172                 : 
     173               0 :                 MAKE_STD_ZVAL(new_obj);
     174               0 :                 new_obj->type = IS_OBJECT;
     175               0 :                 new_obj->value.obj = new_obj_val;
     176               0 :                 zval_copy_ctor(new_obj);
     177                 : 
     178               0 :                 zend_call_method_with_0_params(&new_obj, old_object->ce, &old_object->ce->clone, ZEND_CLONE_FUNC_NAME, NULL);
     179                 : 
     180               0 :                 zval_ptr_dtor(&new_obj);
     181                 :         }
     182               1 : }
     183                 : 
     184                 : ZEND_API zend_object_value zend_objects_clone_obj(zval *zobject TSRMLS_DC)
     185               0 : {
     186                 :         zend_object_value new_obj_val;
     187                 :         zend_object *old_object;
     188                 :         zend_object *new_object;
     189               0 :         zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
     190                 : 
     191                 :         /* assume that create isn't overwritten, so when clone depends on the 
     192                 :          * overwritten one then it must itself be overwritten */
     193               0 :         old_object = zend_objects_get_address(zobject TSRMLS_CC);
     194               0 :         new_obj_val = zend_objects_new(&new_object, old_object->ce TSRMLS_CC);
     195                 : 
     196               0 :         ALLOC_HASHTABLE(new_object->properties);
     197               0 :         zend_hash_init(new_object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
     198                 : 
     199               0 :         zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC);
     200                 : 
     201               0 :         return new_obj_val;
     202                 : }
     203                 : 
     204                 : /*
     205                 :  * Local variables:
     206                 :  * tab-width: 4
     207                 :  * c-basic-offset: 4
     208                 :  * indent-tabs-mode: t
     209                 :  * End:
     210                 :  */

Generated by: LTP GCOV extension version 1.5