+/* 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);
+
+ /* Remove completion matching NAME from the completion list, does nothing
+ if NAME is not already in the completion list. */
+ void remove_completion (const char *name);
+
+ /* 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 (int 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 htab_elements (m_entries_hash) > 0; }
+
+ /* 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:
+
+ /* The type that we place into the m_entries_hash hash table. */
+ class completion_hash_entry;
+
+ /* 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);
+
+ /* Ensure that the lowest common denominator held in the member variable
+ M_LOWEST_COMMON_DENOMINATOR is valid. This method must be called if
+ there is any chance that new completions have been added to the
+ tracker before the lowest common denominator is read. */
+ void recompute_lowest_common_denominator ();
+
+ /* Callback used from recompute_lowest_common_denominator, called for
+ every entry in m_entries_hash. */
+ void recompute_lcd_visitor (completion_hash_entry *entry);
+
+ /* 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 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 = NULL;
+
+ /* 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;
+
+ /* True if the value in M_LOWEST_COMMON_DENOMINATOR is correct. This is
+ set to true each time RECOMPUTE_LOWEST_COMMON_DENOMINATOR is called,
+ and reset to false whenever a new completion is added. */
+ bool m_lowest_common_denominator_valid = false;
+
+ /* To avoid calls to xrealloc in RECOMPUTE_LOWEST_COMMON_DENOMINATOR, we
+ track the maximum possible size of the lowest common denominator,
+ which we know as each completion is added. */
+ size_t m_lowest_common_denominator_max_length = 0;
+};