This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[3/3] FYI: introduce a "condition" completer


I'm checking this in on the trunk.

Yesterday I tried to complete in "condition" like this:

    cond 1 die.offset.sect_<TAB>

I expected this to complete to "sect_off", but instead it offered a
bunch of symbols.

There were two problems here.  First, "condition" did not use the
expression completer.  Second, even if it did, it would not work because
the "1" would confound the completer -- the text considered as a whole
would not parse.

This fixes the problem by introducing a new completer which understands
the arguments to "condition".

Built and regtested on x86-64 Fedora 16.  New tests included.

Tom

>From d04e526818d2fddcc2448b0b5d571a3e1cda6ab4 Mon Sep 17 00:00:00 2001
From: Tom Tromey <tromey@redhat.com>
Date: Tue, 12 Jun 2012 15:01:38 -0600
Subject: [PATCH 3/3] add a completer for the "condition" command.

	* breakpoint.c (condition_completer): New function.
	(_initialize_breakpoint): Use it.
	* value.c (complete_internalvar): New function.
	* value.h (complete_internalvar): Declare.

	* gdb.base/condbreak.exp: Add tests for "condition" completion.
---
 gdb/breakpoint.c                     |   59 +++++++++++++++++++++++++++++++++-
 gdb/testsuite/gdb.base/condbreak.exp |    5 +++
 gdb/value.c                          |   23 +++++++++++++
 gdb/value.h                          |    2 +
 4 files changed, 88 insertions(+), 1 deletions(-)

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index d76065d..82265cc 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/gdb.base/condbreak.exp b/gdb/testsuite/gdb.base/condbreak.exp
index fb82e56..4d0b4ba 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 c64e55b..a6bb718 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 b630fc7..242cae3 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.  */
 
-- 
1.7.7.6


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]