From: Bob Weinand Date: Tue, 31 Dec 2013 18:14:36 +0000 (-0500) Subject: First try of recursive watchpoints X-Git-Tag: php-5.6.0beta2~1^2~37^2~39 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f4eeda9a9b581bece77757a5688d0b34a42fd336;p=php First try of recursive watchpoints --- diff --git a/phpdbg_watch.c b/phpdbg_watch.c index a506f38486..f6d8646a1f 100644 --- a/phpdbg_watch.c +++ b/phpdbg_watch.c @@ -110,6 +110,58 @@ static int phpdbg_create_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_DC) { return SUCCESS; } +static int phpdbg_create_recursive_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_DC) { + HashTable *ht; + + if (watch->type != WATCH_ON_ZVAL) { + return FAILURE; + } + + phpdbg_create_watchpoint(watch TSRMLS_CC); + + switch (Z_TYPE_P(watch->addr.zv)) { + case IS_ARRAY: + ht = Z_ARRVAL_P(watch->addr.zv); + break; + case IS_OBJECT: + ht = Z_OBJPROP_P(watch->addr.zv); + break; + default: + return SUCCESS; + } + + { + HashPosition position; + zval **zv; + zval key; + for (zend_hash_internal_pointer_reset_ex(ht, &position); + zend_hash_get_current_data_ex(ht, (void **)&zv, &position) == SUCCESS; + zend_hash_move_forward_ex(ht, &position)) { + phpdbg_watchpoint_t *new_watch = emalloc(sizeof(phpdbg_watchpoint_t)); + + new_watch->parent = watch; + new_watch->parent_container = ht; + + zend_hash_get_current_key_zval_ex(ht, &key, &position); + if (Z_TYPE(key) == IS_STRING) { + new_watch->name_in_parent = Z_STRVAL(key); + new_watch->name_in_parent_len = Z_STRLEN(key); + } else { + new_watch->name_in_parent = NULL; + new_watch->name_in_parent_len = asprintf(&new_watch->name_in_parent, "%ld", Z_LVAL(key)); + } + + new_watch->str = NULL; + new_watch->str_len = asprintf(&new_watch->str, "%.*s%s%.*s%s", watch->str_len, watch->str, Z_TYPE_P(watch->addr.zv) == IS_ARRAY?"[":"->", new_watch->name_in_parent_len, new_watch->name_in_parent, Z_TYPE_P(watch->addr.zv) == IS_ARRAY?"]":""); + + phpdbg_create_zval_watchpoint(*zv, new_watch); + phpdbg_create_recursive_watchpoint(new_watch TSRMLS_CC); + } + } + + return SUCCESS; +} + static int phpdbg_delete_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_DC) { int ret = zend_hash_del(&PHPDBG_G(watchpoints), watch->str, watch->str_len); @@ -237,6 +289,23 @@ PHPDBG_WATCH(delete) /* {{{ */ return SUCCESS; } /* }}} */ +PHPDBG_WATCH(recursive) /* {{{ */ +{ + if (phpdbg_rebuild_symtable(TSRMLS_C) == FAILURE) { + return SUCCESS; + } + + switch (param->type) { + case STR_PARAM: + phpdbg_watchpoint_parse_input(param->str, param->len, EG(active_symbol_table), 0, phpdbg_create_recursive_watchpoint TSRMLS_CC); + break; + + phpdbg_default_switch_case(); + } + + return SUCCESS; +} /* }}} */ + int phpdbg_create_var_watchpoint(char *input, size_t len TSRMLS_DC) { if (phpdbg_rebuild_symtable(TSRMLS_C) == FAILURE) { return SUCCESS; diff --git a/phpdbg_watch.h b/phpdbg_watch.h index 0f96828edf..411349816b 100644 --- a/phpdbg_watch.h +++ b/phpdbg_watch.h @@ -30,13 +30,15 @@ * Printer Forward Declarations */ PHPDBG_WATCH(delete); +PHPDBG_WATCH(recursive); /** * Commands */ static const phpdbg_command_t phpdbg_watch_commands[] = { - PHPDBG_COMMAND_D_EX(delete, "delete watchpoint", 'd', watch_delete, NULL, 1), + PHPDBG_COMMAND_D_EX(delete, "delete watchpoint", 'd', watch_delete, NULL, 1), + PHPDBG_COMMAND_D_EX(recursive, "create recursive watchpoints", 'r', watch_recursive, NULL, 1), }; /* Watchpoint functions/typedefs */