PR symtab/17559
[deliverable/binutils-gdb.git] / gdb / completer.c
index 43fcf7a8405944c406c38497eac3c3281cc7e65a..a0f3fa32aca7910ec9874f8cfafe05b5d2f1921c 100644 (file)
@@ -1,5 +1,5 @@
 /* Line completion stuff for GDB, the GNU debugger.
-   Copyright (C) 2000, 2001, 2007, 2008, 2009 Free Software Foundation, Inc.
+   Copyright (C) 2000-2014 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -22,6 +22,7 @@
 #include "expression.h"
 #include "filenames.h"         /* For DOSish file names.  */
 #include "language.h"
+#include "gdb_signals.h"
 
 #include "cli/cli-decode.h"
 
@@ -47,21 +48,22 @@ char *line_completion_function (const char *text, int matches,
 /* readline uses the word breaks for two things:
    (1) In figuring out where to point the TEXT parameter to the
    rl_completion_entry_function.  Since we don't use TEXT for much,
-   it doesn't matter a lot what the word breaks are for this purpose, but
-   it does affect how much stuff M-? lists.
+   it doesn't matter a lot what the word breaks are for this purpose,
+   but it does affect how much stuff M-? lists.
    (2) If one of the matches contains a word break character, readline
    will quote it.  That's why we switch between
    current_language->la_word_break_characters() and
    gdb_completer_command_word_break_characters.  I'm not sure when
-   we need this behavior (perhaps for funky characters in C++ symbols?).  */
+   we need this behavior (perhaps for funky characters in C++ 
+   symbols?).  */
 
 /* Variables which are necessary for fancy command line editing.  */
 
 /* When completing on command names, we remove '-' from the list of
    word break characters, since we use it in command names.  If the
    readline library sees one in any of the current completion strings,
-   it thinks that the string needs to be quoted and automatically supplies
-   a leading quote.  */
+   it thinks that the string needs to be quoted and automatically
+   supplies a leading quote.  */
 static char *gdb_completer_command_word_break_characters =
 " \t\n!@#$%^&*()+=|~`}{[]\"';:?/>.<,";
 
@@ -77,13 +79,9 @@ static char *gdb_completer_file_name_break_characters = " \t\n*|\"';?><@";
 static char *gdb_completer_file_name_break_characters = " \t\n*|\"';:?><";
 #endif
 
-/* These are used when completing on locations, which can mix file
-   names and symbol names separated by a colon.  */
-static char *gdb_completer_loc_break_characters = " \t\n*|\"';:?><,";
-
-/* Characters that can be used to quote completion strings.  Note that we
-   can't include '"' because the gdb C parser treats such quoted sequences
-   as strings.  */
+/* Characters that can be used to quote completion strings.  Note that
+   we can't include '"' because the gdb C parser treats such quoted
+   sequences as strings.  */
 static char *gdb_completer_quote_characters = "'";
 \f
 /* Accessor for some completer data that may interest other files.  */
@@ -99,55 +97,42 @@ get_gdb_completer_quote_characters (void)
 char *
 readline_line_completion_function (const char *text, int matches)
 {
-  return line_completion_function (text, matches, rl_line_buffer, rl_point);
+  return line_completion_function (text, matches, 
+                                  rl_line_buffer, rl_point);
 }
 
-/* This can be used for functions which don't want to complete on symbols
-   but don't want to complete on anything else either.  */
-char **
-noop_completer (struct cmd_list_element *ignore, char *text, char *prefix)
+/* This can be used for functions which don't want to complete on
+   symbols but don't want to complete on anything else either.  */
+VEC (char_ptr) *
+noop_completer (struct cmd_list_element *ignore, 
+               const char *text, const char *prefix)
 {
   return NULL;
 }
 
 /* Complete on filenames.  */
-char **
-filename_completer (struct cmd_list_element *ignore, char *text, char *word)
+VEC (char_ptr) *
+filename_completer (struct cmd_list_element *ignore, 
+                   const char *text, const char *word)
 {
   int subsequent_name;
-  char **return_val;
-  int return_val_used;
-  int return_val_alloced;
-
-  return_val_used = 0;
-  /* Small for testing.  */
-  return_val_alloced = 1;
-  return_val = (char **) xmalloc (return_val_alloced * sizeof (char *));
+  VEC (char_ptr) *return_val = NULL;
 
   subsequent_name = 0;
   while (1)
     {
       char *p, *q;
+
       p = rl_filename_completion_function (text, subsequent_name);
-      if (return_val_used >= return_val_alloced)
-       {
-         return_val_alloced *= 2;
-         return_val =
-           (char **) xrealloc (return_val,
-                               return_val_alloced * sizeof (char *));
-       }
       if (p == NULL)
-       {
-         return_val[return_val_used++] = p;
-         break;
-       }
+       break;
       /* We need to set subsequent_name to a non-zero value before the
-        continue line below, because otherwise, if the first file seen
-        by GDB is a backup file whose name ends in a `~', we will loop
-        indefinitely.  */
+        continue line below, because otherwise, if the first file
+        seen by GDB is a backup file whose name ends in a `~', we
+        will loop indefinitely.  */
       subsequent_name = 1;
-      /* Like emacs, don't complete on old versions.  Especially useful
-         in the "source" command.  */
+      /* Like emacs, don't complete on old versions.  Especially
+         useful in the "source" command.  */
       if (p[strlen (p) - 1] == '~')
        {
          xfree (p);
@@ -156,13 +141,12 @@ filename_completer (struct cmd_list_element *ignore, char *text, char *word)
 
       if (word == text)
        /* Return exactly p.  */
-       return_val[return_val_used++] = p;
+       q = p;
       else if (word > text)
        {
          /* Return some portion of p.  */
          q = xmalloc (strlen (p) + 5);
          strcpy (q, p + (word - text));
-         return_val[return_val_used++] = q;
          xfree (p);
        }
       else
@@ -172,14 +156,14 @@ filename_completer (struct cmd_list_element *ignore, char *text, char *word)
          strncpy (q, word, text - word);
          q[text - word] = '\0';
          strcat (q, p);
-         return_val[return_val_used++] = q;
          xfree (p);
        }
+      VEC_safe_push (char_ptr, return_val, q);
     }
 #if 0
-  /* There is no way to do this just long enough to affect quote inserting
-     without also affecting the next completion.  This should be fixed in
-     readline.  FIXME.  */
+  /* There is no way to do this just long enough to affect quote
+     inserting without also affecting the next completion.  This
+     should be fixed in readline.  FIXME.  */
   /* Ensure that readline does the right thing
      with respect to inserting quotes.  */
   rl_completer_word_break_characters = "";
@@ -193,24 +177,27 @@ filename_completer (struct cmd_list_element *ignore, char *text, char *word)
    or
        symbol+offset
 
-   This is intended to be used in commands that set breakpoints etc.  */
-char **
-location_completer (struct cmd_list_element *ignore, char *text, char *word)
+   This is intended to be used in commands that set breakpoints
+   etc.  */
+
+VEC (char_ptr) *
+location_completer (struct cmd_list_element *ignore, 
+                   const char *text, const char *word)
 {
-  int n_syms = 0, n_files = 0;
-  char ** fn_list = NULL;
-  char ** list = NULL;
-  char *p;
+  int n_syms, n_files, ix;
+  VEC (char_ptr) *fn_list = NULL;
+  VEC (char_ptr) *list = NULL;
+  const char *p;
   int quote_found = 0;
   int quoted = *text == '\'' || *text == '"';
   int quote_char = '\0';
-  char *colon = NULL;
+  const char *colon = NULL;
   char *file_to_match = NULL;
-  char *symbol_start = text;
-  char *orig_text = text;
+  const char *symbol_start = text;
+  const char *orig_text = text;
   size_t text_len;
 
-  /* Do we have an unquoted colon, as in "break foo.c::bar"?  */
+  /* Do we have an unquoted colon, as in "break foo.c:bar"?  */
   for (p = text; *p != '\0'; ++p)
     {
       if (*p == '\\' && p[1] == '\'')
@@ -284,24 +271,33 @@ location_completer (struct cmd_list_element *ignore, char *text, char *word)
        fn_list = make_source_files_completion_list (text, text);
     }
 
-  /* How many completions do we have in both lists?  */
-  if (fn_list)
-    for ( ; fn_list[n_files]; n_files++)
-      ;
-  if (list)
-    for ( ; list[n_syms]; n_syms++)
-      ;
+  n_syms = VEC_length (char_ptr, list);
+  n_files = VEC_length (char_ptr, fn_list);
+
+  /* Catenate fn_list[] onto the end of list[].  */
+  if (!n_syms)
+    {
+      VEC_free (char_ptr, list); /* Paranoia.  */
+      list = fn_list;
+      fn_list = NULL;
+    }
+  else
+    {
+      char *fn;
+
+      for (ix = 0; VEC_iterate (char_ptr, fn_list, ix, fn); ++ix)
+       VEC_safe_push (char_ptr, list, fn);
+      VEC_free (char_ptr, fn_list);
+    }
 
-  /* Make list[] large enough to hold both lists, then catenate
-     fn_list[] onto the end of list[].  */
   if (n_syms && n_files)
     {
-      list = xrealloc (list, (n_syms + n_files + 1) * sizeof (char *));
-      memcpy (list + n_syms, fn_list, (n_files + 1) * sizeof (char *));
-      xfree (fn_list);
+      /* Nothing.  */
     }
   else if (n_files)
     {
+      char *fn;
+
       /* If we only have file names as possible completion, we should
         bring them in sync with what rl_complete expects.  The
         problem is that if the user types "break /foo/b TAB", and the
@@ -317,80 +313,61 @@ location_completer (struct cmd_list_element *ignore, char *text, char *word)
         completion, because rl_complete will prepend "/foo/" to each
         candidate completion.  The loop below removes that leading
         part.  */
-      for (n_files = 0; fn_list[n_files]; n_files++)
+      for (ix = 0; VEC_iterate (char_ptr, list, ix, fn); ++ix)
        {
-         memmove (fn_list[n_files], fn_list[n_files] + (word - text),
-                  strlen (fn_list[n_files]) + 1 - (word - text));
+         memmove (fn, fn + (word - text),
+                  strlen (fn) + 1 - (word - text));
        }
-      /* Return just the file-name list as the result.  */
-      list = fn_list;
     }
   else if (!n_syms)
     {
       /* No completions at all.  As the final resort, try completing
         on the entire text as a symbol.  */
       list = make_symbol_completion_list (orig_text, word);
-      xfree (fn_list);
     }
-  else
-    xfree (fn_list);
 
   return list;
 }
 
-/* Helper for expression_completer which recursively counts the number
-   of named fields and methods in a structure or union type.  */
-static int
-count_struct_fields (struct type *type)
-{
-  int i, result = 0;
-
-  CHECK_TYPEDEF (type);
-  for (i = 0; i < TYPE_NFIELDS (type); ++i)
-    {
-      if (i < TYPE_N_BASECLASSES (type))
-       result += count_struct_fields (TYPE_BASECLASS (type, i));
-      else if (TYPE_FIELD_NAME (type, i))
-       ++result;
-    }
-
-  for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; --i)
-    {
-      if (TYPE_FN_FIELDLIST_NAME (type, i))
-       ++result;
-    }
-
-  return result;
-}
-
 /* Helper for expression_completer which recursively adds field and
    method names from TYPE, a struct or union type, to the array
-   OUTPUT.  This function assumes that OUTPUT is correctly-sized.  */
+   OUTPUT.  */
 static void
-add_struct_fields (struct type *type, int *nextp, char **output,
+add_struct_fields (struct type *type, VEC (char_ptr) **output,
                   char *fieldname, int namelen)
 {
   int i;
   int computed_type_name = 0;
-  char *type_name = NULL;
+  const char *type_name = NULL;
 
   CHECK_TYPEDEF (type);
   for (i = 0; i < TYPE_NFIELDS (type); ++i)
     {
       if (i < TYPE_N_BASECLASSES (type))
-       add_struct_fields (TYPE_BASECLASS (type, i), nextp, output,
-                          fieldname, namelen);
-      else if (TYPE_FIELD_NAME (type, i)
-              && ! strncmp (TYPE_FIELD_NAME (type, i), fieldname, namelen))
+       add_struct_fields (TYPE_BASECLASS (type, i),
+                          output, fieldname, namelen);
+      else if (TYPE_FIELD_NAME (type, i))
        {
-         output[*nextp] = xstrdup (TYPE_FIELD_NAME (type, i));
-         ++*nextp;
+         if (TYPE_FIELD_NAME (type, i)[0] != '\0')
+           {
+             if (! strncmp (TYPE_FIELD_NAME (type, i), 
+                            fieldname, namelen))
+               VEC_safe_push (char_ptr, *output,
+                              xstrdup (TYPE_FIELD_NAME (type, i)));
+           }
+         else if (TYPE_CODE (TYPE_FIELD_TYPE (type, i)) == TYPE_CODE_UNION)
+           {
+             /* Recurse into anonymous unions.  */
+             add_struct_fields (TYPE_FIELD_TYPE (type, i),
+                                output, fieldname, namelen);
+           }
        }
     }
 
   for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; --i)
     {
-      char *name = TYPE_FN_FIELDLIST_NAME (type, i);
+      const char *name = TYPE_FN_FIELDLIST_NAME (type, i);
+
       if (name && ! strncmp (name, fieldname, namelen))
        {
          if (!computed_type_name)
@@ -399,11 +376,8 @@ add_struct_fields (struct type *type, int *nextp, char **output,
              computed_type_name = 1;
            }
          /* Omit constructors from the completion list.  */
-         if (type_name && strcmp (type_name, name))
-           {
-             output[*nextp] = xstrdup (name);
-             ++*nextp;
-           }
+         if (!type_name || strcmp (type_name, name))
+           VEC_safe_push (char_ptr, *output, xstrdup (name));
        }
     }
 }
@@ -411,16 +385,25 @@ add_struct_fields (struct type *type, int *nextp, char **output,
 /* Complete on expressions.  Often this means completing on symbol
    names, but some language parsers also have support for completing
    field names.  */
-char **
-expression_completer (struct cmd_list_element *ignore, char *text, char *word)
+VEC (char_ptr) *
+expression_completer (struct cmd_list_element *ignore, 
+                     const char *text, const char *word)
 {
-  struct type *type;
-  char *fieldname, *p;
+  struct type *type = NULL;
+  char *fieldname;
+  const char *p;
+  volatile struct gdb_exception except;
+  enum type_code code = TYPE_CODE_UNDEF;
 
   /* Perform a tentative parse of the expression, to see whether a
      field completion is required.  */
   fieldname = NULL;
-  type = parse_field_expression (text, &fieldname);
+  TRY_CATCH (except, RETURN_MASK_ERROR)
+    {
+      type = parse_expression_for_completion (text, &fieldname, &code);
+    }
+  if (except.reason < 0)
+    return NULL;
   if (fieldname && type)
     {
       for (;;)
@@ -435,17 +418,23 @@ expression_completer (struct cmd_list_element *ignore, char *text, char *word)
       if (TYPE_CODE (type) == TYPE_CODE_UNION
          || TYPE_CODE (type) == TYPE_CODE_STRUCT)
        {
-         int alloc = count_struct_fields (type);
          int flen = strlen (fieldname);
-         int out = 0;
-         char **result = (char **) xmalloc ((alloc + 1) * sizeof (char *));
+         VEC (char_ptr) *result = NULL;
 
-         add_struct_fields (type, &out, result, fieldname, flen);
-         result[out] = NULL;
+         add_struct_fields (type, &result, fieldname, flen);
          xfree (fieldname);
          return result;
        }
     }
+  else if (fieldname && code != TYPE_CODE_UNDEF)
+    {
+      VEC (char_ptr) *result;
+      struct cleanup *cleanup = make_cleanup (xfree, fieldname);
+
+      result = make_symbol_completion_type (fieldname, fieldname, code);
+      do_cleanups (cleanup);
+      return result;
+    }
   xfree (fieldname);
 
   /* Commands which complete on locations want to see the entire
@@ -455,12 +444,28 @@ expression_completer (struct cmd_list_element *ignore, char *text, char *word)
        p--)
     ;
 
-  /* Not ideal but it is what we used to do before... */
+  /* Not ideal but it is what we used to do before...  */
   return location_completer (ignore, p, word);
 }
 
-/* Here are some useful test cases for completion.  FIXME: These should
-   be put in the test suite.  They should be tested with both M-? and TAB.
+/* See definition in completer.h.  */
+
+void
+set_gdb_completion_word_break_characters (completer_ftype *fn)
+{
+  /* So far we are only interested in differentiating filename
+     completers from everything else.  */
+  if (fn == filename_completer)
+    rl_completer_word_break_characters
+      = gdb_completer_file_name_break_characters;
+  else
+    rl_completer_word_break_characters
+      = gdb_completer_command_word_break_characters;
+}
+
+/* Here are some useful test cases for completion.  FIXME: These
+   should be put in the test suite.  They should be tested with both
+   M-? and TAB.
 
    "show output-" "radix"
    "show output" "-radix"
@@ -481,45 +486,73 @@ expression_completer (struct cmd_list_element *ignore, char *text, char *word)
    "file ../gdb.stabs/we" "ird" (needs to not break word at slash)
  */
 
-/* Generate completions all at once.  Returns a NULL-terminated array
-   of strings.  Both the array and each element are allocated with
-   xmalloc.  It can also return NULL if there are no completions.
+typedef enum
+{
+  handle_brkchars,
+  handle_completions,
+  handle_help
+}
+complete_line_internal_reason;
+
+
+/* Internal function used to handle completions.
+
 
    TEXT is the caller's idea of the "word" we are looking at.
 
-   LINE_BUFFER is available to be looked at; it contains the entire text
-   of the line.  POINT is the offset in that line of the cursor.  You
-   should pretend that the line ends at POINT.
-   
-   FOR_HELP is true when completing a 'help' command.  In this case,
+   LINE_BUFFER is available to be looked at; it contains the entire
+   text of the line.  POINT is the offset in that line of the cursor.
+   You should pretend that the line ends at POINT.
+
+   REASON is of type complete_line_internal_reason.
+
+   If REASON is handle_brkchars:
+   Preliminary phase, called by gdb_completion_word_break_characters
+   function, is used to determine the correct set of chars that are
+   word delimiters depending on the current command in line_buffer.
+   No completion list should be generated; the return value should be
+   NULL.  This is checked by an assertion in that function.
+
+   If REASON is handle_completions:
+   Main phase, called by complete_line function, is used to get the list
+   of posible completions.
+
+   If REASON is handle_help:
+   Special case when completing a 'help' command.  In this case,
    once sub-command completions are exhausted, we simply return NULL.
-   When FOR_HELP is false, we will call a sub-command's completion
-   function.  */
+ */
 
-static char **
-complete_line_internal (const char *text, char *line_buffer, int point,
-                       int for_help)
+static VEC (char_ptr) *
+complete_line_internal (const char *text, 
+                       const char *line_buffer, int point,
+                       complete_line_internal_reason reason)
 {
-  char **list = NULL;
-  char *tmp_command, *p;
+  VEC (char_ptr) *list = NULL;
+  char *tmp_command;
+  const char *p;
+  int ignore_help_classes;
   /* Pointer within tmp_command which corresponds to text.  */
   char *word;
   struct cmd_list_element *c, *result_list;
 
-  /* Choose the default set of word break characters to break completions.
-     If we later find out that we are doing completions on command strings
-     (as opposed to strings supplied by the individual command completer
-     functions, which can be any string) then we will switch to the
-     special word break set for command strings, which leaves out the
-     '-' character used in some commands.  */
-
+  /* Choose the default set of word break characters to break
+     completions.  If we later find out that we are doing completions
+     on command strings (as opposed to strings supplied by the
+     individual command completer functions, which can be any string)
+     then we will switch to the special word break set for command
+     strings, which leaves out the '-' character used in some
+     commands.  */
   rl_completer_word_break_characters =
     current_language->la_word_break_characters();
 
-  /* Decide whether to complete on a list of gdb commands or on symbols. */
+  /* Decide whether to complete on a list of gdb commands or on
+     symbols.  */
   tmp_command = (char *) alloca (point + 1);
   p = tmp_command;
 
+  /* The help command should complete help aliases.  */
+  ignore_help_classes = reason != handle_help;
+
   strncpy (tmp_command, line_buffer, point);
   tmp_command[point] = '\0';
   /* Since text always contains some number of characters leading up
@@ -531,12 +564,12 @@ complete_line_internal (const char *text, char *line_buffer, int point,
     {
       /* An empty line we want to consider ambiguous; that is, it
         could be any command.  */
-      c = (struct cmd_list_element *) -1;
+      c = CMD_LIST_AMBIGUOUS;
       result_list = 0;
     }
   else
     {
-      c = lookup_cmd_1 (&p, cmdlist, &result_list, 1);
+      c = lookup_cmd_1 (&p, cmdlist, &result_list, ignore_help_classes);
     }
 
   /* Move p up to the next interesting thing.  */
@@ -551,9 +584,9 @@ complete_line_internal (const char *text, char *line_buffer, int point,
         possible completions.  */
       list = NULL;
     }
-  else if (c == (struct cmd_list_element *) -1)
+  else if (c == CMD_LIST_AMBIGUOUS)
     {
-      char *q;
+      const char *q;
 
       /* lookup_cmd_1 advances p up to the first ambiguous thing, but
         doesn't advance over that thing itself.  Do so now.  */
@@ -575,12 +608,15 @@ complete_line_internal (const char *text, char *line_buffer, int point,
             This we can deal with.  */
          if (result_list)
            {
-             list = complete_on_cmdlist (*result_list->prefixlist, p,
-                                         word);
+             if (reason != handle_brkchars)
+               list = complete_on_cmdlist (*result_list->prefixlist, p,
+                                           word, ignore_help_classes);
            }
          else
            {
-             list = complete_on_cmdlist (cmdlist, p, word);
+             if (reason != handle_brkchars)
+               list = complete_on_cmdlist (cmdlist, p, word,
+                                           ignore_help_classes);
            }
          /* Ensure that readline does the right thing with respect to
             inserting quotes.  */
@@ -594,28 +630,32 @@ complete_line_internal (const char *text, char *line_buffer, int point,
 
       if (p == tmp_command + point)
        {
-         /* There is no non-whitespace in the line beyond the command.  */
+         /* There is no non-whitespace in the line beyond the
+            command.  */
 
          if (p[-1] == ' ' || p[-1] == '\t')
            {
-             /* The command is followed by whitespace; we need to complete
-                on whatever comes after command.  */
+             /* The command is followed by whitespace; we need to
+                complete on whatever comes after command.  */
              if (c->prefixlist)
                {
                  /* It is a prefix command; what comes after it is
                     a subcommand (e.g. "info ").  */
-                 list = complete_on_cmdlist (*c->prefixlist, p, word);
+                 if (reason != handle_brkchars)
+                   list = complete_on_cmdlist (*c->prefixlist, p, word,
+                                               ignore_help_classes);
 
                  /* Ensure that readline does the right thing
                     with respect to inserting quotes.  */
                  rl_completer_word_break_characters =
                    gdb_completer_command_word_break_characters;
                }
-             else if (for_help)
+             else if (reason == handle_help)
                list = NULL;
              else if (c->enums)
                {
-                 list = complete_on_enum (c->enums, p, word);
+                 if (reason != handle_brkchars)
+                   list = complete_on_enum (c->enums, p, word);
                  rl_completer_word_break_characters =
                    gdb_completer_command_word_break_characters;
                }
@@ -651,16 +691,20 @@ complete_line_internal (const char *text, char *line_buffer, int point,
                           p--)
                        ;
                    }
-                 list = (*c->completer) (c, p, word);
+                 if (reason == handle_brkchars
+                     && c->completer_handle_brkchars != NULL)
+                   (*c->completer_handle_brkchars) (c, p, word);
+                 if (reason != handle_brkchars && c->completer != NULL)
+                   list = (*c->completer) (c, p, word);
                }
            }
          else
            {
              /* The command is not followed by whitespace; we need to
-                complete on the command itself e.g. "p" which is a
+                complete on the command itself, e.g. "p" which is a
                 command itself but also can complete to "print", "ptype"
                 etc.  */
-             char *q;
+             const char *q;
 
              /* Find the command we are completing on.  */
              q = p;
@@ -672,7 +716,9 @@ complete_line_internal (const char *text, char *line_buffer, int point,
                    break;
                }
 
-             list = complete_on_cmdlist (result_list, q, word);
+             if (reason != handle_brkchars)
+               list = complete_on_cmdlist (result_list, q, word,
+                                           ignore_help_classes);
 
              /* Ensure that readline does the right thing
                 with respect to inserting quotes.  */
@@ -680,7 +726,7 @@ complete_line_internal (const char *text, char *line_buffer, int point,
                gdb_completer_command_word_break_characters;
            }
        }
-      else if (for_help)
+      else if (reason == handle_help)
        list = NULL;
       else
        {
@@ -694,7 +740,8 @@ complete_line_internal (const char *text, char *line_buffer, int point,
            }
          else if (c->enums)
            {
-             list = complete_on_enum (c->enums, p, word);
+             if (reason != handle_brkchars)
+               list = complete_on_enum (c->enums, p, word);
            }
          else
            {
@@ -705,7 +752,8 @@ complete_line_internal (const char *text, char *line_buffer, int point,
                     of file-name completion.  */
                  for (p = word;
                       p > tmp_command
-                        && strchr (gdb_completer_file_name_break_characters, p[-1]) == NULL;
+                        && strchr (gdb_completer_file_name_break_characters, 
+                                   p[-1]) == NULL;
                       p--)
                    ;
                  rl_completer_word_break_characters =
@@ -719,87 +767,146 @@ complete_line_internal (const char *text, char *line_buffer, int point,
                       p--)
                    ;
                }
-             list = (*c->completer) (c, p, word);
+             if (reason == handle_brkchars
+                 && c->completer_handle_brkchars != NULL)
+               (*c->completer_handle_brkchars) (c, p, word);
+             if (reason != handle_brkchars && c->completer != NULL)
+               list = (*c->completer) (c, p, word);
            }
        }
     }
 
   return list;
 }
+/* Generate completions all at once.  Returns a vector of strings.
+   Each element is allocated with xmalloc.  It can also return NULL if
+   there are no completions.
+
+   TEXT is the caller's idea of the "word" we are looking at.
+
+   LINE_BUFFER is available to be looked at; it contains the entire
+   text of the line.
 
-/* Like complete_line_internal, but always passes 0 for FOR_HELP.  */
+   POINT is the offset in that line of the cursor.  You
+   should pretend that the line ends at POINT.  */
 
-char **
-complete_line (const char *text, char *line_buffer, int point)
+VEC (char_ptr) *
+complete_line (const char *text, const char *line_buffer, int point)
 {
-  return complete_line_internal (text, line_buffer, point, 0);
+  return complete_line_internal (text, line_buffer, 
+                                point, handle_completions);
 }
 
 /* Complete on command names.  Used by "help".  */
-char **
-command_completer (struct cmd_list_element *ignore, char *text, char *word)
+VEC (char_ptr) *
+command_completer (struct cmd_list_element *ignore, 
+                  const char *text, const char *word)
 {
-  return complete_line_internal (word, text, strlen (text), 1);
+  return complete_line_internal (word, text, 
+                                strlen (text), handle_help);
 }
 
-/* Generate completions one by one for the completer.  Each time we are
-   called return another potential completion to the caller.
-   line_completion just completes on commands or passes the buck to the
-   command's completer function, the stuff specific to symbol completion
-   is in make_symbol_completion_list.
+/* Complete on signals.  */
+
+VEC (char_ptr) *
+signal_completer (struct cmd_list_element *ignore,
+                 const char *text, const char *word)
+{
+  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.  */
+
+char *
+gdb_completion_word_break_characters (void)
+{
+  VEC (char_ptr) *list;
+
+  list = complete_line_internal (rl_line_buffer, rl_line_buffer, rl_point,
+                                handle_brkchars);
+  gdb_assert (list == NULL);
+  return rl_completer_word_break_characters;
+}
+
+/* Generate completions one by one for the completer.  Each time we
+   are called return another potential completion to the caller.
+   line_completion just completes on commands or passes the buck to
+   the command's completer function, the stuff specific to symbol
+   completion is in make_symbol_completion_list.
 
    TEXT is the caller's idea of the "word" we are looking at.
 
-   MATCHES is the number of matches that have currently been collected from
-   calling this completion function.  When zero, then we need to initialize,
-   otherwise the initialization has already taken place and we can just
-   return the next potential completion string.
+   MATCHES is the number of matches that have currently been collected
+   from calling this completion function.  When zero, then we need to
+   initialize, otherwise the initialization has already taken place
+   and we can just return the next potential completion string.
 
-   LINE_BUFFER is available to be looked at; it contains the entire text
-   of the line.  POINT is the offset in that line of the cursor.  You
-   should pretend that the line ends at POINT.
+   LINE_BUFFER is available to be looked at; it contains the entire
+   text of the line.  POINT is the offset in that line of the cursor.
+   You should pretend that the line ends at POINT.
 
-   Returns NULL if there are no more completions, else a pointer to a string
-   which is a possible completion, it is the caller's responsibility to
-   free the string.  */
+   Returns NULL if there are no more completions, else a pointer to a
+   string which is a possible completion, it is the caller's
+   responsibility to free the string.  */
 
 static char *
 line_completion_function (const char *text, int matches, 
                          char *line_buffer, int point)
 {
-  static char **list = (char **) NULL; /* Cache of completions.  */
+  static VEC (char_ptr) *list = NULL;  /* Cache of completions.  */
   static int index;                    /* Next cached completion.  */
   char *output = NULL;
 
   if (matches == 0)
     {
-      /* The caller is beginning to accumulate a new set of completions, so
-         we need to find all of them now, and cache them for returning one at
-         a time on future calls.  */
+      /* The caller is beginning to accumulate a new set of
+         completions, so we need to find all of them now, and cache
+         them for returning one at a time on future calls.  */
 
       if (list)
        {
-         /* Free the storage used by LIST, but not by the strings inside.
-            This is because rl_complete_internal () frees the strings.
-            As complete_line may abort by calling `error' clear LIST now.  */
-         xfree (list);
-         list = NULL;
+         /* Free the storage used by LIST, but not by the strings
+            inside.  This is because rl_complete_internal () frees
+            the strings.  As complete_line may abort by calling
+            `error' clear LIST now.  */
+         VEC_free (char_ptr, list);
        }
       index = 0;
       list = complete_line (text, line_buffer, point);
     }
 
-  /* If we found a list of potential completions during initialization then
-     dole them out one at a time.  The vector of completions is NULL
-     terminated, so after returning the last one, return NULL (and continue
-     to do so) each time we are called after that, until a new list is
-     available.  */
+  /* If we found a list of potential completions during initialization
+     then dole them out one at a time.  After returning the last one,
+     return NULL (and continue to do so) each time we are called after
+     that, until a new list is available.  */
 
   if (list)
     {
-      output = list[index];
-      if (output)
+      if (index < VEC_length (char_ptr, list))
        {
+         output = VEC_index (char_ptr, list, index);
          index++;
        }
     }
@@ -808,8 +915,8 @@ line_completion_function (const char *text, int matches,
   /* Can't do this because readline hasn't yet checked the word breaks
      for figuring out whether to insert a quote.  */
   if (output == NULL)
-    /* Make sure the word break characters are set back to normal for the
-       next time that readline tries to complete something.  */
+    /* Make sure the word break characters are set back to normal for
+       the next time that readline tries to complete something.  */
     rl_completer_word_break_characters =
       current_language->la_word_break_characters();
 #endif
@@ -818,16 +925,17 @@ line_completion_function (const char *text, int matches,
 }
 
 /* Skip over the possibly quoted word STR (as defined by the quote
-   characters QUOTECHARS and the the word break characters
-   BREAKCHARS).  Returns pointer to the location after the "word".  If
-   either QUOTECHARS or BREAKCHARS is NULL, use the same values used
-   by the completer.  */
-
-char *
-skip_quoted_chars (char *str, char *quotechars, char *breakchars)
+   characters QUOTECHARS and the word break characters BREAKCHARS).
+   Returns pointer to the location after the "word".  If either
+   QUOTECHARS or BREAKCHARS is NULL, use the same values used by the
+   completer.  */
+
+const char *
+skip_quoted_chars (const char *str, const char *quotechars,
+                  const char *breakchars)
 {
   char quote_char = '\0';
-  char *scan;
+  const char *scan;
 
   if (quotechars == NULL)
     quotechars = gdb_completer_quote_characters;
@@ -849,7 +957,7 @@ skip_quoted_chars (char *str, char *quotechars, char *breakchars)
        }
       else if (strchr (quotechars, *scan))
        {
-         /* Found start of a quoted string. */
+         /* Found start of a quoted string.  */
          quote_char = *scan;
        }
       else if (strchr (breakchars, *scan))
@@ -865,8 +973,8 @@ skip_quoted_chars (char *str, char *quotechars, char *breakchars)
    characters and word break characters used by the completer).
    Returns pointer to the location after the "word".  */
 
-char *
-skip_quoted (char *str)
+const char *
+skip_quoted (const char *str)
 {
   return skip_quoted_chars (str, NULL, NULL);
 }
This page took 0.039618 seconds and 4 git commands to generate.