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]

[patch v3] gdb: add completion handler for "handle"


The command line completion has spoiled me.  Thus the lack of completion with
the "handle" command annoys me.  Patch!

This does a few things:
 - adds a VEC_merge helper
 - adds a generic signal completer
 - adds a completion handler for the "handle" command
 - sets the completion handler for the "signal" command

Signed-off-by: Mike Frysinger <vapier@gentoo.org>

v3
	- replace new array completer with existing enum completer
	- add a new VEC_merge helper
	- improve the handle completer to match existing behavior
	- drop handle/signal docstring changes

2012-08-01  Mike Frysinger  <vapier@gentoo.org>

        * vec.h (VEC_merge): Define.
	(DEF_VEC_ALLOC_FUNC_I): Add a merge helper.
	(DEF_VEC_ALLOC_FUNC_P): Likewise.
	(DEF_VEC_ALLOC_FUNC_O): Likewise.
        * completer.c: Include gdb_signals.h.
        (signal_completer): Define.
        * completer.h (signal_completer): Add prototype.
        * infcmd.c (_initialize_infcmd): Assign the command
        completer for "signal" to handle_completer.
        * infrun.c: Include completer.h.
        (handle_completer): Define.
        (_initialize_infrun): Declare a new local variable c.  Store the
        result of add_com("handle") to it.  Assign the command
        completer for "handle" to handle_completer.

2012-08-01  Mike Frysinger  <vapier@gentoo.org>

	* gdb.base/completion.exp: Add tests for handle completion.

 gdb/common/vec.h                      |   72 +++++++++++++++++++++++++++++++++
 gdb/completer.c                       |   32 +++++++++++++++
 gdb/completer.h                       |    3 ++
 gdb/infcmd.c                          |    3 +-
 gdb/infrun.c                          |   35 +++++++++++++++-
 gdb/testsuite/gdb.base/completion.exp |   18 +++++++++
 6 files changed, 161 insertions(+), 2 deletions(-)

diff --git a/gdb/common/vec.h b/gdb/common/vec.h
index fa15370..d16b604 100644
--- a/gdb/common/vec.h
+++ b/gdb/common/vec.h
@@ -212,6 +212,13 @@
 
 #define VEC_copy(T,V) (VEC_OP(T,copy)(V))
 
+/* Merge two vectors.
+   VEC(T,A) *VEC_T_merge(VEC(T) *, VEC(T) *);
+
+   Copy the live elements of both vectors into a new vector.  The new
+   and old vectors need not be allocated by the same mechanism.  */
+#define VEC_merge(T,V1,V2) (VEC_OP(T,merge)(V1, V2))
+
 /* Determine if a vector has additional capacity.
 
    int VEC_T_space (VEC(T) *v,int reserve)
@@ -463,6 +470,28 @@ static inline VEC(T) *VEC_OP (T,copy) (VEC(T) *vec_)			  \
   return new_vec_;							  \
 }									  \
 									  \
+static inline VEC(T) *VEC_OP (T,merge) (VEC(T) *vec1_, VEC(T) *vec2_)	  \
+{									  \
+  if (vec1_ && vec2_)							  \
+    {									  \
+      size_t len_ = vec1_->num + vec2_->num;				  \
+      VEC (T) *new_vec_ = NULL;						  \
+									  \
+      /* We must request exact size allocation, hence the negation.  */	  \
+      new_vec_ = (VEC (T) *)						  \
+	vec_o_reserve (NULL, -len_, offsetof (VEC(T),vec), sizeof (T));	  \
+									  \
+      new_vec_->num = len_;						  \
+      memcpy (new_vec_->vec, vec1_->vec, sizeof (T) * vec1_->num);	  \
+      memcpy (new_vec_->vec + vec1_->num, vec2_->vec,			  \
+	      sizeof (T) * vec2_->num);					  \
+									  \
+      return new_vec_;							  \
+    }									  \
+  else									  \
+    return VEC_copy (T, vec1_ ? vec1_ : vec2_);				  \
+}									  \
+									  \
 static inline void VEC_OP (T,free)					  \
      (VEC(T) **vec_)							  \
 {									  \
@@ -743,6 +772,27 @@ static inline VEC(T) *VEC_OP (T,copy) (VEC(T) *vec_)			  \
   return new_vec_;							  \
 }									  \
 									  \
+static inline VEC(T) *VEC_OP (T,merge) (VEC(T) *vec1_, VEC(T) *vec2_)	  \
+{									  \
+  if (vec1_ && vec2_)							  \
+    {									  \
+      size_t len_ = vec1_->num + vec2_->num;				  \
+      VEC (T) *new_vec_ = NULL;						  \
+									  \
+      /* We must request exact size allocation, hence the negation.  */	  \
+      new_vec_ = (VEC (T) *)(vec_p_reserve (NULL, -len_));		  \
+									  \
+      new_vec_->num = len_;						  \
+      memcpy (new_vec_->vec, vec1_->vec, sizeof (T) * vec1_->num);	  \
+      memcpy (new_vec_->vec + vec1_->num, vec2_->vec,			  \
+	      sizeof (T) * vec2_->num);					  \
+									  \
+      return new_vec_;							  \
+    }									  \
+  else									  \
+    return VEC_copy (T, vec1_ ? vec1_ : vec2_);				  \
+}									  \
+									  \
 static inline int VEC_OP (T,reserve)					  \
      (VEC(T) **vec_, int alloc_ VEC_ASSERT_DECL)			  \
 {									  \
@@ -977,6 +1027,28 @@ static inline VEC(T) *VEC_OP (T,copy) (VEC(T) *vec_)			  \
   return new_vec_;							  \
 }									  \
 									  \
+static inline VEC(T) *VEC_OP (T,merge) (VEC(T) *vec1_, VEC(T) *vec2_)	  \
+{									  \
+  if (vec1_ && vec2_)							  \
+    {									  \
+      size_t len_ = vec1_->num + vec2_->num;				  \
+      VEC (T) *new_vec_ = NULL;						  \
+									  \
+      /* We must request exact size allocation, hence the negation.  */	  \
+      new_vec_ = (VEC (T) *)						  \
+	vec_o_reserve (NULL, -len_, offsetof (VEC(T),vec), sizeof (T));	  \
+									  \
+      new_vec_->num = len_;						  \
+      memcpy (new_vec_->vec, vec1_->vec, sizeof (T) * vec1_->num);	  \
+      memcpy (new_vec_->vec + vec1_->num, vec2_->vec,			  \
+	      sizeof (T) * vec2_->num);					  \
+									  \
+      return new_vec_;							  \
+    }									  \
+  else									  \
+    return VEC_copy (T, vec1_ ? vec1_ : vec2_);				  \
+}									  \
+									  \
 static inline void VEC_OP (T,free)					  \
      (VEC(T) **vec_)							  \
 {									  \
diff --git a/gdb/completer.c b/gdb/completer.c
index b9f0699..2002578 100644
--- a/gdb/completer.c
+++ b/gdb/completer.c
@@ -24,6 +24,7 @@
 #include "language.h"
 #include "gdb_assert.h"
 #include "exceptions.h"
+#include "gdb_signals.h"
 
 #include "cli/cli-decode.h"
 
@@ -797,6 +798,37 @@ command_completer (struct cmd_list_element *ignore,
 				 strlen (text), handle_help);
 }
 
+/* Complete on signals.  */
+
+VEC (char_ptr) *
+signal_completer (struct cmd_list_element *ignore,
+		  char *text, char *word)
+{
+  int i;
+  VEC (char_ptr) *return_val = NULL;
+  size_t len = strlen (word);
+  enum gdb_signal signum;
+  const char *signame;
+
+  for (signum = GDB_SIGNAL_FIRST; signum != GDB_SIGNAL_LAST; ++signum)
+    {
+      /* Can't handle this, so skip it.  */
+      if (signum == GDB_SIGNAL_0)
+	continue;
+
+      signame = gdb_signal_to_name (signum);
+
+      /* Ignore the unknown signal case.  */
+      if (!signame || strcmp (signame, "?") == 0)
+	continue;
+
+      if (strncasecmp (signame, word, len) == 0)
+	VEC_safe_push (char_ptr, return_val, xstrdup (signame));
+    }
+
+  return return_val;
+}
+
 /* Get the list of chars that are considered as word breaks
    for the current command.  */
 
diff --git a/gdb/completer.h b/gdb/completer.h
index 680bc2d..fddfa42 100644
--- a/gdb/completer.h
+++ b/gdb/completer.h
@@ -41,6 +41,9 @@ extern VEC (char_ptr) *location_completer (struct cmd_list_element *,
 extern VEC (char_ptr) *command_completer (struct cmd_list_element *,
 					  char *, char *);
 
+extern VEC (char_ptr) *signal_completer (struct cmd_list_element *,
+					 char *, char *);
+
 extern char *get_gdb_completer_quote_characters (void);
 
 extern char *gdb_completion_word_break_characters (void);
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 635e577..d56503c 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -3016,9 +3016,10 @@ Disconnect from a target.\n\
 The target will wait for another debugger to connect.  Not available for\n\
 all targets."));
 
-  add_com ("signal", class_run, signal_command, _("\
+  c = add_com ("signal", class_run, signal_command, _("\
 Continue program giving it signal specified by the argument.\n\
 An argument of \"0\" means continue program without giving it a signal."));
+  set_cmd_completer (c, signal_completer);
 
   add_com ("stepi", class_run, stepi_command, _("\
 Step one instruction exactly.\n\
diff --git a/gdb/infrun.c b/gdb/infrun.c
index cf6c062..4f59a92 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -57,6 +57,7 @@
 #include "skip.h"
 #include "probe.h"
 #include "objfiles.h"
+#include "completer.h"
 
 /* Prototypes for local functions */
 
@@ -6416,6 +6417,36 @@ Are you sure you want to change it? "),
   do_cleanups (old_chain);
 }
 
+/* Complete the "handle" command.  */
+
+static VEC (char_ptr) *
+handle_completer (struct cmd_list_element *ignore,
+		  char *text, char *word)
+{
+  VEC (char_ptr) *vec_signals, *vec_keywords, *return_val;
+  static const char * const keywords[] =
+    {
+      "all",
+      "stop",
+      "ignore",
+      "print",
+      "pass",
+      "nostop",
+      "noignore",
+      "noprint",
+      "nopass",
+      NULL,
+    };
+
+  vec_signals = signal_completer (ignore, text, word);
+  vec_keywords = complete_on_enum (keywords, word, word);
+
+  return_val = VEC_merge (char_ptr, vec_signals, vec_keywords);
+  VEC_free (char_ptr, vec_signals);
+  VEC_free (char_ptr, vec_keywords);
+  return return_val;
+}
+
 static void
 xdb_handle_command (char *args, int from_tty)
 {
@@ -7059,13 +7090,14 @@ _initialize_infrun (void)
 {
   int i;
   int numsigs;
+  struct cmd_list_element *c;
 
   add_info ("signals", signals_info, _("\
 What debugger does when program gets various signals.\n\
 Specify a signal as argument to print info on that signal only."));
   add_info_alias ("handle", "signals", 0);
 
-  add_com ("handle", class_run, handle_command, _("\
+  c = add_com ("handle", class_run, handle_command, _("\
 Specify how to handle a signal.\n\
 Args are signals and actions to apply to those signals.\n\
 Symbolic signals (e.g. SIGSEGV) are recommended but numeric signals\n\
@@ -7080,6 +7112,7 @@ Print means print a message if this signal happens.\n\
 Pass means let program see this signal; otherwise program doesn't know.\n\
 Ignore is a synonym for nopass and noignore is a synonym for pass.\n\
 Pass and Stop may be combined."));
+  set_cmd_completer (c, handle_completer);
   if (xdb_commands)
     {
       add_com ("lz", class_info, signals_info, _("\
diff --git a/gdb/testsuite/gdb.base/completion.exp b/gdb/testsuite/gdb.base/completion.exp
index 9b9459c..71b9227 100644
--- a/gdb/testsuite/gdb.base/completion.exp
+++ b/gdb/testsuite/gdb.base/completion.exp
@@ -363,6 +363,24 @@ gdb_test_multiple "" "$test" {
     }
 }
 
+set test "complete 'handle signal'"
+send_gdb "handle sigq\t"
+gdb_test_multiple "" "$test" {
+    -re "^handle SIGQUIT $" {
+	send_gdb "\n"
+	pass "$test"
+    }
+}
+
+set test "complete 'handle keyword'"
+send_gdb "handle nos\t"
+gdb_test_multiple "" "$test" {
+    -re "^handle nostop $" {
+	send_gdb "\n"
+	pass "$test"
+    }
+}
+
 
 # These tests used to try completing the shorter "p b-a".
 # Unfortunately, on some systems, there are .o files in system

Attachment: signature.asc
Description: This is a digitally signed message part.


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