diff options
Diffstat (limited to 'gdb/completer.c')
-rw-r--r-- | gdb/completer.c | 218 |
1 files changed, 196 insertions, 22 deletions
diff --git a/gdb/completer.c b/gdb/completer.c index d1ebf67f08c..7fc27b17782 100644 --- a/gdb/completer.c +++ b/gdb/completer.c @@ -27,6 +27,7 @@ #include "reggroups.h" #include "user-regs.h" #include "arch-utils.h" +#include "location.h" #include "cli/cli-decode.h" @@ -43,6 +44,21 @@ #include "completer.h" +/* An enumeration of the various things a user might + attempt to complete for a location. */ + +enum explicit_location_match_type +{ + /* The filename of a source file. */ + MATCH_SOURCE, + + /* The name of a function or method. */ + MATCH_FUNCTION, + + /* The name of a label. */ + MATCH_LABEL +}; + /* Prototypes for local functions. */ static char *line_completion_function (const char *text, int matches, @@ -175,7 +191,7 @@ filename_completer (struct cmd_list_element *ignore, return return_val; } -/* Complete on locations, which might be of two possible forms: +/* Complete on linespecs, which might be of two possible forms: file:line or @@ -184,9 +200,9 @@ filename_completer (struct cmd_list_element *ignore, 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) +static VEC (char_ptr) * +linespec_location_completer (struct cmd_list_element *ignore, + const char *text, const char *word) { int n_syms, n_files, ix; VEC (char_ptr) *fn_list = NULL; @@ -333,6 +349,182 @@ location_completer (struct cmd_list_element *ignore, return list; } +/* A helper function to collect explicit location matches for the given + LOCATION, which is attempting to match on WORD. */ + +static VEC (char_ptr) * +collect_explicit_location_matches (struct event_location *location, + enum explicit_location_match_type what, + const char *word) +{ + VEC (char_ptr) *matches = NULL; + const struct explicit_location *explicit = get_explicit_location (location); + + switch (what) + { + case MATCH_SOURCE: + { + const char *text = (explicit->source_filename == NULL + ? "" : explicit->source_filename); + + matches = make_source_files_completion_list (text, word); + } + break; + + case MATCH_FUNCTION: + { + const char *text = (explicit->function_name == NULL + ? "" : explicit->function_name); + + if (explicit->source_filename != NULL) + { + matches + = make_file_symbol_completion_list (text, word, + explicit->source_filename); + } + else + matches = make_symbol_completion_list (text, word); + } + break; + + case MATCH_LABEL: + /* Not supported. */ + break; + + default: + gdb_assert_not_reached ("unhandled explicit_location_match_type"); + } + + return matches; +} + +/* A convenience macro to (safely) back up P to the previous word. */ + +static const char * +backup_text_ptr (const char *p, const char *text) +{ + while (p > text && isspace (*p)) + --p; + for (; p > text && !isspace (p[-1]); --p) + ; + + return p; +} + +/* A completer function for explicit locations. This function + completes both options ("-source", "-line", etc) and values. */ + +static VEC (char_ptr) * +explicit_location_completer (struct cmd_list_element *ignore, + struct event_location *location, + const char *text, const char *word) +{ + const char *p; + VEC (char_ptr) *matches = NULL; + + /* Find the beginning of the word. This is necessary because + we need to know if we are completing an option name or value. We + don't get the leading '-' from the completer. */ + p = backup_text_ptr (word, text); + + if (*p == '-') + { + /* Completing on option name. */ + static const char *const keywords[] = + { + "source", + "function", + "line", + "label", + NULL + }; + + /* Skip over the '-'. */ + ++p; + + return complete_on_enum (keywords, p, p); + } + else + { + /* Completing on value (or unknown). Get the previous word to see what + the user is completing on. */ + size_t len, offset; + const char *new_word, *end; + enum explicit_location_match_type what; + struct explicit_location *explicit = get_explicit_location (location); + + /* Backup P to the previous word, which should be the option + the user is attempting to complete. */ + offset = word - p; + end = --p; + p = backup_text_ptr (p, text); + len = end - p; + + if (strncmp (p, "-source", len) == 0) + { + what = MATCH_SOURCE; + new_word = explicit->source_filename + offset; + } + else if (strncmp (p, "-function", len) == 0) + { + what = MATCH_FUNCTION; + new_word = explicit->function_name + offset; + } + else if (strncmp (p, "-label", len) == 0) + { + what = MATCH_LABEL; + new_word = explicit->label_name + offset; + } + else + { + /* The user isn't completing on any valid option name, + e.g., "break -source foo.c [tab]". */ + return NULL; + } + + /* If the user hasn't entered a search expression, e.g., + "break -function <TAB><TAB>", new_word will be NULL, but + search routines require non-NULL search words. */ + if (new_word == NULL) + new_word = ""; + + /* Now gather matches */ + matches = collect_explicit_location_matches (location, what, new_word); + } + + return matches; +} + +/* A completer for locations. */ + +VEC (char_ptr) * +location_completer (struct cmd_list_element *ignore, + const char *text, const char *word) +{ + VEC (char_ptr) *matches = NULL; + const char *copy = text; + struct event_location *location; + + location = string_to_explicit_location (©, current_language, 1); + if (location != NULL) + { + struct cleanup *cleanup; + + cleanup = make_cleanup_delete_event_location (location); + matches = explicit_location_completer (ignore, location, text, word); + do_cleanups (cleanup); + } + else + { + /* This is an address or linespec location. + Right now both of these are handled by the (old) linespec + completer. */ + matches = linespec_location_completer (ignore, text, word); + } + + return matches; +} + /* Helper for expression_completer which recursively adds field and method names from TYPE, a struct or union type, to the array OUTPUT. */ @@ -688,16 +880,6 @@ complete_line_internal (const char *text, rl_completer_word_break_characters = gdb_completer_file_name_break_characters; } - else if (c->completer == location_completer) - { - /* Commands which complete on locations want to - see the entire argument. */ - for (p = word; - p > tmp_command - && p[-1] != ' ' && p[-1] != '\t'; - p--) - ; - } if (reason == handle_brkchars && c->completer_handle_brkchars != NULL) (*c->completer_handle_brkchars) (c, p, word); @@ -766,14 +948,6 @@ complete_line_internal (const char *text, rl_completer_word_break_characters = gdb_completer_file_name_break_characters; } - else if (c->completer == location_completer) - { - for (p = word; - p > tmp_command - && p[-1] != ' ' && p[-1] != '\t'; - p--) - ; - } if (reason == handle_brkchars && c->completer_handle_brkchars != NULL) (*c->completer_handle_brkchars) (c, p, word); |