diff options
author | Gary Benson <gbenson@redhat.com> | 2015-01-31 15:07:22 -0800 |
---|---|---|
committer | Doug Evans <xdje42@gmail.com> | 2015-01-31 15:07:22 -0800 |
commit | ef0b411a110cd2602cb89c3fb237baf8beb28545 (patch) | |
tree | f689bb2c56c0d75b884ee535c8137ed9ebe7d561 /gdb/symtab.c | |
parent | e11c72c7e4879894b9711b5c0b8247c20c6050f6 (diff) | |
download | gdb-ef0b411a110cd2602cb89c3fb237baf8beb28545.zip gdb-ef0b411a110cd2602cb89c3fb237baf8beb28545.tar.gz gdb-ef0b411a110cd2602cb89c3fb237baf8beb28545.tar.bz2 |
Add max-completions parameter, and implement tab-completion limiting.
This commit adds a new exception, MAX_COMPLETIONS_REACHED_ERROR, to be
thrown whenever the completer has generated too many candidates to
be useful. A new user-settable variable, "max_completions", is added
to control this behaviour. A top-level completion limit is added to
complete_line_internal, as the final check to ensure the user never
sees too many completions. An additional limit is added to
default_make_symbol_completion_list_break_on, to halt time-consuming
symbol table expansions.
gdb/ChangeLog:
PR cli/9007
PR cli/11920
PR cli/15548
* cli/cli-cmds.c (complete_command): Notify user if max-completions
reached.
* common/common-exceptions.h (enum errors)
<MAX_COMPLETIONS_REACHED_ERROR>: New value.
* completer.h (get_max_completions_reached_message): New declaration.
(max_completions): Likewise.
(completion_tracker_t): New typedef.
(new_completion_tracker): New declaration.
(make_cleanup_free_completion_tracker): Likewise.
(maybe_add_completion_enum): New enum.
(maybe_add_completion): New declaration.
(throw_max_completions_reached_error): Likewise.
* completer.c (max_completions): New global variable.
(new_completion_tracker): New function.
(free_completion_tracker): Likewise.
(make_cleanup_free_completion_tracker): Likewise.
(maybe_add_completions): Likewise.
(throw_max_completions_reached_error): Likewise.
(complete_line): Remove duplicates and limit result to max_completions
entries.
(get_max_completions_reached_message): New function.
(gdb_display_match_list): Handle max_completions.
(_initialize_completer): New declaration and function.
* symtab.c: Include completer.h.
(completion_tracker): New static variable.
(completion_list_add_name): Call maybe_add_completion.
(default_make_symbol_completion_list_break_on_1): Renamed from
default_make_symbol_completion_list_break_on. Maintain
completion_tracker across calls to completion_list_add_name.
(default_make_symbol_completion_list_break_on): New function.
* top.c (init_main): Set rl_completion_display_matches_hook.
* tui/tui-io.c: Include completer.h.
(tui_old_rl_display_matches_hook): New static global.
(tui_rl_display_match_list): Notify user if max-completions reached.
(tui_setup_io): Save/restore rl_completion_display_matches_hook.
* NEWS (New Options): Mention set/show max-completions.
gdb/doc/ChangeLog:
* gdb.texinfo (Command Completion): Document new
"set/show max-completions" option.
gdb/testsuite/ChangeLog:
* gdb.base/completion.exp: Disable completion limiting for
existing tests. Add new tests to check completion limiting.
* gdb.linespec/ls-errs.exp: Disable completion limiting.
Diffstat (limited to 'gdb/symtab.c')
-rw-r--r-- | gdb/symtab.c | 74 |
1 files changed, 63 insertions, 11 deletions
diff --git a/gdb/symtab.c b/gdb/symtab.c index abff265..84e2680 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -60,6 +60,7 @@ #include "macroscope.h" #include "parser-defs.h" +#include "completer.h" /* Forward declarations for local functions. */ @@ -5001,6 +5002,15 @@ static VEC (char_ptr) *return_val; completion_list_add_name \ (MSYMBOL_NATURAL_NAME (symbol), (sym_text), (len), (text), (word)) +/* 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 demangled for C++ symbols) matches SYM_TEXT in the first SYM_TEXT_LEN characters. If so, add it to the current completion list. */ @@ -5019,6 +5029,7 @@ completion_list_add_name (const char *symname, { char *new; + enum maybe_add_completion_enum add_status; if (word == sym_text) { @@ -5040,7 +5051,22 @@ completion_list_add_name (const char *symname, strcat (new, symname); } - VEC_safe_push (char_ptr, return_val, new); + add_status = maybe_add_completion (completion_tracker, new); + + switch (add_status) + { + case MAYBE_ADD_COMPLETION_OK: + VEC_safe_push (char_ptr, return_val, new); + break; + case MAYBE_ADD_COMPLETION_OK_MAX_REACHED: + VEC_safe_push (char_ptr, return_val, new); + throw_max_completions_reached_error (); + case MAYBE_ADD_COMPLETION_MAX_REACHED: + throw_max_completions_reached_error (); + case MAYBE_ADD_COMPLETION_DUPLICATE: + xfree (new); + break; + } } } @@ -5253,11 +5279,11 @@ symtab_expansion_callback (struct compunit_symtab *symtab, datum->code); } -VEC (char_ptr) * -default_make_symbol_completion_list_break_on (const char *text, - const char *word, - const char *break_on, - enum type_code code) +static void +default_make_symbol_completion_list_break_on_1 (const char *text, + const char *word, + const char *break_on, + enum type_code code) { /* Problem: All of the symbols have to be copied because readline frees them. I'm not going to worry about this; hopefully there @@ -5275,7 +5301,7 @@ default_make_symbol_completion_list_break_on (const char *text, /* Length of sym_text. */ int sym_text_len; struct add_name_data datum; - struct cleanup *back_to; + struct cleanup *cleanups; /* Now look for the symbol we are supposed to complete on. */ { @@ -5310,7 +5336,7 @@ default_make_symbol_completion_list_break_on (const char *text, /* A double-quoted string is never a symbol, nor does it make sense to complete it any other way. */ { - return NULL; + return; } else { @@ -5346,8 +5372,8 @@ default_make_symbol_completion_list_break_on (const char *text, } gdb_assert (sym_text[sym_text_len] == '\0' || sym_text[sym_text_len] == '('); - return_val = NULL; - back_to = make_cleanup (do_free_completion_list, &return_val); + completion_tracker = new_completion_tracker (); + cleanups = make_cleanup_free_completion_tracker (&completion_tracker); datum.sym_text = sym_text; datum.sym_text_len = sym_text_len; @@ -5461,8 +5487,34 @@ default_make_symbol_completion_list_break_on (const char *text, macro_for_each (macro_user_macros, add_macro_name, &datum); } + do_cleanups (cleanups); +} + +VEC (char_ptr) * +default_make_symbol_completion_list_break_on (const char *text, + const char *word, + const char *break_on, + enum type_code code) +{ + struct cleanup *back_to; + volatile struct gdb_exception except; + + return_val = NULL; + back_to = make_cleanup (do_free_completion_list, &return_val); + + TRY_CATCH (except, RETURN_MASK_ERROR) + { + default_make_symbol_completion_list_break_on_1 (text, word, + break_on, code); + } + if (except.reason < 0) + { + if (except.error != MAX_COMPLETIONS_REACHED_ERROR) + throw_exception (except); + } + discard_cleanups (back_to); - return (return_val); + return return_val; } VEC (char_ptr) * |