diff options
author | Keith Seitz <keiths@redhat.com> | 2015-08-11 17:09:36 -0700 |
---|---|---|
committer | Keith Seitz <keiths@redhat.com> | 2015-08-11 17:09:36 -0700 |
commit | 87f0e7204722a986f79f245eee716f0870832d47 (patch) | |
tree | 80936c86b139d303a7139c46ae00b55f89c91f8d /gdb/completer.c | |
parent | 00e52e5376c7ec604a739e6242e6be36221162d7 (diff) | |
download | gdb-87f0e7204722a986f79f245eee716f0870832d47.zip gdb-87f0e7204722a986f79f245eee716f0870832d47.tar.gz gdb-87f0e7204722a986f79f245eee716f0870832d47.tar.bz2 |
Explicit locations: add UI features for CLI
This patch exposes explicit locations to the CLI user. This enables
users to "explicitly" specify attributes of the breakpoint location
to avoid any ambiguity that might otherwise exist with linespecs.
The general syntax of explicit locations is:
-source SOURCE_FILENAME -line {+-}LINE -function FUNCTION_NAME
-label LABEL_NAME
Option names may be abbreviated, e.g., "-s SOURCE_FILENAME -li 3" and users
may use the completer with either options or values.
gdb/ChangeLog:
* completer.c: Include location.h.
(enum match_type): New enum.
(location_completer): Rename to ...
(linespec_completer): ... this.
(collect_explicit_location_matches, backup_text_ptr)
(explicit_location_completer): New functions.
(location_completer): "New" function; handle linespec
and explicit location completions.
(complete_line_internal): Remove all location completer-specific
handling.
* linespec.c (linespec_lexer_lex_keyword, is_ada_operator)
(find_toplevel_char): Export.
(linespec_parse_line_offset): Export.
Issue error if STRING is not numerical.
(gdb_get_linespec_parser_quote_characters): New function.
* linespec.h (linespec_parse_line_offset): Declare.
(get_gdb_linespec_parser_quote_characters): Declare.
(is_ada_operator): Declare.
(find_toplevel_char): Declare.
(linespec_lexer_lex_keyword): Declare.
* location.c (explicit_to_event_location): New function.
(explicit_location_lex_one): New function.
(string_to_explicit_location): New function.
(string_to_event_location): Handle explicit locations.
* location.h (explicit_to_event_location): Declare.
(string_to_explicit_location): Declare.
gdb/testsuite/ChangeLog:
* gdb.linespec/3explicit.c: New file.
* gdb.linespec/cpexplicit.cc: New file.
* gdb.linespec/cpexplicit.exp: New file.
* gdb.linespec/explicit.c: New file.
* gdb.linespec/explicit.exp: New file.
* gdb.linespec/explicit2.c: New file.
* gdb.linespec/ls-errs.exp: Add explicit location tests.
* lib/gdb.exp (capture_command_output): Regexp-escape `command'
before using in the matching pattern.
Clarify that `prefix' is a regular expression.
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 d1ebf67..7fc27b1 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); |