Introduce class completion_tracker & rewrite completion<->readline interaction
This patch reworks the whole completion machinery, and prepares it for later enhancements. Adds a new "completion_tracker" class that is meant to hold everything about the state of the current completion operation. This class now has the responsibility of tracking the list of completion matches, and checking whether the max completions limit has been reached. You can look at this as this patch starting out by C++fying the existing "completion_tracker" in symtab.c (it's just an htab_t typedef currently), moving it to completer.h/c, and then making it a class/generalizing/enhancing it. Unlike with the current tracking, completion_tracker now checks whether the limit has been reached on each completion match list insertion. This both simplifies the max-completions handling code (maybe_add_completion_enum is gone, for example), and is a prerequisite for follow up patches. The current completion_tracker is only used for symbol completions, and the symbol code gets at the current instance via globals. This patch cleans that up by adding a completion_tracker reference to the signature of the completion functions, and passing the tracker around everywhere necessary. Then, the patch changes how the completion match list is handed over to readline. Currently, we're using the rl_completion_entry_function readline entry point, and the patch switches to rl_attempted_completion_function. A following patch will want to let GDB itself decide the common completion prefix between all matches (what readline calls the "lowest common denominator"), instead of having readline compute it, and that's not possible with the rl_completion_entry_function entry point. Also, rl_attempted_completion_function lets GDB hand over the match list to readline as an array in one go instead of passing down matches one by one, so from that angle it's a nicer entry point anyway. Lastly, the patch catches exceptions around the readline entry points, because we can't let C++ exceptions cross readline. We handle that in the readline input entry point, but the completion entry point isn't guarded, so GDB can abort if completion throws. E.g., in current master: (gdb) b -function "fun<tab> terminate called after throwing an instance of 'gdb_exception_RETURN_MASK_ERROR' Aborted (core dumped) This patch fixes that. This will be exercised in the new tests added later on in the series. gdb/ChangeLog: 2017-07-17 Pedro Alves <palves@redhat.com> * ada-lang.c (symbol_completion_match): Adjust comments. (symbol_completion_add): Replace vector parameter with completion_tracker parameter. Use it. (ada_make_symbol_completion_list): Rename to... (ada_collect_symbol_completion_matches): ... this. Add completion_tracker parameter and use it. (ada_language_defn): Adjust. * break-catch-syscall.c (catch_syscall_completer): Adjust prototype and work with completion_tracker instead of VEC. * breakpoint.c (condition_completer): Adjust prototype and work with completion_tracker instead of VEC. * c-lang.c (c_language_defn, cplus_language_defn) (asm_language_defn, minimal_language_defn): Adjust to renames. * cli/cli-cmds.c (complete_command): Rework using completion_tracker. Catch exceptions when completing. * cli/cli-decode.c (integer_unlimited_completer) (complete_on_cmdlist, complete_on_enum): Adjust prototype and work with completion_tracker instead of VEC. * command.h (struct completion_tracker): Forward declare. (completer_ftype, completer_handle_brkchars_ftype): Change types. (complete_on_cmdlist, complete_on_enum): Adjust. * completer.c: Include <algorithm>. (struct gdb_completer_state): New. (current_completion): New global. (readline_line_completion_function): Delete. (noop_completer, filename_completer) (filename_completer_handle_brkchars, complete_files_symbols) (linespec_location_completer): Adjust to work with a completion_tracker instead of a VEC. (string_or_empty): New. (collect_explicit_location_matches): Adjust to work with a completion_tracker instead of a VEC. (explicit_location_completer): Rename to ... (complete_explicit_location): ... this and adjust to work with a completion_tracker instead of a VEC. (location_completer): Adjust to work with a completion_tracker instead of a VEC. (add_struct_fields): Adjust to work with a completion_list instead of VEC. (expression_completer): Rename to ... (complete_expression): ... this and adjust to work with a completion_tracker instead of a VEC. Use complete_files_symbols. (expression_completer): Reimplement on top of complete_expression. (symbol_completer): Adjust to work with a completion_tracker instead of a VEC. (enum complete_line_internal_reason): Add describing comments. (complete_line_internal_normal_command): Adjust to work with a completion_tracker instead of a VEC. (complete_line_internal): Rename to ... (complete_line_internal_1): ... this and adjust to work with a completion_tracker instead of a VEC. Assert TEXT is NULL in the handle_brkchars phase. (new_completion_tracker): Delete. (complete_line_internal): Reimplement as TRY/CATCH wrapper around complete_line_internal_1. (free_completion_tracker): Delete. (INITIAL_COMPLETION_HTAB_SIZE): New. (completion_tracker::completion_tracker) (completion_tracker::~completion_tracker): New. (maybe_add_completion): Delete. (completion_tracker::maybe_add_completion) (completion_tracker::add_completion) (completion_tracker::add_completions): New. (throw_max_completions_reached_error): Delete. (complete_line): Adjust to work with a completion_tracker instead of a VEC. Don't create a completion_tracker_t or check for max completions here. (command_completer, command_completer_handle_brkchars) (signal_completer, reg_or_group_completer_1) (reg_or_group_completer, default_completer_handle_brkchars): Adjust to work with a completion_tracker. (gdb_completion_word_break_characters_throw): New. (gdb_completion_word_break_characters): Reimplement. (line_completion_function): Delete. (completion_tracker::recompute_lowest_common_denominator) (expand_preserving_ws) (completion_tracker::build_completion_result) (completion_result::completion_result) (completion_result::completion_result) (completion_result::~completion_result) (completion_result::completion_result) (completion_result::release_match_list, compare_cstrings) (completion_result::sort_match_list) (completion_result::reset_match_list) (gdb_rl_attempted_completion_function_throw) (gdb_rl_attempted_completion_function): New. * completer.h (completion_list, struct completion_result) (class completion_tracker): New. (complete_line): Add completion_tracker parameter. (readline_line_completion_function): Delete. (gdb_rl_attempted_completion_function): New. (noop_completer, filename_completer, expression_completer) (location_completer, symbol_completer, command_completer) (signal_completer, reg_or_group_completer): Update prototypes. (completion_tracker_t, new_completion_tracker) (make_cleanup_free_completion_tracker): Delete. (enum maybe_add_completion_enum): Delete. (maybe_add_completion): Delete. (throw_max_completions_reached_error): Delete. * corefile.c (complete_set_gnutarget): Adjust to work with a completion_tracker instead of a VEC. * cp-abi.c (cp_abi_completer): Adjust to work with a completion_tracker instead of a VEC. * d-lang.c (d_language_defn): Adjust. * disasm.c (disassembler_options_completer): Adjust to work with a completion_tracker instead of a VEC. * f-lang.c (f_make_symbol_completion_list): Rename to ... (f_collect_symbol_completion_matches): ... this. Adjust to work with a completion_tracker instead of a VEC. (f_language_defn): Adjust. * go-lang.c (go_language_defn): Adjust. * guile/scm-cmd.c (cmdscm_add_completion, cmdscm_completer): Adjust to work with a completion_tracker instead of a VEC. * infrun.c (handle_completer): Likewise. * interps.c (interpreter_completer): Likewise. * interps.h (interpreter_completer): Likewise. * language.c (unknown_language_defn, auto_language_defn) (local_language_defn): Adjust. * language.h (language_defn::la_make_symbol_completion_list): Rename to ... (language_defn::la_collect_symbol_completion_matches): ... this and adjust to work with a completion_tracker instead of a VEC. * m2-lang.c (m2_language_defn): Adjust. * objc-lang.c (objc_language_defn): Adjust. * opencl-lang.c (opencl_language_defn): Adjust. * p-lang.c (pascal_language_defn): Adjust. * python/py-cmd.c (cmdpy_completer_helper): Handle NULL word. (cmdpy_completer_handle_brkchars, cmdpy_completer): Adjust to work with a completion_tracker. * rust-lang.c (rust_language_defn): Adjust. * symtab.c (free_completion_list, do_free_completion_list) (return_val, completion_tracker): Delete. (completion_list_add_name, completion_list_add_symbol) (completion_list_add_msymbol, completion_list_objc_symbol) (completion_list_add_fields, add_symtab_completions): Add completion_tracker parameter and use it. (default_make_symbol_completion_list_break_on_1): Rename to... (default_collect_symbol_completion_matches_break_on): ... this. Add completion_tracker parameter and use it instead of allocating a completion tracker here. (default_make_symbol_completion_list_break_on): Delete old implementation. (default_make_symbol_completion_list): Delete. (default_collect_symbol_completion_matches): New. (make_symbol_completion_list): Delete. (collect_symbol_completion_matches): New. (make_symbol_completion_type): Rename to ... (collect_symbol_completion_matches_type): ... this. Add completion_tracker parameter and use it instead of VEC. (make_file_symbol_completion_list_1): Rename to... (collect_file_symbol_completion_matches): ... this. Add completion_tracker parameter and use it instead of VEC. (make_file_symbol_completion_list): Delete. (add_filename_to_list): Use completion_list instead of a VEC. (add_partial_filename_data::list): Now a completion_list. (make_source_files_completion_list): Work with a completion_list instead of a VEC. * symtab.h: Include "completer.h". (default_make_symbol_completion_list_break_on) (default_make_symbol_completion_list, make_symbol_completion_list) (make_symbol_completion_type, make_file_symbol_completion_list) (make_source_files_completion_list): Delete. (default_collect_symbol_completion_matches_break_on) (default_collect_symbol_completion_matches) (collect_symbol_completion_matches) (collect_symbol_completion_matches_type) (collect_file_symbol_completion_matches) (make_source_files_completion_list): New. * top.c (init_main): Don't install a rl_completion_entry_function hook. Install a rl_attempted_completion_function hook instead. * tui/tui-layout.c (layout_completer): Adjust to work with a completion_tracker. * tui/tui-regs.c (tui_reggroup_completer): * tui/tui-win.c (window_name_completer, focus_completer) (winheight_completer): Adjust to work with a completion_tracker. * value.c: Include "completer.h". (complete_internalvar): Adjust to work with a completion_tracker. * value.h (complete_internalvar): Likewise.
This commit is contained in:
parent
6e1dbf8cda
commit
eb3ff9a551
36 changed files with 1256 additions and 846 deletions
182
gdb/ChangeLog
182
gdb/ChangeLog
|
@ -1,3 +1,185 @@
|
||||||
|
2017-07-17 Pedro Alves <palves@redhat.com>
|
||||||
|
|
||||||
|
* ada-lang.c (symbol_completion_match): Adjust comments.
|
||||||
|
(symbol_completion_add): Replace vector parameter with
|
||||||
|
completion_tracker parameter. Use it.
|
||||||
|
(ada_make_symbol_completion_list): Rename to...
|
||||||
|
(ada_collect_symbol_completion_matches): ... this. Add
|
||||||
|
completion_tracker parameter and use it.
|
||||||
|
(ada_language_defn): Adjust.
|
||||||
|
* break-catch-syscall.c (catch_syscall_completer): Adjust
|
||||||
|
prototype and work with completion_tracker instead of VEC.
|
||||||
|
* breakpoint.c (condition_completer): Adjust prototype and work
|
||||||
|
with completion_tracker instead of VEC.
|
||||||
|
* c-lang.c (c_language_defn, cplus_language_defn)
|
||||||
|
(asm_language_defn, minimal_language_defn): Adjust to renames.
|
||||||
|
* cli/cli-cmds.c (complete_command): Rework using
|
||||||
|
completion_tracker. Catch exceptions when completing.
|
||||||
|
* cli/cli-decode.c (integer_unlimited_completer)
|
||||||
|
(complete_on_cmdlist, complete_on_enum): Adjust prototype and work
|
||||||
|
with completion_tracker instead of VEC.
|
||||||
|
* command.h (struct completion_tracker): Forward declare.
|
||||||
|
(completer_ftype, completer_handle_brkchars_ftype): Change
|
||||||
|
types.
|
||||||
|
(complete_on_cmdlist, complete_on_enum): Adjust.
|
||||||
|
* completer.c: Include <algorithm>.
|
||||||
|
(struct gdb_completer_state): New.
|
||||||
|
(current_completion): New global.
|
||||||
|
(readline_line_completion_function): Delete.
|
||||||
|
(noop_completer, filename_completer)
|
||||||
|
(filename_completer_handle_brkchars, complete_files_symbols)
|
||||||
|
(linespec_location_completer): Adjust to work with a
|
||||||
|
completion_tracker instead of a VEC.
|
||||||
|
(string_or_empty): New.
|
||||||
|
(collect_explicit_location_matches): Adjust to work with a
|
||||||
|
completion_tracker instead of a VEC.
|
||||||
|
(explicit_location_completer): Rename to ...
|
||||||
|
(complete_explicit_location): ... this and adjust to work with a
|
||||||
|
completion_tracker instead of a VEC.
|
||||||
|
(location_completer): Adjust to work with a completion_tracker
|
||||||
|
instead of a VEC.
|
||||||
|
(add_struct_fields): Adjust to work with a completion_list instead
|
||||||
|
of VEC.
|
||||||
|
(expression_completer): Rename to ...
|
||||||
|
(complete_expression): ... this and adjust to work with a
|
||||||
|
completion_tracker instead of a VEC. Use complete_files_symbols.
|
||||||
|
(expression_completer): Reimplement on top of complete_expression.
|
||||||
|
(symbol_completer): Adjust to work with a completion_tracker
|
||||||
|
instead of a VEC.
|
||||||
|
(enum complete_line_internal_reason): Add describing comments.
|
||||||
|
(complete_line_internal_normal_command): Adjust to work with a
|
||||||
|
completion_tracker instead of a VEC.
|
||||||
|
(complete_line_internal): Rename to ...
|
||||||
|
(complete_line_internal_1): ... this and adjust to work with a
|
||||||
|
completion_tracker instead of a VEC. Assert TEXT is NULL in the
|
||||||
|
handle_brkchars phase.
|
||||||
|
(new_completion_tracker): Delete.
|
||||||
|
(complete_line_internal): Reimplement as TRY/CATCH wrapper around
|
||||||
|
complete_line_internal_1.
|
||||||
|
(free_completion_tracker): Delete.
|
||||||
|
(INITIAL_COMPLETION_HTAB_SIZE): New.
|
||||||
|
(completion_tracker::completion_tracker)
|
||||||
|
(completion_tracker::~completion_tracker): New.
|
||||||
|
(maybe_add_completion): Delete.
|
||||||
|
(completion_tracker::maybe_add_completion)
|
||||||
|
(completion_tracker::add_completion)
|
||||||
|
(completion_tracker::add_completions): New.
|
||||||
|
(throw_max_completions_reached_error): Delete.
|
||||||
|
(complete_line): Adjust to work with a completion_tracker instead
|
||||||
|
of a VEC. Don't create a completion_tracker_t or check for max
|
||||||
|
completions here.
|
||||||
|
(command_completer, command_completer_handle_brkchars)
|
||||||
|
(signal_completer, reg_or_group_completer_1)
|
||||||
|
(reg_or_group_completer, default_completer_handle_brkchars):
|
||||||
|
Adjust to work with a completion_tracker.
|
||||||
|
(gdb_completion_word_break_characters_throw): New.
|
||||||
|
(gdb_completion_word_break_characters): Reimplement.
|
||||||
|
(line_completion_function): Delete.
|
||||||
|
(completion_tracker::recompute_lowest_common_denominator)
|
||||||
|
(expand_preserving_ws)
|
||||||
|
(completion_tracker::build_completion_result)
|
||||||
|
(completion_result::completion_result)
|
||||||
|
(completion_result::completion_result)
|
||||||
|
(completion_result::~completion_result)
|
||||||
|
(completion_result::completion_result)
|
||||||
|
(completion_result::release_match_list, compare_cstrings)
|
||||||
|
(completion_result::sort_match_list)
|
||||||
|
(completion_result::reset_match_list)
|
||||||
|
(gdb_rl_attempted_completion_function_throw)
|
||||||
|
(gdb_rl_attempted_completion_function): New.
|
||||||
|
* completer.h (completion_list, struct completion_result)
|
||||||
|
(class completion_tracker): New.
|
||||||
|
(complete_line): Add completion_tracker parameter.
|
||||||
|
(readline_line_completion_function): Delete.
|
||||||
|
(gdb_rl_attempted_completion_function): New.
|
||||||
|
(noop_completer, filename_completer, expression_completer)
|
||||||
|
(location_completer, symbol_completer, command_completer)
|
||||||
|
(signal_completer, reg_or_group_completer): Update prototypes.
|
||||||
|
(completion_tracker_t, new_completion_tracker)
|
||||||
|
(make_cleanup_free_completion_tracker): Delete.
|
||||||
|
(enum maybe_add_completion_enum): Delete.
|
||||||
|
(maybe_add_completion): Delete.
|
||||||
|
(throw_max_completions_reached_error): Delete.
|
||||||
|
* corefile.c (complete_set_gnutarget): Adjust to work with a
|
||||||
|
completion_tracker instead of a VEC.
|
||||||
|
* cp-abi.c (cp_abi_completer): Adjust to work with a
|
||||||
|
completion_tracker instead of a VEC.
|
||||||
|
* d-lang.c (d_language_defn): Adjust.
|
||||||
|
* disasm.c (disassembler_options_completer): Adjust to work with a
|
||||||
|
completion_tracker instead of a VEC.
|
||||||
|
* f-lang.c (f_make_symbol_completion_list): Rename to ...
|
||||||
|
(f_collect_symbol_completion_matches): ... this. Adjust to work
|
||||||
|
with a completion_tracker instead of a VEC.
|
||||||
|
(f_language_defn): Adjust.
|
||||||
|
* go-lang.c (go_language_defn): Adjust.
|
||||||
|
* guile/scm-cmd.c (cmdscm_add_completion, cmdscm_completer):
|
||||||
|
Adjust to work with a completion_tracker instead of a VEC.
|
||||||
|
* infrun.c (handle_completer): Likewise.
|
||||||
|
* interps.c (interpreter_completer): Likewise.
|
||||||
|
* interps.h (interpreter_completer): Likewise.
|
||||||
|
* language.c (unknown_language_defn, auto_language_defn)
|
||||||
|
(local_language_defn): Adjust.
|
||||||
|
* language.h (language_defn::la_make_symbol_completion_list):
|
||||||
|
Rename to ...
|
||||||
|
(language_defn::la_collect_symbol_completion_matches): ... this
|
||||||
|
and adjust to work with a completion_tracker instead of a VEC.
|
||||||
|
* m2-lang.c (m2_language_defn): Adjust.
|
||||||
|
* objc-lang.c (objc_language_defn): Adjust.
|
||||||
|
* opencl-lang.c (opencl_language_defn): Adjust.
|
||||||
|
* p-lang.c (pascal_language_defn): Adjust.
|
||||||
|
* python/py-cmd.c (cmdpy_completer_helper): Handle NULL word.
|
||||||
|
(cmdpy_completer_handle_brkchars, cmdpy_completer): Adjust to work
|
||||||
|
with a completion_tracker.
|
||||||
|
* rust-lang.c (rust_language_defn): Adjust.
|
||||||
|
* symtab.c (free_completion_list, do_free_completion_list)
|
||||||
|
(return_val, completion_tracker): Delete.
|
||||||
|
(completion_list_add_name, completion_list_add_symbol)
|
||||||
|
(completion_list_add_msymbol, completion_list_objc_symbol)
|
||||||
|
(completion_list_add_fields, add_symtab_completions): Add
|
||||||
|
completion_tracker parameter and use it.
|
||||||
|
(default_make_symbol_completion_list_break_on_1): Rename to...
|
||||||
|
(default_collect_symbol_completion_matches_break_on): ... this.
|
||||||
|
Add completion_tracker parameter and use it instead of allocating
|
||||||
|
a completion tracker here.
|
||||||
|
(default_make_symbol_completion_list_break_on): Delete old
|
||||||
|
implementation.
|
||||||
|
(default_make_symbol_completion_list): Delete.
|
||||||
|
(default_collect_symbol_completion_matches): New.
|
||||||
|
(make_symbol_completion_list): Delete.
|
||||||
|
(collect_symbol_completion_matches): New.
|
||||||
|
(make_symbol_completion_type): Rename to ...
|
||||||
|
(collect_symbol_completion_matches_type): ... this. Add
|
||||||
|
completion_tracker parameter and use it instead of VEC.
|
||||||
|
(make_file_symbol_completion_list_1): Rename to...
|
||||||
|
(collect_file_symbol_completion_matches): ... this. Add
|
||||||
|
completion_tracker parameter and use it instead of VEC.
|
||||||
|
(make_file_symbol_completion_list): Delete.
|
||||||
|
(add_filename_to_list): Use completion_list instead of a VEC.
|
||||||
|
(add_partial_filename_data::list): Now a completion_list.
|
||||||
|
(make_source_files_completion_list): Work with a completion_list
|
||||||
|
instead of a VEC.
|
||||||
|
* symtab.h: Include "completer.h".
|
||||||
|
(default_make_symbol_completion_list_break_on)
|
||||||
|
(default_make_symbol_completion_list, make_symbol_completion_list)
|
||||||
|
(make_symbol_completion_type, make_file_symbol_completion_list)
|
||||||
|
(make_source_files_completion_list): Delete.
|
||||||
|
(default_collect_symbol_completion_matches_break_on)
|
||||||
|
(default_collect_symbol_completion_matches)
|
||||||
|
(collect_symbol_completion_matches)
|
||||||
|
(collect_symbol_completion_matches_type)
|
||||||
|
(collect_file_symbol_completion_matches)
|
||||||
|
(make_source_files_completion_list): New.
|
||||||
|
* top.c (init_main): Don't install a rl_completion_entry_function
|
||||||
|
hook. Install a rl_attempted_completion_function hook instead.
|
||||||
|
* tui/tui-layout.c (layout_completer): Adjust to work with a
|
||||||
|
completion_tracker.
|
||||||
|
* tui/tui-regs.c (tui_reggroup_completer):
|
||||||
|
* tui/tui-win.c (window_name_completer, focus_completer)
|
||||||
|
(winheight_completer): Adjust to work with a completion_tracker.
|
||||||
|
* value.c: Include "completer.h".
|
||||||
|
(complete_internalvar): Adjust to work with a completion_tracker.
|
||||||
|
* value.h (complete_internalvar): Likewise.
|
||||||
|
|
||||||
2017-07-17 Pedro Alves <palves@redhat.com>
|
2017-07-17 Pedro Alves <palves@redhat.com>
|
||||||
|
|
||||||
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): Adjust to
|
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): Adjust to
|
||||||
|
|
|
@ -6440,10 +6440,10 @@ symbol_completion_match (const char *sym_name,
|
||||||
return sym_name;
|
return sym_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A companion function to ada_make_symbol_completion_list().
|
/* A companion function to ada_collect_symbol_completion_matches().
|
||||||
Check if SYM_NAME represents a symbol which name would be suitable
|
Check if SYM_NAME represents a symbol which name would be suitable
|
||||||
to complete TEXT (TEXT_LEN is the length of TEXT), in which case
|
to complete TEXT (TEXT_LEN is the length of TEXT), in which case it
|
||||||
it is appended at the end of the given string vector SV.
|
is added as a completion match to TRACKER.
|
||||||
|
|
||||||
ORIG_TEXT is the string original string from the user command
|
ORIG_TEXT is the string original string from the user command
|
||||||
that needs to be completed. WORD is the entire command on which
|
that needs to be completed. WORD is the entire command on which
|
||||||
|
@ -6456,8 +6456,8 @@ symbol_completion_match (const char *sym_name,
|
||||||
encoded). */
|
encoded). */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
symbol_completion_add (VEC(char_ptr) **sv,
|
symbol_completion_add (completion_tracker &tracker,
|
||||||
const char *sym_name,
|
const char *sym_name,
|
||||||
const char *text, int text_len,
|
const char *text, int text_len,
|
||||||
const char *orig_text, const char *word,
|
const char *orig_text, const char *word,
|
||||||
int wild_match_p, int encoded_p)
|
int wild_match_p, int encoded_p)
|
||||||
|
@ -6492,21 +6492,21 @@ symbol_completion_add (VEC(char_ptr) **sv,
|
||||||
strcat (completion, match);
|
strcat (completion, match);
|
||||||
}
|
}
|
||||||
|
|
||||||
VEC_safe_push (char_ptr, *sv, completion);
|
tracker.add_completion (gdb::unique_xmalloc_ptr<char> (completion));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return a list of possible symbol names completing TEXT0. WORD is
|
/* Add the list of possible symbol names completing TEXT0 to TRACKER.
|
||||||
the entire command on which completion is made. */
|
WORD is the entire command on which completion is made. */
|
||||||
|
|
||||||
static VEC (char_ptr) *
|
static void
|
||||||
ada_make_symbol_completion_list (const char *text0, const char *word,
|
ada_collect_symbol_completion_matches (completion_tracker &tracker,
|
||||||
enum type_code code)
|
const char *text0, const char *word,
|
||||||
|
enum type_code code)
|
||||||
{
|
{
|
||||||
char *text;
|
char *text;
|
||||||
int text_len;
|
int text_len;
|
||||||
int wild_match_p;
|
int wild_match_p;
|
||||||
int encoded_p;
|
int encoded_p;
|
||||||
VEC(char_ptr) *completions = VEC_alloc (char_ptr, 128);
|
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
struct compunit_symtab *s;
|
struct compunit_symtab *s;
|
||||||
struct minimal_symbol *msymbol;
|
struct minimal_symbol *msymbol;
|
||||||
|
@ -6562,7 +6562,7 @@ ada_make_symbol_completion_list (const char *text0, const char *word,
|
||||||
ALL_MSYMBOLS (objfile, msymbol)
|
ALL_MSYMBOLS (objfile, msymbol)
|
||||||
{
|
{
|
||||||
QUIT;
|
QUIT;
|
||||||
symbol_completion_add (&completions, MSYMBOL_LINKAGE_NAME (msymbol),
|
symbol_completion_add (tracker, MSYMBOL_LINKAGE_NAME (msymbol),
|
||||||
text, text_len, text0, word, wild_match_p,
|
text, text_len, text0, word, wild_match_p,
|
||||||
encoded_p);
|
encoded_p);
|
||||||
}
|
}
|
||||||
|
@ -6577,7 +6577,7 @@ ada_make_symbol_completion_list (const char *text0, const char *word,
|
||||||
|
|
||||||
ALL_BLOCK_SYMBOLS (b, iter, sym)
|
ALL_BLOCK_SYMBOLS (b, iter, sym)
|
||||||
{
|
{
|
||||||
symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (sym),
|
symbol_completion_add (tracker, SYMBOL_LINKAGE_NAME (sym),
|
||||||
text, text_len, text0, word,
|
text, text_len, text0, word,
|
||||||
wild_match_p, encoded_p);
|
wild_match_p, encoded_p);
|
||||||
}
|
}
|
||||||
|
@ -6592,7 +6592,7 @@ ada_make_symbol_completion_list (const char *text0, const char *word,
|
||||||
b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (s), GLOBAL_BLOCK);
|
b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (s), GLOBAL_BLOCK);
|
||||||
ALL_BLOCK_SYMBOLS (b, iter, sym)
|
ALL_BLOCK_SYMBOLS (b, iter, sym)
|
||||||
{
|
{
|
||||||
symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (sym),
|
symbol_completion_add (tracker, SYMBOL_LINKAGE_NAME (sym),
|
||||||
text, text_len, text0, word,
|
text, text_len, text0, word,
|
||||||
wild_match_p, encoded_p);
|
wild_match_p, encoded_p);
|
||||||
}
|
}
|
||||||
|
@ -6607,14 +6607,13 @@ ada_make_symbol_completion_list (const char *text0, const char *word,
|
||||||
continue;
|
continue;
|
||||||
ALL_BLOCK_SYMBOLS (b, iter, sym)
|
ALL_BLOCK_SYMBOLS (b, iter, sym)
|
||||||
{
|
{
|
||||||
symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (sym),
|
symbol_completion_add (tracker, SYMBOL_LINKAGE_NAME (sym),
|
||||||
text, text_len, text0, word,
|
text, text_len, text0, word,
|
||||||
wild_match_p, encoded_p);
|
wild_match_p, encoded_p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
do_cleanups (old_chain);
|
do_cleanups (old_chain);
|
||||||
return completions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Field Access */
|
/* Field Access */
|
||||||
|
@ -14010,7 +14009,7 @@ const struct language_defn ada_language_defn = {
|
||||||
0, /* c-style arrays */
|
0, /* c-style arrays */
|
||||||
1, /* String lower bound */
|
1, /* String lower bound */
|
||||||
ada_get_gdb_completer_word_break_characters,
|
ada_get_gdb_completer_word_break_characters,
|
||||||
ada_make_symbol_completion_list,
|
ada_collect_symbol_completion_matches,
|
||||||
ada_language_arch_info,
|
ada_language_arch_info,
|
||||||
ada_print_array_index,
|
ada_print_array_index,
|
||||||
default_pass_by_reference,
|
default_pass_by_reference,
|
||||||
|
|
|
@ -612,15 +612,14 @@ catching_syscall_number (int syscall_number)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Complete syscall names. Used by "catch syscall". */
|
/* Complete syscall names. Used by "catch syscall". */
|
||||||
static VEC (char_ptr) *
|
|
||||||
|
static void
|
||||||
catch_syscall_completer (struct cmd_list_element *cmd,
|
catch_syscall_completer (struct cmd_list_element *cmd,
|
||||||
|
completion_tracker &tracker,
|
||||||
const char *text, const char *word)
|
const char *text, const char *word)
|
||||||
{
|
{
|
||||||
struct gdbarch *gdbarch = get_current_arch ();
|
struct gdbarch *gdbarch = get_current_arch ();
|
||||||
struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
|
struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
|
||||||
VEC (char_ptr) *group_retlist = NULL;
|
|
||||||
VEC (char_ptr) *syscall_retlist = NULL;
|
|
||||||
VEC (char_ptr) *retlist = NULL;
|
|
||||||
const char **group_list = NULL;
|
const char **group_list = NULL;
|
||||||
const char **syscall_list = NULL;
|
const char **syscall_list = NULL;
|
||||||
const char *prefix;
|
const char *prefix;
|
||||||
|
@ -636,8 +635,8 @@ catch_syscall_completer (struct cmd_list_element *cmd,
|
||||||
{
|
{
|
||||||
/* Perform completion inside 'group:' namespace only. */
|
/* Perform completion inside 'group:' namespace only. */
|
||||||
group_list = get_syscall_group_names (gdbarch);
|
group_list = get_syscall_group_names (gdbarch);
|
||||||
retlist = (group_list == NULL
|
if (group_list != NULL)
|
||||||
? NULL : complete_on_enum (group_list, word, word));
|
complete_on_enum (tracker, group_list, word, word);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -654,21 +653,15 @@ catch_syscall_completer (struct cmd_list_element *cmd,
|
||||||
make_cleanup (xfree, prefixed_group);
|
make_cleanup (xfree, prefixed_group);
|
||||||
}
|
}
|
||||||
|
|
||||||
syscall_retlist = ((syscall_list == NULL)
|
if (syscall_list != NULL)
|
||||||
? NULL : complete_on_enum (syscall_list, word, word));
|
complete_on_enum (tracker, syscall_list, word, word);
|
||||||
group_retlist = ((group_list == NULL)
|
if (group_list != NULL)
|
||||||
? NULL : complete_on_enum (group_list, word, word));
|
complete_on_enum (tracker, group_list, word, word);
|
||||||
|
|
||||||
retlist = VEC_merge (char_ptr, syscall_retlist, group_retlist);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VEC_free (char_ptr, syscall_retlist);
|
|
||||||
VEC_free (char_ptr, group_retlist);
|
|
||||||
xfree (syscall_list);
|
xfree (syscall_list);
|
||||||
xfree (group_list);
|
xfree (group_list);
|
||||||
do_cleanups (cleanups);
|
do_cleanups (cleanups);
|
||||||
|
|
||||||
return retlist;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -1042,8 +1042,9 @@ set_breakpoint_condition (struct breakpoint *b, const char *exp,
|
||||||
|
|
||||||
/* Completion for the "condition" command. */
|
/* Completion for the "condition" command. */
|
||||||
|
|
||||||
static VEC (char_ptr) *
|
static void
|
||||||
condition_completer (struct cmd_list_element *cmd,
|
condition_completer (struct cmd_list_element *cmd,
|
||||||
|
completion_tracker &tracker,
|
||||||
const char *text, const char *word)
|
const char *text, const char *word)
|
||||||
{
|
{
|
||||||
const char *space;
|
const char *space;
|
||||||
|
@ -1059,9 +1060,9 @@ condition_completer (struct cmd_list_element *cmd,
|
||||||
if (text[0] == '$')
|
if (text[0] == '$')
|
||||||
{
|
{
|
||||||
/* We don't support completion of history indices. */
|
/* We don't support completion of history indices. */
|
||||||
if (isdigit (text[1]))
|
if (!isdigit (text[1]))
|
||||||
return NULL;
|
complete_internalvar (tracker, &text[1]);
|
||||||
return complete_internalvar (&text[1]);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We're completing the breakpoint number. */
|
/* We're completing the breakpoint number. */
|
||||||
|
@ -1074,15 +1075,18 @@ condition_completer (struct cmd_list_element *cmd,
|
||||||
xsnprintf (number, sizeof (number), "%d", b->number);
|
xsnprintf (number, sizeof (number), "%d", b->number);
|
||||||
|
|
||||||
if (strncmp (number, text, len) == 0)
|
if (strncmp (number, text, len) == 0)
|
||||||
VEC_safe_push (char_ptr, result, xstrdup (number));
|
{
|
||||||
|
gdb::unique_xmalloc_ptr<char> copy (xstrdup (number));
|
||||||
|
tracker.add_completion (std::move (copy));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We're completing the expression part. */
|
/* We're completing the expression part. */
|
||||||
text = skip_spaces_const (space);
|
text = skip_spaces_const (space);
|
||||||
return expression_completer (cmd, text, word);
|
expression_completer (cmd, tracker, text, word);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* condition N EXP -- set break condition of breakpoint N to EXP. */
|
/* condition N EXP -- set break condition of breakpoint N to EXP. */
|
||||||
|
|
|
@ -865,7 +865,7 @@ const struct language_defn c_language_defn =
|
||||||
1, /* c-style arrays */
|
1, /* c-style arrays */
|
||||||
0, /* String lower bound */
|
0, /* String lower bound */
|
||||||
default_word_break_characters,
|
default_word_break_characters,
|
||||||
default_make_symbol_completion_list,
|
default_collect_symbol_completion_matches,
|
||||||
c_language_arch_info,
|
c_language_arch_info,
|
||||||
default_print_array_index,
|
default_print_array_index,
|
||||||
default_pass_by_reference,
|
default_pass_by_reference,
|
||||||
|
@ -1009,7 +1009,7 @@ const struct language_defn cplus_language_defn =
|
||||||
1, /* c-style arrays */
|
1, /* c-style arrays */
|
||||||
0, /* String lower bound */
|
0, /* String lower bound */
|
||||||
default_word_break_characters,
|
default_word_break_characters,
|
||||||
default_make_symbol_completion_list,
|
default_collect_symbol_completion_matches,
|
||||||
cplus_language_arch_info,
|
cplus_language_arch_info,
|
||||||
default_print_array_index,
|
default_print_array_index,
|
||||||
cp_pass_by_reference,
|
cp_pass_by_reference,
|
||||||
|
@ -1062,7 +1062,7 @@ const struct language_defn asm_language_defn =
|
||||||
1, /* c-style arrays */
|
1, /* c-style arrays */
|
||||||
0, /* String lower bound */
|
0, /* String lower bound */
|
||||||
default_word_break_characters,
|
default_word_break_characters,
|
||||||
default_make_symbol_completion_list,
|
default_collect_symbol_completion_matches,
|
||||||
c_language_arch_info, /* FIXME: la_language_arch_info. */
|
c_language_arch_info, /* FIXME: la_language_arch_info. */
|
||||||
default_print_array_index,
|
default_print_array_index,
|
||||||
default_pass_by_reference,
|
default_pass_by_reference,
|
||||||
|
@ -1115,7 +1115,7 @@ const struct language_defn minimal_language_defn =
|
||||||
1, /* c-style arrays */
|
1, /* c-style arrays */
|
||||||
0, /* String lower bound */
|
0, /* String lower bound */
|
||||||
default_word_break_characters,
|
default_word_break_characters,
|
||||||
default_make_symbol_completion_list,
|
default_collect_symbol_completion_matches,
|
||||||
c_language_arch_info,
|
c_language_arch_info,
|
||||||
default_print_array_index,
|
default_print_array_index,
|
||||||
default_pass_by_reference,
|
default_pass_by_reference,
|
||||||
|
|
|
@ -238,6 +238,7 @@ help_command (char *command, int from_tty)
|
||||||
help_cmd (command, gdb_stdout);
|
help_cmd (command, gdb_stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Note: The "complete" command is used by Emacs to implement completion.
|
/* Note: The "complete" command is used by Emacs to implement completion.
|
||||||
[Is that why this function writes output with *_unfiltered?] */
|
[Is that why this function writes output with *_unfiltered?] */
|
||||||
|
|
||||||
|
@ -246,8 +247,6 @@ complete_command (char *arg_entry, int from_tty)
|
||||||
{
|
{
|
||||||
const char *arg = arg_entry;
|
const char *arg = arg_entry;
|
||||||
int argpoint;
|
int argpoint;
|
||||||
char *arg_prefix;
|
|
||||||
VEC (char_ptr) *completions;
|
|
||||||
|
|
||||||
dont_repeat ();
|
dont_repeat ();
|
||||||
|
|
||||||
|
@ -279,43 +278,46 @@ complete_command (char *arg_entry, int from_tty)
|
||||||
point--;
|
point--;
|
||||||
}
|
}
|
||||||
|
|
||||||
arg_prefix = (char *) alloca (point - arg + 1);
|
completion_tracker tracker_handle_completions;
|
||||||
memcpy (arg_prefix, arg, point - arg);
|
|
||||||
arg_prefix[point - arg] = 0;
|
|
||||||
|
|
||||||
completions = complete_line (point, arg, argpoint);
|
TRY
|
||||||
|
|
||||||
if (completions)
|
|
||||||
{
|
{
|
||||||
int ix, size = VEC_length (char_ptr, completions);
|
complete_line (tracker_handle_completions, point, arg, strlen (arg));
|
||||||
char *item, *prev = NULL;
|
}
|
||||||
|
CATCH (ex, RETURN_MASK_ALL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
qsort (VEC_address (char_ptr, completions), size,
|
std::string arg_prefix (arg, point - arg);
|
||||||
sizeof (char *), compare_strings);
|
|
||||||
|
|
||||||
/* We do extra processing here since we only want to print each
|
completion_result result
|
||||||
unique item once. */
|
= (tracker_handle_completions.build_completion_result
|
||||||
for (ix = 0; VEC_iterate (char_ptr, completions, ix, item); ++ix)
|
(point, point - arg, strlen (arg)));
|
||||||
|
|
||||||
|
if (result.number_matches != 0)
|
||||||
|
{
|
||||||
|
if (result.number_matches == 1)
|
||||||
|
printf_unfiltered ("%s%s\n", arg_prefix.c_str (), result.match_list[0]);
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (prev == NULL || strcmp (item, prev) != 0)
|
result.sort_match_list ();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < result.number_matches; i++)
|
||||||
{
|
{
|
||||||
printf_unfiltered ("%s%s\n", arg_prefix, item);
|
printf_unfiltered ("%s%s",
|
||||||
xfree (prev);
|
arg_prefix.c_str (),
|
||||||
prev = item;
|
result.match_list[i + 1]);
|
||||||
|
printf_unfiltered ("\n");
|
||||||
}
|
}
|
||||||
else
|
|
||||||
xfree (item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
xfree (prev);
|
if (result.number_matches == max_completions)
|
||||||
VEC_free (char_ptr, completions);
|
|
||||||
|
|
||||||
if (size == max_completions)
|
|
||||||
{
|
{
|
||||||
/* ARG_PREFIX and POINT are included in the output so that emacs
|
/* ARG_PREFIX and POINT are included in the output so that emacs
|
||||||
will include the message in the output. */
|
will include the message in the output. */
|
||||||
printf_unfiltered (_("%s%s %s\n"),
|
printf_unfiltered (_("%s%s %s\n"),
|
||||||
arg_prefix, point,
|
arg_prefix.c_str (), point,
|
||||||
get_max_completions_reached_message ());
|
get_max_completions_reached_message ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -657,8 +657,9 @@ add_setshow_optional_filename_cmd (const char *name, enum command_class theclass
|
||||||
/* Completes on literal "unlimited". Used by integer commands that
|
/* Completes on literal "unlimited". Used by integer commands that
|
||||||
support a special "unlimited" value. */
|
support a special "unlimited" value. */
|
||||||
|
|
||||||
static VEC (char_ptr) *
|
static void
|
||||||
integer_unlimited_completer (struct cmd_list_element *ignore,
|
integer_unlimited_completer (struct cmd_list_element *ignore,
|
||||||
|
completion_tracker &tracker,
|
||||||
const char *text, const char *word)
|
const char *text, const char *word)
|
||||||
{
|
{
|
||||||
static const char * const keywords[] =
|
static const char * const keywords[] =
|
||||||
|
@ -667,7 +668,7 @@ integer_unlimited_completer (struct cmd_list_element *ignore,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
return complete_on_enum (keywords, text, word);
|
complete_on_enum (tracker, keywords, text, word);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add element named NAME to both the set and show command LISTs (the
|
/* Add element named NAME to both the set and show command LISTs (the
|
||||||
|
@ -1771,13 +1772,13 @@ lookup_cmd_composition (const char *text,
|
||||||
"foo" and we want to complete to "foobar". If WORD is "oo", return
|
"foo" and we want to complete to "foobar". If WORD is "oo", return
|
||||||
"oobar"; if WORD is "baz/foo", return "baz/foobar". */
|
"oobar"; if WORD is "baz/foo", return "baz/foobar". */
|
||||||
|
|
||||||
VEC (char_ptr) *
|
void
|
||||||
complete_on_cmdlist (struct cmd_list_element *list,
|
complete_on_cmdlist (struct cmd_list_element *list,
|
||||||
|
completion_tracker &tracker,
|
||||||
const char *text, const char *word,
|
const char *text, const char *word,
|
||||||
int ignore_help_classes)
|
int ignore_help_classes)
|
||||||
{
|
{
|
||||||
struct cmd_list_element *ptr;
|
struct cmd_list_element *ptr;
|
||||||
VEC (char_ptr) *matchlist = NULL;
|
|
||||||
int textlen = strlen (text);
|
int textlen = strlen (text);
|
||||||
int pass;
|
int pass;
|
||||||
int saw_deprecated_match = 0;
|
int saw_deprecated_match = 0;
|
||||||
|
@ -1786,8 +1787,10 @@ complete_on_cmdlist (struct cmd_list_element *list,
|
||||||
commands. If we see no matching commands in the first pass, and
|
commands. If we see no matching commands in the first pass, and
|
||||||
if we did happen to see a matching deprecated command, we do
|
if we did happen to see a matching deprecated command, we do
|
||||||
another loop to collect those. */
|
another loop to collect those. */
|
||||||
for (pass = 0; matchlist == 0 && pass < 2; ++pass)
|
for (pass = 0; pass < 2; ++pass)
|
||||||
{
|
{
|
||||||
|
bool got_matches = false;
|
||||||
|
|
||||||
for (ptr = list; ptr; ptr = ptr->next)
|
for (ptr = list; ptr; ptr = ptr->next)
|
||||||
if (!strncmp (ptr->name, text, textlen)
|
if (!strncmp (ptr->name, text, textlen)
|
||||||
&& !ptr->abbrev_flag
|
&& !ptr->abbrev_flag
|
||||||
|
@ -1820,32 +1823,34 @@ complete_on_cmdlist (struct cmd_list_element *list,
|
||||||
match[text - word] = '\0';
|
match[text - word] = '\0';
|
||||||
strcat (match, ptr->name);
|
strcat (match, ptr->name);
|
||||||
}
|
}
|
||||||
VEC_safe_push (char_ptr, matchlist, match);
|
tracker.add_completion (gdb::unique_xmalloc_ptr<char> (match));
|
||||||
|
got_matches = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (got_matches)
|
||||||
|
break;
|
||||||
|
|
||||||
/* If we saw no matching deprecated commands in the first pass,
|
/* If we saw no matching deprecated commands in the first pass,
|
||||||
just bail out. */
|
just bail out. */
|
||||||
if (!saw_deprecated_match)
|
if (!saw_deprecated_match)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return matchlist;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper function for SYMBOL_COMPLETION_FUNCTION. */
|
/* Helper function for SYMBOL_COMPLETION_FUNCTION. */
|
||||||
|
|
||||||
/* Return a vector of char pointers which point to the different
|
/* Add the different possible completions in ENUMLIST of TEXT.
|
||||||
possible completions in CMD of TEXT.
|
|
||||||
|
|
||||||
WORD points in the same buffer as TEXT, and completions should be
|
WORD points in the same buffer as TEXT, and completions should be
|
||||||
returned relative to this position. For example, suppose TEXT is "foo"
|
returned relative to this position. For example, suppose TEXT is "foo"
|
||||||
and we want to complete to "foobar". If WORD is "oo", return
|
and we want to complete to "foobar". If WORD is "oo", return
|
||||||
"oobar"; if WORD is "baz/foo", return "baz/foobar". */
|
"oobar"; if WORD is "baz/foo", return "baz/foobar". */
|
||||||
|
|
||||||
VEC (char_ptr) *
|
void
|
||||||
complete_on_enum (const char *const *enumlist,
|
complete_on_enum (completion_tracker &tracker,
|
||||||
|
const char *const *enumlist,
|
||||||
const char *text, const char *word)
|
const char *text, const char *word)
|
||||||
{
|
{
|
||||||
VEC (char_ptr) *matchlist = NULL;
|
|
||||||
int textlen = strlen (text);
|
int textlen = strlen (text);
|
||||||
int i;
|
int i;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
@ -1870,10 +1875,8 @@ complete_on_enum (const char *const *enumlist,
|
||||||
match[text - word] = '\0';
|
match[text - word] = '\0';
|
||||||
strcat (match, name);
|
strcat (match, name);
|
||||||
}
|
}
|
||||||
VEC_safe_push (char_ptr, matchlist, match);
|
tracker.add_completion (gdb::unique_xmalloc_ptr<char> (match));
|
||||||
}
|
}
|
||||||
|
|
||||||
return matchlist;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#include "gdb_vecs.h"
|
#include "gdb_vecs.h"
|
||||||
#include "common/scoped_restore.h"
|
#include "common/scoped_restore.h"
|
||||||
|
|
||||||
|
struct completion_tracker;
|
||||||
|
|
||||||
/* This file defines the public interface for any code wanting to
|
/* This file defines the public interface for any code wanting to
|
||||||
create commands. */
|
create commands. */
|
||||||
|
|
||||||
|
@ -174,7 +176,7 @@ typedef void cmd_sfunc_ftype (char *args, int from_tty,
|
||||||
extern void set_cmd_sfunc (struct cmd_list_element *cmd,
|
extern void set_cmd_sfunc (struct cmd_list_element *cmd,
|
||||||
cmd_sfunc_ftype *sfunc);
|
cmd_sfunc_ftype *sfunc);
|
||||||
|
|
||||||
/* A completion routine. Return a list of possible completions.
|
/* A completion routine. Add possible completions to tracker.
|
||||||
|
|
||||||
TEXT is the text beyond what was matched for the command itself
|
TEXT is the text beyond what was matched for the command itself
|
||||||
(leading whitespace is skipped). It stops where we are supposed to
|
(leading whitespace is skipped). It stops where we are supposed to
|
||||||
|
@ -183,11 +185,13 @@ extern void set_cmd_sfunc (struct cmd_list_element *cmd,
|
||||||
relative to this position. For example, suppose TEXT is "foo" and
|
relative to this position. For example, suppose TEXT is "foo" and
|
||||||
we want to complete to "foobar". If WORD is "oo", return "oobar";
|
we want to complete to "foobar". If WORD is "oo", return "oobar";
|
||||||
if WORD is "baz/foo", return "baz/foobar". */
|
if WORD is "baz/foo", return "baz/foobar". */
|
||||||
typedef VEC (char_ptr) *completer_ftype (struct cmd_list_element *,
|
typedef void completer_ftype (struct cmd_list_element *,
|
||||||
const char *text, const char *word);
|
completion_tracker &tracker,
|
||||||
|
const char *text, const char *word);
|
||||||
|
|
||||||
/* Same, but for set_cmd_completer_handle_brkchars. */
|
/* Same, but for set_cmd_completer_handle_brkchars. */
|
||||||
typedef void completer_handle_brkchars_ftype (struct cmd_list_element *,
|
typedef void completer_handle_brkchars_ftype (struct cmd_list_element *,
|
||||||
|
completion_tracker &tracker,
|
||||||
const char *text, const char *word);
|
const char *text, const char *word);
|
||||||
|
|
||||||
extern void set_cmd_completer (struct cmd_list_element *, completer_ftype *);
|
extern void set_cmd_completer (struct cmd_list_element *, completer_ftype *);
|
||||||
|
@ -259,11 +263,13 @@ extern struct cmd_list_element *add_info (const char *,
|
||||||
extern struct cmd_list_element *add_info_alias (const char *, const char *,
|
extern struct cmd_list_element *add_info_alias (const char *, const char *,
|
||||||
int);
|
int);
|
||||||
|
|
||||||
extern VEC (char_ptr) *complete_on_cmdlist (struct cmd_list_element *,
|
extern void complete_on_cmdlist (struct cmd_list_element *,
|
||||||
const char *, const char *, int);
|
completion_tracker &tracker,
|
||||||
|
const char *, const char *, int);
|
||||||
|
|
||||||
extern VEC (char_ptr) *complete_on_enum (const char *const *enumlist,
|
extern void complete_on_enum (completion_tracker &tracker,
|
||||||
const char *, const char *);
|
const char *const *enumlist,
|
||||||
|
const char *, const char *);
|
||||||
|
|
||||||
/* Functions that implement commands about CLI commands. */
|
/* Functions that implement commands about CLI commands. */
|
||||||
|
|
||||||
|
|
937
gdb/completer.c
937
gdb/completer.c
File diff suppressed because it is too large
Load diff
244
gdb/completer.h
244
gdb/completer.h
|
@ -63,44 +63,184 @@ struct match_list_displayer
|
||||||
mld_read_key_ftype *read_key;
|
mld_read_key_ftype *read_key;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* A list of completion candidates. Each element is a malloc string,
|
||||||
|
because ownership of the strings is transferred to readline, which
|
||||||
|
calls free on each element. */
|
||||||
|
typedef std::vector<gdb::unique_xmalloc_ptr<char>> completion_list;
|
||||||
|
|
||||||
|
/* The final result of a completion that is handed over to either
|
||||||
|
readline or the "completion" command (which pretends to be
|
||||||
|
readline). Mainly a wrapper for a readline-style match list array,
|
||||||
|
though other bits of info are included too. */
|
||||||
|
|
||||||
|
struct completion_result
|
||||||
|
{
|
||||||
|
/* Create an empty result. */
|
||||||
|
completion_result ();
|
||||||
|
|
||||||
|
/* Create a result. */
|
||||||
|
completion_result (char **match_list, size_t number_matches,
|
||||||
|
bool completion_suppress_append);
|
||||||
|
|
||||||
|
/* Destroy a result. */
|
||||||
|
~completion_result ();
|
||||||
|
|
||||||
|
/* Disable copying, since we don't need it. */
|
||||||
|
completion_result (const completion_result &rhs) = delete;
|
||||||
|
void operator= (const completion_result &rhs) = delete;
|
||||||
|
|
||||||
|
/* Move a result. */
|
||||||
|
completion_result (completion_result &&rhs);
|
||||||
|
|
||||||
|
/* Release ownership of the match list array. */
|
||||||
|
char **release_match_list ();
|
||||||
|
|
||||||
|
/* Sort the match list. */
|
||||||
|
void sort_match_list ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* Destroy the match list array and its contents. */
|
||||||
|
void reset_match_list ();
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* (There's no point in making these fields private, since the whole
|
||||||
|
point of this wrapper is to build data in the layout expected by
|
||||||
|
readline. Making them private would require adding getters for
|
||||||
|
the "complete" command, which would expose the same
|
||||||
|
implementation details anyway.) */
|
||||||
|
|
||||||
|
/* The match list array, in the format that readline expects.
|
||||||
|
match_list[0] contains the common prefix. The real match list
|
||||||
|
starts at index 1. The list is NULL terminated. If there's only
|
||||||
|
one match, then match_list[1] is NULL. If there are no matches,
|
||||||
|
then this is NULL. */
|
||||||
|
char **match_list;
|
||||||
|
/* The number of matched completions in MATCH_LIST. Does not
|
||||||
|
include the NULL terminator or the common prefix. */
|
||||||
|
size_t number_matches;
|
||||||
|
|
||||||
|
/* Whether readline should suppress appending a whitespace, when
|
||||||
|
there's only one possible completion. */
|
||||||
|
bool completion_suppress_append;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Object used by completers to build a completion match list to hand
|
||||||
|
over to readline. It tracks:
|
||||||
|
|
||||||
|
- How many unique completions have been generated, to terminate
|
||||||
|
completion list generation early if the list has grown to a size
|
||||||
|
so large as to be useless. This helps avoid GDB seeming to lock
|
||||||
|
up in the event the user requests to complete on something vague
|
||||||
|
that necessitates the time consuming expansion of many symbol
|
||||||
|
tables.
|
||||||
|
*/
|
||||||
|
class completion_tracker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
completion_tracker ();
|
||||||
|
~completion_tracker ();
|
||||||
|
|
||||||
|
/* Disable copy. */
|
||||||
|
completion_tracker (const completion_tracker &rhs) = delete;
|
||||||
|
void operator= (const completion_tracker &rhs) = delete;
|
||||||
|
|
||||||
|
/* Add the completion NAME to the list of generated completions if
|
||||||
|
it is not there already. If too many completions were already
|
||||||
|
found, this throws an error. */
|
||||||
|
void add_completion (gdb::unique_xmalloc_ptr<char> name);
|
||||||
|
|
||||||
|
/* Add all completions matches in LIST. Elements are moved out of
|
||||||
|
LIST. */
|
||||||
|
void add_completions (completion_list &&list);
|
||||||
|
|
||||||
|
/* True if we have any completion match recorded. */
|
||||||
|
bool have_completions () const
|
||||||
|
{ return !m_entries_vec.empty (); }
|
||||||
|
|
||||||
|
/* Build a completion_result containing the list of completion
|
||||||
|
matches to hand over to readline. The parameters are as in
|
||||||
|
rl_attempted_completion_function. */
|
||||||
|
completion_result build_completion_result (const char *text,
|
||||||
|
int start, int end);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/* Add the completion NAME to the list of generated completions if
|
||||||
|
it is not there already. If false is returned, too many
|
||||||
|
completions were found. */
|
||||||
|
bool maybe_add_completion (gdb::unique_xmalloc_ptr<char> name);
|
||||||
|
|
||||||
|
/* Given a new match, recompute the lowest common denominator (LCD)
|
||||||
|
to hand over to readline. */
|
||||||
|
void recompute_lowest_common_denominator (const char *new_match);
|
||||||
|
|
||||||
|
/* The completion matches found so far, in a vector. */
|
||||||
|
completion_list m_entries_vec;
|
||||||
|
|
||||||
|
/* The completion matches found so far, in a hash table, for
|
||||||
|
duplicate elimination as entries are added. Otherwise the user
|
||||||
|
is left scratching his/her head: readline and complete_command
|
||||||
|
will remove duplicates, and if removal of duplicates there brings
|
||||||
|
the total under max_completions the user may think gdb quit
|
||||||
|
searching too early. */
|
||||||
|
htab_t m_entries_hash;
|
||||||
|
|
||||||
|
/* Our idea of lowest common denominator to hand over to readline. */
|
||||||
|
char *m_lowest_common_denominator = NULL;
|
||||||
|
|
||||||
|
/* If true, the LCD is unique. I.e., all completion candidates had
|
||||||
|
the same string. */
|
||||||
|
bool m_lowest_common_denominator_unique = false;
|
||||||
|
};
|
||||||
|
|
||||||
extern void gdb_display_match_list (char **matches, int len, int max,
|
extern void gdb_display_match_list (char **matches, int len, int max,
|
||||||
const struct match_list_displayer *);
|
const struct match_list_displayer *);
|
||||||
|
|
||||||
extern const char *get_max_completions_reached_message (void);
|
extern const char *get_max_completions_reached_message (void);
|
||||||
|
|
||||||
extern VEC (char_ptr) *complete_line (const char *text,
|
extern void complete_line (completion_tracker &tracker,
|
||||||
const char *line_buffer,
|
const char *text,
|
||||||
int point);
|
const char *line_buffer,
|
||||||
|
int point);
|
||||||
|
|
||||||
extern char *readline_line_completion_function (const char *text,
|
extern char **gdb_rl_attempted_completion_function (const char *text,
|
||||||
int matches);
|
int start, int end);
|
||||||
|
|
||||||
extern VEC (char_ptr) *noop_completer (struct cmd_list_element *,
|
extern void noop_completer (struct cmd_list_element *,
|
||||||
const char *, const char *);
|
completion_tracker &tracker,
|
||||||
|
const char *, const char *);
|
||||||
|
|
||||||
extern VEC (char_ptr) *filename_completer (struct cmd_list_element *,
|
extern void filename_completer (struct cmd_list_element *,
|
||||||
const char *, const char *);
|
completion_tracker &tracker,
|
||||||
|
const char *, const char *);
|
||||||
|
|
||||||
extern VEC (char_ptr) *expression_completer (struct cmd_list_element *,
|
extern void expression_completer (struct cmd_list_element *,
|
||||||
const char *, const char *);
|
completion_tracker &tracker,
|
||||||
|
const char *, const char *);
|
||||||
|
|
||||||
extern VEC (char_ptr) *location_completer (struct cmd_list_element *,
|
extern void location_completer (struct cmd_list_element *,
|
||||||
const char *, const char *);
|
completion_tracker &tracker,
|
||||||
|
const char *, const char *);
|
||||||
|
|
||||||
extern VEC (char_ptr) *symbol_completer (struct cmd_list_element *,
|
extern void symbol_completer (struct cmd_list_element *,
|
||||||
const char *, const char *);
|
completion_tracker &tracker,
|
||||||
|
const char *, const char *);
|
||||||
|
|
||||||
extern VEC (char_ptr) *command_completer (struct cmd_list_element *,
|
extern void command_completer (struct cmd_list_element *,
|
||||||
const char *, const char *);
|
completion_tracker &tracker,
|
||||||
|
const char *, const char *);
|
||||||
|
|
||||||
extern VEC (char_ptr) *signal_completer (struct cmd_list_element *,
|
extern void signal_completer (struct cmd_list_element *,
|
||||||
const char *, const char *);
|
completion_tracker &tracker,
|
||||||
|
const char *, const char *);
|
||||||
|
|
||||||
extern VEC (char_ptr) *reg_or_group_completer (struct cmd_list_element *,
|
extern void reg_or_group_completer (struct cmd_list_element *,
|
||||||
const char *, const char *);
|
completion_tracker &tracker,
|
||||||
|
const char *, const char *);
|
||||||
|
|
||||||
extern VEC (char_ptr) *reggroup_completer (struct cmd_list_element *,
|
extern void reggroup_completer (struct cmd_list_element *,
|
||||||
const char *, const char *);
|
completion_tracker &tracker,
|
||||||
|
const char *, const char *);
|
||||||
|
|
||||||
extern const char *get_gdb_completer_quote_characters (void);
|
extern const char *get_gdb_completer_quote_characters (void);
|
||||||
|
|
||||||
|
@ -134,62 +274,4 @@ extern const char *skip_quoted (const char *);
|
||||||
|
|
||||||
extern int max_completions;
|
extern int max_completions;
|
||||||
|
|
||||||
/* Object to track how many unique completions have been generated.
|
|
||||||
Used to limit the size of generated completion lists. */
|
|
||||||
|
|
||||||
typedef htab_t completion_tracker_t;
|
|
||||||
|
|
||||||
/* Create a new completion tracker.
|
|
||||||
The result is a hash table to track added completions, or NULL
|
|
||||||
if max_completions <= 0. If max_completions < 0, tracking is disabled.
|
|
||||||
If max_completions == 0, the max is indeed zero. */
|
|
||||||
|
|
||||||
extern completion_tracker_t new_completion_tracker (void);
|
|
||||||
|
|
||||||
/* Make a cleanup to free a completion tracker, and reset its pointer
|
|
||||||
to NULL. */
|
|
||||||
|
|
||||||
extern struct cleanup *make_cleanup_free_completion_tracker
|
|
||||||
(completion_tracker_t *tracker_ptr);
|
|
||||||
|
|
||||||
/* Return values for maybe_add_completion. */
|
|
||||||
|
|
||||||
enum maybe_add_completion_enum
|
|
||||||
{
|
|
||||||
/* NAME has been recorded and max_completions has not been reached,
|
|
||||||
or completion tracking is disabled (max_completions < 0). */
|
|
||||||
MAYBE_ADD_COMPLETION_OK,
|
|
||||||
|
|
||||||
/* NAME has been recorded and max_completions has been reached
|
|
||||||
(thus the caller can stop searching). */
|
|
||||||
MAYBE_ADD_COMPLETION_OK_MAX_REACHED,
|
|
||||||
|
|
||||||
/* max-completions entries has been reached.
|
|
||||||
Whether NAME is a duplicate or not is not determined. */
|
|
||||||
MAYBE_ADD_COMPLETION_MAX_REACHED,
|
|
||||||
|
|
||||||
/* NAME has already been recorded.
|
|
||||||
Note that this is never returned if completion tracking is disabled
|
|
||||||
(max_completions < 0). */
|
|
||||||
MAYBE_ADD_COMPLETION_DUPLICATE
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Add the completion NAME to the list of generated completions if
|
|
||||||
it is not there already.
|
|
||||||
If max_completions is negative, nothing is done, not even watching
|
|
||||||
for duplicates, and MAYBE_ADD_COMPLETION_OK is always returned.
|
|
||||||
|
|
||||||
If MAYBE_ADD_COMPLETION_MAX_REACHED is returned, callers are required to
|
|
||||||
record at least one more completion. The final list will be pruned to
|
|
||||||
max_completions, but recording at least one more than max_completions is
|
|
||||||
the signal to the completion machinery that too many completions were
|
|
||||||
found. */
|
|
||||||
|
|
||||||
extern enum maybe_add_completion_enum
|
|
||||||
maybe_add_completion (completion_tracker_t tracker, char *name);
|
|
||||||
|
|
||||||
/* Wrapper to throw MAX_COMPLETIONS_REACHED_ERROR. */
|
|
||||||
|
|
||||||
extern void throw_max_completions_reached_error (void);
|
|
||||||
|
|
||||||
#endif /* defined (COMPLETER_H) */
|
#endif /* defined (COMPLETER_H) */
|
||||||
|
|
|
@ -483,8 +483,9 @@ set_gnutarget_command (char *ignore, int from_tty,
|
||||||
|
|
||||||
/* A completion function for "set gnutarget". */
|
/* A completion function for "set gnutarget". */
|
||||||
|
|
||||||
static VEC (char_ptr) *
|
static void
|
||||||
complete_set_gnutarget (struct cmd_list_element *cmd,
|
complete_set_gnutarget (struct cmd_list_element *cmd,
|
||||||
|
completion_tracker &tracker,
|
||||||
const char *text, const char *word)
|
const char *text, const char *word)
|
||||||
{
|
{
|
||||||
static const char **bfd_targets;
|
static const char **bfd_targets;
|
||||||
|
@ -502,7 +503,7 @@ complete_set_gnutarget (struct cmd_list_element *cmd,
|
||||||
bfd_targets[last + 1] = NULL;
|
bfd_targets[last + 1] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return complete_on_enum (bfd_targets, text, word);
|
complete_on_enum (tracker, bfd_targets, text, word);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the gnutarget. */
|
/* Set the gnutarget. */
|
||||||
|
|
|
@ -355,8 +355,9 @@ set_cp_abi_cmd (char *args, int from_tty)
|
||||||
|
|
||||||
/* A completion function for "set cp-abi". */
|
/* A completion function for "set cp-abi". */
|
||||||
|
|
||||||
static VEC (char_ptr) *
|
static void
|
||||||
cp_abi_completer (struct cmd_list_element *ignore,
|
cp_abi_completer (struct cmd_list_element *ignore,
|
||||||
|
completion_tracker &tracker,
|
||||||
const char *text, const char *word)
|
const char *text, const char *word)
|
||||||
{
|
{
|
||||||
static const char **cp_abi_names;
|
static const char **cp_abi_names;
|
||||||
|
@ -371,7 +372,7 @@ cp_abi_completer (struct cmd_list_element *ignore,
|
||||||
cp_abi_names[i] = NULL;
|
cp_abi_names[i] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return complete_on_enum (cp_abi_names, text, word);
|
complete_on_enum (tracker, cp_abi_names, text, word);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Show the currently selected C++ ABI. */
|
/* Show the currently selected C++ ABI. */
|
||||||
|
|
|
@ -239,7 +239,7 @@ static const struct language_defn d_language_defn =
|
||||||
1, /* C-style arrays. */
|
1, /* C-style arrays. */
|
||||||
0, /* String lower bound. */
|
0, /* String lower bound. */
|
||||||
default_word_break_characters,
|
default_word_break_characters,
|
||||||
default_make_symbol_completion_list,
|
default_collect_symbol_completion_matches,
|
||||||
d_language_arch_info,
|
d_language_arch_info,
|
||||||
default_print_array_index,
|
default_print_array_index,
|
||||||
default_pass_by_reference,
|
default_pass_by_reference,
|
||||||
|
|
|
@ -1030,8 +1030,9 @@ The following disassembler options are supported for use with the\n\
|
||||||
|
|
||||||
/* A completion function for "set disassembler". */
|
/* A completion function for "set disassembler". */
|
||||||
|
|
||||||
static VEC (char_ptr) *
|
static void
|
||||||
disassembler_options_completer (struct cmd_list_element *ignore,
|
disassembler_options_completer (struct cmd_list_element *ignore,
|
||||||
|
completion_tracker &tracker,
|
||||||
const char *text, const char *word)
|
const char *text, const char *word)
|
||||||
{
|
{
|
||||||
struct gdbarch *gdbarch = get_current_arch ();
|
struct gdbarch *gdbarch = get_current_arch ();
|
||||||
|
@ -1044,9 +1045,8 @@ disassembler_options_completer (struct cmd_list_element *ignore,
|
||||||
if (separator != NULL)
|
if (separator != NULL)
|
||||||
text = separator + 1;
|
text = separator + 1;
|
||||||
text = skip_spaces_const (text);
|
text = skip_spaces_const (text);
|
||||||
return complete_on_enum (opts->name, text, word);
|
complete_on_enum (tracker, opts->name, text, word);
|
||||||
}
|
}
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
12
gdb/f-lang.c
12
gdb/f-lang.c
|
@ -228,11 +228,13 @@ f_word_break_characters (void)
|
||||||
/* Consider the modules separator :: as a valid symbol name character
|
/* Consider the modules separator :: as a valid symbol name character
|
||||||
class. */
|
class. */
|
||||||
|
|
||||||
static VEC (char_ptr) *
|
static void
|
||||||
f_make_symbol_completion_list (const char *text, const char *word,
|
f_collect_symbol_completion_matches (completion_tracker &tracker,
|
||||||
enum type_code code)
|
const char *text, const char *word,
|
||||||
|
enum type_code code)
|
||||||
{
|
{
|
||||||
return default_make_symbol_completion_list_break_on (text, word, ":", code);
|
default_collect_symbol_completion_matches_break_on (tracker,
|
||||||
|
text, word, ":", code);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *f_extensions[] =
|
static const char *f_extensions[] =
|
||||||
|
@ -282,7 +284,7 @@ const struct language_defn f_language_defn =
|
||||||
0, /* arrays are first-class (not c-style) */
|
0, /* arrays are first-class (not c-style) */
|
||||||
1, /* String lower bound */
|
1, /* String lower bound */
|
||||||
f_word_break_characters,
|
f_word_break_characters,
|
||||||
f_make_symbol_completion_list,
|
f_collect_symbol_completion_matches,
|
||||||
f_language_arch_info,
|
f_language_arch_info,
|
||||||
default_print_array_index,
|
default_print_array_index,
|
||||||
default_pass_by_reference,
|
default_pass_by_reference,
|
||||||
|
|
|
@ -600,13 +600,13 @@ static const struct language_defn go_language_defn =
|
||||||
1, /* C-style arrays. */
|
1, /* C-style arrays. */
|
||||||
0, /* String lower bound. */
|
0, /* String lower bound. */
|
||||||
default_word_break_characters,
|
default_word_break_characters,
|
||||||
default_make_symbol_completion_list,
|
default_collect_symbol_completion_matches,
|
||||||
go_language_arch_info,
|
go_language_arch_info,
|
||||||
default_print_array_index,
|
default_print_array_index,
|
||||||
default_pass_by_reference,
|
default_pass_by_reference,
|
||||||
c_get_string,
|
c_get_string,
|
||||||
c_watch_location_expression,
|
c_watch_location_expression,
|
||||||
NULL,
|
NULL, /* la_get_symbol_name_cmp */
|
||||||
iterate_over_symbols,
|
iterate_over_symbols,
|
||||||
&default_varobj_ops,
|
&default_varobj_ops,
|
||||||
NULL,
|
NULL,
|
||||||
|
|
|
@ -350,9 +350,8 @@ cmdscm_bad_completion_result (const char *msg, SCM completion)
|
||||||
The result is a boolean indicating success. */
|
The result is a boolean indicating success. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cmdscm_add_completion (SCM completion, VEC (char_ptr) **result)
|
cmdscm_add_completion (SCM completion, completion_tracker &tracker)
|
||||||
{
|
{
|
||||||
char *item;
|
|
||||||
SCM except_scm;
|
SCM except_scm;
|
||||||
|
|
||||||
if (!scm_is_string (completion))
|
if (!scm_is_string (completion))
|
||||||
|
@ -363,8 +362,9 @@ cmdscm_add_completion (SCM completion, VEC (char_ptr) **result)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
item = gdbscm_scm_to_string (completion, NULL, host_charset (), 1,
|
gdb::unique_xmalloc_ptr<char> item
|
||||||
&except_scm);
|
(gdbscm_scm_to_string (completion, NULL, host_charset (), 1,
|
||||||
|
&except_scm));
|
||||||
if (item == NULL)
|
if (item == NULL)
|
||||||
{
|
{
|
||||||
/* Inform the user, but otherwise ignore the entire result. */
|
/* Inform the user, but otherwise ignore the entire result. */
|
||||||
|
@ -372,21 +372,21 @@ cmdscm_add_completion (SCM completion, VEC (char_ptr) **result)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
VEC_safe_push (char_ptr, *result, item);
|
tracker.add_completion (std::move (item));
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called by gdb for command completion. */
|
/* Called by gdb for command completion. */
|
||||||
|
|
||||||
static VEC (char_ptr) *
|
static void
|
||||||
cmdscm_completer (struct cmd_list_element *command,
|
cmdscm_completer (struct cmd_list_element *command,
|
||||||
|
completion_tracker &tracker,
|
||||||
const char *text, const char *word)
|
const char *text, const char *word)
|
||||||
{
|
{
|
||||||
command_smob *c_smob/*obj*/ = (command_smob *) get_cmd_context (command);
|
command_smob *c_smob/*obj*/ = (command_smob *) get_cmd_context (command);
|
||||||
SCM completer_result_scm;
|
SCM completer_result_scm;
|
||||||
SCM text_scm, word_scm, result_scm;
|
SCM text_scm, word_scm, result_scm;
|
||||||
VEC (char_ptr) *result = NULL;
|
|
||||||
|
|
||||||
gdb_assert (c_smob != NULL);
|
gdb_assert (c_smob != NULL);
|
||||||
gdb_assert (gdbscm_is_procedure (c_smob->complete));
|
gdb_assert (gdbscm_is_procedure (c_smob->complete));
|
||||||
|
@ -408,7 +408,7 @@ cmdscm_completer (struct cmd_list_element *command,
|
||||||
{
|
{
|
||||||
/* Inform the user, but otherwise ignore. */
|
/* Inform the user, but otherwise ignore. */
|
||||||
gdbscm_print_gdb_exception (SCM_BOOL_F, completer_result_scm);
|
gdbscm_print_gdb_exception (SCM_BOOL_F, completer_result_scm);
|
||||||
goto done;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gdbscm_is_true (scm_list_p (completer_result_scm)))
|
if (gdbscm_is_true (scm_list_p (completer_result_scm)))
|
||||||
|
@ -419,11 +419,8 @@ cmdscm_completer (struct cmd_list_element *command,
|
||||||
{
|
{
|
||||||
SCM next = scm_car (list);
|
SCM next = scm_car (list);
|
||||||
|
|
||||||
if (!cmdscm_add_completion (next, &result))
|
if (!cmdscm_add_completion (next, tracker))
|
||||||
{
|
break;
|
||||||
VEC_free (char_ptr, result);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
list = scm_cdr (list);
|
list = scm_cdr (list);
|
||||||
}
|
}
|
||||||
|
@ -437,17 +434,13 @@ cmdscm_completer (struct cmd_list_element *command,
|
||||||
{
|
{
|
||||||
if (gdbscm_is_exception (next))
|
if (gdbscm_is_exception (next))
|
||||||
{
|
{
|
||||||
/* Inform the user, but otherwise ignore the entire result. */
|
/* Inform the user. */
|
||||||
gdbscm_print_gdb_exception (SCM_BOOL_F, completer_result_scm);
|
gdbscm_print_gdb_exception (SCM_BOOL_F, completer_result_scm);
|
||||||
VEC_free (char_ptr, result);
|
break;
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cmdscm_add_completion (next, &result))
|
if (cmdscm_add_completion (next, tracker))
|
||||||
{
|
break;
|
||||||
VEC_free (char_ptr, result);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
next = itscm_safe_call_next_x (iter, NULL);
|
next = itscm_safe_call_next_x (iter, NULL);
|
||||||
}
|
}
|
||||||
|
@ -458,9 +451,6 @@ cmdscm_completer (struct cmd_list_element *command,
|
||||||
cmdscm_bad_completion_result (_("Bad completer result: "),
|
cmdscm_bad_completion_result (_("Bad completer result: "),
|
||||||
completer_result_scm);
|
completer_result_scm);
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper for gdbscm_make_command which locates the command list to use and
|
/* Helper for gdbscm_make_command which locates the command list to use and
|
||||||
|
|
13
gdb/infrun.c
13
gdb/infrun.c
|
@ -8691,11 +8691,11 @@ Are you sure you want to change it? "),
|
||||||
|
|
||||||
/* Complete the "handle" command. */
|
/* Complete the "handle" command. */
|
||||||
|
|
||||||
static VEC (char_ptr) *
|
static void
|
||||||
handle_completer (struct cmd_list_element *ignore,
|
handle_completer (struct cmd_list_element *ignore,
|
||||||
|
completion_tracker &tracker,
|
||||||
const char *text, const char *word)
|
const char *text, const char *word)
|
||||||
{
|
{
|
||||||
VEC (char_ptr) *vec_signals, *vec_keywords, *return_val;
|
|
||||||
static const char * const keywords[] =
|
static const char * const keywords[] =
|
||||||
{
|
{
|
||||||
"all",
|
"all",
|
||||||
|
@ -8710,13 +8710,8 @@ handle_completer (struct cmd_list_element *ignore,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
vec_signals = signal_completer (ignore, text, word);
|
signal_completer (ignore, tracker, text, word);
|
||||||
vec_keywords = complete_on_enum (keywords, word, word);
|
complete_on_enum (tracker, keywords, word, word);
|
||||||
|
|
||||||
return_val = VEC_merge (char_ptr, vec_signals, vec_keywords);
|
|
||||||
VEC_free (char_ptr, vec_signals);
|
|
||||||
VEC_free (char_ptr, vec_keywords);
|
|
||||||
return return_val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum gdb_signal
|
enum gdb_signal
|
||||||
|
|
|
@ -452,13 +452,13 @@ interpreter_exec_cmd (char *args, int from_tty)
|
||||||
|
|
||||||
/* See interps.h. */
|
/* See interps.h. */
|
||||||
|
|
||||||
VEC (char_ptr) *
|
void
|
||||||
interpreter_completer (struct cmd_list_element *ignore,
|
interpreter_completer (struct cmd_list_element *ignore,
|
||||||
|
completion_tracker &tracker,
|
||||||
const char *text, const char *word)
|
const char *text, const char *word)
|
||||||
{
|
{
|
||||||
struct interp_factory *interp;
|
struct interp_factory *interp;
|
||||||
int textlen;
|
int textlen;
|
||||||
VEC (char_ptr) *matches = NULL;
|
|
||||||
int ix;
|
int ix;
|
||||||
|
|
||||||
textlen = strlen (text);
|
textlen = strlen (text);
|
||||||
|
@ -485,11 +485,9 @@ interpreter_completer (struct cmd_list_element *ignore,
|
||||||
match[text - word] = '\0';
|
match[text - word] = '\0';
|
||||||
strcat (match, interp->name);
|
strcat (match, interp->name);
|
||||||
}
|
}
|
||||||
VEC_safe_push (char_ptr, matches, match);
|
tracker.add_completion (gdb::unique_xmalloc_ptr<char> (match));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return matches;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct interp *
|
struct interp *
|
||||||
|
|
|
@ -138,9 +138,10 @@ extern void interp_pre_command_loop (struct interp *interp);
|
||||||
|
|
||||||
/* List the possible interpreters which could complete the given
|
/* List the possible interpreters which could complete the given
|
||||||
text. */
|
text. */
|
||||||
extern VEC (char_ptr) *interpreter_completer (struct cmd_list_element *ignore,
|
extern void interpreter_completer (struct cmd_list_element *ignore,
|
||||||
const char *text,
|
completion_tracker &tracker,
|
||||||
const char *word);
|
const char *text,
|
||||||
|
const char *word);
|
||||||
|
|
||||||
/* well-known interpreters */
|
/* well-known interpreters */
|
||||||
#define INTERP_CONSOLE "console"
|
#define INTERP_CONSOLE "console"
|
||||||
|
|
|
@ -855,7 +855,7 @@ const struct language_defn unknown_language_defn =
|
||||||
1, /* c-style arrays */
|
1, /* c-style arrays */
|
||||||
0, /* String lower bound */
|
0, /* String lower bound */
|
||||||
default_word_break_characters,
|
default_word_break_characters,
|
||||||
default_make_symbol_completion_list,
|
default_collect_symbol_completion_matches,
|
||||||
unknown_language_arch_info, /* la_language_arch_info. */
|
unknown_language_arch_info, /* la_language_arch_info. */
|
||||||
default_print_array_index,
|
default_print_array_index,
|
||||||
default_pass_by_reference,
|
default_pass_by_reference,
|
||||||
|
@ -905,7 +905,7 @@ const struct language_defn auto_language_defn =
|
||||||
1, /* c-style arrays */
|
1, /* c-style arrays */
|
||||||
0, /* String lower bound */
|
0, /* String lower bound */
|
||||||
default_word_break_characters,
|
default_word_break_characters,
|
||||||
default_make_symbol_completion_list,
|
default_collect_symbol_completion_matches,
|
||||||
unknown_language_arch_info, /* la_language_arch_info. */
|
unknown_language_arch_info, /* la_language_arch_info. */
|
||||||
default_print_array_index,
|
default_print_array_index,
|
||||||
default_pass_by_reference,
|
default_pass_by_reference,
|
||||||
|
@ -953,7 +953,7 @@ const struct language_defn local_language_defn =
|
||||||
1, /* c-style arrays */
|
1, /* c-style arrays */
|
||||||
0, /* String lower bound */
|
0, /* String lower bound */
|
||||||
default_word_break_characters,
|
default_word_break_characters,
|
||||||
default_make_symbol_completion_list,
|
default_collect_symbol_completion_matches,
|
||||||
unknown_language_arch_info, /* la_language_arch_info. */
|
unknown_language_arch_info, /* la_language_arch_info. */
|
||||||
default_print_array_index,
|
default_print_array_index,
|
||||||
default_pass_by_reference,
|
default_pass_by_reference,
|
||||||
|
|
|
@ -134,7 +134,7 @@ struct language_arch_info
|
||||||
transformed for lookup. */
|
transformed for lookup. */
|
||||||
|
|
||||||
typedef int (*symbol_name_cmp_ftype) (const char *symbol_search_name,
|
typedef int (*symbol_name_cmp_ftype) (const char *symbol_search_name,
|
||||||
const char *lookup_name);
|
const char *lookup_name);
|
||||||
|
|
||||||
/* Structure tying together assorted information about a language. */
|
/* Structure tying together assorted information about a language. */
|
||||||
|
|
||||||
|
@ -323,14 +323,16 @@ struct language_defn
|
||||||
/* The list of characters forming word boundaries. */
|
/* The list of characters forming word boundaries. */
|
||||||
const char *(*la_word_break_characters) (void);
|
const char *(*la_word_break_characters) (void);
|
||||||
|
|
||||||
/* Should return a vector of all symbols which are possible
|
/* Add to the completion tracker all symbols which are possible
|
||||||
completions for TEXT. WORD is the entire command on which the
|
completions for TEXT. WORD is the entire command on which the
|
||||||
completion is being made. If CODE is TYPE_CODE_UNDEF, then all
|
completion is being made. If CODE is TYPE_CODE_UNDEF, then all
|
||||||
symbols should be examined; otherwise, only STRUCT_DOMAIN
|
symbols should be examined; otherwise, only STRUCT_DOMAIN
|
||||||
symbols whose type has a code of CODE should be matched. */
|
symbols whose type has a code of CODE should be matched. */
|
||||||
VEC (char_ptr) *(*la_make_symbol_completion_list) (const char *text,
|
void (*la_collect_symbol_completion_matches)
|
||||||
const char *word,
|
(completion_tracker &tracker,
|
||||||
enum type_code code);
|
const char *text,
|
||||||
|
const char *word,
|
||||||
|
enum type_code code);
|
||||||
|
|
||||||
/* The per-architecture (OS/ABI) language information. */
|
/* The per-architecture (OS/ABI) language information. */
|
||||||
void (*la_language_arch_info) (struct gdbarch *,
|
void (*la_language_arch_info) (struct gdbarch *,
|
||||||
|
|
|
@ -388,7 +388,7 @@ const struct language_defn m2_language_defn =
|
||||||
0, /* arrays are first-class (not c-style) */
|
0, /* arrays are first-class (not c-style) */
|
||||||
0, /* String lower bound */
|
0, /* String lower bound */
|
||||||
default_word_break_characters,
|
default_word_break_characters,
|
||||||
default_make_symbol_completion_list,
|
default_collect_symbol_completion_matches,
|
||||||
m2_language_arch_info,
|
m2_language_arch_info,
|
||||||
default_print_array_index,
|
default_print_array_index,
|
||||||
default_pass_by_reference,
|
default_pass_by_reference,
|
||||||
|
|
|
@ -397,7 +397,7 @@ const struct language_defn objc_language_defn = {
|
||||||
1, /* C-style arrays */
|
1, /* C-style arrays */
|
||||||
0, /* String lower bound */
|
0, /* String lower bound */
|
||||||
default_word_break_characters,
|
default_word_break_characters,
|
||||||
default_make_symbol_completion_list,
|
default_collect_symbol_completion_matches,
|
||||||
c_language_arch_info,
|
c_language_arch_info,
|
||||||
default_print_array_index,
|
default_print_array_index,
|
||||||
default_pass_by_reference,
|
default_pass_by_reference,
|
||||||
|
|
|
@ -1077,7 +1077,7 @@ const struct language_defn opencl_language_defn =
|
||||||
1, /* c-style arrays */
|
1, /* c-style arrays */
|
||||||
0, /* String lower bound */
|
0, /* String lower bound */
|
||||||
default_word_break_characters,
|
default_word_break_characters,
|
||||||
default_make_symbol_completion_list,
|
default_collect_symbol_completion_matches,
|
||||||
opencl_language_arch_info,
|
opencl_language_arch_info,
|
||||||
default_print_array_index,
|
default_print_array_index,
|
||||||
default_pass_by_reference,
|
default_pass_by_reference,
|
||||||
|
|
|
@ -451,7 +451,7 @@ const struct language_defn pascal_language_defn =
|
||||||
1, /* c-style arrays */
|
1, /* c-style arrays */
|
||||||
0, /* String lower bound */
|
0, /* String lower bound */
|
||||||
default_word_break_characters,
|
default_word_break_characters,
|
||||||
default_make_symbol_completion_list,
|
default_collect_symbol_completion_matches,
|
||||||
pascal_language_arch_info,
|
pascal_language_arch_info,
|
||||||
default_print_array_index,
|
default_print_array_index,
|
||||||
default_pass_by_reference,
|
default_pass_by_reference,
|
||||||
|
|
|
@ -242,10 +242,21 @@ cmdpy_completer_helper (struct cmd_list_element *command,
|
||||||
NULL));
|
NULL));
|
||||||
if (textobj == NULL)
|
if (textobj == NULL)
|
||||||
error (_("Could not convert argument to Python string."));
|
error (_("Could not convert argument to Python string."));
|
||||||
gdbpy_ref<> wordobj (PyUnicode_Decode (word, strlen (word), host_charset (),
|
|
||||||
NULL));
|
gdbpy_ref<> wordobj;
|
||||||
if (wordobj == NULL)
|
if (word == NULL)
|
||||||
error (_("Could not convert argument to Python string."));
|
{
|
||||||
|
/* "brkchars" phase. */
|
||||||
|
wordobj.reset (Py_None);
|
||||||
|
Py_INCREF (Py_None);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wordobj.reset (PyUnicode_Decode (word, strlen (word), host_charset (),
|
||||||
|
NULL));
|
||||||
|
if (wordobj == NULL)
|
||||||
|
error (_("Could not convert argument to Python string."));
|
||||||
|
}
|
||||||
|
|
||||||
gdbpy_ref<> resultobj (PyObject_CallMethodObjArgs ((PyObject *) obj,
|
gdbpy_ref<> resultobj (PyObject_CallMethodObjArgs ((PyObject *) obj,
|
||||||
complete_cst,
|
complete_cst,
|
||||||
|
@ -267,6 +278,7 @@ cmdpy_completer_helper (struct cmd_list_element *command,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cmdpy_completer_handle_brkchars (struct cmd_list_element *command,
|
cmdpy_completer_handle_brkchars (struct cmd_list_element *command,
|
||||||
|
completion_tracker &tracker,
|
||||||
const char *text, const char *word)
|
const char *text, const char *word)
|
||||||
{
|
{
|
||||||
gdbpy_enter enter_py (get_current_arch (), current_language);
|
gdbpy_enter enter_py (get_current_arch (), current_language);
|
||||||
|
@ -300,19 +312,18 @@ cmdpy_completer_handle_brkchars (struct cmd_list_element *command,
|
||||||
adjust the break characters accordingly. */
|
adjust the break characters accordingly. */
|
||||||
brkchars_fn = (completer_handle_brkchars_func_for_completer
|
brkchars_fn = (completer_handle_brkchars_func_for_completer
|
||||||
(completers[value].completer));
|
(completers[value].completer));
|
||||||
brkchars_fn (command, text, word);
|
brkchars_fn (command, tracker, text, word);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called by gdb for command completion. */
|
/* Called by gdb for command completion. */
|
||||||
|
|
||||||
static VEC (char_ptr) *
|
static void
|
||||||
cmdpy_completer (struct cmd_list_element *command,
|
cmdpy_completer (struct cmd_list_element *command,
|
||||||
|
completion_tracker &tracker,
|
||||||
const char *text, const char *word)
|
const char *text, const char *word)
|
||||||
{
|
{
|
||||||
VEC (char_ptr) *result = NULL;
|
|
||||||
|
|
||||||
gdbpy_enter enter_py (get_current_arch (), current_language);
|
gdbpy_enter enter_py (get_current_arch (), current_language);
|
||||||
|
|
||||||
/* Calling our helper to obtain the PyObject of the Python
|
/* Calling our helper to obtain the PyObject of the Python
|
||||||
|
@ -320,12 +331,10 @@ cmdpy_completer (struct cmd_list_element *command,
|
||||||
gdbpy_ref<> resultobj (cmdpy_completer_helper (command, text, word));
|
gdbpy_ref<> resultobj (cmdpy_completer_helper (command, text, word));
|
||||||
|
|
||||||
/* If the result object of calling the Python function is NULL, it
|
/* If the result object of calling the Python function is NULL, it
|
||||||
means that there was an error. In this case, just give up and
|
means that there was an error. In this case, just give up. */
|
||||||
return NULL. */
|
|
||||||
if (resultobj == NULL)
|
if (resultobj == NULL)
|
||||||
return NULL;
|
return;
|
||||||
|
|
||||||
result = NULL;
|
|
||||||
if (PyInt_Check (resultobj.get ()))
|
if (PyInt_Check (resultobj.get ()))
|
||||||
{
|
{
|
||||||
/* User code may also return one of the completion constants,
|
/* User code may also return one of the completion constants,
|
||||||
|
@ -338,15 +347,16 @@ cmdpy_completer (struct cmd_list_element *command,
|
||||||
PyErr_Clear ();
|
PyErr_Clear ();
|
||||||
}
|
}
|
||||||
else if (value >= 0 && value < (long) N_COMPLETERS)
|
else if (value >= 0 && value < (long) N_COMPLETERS)
|
||||||
result = completers[value].completer (command, text, word);
|
completers[value].completer (command, tracker, text, word);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gdbpy_ref<> iter (PyObject_GetIter (resultobj.get ()));
|
gdbpy_ref<> iter (PyObject_GetIter (resultobj.get ()));
|
||||||
|
|
||||||
if (iter == NULL)
|
if (iter == NULL)
|
||||||
return NULL;
|
return;
|
||||||
|
|
||||||
|
bool got_matches = false;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
gdbpy_ref<> elt (PyIter_Next (iter.get ()));
|
gdbpy_ref<> elt (PyIter_Next (iter.get ()));
|
||||||
|
@ -366,16 +376,15 @@ cmdpy_completer (struct cmd_list_element *command,
|
||||||
PyErr_Clear ();
|
PyErr_Clear ();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
VEC_safe_push (char_ptr, result, item.release ());
|
tracker.add_completion (std::move (item));
|
||||||
|
got_matches = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we got some results, ignore problems. Otherwise, report
|
/* If we got some results, ignore problems. Otherwise, report
|
||||||
the problem. */
|
the problem. */
|
||||||
if (result != NULL && PyErr_Occurred ())
|
if (got_matches && PyErr_Occurred ())
|
||||||
PyErr_Clear ();
|
PyErr_Clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper for cmdpy_init which locates the command list to use and
|
/* Helper for cmdpy_init which locates the command list to use and
|
||||||
|
|
|
@ -2184,7 +2184,7 @@ static const struct language_defn rust_language_defn =
|
||||||
1, /* c-style arrays */
|
1, /* c-style arrays */
|
||||||
0, /* String lower bound */
|
0, /* String lower bound */
|
||||||
default_word_break_characters,
|
default_word_break_characters,
|
||||||
default_make_symbol_completion_list,
|
default_collect_symbol_completion_matches,
|
||||||
rust_language_arch_info,
|
rust_language_arch_info,
|
||||||
default_print_array_index,
|
default_print_array_index,
|
||||||
default_pass_by_reference,
|
default_pass_by_reference,
|
||||||
|
|
274
gdb/symtab.c
274
gdb/symtab.c
|
@ -4747,44 +4747,13 @@ compare_symbol_name (const char *name, const char *sym_text, int sym_text_len)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free any memory associated with a completion list. */
|
|
||||||
|
|
||||||
static void
|
|
||||||
free_completion_list (VEC (char_ptr) **list_ptr)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
for (i = 0; VEC_iterate (char_ptr, *list_ptr, i, p); ++i)
|
|
||||||
xfree (p);
|
|
||||||
VEC_free (char_ptr, *list_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Callback for make_cleanup. */
|
|
||||||
|
|
||||||
static void
|
|
||||||
do_free_completion_list (void *list)
|
|
||||||
{
|
|
||||||
free_completion_list ((VEC (char_ptr) **) list);
|
|
||||||
}
|
|
||||||
|
|
||||||
static VEC (char_ptr) *return_val;
|
|
||||||
|
|
||||||
/* Tracker for how many unique completions have been generated. Used
|
|
||||||
to terminate completion list generation early if the list has grown
|
|
||||||
to a size so large as to be useless. This helps avoid GDB seeming
|
|
||||||
to lock up in the event the user requests to complete on something
|
|
||||||
vague that necessitates the time consuming expansion of many symbol
|
|
||||||
tables. */
|
|
||||||
|
|
||||||
static completion_tracker_t completion_tracker;
|
|
||||||
|
|
||||||
/* Test to see if the symbol specified by SYMNAME (which is already
|
/* Test to see if the symbol specified by SYMNAME (which is already
|
||||||
demangled for C++ symbols) matches SYM_TEXT in the first SYM_TEXT_LEN
|
demangled for C++ symbols) matches SYM_TEXT in the first SYM_TEXT_LEN
|
||||||
characters. If so, add it to the current completion list. */
|
characters. If so, add it to the current completion list. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
completion_list_add_name (const char *symname,
|
completion_list_add_name (completion_tracker &tracker,
|
||||||
|
const char *symname,
|
||||||
const char *sym_text, int sym_text_len,
|
const char *sym_text, int sym_text_len,
|
||||||
const char *text, const char *word)
|
const char *text, const char *word)
|
||||||
{
|
{
|
||||||
|
@ -4797,7 +4766,6 @@ completion_list_add_name (const char *symname,
|
||||||
|
|
||||||
{
|
{
|
||||||
char *newobj;
|
char *newobj;
|
||||||
enum maybe_add_completion_enum add_status;
|
|
||||||
|
|
||||||
if (word == sym_text)
|
if (word == sym_text)
|
||||||
{
|
{
|
||||||
|
@ -4819,45 +4787,33 @@ completion_list_add_name (const char *symname,
|
||||||
strcat (newobj, symname);
|
strcat (newobj, symname);
|
||||||
}
|
}
|
||||||
|
|
||||||
add_status = maybe_add_completion (completion_tracker, newobj);
|
gdb::unique_xmalloc_ptr<char> completion (newobj);
|
||||||
|
|
||||||
switch (add_status)
|
tracker.add_completion (std::move (completion));
|
||||||
{
|
|
||||||
case MAYBE_ADD_COMPLETION_OK:
|
|
||||||
VEC_safe_push (char_ptr, return_val, newobj);
|
|
||||||
break;
|
|
||||||
case MAYBE_ADD_COMPLETION_OK_MAX_REACHED:
|
|
||||||
VEC_safe_push (char_ptr, return_val, newobj);
|
|
||||||
throw_max_completions_reached_error ();
|
|
||||||
case MAYBE_ADD_COMPLETION_MAX_REACHED:
|
|
||||||
xfree (newobj);
|
|
||||||
throw_max_completions_reached_error ();
|
|
||||||
case MAYBE_ADD_COMPLETION_DUPLICATE:
|
|
||||||
xfree (newobj);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* completion_list_add_name wrapper for struct symbol. */
|
/* completion_list_add_name wrapper for struct symbol. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
completion_list_add_symbol (symbol *sym,
|
completion_list_add_symbol (completion_tracker &tracker,
|
||||||
|
symbol *sym,
|
||||||
const char *sym_text, int sym_text_len,
|
const char *sym_text, int sym_text_len,
|
||||||
const char *text, const char *word)
|
const char *text, const char *word)
|
||||||
{
|
{
|
||||||
completion_list_add_name (SYMBOL_NATURAL_NAME (sym),
|
completion_list_add_name (tracker, SYMBOL_NATURAL_NAME (sym),
|
||||||
sym_text, sym_text_len, text, word);
|
sym_text, sym_text_len, text, word);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* completion_list_add_name wrapper for struct minimal_symbol. */
|
/* completion_list_add_name wrapper for struct minimal_symbol. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
completion_list_add_msymbol (minimal_symbol *sym,
|
completion_list_add_msymbol (completion_tracker &tracker,
|
||||||
|
minimal_symbol *sym,
|
||||||
const char *sym_text, int sym_text_len,
|
const char *sym_text, int sym_text_len,
|
||||||
const char *text, const char *word)
|
const char *text, const char *word)
|
||||||
{
|
{
|
||||||
completion_list_add_name (MSYMBOL_NATURAL_NAME (sym),
|
completion_list_add_name (tracker, MSYMBOL_NATURAL_NAME (sym),
|
||||||
sym_text, sym_text_len, text, word);
|
sym_text, sym_text_len, text, word);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4865,7 +4821,8 @@ completion_list_add_msymbol (minimal_symbol *sym,
|
||||||
again and feed all the selectors into the mill. */
|
again and feed all the selectors into the mill. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
completion_list_objc_symbol (struct minimal_symbol *msymbol,
|
completion_list_objc_symbol (completion_tracker &tracker,
|
||||||
|
struct minimal_symbol *msymbol,
|
||||||
const char *sym_text, int sym_text_len,
|
const char *sym_text, int sym_text_len,
|
||||||
const char *text, const char *word)
|
const char *text, const char *word)
|
||||||
{
|
{
|
||||||
|
@ -4883,7 +4840,8 @@ completion_list_objc_symbol (struct minimal_symbol *msymbol,
|
||||||
|
|
||||||
if (sym_text[0] == '[')
|
if (sym_text[0] == '[')
|
||||||
/* Complete on shortened method method. */
|
/* Complete on shortened method method. */
|
||||||
completion_list_add_name (method + 1, sym_text, sym_text_len, text, word);
|
completion_list_add_name (tracker, method + 1,
|
||||||
|
sym_text, sym_text_len, text, word);
|
||||||
|
|
||||||
while ((strlen (method) + 1) >= tmplen)
|
while ((strlen (method) + 1) >= tmplen)
|
||||||
{
|
{
|
||||||
|
@ -4904,9 +4862,11 @@ completion_list_objc_symbol (struct minimal_symbol *msymbol,
|
||||||
memcpy (tmp, method, (category - method));
|
memcpy (tmp, method, (category - method));
|
||||||
tmp[category - method] = ' ';
|
tmp[category - method] = ' ';
|
||||||
memcpy (tmp + (category - method) + 1, selector, strlen (selector) + 1);
|
memcpy (tmp + (category - method) + 1, selector, strlen (selector) + 1);
|
||||||
completion_list_add_name (tmp, sym_text, sym_text_len, text, word);
|
completion_list_add_name (tracker, tmp,
|
||||||
|
sym_text, sym_text_len, text, word);
|
||||||
if (sym_text[0] == '[')
|
if (sym_text[0] == '[')
|
||||||
completion_list_add_name (tmp + 1, sym_text, sym_text_len, text, word);
|
completion_list_add_name (tracker, tmp + 1,
|
||||||
|
sym_text, sym_text_len, text, word);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selector != NULL)
|
if (selector != NULL)
|
||||||
|
@ -4917,7 +4877,8 @@ completion_list_objc_symbol (struct minimal_symbol *msymbol,
|
||||||
if (tmp2 != NULL)
|
if (tmp2 != NULL)
|
||||||
*tmp2 = '\0';
|
*tmp2 = '\0';
|
||||||
|
|
||||||
completion_list_add_name (tmp, sym_text, sym_text_len, text, word);
|
completion_list_add_name (tracker, tmp,
|
||||||
|
sym_text, sym_text_len, text, word);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4968,9 +4929,10 @@ language_search_unquoted_string (const char *text, const char *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
completion_list_add_fields (struct symbol *sym, const char *sym_text,
|
completion_list_add_fields (completion_tracker &tracker,
|
||||||
int sym_text_len, const char *text,
|
struct symbol *sym,
|
||||||
const char *word)
|
const char *sym_text, int sym_text_len,
|
||||||
|
const char *text, const char *word)
|
||||||
{
|
{
|
||||||
if (SYMBOL_CLASS (sym) == LOC_TYPEDEF)
|
if (SYMBOL_CLASS (sym) == LOC_TYPEDEF)
|
||||||
{
|
{
|
||||||
|
@ -4981,7 +4943,7 @@ completion_list_add_fields (struct symbol *sym, const char *sym_text,
|
||||||
if (c == TYPE_CODE_UNION || c == TYPE_CODE_STRUCT)
|
if (c == TYPE_CODE_UNION || c == TYPE_CODE_STRUCT)
|
||||||
for (j = TYPE_N_BASECLASSES (t); j < TYPE_NFIELDS (t); j++)
|
for (j = TYPE_N_BASECLASSES (t); j < TYPE_NFIELDS (t); j++)
|
||||||
if (TYPE_FIELD_NAME (t, j))
|
if (TYPE_FIELD_NAME (t, j))
|
||||||
completion_list_add_name (TYPE_FIELD_NAME (t, j),
|
completion_list_add_name (tracker, TYPE_FIELD_NAME (t, j),
|
||||||
sym_text, sym_text_len, text, word);
|
sym_text, sym_text_len, text, word);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4990,6 +4952,7 @@ completion_list_add_fields (struct symbol *sym, const char *sym_text,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_symtab_completions (struct compunit_symtab *cust,
|
add_symtab_completions (struct compunit_symtab *cust,
|
||||||
|
completion_tracker &tracker,
|
||||||
const char *sym_text, int sym_text_len,
|
const char *sym_text, int sym_text_len,
|
||||||
const char *text, const char *word,
|
const char *text, const char *word,
|
||||||
enum type_code code)
|
enum type_code code)
|
||||||
|
@ -5011,18 +4974,18 @@ add_symtab_completions (struct compunit_symtab *cust,
|
||||||
if (code == TYPE_CODE_UNDEF
|
if (code == TYPE_CODE_UNDEF
|
||||||
|| (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
|
|| (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
|
||||||
&& TYPE_CODE (SYMBOL_TYPE (sym)) == code))
|
&& TYPE_CODE (SYMBOL_TYPE (sym)) == code))
|
||||||
completion_list_add_symbol (sym,
|
completion_list_add_symbol (tracker, sym,
|
||||||
sym_text, sym_text_len,
|
sym_text, sym_text_len,
|
||||||
text, word);
|
text, word);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
default_make_symbol_completion_list_break_on_1 (const char *text,
|
default_collect_symbol_completion_matches_break_on
|
||||||
const char *word,
|
(completion_tracker &tracker,
|
||||||
const char *break_on,
|
const char *text, const char *word,
|
||||||
enum type_code code)
|
const char *break_on, enum type_code code)
|
||||||
{
|
{
|
||||||
/* Problem: All of the symbols have to be copied because readline
|
/* Problem: All of the symbols have to be copied because readline
|
||||||
frees them. I'm not going to worry about this; hopefully there
|
frees them. I'm not going to worry about this; hopefully there
|
||||||
|
@ -5039,7 +5002,6 @@ default_make_symbol_completion_list_break_on_1 (const char *text,
|
||||||
const char *sym_text;
|
const char *sym_text;
|
||||||
/* Length of sym_text. */
|
/* Length of sym_text. */
|
||||||
int sym_text_len;
|
int sym_text_len;
|
||||||
struct cleanup *cleanups;
|
|
||||||
|
|
||||||
/* Now look for the symbol we are supposed to complete on. */
|
/* Now look for the symbol we are supposed to complete on. */
|
||||||
{
|
{
|
||||||
|
@ -5109,9 +5071,6 @@ default_make_symbol_completion_list_break_on_1 (const char *text,
|
||||||
}
|
}
|
||||||
gdb_assert (sym_text[sym_text_len] == '\0' || sym_text[sym_text_len] == '(');
|
gdb_assert (sym_text[sym_text_len] == '\0' || sym_text[sym_text_len] == '(');
|
||||||
|
|
||||||
completion_tracker = new_completion_tracker ();
|
|
||||||
cleanups = make_cleanup_free_completion_tracker (&completion_tracker);
|
|
||||||
|
|
||||||
/* At this point scan through the misc symbol vectors and add each
|
/* At this point scan through the misc symbol vectors and add each
|
||||||
symbol you find to the list. Eventually we want to ignore
|
symbol you find to the list. Eventually we want to ignore
|
||||||
anything that isn't a text symbol (everything else will be
|
anything that isn't a text symbol (everything else will be
|
||||||
|
@ -5122,18 +5081,21 @@ default_make_symbol_completion_list_break_on_1 (const char *text,
|
||||||
ALL_MSYMBOLS (objfile, msymbol)
|
ALL_MSYMBOLS (objfile, msymbol)
|
||||||
{
|
{
|
||||||
QUIT;
|
QUIT;
|
||||||
completion_list_add_msymbol (msymbol, sym_text, sym_text_len, text,
|
|
||||||
word);
|
|
||||||
|
|
||||||
completion_list_objc_symbol (msymbol, sym_text, sym_text_len, text,
|
completion_list_add_msymbol (tracker,
|
||||||
word);
|
msymbol, sym_text, sym_text_len,
|
||||||
|
text, word);
|
||||||
|
|
||||||
|
completion_list_objc_symbol (tracker,
|
||||||
|
msymbol, sym_text, sym_text_len,
|
||||||
|
text, word);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add completions for all currently loaded symbol tables. */
|
/* Add completions for all currently loaded symbol tables. */
|
||||||
ALL_COMPUNITS (objfile, cust)
|
ALL_COMPUNITS (objfile, cust)
|
||||||
add_symtab_completions (cust, sym_text, sym_text_len, text, word,
|
add_symtab_completions (cust, tracker,
|
||||||
code);
|
sym_text, sym_text_len, text, word, code);
|
||||||
|
|
||||||
/* Look through the partial symtabs for all symbols which begin by
|
/* Look through the partial symtabs for all symbols which begin by
|
||||||
matching SYM_TEXT. Expand all CUs that you find to the list. */
|
matching SYM_TEXT. Expand all CUs that you find to the list. */
|
||||||
|
@ -5147,6 +5109,7 @@ default_make_symbol_completion_list_break_on_1 (const char *text,
|
||||||
[&] (compunit_symtab *symtab) /* expansion notify */
|
[&] (compunit_symtab *symtab) /* expansion notify */
|
||||||
{
|
{
|
||||||
add_symtab_completions (symtab,
|
add_symtab_completions (symtab,
|
||||||
|
tracker,
|
||||||
sym_text, sym_text_len,
|
sym_text, sym_text_len,
|
||||||
text, word, code);
|
text, word, code);
|
||||||
},
|
},
|
||||||
|
@ -5169,14 +5132,17 @@ default_make_symbol_completion_list_break_on_1 (const char *text,
|
||||||
{
|
{
|
||||||
if (code == TYPE_CODE_UNDEF)
|
if (code == TYPE_CODE_UNDEF)
|
||||||
{
|
{
|
||||||
completion_list_add_symbol (sym, sym_text, sym_text_len, text,
|
completion_list_add_symbol (tracker, sym,
|
||||||
|
sym_text, sym_text_len, text,
|
||||||
word);
|
word);
|
||||||
completion_list_add_fields (sym, sym_text, sym_text_len, text,
|
completion_list_add_fields (tracker, sym,
|
||||||
|
sym_text, sym_text_len, text,
|
||||||
word);
|
word);
|
||||||
}
|
}
|
||||||
else if (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
|
else if (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
|
||||||
&& TYPE_CODE (SYMBOL_TYPE (sym)) == code)
|
&& TYPE_CODE (SYMBOL_TYPE (sym)) == code)
|
||||||
completion_list_add_symbol (sym, sym_text, sym_text_len, text,
|
completion_list_add_symbol (tracker, sym,
|
||||||
|
sym_text, sym_text_len, text,
|
||||||
word);
|
word);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5194,11 +5160,13 @@ default_make_symbol_completion_list_break_on_1 (const char *text,
|
||||||
{
|
{
|
||||||
if (surrounding_static_block != NULL)
|
if (surrounding_static_block != NULL)
|
||||||
ALL_BLOCK_SYMBOLS (surrounding_static_block, iter, sym)
|
ALL_BLOCK_SYMBOLS (surrounding_static_block, iter, sym)
|
||||||
completion_list_add_fields (sym, sym_text, sym_text_len, text, word);
|
completion_list_add_fields (tracker, sym,
|
||||||
|
sym_text, sym_text_len, text, word);
|
||||||
|
|
||||||
if (surrounding_global_block != NULL)
|
if (surrounding_global_block != NULL)
|
||||||
ALL_BLOCK_SYMBOLS (surrounding_global_block, iter, sym)
|
ALL_BLOCK_SYMBOLS (surrounding_global_block, iter, sym)
|
||||||
completion_list_add_fields (sym, sym_text, sym_text_len, text, word);
|
completion_list_add_fields (tracker, sym,
|
||||||
|
sym_text, sym_text_len, text, word);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip macros if we are completing a struct tag -- arguable but
|
/* Skip macros if we are completing a struct tag -- arguable but
|
||||||
|
@ -5214,7 +5182,7 @@ default_make_symbol_completion_list_break_on_1 (const char *text,
|
||||||
macro_source_file *,
|
macro_source_file *,
|
||||||
int)
|
int)
|
||||||
{
|
{
|
||||||
completion_list_add_name (macro_name,
|
completion_list_add_name (tracker, macro_name,
|
||||||
sym_text, sym_text_len,
|
sym_text, sym_text_len,
|
||||||
text, word);
|
text, word);
|
||||||
};
|
};
|
||||||
|
@ -5237,74 +5205,52 @@ default_make_symbol_completion_list_break_on_1 (const char *text,
|
||||||
/* User-defined macros are always visible. */
|
/* User-defined macros are always visible. */
|
||||||
macro_for_each (macro_user_macros, add_macro_name);
|
macro_for_each (macro_user_macros, add_macro_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
do_cleanups (cleanups);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VEC (char_ptr) *
|
void
|
||||||
default_make_symbol_completion_list_break_on (const char *text,
|
default_collect_symbol_completion_matches (completion_tracker &tracker,
|
||||||
const char *word,
|
const char *text, const char *word,
|
||||||
const char *break_on,
|
enum type_code code)
|
||||||
enum type_code code)
|
|
||||||
{
|
{
|
||||||
struct cleanup *back_to;
|
return default_collect_symbol_completion_matches_break_on (tracker,
|
||||||
|
text, word, "",
|
||||||
return_val = NULL;
|
code);
|
||||||
back_to = make_cleanup (do_free_completion_list, &return_val);
|
|
||||||
|
|
||||||
TRY
|
|
||||||
{
|
|
||||||
default_make_symbol_completion_list_break_on_1 (text, word,
|
|
||||||
break_on, code);
|
|
||||||
}
|
|
||||||
CATCH (except, RETURN_MASK_ERROR)
|
|
||||||
{
|
|
||||||
if (except.error != MAX_COMPLETIONS_REACHED_ERROR)
|
|
||||||
throw_exception (except);
|
|
||||||
}
|
|
||||||
END_CATCH
|
|
||||||
|
|
||||||
discard_cleanups (back_to);
|
|
||||||
return return_val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VEC (char_ptr) *
|
/* Collect all symbols (regardless of class) which begin by matching
|
||||||
default_make_symbol_completion_list (const char *text, const char *word,
|
TEXT. */
|
||||||
enum type_code code)
|
|
||||||
|
void
|
||||||
|
collect_symbol_completion_matches (completion_tracker &tracker,
|
||||||
|
const char *text, const char *word)
|
||||||
{
|
{
|
||||||
return default_make_symbol_completion_list_break_on (text, word, "", code);
|
current_language->la_collect_symbol_completion_matches (tracker,
|
||||||
|
text, word,
|
||||||
|
TYPE_CODE_UNDEF);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return a vector of all symbols (regardless of class) which begin by
|
/* Like collect_symbol_completion_matches, but only collect
|
||||||
matching TEXT. If the answer is no symbols, then the return value
|
STRUCT_DOMAIN symbols whose type code is CODE. */
|
||||||
is NULL. */
|
|
||||||
|
|
||||||
VEC (char_ptr) *
|
void
|
||||||
make_symbol_completion_list (const char *text, const char *word)
|
collect_symbol_completion_matches_type (completion_tracker &tracker,
|
||||||
{
|
const char *text, const char *word,
|
||||||
return current_language->la_make_symbol_completion_list (text, word,
|
enum type_code code)
|
||||||
TYPE_CODE_UNDEF);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Like make_symbol_completion_list, but only return STRUCT_DOMAIN
|
|
||||||
symbols whose type code is CODE. */
|
|
||||||
|
|
||||||
VEC (char_ptr) *
|
|
||||||
make_symbol_completion_type (const char *text, const char *word,
|
|
||||||
enum type_code code)
|
|
||||||
{
|
{
|
||||||
gdb_assert (code == TYPE_CODE_UNION
|
gdb_assert (code == TYPE_CODE_UNION
|
||||||
|| code == TYPE_CODE_STRUCT
|
|| code == TYPE_CODE_STRUCT
|
||||||
|| code == TYPE_CODE_ENUM);
|
|| code == TYPE_CODE_ENUM);
|
||||||
return current_language->la_make_symbol_completion_list (text, word, code);
|
current_language->la_collect_symbol_completion_matches (tracker,
|
||||||
|
text, word, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Like make_symbol_completion_list, but returns a list of symbols
|
/* Like collect_symbol_completion_matches, but collects a list of
|
||||||
defined in all source files name SRCFILE. */
|
symbols defined in all source files named SRCFILE. */
|
||||||
|
|
||||||
static VEC (char_ptr) *
|
void
|
||||||
make_file_symbol_completion_list_1 (const char *text, const char *word,
|
collect_file_symbol_completion_matches (completion_tracker &tracker,
|
||||||
const char *srcfile)
|
const char *text, const char *word,
|
||||||
|
const char *srcfile)
|
||||||
{
|
{
|
||||||
/* The symbol we are completing on. Points in same buffer as text. */
|
/* The symbol we are completing on. Points in same buffer as text. */
|
||||||
const char *sym_text;
|
const char *sym_text;
|
||||||
|
@ -5345,7 +5291,7 @@ make_file_symbol_completion_list_1 (const char *text, const char *word,
|
||||||
/* A double-quoted string is never a symbol, nor does it make sense
|
/* A double-quoted string is never a symbol, nor does it make sense
|
||||||
to complete it any other way. */
|
to complete it any other way. */
|
||||||
{
|
{
|
||||||
return NULL;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -5361,42 +5307,11 @@ make_file_symbol_completion_list_1 (const char *text, const char *word,
|
||||||
iterate_over_symtabs (srcfile, [&] (symtab *s)
|
iterate_over_symtabs (srcfile, [&] (symtab *s)
|
||||||
{
|
{
|
||||||
add_symtab_completions (SYMTAB_COMPUNIT (s),
|
add_symtab_completions (SYMTAB_COMPUNIT (s),
|
||||||
|
tracker,
|
||||||
sym_text, sym_text_len,
|
sym_text, sym_text_len,
|
||||||
text, word, TYPE_CODE_UNDEF);
|
text, word, TYPE_CODE_UNDEF);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
return (return_val);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wrapper around make_file_symbol_completion_list_1
|
|
||||||
to handle MAX_COMPLETIONS_REACHED_ERROR. */
|
|
||||||
|
|
||||||
VEC (char_ptr) *
|
|
||||||
make_file_symbol_completion_list (const char *text, const char *word,
|
|
||||||
const char *srcfile)
|
|
||||||
{
|
|
||||||
struct cleanup *back_to, *cleanups;
|
|
||||||
|
|
||||||
completion_tracker = new_completion_tracker ();
|
|
||||||
cleanups = make_cleanup_free_completion_tracker (&completion_tracker);
|
|
||||||
return_val = NULL;
|
|
||||||
back_to = make_cleanup (do_free_completion_list, &return_val);
|
|
||||||
|
|
||||||
TRY
|
|
||||||
{
|
|
||||||
make_file_symbol_completion_list_1 (text, word, srcfile);
|
|
||||||
}
|
|
||||||
CATCH (except, RETURN_MASK_ERROR)
|
|
||||||
{
|
|
||||||
if (except.error != MAX_COMPLETIONS_REACHED_ERROR)
|
|
||||||
throw_exception (except);
|
|
||||||
}
|
|
||||||
END_CATCH
|
|
||||||
|
|
||||||
discard_cleanups (back_to);
|
|
||||||
do_cleanups (cleanups);
|
|
||||||
return return_val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A helper function for make_source_files_completion_list. It adds
|
/* A helper function for make_source_files_completion_list. It adds
|
||||||
|
@ -5405,7 +5320,7 @@ make_file_symbol_completion_list (const char *text, const char *word,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_filename_to_list (const char *fname, const char *text, const char *word,
|
add_filename_to_list (const char *fname, const char *text, const char *word,
|
||||||
VEC (char_ptr) **list)
|
completion_list *list)
|
||||||
{
|
{
|
||||||
char *newobj;
|
char *newobj;
|
||||||
size_t fnlen = strlen (fname);
|
size_t fnlen = strlen (fname);
|
||||||
|
@ -5430,7 +5345,7 @@ add_filename_to_list (const char *fname, const char *text, const char *word,
|
||||||
newobj[text - word] = '\0';
|
newobj[text - word] = '\0';
|
||||||
strcat (newobj, fname);
|
strcat (newobj, fname);
|
||||||
}
|
}
|
||||||
VEC_safe_push (char_ptr, *list, newobj);
|
list->emplace_back (newobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -5458,7 +5373,7 @@ struct add_partial_filename_data
|
||||||
const char *text;
|
const char *text;
|
||||||
const char *word;
|
const char *word;
|
||||||
int text_len;
|
int text_len;
|
||||||
VEC (char_ptr) **list;
|
completion_list *list;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A callback for map_partial_symbol_filenames. */
|
/* A callback for map_partial_symbol_filenames. */
|
||||||
|
@ -5490,19 +5405,18 @@ maybe_add_partial_symtab_filename (const char *filename, const char *fullname,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return a vector of all source files whose names begin with matching
|
/* Return a list of all source files whose names begin with matching
|
||||||
TEXT. The file names are looked up in the symbol tables of this
|
TEXT. The file names are looked up in the symbol tables of this
|
||||||
program. If the answer is no matchess, then the return value is
|
program. */
|
||||||
NULL. */
|
|
||||||
|
|
||||||
VEC (char_ptr) *
|
completion_list
|
||||||
make_source_files_completion_list (const char *text, const char *word)
|
make_source_files_completion_list (const char *text, const char *word)
|
||||||
{
|
{
|
||||||
struct compunit_symtab *cu;
|
struct compunit_symtab *cu;
|
||||||
struct symtab *s;
|
struct symtab *s;
|
||||||
struct objfile *objfile;
|
struct objfile *objfile;
|
||||||
size_t text_len = strlen (text);
|
size_t text_len = strlen (text);
|
||||||
VEC (char_ptr) *list = NULL;
|
completion_list list;
|
||||||
const char *base_name;
|
const char *base_name;
|
||||||
struct add_partial_filename_data datum;
|
struct add_partial_filename_data datum;
|
||||||
struct cleanup *back_to;
|
struct cleanup *back_to;
|
||||||
|
@ -5510,8 +5424,6 @@ make_source_files_completion_list (const char *text, const char *word)
|
||||||
if (!have_full_symbols () && !have_partial_symbols ())
|
if (!have_full_symbols () && !have_partial_symbols ())
|
||||||
return list;
|
return list;
|
||||||
|
|
||||||
back_to = make_cleanup (do_free_completion_list, &list);
|
|
||||||
|
|
||||||
filename_seen_cache filenames_seen;
|
filename_seen_cache filenames_seen;
|
||||||
|
|
||||||
ALL_FILETABS (objfile, cu, s)
|
ALL_FILETABS (objfile, cu, s)
|
||||||
|
@ -5547,8 +5459,6 @@ make_source_files_completion_list (const char *text, const char *word)
|
||||||
map_symbol_filenames (maybe_add_partial_symtab_filename, &datum,
|
map_symbol_filenames (maybe_add_partial_symtab_filename, &datum,
|
||||||
0 /*need_fullname*/);
|
0 /*need_fullname*/);
|
||||||
|
|
||||||
discard_cleanups (back_to);
|
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
31
gdb/symtab.h
31
gdb/symtab.h
|
@ -25,6 +25,7 @@
|
||||||
#include "gdbtypes.h"
|
#include "gdbtypes.h"
|
||||||
#include "common/enum-flags.h"
|
#include "common/enum-flags.h"
|
||||||
#include "common/function-view.h"
|
#include "common/function-view.h"
|
||||||
|
#include "completer.h"
|
||||||
|
|
||||||
/* Opaque declarations. */
|
/* Opaque declarations. */
|
||||||
struct ui_file;
|
struct ui_file;
|
||||||
|
@ -1498,22 +1499,28 @@ extern void forget_cached_source_info (void);
|
||||||
|
|
||||||
extern void select_source_symtab (struct symtab *);
|
extern void select_source_symtab (struct symtab *);
|
||||||
|
|
||||||
extern VEC (char_ptr) *default_make_symbol_completion_list_break_on
|
extern void default_collect_symbol_completion_matches_break_on
|
||||||
(const char *text, const char *word, const char *break_on,
|
(completion_tracker &tracker,
|
||||||
|
const char *text, const char *word, const char *break_on,
|
||||||
enum type_code code);
|
enum type_code code);
|
||||||
extern VEC (char_ptr) *default_make_symbol_completion_list (const char *,
|
extern void default_collect_symbol_completion_matches
|
||||||
const char *,
|
(completion_tracker &tracker,
|
||||||
enum type_code);
|
const char *,
|
||||||
extern VEC (char_ptr) *make_symbol_completion_list (const char *, const char *);
|
const char *,
|
||||||
extern VEC (char_ptr) *make_symbol_completion_type (const char *, const char *,
|
enum type_code);
|
||||||
|
extern void collect_symbol_completion_matches (completion_tracker &tracker,
|
||||||
|
const char *, const char *);
|
||||||
|
extern void collect_symbol_completion_matches_type (completion_tracker &tracker,
|
||||||
|
const char *, const char *,
|
||||||
enum type_code);
|
enum type_code);
|
||||||
|
|
||||||
extern VEC (char_ptr) *make_file_symbol_completion_list (const char *,
|
extern void collect_file_symbol_completion_matches (completion_tracker &tracker,
|
||||||
const char *,
|
const char *,
|
||||||
const char *);
|
const char *,
|
||||||
|
const char *);
|
||||||
|
|
||||||
extern VEC (char_ptr) *make_source_files_completion_list (const char *,
|
extern completion_list
|
||||||
const char *);
|
make_source_files_completion_list (const char *, const char *);
|
||||||
|
|
||||||
/* symtab.c */
|
/* symtab.c */
|
||||||
|
|
||||||
|
|
|
@ -2023,7 +2023,7 @@ init_main (void)
|
||||||
|
|
||||||
/* Setup important stuff for command line editing. */
|
/* Setup important stuff for command line editing. */
|
||||||
rl_completion_word_break_hook = gdb_completion_word_break_characters;
|
rl_completion_word_break_hook = gdb_completion_word_break_characters;
|
||||||
rl_completion_entry_function = readline_line_completion_function;
|
rl_attempted_completion_function = gdb_rl_attempted_completion_function;
|
||||||
set_rl_completer_word_break_characters (default_word_break_characters ());
|
set_rl_completer_word_break_characters (default_word_break_characters ());
|
||||||
rl_completer_quote_characters = get_gdb_completer_quote_characters ();
|
rl_completer_quote_characters = get_gdb_completer_quote_characters ();
|
||||||
rl_completion_display_matches_hook = cli_display_match_list;
|
rl_completion_display_matches_hook = cli_display_match_list;
|
||||||
|
|
|
@ -353,14 +353,15 @@ tui_default_win_viewport_height (enum tui_win_type type,
|
||||||
/* Complete possible layout names. TEXT is the complete text entered so
|
/* Complete possible layout names. TEXT is the complete text entered so
|
||||||
far, WORD is the word currently being completed. */
|
far, WORD is the word currently being completed. */
|
||||||
|
|
||||||
static VEC (char_ptr) *
|
static void
|
||||||
layout_completer (struct cmd_list_element *ignore,
|
layout_completer (struct cmd_list_element *ignore,
|
||||||
|
completion_tracker &tracker,
|
||||||
const char *text, const char *word)
|
const char *text, const char *word)
|
||||||
{
|
{
|
||||||
static const char *layout_names [] =
|
static const char *layout_names [] =
|
||||||
{ "src", "asm", "split", "regs", "next", "prev", NULL };
|
{ "src", "asm", "split", "regs", "next", "prev", NULL };
|
||||||
|
|
||||||
return complete_on_enum (layout_names, text, word);
|
complete_on_enum (tracker, layout_names, text, word);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Function to initialize gdb commands, for tui window layout
|
/* Function to initialize gdb commands, for tui window layout
|
||||||
|
|
|
@ -668,24 +668,23 @@ tui_reg_command (char *args, int from_tty)
|
||||||
/* Complete names of register groups, and add the special "prev" and "next"
|
/* Complete names of register groups, and add the special "prev" and "next"
|
||||||
names. */
|
names. */
|
||||||
|
|
||||||
static VEC (char_ptr) *
|
static void
|
||||||
tui_reggroup_completer (struct cmd_list_element *ignore,
|
tui_reggroup_completer (struct cmd_list_element *ignore,
|
||||||
|
completion_tracker &tracker,
|
||||||
const char *text, const char *word)
|
const char *text, const char *word)
|
||||||
{
|
{
|
||||||
VEC (char_ptr) *result = NULL;
|
|
||||||
static const char *extra[] = { "next", "prev", NULL };
|
static const char *extra[] = { "next", "prev", NULL };
|
||||||
size_t len = strlen (word);
|
size_t len = strlen (word);
|
||||||
const char **tmp;
|
const char **tmp;
|
||||||
|
|
||||||
result = reggroup_completer (ignore, text, word);
|
reggroup_completer (ignore, tracker, text, word);
|
||||||
|
|
||||||
|
/* XXXX use complete_on_enum instead? */
|
||||||
for (tmp = extra; *tmp != NULL; ++tmp)
|
for (tmp = extra; *tmp != NULL; ++tmp)
|
||||||
{
|
{
|
||||||
if (strncmp (word, *tmp, len) == 0)
|
if (strncmp (word, *tmp, len) == 0)
|
||||||
VEC_safe_push (char_ptr, result, xstrdup (*tmp));
|
tracker.add_completion (gdb::unique_xmalloc_ptr<char> (xstrdup (*tmp)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Provide a prototype to silence -Wmissing-prototypes. */
|
/* Provide a prototype to silence -Wmissing-prototypes. */
|
||||||
|
|
|
@ -359,12 +359,12 @@ tui_set_var_cmd (char *null_args, int from_tty, struct cmd_list_element *c)
|
||||||
window names 'next' and 'prev' will also be considered as possible
|
window names 'next' and 'prev' will also be considered as possible
|
||||||
completions of the window name. */
|
completions of the window name. */
|
||||||
|
|
||||||
static VEC (char_ptr) *
|
static void
|
||||||
window_name_completer (int include_next_prev_p,
|
window_name_completer (completion_tracker &tracker,
|
||||||
|
int include_next_prev_p,
|
||||||
const char *text, const char *word)
|
const char *text, const char *word)
|
||||||
{
|
{
|
||||||
VEC (const_char_ptr) *completion_name_vec = NULL;
|
VEC (const_char_ptr) *completion_name_vec = NULL;
|
||||||
VEC (char_ptr) *matches_vec;
|
|
||||||
int win_type;
|
int win_type;
|
||||||
|
|
||||||
for (win_type = SRC_WIN; win_type < MAX_MAJOR_WINDOWS; win_type++)
|
for (win_type = SRC_WIN; win_type < MAX_MAJOR_WINDOWS; win_type++)
|
||||||
|
@ -398,39 +398,39 @@ window_name_completer (int include_next_prev_p,
|
||||||
}
|
}
|
||||||
|
|
||||||
VEC_safe_push (const_char_ptr, completion_name_vec, NULL);
|
VEC_safe_push (const_char_ptr, completion_name_vec, NULL);
|
||||||
matches_vec
|
complete_on_enum (tracker,
|
||||||
= complete_on_enum (VEC_address (const_char_ptr, completion_name_vec),
|
VEC_address (const_char_ptr, completion_name_vec),
|
||||||
text, word);
|
text, word);
|
||||||
|
|
||||||
VEC_free (const_char_ptr, completion_name_vec);
|
VEC_free (const_char_ptr, completion_name_vec);
|
||||||
|
|
||||||
return matches_vec;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Complete possible window names to focus on. TEXT is the complete text
|
/* Complete possible window names to focus on. TEXT is the complete text
|
||||||
entered so far, WORD is the word currently being completed. */
|
entered so far, WORD is the word currently being completed. */
|
||||||
|
|
||||||
static VEC (char_ptr) *
|
static void
|
||||||
focus_completer (struct cmd_list_element *ignore,
|
focus_completer (struct cmd_list_element *ignore,
|
||||||
const char *text, const char *word)
|
completion_tracker &tracker,
|
||||||
|
const char *text, const char *word)
|
||||||
{
|
{
|
||||||
return window_name_completer (1, text, word);
|
window_name_completer (tracker, 1, text, word);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Complete possible window names for winheight command. TEXT is the
|
/* Complete possible window names for winheight command. TEXT is the
|
||||||
complete text entered so far, WORD is the word currently being
|
complete text entered so far, WORD is the word currently being
|
||||||
completed. */
|
completed. */
|
||||||
|
|
||||||
static VEC (char_ptr) *
|
static void
|
||||||
winheight_completer (struct cmd_list_element *ignore,
|
winheight_completer (struct cmd_list_element *ignore,
|
||||||
|
completion_tracker &tracker,
|
||||||
const char *text, const char *word)
|
const char *text, const char *word)
|
||||||
{
|
{
|
||||||
/* The first word is the window name. That we can complete. Subsequent
|
/* The first word is the window name. That we can complete. Subsequent
|
||||||
words can't be completed. */
|
words can't be completed. */
|
||||||
if (word != text)
|
if (word != text)
|
||||||
return NULL;
|
return;
|
||||||
|
|
||||||
return window_name_completer (0, text, word);
|
window_name_completer (tracker, 0, text, word);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Function to initialize gdb commands, for tui window
|
/* Function to initialize gdb commands, for tui window
|
||||||
|
|
17
gdb/value.c
17
gdb/value.c
|
@ -41,6 +41,7 @@
|
||||||
#include "cp-abi.h"
|
#include "cp-abi.h"
|
||||||
#include "user-regs.h"
|
#include "user-regs.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include "completer.h"
|
||||||
|
|
||||||
/* Prototypes for exported functions. */
|
/* Prototypes for exported functions. */
|
||||||
|
|
||||||
|
@ -2144,14 +2145,12 @@ lookup_only_internalvar (const char *name)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Complete NAME by comparing it to the names of internal variables.
|
/* Complete NAME by comparing it to the names of internal
|
||||||
Returns a vector of newly allocated strings, or NULL if no matches
|
variables. */
|
||||||
were found. */
|
|
||||||
|
|
||||||
VEC (char_ptr) *
|
void
|
||||||
complete_internalvar (const char *name)
|
complete_internalvar (completion_tracker &tracker, const char *name)
|
||||||
{
|
{
|
||||||
VEC (char_ptr) *result = NULL;
|
|
||||||
struct internalvar *var;
|
struct internalvar *var;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
@ -2160,12 +2159,10 @@ complete_internalvar (const char *name)
|
||||||
for (var = internalvars; var; var = var->next)
|
for (var = internalvars; var; var = var->next)
|
||||||
if (strncmp (var->name, name, len) == 0)
|
if (strncmp (var->name, name, len) == 0)
|
||||||
{
|
{
|
||||||
char *r = xstrdup (var->name);
|
gdb::unique_xmalloc_ptr<char> copy (xstrdup (var->name));
|
||||||
|
|
||||||
VEC_safe_push (char_ptr, result, r);
|
tracker.add_completion (std::move (copy));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create an internal variable with name NAME and with a void value.
|
/* Create an internal variable with name NAME and with a void value.
|
||||||
|
|
|
@ -927,7 +927,8 @@ extern struct internalvar *lookup_only_internalvar (const char *name);
|
||||||
|
|
||||||
extern struct internalvar *create_internalvar (const char *name);
|
extern struct internalvar *create_internalvar (const char *name);
|
||||||
|
|
||||||
extern VEC (char_ptr) *complete_internalvar (const char *name);
|
extern void complete_internalvar (completion_tracker &tracker,
|
||||||
|
const char *name);
|
||||||
|
|
||||||
/* An internalvar can be dynamically computed by supplying a vector of
|
/* An internalvar can be dynamically computed by supplying a vector of
|
||||||
function pointers to perform various operations. */
|
function pointers to perform various operations. */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue