/* Symbol table lookup for the GNU debugger, GDB.
- Copyright (C) 1986-2004, 2007-2012 Free Software Foundation, Inc.
+ Copyright (C) 1986-2013 Free Software Foundation, Inc.
This file is part of GDB.
#include "symfile.h"
#include "objfiles.h"
#include "gdbcmd.h"
-#include "call-cmds.h"
#include "gdb_regex.h"
#include "expression.h"
#include "language.h"
#include "demangle.h"
#include "inferior.h"
-#include "linespec.h"
#include "source.h"
#include "filenames.h" /* for FILENAME_CMP */
#include "objc-lang.h"
#include "macroscope.h"
#include "psymtab.h"
+#include "parser-defs.h"
/* Prototypes for local functions */
static void sources_info (char *, int);
-static void output_source_filename (const char *, int *);
-
static int find_line_common (struct linetable *, int, int *, int);
static struct symbol *lookup_symbol_aux (const char *name,
const struct block *block,
const domain_enum domain,
enum language language,
- int *is_a_field_of_this);
+ struct field_of_this_result *is_a_field_of_this);
static
struct symbol *lookup_symbol_aux_local (const char *name,
/* See whether FILENAME matches SEARCH_NAME using the rule that we
advertise to the user. (The manual's description of linespecs
- describes what we advertise). SEARCH_LEN is the length of
- SEARCH_NAME. We assume that SEARCH_NAME is a relative path.
- Returns true if they match, false otherwise. */
+ describes what we advertise). We assume that SEARCH_NAME is
+ a relative path. Returns true if they match, false otherwise. */
int
-compare_filenames_for_search (const char *filename, const char *search_name,
- int search_len)
+compare_filenames_for_search (const char *filename, const char *search_name)
{
int len = strlen (filename);
+ size_t search_len = strlen (search_name);
if (len < search_len)
return 0;
/* Either the names must completely match, or the character
preceding the trailing SEARCH_NAME segment of FILENAME must be a
- directory separator. */
+ directory separator.
+
+ The HAS_DRIVE_SPEC purpose is to make FILENAME "c:file.c"
+ compatible with SEARCH_NAME "file.c". In such case a compiler had
+ to put the "c:file.c" name into debug info. Such compatibility
+ works only on GDB built for DOS host. */
return (len == search_len
|| IS_DIR_SEPARATOR (filename[len - search_len - 1])
|| (HAS_DRIVE_SPEC (filename)
{
struct symtab *s = NULL;
const char* base_name = lbasename (name);
- int name_len = strlen (name);
int is_abs = IS_ABSOLUTE_PATH (name);
for (s = first; s != NULL && s != after_last; s = s->next)
return 1;
}
- if (!is_abs && compare_filenames_for_search (s->filename, name, name_len))
+ if (!is_abs && compare_filenames_for_search (s->filename, name))
{
if (callback (s, data))
return 1;
{
const char *fp = symtab_to_fullname (s);
- if (fp != NULL && FILENAME_CMP (full_path, fp) == 0)
+ if (FILENAME_CMP (full_path, fp) == 0)
{
if (callback (s, data))
return 1;
}
- if (fp != NULL && !is_abs && compare_filenames_for_search (fp, name,
- name_len))
+ if (!is_abs && compare_filenames_for_search (fp, name))
{
if (callback (s, data))
return 1;
if (real_path != NULL)
{
- char *fullname = symtab_to_fullname (s);
+ const char *fullname = symtab_to_fullname (s);
+ char *rp = gdb_realpath (fullname);
+ struct cleanup *cleanups = make_cleanup (xfree, rp);
- if (fullname != NULL)
- {
- char *rp = gdb_realpath (fullname);
-
- make_cleanup (xfree, rp);
- if (FILENAME_CMP (real_path, rp) == 0)
+ if (FILENAME_CMP (real_path, rp) == 0)
+ {
+ if (callback (s, data))
{
- if (callback (s, data))
- return 1;
+ do_cleanups (cleanups);
+ return 1;
}
+ }
- if (!is_abs && compare_filenames_for_search (rp, name, name_len))
+ if (!is_abs && compare_filenames_for_search (rp, name))
+ {
+ if (callback (s, data))
{
- if (callback (s, data))
- return 1;
+ do_cleanups (cleanups);
+ return 1;
}
- }
+ }
+ do_cleanups (cleanups);
}
}
void *data),
void *data)
{
- struct symtab *s = NULL;
struct objfile *objfile;
char *real_path = NULL;
char *full_path = NULL;
if (len == 0)
{
- sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
+ xsnprintf (buf, sizeof (buf), "__%s%s", const_prefix, volatile_prefix);
}
else if (physname[0] == 't' || physname[0] == 'Q')
{
/* The physname for template and qualified methods already includes
the class name. */
- sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
+ xsnprintf (buf, sizeof (buf), "__%s%s", const_prefix, volatile_prefix);
newname = NULL;
len = 0;
}
else
{
- sprintf (buf, "__%s%s%d", const_prefix, volatile_prefix, len);
+ xsnprintf (buf, sizeof (buf), "__%s%s%d", const_prefix,
+ volatile_prefix, len);
}
mangled_name_len = ((is_constructor ? 0 : strlen (field_name))
+ strlen (buf) + len + strlen (physname) + 1);
void
symbol_set_demangled_name (struct general_symbol_info *gsymbol,
- char *name,
+ const char *name,
struct objfile *objfile)
{
if (gsymbol->language == language_cplus)
/* Objects of this type are stored in the demangled name hash table. */
struct demangled_name_entry
{
- char *mangled;
+ const char *mangled;
char demangled[1];
};
linkage_name_copy = linkage_name;
}
- entry.mangled = (char *) lookup_name;
+ entry.mangled = lookup_name;
slot = ((struct demangled_name_entry **)
htab_find_slot (objfile->demangled_names_hash,
&entry, INSERT));
offsetof (struct demangled_name_entry,
demangled)
+ demangled_len + 1);
- (*slot)->mangled = (char *) lookup_name;
+ (*slot)->mangled = lookup_name;
}
else
{
+ char *mangled_ptr;
+
/* If we must copy the mangled name, put it directly after
the demangled name so we can have a single
allocation. */
offsetof (struct demangled_name_entry,
demangled)
+ lookup_len + demangled_len + 2);
- (*slot)->mangled = &((*slot)->demangled[demangled_len + 1]);
- strcpy ((*slot)->mangled, lookup_name);
+ mangled_ptr = &((*slot)->demangled[demangled_len + 1]);
+ strcpy (mangled_ptr, lookup_name);
+ (*slot)->mangled = mangled_ptr;
}
if (demangled_name != NULL)
struct symbol *
lookup_symbol_in_language (const char *name, const struct block *block,
const domain_enum domain, enum language lang,
- int *is_a_field_of_this)
+ struct field_of_this_result *is_a_field_of_this)
{
const char *modified_name;
struct symbol *returnval;
struct symbol *
lookup_symbol (const char *name, const struct block *block,
- domain_enum domain, int *is_a_field_of_this)
+ domain_enum domain,
+ struct field_of_this_result *is_a_field_of_this)
{
return lookup_symbol_in_language (name, block, domain,
current_language->la_language,
return NULL;
}
+/* Given TYPE, a structure/union,
+ return 1 if the component named NAME from the ultimate target
+ structure/union is defined, otherwise, return 0. */
+
+static int
+check_field (struct type *type, const char *name,
+ struct field_of_this_result *is_a_field_of_this)
+{
+ int i;
+
+ /* The type may be a stub. */
+ CHECK_TYPEDEF (type);
+
+ for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--)
+ {
+ const char *t_field_name = TYPE_FIELD_NAME (type, i);
+
+ if (t_field_name && (strcmp_iw (t_field_name, name) == 0))
+ {
+ is_a_field_of_this->type = type;
+ is_a_field_of_this->field = &TYPE_FIELD (type, i);
+ return 1;
+ }
+ }
+
+ /* C++: If it was not found as a data field, then try to return it
+ as a pointer to a method. */
+
+ for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; --i)
+ {
+ if (strcmp_iw (TYPE_FN_FIELDLIST_NAME (type, i), name) == 0)
+ {
+ is_a_field_of_this->type = type;
+ is_a_field_of_this->fn_field = &TYPE_FN_FIELDLIST (type, i);
+ return 1;
+ }
+ }
+
+ for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)
+ if (check_field (TYPE_BASECLASS (type, i), name, is_a_field_of_this))
+ return 1;
+
+ return 0;
+}
+
/* Behave like lookup_symbol except that NAME is the natural name
(e.g., demangled name) of the symbol that we're looking for. */
static struct symbol *
lookup_symbol_aux (const char *name, const struct block *block,
const domain_enum domain, enum language language,
- int *is_a_field_of_this)
+ struct field_of_this_result *is_a_field_of_this)
{
struct symbol *sym;
const struct language_defn *langdef;
/* Make sure we do something sensible with is_a_field_of_this, since
the callers that set this parameter to some non-null value will
- certainly use it later and expect it to be either 0 or 1.
- If we don't set it, the contents of is_a_field_of_this are
- undefined. */
+ certainly use it later. If we don't set it, the contents of
+ is_a_field_of_this are undefined. */
if (is_a_field_of_this != NULL)
- *is_a_field_of_this = 0;
+ memset (is_a_field_of_this, 0, sizeof (*is_a_field_of_this));
/* Search specified block and its superiors. Don't search
STATIC_BLOCK or GLOBAL_BLOCK. */
langdef = language_def (language);
- if (is_a_field_of_this != NULL)
+ /* Don't do this check if we are searching for a struct. It will
+ not be found by check_field, but will be found by other
+ means. */
+ if (is_a_field_of_this != NULL && domain != STRUCT_DOMAIN)
{
struct symbol *sym = lookup_language_this (langdef, block);
error (_("Internal error: `%s' is not an aggregate"),
langdef->la_name_of_this);
- if (check_field (t, name))
- {
- *is_a_field_of_this = 1;
- return NULL;
- }
+ if (check_field (t, name, is_a_field_of_this))
+ return NULL;
}
}
const struct block *block;
struct symtab *s;
- if (objfile->sf)
- objfile->sf->qf->pre_expand_symtabs_matching (objfile, block_index,
- name, domain);
-
ALL_OBJFILE_PRIMARY_SYMTABS (objfile, s)
{
bv = BLOCKVECTOR (s);
lookup_data.name = name;
lookup_data.domain = domain;
gdbarch_iterate_over_objfiles_in_search_order
- (objfile != NULL ? get_objfile_arch (objfile) : target_gdbarch,
+ (objfile != NULL ? get_objfile_arch (objfile) : target_gdbarch (),
lookup_symbol_global_iterator_cb, &lookup_data, objfile);
return lookup_data.result;
ALL_OBJFILES (objfile)
{
- if (objfile->sf)
- objfile->sf->qf->pre_expand_symtabs_matching (objfile,
- GLOBAL_BLOCK,
- name, STRUCT_DOMAIN);
-
ALL_OBJFILE_PRIMARY_SYMTABS (objfile, s)
{
bv = BLOCKVECTOR (s);
ALL_OBJFILES (objfile)
{
- if (objfile->sf)
- objfile->sf->qf->pre_expand_symtabs_matching (objfile, STATIC_BLOCK,
- name, STRUCT_DOMAIN);
-
ALL_OBJFILE_PRIMARY_SYMTABS (objfile, s)
{
bv = BLOCKVECTOR (s);
struct symtab *s = NULL;
struct symtab *best_s = NULL;
struct objfile *objfile;
- struct program_space *pspace;
CORE_ADDR distance = 0;
struct minimal_symbol *msymbol;
- pspace = current_program_space;
-
/* If we know that this is not a text address, return failure. This is
necessary because we loop based on the block's high and low code
addresses, which do not include the data ranges, and because
if (best_s != NULL)
return (best_s);
+ /* Not found in symtabs, search the "quick" symtabs (e.g. psymtabs). */
+
ALL_OBJFILES (objfile)
{
struct symtab *result;
we will use a line one less than this,
with a range from the start of that file to the first line's pc. */
struct linetable_entry *alt = NULL;
- struct symtab *alt_symtab = 0;
/* Info on best line seen in this file. */
/* Is this file's first line closer than the first lines of other files?
If so, record this file, and its first line, as best alternate. */
if (item->pc > pc && (!alt || item->pc < alt->pc))
- {
- alt = item;
- alt_symtab = s;
- }
+ alt = item;
for (i = 0; i < len; i++, item++)
{
symtab->filename);
}
- /* Get symbol full file name if possible. */
- symtab_to_fullname (symtab);
-
ALL_SYMTABS (objfile, s)
{
struct linetable *l;
if (FILENAME_CMP (symtab->filename, s->filename) != 0)
continue;
- if (symtab->fullname != NULL
- && symtab_to_fullname (s) != NULL
- && FILENAME_CMP (symtab->fullname, s->fullname) != 0)
+ if (FILENAME_CMP (symtab_to_fullname (symtab),
+ symtab_to_fullname (s)) != 0)
continue;
l = LINETABLE (s);
ind = find_line_common (l, line, &exact, 0);
find_pcs_for_symtab_line (struct symtab *symtab, int line,
struct linetable_entry **best_item)
{
- int start = 0, ix;
- struct symbol *previous_function = NULL;
+ int start = 0;
VEC (CORE_ADDR) *result = NULL;
/* First, collect all the PCs that are at this line. */
struct block *b, *function_block;
int force_skip, skip;
- /* Do not change the SAL is PC was specified explicitly. */
+ /* Do not change the SAL if PC was specified explicitly. */
if (sal->explicit_pc)
return;
}
\f
-/* If FILE is not already in the table of files, return zero;
+/* 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;
+
+ 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 = 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. If *FIRST is non-zero, forget the old table
- contents. */
+ 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 (const char *file, int add, int *first)
+filename_seen (struct filename_seen_cache *cache, const char *file, int add)
{
- /* Table of files seen so far. */
- static const char **tab = NULL;
- /* Allocated size of tab in elements.
- Start with one 256-byte block (when using GNU malloc.c).
- 24 is the malloc overhead when range checking is in effect. */
- static int tab_alloc_size = (256 - 24) / sizeof (char *);
- /* Current size of tab in elements. */
- static int tab_cur_size;
- const char **p;
-
- if (*first)
- {
- if (tab == NULL)
- tab = (const char **) xmalloc (tab_alloc_size * sizeof (*tab));
- tab_cur_size = 0;
- }
+ void **slot;
/* Is FILE in tab? */
- for (p = tab; p < tab + tab_cur_size; p++)
- if (filename_cmp (*p, file) == 0)
- return 1;
+ slot = htab_find_slot (cache->tab, file, add ? INSERT : NO_INSERT);
+ if (*slot != NULL)
+ return 1;
/* No; maybe add it to tab. */
if (add)
- {
- if (tab_cur_size == tab_alloc_size)
- {
- tab_alloc_size *= 2;
- tab = (const char **) xrealloc ((char *) tab,
- tab_alloc_size * sizeof (*tab));
- }
- tab[tab_cur_size++] = file;
- }
+ *slot = (char *) file;
return 0;
}
+/* Data structure to maintain printing state for output_source_filename. */
+
+struct output_source_filename_data
+{
+ /* Cache of what we've seen so far. */
+ struct filename_seen_cache *filename_seen_cache;
+
+ /* Flag of whether we're printing the first one. */
+ int first;
+};
+
/* Slave routine for sources_info. Force line breaks at ,'s.
- NAME is the name to print and *FIRST is nonzero if this is the first
- name printed. Set *FIRST to zero. */
+ NAME is the name to print.
+ DATA contains the state for printing and watching for duplicates. */
static void
-output_source_filename (const char *name, int *first)
+output_source_filename (const char *name,
+ struct output_source_filename_data *data)
{
/* Since a single source file can result in several partial symbol
tables, we need to avoid printing it more than once. Note: if
symtabs; it doesn't hurt to check. */
/* Was NAME already seen? */
- if (filename_seen (name, 1, first))
+ if (filename_seen (data->filename_seen_cache, name, 1))
{
/* Yes; don't print it again. */
return;
}
+
/* No; print it and reset *FIRST. */
- if (*first)
- {
- *first = 0;
- }
- else
- {
- printf_filtered (", ");
- }
+ if (! data->first)
+ printf_filtered (", ");
+ data->first = 0;
wrap_here ("");
fputs_filtered (name, gdb_stdout);
{
struct symtab *s;
struct objfile *objfile;
- int first;
+ 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);
+
printf_filtered ("Source files for which symbols have been read in:\n\n");
- first = 1;
+ data.first = 1;
ALL_SYMTABS (objfile, s)
{
const char *fullname = symtab_to_fullname (s);
- output_source_filename (fullname ? fullname : s->filename, &first);
+ output_source_filename (fullname, &data);
}
printf_filtered ("\n\n");
printf_filtered ("Source files for which symbols "
"will be read in on demand:\n\n");
- first = 1;
- map_partial_symbol_filenames (output_partial_symbol_filename, &first,
+ clear_filename_seen_cache (data.filename_seen_cache);
+ data.first = 1;
+ map_partial_symbol_filenames (output_partial_symbol_filename, &data,
1 /*need_fullname*/);
printf_filtered ("\n");
+
+ do_cleanups (cleanups);
}
static int
search_symbols (regexp, kind, 0, (char **) NULL, &symbols);
old_chain = make_cleanup_free_search_symbols (symbols);
- printf_filtered (regexp
- ? "All %ss matching regular expression \"%s\":\n"
- : "All defined %ss:\n",
- classnames[kind], regexp);
+ if (regexp != NULL)
+ printf_filtered (_("All %ss matching regular expression \"%s\":\n"),
+ classnames[kind], regexp);
+ else
+ printf_filtered (_("All defined %ss:\n"), classnames[kind]);
for (p = symbols; p != NULL; p = p->next)
{
{
if (first)
{
- printf_filtered ("\nNon-debugging symbols:\n");
+ printf_filtered (_("\nNon-debugging symbols:\n"));
first = 0;
}
print_msymbol_info (p->msymbol);
const char *sym_text, int sym_text_len,
const char *text, const char *word)
{
- int newsize;
-
/* Clip symbols that cannot match. */
if (!compare_symbol_name (symname, sym_text, sym_text_len))
return;
VEC (char_ptr) *
default_make_symbol_completion_list_break_on (char *text, char *word,
- const char *break_on)
+ 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
anything that isn't a text symbol (everything else will be
handled by the psymtab code above). */
- ALL_MSYMBOLS (objfile, msymbol)
- {
- QUIT;
- COMPLETION_LIST_ADD_SYMBOL (msymbol, sym_text, sym_text_len, text, word);
+ if (code == TYPE_CODE_UNDEF)
+ {
+ ALL_MSYMBOLS (objfile, msymbol)
+ {
+ QUIT;
+ COMPLETION_LIST_ADD_SYMBOL (msymbol, sym_text, sym_text_len, text,
+ word);
- completion_list_objc_symbol (msymbol, sym_text, sym_text_len, text, word);
- }
+ completion_list_objc_symbol (msymbol, sym_text, sym_text_len, text,
+ word);
+ }
+ }
/* Search upwards from currently selected frame (so that we can
complete on local vars). Also catch fields of types defined in
ALL_BLOCK_SYMBOLS (b, iter, sym)
{
- COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text,
- word);
- completion_list_add_fields (sym, sym_text, sym_text_len, text,
- word);
+ if (code == TYPE_CODE_UNDEF)
+ {
+ 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,
+ word);
}
/* Stop when we encounter an enclosing function. Do not stop for
/* Add fields from the file's types; symbols will be added below. */
- if (surrounding_static_block != NULL)
- ALL_BLOCK_SYMBOLS (surrounding_static_block, iter, sym)
- completion_list_add_fields (sym, sym_text, sym_text_len, text, word);
+ if (code == TYPE_CODE_UNDEF)
+ {
+ if (surrounding_static_block != NULL)
+ ALL_BLOCK_SYMBOLS (surrounding_static_block, iter, sym)
+ completion_list_add_fields (sym, sym_text, sym_text_len, text, word);
- if (surrounding_global_block != NULL)
- ALL_BLOCK_SYMBOLS (surrounding_global_block, iter, sym)
- completion_list_add_fields (sym, sym_text, sym_text_len, text, word);
+ if (surrounding_global_block != NULL)
+ ALL_BLOCK_SYMBOLS (surrounding_global_block, iter, sym)
+ completion_list_add_fields (sym, sym_text, sym_text_len, text, word);
+ }
/* Go through the symtabs and check the externs and statics for
symbols which match. */
b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
ALL_BLOCK_SYMBOLS (b, iter, sym)
{
- COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
+ if (code == TYPE_CODE_UNDEF
+ || (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
+ && TYPE_CODE (SYMBOL_TYPE (sym)) == code))
+ COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
}
}
b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
ALL_BLOCK_SYMBOLS (b, iter, sym)
{
- COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
+ if (code == TYPE_CODE_UNDEF
+ || (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
+ && TYPE_CODE (SYMBOL_TYPE (sym)) == code))
+ COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
}
}
- if (current_language->la_macro_expansion == macro_expansion_c)
+ /* Skip macros if we are completing a struct tag -- arguable but
+ usually what is expected. */
+ if (current_language->la_macro_expansion == macro_expansion_c
+ && code == TYPE_CODE_UNDEF)
{
struct macro_scope *scope;
}
VEC (char_ptr) *
-default_make_symbol_completion_list (char *text, char *word)
+default_make_symbol_completion_list (char *text, char *word,
+ enum type_code code)
{
- return default_make_symbol_completion_list_break_on (text, word, "");
+ return default_make_symbol_completion_list_break_on (text, word, "", code);
}
/* Return a vector of all symbols (regardless of class) which begin by
VEC (char_ptr) *
make_symbol_completion_list (char *text, char *word)
{
- return current_language->la_make_symbol_completion_list (text, word);
+ return current_language->la_make_symbol_completion_list (text, word,
+ TYPE_CODE_UNDEF);
+}
+
+/* Like make_symbol_completion_list, but only return STRUCT_DOMAIN
+ symbols whose type code is CODE. */
+
+VEC (char_ptr) *
+make_symbol_completion_type (char *text, char *word, enum type_code code)
+{
+ gdb_assert (code == TYPE_CODE_UNION
+ || code == TYPE_CODE_STRUCT
+ || code == TYPE_CODE_CLASS
+ || code == TYPE_CODE_ENUM);
+ return current_language->la_make_symbol_completion_list (text, word, code);
}
/* Like make_symbol_completion_list, but suitable for use as a
map_partial_symbol_filenames. */
struct add_partial_filename_data
{
- int *first;
+ struct filename_seen_cache *filename_seen_cache;
char *text;
char *word;
int text_len;
if (not_interesting_fname (filename))
return;
- if (!filename_seen (filename, 1, data->first)
+ if (!filename_seen (data->filename_seen_cache, filename, 1)
&& 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 (base_name, 1, data->first)
+ && !filename_seen (data->filename_seen_cache, base_name, 1)
&& filename_ncmp (base_name, data->text, data->text_len) == 0)
add_filename_to_list (base_name, data->text, data->word, data->list);
}
{
struct symtab *s;
struct objfile *objfile;
- int first = 1;
size_t text_len = strlen (text);
VEC (char_ptr) *list = NULL;
const char *base_name;
struct add_partial_filename_data datum;
- struct cleanup *back_to;
+ struct filename_seen_cache *filename_seen_cache;
+ struct cleanup *back_to, *cache_cleanup;
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);
+
ALL_SYMTABS (objfile, s)
{
if (not_interesting_fname (s->filename))
continue;
- if (!filename_seen (s->filename, 1, &first)
+ if (!filename_seen (filename_seen_cache, s->filename, 1)
&& 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 (base_name, 1, &first)
+ && !filename_seen (filename_seen_cache, base_name, 1)
&& filename_ncmp (base_name, text, text_len) == 0)
add_filename_to_list (base_name, text, word, &list);
}
}
- datum.first = &first;
+ datum.filename_seen_cache = filename_seen_cache;
datum.text = text;
datum.word = word;
datum.text_len = text_len;
datum.list = &list;
map_partial_symbol_filenames (maybe_add_partial_symtab_filename, &datum,
0 /*need_fullname*/);
+
+ do_cleanups (cache_cleanup);
discard_cleanups (back_to);
return list;
line mark the prologue -> body transition. */
if (sal.line >= prologue_sal.line)
break;
+ /* Likewise if we are in a different symtab altogether
+ (e.g. within a file included via #include). */
+ if (sal.symtab != prologue_sal.symtab)
+ break;
/* The line number is smaller. Check that it's from the
same function, not something inlined. If it's inlined,
return prologue_sal.pc;
}
\f
-struct symtabs_and_lines
-decode_line_spec (char *string, int flags)
-{
- struct symtabs_and_lines sals;
- struct symtab_and_line cursal;
-
- if (string == 0)
- error (_("Empty line specification."));
-
- /* We use whatever is set as the current source line. We do not try
- and get a default or it will recursively call us! */
- cursal = get_current_source_symtab_and_line ();
-
- sals = decode_line_1 (&string, flags,
- cursal.symtab, cursal.line);
-
- if (*string)
- error (_("Junk at end of line specification: %s"), string);
- return sals;
-}
-
/* Track MAIN */
static char *name_of_main;
enum language language_of_main = language_unknown;