Skip to content

Commit

Permalink
- Implemented the "show-local" command (shows all local variables in the
Browse files Browse the repository at this point in the history
  current scope including all contents).
- Implemented conditions for breakpoints in the "break" command.
- Fixed a memleak.

SVN Rev: 700
  • Loading branch information
derickr committed May 14, 2003
1 parent 8604841 commit b8fee74
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 38 deletions.
7 changes: 7 additions & 0 deletions NEWS
@@ -1,3 +1,10 @@
???, ??? ??, 2003 - xdebug 1.3.0

+ Implemented the "show-local" command (shows all local variables in the
current scope including all contents). (Derick)
+ Implemented conditions for breakpoints in the "break" command. (Derick)


Mon, Apr 21, 2003 - xdebug 1.2.0

= Fixed compilation on MacOSX. (Derick)
Expand Down
2 changes: 0 additions & 2 deletions TODO
Expand Up @@ -6,8 +6,6 @@ For 1.3.0:
* Don't show memory footprint at all if it's not enabled
- Profiling
* Add another profiling mode that allows for detailed function analysis.
- Update gdb debugging capabilities
* watches / conditional breakpoints
- Additions
* Add xdebug_break() function to insert breakpoints in your script manually.
* Provide codes for messages (for localization) including parameters
Expand Down
23 changes: 16 additions & 7 deletions package.xml
Expand Up @@ -12,18 +12,16 @@
</maintainer>
</maintainers>
<description>
An extension which gives you detailed errors with backtraces and provides
A extension which gives you detailed errors with backtraces and provides
functions for function tracing, memory usage and profiling.
</description>
<license>PHP</license>
<release>
<state>stable</state>
<version>1.2.0</version>
<date>2003-04-21</date>
<state>beta</state>
<version>1.3.0rc1</version>
<date>2003-05-15</date>
<notes>
Fixed a bug in handling Windows path files and one for dealing with Zend
Engine 2. Also added support for MacOSX and added the xdebug_call_class()
function.
TBW
</notes>
<filelist>
<file role="src" name="php_xdebug.h"/>
Expand Down Expand Up @@ -66,6 +64,17 @@
</filelist>
</release>
<changelog>
<release>
<state>beta</state>
<version>1.3.0rc1</version>
<date>2003-05-15</date>
<notes>
+ Implemented the "show-local" command (shows all local variables in the
current scope including all contents). (Derick)
+ Implemented conditions for breakpoints in the "break" command. (Derick)
</notes>
</release>

<release>
<state>stable</state>
<version>1.2.0</version>
Expand Down
38 changes: 33 additions & 5 deletions xdebug.c
Expand Up @@ -1617,18 +1617,46 @@ ZEND_DLEXPORT void xdebug_statement_call(zend_op_array *op_array)
}

if (XG(context).line_breakpoints) {

char *filename = xdebug_mangle_filename(file);
int break_ok;
int old_error_reporting;
zval retval;

for (le = XDEBUG_LLIST_HEAD(XG(context).line_breakpoints); le != NULL; le = XDEBUG_LLIST_NEXT(le)) {
brk = XDEBUG_LLIST_VALP(le);

if (lineno == brk->lineno && memcmp(brk->file, filename + file_len - brk->file_len, brk->file_len) == 0) {
if (!XG(context).handler->remote_breakpoint(&(XG(context)), XG(stack), file, lineno, XDEBUG_BREAK)) {
XG(remote_enabled) = 0;
XG(remote_enable) = 0;
break_ok = 1; /* Breaking is allowed by default */

/* Check if we have a condition set for it */
if (brk->condition) {
/* If there is a condition, we disable breaking by
* default and only enabled it when the code evaluates
* to TRUE */
break_ok = 0;

/* Remember error reporting level */
old_error_reporting = EG(error_reporting);
EG(error_reporting) = 0;

/* Check the condition */
if (zend_eval_string(brk->condition, &retval, "xdebug conditional breakpoint" TSRMLS_CC) == SUCCESS) {
convert_to_boolean(&retval);
break_ok = retval.value.lval;
zval_dtor(&retval);
}

/* Restore error reporting level */
EG(error_reporting) = old_error_reporting;
}
if (break_ok) {
if (!XG(context).handler->remote_breakpoint(&(XG(context)), XG(stack), file, lineno, XDEBUG_BREAK)) {
XG(remote_enabled) = 0;
XG(remote_enable) = 0;
break;
}
break;
}
break;
}
}
xdebug_free_filename(filename);
Expand Down
102 changes: 78 additions & 24 deletions xdebug_handler_gdb.c
Expand Up @@ -53,6 +53,7 @@ char *xdebug_handle_pwd(xdebug_con *context, xdebug_arg *args);
char *xdebug_handle_quit(xdebug_con *context, xdebug_arg *args);
char *xdebug_handle_run(xdebug_con *context, xdebug_arg *args);
char *xdebug_handle_show(xdebug_con *context, xdebug_arg *args);
char *xdebug_handle_show_local(xdebug_con *context, xdebug_arg *args);
char *xdebug_handle_step(xdebug_con *context, xdebug_arg *args);

/*****************************************************************************
Expand Down Expand Up @@ -96,6 +97,9 @@ static xdebug_cmd commands_data[] = {
{ "show", 0, "show", xdebug_handle_show, 1,
"Show a list of all variables"
},
{ "show-local", 0, "show-local", xdebug_handle_show_local, 1,
"Show a list of all variables"
},
{ "print", 1, "print", xdebug_handle_print, 1,
"Prints the contents of the variable"
},
Expand Down Expand Up @@ -571,6 +575,8 @@ char *xdebug_handle_breakpoint(xdebug_con *context, xdebug_arg *args)
xdebug_arg *method = (xdebug_arg*) xdmalloc(sizeof(xdebug_arg));
char *tmp_name;
xdebug_brk_info *extra_brk_info;
xdebug_str eval = {0, 0, NULL};
int i = 0;

xdebug_arg_init(method);

Expand Down Expand Up @@ -630,6 +636,20 @@ char *xdebug_handle_breakpoint(xdebug_con *context, xdebug_arg *args)
extra_brk_info->lineno = atoi(method->args[1]);
extra_brk_info->file = tmp_name;
extra_brk_info->file_len = strlen(tmp_name);
extra_brk_info->condition = NULL;

/* If there are more second parameters to the "break" command, then we
* concat them and use it as a conditional statement */
if (args->c > 1) {
XDEBUG_STR_ADD(&eval, args->args[1], 0);

for (i = 2; i < args->c; i++) {
XDEBUG_STR_ADD(&eval, " ", 0);
XDEBUG_STR_ADD(&eval, args->args[i], 0);
}
extra_brk_info->condition = xdstrdup(eval.d);
XDEBUG_STR_FREE(&eval);
}

/* Add breakpoint to the list */
xdebug_llist_insert_next(context->line_breakpoints, XDEBUG_LLIST_TAIL(context->line_breakpoints), (void*) extra_brk_info);
Expand Down Expand Up @@ -658,7 +678,6 @@ char *xdebug_handle_delete(xdebug_con *context, xdebug_arg *args)
{
xdebug_arg *method = (xdebug_arg*) xdmalloc(sizeof(xdebug_arg));
char *tmp_name;
xdebug_brk_info *extra_brk_info;
xdebug_llist_element *le;
xdebug_brk_info *brk;
TSRMLS_FETCH();
Expand Down Expand Up @@ -706,12 +725,6 @@ char *xdebug_handle_delete(xdebug_con *context, xdebug_arg *args)
tmp_name = xdebug_sprintf("%s", method->args[0]);
}

/* Set line number in extra structure */
extra_brk_info = xdmalloc(sizeof(xdebug_brk_info));
extra_brk_info->lineno = atoi(method->args[1]);
extra_brk_info->file = tmp_name;
extra_brk_info->file_len = strlen(tmp_name);

/* Add breakpoint to the list */
for (le = XDEBUG_LLIST_HEAD(XG(context).line_breakpoints); le != NULL; le = XDEBUG_LLIST_NEXT(le)) {
brk = XDEBUG_LLIST_VALP(le);
Expand Down Expand Up @@ -891,36 +904,42 @@ char *xdebug_handle_option(xdebug_con *context, xdebug_arg *args)
return NULL;
}

char *xdebug_handle_print(xdebug_con *context, xdebug_arg *args)
static char* get_symbol_contents(xdebug_con *context, char* name, int name_length)
{
HashTable *st = NULL;
zval **retval;
xdebug_gdb_options *options = (xdebug_gdb_options*)context->options;
int xml = (options->response_format == XDEBUG_RESPONSE_XML);
TSRMLS_FETCH();

st = EG(active_symbol_table);
if (zend_hash_find(st, args->args[0], strlen(args->args[0]) + 1, (void **) &retval) == SUCCESS) {
SSEND(context->socket, xml ? "<xdebug><print>" : "");
SENDMSG(context->socket, get_variable(context, args->args[0], *retval));
SSEND(context->socket, xml ? "</print></xdebug>\n" : "\n");
return NULL;
if (zend_hash_find(st, name, name_length, (void **) &retval) == SUCCESS) {
return get_variable(context, name, *retval);
}

st = EG(active_op_array)->static_variables;
if (st) {
if (zend_hash_find(st, args->args[0], strlen(args->args[0]) + 1, (void **) &retval) == SUCCESS) {
SSEND(context->socket, xml ? "<xdebug><print>" : "");
SENDMSG(context->socket, get_variable(context, args->args[0], *retval));
SSEND(context->socket, xml ? "</print></xdebug>\n" : "\n");
return NULL;
if (zend_hash_find(st, name, name_length, (void **) &retval) == SUCCESS) {
return get_variable(context, name, *retval);
}
}

st = &EG(symbol_table);
if (zend_hash_find(st, args->args[0], strlen(args->args[0]) + 1, (void **) &retval) == SUCCESS) {
if (zend_hash_find(st, name, name_length, (void **) &retval) == SUCCESS) {
return get_variable(context, name, *retval);
}
return NULL;
}

char *xdebug_handle_print(xdebug_con *context, xdebug_arg *args)
{
xdebug_gdb_options *options = (xdebug_gdb_options*)context->options;
int xml = (options->response_format == XDEBUG_RESPONSE_XML);
char *var_data;

var_data = get_symbol_contents(context, args->args[0], strlen(args->args[0]) + 1);

if (var_data) {
SSEND(context->socket, xml ? "<xdebug><print>" : "");
SENDMSG(context->socket, get_variable(context, args->args[0], *retval));
SENDMSG(context->socket, var_data);
SSEND(context->socket, xml ? "</print></xdebug>\n" : "\n");
return NULL;
}
Expand Down Expand Up @@ -974,7 +993,31 @@ static void dump_used_var(void *context, xdebug_hash_element* he)
}
}

char *xdebug_handle_show(xdebug_con *context, xdebug_arg *args)
static void dump_used_var_with_contents(void *context, xdebug_hash_element* he)
{
char *name = (char*) he->ptr;
xdebug_con *h = (xdebug_con*) context;
xdebug_gdb_options *options = (xdebug_gdb_options*) h->options;
char *contents;

contents = get_symbol_contents(context, name, strlen(name) + 1);
if (contents) {
if (options->response_format == XDEBUG_RESPONSE_XML) {
SENDMSG(h->socket, contents);
} else {
SENDMSG(h->socket, xdebug_sprintf("%s", contents));
xdfree(contents);
}
} else {
if (options->response_format == XDEBUG_RESPONSE_XML) {
SENDMSG(h->socket, xdebug_sprintf("<var name='%s'/>", name));
} else {
SENDMSG(h->socket, xdebug_sprintf("$%s = *uninitialized*\n", name));
}
}
}

static char* show_local_vars(xdebug_con *context, xdebug_arg *args, void (*func)(void *, xdebug_hash_element*))
{
struct function_stack_entry *i;
xdebug_hash *ht;
Expand All @@ -992,7 +1035,7 @@ char *xdebug_handle_show(xdebug_con *context, xdebug_arg *args)
SSEND(context->socket, "<xdebug><show>");
}

xdebug_hash_apply(ht, (void *) context, dump_used_var);
xdebug_hash_apply(ht, (void *) context, func);

if (options->response_format == XDEBUG_RESPONSE_XML) {
SSEND(context->socket, "</show></xdebug>\n");
Expand All @@ -1005,6 +1048,17 @@ char *xdebug_handle_show(xdebug_con *context, xdebug_arg *args)
return NULL;
}

char *xdebug_handle_show(xdebug_con *context, xdebug_arg *args)
{
return show_local_vars(context, args, dump_used_var);
}


char *xdebug_handle_show_local(xdebug_con *context, xdebug_arg *args)
{
return show_local_vars(context, args, dump_used_var_with_contents);
}


char *xdebug_handle_step(xdebug_con *context, xdebug_arg *args)
{
Expand Down
3 changes: 3 additions & 0 deletions xdebug_handlers.c
Expand Up @@ -46,5 +46,8 @@ void xdebug_brk_dtor(void *dummy, xdebug_brk_info *brk)
if (brk->file) {
xdfree(brk->file);
}
if (brk->condition) {
xdfree(brk->condition);
}
xdfree(brk);
}
1 change: 1 addition & 0 deletions xdebug_handlers.h
Expand Up @@ -58,6 +58,7 @@ struct _xdebug_brk_info {
char *file;
int file_len;
int lineno;
char *condition;
};

struct _xdebug_remote_handler {
Expand Down

0 comments on commit b8fee74

Please sign in to comment.