diff options
author | Pedro Alves <palves@redhat.com> | 2017-07-17 20:24:41 +0100 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2017-07-17 20:24:41 +0100 |
commit | a245927022bc4351fafd9e6275e217021ec93e08 (patch) | |
tree | 0446dc2f9ce7476bc3ef3d8649c419b86b20378e /gdb/linespec.c | |
parent | c6756f62e04846d68c24ee922ddb0377d4bd17f2 (diff) | |
download | gdb-a245927022bc4351fafd9e6275e217021ec93e08.zip gdb-a245927022bc4351fafd9e6275e217021ec93e08.tar.gz gdb-a245927022bc4351fafd9e6275e217021ec93e08.tar.bz2 |
Explicit locations -label completer
We're missing a completer for
(gdb) break -function func -label [TAB]
This patch adds one. Tests will be added later in the series.
gdb/ChangeLog:
2017-07-17 Pedro Alves <palves@redhat.com>
* completer.c (collect_explicit_location_matches): Handle
MATCH_LABEL.
(convert_explicit_location_to_linespec): New, factored out from
...
(convert_explicit_location_to_sals): ... this.
(complete_label): New.
(linespec_complete_label, find_label_symbols_in_block): New.
(find_label_symbols): Add completion_mode parameter and adjust to
call find_label_symbols_in_block.
* linespec.h (linespec_complete_label): Declare.
Diffstat (limited to 'gdb/linespec.c')
-rw-r--r-- | gdb/linespec.c | 199 |
1 files changed, 159 insertions, 40 deletions
diff --git a/gdb/linespec.c b/gdb/linespec.c index 20ac71d..0216bf1 100644 --- a/gdb/linespec.c +++ b/gdb/linespec.c @@ -299,7 +299,8 @@ static VEC (symtab_ptr) *symtabs_from_filename (const char *, static VEC (symbolp) *find_label_symbols (struct linespec_state *self, VEC (symbolp) *function_symbols, VEC (symbolp) **label_funcs_ret, - const char *name); + const char *name, + bool completion_mode = false); static void find_linespec_symbols (struct linespec_state *self, VEC (symtab_ptr) *file_symtabs, @@ -2053,31 +2054,33 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls) return sals; } -/* Convert the explicit location EXPLICIT_LOC into SaLs. */ +/* Build RESULT from the explicit location components SOURCE_FILENAME, + FUNCTION_NAME, LABEL_NAME and LINE_OFFSET. */ -static struct symtabs_and_lines -convert_explicit_location_to_sals (struct linespec_state *self, - linespec_p result, - const struct explicit_location *explicit_loc) +static void +convert_explicit_location_to_linespec (struct linespec_state *self, + linespec_p result, + const char *source_filename, + const char *function_name, + const char *label_name, + struct line_offset line_offset) { VEC (symbolp) *symbols, *labels; VEC (bound_minimal_symbol_d) *minimal_symbols; - if (explicit_loc->source_filename != NULL) + if (source_filename != NULL) { TRY { result->file_symtabs - = symtabs_from_filename (explicit_loc->source_filename, - self->search_pspace); + = symtabs_from_filename (source_filename, self->search_pspace); } CATCH (except, RETURN_MASK_ERROR) { - source_file_not_found_error (explicit_loc->source_filename); + source_file_not_found_error (source_filename); } END_CATCH - result->explicit_loc.source_filename - = xstrdup (explicit_loc->source_filename); + result->explicit_loc.source_filename = xstrdup (source_filename); } else { @@ -2085,41 +2088,53 @@ convert_explicit_location_to_sals (struct linespec_state *self, VEC_safe_push (symtab_ptr, result->file_symtabs, NULL); } - if (explicit_loc->function_name != NULL) + if (function_name != NULL) { find_linespec_symbols (self, result->file_symtabs, - explicit_loc->function_name, &symbols, + function_name, &symbols, &minimal_symbols); if (symbols == NULL && minimal_symbols == NULL) - symbol_not_found_error (explicit_loc->function_name, + symbol_not_found_error (function_name, result->explicit_loc.source_filename); - result->explicit_loc.function_name - = xstrdup (explicit_loc->function_name); + result->explicit_loc.function_name = xstrdup (function_name); result->function_symbols = symbols; result->minimal_symbols = minimal_symbols; } - if (explicit_loc->label_name != NULL) + if (label_name != NULL) { symbols = NULL; labels = find_label_symbols (self, result->function_symbols, - &symbols, explicit_loc->label_name); + &symbols, label_name); if (labels == NULL) undefined_label_error (result->explicit_loc.function_name, - explicit_loc->label_name); + label_name); - result->explicit_loc.label_name = xstrdup (explicit_loc->label_name); + result->explicit_loc.label_name = xstrdup (label_name); result->labels.label_symbols = labels; result->labels.function_symbols = symbols; } - if (explicit_loc->line_offset.sign != LINE_OFFSET_UNKNOWN) - result->explicit_loc.line_offset = explicit_loc->line_offset; + if (line_offset.sign != LINE_OFFSET_UNKNOWN) + result->explicit_loc.line_offset = line_offset; +} - return convert_linespec_to_sals (self, result); +/* Convert the explicit location EXPLICIT_LOC into SaLs. */ + +static struct symtabs_and_lines +convert_explicit_location_to_sals (struct linespec_state *self, + linespec_p result, + const struct explicit_location *explicit_loc) +{ + convert_explicit_location_to_linespec (self, result, + explicit_loc->source_filename, + explicit_loc->function_name, + explicit_loc->label_name, + explicit_loc->line_offset); + return convert_linespec_to_sals (self, result); } /* Parse a string that specifies a linespec. @@ -2470,6 +2485,69 @@ linespec_complete_function (completion_tracker &tracker, collect_symbol_completion_matches (tracker, mode, function, function); } +/* Helper for linespec_complete_label. Find labels that match + LABEL_NAME in the function symbols listed in the PARSER, and add + them to the tracker. */ + +static void +complete_label (completion_tracker &tracker, + linespec_parser *parser, + const char *label_name) +{ + VEC (symbolp) *label_function_symbols = NULL; + VEC (symbolp) *labels + = find_label_symbols (PARSER_STATE (parser), + PARSER_RESULT (parser)->function_symbols, + &label_function_symbols, + label_name, true); + + symbol *label; + for (int ix = 0; + VEC_iterate (symbolp, labels, ix, label); ++ix) + { + char *match = xstrdup (SYMBOL_SEARCH_NAME (label)); + tracker.add_completion (gdb::unique_xmalloc_ptr<char> (match)); + } + VEC_free (symbolp, labels); +} + +/* See linespec.h. */ + +void +linespec_complete_label (completion_tracker &tracker, + const struct language_defn *language, + const char *source_filename, + const char *function_name, + const char *label_name) +{ + linespec_parser parser; + struct cleanup *cleanup; + + linespec_parser_new (&parser, 0, language, NULL, NULL, 0, NULL); + cleanup = make_cleanup (linespec_parser_delete, &parser); + + line_offset unknown_offset = { 0, LINE_OFFSET_UNKNOWN }; + + TRY + { + convert_explicit_location_to_linespec (PARSER_STATE (&parser), + PARSER_RESULT (&parser), + source_filename, + function_name, + NULL, unknown_offset); + } + CATCH (ex, RETURN_MASK_ERROR) + { + do_cleanups (cleanup); + return; + } + END_CATCH + + complete_label (tracker, &parser, label_name); + + do_cleanups (cleanup); +} + /* A helper function for decode_line_full and decode_line_1 to turn LOCATION into symtabs_and_lines. */ @@ -3385,13 +3463,63 @@ find_linespec_symbols (struct linespec_state *state, } } -/* Return all labels named NAME in FUNCTION_SYMBOLS. Return the - actual function symbol in which the label was found in LABEL_FUNC_RET. */ +/* Helper for find_label_symbols. Find all labels that match name + NAME in BLOCK. Return all labels that match in FUNCTION_SYMBOLS. + Return the actual function symbol in which the label was found in + LABEL_FUNC_RET. If COMPLETION_MODE is true, then NAME is + interpreted as a label name prefix. Otherwise, only a label named + exactly NAME match. */ + +static void +find_label_symbols_in_block (const struct block *block, + const char *name, struct symbol *fn_sym, + bool completion_mode, + VEC (symbolp) **result, + VEC (symbolp) **label_funcs_ret) +{ + if (completion_mode) + { + struct block_iterator iter; + struct symbol *sym; + size_t name_len = strlen (name); + + int (*cmp) (const char *, const char *, size_t); + cmp = case_sensitivity == case_sensitive_on ? strncmp : strncasecmp; + + ALL_BLOCK_SYMBOLS (block, iter, sym) + { + if (symbol_matches_domain (SYMBOL_LANGUAGE (sym), + SYMBOL_DOMAIN (sym), LABEL_DOMAIN) + && cmp (SYMBOL_SEARCH_NAME (sym), name, name_len) == 0) + { + VEC_safe_push (symbolp, *result, sym); + VEC_safe_push (symbolp, *label_funcs_ret, fn_sym); + } + } + } + else + { + struct symbol *sym = lookup_symbol (name, block, LABEL_DOMAIN, 0).symbol; + + if (sym != NULL) + { + VEC_safe_push (symbolp, *result, sym); + VEC_safe_push (symbolp, *label_funcs_ret, fn_sym); + } + } +} + +/* Return all labels that match name NAME in FUNCTION_SYMBOLS. Return + the actual function symbol in which the label was found in + LABEL_FUNC_RET. If COMPLETION_MODE is true, then NAME is + interpreted as a label name prefix. Otherwise, only labels named + exactly NAME match. */ static VEC (symbolp) * find_label_symbols (struct linespec_state *self, VEC (symbolp) *function_symbols, - VEC (symbolp) **label_funcs_ret, const char *name) + VEC (symbolp) **label_funcs_ret, const char *name, + bool completion_mode) { int ix; const struct block *block; @@ -3412,13 +3540,8 @@ find_label_symbols (struct linespec_state *self, return NULL; fn_sym = BLOCK_FUNCTION (block); - sym = lookup_symbol (name, block, LABEL_DOMAIN, 0).symbol; - - if (sym != NULL) - { - VEC_safe_push (symbolp, result, sym); - VEC_safe_push (symbolp, *label_funcs_ret, fn_sym); - } + find_label_symbols_in_block (block, name, fn_sym, completion_mode, + &result, label_funcs_ret); } else { @@ -3427,13 +3550,9 @@ find_label_symbols (struct linespec_state *self, { set_current_program_space (SYMTAB_PSPACE (symbol_symtab (fn_sym))); block = SYMBOL_BLOCK_VALUE (fn_sym); - sym = lookup_symbol (name, block, LABEL_DOMAIN, 0).symbol; - if (sym != NULL) - { - VEC_safe_push (symbolp, result, sym); - VEC_safe_push (symbolp, *label_funcs_ret, fn_sym); - } + find_label_symbols_in_block (block, name, fn_sym, completion_mode, + &result, label_funcs_ret); } } |