247190
  +   lY>eJ}@?q1hmo_I|+ ?     /*
   +----------------------------------------------------------------------+
   | Zend Engine                                                          |
   +----------------------------------------------------------------------+
   | Copyright (c) 1998-2016 Zend Technologies Ltd. (http://www.zend.com) |
   +----------------------------------------------------------------------+
   | This source file is subject to version 2.00 of the Zend license,     |
   | that is bundled with this package in the file LICENSE, and is        |
   | available through the world-wide-web at the following url:           |
   | http://www.zend.com/license/2_00.txt.                                |
   | If you did not receive a copy of the Zend license and are unable to  |
   | obtain it through the world-wide-web, please send a note to          |
   | license@zend.com so we can mail you a copy immediately.              |
   +----------------------------------------------------------------------+
   | Authors: Andi Gutmans <andi@zend.com>                                |
   |          Zeev Suraski <zeev@zend.com>                                |
   +----------------------------------------------------------------------+
*/

/* $Id$ */

#include "zend.h"
#include "zend_globals.h"
#include "zend_variables.h"
#include "zend_API.h"
#include "zend_objects.h"
#include "zend_objects_API.h"
#include "zend_object_handlers.h"
#include "zend_interfaces.h"
#include "zend_closures.h"
#include "zend_compile.h"

#define DEBUG_OBJECT_HANDLERS 0

#define Z_OBJ_P(zval_p) \
	((zend_object*)(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zval_p)].bucket.obj.object))

#define Z_OBJ_PROTECT_RECURSION(zval_p) \
	do { \
		if (EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zval_p)].apply_count++ >= 3) { \
			zend_error(E_ERROR, "Nesting level too deep - recursive dependency?"); \
		} \
	} while (0)


#define Z_OBJ_UNPROTECT_RECURSION(zval_p) \
	EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zval_p)].apply_count--

/*
  __X accessors explanation:

  if we have __get and property that is not part of the properties array is
  requested, we call __get handler. If it fails, we return uninitialized.

  if we have __set and property that is not part of the properties array is
  set, we call __set handler. If it fails, we do not change the array.

  for both handlers above, when we are inside __get/__set, no further calls for
  __get/__set for this property of this object will be made, to prevent endless
  recursion and enable accessors to change properties array.

  if we have __call and method which is not part of the class function table is
  called, we cal __call handler.
*/

ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */
{
	if (!zobj->properties) {
		HashPosition pos;
		zend_property_info *prop_info;
		zend_class_entry *ce = zobj->ce;

		ALLOC_HASHTABLE(zobj->properties);
		zend_hash_init(zobj->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
		if (ce->default_properties_count) {
			for (zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
			     zend_hash_get_current_data_ex(&ce->properties_info, (void**)&prop_info, &pos) == SUCCESS;
			     zend_hash_move_forward_ex(&ce->properties_info, &pos)) {
				if (/*prop_info->ce == ce &&*/
				    (prop_info->flags & ZEND_ACC_STATIC) == 0 &&
				    prop_info->offset >= 0 &&
				    zobj->properties_table[prop_info->offset]) {
					zend_hash_quick_add(zobj->properties, prop_info->name, prop_info->name_length+1, prop_info->h, (void**)&zobj->properties_table[prop_info->offset], sizeof(zval*), (void**)&zobj->properties_table[prop_info->offset]);
				}
			}
			while (ce->parent && ce->parent->default_properties_count) {
				ce = ce->parent;
				for (zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
				     zend_hash_get_current_data_ex(&ce->properties_info, (void**)&prop_info, &pos) == SUCCESS;
				     zend_hash_move_forward_ex(&ce->properties_info, &pos)) {
					if (prop_info->ce == ce &&
					    (prop_info->flags &