gdb/testsuite/
[binutils-gdb.git] / gdb / completer.c
index 163a9dcfc83184c2c703845ce5ebd79b96609fef..3ba481ee52c4f75ac69584c8f64e7eec68001d97 100644 (file)
@@ -1,5 +1,6 @@
 /* Line completion stuff for GDB, the GNU debugger.
 /* Line completion stuff for GDB, the GNU debugger.
-   Copyright (C) 2000, 2001, 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2007, 2008, 2009, 2010
+   Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 
    This file is part of GDB.
 
@@ -22,6 +23,7 @@
 #include "expression.h"
 #include "filenames.h"         /* For DOSish file names.  */
 #include "language.h"
 #include "expression.h"
 #include "filenames.h"         /* For DOSish file names.  */
 #include "language.h"
+#include "gdb_assert.h"
 
 #include "cli/cli-decode.h"
 
 
 #include "cli/cli-decode.h"
 
@@ -77,10 +79,6 @@ static char *gdb_completer_file_name_break_characters = " \t\n*|\"';?><@";
 static char *gdb_completer_file_name_break_characters = " \t\n*|\"';:?><";
 #endif
 
 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.  */
@@ -105,14 +103,14 @@ readline_line_completion_function (const char *text, int matches)
 /* 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 **
 /* 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 (char *text, char *prefix)
+noop_completer (struct cmd_list_element *ignore, char *text, char *prefix)
 {
   return NULL;
 }
 
 /* Complete on filenames.  */
 char **
 {
   return NULL;
 }
 
 /* Complete on filenames.  */
 char **
-filename_completer (char *text, char *word)
+filename_completer (struct cmd_list_element *ignore, char *text, char *word)
 {
   int subsequent_name;
   char **return_val;
 {
   int subsequent_name;
   char **return_val;
@@ -128,6 +126,7 @@ filename_completer (char *text, char *word)
   while (1)
     {
       char *p, *q;
   while (1)
     {
       char *p, *q;
+
       p = rl_filename_completion_function (text, subsequent_name);
       if (return_val_used >= return_val_alloced)
        {
       p = rl_filename_completion_function (text, subsequent_name);
       if (return_val_used >= return_val_alloced)
        {
@@ -195,7 +194,7 @@ filename_completer (char *text, char *word)
 
    This is intended to be used in commands that set breakpoints etc.  */
 char **
 
    This is intended to be used in commands that set breakpoints etc.  */
 char **
-location_completer (char *text, char *word)
+location_completer (struct cmd_list_element *ignore, char *text, char *word)
 {
   int n_syms = 0, n_files = 0;
   char ** fn_list = NULL;
 {
   int n_syms = 0, n_files = 0;
   char ** fn_list = NULL;
@@ -339,7 +338,7 @@ location_completer (char *text, char *word)
 }
 
 /* Helper for expression_completer which recursively counts the number
 }
 
 /* Helper for expression_completer which recursively counts the number
-   of named fields in a structure or union type.  */
+   of named fields and methods in a structure or union type.  */
 static int
 count_struct_fields (struct type *type)
 {
 static int
 count_struct_fields (struct type *type)
 {
@@ -353,17 +352,26 @@ count_struct_fields (struct type *type)
       else if (TYPE_FIELD_NAME (type, i))
        ++result;
     }
       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;
 }
 
   return result;
 }
 
-/* Helper for expression_completer which recursively adds field names
-   from TYPE, a struct or union type, to the array OUTPUT.  This
-   function assumes that OUTPUT is correctly-sized.  */
+/* 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.  */
 static void
 add_struct_fields (struct type *type, int *nextp, char **output,
                   char *fieldname, int namelen)
 {
   int i;
 static void
 add_struct_fields (struct type *type, int *nextp, char **output,
                   char *fieldname, int namelen)
 {
   int i;
+  int computed_type_name = 0;
+  char *type_name = NULL;
 
   CHECK_TYPEDEF (type);
   for (i = 0; i < TYPE_NFIELDS (type); ++i)
 
   CHECK_TYPEDEF (type);
   for (i = 0; i < TYPE_NFIELDS (type); ++i)
@@ -378,16 +386,36 @@ add_struct_fields (struct type *type, int *nextp, char **output,
          ++*nextp;
        }
     }
          ++*nextp;
        }
     }
+
+  for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; --i)
+    {
+      char *name = TYPE_FN_FIELDLIST_NAME (type, i);
+
+      if (name && ! strncmp (name, fieldname, namelen))
+       {
+         if (!computed_type_name)
+           {
+             type_name = type_name_no_tag (type);
+             computed_type_name = 1;
+           }
+         /* Omit constructors from the completion list.  */
+         if (!type_name || strcmp (type_name, name))
+           {
+             output[*nextp] = xstrdup (name);
+             ++*nextp;
+           }
+       }
+    }
 }
 
 /* Complete on expressions.  Often this means completing on symbol
    names, but some language parsers also have support for completing
    field names.  */
 char **
 }
 
 /* Complete on expressions.  Often this means completing on symbol
    names, but some language parsers also have support for completing
    field names.  */
 char **
-expression_completer (char *text, char *word)
+expression_completer (struct cmd_list_element *ignore, char *text, char *word)
 {
   struct type *type;
 {
   struct type *type;
-  char *fieldname;
+  char *fieldname, *p;
 
   /* Perform a tentative parse of the expression, to see whether a
      field completion is required.  */
 
   /* Perform a tentative parse of the expression, to see whether a
      field completion is required.  */
@@ -414,22 +442,23 @@ expression_completer (char *text, char *word)
 
          add_struct_fields (type, &out, result, fieldname, flen);
          result[out] = NULL;
 
          add_struct_fields (type, &out, result, fieldname, flen);
          result[out] = NULL;
+         xfree (fieldname);
          return result;
        }
     }
          return result;
        }
     }
+  xfree (fieldname);
 
 
-  /* Not ideal but it is what we used to do before... */
-  return location_completer (text, word);
-}
+  /* Commands which complete on locations want to see the entire
+     argument.  */
+  for (p = word;
+       p > text && p[-1] != ' ' && p[-1] != '\t';
+       p--)
+    ;
 
 
-/* Complete on command names.  Used by "help".  */
-char **
-command_completer (char *text, char *word)
-{
-  return complete_on_cmdlist (cmdlist, text, word);
+  /* 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.
 
 /* 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.
 
@@ -452,18 +481,45 @@ command_completer (char *text, char *word)
    "file ../gdb.stabs/we" "ird" (needs to not break word at slash)
  */
 
    "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
 
    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.  */
+   should pretend that the line ends at POINT.
 
 
-char **
-complete_line (const char *text, char *line_buffer, int 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.
+ */
+
+static char **
+complete_line_internal (const char *text, char *line_buffer, int point,
+                       complete_line_internal_reason reason)
 {
   char **list = NULL;
   char *tmp_command, *p;
 {
   char **list = NULL;
   char *tmp_command, *p;
@@ -477,7 +533,6 @@ complete_line (const char *text, char *line_buffer, int point)
      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.  */
      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();
 
   rl_completer_word_break_characters =
     current_language->la_word_break_characters();
 
@@ -540,12 +595,14 @@ complete_line (const char *text, char *line_buffer, int point)
             This we can deal with.  */
          if (result_list)
            {
             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);
            }
          else
            {
            }
          else
            {
-             list = complete_on_cmdlist (cmdlist, p, word);
+             if (reason != handle_brkchars)
+               list = complete_on_cmdlist (cmdlist, p, word);
            }
          /* Ensure that readline does the right thing with respect to
             inserting quotes.  */
            }
          /* Ensure that readline does the right thing with respect to
             inserting quotes.  */
@@ -569,16 +626,20 @@ complete_line (const char *text, char *line_buffer, int point)
                {
                  /* It is a prefix command; what comes after it is
                     a subcommand (e.g. "info ").  */
                {
                  /* 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);
 
                  /* Ensure that readline does the right thing
                     with respect to inserting quotes.  */
                  rl_completer_word_break_characters =
                    gdb_completer_command_word_break_characters;
                }
 
                  /* 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 (reason == handle_help)
+               list = NULL;
              else if (c->enums)
                {
              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;
                }
                  rl_completer_word_break_characters =
                    gdb_completer_command_word_break_characters;
                }
@@ -604,8 +665,7 @@ complete_line (const char *text, char *line_buffer, int point)
                      rl_completer_word_break_characters =
                        gdb_completer_file_name_break_characters;
                    }
                      rl_completer_word_break_characters =
                        gdb_completer_file_name_break_characters;
                    }
-                 else if (c->completer == location_completer
-                          || c->completer == expression_completer)
+                 else if (c->completer == location_completer)
                    {
                      /* Commands which complete on locations want to
                         see the entire argument.  */
                    {
                      /* Commands which complete on locations want to
                         see the entire argument.  */
@@ -615,7 +675,8 @@ complete_line (const char *text, char *line_buffer, int point)
                           p--)
                        ;
                    }
                           p--)
                        ;
                    }
-                 list = (*c->completer) (p, word);
+                 if (reason != handle_brkchars && c->completer != NULL)
+                   list = (*c->completer) (c, p, word);
                }
            }
          else
                }
            }
          else
@@ -636,7 +697,8 @@ complete_line (const char *text, char *line_buffer, int point)
                    break;
                }
 
                    break;
                }
 
-             list = complete_on_cmdlist (result_list, q, word);
+             if (reason != handle_brkchars)
+               list = complete_on_cmdlist (result_list, q, word);
 
              /* Ensure that readline does the right thing
                 with respect to inserting quotes.  */
 
              /* Ensure that readline does the right thing
                 with respect to inserting quotes.  */
@@ -644,6 +706,8 @@ complete_line (const char *text, char *line_buffer, int point)
                gdb_completer_command_word_break_characters;
            }
        }
                gdb_completer_command_word_break_characters;
            }
        }
+      else if (reason == handle_help)
+       list = NULL;
       else
        {
          /* There is non-whitespace beyond the command.  */
       else
        {
          /* There is non-whitespace beyond the command.  */
@@ -656,7 +720,8 @@ complete_line (const char *text, char *line_buffer, int point)
            }
          else if (c->enums)
            {
            }
          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
            {
            }
          else
            {
@@ -673,8 +738,7 @@ complete_line (const char *text, char *line_buffer, int point)
                  rl_completer_word_break_characters =
                    gdb_completer_file_name_break_characters;
                }
                  rl_completer_word_break_characters =
                    gdb_completer_file_name_break_characters;
                }
-             else if (c->completer == location_completer
-                      || c->completer == expression_completer)
+             else if (c->completer == location_completer)
                {
                  for (p = word;
                       p > tmp_command
                {
                  for (p = word;
                       p > tmp_command
@@ -682,13 +746,52 @@ complete_line (const char *text, char *line_buffer, int point)
                       p--)
                    ;
                }
                       p--)
                    ;
                }
-             list = (*c->completer) (p, word);
+             if (reason != handle_brkchars && c->completer != NULL)
+               list = (*c->completer) (c, p, word);
            }
        }
     }
 
   return list;
 }
            }
        }
     }
 
   return list;
 }
+/* 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.
+
+   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.  */
+
+char **
+complete_line (const char *text, char *line_buffer, int point)
+{
+  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)
+{
+  return complete_line_internal (word, text, strlen (text), handle_help);
+}
+
+/* Get the list of chars that are considered as word breaks
+   for the current command.  */
+
+char *
+gdb_completion_word_break_characters (void)
+{
+  char **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.
 
 /* Generate completions one by one for the completer.  Each time we are
    called return another potential completion to the caller.
@@ -728,8 +831,10 @@ line_completion_function (const char *text, int matches,
       if (list)
        {
          /* Free the storage used by LIST, but not by the strings inside.
       if (list)
        {
          /* Free the storage used by LIST, but not by the strings inside.
-            This is because rl_complete_internal () frees the strings.  */
+            This is because rl_complete_internal () frees the strings.
+            As complete_line may abort by calling `error' clear LIST now.  */
          xfree (list);
          xfree (list);
+         list = NULL;
        }
       index = 0;
       list = complete_line (text, line_buffer, point);
        }
       index = 0;
       list = complete_line (text, line_buffer, point);