#include "parser-defs.h"
#include "completer.h"
+#include "progspace-and-thread.h"
+#include "common/gdb_optional.h"
+#include "filename-seen-cache.h"
/* Forward declarations for local functions. */
Similarly, any Ada type declaration implicitly defines a typedef. */
if (symbol_language == language_cplus
|| symbol_language == language_d
- || symbol_language == language_ada)
+ || symbol_language == language_ada
+ || symbol_language == language_rust)
{
if ((domain == VAR_DOMAIN || domain == STRUCT_DOMAIN)
&& symbol_domain == STRUCT_DOMAIN)
}
/* Given SYMTAB, returns all the PCs function in the symtab that
- exactly match LINE. Returns NULL if there are no exact matches,
- but updates BEST_ITEM in this case. */
+ exactly match LINE. Returns an empty vector if there are no exact
+ matches, but updates BEST_ITEM in this case. */
-VEC (CORE_ADDR) *
+std::vector<CORE_ADDR>
find_pcs_for_symtab_line (struct symtab *symtab, int line,
struct linetable_entry **best_item)
{
int start = 0;
- VEC (CORE_ADDR) *result = NULL;
+ std::vector<CORE_ADDR> result;
/* First, collect all the PCs that are at this line. */
while (1)
break;
}
- VEC_safe_push (CORE_ADDR, result,
- SYMTAB_LINETABLE (symtab)->item[idx].pc);
+ result.push_back (SYMTAB_LINETABLE (symtab)->item[idx].pc);
start = idx + 1;
}
{
struct symbol *sym;
struct symtab_and_line start_sal;
- struct cleanup *old_chain;
CORE_ADDR pc, saved_pc;
struct obj_section *section;
const char *name;
if (sal->explicit_pc)
return;
- old_chain = save_current_space_and_thread ();
+ scoped_restore_current_pspace_and_thread restore_pspace_thread;
+
switch_to_program_space_and_thread (sal->pspace);
sym = find_pc_sect_function (sal->pc, sal->section);
= lookup_minimal_symbol_by_pc_section (sal->pc, sal->section);
if (msymbol.minsym == NULL)
- {
- do_cleanups (old_chain);
- return;
- }
+ return;
objfile = msymbol.objfile;
pc = BMSYMBOL_VALUE_ADDRESS (msymbol);
start_sal = find_pc_sect_line (pc, section, 0);
}
- do_cleanups (old_chain);
-
/* If we're already past the prologue, leave SAL unchanged. Otherwise
forward SAL to the end of the prologue. */
if (sal->pc >= pc)
}
\f
-/* Cache to watch for file names already seen by filename_seen. */
-
-struct filename_seen_cache
-{
- /* Table of files seen so far. */
- htab_t tab;
- /* Initial size of the table. It automagically grows from here. */
-#define INITIAL_FILENAME_SEEN_CACHE_SIZE 100
-};
-
-/* filename_seen_cache constructor. */
-
-static struct filename_seen_cache *
-create_filename_seen_cache (void)
-{
- struct filename_seen_cache *cache = XNEW (struct filename_seen_cache);
-
- cache->tab = htab_create_alloc (INITIAL_FILENAME_SEEN_CACHE_SIZE,
- filename_hash, filename_eq,
- NULL, xcalloc, xfree);
-
- return cache;
-}
-
-/* Empty the cache, but do not delete it. */
-
-static void
-clear_filename_seen_cache (struct filename_seen_cache *cache)
-{
- htab_empty (cache->tab);
-}
-
-/* filename_seen_cache destructor.
- This takes a void * argument as it is generally used as a cleanup. */
-
-static void
-delete_filename_seen_cache (void *ptr)
-{
- struct filename_seen_cache *cache = (struct filename_seen_cache *) ptr;
-
- htab_delete (cache->tab);
- xfree (cache);
-}
-
-/* If FILE is not already in the table of files in CACHE, return zero;
- otherwise return non-zero. Optionally add FILE to the table if ADD
- is non-zero.
-
- NOTE: We don't manage space for FILE, we assume FILE lives as long
- as the caller needs. */
-
-static int
-filename_seen (struct filename_seen_cache *cache, const char *file, int add)
-{
- void **slot;
-
- /* Is FILE in tab? */
- slot = htab_find_slot (cache->tab, file, add ? INSERT : NO_INSERT);
- if (*slot != NULL)
- return 1;
-
- /* No; maybe add it to tab. */
- if (add)
- *slot = (char *) file;
-
- return 0;
-}
-
/* Data structure to maintain printing state for output_source_filename. */
struct output_source_filename_data
symtabs; it doesn't hurt to check. */
/* Was NAME already seen? */
- if (filename_seen (data->filename_seen_cache, name, 1))
+ if (data->filename_seen_cache->seen (name))
{
/* Yes; don't print it again. */
return;
struct symtab *s;
struct objfile *objfile;
struct output_source_filename_data data;
- struct cleanup *cleanups;
if (!have_full_symbols () && !have_partial_symbols ())
{
error (_("No symbol table is loaded. Use the \"file\" command."));
}
- data.filename_seen_cache = create_filename_seen_cache ();
- cleanups = make_cleanup (delete_filename_seen_cache,
- data.filename_seen_cache);
+ filename_seen_cache filenames_seen;
+
+ data.filename_seen_cache = &filenames_seen;
printf_filtered ("Source files for which symbols have been read in:\n\n");
printf_filtered ("Source files for which symbols "
"will be read in on demand:\n\n");
- clear_filename_seen_cache (data.filename_seen_cache);
+ filenames_seen.clear ();
data.first = 1;
map_symbol_filenames (output_partial_symbol_filename, &data,
1 /*need_fullname*/);
printf_filtered ("\n");
-
- do_cleanups (cleanups);
}
/* Compare FILE against all the NFILES entries of FILES. If BASENAMES is
struct symbol_search *found;
struct symbol_search *tail;
int nfound;
- /* This is true if PREG contains valid data, false otherwise. */
- bool preg_p;
- regex_t preg;
+ gdb::optional<compiled_regex> preg;
/* OLD_CHAIN .. RETVAL_CHAIN is always freed, RETVAL_CHAIN .. current
CLEANUP_CHAIN is freed only in the case of an error. */
ourtype4 = types4[kind];
*matches = NULL;
- preg_p = false;
if (regexp != NULL)
{
}
}
- errcode = regcomp (&preg, regexp,
- REG_NOSUB | (case_sensitivity == case_sensitive_off
- ? REG_ICASE : 0));
- if (errcode != 0)
- {
- char *err = get_regcomp_error (errcode, &preg);
-
- make_cleanup (xfree, err);
- error (_("Invalid regexp (%s): %s"), err, regexp);
- }
- preg_p = true;
- make_regfree_cleanup (&preg);
+ int cflags = REG_NOSUB | (case_sensitivity == case_sensitive_off
+ ? REG_ICASE : 0);
+ preg.emplace (regexp, cflags, _("Invalid regexp"));
}
/* Search through the partial symtabs *first* for all symbols
},
[&] (const char *symname)
{
- return (!preg_p || regexec (&preg, symname,
- 0, NULL, 0) == 0);
+ return (!preg || preg->exec (symname,
+ 0, NULL, 0) == 0);
},
NULL,
kind);
|| MSYMBOL_TYPE (msymbol) == ourtype3
|| MSYMBOL_TYPE (msymbol) == ourtype4)
{
- if (!preg_p
- || regexec (&preg, MSYMBOL_NATURAL_NAME (msymbol), 0,
- NULL, 0) == 0)
+ if (!preg
+ || preg->exec (MSYMBOL_NATURAL_NAME (msymbol), 0,
+ NULL, 0) == 0)
{
/* Note: An important side-effect of these lookup functions
is to expand the symbol table if msymbol is found, for the
files, nfiles, 1))
&& file_matches (symtab_to_fullname (real_symtab),
files, nfiles, 0)))
- && ((!preg_p
- || regexec (&preg, SYMBOL_NATURAL_NAME (sym), 0,
- NULL, 0) == 0)
+ && ((!preg
+ || preg->exec (SYMBOL_NATURAL_NAME (sym), 0,
+ NULL, 0) == 0)
&& ((kind == VARIABLES_DOMAIN
&& SYMBOL_CLASS (sym) != LOC_TYPEDEF
&& SYMBOL_CLASS (sym) != LOC_UNRESOLVED
|| MSYMBOL_TYPE (msymbol) == ourtype3
|| MSYMBOL_TYPE (msymbol) == ourtype4)
{
- if (!preg_p
- || regexec (&preg, MSYMBOL_NATURAL_NAME (msymbol), 0,
- NULL, 0) == 0)
+ if (!preg || preg->exec (MSYMBOL_NATURAL_NAME (msymbol), 0,
+ NULL, 0) == 0)
{
/* For functions we can do a quick check of whether the
symbol might be found via find_pc_symtab. */
free_completion_list ((VEC (char_ptr) **) list);
}
-/* Helper routine for make_symbol_completion_list. */
-
static VEC (char_ptr) *return_val;
-#define COMPLETION_LIST_ADD_SYMBOL(symbol, sym_text, len, text, word) \
- completion_list_add_name \
- (SYMBOL_NATURAL_NAME (symbol), (sym_text), (len), (text), (word))
-
-#define MCOMPLETION_LIST_ADD_SYMBOL(symbol, sym_text, len, text, word) \
- 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
}
}
+/* completion_list_add_name wrapper for struct symbol. */
+
+static void
+completion_list_add_symbol (symbol *sym,
+ const char *sym_text, int sym_text_len,
+ const char *text, const char *word)
+{
+ completion_list_add_name (SYMBOL_NATURAL_NAME (sym),
+ sym_text, sym_text_len, text, word);
+}
+
+/* completion_list_add_name wrapper for struct minimal_symbol. */
+
+static void
+completion_list_add_msymbol (minimal_symbol *sym,
+ const char *sym_text, int sym_text_len,
+ const char *text, const char *word)
+{
+ completion_list_add_name (MSYMBOL_NATURAL_NAME (sym),
+ sym_text, sym_text_len, text, word);
+}
+
/* ObjC: In case we are completing on a selector, look as the msymbol
again and feed all the selectors into the mill. */
if (code == TYPE_CODE_UNDEF
|| (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
&& TYPE_CODE (SYMBOL_TYPE (sym)) == code))
- COMPLETION_LIST_ADD_SYMBOL (sym,
+ completion_list_add_symbol (sym,
sym_text, sym_text_len,
text, word);
}
ALL_MSYMBOLS (objfile, msymbol)
{
QUIT;
- MCOMPLETION_LIST_ADD_SYMBOL (msymbol, sym_text, sym_text_len, text,
+ completion_list_add_msymbol (msymbol, sym_text, sym_text_len, text,
word);
completion_list_objc_symbol (msymbol, sym_text, sym_text_len, text,
{
if (code == TYPE_CODE_UNDEF)
{
- COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text,
+ completion_list_add_symbol (sym, sym_text, sym_text_len, text,
word);
completion_list_add_fields (sym, sym_text, sym_text_len, text,
word);
}
else if (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
&& TYPE_CODE (SYMBOL_TYPE (sym)) == code)
- COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text,
+ completion_list_add_symbol (sym, sym_text, sym_text_len, text,
word);
}
return current_language->la_make_symbol_completion_list (text, word, code);
}
-/* Like make_symbol_completion_list, but suitable for use as a
- completion function. */
-
-VEC (char_ptr) *
-make_symbol_completion_list_fn (struct cmd_list_element *ignore,
- const char *text, const char *word)
-{
- return make_symbol_completion_list (text, word);
-}
-
/* Like make_symbol_completion_list, but returns a list of symbols
- defined in a source file FILE. */
+ defined in all source files name SRCFILE. */
static VEC (char_ptr) *
make_file_symbol_completion_list_1 (const char *text, const char *word,
const char *srcfile)
{
- struct symtab *s;
/* The symbol we are completing on. Points in same buffer as text. */
const char *sym_text;
/* Length of sym_text. */
sym_text_len = strlen (sym_text);
- /* Find the symtab for SRCFILE (this loads it if it was not yet read
- in). */
- s = lookup_symtab (srcfile);
- if (s == NULL)
+ /* Go through symtabs for SRCFILE and check the externs and statics
+ for symbols which match. */
+ iterate_over_symtabs (srcfile, [&] (symtab *s)
{
- /* Maybe they typed the file with leading directories, while the
- symbol tables record only its basename. */
- const char *tail = lbasename (srcfile);
-
- if (tail > srcfile)
- s = lookup_symtab (tail);
- }
-
- /* If we have no symtab for that file, return an empty list. */
- if (s == NULL)
- return (return_val);
-
- /* Go through this symtab and check the externs and statics for
- symbols which match. */
- add_symtab_completions (SYMTAB_COMPUNIT (s),
- sym_text, sym_text_len,
- text, word, TYPE_CODE_UNDEF);
+ add_symtab_completions (SYMTAB_COMPUNIT (s),
+ sym_text, sym_text_len,
+ text, word, TYPE_CODE_UNDEF);
+ return false;
+ });
return (return_val);
}
if (not_interesting_fname (filename))
return;
- if (!filename_seen (data->filename_seen_cache, filename, 1)
+ if (!data->filename_seen_cache->seen (filename)
&& filename_ncmp (filename, data->text, data->text_len) == 0)
{
/* This file matches for a completion; add it to the
const char *base_name = lbasename (filename);
if (base_name != filename
- && !filename_seen (data->filename_seen_cache, base_name, 1)
+ && !data->filename_seen_cache->seen (base_name)
&& filename_ncmp (base_name, data->text, data->text_len) == 0)
add_filename_to_list (base_name, data->text, data->word, data->list);
}
VEC (char_ptr) *list = NULL;
const char *base_name;
struct add_partial_filename_data datum;
- struct filename_seen_cache *filename_seen_cache;
- struct cleanup *back_to, *cache_cleanup;
+ struct cleanup *back_to;
if (!have_full_symbols () && !have_partial_symbols ())
return list;
back_to = make_cleanup (do_free_completion_list, &list);
- filename_seen_cache = create_filename_seen_cache ();
- cache_cleanup = make_cleanup (delete_filename_seen_cache,
- filename_seen_cache);
+ filename_seen_cache filenames_seen;
ALL_FILETABS (objfile, cu, s)
{
if (not_interesting_fname (s->filename))
continue;
- if (!filename_seen (filename_seen_cache, s->filename, 1)
+ if (!filenames_seen.seen (s->filename)
&& filename_ncmp (s->filename, text, text_len) == 0)
{
/* This file matches for a completion; add it to the current
command do when they parse file names. */
base_name = lbasename (s->filename);
if (base_name != s->filename
- && !filename_seen (filename_seen_cache, base_name, 1)
+ && !filenames_seen.seen (base_name)
&& filename_ncmp (base_name, text, text_len) == 0)
add_filename_to_list (base_name, text, word, &list);
}
}
- datum.filename_seen_cache = filename_seen_cache;
+ datum.filename_seen_cache = &filenames_seen;
datum.text = text;
datum.word = word;
datum.text_len = text_len;
map_symbol_filenames (maybe_add_partial_symtab_filename, &datum,
0 /*need_fullname*/);
- do_cleanups (cache_cleanup);
discard_cleanups (back_to);
return list;