SharedValue KPHPObject::Get(const char *name) { zval** zPropertyPtr; unsigned int nameLength = strlen(name); TSRMLS_FETCH(); // First try to get the property via the read_property handler. if (this->PropertyExists(name TSRMLS_CC) && Z_OBJ_HANDLER_P(object, read_property)) { zval zname; ZVAL_STRINGL(&zname, name, nameLength, 0); // Use the read_property handler in the class. zval* zProperty = Z_OBJ_HANDLER_P(object, read_property)( object, &zname, 2 TSRMLS_CC); return PHPUtils::ToKrollValue(zProperty TSRMLS_CC); } // Next just try reading it from the properties hash. else if (zend_hash_find(Z_OBJPROP_P(object), name, nameLength + 1, (void**) &zPropertyPtr) != FAILURE) { return PHPUtils::ToKrollValue(*zPropertyPtr TSRMLS_CC); } // Check if the method exists on the object else if (this->MethodExists(name TSRMLS_CC)) { return Value::NewMethod(new KPHPMethod(object, name)); } else { return Value::Undefined; } }
ZEND_API void zend_print_flat_zval_r(zval *expr) /* {{{ */ { switch (Z_TYPE_P(expr)) { case IS_ARRAY: ZEND_PUTS("Array ("); if (Z_REFCOUNTED_P(expr)) { if (Z_IS_RECURSIVE_P(expr)) { ZEND_PUTS(" *RECURSION*"); return; } Z_PROTECT_RECURSION_P(expr); } print_flat_hash(Z_ARRVAL_P(expr)); ZEND_PUTS(")"); if (Z_REFCOUNTED_P(expr)) { Z_UNPROTECT_RECURSION_P(expr); } break; case IS_OBJECT: { HashTable *properties = NULL; zend_string *class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr)); zend_printf("%s Object (", ZSTR_VAL(class_name)); zend_string_release(class_name); if (Z_IS_RECURSIVE_P(expr)) { ZEND_PUTS(" *RECURSION*"); return; } if (Z_OBJ_HANDLER_P(expr, get_properties)) { properties = Z_OBJPROP_P(expr); } if (properties) { Z_PROTECT_RECURSION_P(expr); print_flat_hash(properties); Z_UNPROTECT_RECURSION_P(expr); } ZEND_PUTS(")"); break; } case IS_REFERENCE: zend_print_flat_zval_r(Z_REFVAL_P(expr)); break; default: zend_print_variable(expr); break; } }
ZEND_API void zend_print_flat_zval_r(zval *expr) /* {{{ */ { switch (Z_TYPE_P(expr)) { case IS_ARRAY: ZEND_PUTS("Array ("); if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr)) && ++Z_ARRVAL_P(expr)->u.v.nApplyCount>1) { ZEND_PUTS(" *RECURSION*"); Z_ARRVAL_P(expr)->u.v.nApplyCount--; return; } print_flat_hash(Z_ARRVAL_P(expr)); ZEND_PUTS(")"); if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr))) { Z_ARRVAL_P(expr)->u.v.nApplyCount--; } break; case IS_OBJECT: { HashTable *properties = NULL; zend_string *class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr)); zend_printf("%s Object (", ZSTR_VAL(class_name)); zend_string_release(class_name); if (Z_OBJ_APPLY_COUNT_P(expr) > 0) { ZEND_PUTS(" *RECURSION*"); return; } if (Z_OBJ_HANDLER_P(expr, get_properties)) { properties = Z_OBJPROP_P(expr); } if (properties) { Z_OBJ_INC_APPLY_COUNT_P(expr); print_flat_hash(properties); Z_OBJ_DEC_APPLY_COUNT_P(expr); } ZEND_PUTS(")"); break; } case IS_REFERENCE: zend_print_flat_zval_r(Z_REFVAL_P(expr)); break; default: zend_print_variable(expr); break; } }
static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent) /* {{{ */ { switch (Z_TYPE_P(expr)) { case IS_ARRAY: smart_str_appends(buf, "Array\n"); if (Z_REFCOUNTED_P(expr)) { if (Z_IS_RECURSIVE_P(expr)) { smart_str_appends(buf, " *RECURSION*"); return; } Z_PROTECT_RECURSION_P(expr); } print_hash(buf, Z_ARRVAL_P(expr), indent, 0); if (Z_REFCOUNTED_P(expr)) { Z_UNPROTECT_RECURSION_P(expr); } break; case IS_OBJECT: { HashTable *properties; int is_temp; zend_string *class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr)); smart_str_appends(buf, ZSTR_VAL(class_name)); zend_string_release(class_name); smart_str_appends(buf, " Object\n"); if (Z_IS_RECURSIVE_P(expr)) { smart_str_appends(buf, " *RECURSION*"); return; } if ((properties = Z_OBJDEBUG_P(expr, is_temp)) == NULL) { break; } Z_PROTECT_RECURSION_P(expr); print_hash(buf, properties, indent, 1); Z_UNPROTECT_RECURSION_P(expr); if (is_temp) { zend_hash_destroy(properties); FREE_HASHTABLE(properties); } break; } case IS_LONG: smart_str_append_long(buf, Z_LVAL_P(expr)); break; case IS_REFERENCE: zend_print_zval_r_to_buf(buf, Z_REFVAL_P(expr), indent); break; default: { zend_string *str = zval_get_string(expr); smart_str_append(buf, str); zend_string_release(str); } break; } }
U_CFUNC zend_function *IntlPartsIterator_get_method(zend_object **object_ptr, zend_string *method, const zval *key) { zend_function *ret; zend_string *lc_method_name; ALLOCA_FLAG(use_heap); if (key == NULL) { STR_ALLOCA_ALLOC(lc_method_name, method->len, use_heap); zend_str_tolower_copy(lc_method_name->val, method->val, method->len); } else { lc_method_name = Z_STR_P(key); } if (method->len == sizeof("getrulestatus") - 1 && memcmp("getrulestatus", lc_method_name->val, lc_method_name->len) == 0) { IntlIterator_object *obj = php_intl_iterator_fetch_object(*object_ptr); if (obj->iterator && !Z_ISUNDEF(obj->iterator->data)) { zval *break_iter_zv = &obj->iterator->data; *object_ptr = Z_OBJ_P(break_iter_zv); ret = Z_OBJ_HANDLER_P(break_iter_zv, get_method)(object_ptr, method, key); goto end; } } ret = std_object_handlers.get_method(object_ptr, method, key); end: if (key == NULL) { STR_ALLOCA_FREE(lc_method_name, use_heap); } return ret; }
static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent) /* {{{ */ { ZVAL_DEREF(expr); switch (Z_TYPE_P(expr)) { case IS_ARRAY: smart_str_appends(buf, "Array\n"); if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr)) && ++Z_ARRVAL_P(expr)->u.v.nApplyCount>1) { smart_str_appends(buf, " *RECURSION*"); Z_ARRVAL_P(expr)->u.v.nApplyCount--; return; } print_hash(buf, Z_ARRVAL_P(expr), indent, 0); if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr))) { Z_ARRVAL_P(expr)->u.v.nApplyCount--; } break; case IS_OBJECT: { HashTable *properties; int is_temp; zend_string *class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr)); smart_str_appends(buf, ZSTR_VAL(class_name)); zend_string_release(class_name); smart_str_appends(buf, " Object\n"); if (Z_OBJ_APPLY_COUNT_P(expr) > 0) { smart_str_appends(buf, " *RECURSION*"); return; } if ((properties = Z_OBJDEBUG_P(expr, is_temp)) == NULL) { break; } Z_OBJ_INC_APPLY_COUNT_P(expr); print_hash(buf, properties, indent, 1); Z_OBJ_DEC_APPLY_COUNT_P(expr); if (is_temp) { zend_hash_destroy(properties); FREE_HASHTABLE(properties); } break; } case IS_LONG: smart_str_append_long(buf, Z_LVAL_P(expr)); break; default: { zend_string *str = zval_get_string(expr); smart_str_append(buf, str); zend_string_release(str); } break; } }
static PHP_FUNCTION(com_method_handler) { zval *object = getThis(); Z_OBJ_HANDLER_P(object, call_method)( ((zend_internal_function*)EX(func))->function_name, Z_OBJ_P(object), INTERNAL_FUNCTION_PARAM_PASSTHRU); }
static void _build_trace_args(zval *arg, smart_str *str) /* {{{ */ { /* the trivial way would be to do * convert_to_string_ex(arg); * append it and kill the now tmp arg. * but that could cause some E_NOTICE and also damn long lines. */ ZVAL_DEREF(arg); switch (Z_TYPE_P(arg)) { case IS_NULL: smart_str_appends(str, "NULL, "); break; case IS_STRING: smart_str_appendc(str, '\''); smart_str_append_escaped(str, Z_STRVAL_P(arg), MIN(Z_STRLEN_P(arg), 15)); if (Z_STRLEN_P(arg) > 15) { smart_str_appends(str, "...', "); } else { smart_str_appends(str, "', "); } break; case IS_FALSE: smart_str_appends(str, "false, "); break; case IS_TRUE: smart_str_appends(str, "true, "); break; case IS_RESOURCE: smart_str_appends(str, "Resource id #"); smart_str_append_long(str, Z_RES_HANDLE_P(arg)); smart_str_appends(str, ", "); break; case IS_LONG: smart_str_append_long(str, Z_LVAL_P(arg)); smart_str_appends(str, ", "); break; case IS_DOUBLE: { smart_str_append_printf(str, "%.*G", (int) EG(precision), Z_DVAL_P(arg)); smart_str_appends(str, ", "); break; } case IS_ARRAY: smart_str_appends(str, "Array, "); break; case IS_OBJECT: { zend_string *class_name = Z_OBJ_HANDLER_P(arg, get_class_name)(Z_OBJ_P(arg)); smart_str_appends(str, "Object("); smart_str_appends(str, ZSTR_VAL(class_name)); smart_str_appends(str, "), "); zend_string_release_ex(class_name, 0); break; } } }
ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int indent) /* {{{ */ { ZVAL_DEREF(expr); switch (Z_TYPE_P(expr)) { case IS_ARRAY: ZEND_PUTS_EX("Array\n"); if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr)) && ++Z_ARRVAL_P(expr)->u.v.nApplyCount>1) { ZEND_PUTS_EX(" *RECURSION*"); Z_ARRVAL_P(expr)->u.v.nApplyCount--; return; } print_hash(write_func, Z_ARRVAL_P(expr), indent, 0); if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr))) { Z_ARRVAL_P(expr)->u.v.nApplyCount--; } break; case IS_OBJECT: { HashTable *properties; int is_temp; zend_string *class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr)); ZEND_PUTS_EX(ZSTR_VAL(class_name)); zend_string_release(class_name); ZEND_PUTS_EX(" Object\n"); if (Z_OBJ_APPLY_COUNT_P(expr) > 0) { ZEND_PUTS_EX(" *RECURSION*"); return; } if ((properties = Z_OBJDEBUG_P(expr, is_temp)) == NULL) { break; } Z_OBJ_INC_APPLY_COUNT_P(expr); print_hash(write_func, properties, indent, 1); Z_OBJ_DEC_APPLY_COUNT_P(expr); if (is_temp) { zend_hash_destroy(properties); FREE_HASHTABLE(properties); } break; } default: zend_print_zval_ex(write_func, expr, indent); break; } }
void KPHPObject::Set(const char *name, SharedValue value) { // zend_update_property will call the write_property handler, but will // error out if the handler is NULL. add_property_zval_ex will try to // call the write_property handler without checking if it's NULL. Both // of these functions are exposed in the API with *NO* documentation. // and terribly misleading names. // That said, we'll do our own check for the write_property handler and // throw our own exception if it fails. This way we can handle the NULL // case, but not have to deal with zend_error handling. if (Z_OBJ_HANDLER_P(object, write_property)) { zval* zvalue = PHPUtils::ToPHPValue(value); TSRMLS_FETCH(); add_property_zval_ex(object, name, strlen(name)+1, zvalue TSRMLS_CC); } else { throw ValueException::FromFormat("Could not set property '%s': " "missing write_property handler", name); } }
static int money_handler_compare_objects(zval *object1, zval *object2) { zval *amount1, *amount2, *currency1, *currency2; long compare_result; currency1 = zend_read_property(Z_OBJCE_P(object1), object1, MONEY_PROP_CURRENCY_WS, 0); currency2 = zend_read_property(Z_OBJCE_P(object2), object2, MONEY_PROP_CURRENCY_WS, 0); if ((compare_result = Z_OBJ_HANDLER_P(currency1, compare_objects)(currency1, currency2)) != 0) { zend_throw_exception(CurrencyMismatchException_ce, "Currencies don't match", 0); return compare_result; } amount1 = zend_read_property(Z_OBJCE_P(object1), object1, MONEY_PROP_AMOUNT_WS, 0); amount2 = zend_read_property(Z_OBJCE_P(object2), object2, MONEY_PROP_AMOUNT_WS, 0); if (Z_LVAL_P(amount1) == Z_LVAL_P(amount2)) { return 0; } else if(Z_LVAL_P(amount1) < Z_LVAL_P(amount2)) { return -1; } return 1; }
PHPAPI void php_var_dump(zval *struc, int level) /* {{{ */ { HashTable *myht; zend_string *class_name; int is_temp; int is_ref = 0; zend_ulong num; zend_string *key; zval *val; uint32_t count; if (level > 1) { php_printf("%*c", level - 1, ' '); } again: switch (Z_TYPE_P(struc)) { case IS_FALSE: php_printf("%sbool(false)\n", COMMON); break; case IS_TRUE: php_printf("%sbool(true)\n", COMMON); break; case IS_NULL: php_printf("%sNULL\n", COMMON); break; case IS_LONG: php_printf("%sint(" ZEND_LONG_FMT ")\n", COMMON, Z_LVAL_P(struc)); break; case IS_DOUBLE: php_printf("%sfloat(%.*G)\n", COMMON, (int) EG(precision), Z_DVAL_P(struc)); break; case IS_STRING: php_printf("%sstring(%zd) \"", COMMON, Z_STRLEN_P(struc)); PHPWRITE(Z_STRVAL_P(struc), Z_STRLEN_P(struc)); PUTS("\"\n"); break; case IS_ARRAY: myht = Z_ARRVAL_P(struc); if (level > 1 && ZEND_HASH_APPLY_PROTECTION(myht) && ++myht->u.v.nApplyCount > 1) { PUTS("*RECURSION*\n"); --myht->u.v.nApplyCount; return; } count = zend_array_count(myht); php_printf("%sarray(%d) {\n", COMMON, count); is_temp = 0; ZEND_HASH_FOREACH_KEY_VAL_IND(myht, num, key, val) { php_array_element_dump(val, num, key, level); } ZEND_HASH_FOREACH_END(); if (level > 1 && ZEND_HASH_APPLY_PROTECTION(myht)) { --myht->u.v.nApplyCount; } if (is_temp) { zend_hash_destroy(myht); efree(myht); } if (level > 1) { php_printf("%*c", level-1, ' '); } PUTS("}\n"); break; case IS_OBJECT: if (Z_OBJ_APPLY_COUNT_P(struc) > 0) { PUTS("*RECURSION*\n"); return; } Z_OBJ_INC_APPLY_COUNT_P(struc); myht = Z_OBJDEBUG_P(struc, is_temp); class_name = Z_OBJ_HANDLER_P(struc, get_class_name)(Z_OBJ_P(struc)); php_printf("%sobject(%s)#%d (%d) {\n", COMMON, ZSTR_VAL(class_name), Z_OBJ_HANDLE_P(struc), myht ? zend_array_count(myht) : 0); zend_string_release(class_name); if (myht) { zend_ulong num; zend_string *key; zval *val; ZEND_HASH_FOREACH_KEY_VAL_IND(myht, num, key, val) { php_object_property_dump(val, num, key, level); } ZEND_HASH_FOREACH_END(); if (is_temp) { zend_hash_destroy(myht); efree(myht); } }
php_stream_filter_status_t userfilter_filter( php_stream *stream, php_stream_filter *thisfilter, php_stream_bucket_brigade *buckets_in, php_stream_bucket_brigade *buckets_out, size_t *bytes_consumed, int flags ) { int ret = PSFS_ERR_FATAL; zval *obj = &thisfilter->abstract; zval func_name; zval retval; zval args[4]; zval zpropname; int call_result; /* the userfilter object probably doesn't exist anymore */ if (CG(unclean_shutdown)) { return ret; } if (!zend_hash_str_exists(Z_OBJPROP_P(obj), "stream", sizeof("stream")-1)) { zval tmp; /* Give the userfilter class a hook back to the stream */ php_stream_to_zval(stream, &tmp); zval_copy_ctor(&tmp); add_property_zval(obj, "stream", &tmp); /* add_property_zval increments the refcount which is unwanted here */ zval_ptr_dtor(&tmp); } ZVAL_STRINGL(&func_name, "filter", sizeof("filter")-1); /* Setup calling arguments */ ZVAL_RES(&args[0], zend_register_resource(buckets_in, le_bucket_brigade)); ZVAL_RES(&args[1], zend_register_resource(buckets_out, le_bucket_brigade)); if (bytes_consumed) { ZVAL_LONG(&args[2], *bytes_consumed); } else { ZVAL_NULL(&args[2]); } ZVAL_BOOL(&args[3], flags & PSFS_FLAG_FLUSH_CLOSE); call_result = call_user_function_ex(NULL, obj, &func_name, &retval, 4, args, 0, NULL); zval_ptr_dtor(&func_name); if (call_result == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { convert_to_long(&retval); ret = (int)Z_LVAL(retval); } else if (call_result == FAILURE) { php_error_docref(NULL, E_WARNING, "failed to call filter function"); } if (bytes_consumed) { *bytes_consumed = zval_get_long(&args[2]); } if (buckets_in->head) { php_stream_bucket *bucket = buckets_in->head; php_error_docref(NULL, E_WARNING, "Unprocessed filter buckets remaining on input brigade"); while ((bucket = buckets_in->head)) { /* Remove unconsumed buckets from the brigade */ php_stream_bucket_unlink(bucket); php_stream_bucket_delref(bucket); } } if (ret != PSFS_PASS_ON) { php_stream_bucket *bucket = buckets_out->head; while (bucket != NULL) { php_stream_bucket_unlink(bucket); php_stream_bucket_delref(bucket); bucket = buckets_out->head; } } /* filter resources are cleaned up by the stream destructor, * keeping a reference to the stream resource here would prevent it * from being destroyed properly */ ZVAL_STRINGL(&zpropname, "stream", sizeof("stream")-1); Z_OBJ_HANDLER_P(obj, unset_property)(obj, &zpropname, NULL); zval_ptr_dtor(&zpropname); zval_ptr_dtor(&args[3]); zval_ptr_dtor(&args[2]); zval_ptr_dtor(&args[1]); zval_ptr_dtor(&args[0]); return ret; }
static int money_handler_do_operation(zend_uchar opcode, zval *result, zval *op1, zval *op2) { zval *currency1 = NULL, *currency2 = NULL, *currency_result = NULL; long amount1, amount2, amount_result; switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) { case TYPE_PAIR(IS_OBJECT, IS_OBJECT): if (!instanceof_function(Z_OBJCE_P(op1), money_ce) || !instanceof_function(Z_OBJCE_P(op2), money_ce)) { return FAILURE; } currency1 = zend_read_property(Z_OBJCE_P(op1), op1, MONEY_PROP_CURRENCY_WS, 0); currency2 = zend_read_property(Z_OBJCE_P(op2), op2, MONEY_PROP_CURRENCY_WS, 0); if (Z_OBJ_HANDLER_P(currency1, compare_objects)(currency1, currency2) != 0) { zend_throw_exception(CurrencyMismatchException_ce, "Currencies don't match", 0); ZVAL_NULL(result); return SUCCESS; } amount1 = Z_LVAL_P(zend_read_property(Z_OBJCE_P(op1), op1, MONEY_PROP_AMOUNT_WS, 0)); amount2 = Z_LVAL_P(zend_read_property(Z_OBJCE_P(op2), op2, MONEY_PROP_AMOUNT_WS, 0)); currency_result = currency1; break; case TYPE_PAIR(IS_LONG, IS_OBJECT): /* negate */ if (!instanceof_function(Z_OBJCE_P(op2), money_ce)) { return FAILURE; } if (Z_LVAL_P(op1) != 0) { return FAILURE; /* I said negate */ } amount1 = 0; amount2 = Z_LVAL_P(zend_read_property(Z_OBJCE_P(op2), op2, MONEY_PROP_AMOUNT_WS, 0)); currency_result = zend_read_property(Z_OBJCE_P(op2), op2, MONEY_PROP_CURRENCY_WS, 0); break; default : return FAILURE; } INIT_ZVAL(*result); switch (opcode) { case ZEND_ADD: if (UNEXPECTED((amount1 & LONG_SIGN_MASK) == (amount2 & LONG_SIGN_MASK) && (amount1 & LONG_SIGN_MASK) != ((amount1 + amount2) & LONG_SIGN_MASK))) { zend_throw_exception(spl_ce_OverflowException, "Integer overflow", 0); return FAILURE; } amount_result = amount1 + amount2; goto success; break; case ZEND_SUB: { amount_result = amount1 - amount2; if (amount_result == LONG_MIN) { zend_throw_exception(spl_ce_OverflowException, "Integer negative overflow", 0); return FAILURE; } goto success; } break; default: return FAILURE; break; } success: CREATE_NEW_MONEY_OBJ(result, amount_result, currency_result); return SUCCESS; }
PHPAPI void php_var_dump(zval *struc, int level) /* {{{ */ { HashTable *myht; zend_string *class_name; int is_ref = 0; zend_ulong num; zend_string *key; zval *val; uint32_t count; if (level > 1) { php_printf("%*c", level - 1, ' '); } again: switch (Z_TYPE_P(struc)) { case IS_FALSE: php_printf("%sbool(false)\n", COMMON); break; case IS_TRUE: php_printf("%sbool(true)\n", COMMON); break; case IS_NULL: php_printf("%sNULL\n", COMMON); break; case IS_LONG: php_printf("%sint(" ZEND_LONG_FMT ")\n", COMMON, Z_LVAL_P(struc)); break; case IS_DOUBLE: php_printf("%sfloat(%.*G)\n", COMMON, (int) EG(precision), Z_DVAL_P(struc)); break; case IS_STRING: php_printf("%sstring(%zd) \"", COMMON, Z_STRLEN_P(struc)); PHPWRITE(Z_STRVAL_P(struc), Z_STRLEN_P(struc)); PUTS("\"\n"); break; case IS_ARRAY: myht = Z_ARRVAL_P(struc); if (level > 1 && !(GC_FLAGS(myht) & GC_IMMUTABLE)) { if (GC_IS_RECURSIVE(myht)) { PUTS("*RECURSION*\n"); return; } GC_PROTECT_RECURSION(myht); } count = zend_array_count(myht); php_printf("%sarray(%d) {\n", COMMON, count); ZEND_HASH_FOREACH_KEY_VAL_IND(myht, num, key, val) { php_array_element_dump(val, num, key, level); } ZEND_HASH_FOREACH_END(); if (level > 1 && !(GC_FLAGS(myht) & GC_IMMUTABLE)) { GC_UNPROTECT_RECURSION(myht); } if (level > 1) { php_printf("%*c", level-1, ' '); } PUTS("}\n"); break; case IS_OBJECT: if (Z_IS_RECURSIVE_P(struc)) { PUTS("*RECURSION*\n"); return; } Z_PROTECT_RECURSION_P(struc); myht = zend_get_properties_for(struc, ZEND_PROP_PURPOSE_DEBUG); class_name = Z_OBJ_HANDLER_P(struc, get_class_name)(Z_OBJ_P(struc)); php_printf("%sobject(%s)#%d (%d) {\n", COMMON, ZSTR_VAL(class_name), Z_OBJ_HANDLE_P(struc), myht ? zend_array_count(myht) : 0); zend_string_release_ex(class_name, 0); if (myht) { zend_ulong num; zend_string *key; zval *val; ZEND_HASH_FOREACH_KEY_VAL(myht, num, key, val) { zend_property_info *prop_info = NULL; if (Z_TYPE_P(val) == IS_INDIRECT) { val = Z_INDIRECT_P(val); if (key) { prop_info = zend_get_typed_property_info_for_slot(Z_OBJ_P(struc), val); } } if (!Z_ISUNDEF_P(val) || prop_info) { php_object_property_dump(prop_info, val, num, key, level); } } ZEND_HASH_FOREACH_END(); zend_release_properties(myht); }