aboutsummaryrefslogtreecommitdiff
path: root/gdb/symtab.c
diff options
context:
space:
mode:
authorGary Benson <gbenson@redhat.com>2015-01-31 15:07:22 -0800
committerDoug Evans <xdje42@gmail.com>2015-01-31 15:07:22 -0800
commitef0b411a110cd2602cb89c3fb237baf8beb28545 (patch)
treef689bb2c56c0d75b884ee535c8137ed9ebe7d561 /gdb/symtab.c
parente11c72c7e4879894b9711b5c0b8247c20c6050f6 (diff)
downloadgdb-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.c74
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) *