/* Line completion stuff for GDB, the GNU debugger.
- Copyright (C) 2000, 2001, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2007, 2008 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "symtab.h"
subsequent_name = 0;
while (1)
{
- char *p;
+ char *p, *q;
p = rl_filename_completion_function (text, subsequent_name);
if (return_val_used >= return_val_alloced)
{
/* Like emacs, don't complete on old versions. Especially useful
in the "source" command. */
if (p[strlen (p) - 1] == '~')
- continue;
+ {
+ xfree (p);
+ continue;
+ }
- {
- char *q;
- if (word == text)
- /* Return exactly p. */
- return_val[return_val_used++] = 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
- {
- /* Return some of TEXT plus p. */
- q = xmalloc (strlen (p) + (text - word) + 5);
- strncpy (q, word, text - word);
- q[text - word] = '\0';
- strcat (q, p);
- return_val[return_val_used++] = q;
- xfree (p);
- }
- }
+ if (word == text)
+ /* Return exactly p. */
+ return_val[return_val_used++] = 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
+ {
+ /* Return some of TEXT plus p. */
+ q = xmalloc (strlen (p) + (text - word) + 5);
+ strncpy (q, word, text - word);
+ q[text - word] = '\0';
+ strcat (q, p);
+ return_val[return_val_used++] = q;
+ xfree (p);
+ }
}
#if 0
/* There is no way to do this just long enough to affect quote inserting
return list;
}
-/* Complete on command names. Used by "help". */
-char **
-command_completer (char *text, char *word)
+/* Helper for expression_completer which recursively counts the number
+ of named fields in a structure or union type. */
+static int
+count_struct_fields (struct type *type)
{
- return complete_on_cmdlist (cmdlist, text, word);
+ 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;
+ }
+ 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. */
+static void
+add_struct_fields (struct type *type, int *nextp, char **output,
+ char *fieldname, int namelen)
+{
+ int i;
+
+ 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))
+ {
+ output[*nextp] = xstrdup (TYPE_FIELD_NAME (type, i));
+ ++*nextp;
+ }
+ }
}
+/* 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)
+{
+ struct type *type;
+ char *fieldname, *p;
+
+ /* Perform a tentative parse of the expression, to see whether a
+ field completion is required. */
+ fieldname = NULL;
+ type = parse_field_expression (text, &fieldname);
+ if (fieldname && type)
+ {
+ for (;;)
+ {
+ CHECK_TYPEDEF (type);
+ if (TYPE_CODE (type) != TYPE_CODE_PTR
+ && TYPE_CODE (type) != TYPE_CODE_REF)
+ break;
+ type = TYPE_TARGET_TYPE (type);
+ }
+
+ 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 *));
+
+ add_struct_fields (type, &out, result, fieldname, flen);
+ result[out] = NULL;
+ return result;
+ }
+ }
+
+ /* Commands which complete on locations want to see the entire
+ argument. */
+ for (p = word;
+ p > text && p[-1] != ' ' && p[-1] != '\t';
+ p--)
+ ;
+
+ /* Not ideal but it is what we used to do before... */
+ return location_completer (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.
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)
+ should pretend that the line ends at POINT.
+
+ FOR_HELP is true 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)
{
char **list = NULL;
char *tmp_command, *p;
rl_completer_word_break_characters =
gdb_completer_command_word_break_characters;
}
+ else if (for_help)
+ list = NULL;
else if (c->enums)
{
list = complete_on_enum (c->enums, p, word);
gdb_completer_command_word_break_characters;
}
}
+ else if (for_help)
+ list = NULL;
else
{
/* There is non-whitespace beyond the command. */
return list;
}
+/* Like complete_line_internal, but always passes 0 for FOR_HELP. */
+
+char **
+complete_line (const char *text, char *line_buffer, int point)
+{
+ return complete_line_internal (text, line_buffer, point, 0);
+}
+
+/* Complete on command names. Used by "help". */
+char **
+command_completer (char *text, char *word)
+{
+ return complete_line_internal (word, text, strlen (text), 1);
+}
+
/* 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