/* 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;
{
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);
-
- if (fullname != NULL)
- {
- char *rp = gdb_realpath (fullname);
+ const char *fullname = symtab_to_fullname (s);
+ char *rp = gdb_realpath (fullname);
- make_cleanup (xfree, rp);
- if (FILENAME_CMP (real_path, rp) == 0)
- {
- if (callback (s, data))
- return 1;
- }
+ make_cleanup (xfree, rp);
+ if (FILENAME_CMP (real_path, rp) == 0)
+ {
+ if (callback (s, data))
+ return 1;
+ }
- if (!is_abs && compare_filenames_for_search (rp, name, name_len))
- {
- if (callback (s, data))
- return 1;
- }
- }
+ if (!is_abs && compare_filenames_for_search (rp, name))
+ {
+ if (callback (s, data))
+ return 1;
+ }
}
}
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);
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);
if (best_s != NULL)
return (best_s);
+ /* Not found in symtabs, search the "quick" symtabs (e.g. psymtabs). */
+
ALL_OBJFILES (objfile)
{
struct symtab *result;
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);
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);
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;
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;