]> granicus.if.org Git - php/commitdiff
Add xml formatted deep dump of return value from ev
authorBob Weinand <bobwei9@hotmail.com>
Thu, 23 Oct 2014 15:19:26 +0000 (17:19 +0200)
committerBob Weinand <bobwei9@hotmail.com>
Thu, 23 Oct 2014 15:19:26 +0000 (17:19 +0200)
phpdbg_prompt.c
phpdbg_utils.c
phpdbg_utils.h
xml.md

index 6c78ec6d1302fc07425abec7054592d2a60878b5..82444fbf1d39731fcaf3cd778b88b96474c2ccba 100644 (file)
@@ -707,6 +707,10 @@ PHPDBG_COMMAND(ev) /* {{{ */
        zend_try {
                if (zend_eval_stringl(param->str, param->len,&retval, "eval()'d code" TSRMLS_CC) == SUCCESS) {
                        phpdbg_xml("<eval %r>");
+                       if (PHPDBG_G(flags) & PHPDBG_WRITE_XML) {
+                               zval *zvp = &retval;
+                               phpdbg_xml_var_dump(&zvp TSRMLS_CC);
+                       }
                        zend_print_zval_r(&retval, 0 TSRMLS_CC);
                        phpdbg_xml("</eval>");
                        phpdbg_out("\n");
index fa4b8b0baa0db92330d370a7dfd07e0e065e9749..6dfec7d272da9883b970ed8862c1e64417b62381 100644 (file)
@@ -19,6 +19,7 @@
 */
 
 #include "zend.h"
+
 #include "php.h"
 #include "phpdbg.h"
 #include "phpdbg_opcode.h"
@@ -502,3 +503,140 @@ PHPDBG_API int phpdbg_parse_variable_with_arg(char *input, size_t len, HashTable
                phpdbg_error("variable", "type=\"invalidinput\"", "Malformed input");
                return FAILURE;
 }
+
+static int phpdbg_xml_array_element_dump(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) {
+       phpdbg_xml("<element");
+
+       phpdbg_try_access {
+               if (hash_key->nKeyLength == 0) { /* numeric key */
+                       phpdbg_xml(" name=\"%ld\"", hash_key->h);
+               } else { /* string key */
+                       phpdbg_xml(" name=\"%.*s\"", hash_key->arKey, hash_key->nKeyLength - 1);
+               }
+       } phpdbg_catch_access {
+               phpdbg_xml(" severity=\"error\" ></element>");
+               return 0;
+       } phpdbg_end_try_access();
+
+       phpdbg_xml(">");
+
+       phpdbg_xml_var_dump(zv TSRMLS_CC);
+
+       phpdbg_xml("</element>");
+
+       return 0;
+}
+
+static int phpdbg_xml_object_property_dump(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) {
+       phpdbg_xml("<property");
+
+       phpdbg_try_access {
+               if (hash_key->nKeyLength == 0) { /* numeric key */
+                       phpdbg_xml(" name=\"%ld\"", hash_key->h);
+               } else { /* string key */
+                       const char *prop_name, *class_name;
+                       int unmangle = zend_unmangle_property_name(hash_key->arKey, hash_key->nKeyLength - 1, &class_name, &prop_name);
+
+                       if (class_name && unmangle == SUCCESS) {
+                               phpdbg_xml(" name=\"%s\"", prop_name);
+                               if (class_name[0] == '*') {
+                                       phpdbg_xml(" protection=\"protected\"");
+                               } else {
+                                       phpdbg_xml("class=\"%s\" protection=\"private\"", class_name);
+                               }
+                       } else {
+                               phpdbg_xml(" name=\"%.*s\" protection=\"public\"", hash_key->arKey, hash_key->nKeyLength - 1);
+                       }
+               }
+       } phpdbg_catch_access {
+               phpdbg_xml(" severity=\"error\" ></property>");
+               return 0;
+       } phpdbg_end_try_access();
+
+       phpdbg_xml(">");
+
+       phpdbg_xml_var_dump(zv TSRMLS_CC);
+
+       phpdbg_xml("</property>");
+
+       return 0;
+}
+
+#define COMMON (Z_ISREF_PP(zv) ? "&" : "")
+
+PHPDBG_API void phpdbg_xml_var_dump(zval **zv TSRMLS_DC) {
+       HashTable *myht;
+       const char *class_name;
+       zend_uint class_name_len;
+       int (*element_dump_func)(zval** TSRMLS_DC, int, va_list, zend_hash_key*);
+       int is_temp;
+
+       phpdbg_try_access {
+               switch (Z_TYPE_PP(zv)) {
+                       case IS_BOOL:
+                               phpdbg_xml("<bool refstatus=\"%s\" value=\"%s\" />", COMMON, Z_LVAL_PP(zv) ? "true" : "false");
+                               break;
+                       case IS_NULL:
+                               phpdbg_xml("<null refstatus=\"%s\" />", COMMON);
+                               break;
+                       case IS_LONG:
+                               phpdbg_xml("<int refstatus=\"%s\" value=\"%ld\" />", COMMON, Z_LVAL_PP(zv));
+                               break;
+                       case IS_DOUBLE:
+                               php_printf("<float refstatus=\"%s\" value=\"%.*G\" />", COMMON, (int) EG(precision), Z_DVAL_PP(zv));
+                                       break;
+                       case IS_STRING:
+                               php_printf("<string refstatus=\"%s\" length=\"%d\" value=\"%.*s\" />", COMMON, Z_STRLEN_PP(zv), Z_STRLEN_PP(zv), Z_STRVAL_PP(zv));
+                                       break;
+                       case IS_ARRAY:
+                               myht = Z_ARRVAL_PP(zv);
+                               if (++myht->nApplyCount > 1) {
+                                       phpdbg_xml("<recursion />");
+                                       --myht->nApplyCount;
+                                       break;
+                               }
+                               phpdbg_xml("<array refstatus=\"%s\" num=\"%d\">", COMMON, zend_hash_num_elements(myht));
+                               element_dump_func = phpdbg_xml_array_element_dump;
+                               is_temp = 0;
+                               goto head_done;
+                       case IS_OBJECT:
+                               myht = Z_OBJDEBUG_PP(zv, is_temp);
+                                       if (myht && ++myht->nApplyCount > 1) {
+                                       phpdbg_xml("<recursion />");
+                                               --myht->nApplyCount;
+                                       break;
+                               }
+       
+                               if (Z_OBJ_HANDLER(**zv, get_class_name)) {
+                                       Z_OBJ_HANDLER(**zv, get_class_name)(*zv, &class_name, &class_name_len, 0 TSRMLS_CC);
+                                       phpdbg_xml("<object refstatus=\"%s\" class=\"%s\" id=\"%d\" num=\"%d\">", COMMON, class_name, Z_OBJ_HANDLE_PP(zv), myht ? zend_hash_num_elements(myht) : 0);
+                                       efree((char*)class_name);
+                               } else {
+                                       phpdbg_xml("<object refstatus=\"%s\" class=\"\" id=\"%d\" num=\"%d\">", COMMON, Z_OBJ_HANDLE_PP(zv), myht ? zend_hash_num_elements(myht) : 0);
+                               }
+                               element_dump_func = phpdbg_xml_object_property_dump;
+head_done:
+                               if (myht) {
+                                       zend_hash_apply_with_arguments(myht TSRMLS_CC, (apply_func_args_t) element_dump_func, 0);
+                                       --myht->nApplyCount;
+                                       if (is_temp) {
+                                               zend_hash_destroy(myht);
+                                                       efree(myht);
+                                       }
+                               }
+                               if (Z_TYPE_PP(zv) == IS_ARRAY) {
+                                               phpdbg_xml("</array>");
+                               } else {
+                                       phpdbg_xml("</object>");
+                               }
+                               break;
+                       case IS_RESOURCE: {
+                               const char *type_name = zend_rsrc_list_get_rsrc_type(Z_LVAL_PP(zv) TSRMLS_CC);
+                               phpdbg_xml("<resource refstatus=\"%s\" id=\"%ld\" type=\"%ld\" />", COMMON, Z_LVAL_PP(zv), type_name ? type_name : "unknown");
+                               break;
+                               }
+                       default:
+                               break;
+               }
+       } phpdbg_end_try_access();
+}
index 52338c18363d00d433b58bd640182d24d4982fa4..d657dc79fd9359c6f9790e4a21b29ed407abbdc0 100644 (file)
@@ -110,4 +110,6 @@ typedef int (*phpdbg_parse_var_with_arg_func)(char *name, size_t len, char *keyn
 PHPDBG_API int phpdbg_parse_variable(char *input, size_t len, HashTable *parent, size_t i, phpdbg_parse_var_func callback, zend_bool silent TSRMLS_DC);
 PHPDBG_API int phpdbg_parse_variable_with_arg(char *input, size_t len, HashTable *parent, size_t i, phpdbg_parse_var_with_arg_func callback, zend_bool silent, void *arg TSRMLS_DC);
 
+PHPDBG_API void phpdbg_xml_var_dump(zval **zv TSRMLS_DC);
+
 #endif /* PHPDBG_UTILS_H */
diff --git a/xml.md b/xml.md
index 05734d6be8951eff9efb3f0e7d8a640d89ba807b..9d3b83f8269c78226897e6959e10064f02003e0f 100644 (file)
--- a/xml.md
+++ b/xml.md
@@ -60,6 +60,7 @@ type
 
 - general attribute for most errors, describes the genre of the error
 
+
 General tags
 ============
 
@@ -460,6 +461,7 @@ ev
 
 - eval()uates some code
 - output wrapped in &lt;eval> tags
+- output is here first a dump of xml tags (see "Variable Dump" section), then a dump wrapped in <stream> tags
 
 sh
 --
@@ -633,6 +635,7 @@ dl
 
 - errors may have the module or extension attribute when their name is already known at the point of failure
 
+
 Other tags
 ==========
 
@@ -673,3 +676,83 @@ Other tags
 
 - generally emitted when data couldn't be fetched (e.g. by accessing inconsistent data); only used in hard interrupt mode
 - it might mean that data couldn't be fetched at all, or that only incomplete data was fetched (e.g. when a fixed number of following attributes are fetched, this tag will mark a stop of fetching if none or not all tags were printed)
+
+
+Variable Dump
+=============
+
+- all except property and element tags have a refstatus attribute, is set to non-empty if it's a reference
+
+object properties
+-----------------
+
+- wrapped in a property tag &lt;property name="" protection="">
+ - name: name of key
+ - protection: one of these three values: public / protected / private
+ - class: only present if protection attribute is set to "private", contains the name of the class to which the property belongs
+- if the property tag contains any serverity="error" attribute, there was some crucial error to read it, just skip it
+
+array elements
+--------------
+- wrapped in an element tag &lt;property name="" protection="">
+ - name: name of key
+- if the element tag contains any serverity="error" attribute, there was some crucial error to read it, jsut skip it
+
+int
+---
+
+- &lt;int refstatus="" value="" />
+ - value is the integer
+
+float
+-----
+
+- &lt;float refstatus="" value="" />
+ - value is the float
+
+bool
+----
+
+- &lt;bool refstatus="" value="" />
+ -value: true or false
+
+string
+------
+
+- &lt;string refstatus="" length="" value="" />
+ - length: length or string
+ - value: the string
+
+null
+----
+
+- &lt;null refstatus="" />
+
+array
+-----
+
+- &lt;array refstatus="" num="">
+ - num: number of elements
+ - contains &lt;element> tags
+object
+------
+
+- &lt;object refstatus="" class="" id="" num="">
+ - class: name of the class the object is an instance of (may be empty if unknown)
+ - id: id of the object
+ - num: number of properties
+ - contains &lt;property> tags
+
+resource
+--------
+
+- &lt;resource refstatus="" id="" type="" />
+ - id: resource id
+ - type: type of resource
+
+recursion
+---------
+
+- &lt;recursion />
+- if that tag appears, there's a recursive reference inside the value to be printed