Hello internals,
the attached patch introduces a new handler to the engine that is
supposed to help debugging overloaded objects. It allows to return a
temporary hash rather then the object properties. This way an extension
can show non properties in var_dump() and print_r(). It will be used
in extensions like SimpleXML. To show how it will look like the changes
for said extension are alsopresent. Last but not least the handler can
be NULL in which case the old behavior is maintained. If noone objects
I will commit this by the end of the week.
Any comments?
Best regards,
Marcus
Index: Zend/zend.c
===================================================================
RCS file: /repository/ZendEngine2/zend.c,v
retrieving revision 1.391
diff -u -p -d -r1.391 zend.c
--- Zend/zend.c 12 Jan 2007 14:38:07 -0000 1.391
+++ Zend/zend.c 15 Jan 2007 22:23:16 -0000
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: zend.c,v 1.391 2007/01/12 14:38:07 dmitry Exp $ */
+/* $Id: zend.c,v 1.390 2007/01/11 16:47:46 dmitry Exp $ */
#include "zend.h"
#include "zend_extensions.h"
@@ -581,6 +581,7 @@ ZEND_API void zend_print_zval_r_ex(zend_
HashTable *properties = NULL;
zstr class_name = NULL_ZSTR;
zend_uint clen;
+ int is_temp;
if (Z_OBJ_HANDLER_P(expr, get_class_name)) {
Z_OBJ_HANDLER_P(expr,
get_class_name)(expr, &class_name, &clen, 0 TSRMLS_CC);
@@ -593,8 +594,11 @@ ZEND_API void zend_print_zval_r_ex(zend_
if (class_name.v) {
efree(class_name.v);
}
- if (Z_OBJ_HANDLER_P(expr, get_properties)) {
+ if (Z_OBJ_HANDLER_P(expr, get_debug_info)) {
+ properties = Z_OBJ_HANDLER_P(expr,
get_debug_info)(expr, &is_temp TSRMLS_CC);
+ } else if (Z_OBJ_HANDLER_P(expr,
get_properties)) {
properties = Z_OBJPROP_P(expr);
+ is_temp = 0;
}
if (properties) {
if (++properties->nApplyCount>1) {
@@ -604,6 +608,10 @@ ZEND_API void zend_print_zval_r_ex(zend_
}
print_hash(properties, indent, 1
TSRMLS_CC);
properties->nApplyCount--;
+ if (is_temp) {
+ zend_hash_destroy(properties);
+ efree(properties);
+ }
}
break;
}
Index: Zend/zend_object_handlers.c
===================================================================
RCS file: /repository/ZendEngine2/zend_object_handlers.c,v
retrieving revision 1.182
diff -u -p -d -r1.182 zend_object_handlers.c
--- Zend/zend_object_handlers.c 10 Jan 2007 15:59:55 -0000 1.182
+++ Zend/zend_object_handlers.c 15 Jan 2007 22:23:17 -0000
@@ -49,13 +49,19 @@
called, we cal __call handler.
*/
-static HashTable *zend_std_get_properties(zval *object TSRMLS_DC)
+ZEND_API HashTable *zend_std_get_properties(zval *object TSRMLS_DC)
{
zend_object *zobj;
zobj = Z_OBJ_P(object);
return zobj->properties;
}
+ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp
TSRMLS_DC)
+{
+ *is_temp = 0;
+ return zend_std_get_properties(object TSRMLS_CC);
+}
+
static zval *zend_std_call_getter(zval *object, zval *member TSRMLS_DC)
{
zval *retval = NULL;
@@ -1186,6 +1192,7 @@ ZEND_API zend_object_handlers std_object
zend_std_compare_objects, /*
compare_objects */
zend_std_cast_object_tostring, /* cast_object */
NULL,
/* count_elements */
+ NULL, /* get_debug_info */
};
/*
Index: Zend/zend_object_handlers.h
===================================================================
RCS file: /repository/ZendEngine2/zend_object_handlers.h,v
retrieving revision 1.61
diff -u -p -d -r1.61 zend_object_handlers.h
--- Zend/zend_object_handlers.h 1 Jan 2007 09:29:21 -0000 1.61
+++ Zend/zend_object_handlers.h 15 Jan 2007 22:23:17 -0000
@@ -80,6 +80,8 @@ typedef void (*zend_object_unset_dimensi
/* Used to get hash of the properties of the object, as hash of zval's */
typedef HashTable *(*zend_object_get_properties_t)(zval *object TSRMLS_DC);
+typedef HashTable *(*zend_object_get_debug_info_t)(zval *object, int *is_temp
TSRMLS_DC);
+
/* Used to call methods */
/* args on stack! */
/* Andi - EX(fbc) (function being called) needs to be initialized already in
the INIT fcall opcode so that the parameters can be parsed the right way. We
need to add another callback for this.
@@ -132,6 +134,7 @@ struct _zend_object_handlers {
zend_object_compare_t compare_objects;
zend_object_cast_t
cast_object;
zend_object_count_elements_t count_elements;
+ zend_object_get_debug_info_t get_debug_info;
};
extern ZEND_API zend_object_handlers std_object_handlers;
@@ -142,7 +145,8 @@ ZEND_API zval **zend_std_get_static_prop
ZEND_API zend_bool zend_std_unset_static_property(zend_class_entry *ce,
zend_uchar type, zstr property_name, int property_name_len TSRMLS_DC);
ZEND_API union _zend_function *zend_std_get_constructor(zval *object
TSRMLS_DC);
ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry
*ce, zval *member, int silent TSRMLS_DC);
-
+ZEND_API HashTable *zend_std_get_properties(zval *object TSRMLS_DC);
+ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp
TSRMLS_DC);
ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int
type, void *extra TSRMLS_DC);
Index: ext/simplexml/simplexml.c
===================================================================
RCS file: /repository/php-src/ext/simplexml/simplexml.c,v
retrieving revision 1.226
diff -u -p -d -r1.226 simplexml.c
--- ext/simplexml/simplexml.c 1 Jan 2007 09:29:29 -0000 1.226
+++ ext/simplexml/simplexml.c 15 Jan 2007 22:23:18 -0000
@@ -615,6 +615,7 @@ static void sxe_dimension_write(zval *ob
}
/* }}} */
+#if HELLY_0
static zval** sxe_property_get_adr(zval *object, zval *member TSRMLS_DC) /*
{{{ */
{
php_sxe_object *sxe;
@@ -639,12 +640,16 @@ static zval** sxe_property_get_adr(zval
_node_as_zval(sxe, node, return_value, type, name, sxe->iter.nsprefix,
sxe->iter.isprefix TSRMLS_CC);
sxe = php_sxe_fetch_object(return_value TSRMLS_CC);
+ if (sxe->tmp) {
+ zval_ptr_dtor(&sxe->tmp);
+ }
sxe->tmp = return_value;
return_value->is_ref = 1;
return &sxe->tmp;
}
/* }}} */
+#endif
/* {{{ sxe_prop_dim_exists()
*/
@@ -946,9 +951,7 @@ static void sxe_properties_add(HashTable
}
}
-/* {{{ sxe_properties_get()
- */
-static HashTable * sxe_properties_get(zval *object TSRMLS_DC)
+static HashTable * sxe_get_prop_hash(zval *object, int is_debug TSRMLS_DC) /*
{{{ */
{
zval *value;
zval *zattr;
@@ -962,7 +965,10 @@ static HashTable * sxe_properties_get(zv
sxe = php_sxe_fetch_object(object TSRMLS_CC);
- if (sxe->properties) {
+ if (is_debug) {
+ ALLOC_HASHTABLE(rv);
+ zend_u_hash_init(rv, 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
+ } else if (sxe->properties) {
zend_hash_clean(sxe->properties);
rv = sxe->properties;
} else {
@@ -975,7 +981,7 @@ static HashTable * sxe_properties_get(zv
if (!node) {
return rv;
}
- if (1||sxe->iter.type != SXE_ITER_CHILD) {
+ if (is_debug) {
if (sxe->iter.type == SXE_ITER_ELEMENT) {
node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
}
@@ -1066,6 +1072,19 @@ next_iter:
}
/* }}} */
+static HashTable * sxe_get_properties(zval *object TSRMLS_DC) /* {{{ */
+{
+ return sxe_get_prop_hash(object, 0 TSRMLS_CC);
+}
+/* }}} */
+
+static HashTable * sxe_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /*
{{{ */
+{
+ *is_temp = 1;
+ return sxe_get_prop_hash(object, 1 TSRMLS_CC);
+}
+/* }}} */
+
static int sxe_objects_compare(zval *object1, zval *object2 TSRMLS_DC) /* {{{
*/
{
php_sxe_object *sxe1;
@@ -1657,16 +1676,20 @@ static int cast_object(zval *object, int
static int sxe_object_cast(zval *readobj, zval *writeobj, int type, void
*extra TSRMLS_DC)
{
php_sxe_object *sxe;
- xmlChar *contents = NULL;
+ xmlChar *contents = NULL;
xmlNodePtr node;
- int rv;
+ int rv;
+ HashTable *prop_hash;
sxe = php_sxe_fetch_object(readobj TSRMLS_CC);
if (type == IS_BOOL) {
node = php_sxe_get_first_node(sxe, NULL TSRMLS_CC);
+ prop_hash = sxe_get_prop_hash(readobj, 1 TSRMLS_CC);
INIT_PZVAL(writeobj);
- ZVAL_BOOL(writeobj, node != NULL ||
zend_hash_num_elements(sxe_properties_get(readobj TSRMLS_CC)) > 0);
+ ZVAL_BOOL(writeobj, node != NULL ||
zend_hash_num_elements(prop_hash) > 0);
+ zend_hash_destroy(prop_hash);
+ efree(prop_hash);
return SUCCESS;
}
@@ -1749,14 +1772,14 @@ static zend_object_handlers sxe_object_h
sxe_property_write,
sxe_dimension_read,
sxe_dimension_write,
- sxe_property_get_adr,
+ NULL,
sxe_get_value, /* get */
NULL,
sxe_property_exists,
sxe_property_delete,
sxe_dimension_exists,
sxe_dimension_delete,
- sxe_properties_get,
+ sxe_get_properties,
NULL, /* zend_get_std_object_handlers()->get_method,*/
NULL, /* zend_get_std_object_handlers()->call_method,*/
NULL, /* zend_get_std_object_handlers()->get_constructor, */
@@ -1764,7 +1787,8 @@ static zend_object_handlers sxe_object_h
NULL, /* zend_get_std_object_handlers()->get_class_name,*/
sxe_objects_compare,
sxe_object_cast,
- sxe_count_elements
+ sxe_count_elements,
+ sxe_get_debug_info
};
/* {{{ sxe_object_clone()
Index: ext/standard/var.c
===================================================================
RCS file: /repository/php-src/ext/standard/var.c,v
retrieving revision 1.259
diff -u -p -d -r1.259 var.c
--- ext/standard/var.c 1 Jan 2007 09:29:32 -0000 1.259
+++ ext/standard/var.c 15 Jan 2007 22:23:18 -0000
@@ -181,6 +181,7 @@ PHPAPI void php_var_dump(zval **struc, i
zstr class_name;
zend_uint class_name_len;
int (*php_element_dump_func)(zval**, int, va_list, zend_hash_key*);
+ int is_temp;
if (level > 1) {
php_printf("%*c", level - 1, ' ');
@@ -217,9 +218,10 @@ PHPAPI void php_var_dump(zval **struc, i
}
php_printf("%sarray(%d) {\n", COMMON,
zend_hash_num_elements(myht));
php_element_dump_func = php_array_element_dump;
+ is_temp = 0;
goto head_done;
case IS_OBJECT:
- myht = Z_OBJPROP_PP(struc);
+ myht = Z_OBJ_HANDLER_PP(struc, get_debug_info)(*struc, &is_temp
TSRMLS_CC);
if (myht && myht->nApplyCount > 1) {
PUTS("*RECURSION*\n");
return;
@@ -237,6 +239,10 @@ head_done:
php_printf("%*c", level-1, ' ');
}
PUTS("}\n");
+ if (is_temp) {
+ zend_hash_destroy(myht);
+ efree(myht);
+ }
break;
case IS_RESOURCE: {
char *type_name;
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php