X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fcompleter.c;h=48a4e463a7f7c6cf325696382f06f76f0c307595;hb=2c02bd729076b940958bccf68f1cc0b1ecf8403b;hp=d109140ee3e0bc6e620ca43667d98697f9339106;hpb=a0b7aece708587e6c4a33d9c62fd0fe73b990b6b;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/completer.c b/gdb/completer.c index d109140ee3..48a4e463a7 100644 --- a/gdb/completer.c +++ b/gdb/completer.c @@ -1,5 +1,5 @@ /* Line completion stuff for GDB, the GNU debugger. - Copyright (C) 2000, 2001, 2007, 2008 Free Software Foundation, Inc. + Copyright (C) 2000-2001, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -22,6 +22,8 @@ #include "expression.h" #include "filenames.h" /* For DOSish file names. */ #include "language.h" +#include "gdb_assert.h" +#include "exceptions.h" #include "cli/cli-decode.h" @@ -47,21 +49,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 +80,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 = "'"; /* Accessor for some completer data that may interest other files. */ @@ -99,20 +98,23 @@ 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. */ +/* 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; @@ -128,6 +130,7 @@ filename_completer (char *text, char *word) while (1) { char *p, *q; + p = rl_filename_completion_function (text, subsequent_name); if (return_val_used >= return_val_alloced) { @@ -142,12 +145,12 @@ filename_completer (char *text, char *word) 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); @@ -177,9 +180,9 @@ filename_completer (char *text, char *word) } } #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,9 +196,12 @@ filename_completer (char *text, char *word) or symbol+offset - This is intended to be used in commands that set breakpoints etc. */ + 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; @@ -339,7 +345,7 @@ location_completer (char *text, char *word) } /* 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) { @@ -351,31 +357,80 @@ count_struct_fields (struct type *type) if (i < TYPE_N_BASECLASSES (type)) result += count_struct_fields (TYPE_BASECLASS (type, i)); else if (TYPE_FIELD_NAME (type, i)) + { + if (TYPE_FIELD_NAME (type, i)[0] != '\0') + ++result; + else if (TYPE_CODE (TYPE_FIELD_TYPE (type, i)) == TYPE_CODE_UNION) + { + /* Recurse into anonymous unions. */ + result += count_struct_fields (TYPE_FIELD_TYPE (type, i)); + } + } + } + + 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 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; + 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)) + add_struct_fields (TYPE_BASECLASS (type, i), nextp, + 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)) + { + output[*nextp] = xstrdup (TYPE_FIELD_NAME (type, i)); + ++*nextp; + } + } + else if (TYPE_CODE (TYPE_FIELD_TYPE (type, i)) == TYPE_CODE_UNION) + { + /* Recurse into anonymous unions. */ + add_struct_fields (TYPE_FIELD_TYPE (type, i), nextp, + output, fieldname, namelen); + } + } + } + + 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; + } } } } @@ -384,15 +439,22 @@ add_struct_fields (struct type *type, int *nextp, char **output, 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 = NULL; char *fieldname, *p; + volatile struct gdb_exception except; /* 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_field_expression (text, &fieldname); + } + if (except.reason < 0) + return NULL; if (fieldname && type) { for (;;) @@ -427,12 +489,13 @@ expression_completer (char *text, char *word) p--) ; - /* Not ideal but it is what we used to do before... */ - return location_completer (p, 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. "show output-" "radix" "show output" "-radix" @@ -453,24 +516,46 @@ expression_completer (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) +complete_line_internal (const char *text, + char *line_buffer, int point, + complete_line_internal_reason reason) { char **list = NULL; char *tmp_command, *p; @@ -478,17 +563,18 @@ complete_line_internal (const char *text, char *line_buffer, int point, 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; @@ -503,7 +589,7 @@ 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 @@ -523,7 +609,7 @@ 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; @@ -547,12 +633,14 @@ 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); } 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. */ @@ -566,28 +654,31 @@ 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); /* 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; } @@ -623,13 +714,14 @@ complete_line_internal (const char *text, char *line_buffer, int point, p--) ; } - list = (*c->completer) (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; @@ -644,7 +736,8 @@ 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); /* Ensure that readline does the right thing with respect to inserting quotes. */ @@ -652,7 +745,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 { @@ -666,7 +759,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 { @@ -677,7 +771,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 = @@ -691,49 +786,76 @@ complete_line_internal (const char *text, char *line_buffer, int point, p--) ; } - list = (*c->completer) (p, word); + if (reason != handle_brkchars && c->completer != NULL) + list = (*c->completer) (c, p, word); } } } 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. -/* 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) { - 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 (char *text, char *word) +command_completer (struct cmd_list_element *ignore, + char *text, 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. +/* 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. + 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, @@ -745,25 +867,28 @@ line_completion_function (const char *text, int matches, 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. */ + /* 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; } 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. 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 (list) { @@ -778,8 +903,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 @@ -788,10 +913,10 @@ 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. */ + 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. */ char * skip_quoted_chars (char *str, char *quotechars, char *breakchars) @@ -819,7 +944,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))