gdb: add completion handler for "handle" and "signal"
authorMike Frysinger <vapier@gentoo.org>
Fri, 10 Aug 2012 05:03:13 +0000 (05:03 +0000)
committerMike Frysinger <vapier@gentoo.org>
Fri, 10 Aug 2012 05:03:13 +0000 (05:03 +0000)
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

URL: http://sourceware.org/bugzilla/show_bug.cgi?id=10436
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
gdb/ChangeLog
gdb/common/vec.h
gdb/completer.c
gdb/completer.h
gdb/infcmd.c
gdb/infrun.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/completion.exp

index f1e503be0001d86b079a4e54ebb42e198d24677b..17f9b083a558e501c48646a4f612e1fd938501ef 100644 (file)
@@ -1,3 +1,21 @@
+2012-08-10  Mike Frysinger  <vapier@gentoo.org>
+
+       PR cli/10436:
+       * common/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-09  Yao Qi  <yao@codesourcery.com>
 
        * cli/cli-decode.c (set_cmd_prefix): New.
index 49116e1f166627a74972d84a64196241b2741cad..a99bcd6b7ae62164bb1649e798b812c01108e46a 100644 (file)
 
 #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)
@@ -461,6 +468,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_)                                                     \
 {                                                                        \
@@ -741,6 +770,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)                         \
 {                                                                        \
@@ -975,6 +1025,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_)                                                     \
 {                                                                        \
index b9f069976340724f692c43ecb5a9fb9d06b80e83..20025785eead6925cfa8f9714e453910840424e0 100644 (file)
@@ -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.  */
 
index 680bc2dc1a0fb8da820d6e335f595b1919c7eb50..fddfa42eb7dad6d8da1d2436e5452f5563c1ac00 100644 (file)
@@ -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);
index 635e577eda15c022ac9c6b2171b043a3438d5314..d56503ca47a973a30e72e3ffa521aecbcb5aef07 100644 (file)
@@ -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\
index cf6c062eee0e46ad3302218c67ea7e773b9d96ed..4f59a9261ea9dc655ca6ab7a0fa93ef32f3cd668 100644 (file)
@@ -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, _("\
index 8d6aca0862fe96e807c47917391517bb1e7837bb..3113c6a6ca345493b6ee3a5dc10dfa46a3fd89a0 100644 (file)
@@ -1,3 +1,8 @@
+2012-08-10  Mike Frysinger  <vapier@gentoo.org>
+
+       PR cli/10436:
+       * gdb.base/completion.exp: Add tests for handle completion.
+
 2012-08-09  Yao Qi  <yao@codesourcery.com>
 
        * gdb.mi/mi-cmd-param-changed.exp: New.
index 9b9459c55ee74f2aeac2218afb44e18c24474aff..ccdc199e670ba754af92a09276491949bfe6f7ea 100644 (file)
@@ -363,6 +363,32 @@ gdb_test_multiple "" "$test" {
     }
 }
 
+set test "complete 'handle signal'"
+send_gdb "handle sigq\t"
+gdb_test_multiple "" "$test" {
+    -re "^handle sigq\b\b\b\bSIGQUIT $" {
+       send_gdb "\n"
+       gdb_test_multiple "" "$test" {
+           -re "SIGQUIT.*Quit.*$gdb_prompt $" {
+               pass "$test"
+           }
+       }
+    }
+}
+
+set test "complete 'handle keyword'"
+send_gdb "handle nos\t"
+gdb_test_multiple "" "$test" {
+    -re "^handle nostop $" {
+       send_gdb "\n"
+       gdb_test_multiple "" "$test" {
+           -re "$gdb_prompt $" {
+               pass "$test"
+           }
+       }
+    }
+}
+
 
 # These tests used to try completing the shorter "p b-a".
 # Unfortunately, on some systems, there are .o files in system
This page took 0.070295 seconds and 4 git commands to generate.