X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gdb%2Fcompleter.c;h=d3900ae201443ab0a5510816e9c5589ef36b9f5b;hb=e05523bd2411bac0277da73556f4d01f6c7448aa;hp=bc0501abf0a79f8b96a5f7faef782ff67af16f8e;hpb=eca1f90cf47a2edc1a1cd22e12c6c0f3b900654e;p=binutils-gdb.git diff --git a/gdb/completer.c b/gdb/completer.c index bc0501abf0a..d3900ae2014 100644 --- a/gdb/completer.c +++ b/gdb/completer.c @@ -1,5 +1,5 @@ /* Line completion stuff for GDB, the GNU debugger. - Copyright (C) 2000-2020 Free Software Foundation, Inc. + Copyright (C) 2000-2022 Free Software Foundation, Inc. This file is part of GDB. @@ -31,7 +31,6 @@ #include #include "linespec.h" #include "cli/cli-decode.h" -#include "cli/cli-style.h" /* FIXME: This is needed because of lookup_cmd_1 (). We should be calling a hook instead so we eliminate the CLI dependency. */ @@ -89,14 +88,6 @@ public: return htab_hash_string (m_name.get ()); } - /* A static function that can be passed to the htab hash system to be - used as a callback that deletes an item from the hash. */ - static void deleter (void *arg) - { - completion_hash_entry *entry = (completion_hash_entry *) arg; - delete entry; - } - private: /* The symbol name stored in this hash entry. */ @@ -156,7 +147,7 @@ enum explicit_location_match_type but it does affect how much stuff M-? lists. (2) If one of the matches contains a word break character, readline will quote it. That's why we switch between - current_language->la_word_break_characters() and + current_language->word_break_characters () and gdb_completer_command_word_break_characters. I'm not sure when we need this behavior (perhaps for funky characters in C++ symbols?). */ @@ -229,7 +220,7 @@ filename_completer (struct cmd_list_element *ignore, will loop indefinitely. */ subsequent_name = 1; /* Like emacs, don't complete on old versions. Especially - useful in the "source" command. */ + useful in the "source" command. */ const char *p = p_rl.get (); if (p[strlen (p) - 1] == '~') continue; @@ -259,14 +250,6 @@ filename_completer_handle_brkchars (struct cmd_list_element *ignore, (gdb_completer_file_name_break_characters); } -/* Possible values for the found_quote flags word used by the completion - functions. It says what kind of (shell-like) quoting we found anywhere - in the line. */ -#define RL_QF_SINGLE_QUOTE 0x01 -#define RL_QF_DOUBLE_QUOTE 0x02 -#define RL_QF_BACKSLASH 0x04 -#define RL_QF_OTHER_QUOTE 0x08 - /* Find the bounds of the current word for completion purposes, and return a pointer to the end of the word. This mimics (and is a modified version of) readline's _rl_find_completion_word internal @@ -293,7 +276,7 @@ gdb_rl_find_completion_word (struct gdb_rl_completion_word_info *info, int *qc, int *dp, const char *line_buffer) { - int scan, end, found_quote, delimiter, pass_next, isbrk; + int scan, end, delimiter, pass_next, isbrk; char quote_char; const char *brkchars; int point = strlen (line_buffer); @@ -310,7 +293,7 @@ gdb_rl_find_completion_word (struct gdb_rl_completion_word_info *info, } end = point; - found_quote = delimiter = 0; + delimiter = 0; quote_char = '\0'; brkchars = info->word_break_characters; @@ -320,8 +303,6 @@ gdb_rl_find_completion_word (struct gdb_rl_completion_word_info *info, /* We have a list of characters which can be used in pairs to quote substrings for the completer. Try to find the start of an unclosed quoted substring. */ - /* FOUND_QUOTE is set so we know what kind of quotes we - found. */ for (scan = pass_next = 0; scan < end; scan++) @@ -339,7 +320,6 @@ gdb_rl_find_completion_word (struct gdb_rl_completion_word_info *info, if (quote_char != '\'' && line_buffer[scan] == '\\') { pass_next = 1; - found_quote |= RL_QF_BACKSLASH; continue; } @@ -360,13 +340,6 @@ gdb_rl_find_completion_word (struct gdb_rl_completion_word_info *info, /* Found start of a quoted substring. */ quote_char = line_buffer[scan]; point = scan + 1; - /* Shell-like quoting conventions. */ - if (quote_char == '\'') - found_quote |= RL_QF_SINGLE_QUOTE; - else if (quote_char == '"') - found_quote |= RL_QF_DOUBLE_QUOTE; - else - found_quote |= RL_QF_OTHER_QUOTE; } } } @@ -449,7 +422,7 @@ const char * advance_to_expression_complete_word_point (completion_tracker &tracker, const char *text) { - const char *brk_chars = current_language->la_word_break_characters (); + const char *brk_chars = current_language->word_break_characters (); return advance_to_completion_word (tracker, brk_chars, text); } @@ -574,7 +547,7 @@ complete_files_symbols (completion_tracker &tracker, colon = p; symbol_start = p + 1; } - else if (strchr (current_language->la_word_break_characters(), *p)) + else if (strchr (current_language->word_break_characters (), *p)) symbol_start = p + 1; } @@ -893,7 +866,11 @@ complete_explicit_location (completion_tracker &tracker, int keyword = skip_keyword (tracker, explicit_options, &text); if (keyword == -1) - complete_on_enum (tracker, explicit_options, text, text); + { + complete_on_enum (tracker, explicit_options, text, text); + /* There are keywords that start with "-". Include them, too. */ + complete_on_enum (tracker, linespec_keywords, text, text); + } else { /* Completing on value. */ @@ -1096,18 +1073,18 @@ add_struct_fields (struct type *type, completion_list &output, if (i < TYPE_N_BASECLASSES (type)) add_struct_fields (TYPE_BASECLASS (type, i), output, fieldname, namelen); - else if (TYPE_FIELD_NAME (type, i)) + else if (type->field (i).name ()) { - if (TYPE_FIELD_NAME (type, i)[0] != '\0') + if (type->field (i).name ()[0] != '\0') { - if (! strncmp (TYPE_FIELD_NAME (type, i), + if (! strncmp (type->field (i).name (), fieldname, namelen)) - output.emplace_back (xstrdup (TYPE_FIELD_NAME (type, i))); + output.emplace_back (xstrdup (type->field (i).name ())); } - else if (TYPE_FIELD_TYPE (type, i)->code () == TYPE_CODE_UNION) + else if (type->field (i).type ()->code () == TYPE_CODE_UNION) { /* Recurse into anonymous unions. */ - add_struct_fields (TYPE_FIELD_TYPE (type, i), + add_struct_fields (type->field (i).type (), output, fieldname, namelen); } } @@ -1157,7 +1134,7 @@ complete_expression (completion_tracker &tracker, for (;;) { type = check_typedef (type); - if (type->code () != TYPE_CODE_PTR && !TYPE_IS_REFERENCE (type)) + if (!type->is_pointer_or_reference ()) break; type = TYPE_TARGET_TYPE (type); } @@ -1349,7 +1326,7 @@ complete_line_internal_1 (completion_tracker &tracker, strings, which leaves out the '-' and '.' character used in some commands. */ set_rl_completer_word_break_characters - (current_language->la_word_break_characters()); + (current_language->word_break_characters ()); /* Decide whether to complete on a list of gdb commands or on symbols. */ @@ -1385,9 +1362,8 @@ complete_line_internal_1 (completion_tracker &tracker, result_list = 0; } else - { - c = lookup_cmd_1 (&p, cmdlist, &result_list, ignore_help_classes); - } + c = lookup_cmd_1 (&p, cmdlist, &result_list, NULL, ignore_help_classes, + true); /* Move p up to the next interesting thing. */ while (*p == ' ' || *p == '\t') @@ -1426,7 +1402,7 @@ complete_line_internal_1 (completion_tracker &tracker, if (result_list) { if (reason != handle_brkchars) - complete_on_cmdlist (*result_list->prefixlist, tracker, p, + complete_on_cmdlist (*result_list->subcommands, tracker, p, word, ignore_help_classes); } else @@ -1454,12 +1430,12 @@ complete_line_internal_1 (completion_tracker &tracker, { /* The command is followed by whitespace; we need to complete on whatever comes after command. */ - if (c->prefixlist) + if (c->is_prefix ()) { /* It is a prefix command; what comes after it is a subcommand (e.g. "info "). */ if (reason != handle_brkchars) - complete_on_cmdlist (*c->prefixlist, tracker, p, word, + complete_on_cmdlist (*c->subcommands, tracker, p, word, ignore_help_classes); /* Ensure that readline does the right thing @@ -1522,7 +1498,7 @@ complete_line_internal_1 (completion_tracker &tracker, { /* There is non-whitespace beyond the command. */ - if (c->prefixlist && !c->allow_unknown) + if (c->is_prefix () && !c->allow_unknown) { /* It is an unrecognized subcommand of a prefix command, e.g. "info adsfkdj". */ @@ -1588,13 +1564,10 @@ completion_tracker::discard_completions () m_lowest_common_denominator_unique = false; m_lowest_common_denominator_valid = false; - /* A null check here allows this function to be used from the - constructor. */ - if (m_entries_hash != NULL) - htab_delete (m_entries_hash); + m_entries_hash.reset (nullptr); /* A callback used by the hash table to compare new entries with existing - entries. We can't use the standard streq_hash function here as the + entries. We can't use the standard htab_eq_string function here as the key to our hash is just a single string, while the values we store in the hash are a struct containing multiple strings. */ static auto entry_eq_func @@ -1619,10 +1592,11 @@ completion_tracker::discard_completions () return entry->hash_name (); }; - m_entries_hash = htab_create_alloc (INITIAL_COMPLETION_HTAB_SIZE, - entry_hash_func, entry_eq_func, - completion_hash_entry::deleter, - xcalloc, xfree); + m_entries_hash.reset + (htab_create_alloc (INITIAL_COMPLETION_HTAB_SIZE, + entry_hash_func, entry_eq_func, + htab_delete_entry, + xcalloc, xfree)); } /* See completer.h. */ @@ -1630,7 +1604,6 @@ completion_tracker::discard_completions () completion_tracker::~completion_tracker () { xfree (m_lowest_common_denominator); - htab_delete (m_entries_hash); } /* See completer.h. */ @@ -1646,11 +1619,12 @@ completion_tracker::maybe_add_completion if (max_completions == 0) return false; - if (htab_elements (m_entries_hash) >= max_completions) + if (htab_elements (m_entries_hash.get ()) >= max_completions) return false; hashval_t hash = htab_hash_string (name.get ()); - slot = htab_find_slot_with_hash (m_entries_hash, name.get (), hash, INSERT); + slot = htab_find_slot_with_hash (m_entries_hash.get (), name.get (), + hash, INSERT); if (*slot == HTAB_EMPTY_ENTRY) { const char *match_for_lcd_str = NULL; @@ -1701,10 +1675,10 @@ void completion_tracker::remove_completion (const char *name) { hashval_t hash = htab_hash_string (name); - if (htab_find_slot_with_hash (m_entries_hash, name, hash, NO_INSERT) + if (htab_find_slot_with_hash (m_entries_hash.get (), name, hash, NO_INSERT) != NULL) { - htab_remove_elt_with_hash (m_entries_hash, name, hash); + htab_remove_elt_with_hash (m_entries_hash.get (), name, hash); m_lowest_common_denominator_valid = false; } } @@ -1965,7 +1939,7 @@ default_completer_handle_brkchars (struct cmd_list_element *ignore, const char *text, const char *word) { set_rl_completer_word_break_characters - (current_language->la_word_break_characters ()); + (current_language->word_break_characters ()); } /* See definition in completer.h. */ @@ -2145,7 +2119,7 @@ completion_tracker::recompute_lowest_common_denominator () return 1; }; - htab_traverse (m_entries_hash, visitor_func, this); + htab_traverse (m_entries_hash.get (), visitor_func, this); m_lowest_common_denominator_valid = true; } @@ -2228,7 +2202,7 @@ completion_result completion_tracker::build_completion_result (const char *text, int start, int end) { - size_t element_count = htab_elements (m_entries_hash); + size_t element_count = htab_elements (m_entries_hash.get ()); if (element_count == 0) return {}; @@ -2257,9 +2231,11 @@ completion_tracker::build_completion_result (const char *text, /* If the tracker wants to, or we already have a space at the end of the match, tell readline to skip appending another. */ + char *match = match_list[0]; bool completion_suppress_append = (suppress_append_ws () - || match_list[0][strlen (match_list[0]) - 1] == ' '); + || (match[0] != '\0' + && match[strlen (match) - 1] == ' ')); return completion_result (match_list, 1, completion_suppress_append); } @@ -2295,7 +2271,7 @@ completion_tracker::build_completion_result (const char *text, }; /* Build the completion list and add a null at the end. */ - htab_traverse_noresize (m_entries_hash, func, &builder); + htab_traverse_noresize (m_entries_hash.get (), func, &builder); match_list[builder.index] = NULL; return completion_result (match_list, builder.index - 1, false); @@ -2474,7 +2450,7 @@ skip_quoted_chars (const char *str, const char *quotechars, quotechars = gdb_completer_quote_characters; if (breakchars == NULL) - breakchars = current_language->la_word_break_characters(); + breakchars = current_language->word_break_characters (); for (scan = str; *scan != '\0'; scan++) { @@ -2654,8 +2630,8 @@ gdb_printable_part (char *pathname) else if (temp[1] == '\0') { for (x = temp - 1; x > pathname; x--) - if (*x == '/') - break; + if (*x == '/') + break; return ((*x == '/') ? x + 1 : pathname); } else @@ -2715,8 +2691,6 @@ gdb_fnwidth (const char *string) return width; } -extern int _rl_completion_prefix_display_length; - /* Print TO_PRINT, one matching completion. PREFIX_BYTES is number of common prefix bytes. Based on readline/complete.c:fnprint. */ @@ -2725,7 +2699,7 @@ static int gdb_fnprint (const char *to_print, int prefix_bytes, const struct match_list_displayer *displayer) { - int common_prefix_len, printed_len, w; + int printed_len, w; const char *s; #if defined (HANDLE_MULTIBYTE) mbstate_t ps; @@ -2738,18 +2712,14 @@ gdb_fnprint (const char *to_print, int prefix_bytes, memset (&ps, 0, sizeof (mbstate_t)); #endif - printed_len = common_prefix_len = 0; + printed_len = 0; /* Don't print only the ellipsis if the common prefix is one of the possible completions */ if (to_print[prefix_bytes] == '\0') prefix_bytes = 0; - ui_file_style style = completion_prefix_style.style (); - if (!style.is_default ()) - displayer->puts (displayer, style.to_ansi ().c_str ()); - - if (prefix_bytes && _rl_completion_prefix_display_length > 0) + if (prefix_bytes) { char ellipsis; @@ -2758,30 +2728,20 @@ gdb_fnprint (const char *to_print, int prefix_bytes, displayer->putch (displayer, ellipsis); printed_len = ELLIPSIS_LEN; } - else if (prefix_bytes && !style.is_default ()) - { - common_prefix_len = prefix_bytes; - prefix_bytes = 0; - } - - /* There are 3 states: the initial state (#0), when we use the - prefix style; the difference state (#1), which lasts a single - character; and then the suffix state (#2). */ - int state = 0; s = to_print + prefix_bytes; while (*s) { if (CTRL_CHAR (*s)) - { - displayer->putch (displayer, '^'); - displayer->putch (displayer, UNCTRL (*s)); - printed_len += 2; - s++; + { + displayer->putch (displayer, '^'); + displayer->putch (displayer, UNCTRL (*s)); + printed_len += 2; + s++; #if defined (HANDLE_MULTIBYTE) memset (&ps, 0, sizeof (mbstate_t)); #endif - } + } else if (*s == RUBOUT) { displayer->putch (displayer, '^'); @@ -2819,31 +2779,8 @@ gdb_fnprint (const char *to_print, int prefix_bytes, printed_len++; #endif } - if (common_prefix_len > 0 && (s - to_print) >= common_prefix_len) - { - if (!style.is_default ()) - displayer->puts (displayer, ui_file_style ().to_ansi ().c_str ()); - - ++state; - if (state == 1) - { - common_prefix_len = 1; - style = completion_difference_style.style (); - } - else - { - common_prefix_len = 0; - style = completion_suffix_style.style (); - } - - if (!style.is_default ()) - displayer->puts (displayer, style.to_ansi ().c_str ()); - } } - if (!style.is_default ()) - displayer->puts (displayer, ui_file_style ().to_ansi ().c_str ()); - return printed_len; } @@ -2952,6 +2889,7 @@ gdb_complete_get_screenwidth (const struct match_list_displayer *displayer) return displayer->width; } +extern int _rl_completion_prefix_display_length; extern int _rl_print_completions_horizontally; EXTERN_C int _rl_qsort_string_compare (const void *, const void *); @@ -2970,23 +2908,19 @@ gdb_display_match_list_1 (char **matches, int len, int max, char *temp, *t; int page_completions = displayer->height != INT_MAX && pagination_enabled; - bool want_style = !completion_prefix_style.style ().is_default (); - /* Find the length of the prefix common to all items: length as displayed characters (common_length) and as a byte index into the matches (sind) */ common_length = sind = 0; - if (_rl_completion_prefix_display_length > 0 || want_style) + if (_rl_completion_prefix_display_length > 0) { t = gdb_printable_part (matches[0]); temp = strrchr (t, '/'); common_length = temp ? gdb_fnwidth (temp) : gdb_fnwidth (t); sind = temp ? strlen (temp) : strlen (t); - if (_rl_completion_prefix_display_length > 0 - && common_length > _rl_completion_prefix_display_length - && common_length > ELLIPSIS_LEN) + if (common_length > _rl_completion_prefix_display_length && common_length > ELLIPSIS_LEN) max -= common_length - ELLIPSIS_LEN; - else if (!want_style || common_length > max || sind > max) + else common_length = sind = 0; }