/* Line completion stuff for GDB, the GNU debugger.
- Copyright (C) 2000, 2001, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2007, 2008, 2009 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"
#include "gdbtypes.h"
#include "expression.h"
-#include "filenames.h" /* for DOSish file names */
+#include "filenames.h" /* For DOSish file names. */
#include "language.h"
#include "cli/cli-decode.h"
#include "completer.h"
-/* Prototypes for local functions */
+/* Prototypes for local functions. */
static
char *line_completion_function (const char *text, int matches,
char *line_buffer,
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. */
+ a leading quote. */
static char *gdb_completer_command_word_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. */
+ as strings. */
static char *gdb_completer_quote_characters = "'";
\f
-/* Accessor for some completer data that may interest other files. */
+/* Accessor for some completer data that may interest other files. */
char *
get_gdb_completer_quote_characters (void)
/* 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 **
-filename_completer (char *text, char *word)
+filename_completer (struct cmd_list_element *ignore, char *text, char *word)
{
int subsequent_name;
char **return_val;
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
without also affecting the next completion. This should be fixed in
readline. FIXME. */
- /* Insure that readline does the right thing
+ /* Ensure that readline does the right thing
with respect to inserting quotes. */
rl_completer_word_break_characters = "";
#endif
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;
if (*p == quote_found)
quote_found = 0;
else
- break; /* hit the end of text */
+ break; /* Hit the end of text. */
}
#if HAVE_DOS_BASED_FILE_SYSTEM
/* If we have a DOS-style absolute file name at the beginning of
list = make_symbol_completion_list (symbol_start, word);
/* If text includes characters which cannot appear in a file
name, they cannot be asking for completion on files. */
- if (strcspn (text, gdb_completer_file_name_break_characters) == text_len)
+ if (strcspn (text,
+ gdb_completer_file_name_break_characters) == text_len)
fn_list = make_source_files_completion_list (text, text);
}
/* 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;
}
-/* 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 and methods 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;
+ }
+
+ 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. */
+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)
+ {
+ 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;
+ }
+ }
+
+ 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 **
+expression_completer (struct cmd_list_element *ignore, 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;
+ xfree (fieldname);
+ return result;
+ }
+ }
+ xfree (fieldname);
+
+ /* 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 (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.
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 =
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;
{
list = complete_on_cmdlist (cmdlist, p, word);
}
- /* Insure that readline does the right thing with respect to
+ /* Ensure that readline does the right thing with respect to
inserting quotes. */
rl_completer_word_break_characters =
gdb_completer_command_word_break_characters;
a subcommand (e.g. "info "). */
list = complete_on_cmdlist (*c->prefixlist, p, word);
- /* Insure that readline does the right thing
- with respect to inserting quotes. */
+ /* 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)
+ list = NULL;
else if (c->enums)
{
list = complete_on_enum (c->enums, p, word);
p--)
;
}
- list = (*c->completer) (p, word);
+ list = (*c->completer) (c, p, word);
}
}
else
list = complete_on_cmdlist (result_list, q, word);
- /* Insure that readline does the right thing
- with respect to inserting quotes. */
+ /* 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)
+ list = NULL;
else
{
/* There is non-whitespace beyond the command. */
p--)
;
}
- list = (*c->completer) (p, word);
+ list = (*c->completer) (c, p, word);
}
}
}
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 (struct cmd_list_element *ignore, 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
free the string. */
static char *
-line_completion_function (const char *text, int matches, char *line_buffer, int point)
+line_completion_function (const char *text, int matches,
+ char *line_buffer, int point)
{
- static char **list = (char **) NULL; /* Cache of completions */
- static int index; /* Next cached completion */
+ static char **list = (char **) 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. */
+ 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. */
+ This is because rl_complete_internal () frees the strings.
+ As complete_line may abort by calling `error' clear LIST now. */
xfree (list);
+ list = NULL;
}
index = 0;
list = complete_line (text, line_buffer, point);
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. */
+ available. */
if (list)
{
{
if (quote_char != '\0')
{
- /* Ignore everything until the matching close quote char */
+ /* Ignore everything until the matching close quote char. */
if (*scan == quote_char)
{
- /* Found matching close quote. */
+ /* Found matching close quote. */
scan++;
break;
}
/* Skip over the possibly quoted word STR (as defined by the quote
characters and word break characters used by the completer).
- Returns pointer to the location after the "word". */
+ Returns pointer to the location after the "word". */
char *
skip_quoted (char *str)