/* Header for GDB line completion.
- Copyright (C) 2000-2017 Free Software Foundation, Inc.
+ Copyright (C) 2000-2019 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#if !defined (COMPLETER_H)
#define COMPLETER_H 1
-#include "gdb_vecs.h"
+#include "common/gdb_vecs.h"
#include "command.h"
/* Types of functions in struct match_list_displayer. */
mld_read_key_ftype *read_key;
};
-extern void gdb_display_match_list (char **matches, int len, int max,
- const struct match_list_displayer *);
+/* 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;
-extern const char *get_max_completions_reached_message (void);
+/* The result of a successful completion match. When doing symbol
+ comparison, we use the symbol search name for the symbol name match
+ check, but the matched name that is shown to the user may be
+ different. For example, Ada uses encoded names for lookup, but
+ then wants to decode the symbol name to show to the user, and also
+ in some cases wrap the matched name in "<sym>" (meaning we can't
+ always use the symbol's print name). */
-extern VEC (char_ptr) *complete_line (const char *text,
- const char *line_buffer,
- int point);
+class completion_match
+{
+public:
+ /* Get the completion match result. See m_match/m_storage's
+ descriptions. */
+ const char *match ()
+ { return m_match; }
+
+ /* Set the completion match result. See m_match/m_storage's
+ descriptions. */
+ void set_match (const char *match)
+ { m_match = match; }
+
+ /* Get temporary storage for generating a match result, dynamically.
+ The built string is only good until the next clear() call. I.e.,
+ good until the next symbol comparison. */
+ std::string &storage ()
+ { return m_storage; }
+
+ /* Prepare for another completion matching sequence. */
+ void clear ()
+ {
+ m_match = NULL;
+ m_storage.clear ();
+ }
+
+private:
+ /* The completion match result. This can either be a pointer into
+ M_STORAGE string, or it can be a pointer into the some other
+ string that outlives the completion matching sequence (usually, a
+ pointer to a symbol's name). */
+ const char *m_match;
+
+ /* Storage a symbol comparison routine can use for generating a
+ match result, dynamically. The built string is only good until
+ the next clear() call. I.e., good until the next symbol
+ comparison. */
+ std::string m_storage;
+};
-extern char *readline_line_completion_function (const char *text,
- int matches);
+/* The result of a successful completion match, but for least common
+ denominator (LCD) computation. Some completers provide matches
+ that don't start with the completion "word". E.g., completing on
+ "b push_ba" on a C++ program usually completes to
+ std::vector<...>::push_back, std::string::push_back etc. In such
+ case, the symbol comparison routine will set the LCD match to point
+ into the "push_back" substring within the symbol's name string.
+ Also, in some cases, the symbol comparison routine will want to
+ ignore parts of the symbol name for LCD purposes, such as for
+ example symbols with abi tags in C++. In such cases, the symbol
+ comparison routine will set MARK_IGNORED_RANGE to mark the ignored
+ substrings of the matched string. The resulting LCD string with
+ the ignored parts stripped out is computed at the end of a
+ completion match sequence iff we had a positive match. */
+
+class completion_match_for_lcd
+{
+public:
+ /* Get the resulting LCD, after a successful match. */
+ const char *match ()
+ { return m_match; }
+
+ /* Set the match for LCD. See m_match's description. */
+ void set_match (const char *match)
+ { m_match = match; }
+
+ /* Mark the range between [BEGIN, END) as ignored. */
+ void mark_ignored_range (const char *begin, const char *end)
+ { m_ignored_ranges.emplace_back (begin, end); }
+
+ /* Get the resulting LCD, after a successful match. If there are
+ ignored ranges, then this builds a new string with the ignored
+ parts removed (and stores it internally). As such, the result of
+ this call is only good for the current completion match
+ sequence. */
+ const char *finish ()
+ {
+ if (m_ignored_ranges.empty ())
+ return m_match;
+ else
+ {
+ m_finished_storage.clear ();
+
+ const char *prev = m_match;
+ for (const auto &range : m_ignored_ranges)
+ {
+ m_finished_storage.append (prev, range.first);
+ prev = range.second;
+ }
+ m_finished_storage.append (prev);
+
+ return m_finished_storage.c_str ();
+ }
+ }
+
+ /* Prepare for another completion matching sequence. */
+ void clear ()
+ {
+ m_match = NULL;
+ m_ignored_ranges.clear ();
+ }
+
+private:
+ /* The completion match result for LCD. This is usually either a
+ pointer into to a substring within a symbol's name, or to the
+ storage of the pairing completion_match object. */
+ const char *m_match;
+
+ /* The ignored substring ranges within M_MATCH. E.g., if we were
+ looking for completion matches for C++ functions starting with
+ "functio"
+ and successfully match:
+ "function[abi:cxx11](int)"
+ the ignored ranges vector will contain an entry that delimits the
+ "[abi:cxx11]" substring, such that calling finish() results in:
+ "function(int)"
+ */
+ std::vector<std::pair<const char *, const char *>> m_ignored_ranges;
+
+ /* Storage used by the finish() method, if it has to compute a new
+ string. */
+ std::string m_finished_storage;
+};
-extern VEC (char_ptr) *noop_completer (struct cmd_list_element *,
- const char *, const char *);
+/* Convenience aggregate holding info returned by the symbol name
+ matching routines (see symbol_name_matcher_ftype). */
+struct completion_match_result
+{
+ /* The completion match candidate. */
+ completion_match match;
+
+ /* The completion match, for LCD computation purposes. */
+ completion_match_for_lcd match_for_lcd;
+
+ /* Convenience that sets both MATCH and MATCH_FOR_LCD. M_FOR_LCD is
+ optional. If not specified, defaults to M. */
+ void set_match (const char *m, const char *m_for_lcd = NULL)
+ {
+ match.set_match (m);
+ if (m_for_lcd == NULL)
+ match_for_lcd.set_match (m);
+ else
+ match_for_lcd.set_match (m_for_lcd);
+ }
+};
-extern VEC (char_ptr) *filename_completer (struct cmd_list_element *,
- const char *, const char *);
+/* 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. */
-extern VEC (char_ptr) *expression_completer (struct cmd_list_element *,
- const char *, const char *);
+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_COPY_AND_ASSIGN (completion_result);
+
+ /* 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;
+};
-extern VEC (char_ptr) *location_completer (struct cmd_list_element *,
- const char *, const char *);
+/* 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.
+
+ - The completer's idea of least common denominator (aka the common
+ prefix) between all completion matches to hand over to readline.
+ Some completers provide matches that don't start with the
+ completion "word". E.g., completing on "b push_ba" on a C++
+ program usually completes to std::vector<...>::push_back,
+ std::string::push_back etc. If all matches happen to start with
+ "std::", then readline would figure out that the lowest common
+ denominator is "std::", and thus would do a partial completion
+ with that. I.e., it would replace "push_ba" in the input buffer
+ with "std::", losing the original "push_ba", which is obviously
+ undesirable. To avoid that, such completers pass the substring
+ of the match that matters for common denominator computation as
+ MATCH_FOR_LCD argument to add_completion. The end result is
+ passed to readline in gdb_rl_attempted_completion_function.
+
+ - The custom word point to hand over to readline, for completers
+ that parse the input string in order to dynamically adjust
+ themselves depending on exactly what they're completing. E.g.,
+ the linespec completer needs to bypass readline's too-simple word
+ breaking algorithm.
+*/
+class completion_tracker
+{
+public:
+ completion_tracker ();
+ ~completion_tracker ();
+
+ DISABLE_COPY_AND_ASSIGN (completion_tracker);
+
+ /* 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,
+ completion_match_for_lcd *match_for_lcd = NULL,
+ const char *text = NULL, const char *word = NULL);
+
+ /* Add all completions matches in LIST. Elements are moved out of
+ LIST. */
+ void add_completions (completion_list &&list);
+
+ /* Set the quote char to be appended after a unique completion is
+ added to the input line. Set to '\0' to clear. See
+ m_quote_char's description. */
+ void set_quote_char (int quote_char)
+ { m_quote_char = quote_char; }
+
+ /* The quote char to be appended after a unique completion is added
+ to the input line. Returns '\0' if no quote char has been set.
+ See m_quote_char's description. */
+ int quote_char () { return m_quote_char; }
+
+ /* Tell the tracker that the current completer wants to provide a
+ custom word point instead of a list of a break chars, in the
+ handle_brkchars phase. Such completers must also compute their
+ completions then. */
+ void set_use_custom_word_point (bool enable)
+ { m_use_custom_word_point = enable; }
+
+ /* Whether the current completer computes a custom word point. */
+ bool use_custom_word_point () const
+ { return m_use_custom_word_point; }
+
+ /* The custom word point. */
+ int custom_word_point () const
+ { return m_custom_word_point; }
+
+ /* Set the custom word point to POINT. */
+ void set_custom_word_point (int point)
+ { m_custom_word_point = point; }
+
+ /* Advance the custom word point by LEN. */
+ void advance_custom_word_point_by (size_t len);
+
+ /* Whether to tell readline to skip appending a whitespace after the
+ completion. See m_suppress_append_ws. */
+ bool suppress_append_ws () const
+ { return m_suppress_append_ws; }
+
+ /* Set whether to tell readline to skip appending a whitespace after
+ the completion. See m_suppress_append_ws. */
+ void set_suppress_append_ws (bool suppress)
+ { m_suppress_append_ws = suppress; }
+
+ /* Return true if we only have one completion, and it matches
+ exactly the completion word. I.e., completing results in what we
+ already have. */
+ bool completes_to_completion_word (const char *word);
+
+ /* Get a reference to the shared (between all the multiple symbol
+ name comparison calls) completion_match_result object, ready for
+ another symbol name match sequence. */
+ completion_match_result &reset_completion_match_result ()
+ {
+ completion_match_result &res = m_completion_match_result;
+
+ /* Clear any previous match. */
+ res.match.clear ();
+ res.match_for_lcd.clear ();
+ return m_completion_match_result;
+ }
+
+ /* True if we have any completion match recorded. */
+ bool have_completions () const
+ { return !m_entries_vec.empty (); }
+
+ /* Discard the current completion match list and the current
+ LCD. */
+ void discard_completions ();
+
+ /* 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,
+ completion_match_for_lcd *match_for_lcd,
+ const char *text, const char *word);
+
+ /* Given a new match, recompute the lowest common denominator (LCD)
+ to hand over to readline. Normally readline computes this itself
+ based on the whole set of completion matches. However, some
+ completers want to override readline, in order to be able to
+ provide a LCD that is not really a prefix of the matches, but the
+ lowest common denominator of some relevant substring of each
+ match. E.g., "b push_ba" completes to
+ "std::vector<..>::push_back", "std::string::push_back", etc., and
+ in this case we want the lowest common denominator to be
+ "push_back" instead of "std::". */
+ void recompute_lowest_common_denominator
+ (gdb::unique_xmalloc_ptr<char> &&new_match);
+
+ /* Completion match outputs returned by the symbol name matching
+ routines (see symbol_name_matcher_ftype). These results are only
+ valid for a single match call. This is here in order to be able
+ to conveniently share the same storage among all the calls to the
+ symbol name matching routines. */
+ completion_match_result m_completion_match_result;
+
+ /* 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;
+
+ /* If non-zero, then this is the quote char that needs to be
+ appended after completion (iff we have a unique completion). We
+ don't rely on readline appending the quote char as delimiter as
+ then readline wouldn't append the ' ' after the completion.
+ I.e., we want this:
+
+ before tab: "b 'function("
+ after tab: "b 'function()' "
+ */
+ int m_quote_char = '\0';
+
+ /* If true, the completer has its own idea of "word" point, and
+ doesn't want to rely on readline computing it based on brkchars.
+ Set in the handle_brkchars phase. */
+ bool m_use_custom_word_point = false;
+
+ /* The completer's idea of where the "word" we were looking at is
+ relative to RL_LINE_BUFFER. This is advanced in the
+ handle_brkchars phase as the completer discovers potential
+ completable words. */
+ int m_custom_word_point = 0;
+
+ /* If true, tell readline to skip appending a whitespace after the
+ completion. Automatically set if we have a unique completion
+ that already has a space at the end. A completer may also
+ explicitly set this. E.g., the linespec completer sets this when
+ the completion ends with the ":" separator between filename and
+ function name. */
+ bool m_suppress_append_ws = false;
+
+ /* Our idea of lowest common denominator to hand over to readline.
+ See intro. */
+ char *m_lowest_common_denominator = NULL;
+
+ /* If true, the LCD is unique. I.e., all completions had the same
+ MATCH_FOR_LCD substring, even if the completions were different.
+ For example, if "break function<tab>" found "a::function()" and
+ "b::function()", the LCD will be "function()" in both cases and
+ so we want to tell readline to complete the line with
+ "function()", instead of showing all the possible
+ completions. */
+ bool m_lowest_common_denominator_unique = false;
+};
-extern VEC (char_ptr) *command_completer (struct cmd_list_element *,
- const char *, const char *);
+/* Return a string to hand off to readline as a completion match
+ candidate, potentially composed of parts of MATCH_NAME and of
+ TEXT/WORD. For a description of TEXT/WORD see completer_ftype. */
-extern VEC (char_ptr) *signal_completer (struct cmd_list_element *,
- const char *, const char *);
+extern gdb::unique_xmalloc_ptr<char>
+ make_completion_match_str (const char *match_name,
+ const char *text, const char *word);
-extern VEC (char_ptr) *reg_or_group_completer (struct cmd_list_element *,
- const char *, const char *);
+/* Like above, but takes ownership of MATCH_NAME (i.e., can
+ reuse/return it). */
-extern VEC (char_ptr) *reggroup_completer (struct cmd_list_element *,
- const char *, const char *);
+extern gdb::unique_xmalloc_ptr<char>
+ make_completion_match_str (gdb::unique_xmalloc_ptr<char> &&match_name,
+ const char *text, const char *word);
-extern char *get_gdb_completer_quote_characters (void);
+extern void gdb_display_match_list (char **matches, int len, int max,
+ const struct match_list_displayer *);
-extern char *gdb_completion_word_break_characters (void);
+extern const char *get_max_completions_reached_message (void);
-/* Set the word break characters array to the corresponding set of
- chars, based on FN. This function is useful for cases when the
- completer doesn't know the type of the completion until some
- calculation is done (e.g., for Python functions). */
+extern void complete_line (completion_tracker &tracker,
+ const char *text,
+ const char *line_buffer,
+ int point);
-extern void set_gdb_completion_word_break_characters (completer_ftype *fn);
+/* Find the bounds of the word in TEXT for completion purposes, and
+ return a pointer to the end of the word. Calls the completion
+ machinery for a handle_brkchars phase (using TRACKER) to figure out
+ the right work break characters for the command in TEXT.
+ QUOTE_CHAR, if non-null, is set to the opening quote character if
+ we found an unclosed quoted substring, '\0' otherwise. */
+extern const char *completion_find_completion_word (completion_tracker &tracker,
+ const char *text,
+ int *quote_char);
-/* Exported to linespec.c */
-extern const char *skip_quoted_chars (const char *, const char *,
- const char *);
+/* Assuming TEXT is an expression in the current language, find the
+ completion word point for TEXT, emulating the algorithm readline
+ uses to find the word point, using the current language's word
+ break characters. */
-extern const char *skip_quoted (const char *);
+const char *advance_to_expression_complete_word_point
+ (completion_tracker &tracker, const char *text);
-/* Maximum number of candidates to consider before the completer
- bails by throwing MAX_COMPLETIONS_REACHED_ERROR. Negative values
- disable limiting. */
+extern char **gdb_rl_attempted_completion_function (const char *text,
+ int start, int end);
-extern int max_completions;
+extern void noop_completer (struct cmd_list_element *,
+ completion_tracker &tracker,
+ const char *, const char *);
-/* Object to track how many unique completions have been generated.
- Used to limit the size of generated completion lists. */
+extern void filename_completer (struct cmd_list_element *,
+ completion_tracker &tracker,
+ const char *, const char *);
-typedef htab_t completion_tracker_t;
+extern void expression_completer (struct cmd_list_element *,
+ completion_tracker &tracker,
+ const char *, const char *);
-/* 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 void location_completer (struct cmd_list_element *,
+ completion_tracker &tracker,
+ const char *, const char *);
-extern completion_tracker_t new_completion_tracker (void);
+extern void symbol_completer (struct cmd_list_element *,
+ completion_tracker &tracker,
+ const char *, const char *);
-/* Make a cleanup to free a completion tracker, and reset its pointer
- to NULL. */
+extern void command_completer (struct cmd_list_element *,
+ completion_tracker &tracker,
+ const char *, const char *);
-extern struct cleanup *make_cleanup_free_completion_tracker
- (completion_tracker_t *tracker_ptr);
+extern void signal_completer (struct cmd_list_element *,
+ completion_tracker &tracker,
+ const char *, const char *);
-/* Return values for maybe_add_completion. */
+extern void reg_or_group_completer (struct cmd_list_element *,
+ completion_tracker &tracker,
+ const char *, const char *);
-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
-};
+extern void reggroup_completer (struct cmd_list_element *,
+ completion_tracker &tracker,
+ const char *, const char *);
+
+extern const char *get_gdb_completer_quote_characters (void);
+
+extern char *gdb_completion_word_break_characters (void);
+
+/* Set the word break characters array to BREAK_CHARS. This function
+ is useful as const-correct alternative to direct assignment to
+ rl_completer_word_break_characters, which is "char *",
+ not "const char *". */
+extern void set_rl_completer_word_break_characters (const char *break_chars);
+
+/* Get the matching completer_handle_brkchars_ftype function for FN.
+ FN is one of the core completer functions above (filename,
+ location, symbol, etc.). This function is useful for cases when
+ the completer doesn't know the type of the completion until some
+ calculation is done (e.g., for Python functions). */
-/* 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.
+extern completer_handle_brkchars_ftype *
+ completer_handle_brkchars_func_for_completer (completer_ftype *fn);
- 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. */
+/* Exported to linespec.c */
+
+/* Return a list of all source files whose names begin with matching
+ TEXT. */
+extern completion_list complete_source_filenames (const char *text);
+
+/* Complete on expressions. Often this means completing on symbol
+ names, but some language parsers also have support for completing
+ field names. */
+extern void complete_expression (completion_tracker &tracker,
+ const char *text, const char *word);
-extern enum maybe_add_completion_enum
- maybe_add_completion (completion_tracker_t tracker, char *name);
+extern const char *skip_quoted_chars (const char *, const char *,
+ const char *);
-/* Wrapper to throw MAX_COMPLETIONS_REACHED_ERROR. */
+extern const char *skip_quoted (const char *);
-extern void throw_max_completions_reached_error (void);
+/* Maximum number of candidates to consider before the completer
+ bails by throwing MAX_COMPLETIONS_REACHED_ERROR. Negative values
+ disable limiting. */
+
+extern int max_completions;
#endif /* defined (COMPLETER_H) */