From d55637df6923689396e58c3d789e82314f4826ec Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Wed, 13 Jun 2012 15:50:22 +0000 Subject: [PATCH] * breakpoint.c (condition_completer): New function. (_initialize_breakpoint): Use it. * value.c (complete_internalvar): New function. * value.h (complete_internalvar): Declare. testsuite * gdb.base/condbreak.exp: Add tests for "condition" completion. --- gdb/ChangeLog | 7 ++++ gdb/breakpoint.c | 59 +++++++++++++++++++++++++++- gdb/testsuite/ChangeLog | 4 ++ gdb/testsuite/gdb.base/condbreak.exp | 5 +++ gdb/value.c | 23 +++++++++++ gdb/value.h | 2 + 6 files changed, 99 insertions(+), 1 deletion(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 81bd9a94599..304adc62967 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2012-06-13 Tom Tromey + + * breakpoint.c (condition_completer): New function. + (_initialize_breakpoint): Use it. + * value.c (complete_internalvar): New function. + * value.h (complete_internalvar): Declare. + 2012-06-13 Tom Tromey * ada-lang.c (ada_make_symbol_completion_list): Return a VEC. diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index d76065dc4ed..82265cc590a 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -947,6 +947,62 @@ set_breakpoint_condition (struct breakpoint *b, char *exp, observer_notify_breakpoint_modified (b); } +/* Completion for the "condition" command. */ + +static VEC (char_ptr) * +condition_completer (struct cmd_list_element *cmd, char *text, char *word) +{ + char *space; + + text = skip_spaces (text); + space = skip_to_space (text); + if (*space == '\0') + { + int len; + struct breakpoint *b; + VEC (char_ptr) *result = NULL; + + if (text[0] == '$') + { + /* We don't support completion of history indices. */ + if (isdigit (text[1])) + return NULL; + return complete_internalvar (&text[1]); + } + + /* We're completing the breakpoint number. */ + len = strlen (text); + + ALL_BREAKPOINTS (b) + { + int single = b->loc->next == NULL; + struct bp_location *loc; + int count = 1; + + for (loc = b->loc; loc; loc = loc->next) + { + char location[50]; + + if (single) + sprintf (location, "%d", b->number); + else + sprintf (location, "%d.%d", b->number, count); + + if (strncmp (location, text, len) == 0) + VEC_safe_push (char_ptr, result, xstrdup (location)); + + ++count; + } + } + + return result; + } + + /* We're completing the expression part. */ + text = skip_spaces (space); + return expression_completer (cmd, text, word); +} + /* condition N EXP -- set break condition of breakpoint N to EXP. */ static void @@ -15528,10 +15584,11 @@ Type a line containing \"end\" to indicate the end of them.\n\ Give \"silent\" as the first line to make the breakpoint silent;\n\ then no output is printed when it is hit, except what the commands print.")); - add_com ("condition", class_breakpoint, condition_command, _("\ + c = add_com ("condition", class_breakpoint, condition_command, _("\ Specify breakpoint number N to break only if COND is true.\n\ Usage is `condition N COND', where N is an integer and COND is an\n\ expression to be evaluated whenever breakpoint N is reached.")); + set_cmd_completer (c, condition_completer); c = add_com ("tbreak", class_breakpoint, tbreak_command, _("\ Set a temporary breakpoint.\n\ diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index dfc7753b811..d369a2a2630 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2012-06-13 Tom Tromey + + * gdb.base/condbreak.exp: Add tests for "condition" completion. + 2012-06-11 Jan Kratochvil Fix regression by the "ambiguous linespec" series. diff --git a/gdb/testsuite/gdb.base/condbreak.exp b/gdb/testsuite/gdb.base/condbreak.exp index fb82e561e78..4d0b4ba45e7 100644 --- a/gdb/testsuite/gdb.base/condbreak.exp +++ b/gdb/testsuite/gdb.base/condbreak.exp @@ -261,3 +261,8 @@ gdb_test_multiple "continue" $test { xfail $test } } + +gdb_test "complete cond 1" "cond 1" +gdb_test "set variable \$var = 1" +gdb_test "complete cond \$v" "cond \\\$var" +gdb_test "complete cond 1 values\[0\].a" "cond 1 values.0..a_field" diff --git a/gdb/value.c b/gdb/value.c index c64e55b2162..a6bb71865bd 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -1714,6 +1714,29 @@ lookup_only_internalvar (const char *name) return NULL; } +/* Complete NAME by comparing it to the names of internal variables. + Returns a vector of newly allocated strings, or NULL if no matches + were found. */ + +VEC (char_ptr) * +complete_internalvar (const char *name) +{ + VEC (char_ptr) *result = NULL; + struct internalvar *var; + int len; + + len = strlen (name); + + for (var = internalvars; var; var = var->next) + if (strncmp (var->name, name, len) == 0) + { + char *r = xstrdup (var->name); + + VEC_safe_push (char_ptr, result, r); + } + + return result; +} /* Create an internal variable with name NAME and with a void value. NAME should not normally include a dollar sign. */ diff --git a/gdb/value.h b/gdb/value.h index b630fc72455..242cae30c62 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -765,6 +765,8 @@ extern struct internalvar *lookup_only_internalvar (const char *name); extern struct internalvar *create_internalvar (const char *name); +extern VEC (char_ptr) *complete_internalvar (const char *name); + /* An internalvar can be dynamically computed by supplying a vector of function pointers to perform various operations. */ -- 2.30.2