/* Symbol table lookup for the GNU debugger, GDB.
- Copyright 1986, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 1998
- Free Software Foundation, Inc.
+
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
+ 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 Free Software
+ Foundation, Inc.
This file is part of GDB.
#include "demangle.h"
#include "inferior.h"
#include "linespec.h"
+#include "source.h"
+#include "filenames.h" /* for FILENAME_CMP */
-#include "obstack.h"
+#include "gdb_obstack.h"
#include <sys/types.h>
#include <fcntl.h>
#include "gdb_string.h"
#include "gdb_stat.h"
#include <ctype.h>
-
-/* Prototype for one function in parser-defs.h,
- instead of including that entire file. */
-
-extern char *find_template_name_end (char *);
+#include "cp-abi.h"
/* Prototypes for local functions */
const char *, int,
namespace_enum);
-static struct symtab *lookup_symtab_1 (char *);
-
-static struct symbol *lookup_symbol_aux (const char *name, const
- struct block *block, const
- namespace_enum namespace, int
- *is_a_field_of_this, struct
- symtab **symtab);
-
+static struct symbol *lookup_symbol_aux (const char *name,
+ const char *mangled_name,
+ const struct block *block,
+ const namespace_enum namespace,
+ int *is_a_field_of_this,
+ struct symtab **symtab);
+
+static struct symbol *lookup_symbol_aux_local (const char *name,
+ const char *mangled_name,
+ const struct block *block,
+ const namespace_enum namespace,
+ struct symtab **symtab);
+
+static
+struct symbol *lookup_symbol_aux_symtabs (int block_index,
+ const char *name,
+ const char *mangled_name,
+ const namespace_enum namespace,
+ struct symtab **symtab);
+
+static
+struct symbol *lookup_symbol_aux_psymtabs (int block_index,
+ const char *name,
+ const char *mangled_name,
+ const namespace_enum namespace,
+ struct symtab **symtab);
static struct symbol *find_active_alias (struct symbol *sym, CORE_ADDR addr);
const struct block *block_found;
-/* While the C++ support is still in flux, issue a possibly helpful hint on
- using the new command completion feature on single quoted demangled C++
- symbols. Remove when loose ends are cleaned up. FIXME -fnf */
-
-static void
-cplusplus_hint (char *name)
-{
- while (*name == '\'')
- name++;
- printf_filtered ("Hint: try '%s<TAB> or '%s<ESC-?>\n", name, name);
- printf_filtered ("(Note leading single quote.)\n");
-}
-
/* Check for a symtab of a specific name; first in symtabs, then in
psymtabs. *If* there is no '/' in the name, a match after a '/'
in the symtab filename will also work. */
-static struct symtab *
-lookup_symtab_1 (char *name)
+struct symtab *
+lookup_symtab (const char *name)
{
register struct symtab *s;
register struct partial_symtab *ps;
- register char *slash;
register struct objfile *objfile;
+ char *real_path = NULL;
+ char *full_path = NULL;
+
+ /* Here we are interested in canonicalizing an absolute path, not
+ absolutizing a relative path. */
+ if (IS_ABSOLUTE_PATH (name))
+ {
+ full_path = xfullpath (name);
+ make_cleanup (xfree, full_path);
+ real_path = gdb_realpath (name);
+ make_cleanup (xfree, real_path);
+ }
got_symtab:
/* First, search for an exact match */
ALL_SYMTABS (objfile, s)
- if (STREQ (name, s->filename))
- return s;
+ {
+ if (FILENAME_CMP (name, s->filename) == 0)
+ {
+ return s;
+ }
+
+ /* If the user gave us an absolute path, try to find the file in
+ this symtab and use its absolute path. */
+
+ if (full_path != NULL)
+ {
+ const char *fp = symtab_to_filename (s);
+ if (FILENAME_CMP (full_path, fp) == 0)
+ {
+ return s;
+ }
+ }
- slash = strchr (name, '/');
+ if (real_path != NULL)
+ {
+ char *rp = gdb_realpath (symtab_to_filename (s));
+ make_cleanup (xfree, rp);
+ if (FILENAME_CMP (real_path, rp) == 0)
+ {
+ return s;
+ }
+ }
+ }
/* Now, search for a matching tail (only if name doesn't have any dirs) */
- if (!slash)
+ if (lbasename (name) == name)
ALL_SYMTABS (objfile, s)
{
- char *p = s->filename;
- char *tail = strrchr (p, '/');
-
- if (tail)
- p = tail + 1;
-
- if (STREQ (p, name))
+ if (FILENAME_CMP (lbasename (s->filename), name) == 0)
return s;
}
goto got_symtab;
}
-/* Lookup the symbol table of a source file named NAME. Try a couple
- of variations if the first lookup doesn't work. */
-
-struct symtab *
-lookup_symtab (char *name)
-{
- register struct symtab *s;
-#if 0
- register char *copy;
-#endif
-
- s = lookup_symtab_1 (name);
- if (s)
- return s;
-
-#if 0
- /* This screws c-exp.y:yylex if there is both a type "tree" and a symtab
- "tree.c". */
-
- /* If name not found as specified, see if adding ".c" helps. */
- /* Why is this? Is it just a user convenience? (If so, it's pretty
- questionable in the presence of C++, FORTRAN, etc.). It's not in
- the GDB manual. */
-
- copy = (char *) alloca (strlen (name) + 3);
- strcpy (copy, name);
- strcat (copy, ".c");
- s = lookup_symtab_1 (copy);
- if (s)
- return s;
-#endif /* 0 */
-
- /* We didn't find anything; die. */
- return 0;
-}
-
/* Lookup the partial symbol table of a source file named NAME.
*If* there is no '/' in the name, a match after a '/'
in the psymtab filename will also work. */
struct partial_symtab *
-lookup_partial_symtab (char *name)
+lookup_partial_symtab (const char *name)
{
register struct partial_symtab *pst;
register struct objfile *objfile;
+ char *full_path = NULL;
+ char *real_path = NULL;
+
+ /* Here we are interested in canonicalizing an absolute path, not
+ absolutizing a relative path. */
+ if (IS_ABSOLUTE_PATH (name))
+ {
+ full_path = xfullpath (name);
+ make_cleanup (xfree, full_path);
+ real_path = gdb_realpath (name);
+ make_cleanup (xfree, real_path);
+ }
ALL_PSYMTABS (objfile, pst)
{
- if (STREQ (name, pst->filename))
+ if (FILENAME_CMP (name, pst->filename) == 0)
{
return (pst);
}
+
+ /* If the user gave us an absolute path, try to find the file in
+ this symtab and use its absolute path. */
+ if (full_path != NULL)
+ {
+ if (pst->fullname == NULL)
+ source_full_path_of (pst->filename, &pst->fullname);
+ if (pst->fullname != NULL
+ && FILENAME_CMP (full_path, pst->fullname) == 0)
+ {
+ return pst;
+ }
+ }
+
+ if (real_path != NULL)
+ {
+ char *rp = NULL;
+ if (pst->fullname == NULL)
+ source_full_path_of (pst->filename, &pst->fullname);
+ if (pst->fullname != NULL)
+ {
+ rp = gdb_realpath (pst->fullname);
+ make_cleanup (xfree, rp);
+ }
+ if (rp != NULL && FILENAME_CMP (real_path, rp) == 0)
+ {
+ return pst;
+ }
+ }
}
/* Now, search for a matching tail (only if name doesn't have any dirs) */
- if (!strchr (name, '/'))
+ if (lbasename (name) == name)
ALL_PSYMTABS (objfile, pst)
{
- char *p = pst->filename;
- char *tail = strrchr (p, '/');
-
- if (tail)
- p = tail + 1;
-
- if (STREQ (p, name))
+ if (FILENAME_CMP (lbasename (pst->filename), name) == 0)
return (pst);
}
int is_full_physname_constructor;
int is_constructor;
- int is_destructor = DESTRUCTOR_PREFIX_P (physname);
+ int is_destructor = is_destructor_name (physname);
/* Need a new type prefix. */
char *const_prefix = method->is_const ? "C" : "";
char *volatile_prefix = method->is_volatile ? "V" : "";
char buf[20];
int len = (newname == NULL ? 0 : strlen (newname));
- if (OPNAME_PREFIX_P (field_name))
+ /* Nothing to do if physname already contains a fully mangled v3 abi name
+ or an operator name. */
+ if ((physname[0] == '_' && physname[1] == 'Z')
+ || is_operator_name (field_name))
return xstrdup (physname);
- is_full_physname_constructor =
- ((physname[0] == '_' && physname[1] == '_' &&
- (isdigit (physname[2]) || physname[2] == 'Q' || physname[2] == 't'))
- || (strncmp (physname, "__ct", 4) == 0));
+ is_full_physname_constructor = is_constructor_name (physname);
is_constructor =
is_full_physname_constructor || (newname && STREQ (field_name, newname));
strcat (mangled_name, physname);
return (mangled_name);
}
+
+\f
+/* Initialize the language dependent portion of a symbol
+ depending upon the language for the symbol. */
+void
+symbol_init_language_specific (struct general_symbol_info *gsymbol,
+ enum language language)
+{
+ gsymbol->language = language;
+ if (gsymbol->language == language_cplus
+ || gsymbol->language == language_java)
+ {
+ gsymbol->language_specific.cplus_specific.demangled_name = NULL;
+ }
+ else if (gsymbol->language == language_objc)
+ {
+ gsymbol->language_specific.objc_specific.demangled_name = NULL;
+ }
+ /* OBSOLETE else if (SYMBOL_LANGUAGE (symbol) == language_chill) */
+ /* OBSOLETE { */
+ /* OBSOLETE SYMBOL_CHILL_DEMANGLED_NAME (symbol) = NULL; */
+ /* OBSOLETE } */
+ else
+ {
+ memset (&gsymbol->language_specific, 0,
+ sizeof (gsymbol->language_specific));
+ }
+}
+
+/* Initialize a symbol's mangled name. */
+
+/* Try to initialize the demangled name for a symbol, based on the
+ language of that symbol. If the language is set to language_auto,
+ it will attempt to find any demangling algorithm that works and
+ then set the language appropriately. If no demangling of any kind
+ is found, the language is set back to language_unknown, so we can
+ avoid doing this work again the next time we encounter the symbol.
+ Any required space to store the name is obtained from the specified
+ obstack. */
+
+void
+symbol_init_demangled_name (struct general_symbol_info *gsymbol,
+ struct obstack *obstack)
+{
+ char *mangled = gsymbol->name;
+ char *demangled = NULL;
+
+ if (gsymbol->language == language_unknown)
+ gsymbol->language = language_auto;
+ if (gsymbol->language == language_cplus
+ || gsymbol->language == language_auto)
+ {
+ demangled =
+ cplus_demangle (gsymbol->name, DMGL_PARAMS | DMGL_ANSI);
+ if (demangled != NULL)
+ {
+ gsymbol->language = language_cplus;
+ gsymbol->language_specific.cplus_specific.demangled_name =
+ obsavestring (demangled, strlen (demangled), obstack);
+ xfree (demangled);
+ }
+ else
+ {
+ gsymbol->language_specific.cplus_specific.demangled_name = NULL;
+ }
+ }
+ if (gsymbol->language == language_java)
+ {
+ demangled =
+ cplus_demangle (gsymbol->name,
+ DMGL_PARAMS | DMGL_ANSI | DMGL_JAVA);
+ if (demangled != NULL)
+ {
+ gsymbol->language = language_java;
+ gsymbol->language_specific.cplus_specific.demangled_name =
+ obsavestring (demangled, strlen (demangled), obstack);
+ xfree (demangled);
+ }
+ else
+ {
+ gsymbol->language_specific.cplus_specific.demangled_name = NULL;
+ }
+ }
+#if 0
+ /* OBSOLETE if (demangled == NULL */
+ /* OBSOLETE && (gsymbol->language == language_chill */
+ /* OBSOLETE || gsymbol->language == language_auto)) */
+ /* OBSOLETE { */
+ /* OBSOLETE demangled = */
+ /* OBSOLETE chill_demangle (gsymbol->name); */
+ /* OBSOLETE if (demangled != NULL) */
+ /* OBSOLETE { */
+ /* OBSOLETE gsymbol->language = language_chill; */
+ /* OBSOLETE gsymbol->language_specific.chill_specific.demangled_name = */
+ /* OBSOLETE obsavestring (demangled, strlen (demangled), obstack); */
+ /* OBSOLETE xfree (demangled); */
+ /* OBSOLETE } */
+ /* OBSOLETE else */
+ /* OBSOLETE { */
+ /* OBSOLETE gsymbol->language_specific.chill_specific.demangled_name = NULL; */
+ /* OBSOLETE } */
+ /* OBSOLETE } */
+#endif
+}
+
+/* Return the demangled name for a symbol based on the language for
+ that symbol. If no demangled name exists, return NULL. */
+char *
+symbol_demangled_name (struct general_symbol_info *gsymbol)
+{
+ if (gsymbol->language == language_cplus
+ || gsymbol->language == language_java)
+ return gsymbol->language_specific.cplus_specific.demangled_name;
+
+ else if (gsymbol->language == language_objc)
+ return gsymbol->language_specific.objc_specific.demangled_name;
+
+ else
+ return NULL;
+
+ /* OBSOLETE (SYMBOL_LANGUAGE (symbol) == language_chill */
+ /* OBSOLETE ? SYMBOL_CHILL_DEMANGLED_NAME (symbol) */
+}
+
+/* Initialize the structure fields to zero values. */
+void
+init_sal (struct symtab_and_line *sal)
+{
+ sal->symtab = 0;
+ sal->section = 0;
+ sal->line = 0;
+ sal->pc = 0;
+ sal->end = 0;
+}
\f
{
register struct partial_symtab *pst;
register struct objfile *objfile;
+ struct minimal_symbol *msymbol;
+
+ /* If we know that this is not a text address, return failure. This is
+ necessary because we loop based on texthigh and textlow, which do
+ not include the data ranges. */
+ msymbol = lookup_minimal_symbol_by_pc_section (pc, section);
+ if (msymbol
+ && (msymbol->type == mst_data
+ || msymbol->type == mst_bss
+ || msymbol->type == mst_abs
+ || msymbol->type == mst_file_data
+ || msymbol->type == mst_file_bss))
+ return NULL;
ALL_PSYMTABS (objfile, pst)
{
if (pc >= pst->textlow && pc < pst->texthigh)
{
- struct minimal_symbol *msymbol;
struct partial_symtab *tpst;
/* An objfile that has its functions reordered might have
section == 0) /* can't validate section this way */
return (pst);
- msymbol = lookup_minimal_symbol_by_pc_section (pc, section);
if (msymbol == NULL)
return (pst);
const namespace_enum namespace, int *is_a_field_of_this,
struct symtab **symtab)
{
- char *modified_name = NULL;
- char *modified_name2 = NULL;
+ char *demangled_name = NULL;
+ const char *modified_name = NULL;
+ const char *mangled_name = NULL;
int needtofreename = 0;
struct symbol *returnval;
+ modified_name = name;
+
+ /* If we are using C++ language, demangle the name before doing a lookup, so
+ we can always binary search. */
+ if (current_language->la_language == language_cplus)
+ {
+ demangled_name = cplus_demangle (name, DMGL_ANSI | DMGL_PARAMS);
+ if (demangled_name)
+ {
+ mangled_name = name;
+ modified_name = demangled_name;
+ needtofreename = 1;
+ }
+ }
+
if (case_sensitivity == case_sensitive_off)
{
char *copy;
copy[len] = 0;
modified_name = copy;
}
- else
- modified_name = (char *) name;
- /* If we are using C++ language, demangle the name before doing a lookup, so
- we can always binary search. */
- if (current_language->la_language == language_cplus)
- {
- modified_name2 = cplus_demangle (modified_name, DMGL_ANSI | DMGL_PARAMS);
- if (modified_name2)
- {
- modified_name = modified_name2;
- needtofreename = 1;
- }
- }
-
- returnval = lookup_symbol_aux (modified_name, block, namespace,
- is_a_field_of_this, symtab);
+ returnval = lookup_symbol_aux (modified_name, mangled_name, block,
+ namespace, is_a_field_of_this, symtab);
if (needtofreename)
- xfree (modified_name2);
+ xfree (demangled_name);
return returnval;
}
static struct symbol *
-lookup_symbol_aux (const char *name, const struct block *block,
- const namespace_enum namespace, int *is_a_field_of_this,
- struct symtab **symtab)
+lookup_symbol_aux (const char *name, const char *mangled_name,
+ const struct block *block, const namespace_enum namespace,
+ int *is_a_field_of_this, struct symtab **symtab)
{
- register struct symbol *sym;
- register struct symtab *s = NULL;
- register struct partial_symtab *ps;
- register struct blockvector *bv;
- register struct objfile *objfile = NULL;
- register struct block *b;
- register struct minimal_symbol *msymbol;
-
+ struct symbol *sym;
+ struct symtab *s = NULL;
+ struct blockvector *bv;
+ struct minimal_symbol *msymbol;
/* Search specified block and its superiors. */
- while (block != 0)
- {
- sym = lookup_block_symbol (block, name, namespace);
- if (sym)
- {
- block_found = block;
- if (symtab != NULL)
- {
- /* Search the list of symtabs for one which contains the
- address of the start of this block. */
- ALL_SYMTABS (objfile, s)
- {
- bv = BLOCKVECTOR (s);
- b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
- if (BLOCK_START (b) <= BLOCK_START (block)
- && BLOCK_END (b) > BLOCK_START (block))
- goto found;
- }
- found:
- *symtab = s;
- }
+ sym = lookup_symbol_aux_local (name, mangled_name, block, namespace,
+ symtab);
+ if (sym != NULL)
+ return sym;
- return fixup_symbol_section (sym, objfile);
- }
- block = BLOCK_SUPERBLOCK (block);
- }
+#if 0
+ /* NOTE: carlton/2002-11-05: At the time that this code was
+ #ifdeffed out, the value of 'block' was always NULL at this
+ point, hence the bemused comments below. */
/* FIXME: this code is never executed--block is always NULL at this
point. What is it trying to do, anyway? We already should have
if (BLOCK_START (b) <= BLOCK_START (block)
&& BLOCK_END (b) > BLOCK_START (block))
{
- sym = lookup_block_symbol (b, name, VAR_NAMESPACE);
+ sym = lookup_block_symbol (b, name, mangled_name, VAR_NAMESPACE);
if (sym)
{
block_found = b;
}
}
}
-
+#endif /* 0 */
/* C++: If requested to do so by the caller,
check to see if NAME is a field of `this'. */
of the desired name as a global, then do psymtab-to-symtab
conversion on the fly and return the found symbol. */
- ALL_SYMTABS (objfile, s)
- {
- bv = BLOCKVECTOR (s);
- block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
- sym = lookup_block_symbol (block, name, namespace);
- if (sym)
- {
- block_found = block;
- if (symtab != NULL)
- *symtab = s;
- return fixup_symbol_section (sym, objfile);
- }
- }
+ sym = lookup_symbol_aux_symtabs (GLOBAL_BLOCK, name, mangled_name,
+ namespace, symtab);
+ if (sym != NULL)
+ return sym;
#ifndef HPUXHPPA
/* This is a function which has a symtab for its address. */
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
- sym = lookup_block_symbol (block, SYMBOL_NAME (msymbol),
- namespace);
+
+ /* This call used to pass `SYMBOL_NAME (msymbol)' as the
+ `name' argument to lookup_block_symbol. But the name
+ of a minimal symbol is always mangled, so that seems
+ to be clearly the wrong thing to pass as the
+ unmangled name. */
+ sym = lookup_block_symbol (block, name, mangled_name, namespace);
/* We kept static functions in minimal symbol table as well as
in static scope. We want to find them in the symbol table. */
if (!sym)
{
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
- sym = lookup_block_symbol (block, SYMBOL_NAME (msymbol),
- namespace);
+ sym = lookup_block_symbol (block, name,
+ mangled_name, namespace);
}
/* sym == 0 if symbol was found in the minimal symbol table
if (symtab != NULL)
*symtab = s;
- return fixup_symbol_section (sym, objfile);
+ return fixup_symbol_section (sym, s->objfile);
}
else if (MSYMBOL_TYPE (msymbol) != mst_text
&& MSYMBOL_TYPE (msymbol) != mst_file_text
{
/* This is a mangled variable, look it up by its
mangled name. */
- return lookup_symbol_aux (SYMBOL_NAME (msymbol), block,
+ return lookup_symbol_aux (SYMBOL_NAME (msymbol), mangled_name, NULL,
namespace, is_a_field_of_this, symtab);
}
/* There are no debug symbols for this file, or we are looking
#endif
- ALL_PSYMTABS (objfile, ps)
- {
- if (!ps->readin && lookup_partial_symbol (ps, name, 1, namespace))
- {
- s = PSYMTAB_TO_SYMTAB (ps);
- bv = BLOCKVECTOR (s);
- block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
- sym = lookup_block_symbol (block, name, namespace);
- if (!sym)
- {
- /* This shouldn't be necessary, but as a last resort
- * try looking in the statics even though the psymtab
- * claimed the symbol was global. It's possible that
- * the psymtab gets it wrong in some cases.
- */
- block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
- sym = lookup_block_symbol (block, name, namespace);
- if (!sym)
- error ("Internal: global symbol `%s' found in %s psymtab but not in symtab.\n\
-%s may be an inlined function, or may be a template function\n\
-(if a template, try specifying an instantiation: %s<type>).",
- name, ps->filename, name, name);
- }
- if (symtab != NULL)
- *symtab = s;
- return fixup_symbol_section (sym, objfile);
- }
- }
+ sym = lookup_symbol_aux_psymtabs (GLOBAL_BLOCK, name, mangled_name,
+ namespace, symtab);
+ if (sym != NULL)
+ return sym;
- /* Now search all static file-level symbols.
- Not strictly correct, but more useful than an error.
- Do the symtabs first, then check the psymtabs.
- If a psymtab indicates the existence
- of the desired name as a file-level static, then do psymtab-to-symtab
+ /* Now search all static file-level symbols. Not strictly correct,
+ but more useful than an error. Do the symtabs first, then check
+ the psymtabs. If a psymtab indicates the existence of the
+ desired name as a file-level static, then do psymtab-to-symtab
conversion on the fly and return the found symbol. */
- ALL_SYMTABS (objfile, s)
- {
- bv = BLOCKVECTOR (s);
- block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
- sym = lookup_block_symbol (block, name, namespace);
- if (sym)
- {
- block_found = block;
- if (symtab != NULL)
- *symtab = s;
- return fixup_symbol_section (sym, objfile);
- }
- }
-
- ALL_PSYMTABS (objfile, ps)
- {
- if (!ps->readin && lookup_partial_symbol (ps, name, 0, namespace))
- {
- s = PSYMTAB_TO_SYMTAB (ps);
- bv = BLOCKVECTOR (s);
- block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
- sym = lookup_block_symbol (block, name, namespace);
- if (!sym)
- {
- /* This shouldn't be necessary, but as a last resort
- * try looking in the globals even though the psymtab
- * claimed the symbol was static. It's possible that
- * the psymtab gets it wrong in some cases.
- */
- block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
- sym = lookup_block_symbol (block, name, namespace);
- if (!sym)
- error ("Internal: static symbol `%s' found in %s psymtab but not in symtab.\n\
-%s may be an inlined function, or may be a template function\n\
-(if a template, try specifying an instantiation: %s<type>).",
- name, ps->filename, name, name);
- }
- if (symtab != NULL)
- *symtab = s;
- return fixup_symbol_section (sym, objfile);
- }
- }
+ sym = lookup_symbol_aux_symtabs (STATIC_BLOCK, name, mangled_name,
+ namespace, symtab);
+ if (sym != NULL)
+ return sym;
+
+ sym = lookup_symbol_aux_psymtabs (STATIC_BLOCK, name, mangled_name,
+ namespace, symtab);
+ if (sym != NULL)
+ return sym;
#ifdef HPUXHPPA
{
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
- sym = lookup_block_symbol (block, SYMBOL_NAME (msymbol),
- namespace);
+ /* This call used to pass `SYMBOL_NAME (msymbol)' as the
+ `name' argument to lookup_block_symbol. But the name
+ of a minimal symbol is always mangled, so that seems
+ to be clearly the wrong thing to pass as the
+ unmangled name. */
+ sym = lookup_block_symbol (block, name, mangled_name, namespace);
/* We kept static functions in minimal symbol table as well as
in static scope. We want to find them in the symbol table. */
if (!sym)
{
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
- sym = lookup_block_symbol (block, SYMBOL_NAME (msymbol),
- namespace);
+ sym = lookup_block_symbol (block, name,
+ mangled_name, namespace);
}
/* If we found one, return it */
if (sym)
&& MSYMBOL_TYPE (msymbol) != mst_file_text
&& !STREQ (name, SYMBOL_NAME (msymbol)))
{
- return lookup_symbol (SYMBOL_NAME (msymbol), block,
- namespace, is_a_field_of_this, symtab);
+ return lookup_symbol_aux (SYMBOL_NAME (msymbol), mangled_name,
+ NULL, namespace, is_a_field_of_this,
+ symtab);
}
}
}
if (symtab != NULL)
*symtab = NULL;
- return 0;
+ return NULL;
+}
+
+/* Check to see if the symbol is defined in BLOCK or its
+ superiors. */
+
+static struct symbol *
+lookup_symbol_aux_local (const char *name, const char *mangled_name,
+ const struct block *block,
+ const namespace_enum namespace,
+ struct symtab **symtab)
+{
+ struct symbol *sym;
+ struct objfile *objfile = NULL;
+ struct blockvector *bv;
+ struct block *b;
+ struct symtab *s = NULL;
+
+ while (block != 0)
+ {
+ sym = lookup_block_symbol (block, name, mangled_name, namespace);
+ if (sym)
+ {
+ block_found = block;
+ if (symtab != NULL)
+ {
+ /* Search the list of symtabs for one which contains the
+ address of the start of this block. */
+ ALL_SYMTABS (objfile, s)
+ {
+ bv = BLOCKVECTOR (s);
+ b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ if (BLOCK_START (b) <= BLOCK_START (block)
+ && BLOCK_END (b) > BLOCK_START (block))
+ goto found;
+ }
+ found:
+ *symtab = s;
+ }
+
+ return fixup_symbol_section (sym, objfile);
+ }
+ block = BLOCK_SUPERBLOCK (block);
+ }
+
+ return NULL;
+}
+
+/* Check to see if the symbol is defined in one of the symtabs.
+ BLOCK_INDEX should be either GLOBAL_BLOCK or STATIC_BLOCK,
+ depending on whether or not we want to search global symbols or
+ static symbols. */
+
+static struct symbol *
+lookup_symbol_aux_symtabs (int block_index,
+ const char *name, const char *mangled_name,
+ const namespace_enum namespace,
+ struct symtab **symtab)
+{
+ struct symbol *sym;
+ struct objfile *objfile;
+ struct blockvector *bv;
+ const struct block *block;
+ struct symtab *s;
+
+ ALL_SYMTABS (objfile, s)
+ {
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, block_index);
+ sym = lookup_block_symbol (block, name, mangled_name, namespace);
+ if (sym)
+ {
+ block_found = block;
+ if (symtab != NULL)
+ *symtab = s;
+ return fixup_symbol_section (sym, objfile);
+ }
+ }
+
+ return NULL;
+}
+
+/* Check to see if the symbol is defined in one of the partial
+ symtabs. BLOCK_INDEX should be either GLOBAL_BLOCK or
+ STATIC_BLOCK, depending on whether or not we want to search global
+ symbols or static symbols. */
+
+static struct symbol *
+lookup_symbol_aux_psymtabs (int block_index, const char *name,
+ const char *mangled_name,
+ const namespace_enum namespace,
+ struct symtab **symtab)
+{
+ struct symbol *sym;
+ struct objfile *objfile;
+ struct blockvector *bv;
+ const struct block *block;
+ struct partial_symtab *ps;
+ struct symtab *s;
+ const int psymtab_index = (block_index == GLOBAL_BLOCK ? 1 : 0);
+
+ ALL_PSYMTABS (objfile, ps)
+ {
+ if (!ps->readin
+ && lookup_partial_symbol (ps, name, psymtab_index, namespace))
+ {
+ s = PSYMTAB_TO_SYMTAB (ps);
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, block_index);
+ sym = lookup_block_symbol (block, name, mangled_name, namespace);
+ if (!sym)
+ {
+ /* This shouldn't be necessary, but as a last resort try
+ looking in the statics even though the psymtab claimed
+ the symbol was global, or vice-versa. It's possible
+ that the psymtab gets it wrong in some cases. */
+
+ /* FIXME: carlton/2002-09-30: Should we really do that?
+ If that happens, isn't it likely to be a GDB error, in
+ which case we should fix the GDB error rather than
+ silently dealing with it here? So I'd vote for
+ removing the check for the symbol in the other
+ block. */
+ block = BLOCKVECTOR_BLOCK (bv,
+ block_index == GLOBAL_BLOCK ?
+ STATIC_BLOCK : GLOBAL_BLOCK);
+ sym = lookup_block_symbol (block, name, mangled_name, namespace);
+ if (!sym)
+ error ("Internal: %s symbol `%s' found in %s psymtab but not in symtab.\n%s may be an inlined function, or may be a template function\n(if a template, try specifying an instantiation: %s<type>).",
+ block_index == GLOBAL_BLOCK ? "global" : "static",
+ name, ps->filename, name, name);
+ }
+ if (symtab != NULL)
+ *symtab = s;
+ return fixup_symbol_section (sym, objfile);
+ }
+ }
+
+ return NULL;
}
-
+
/* Look, in partial_symtab PST, for symbol NAME. Check the global
symbols if GLOBAL, the static symbols if not */
{
center = bottom + (top - bottom) / 2;
if (!(center < top))
- abort ();
+ internal_error (__FILE__, __LINE__, "failed internal consistency check");
if (!do_linear_search
&& (SYMBOL_LANGUAGE (*center) == language_java))
{
do_linear_search = 1;
}
- if (STRCMP (SYMBOL_SOURCE_NAME (*center), name) >= 0)
+ if (strcmp (SYMBOL_SOURCE_NAME (*center), name) >= 0)
{
top = center;
}
}
}
if (!(top == bottom))
- abort ();
+ internal_error (__FILE__, __LINE__, "failed internal consistency check");
/* djb - 2000-06-03 - Use SYMBOL_MATCHES_NAME, not a strcmp, so
we don't have to force a linear search on C++. Probably holds true
{
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
- sym = lookup_block_symbol (block, name, STRUCT_NAMESPACE);
+ sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE);
if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
{
return SYMBOL_TYPE (sym);
s = PSYMTAB_TO_SYMTAB (ps);
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
- sym = lookup_block_symbol (block, name, STRUCT_NAMESPACE);
+ sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE);
if (!sym)
{
/* This shouldn't be necessary, but as a last resort
* the psymtab gets it wrong in some cases.
*/
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
- sym = lookup_block_symbol (block, name, STRUCT_NAMESPACE);
+ sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE);
if (!sym)
error ("Internal: global symbol `%s' found in %s psymtab but not in symtab.\n\
%s may be an inlined function, or may be a template function\n\
{
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
- sym = lookup_block_symbol (block, name, STRUCT_NAMESPACE);
+ sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE);
if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
{
return SYMBOL_TYPE (sym);
s = PSYMTAB_TO_SYMTAB (ps);
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
- sym = lookup_block_symbol (block, name, STRUCT_NAMESPACE);
+ sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE);
if (!sym)
{
/* This shouldn't be necessary, but as a last resort
* the psymtab gets it wrong in some cases.
*/
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
- sym = lookup_block_symbol (block, name, STRUCT_NAMESPACE);
+ sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE);
if (!sym)
error ("Internal: static symbol `%s' found in %s psymtab but not in symtab.\n\
%s may be an inlined function, or may be a template function\n\
ALL_PSYMTABS (objfile, pst)
{
- if (lookup_partial_symbol (pst, "main", 1, VAR_NAMESPACE))
+ if (lookup_partial_symbol (pst, main_name (), 1, VAR_NAMESPACE))
{
return (pst);
}
binary search terminates, we drop through and do a straight linear
search on the symbols. Each symbol which is marked as being a C++
symbol (language_cplus set) has both the encoded and non-encoded names
- tested for a match. */
+ tested for a match.
+
+ If MANGLED_NAME is non-NULL, verify that any symbol we find has this
+ particular mangled name.
+*/
struct symbol *
lookup_block_symbol (register const struct block *block, const char *name,
+ const char *mangled_name,
const namespace_enum namespace)
{
register int bot, top, inc;
register struct symbol *sym_found = NULL;
register int do_linear_search = 1;
+ if (BLOCK_HASHTABLE (block))
+ {
+ unsigned int hash_index;
+ hash_index = msymbol_hash_iw (name);
+ hash_index = hash_index % BLOCK_BUCKETS (block);
+ for (sym = BLOCK_BUCKET (block, hash_index); sym; sym = sym->hash_next)
+ {
+ if (SYMBOL_NAMESPACE (sym) == namespace
+ && (mangled_name
+ ? strcmp (SYMBOL_NAME (sym), mangled_name) == 0
+ : SYMBOL_MATCHES_NAME (sym, name)))
+ return sym;
+ }
+ return NULL;
+ }
+
/* If the blocks's symbols were sorted, start with a binary search. */
if (BLOCK_SHOULD_SORT (block))
{
top = inc;
}
- else if (STRCMP (SYMBOL_SOURCE_NAME (sym), name) < 0)
+ else if (strcmp (SYMBOL_SOURCE_NAME (sym), name) < 0)
{
bot = inc;
}
return the first one; I believe it is now impossible for us
to encounter two symbols with the same name and namespace
here, because blocks containing argument symbols are no
- longer sorted. */
+ longer sorted. The exception is for C++, where multiple functions
+ (cloned constructors / destructors, in particular) can have
+ the same demangled name. So if we have a particular
+ mangled name to match, try to do so. */
top = BLOCK_NSYMS (block);
while (bot < top)
{
sym = BLOCK_SYM (block, bot);
- if (SYMBOL_MATCHES_NAME (sym, name))
- return sym;
+ if (SYMBOL_NAMESPACE (sym) == namespace
+ && (mangled_name
+ ? strcmp (SYMBOL_NAME (sym), mangled_name) == 0
+ : SYMBOL_MATCHES_NAME (sym, name)))
+ {
+ return sym;
+ }
+ if (SYMBOL_SOURCE_NAME (sym)[0] > name[0])
+ {
+ break;
+ }
bot++;
}
}
/* Here if block isn't sorted, or we fail to find a match during the
binary search above. If during the binary search above, we find a
- symbol which is a C++ symbol, then we have re-enabled the linear
+ symbol which is a Java symbol, then we have re-enabled the linear
search flag which was reset when starting the binary search.
This loop is equivalent to the loop above, but hacked greatly for speed.
while (bot < top)
{
sym = BLOCK_SYM (block, bot);
- if (SYMBOL_NAMESPACE (sym) == namespace &&
- SYMBOL_MATCHES_NAME (sym, name))
+ if (SYMBOL_NAMESPACE (sym) == namespace
+ && (mangled_name
+ ? strcmp (SYMBOL_NAME (sym), mangled_name) == 0
+ : SYMBOL_MATCHES_NAME (sym, name)))
{
/* If SYM has aliases, then use any alias that is active
at the current PC. If no alias is active at the current
register struct partial_symtab *ps;
register struct objfile *objfile;
CORE_ADDR distance = 0;
+ struct minimal_symbol *msymbol;
+
+ /* 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
+ we call find_pc_sect_psymtab which has a similar restriction based
+ on the partial_symtab's texthigh and textlow. */
+ msymbol = lookup_minimal_symbol_by_pc_section (pc, section);
+ if (msymbol
+ && (msymbol->type == mst_data
+ || msymbol->type == mst_bss
+ || msymbol->type == mst_abs
+ || msymbol->type == mst_file_data
+ || msymbol->type == mst_file_bss))
+ return NULL;
/* Search all symtabs for the one whose file contains our address, and which
is the smallest of all the ones containing the address. This is designed
if (section != 0)
{
int i;
+ struct symbol *sym = NULL;
- for (i = 0; i < b->nsyms; i++)
+ ALL_BLOCK_SYMBOLS (b, i, sym)
{
- fixup_symbol_section (b->sym[i], objfile);
- if (section == SYMBOL_BFD_SECTION (b->sym[i]))
+ fixup_symbol_section (sym, objfile);
+ if (section == SYMBOL_BFD_SECTION (sym))
break;
}
- if (i >= b->nsyms)
+ if ((i >= BLOCK_BUCKETS (b)) && (sym == NULL))
continue; /* no symbol in this symtab matches section */
}
distance = BLOCK_END (b) - BLOCK_START (b);
}
\f
-#if 0
-
-/* Find the closest symbol value (of any sort -- function or variable)
- for a given address value. Slow but complete. (currently unused,
- mainly because it is too slow. We could fix it if each symtab and
- psymtab had contained in it the addresses ranges of each of its
- sections, which also would be required to make things like "info
- line *0x2345" cause psymtabs to be converted to symtabs). */
-
-struct symbol *
-find_addr_symbol (CORE_ADDR addr, struct symtab **symtabp, CORE_ADDR *symaddrp)
-{
- struct symtab *symtab, *best_symtab;
- struct objfile *objfile;
- register int bot, top;
- register struct symbol *sym;
- register CORE_ADDR sym_addr;
- struct block *block;
- int blocknum;
-
- /* Info on best symbol seen so far */
-
- register CORE_ADDR best_sym_addr = 0;
- struct symbol *best_sym = 0;
-
- /* FIXME -- we should pull in all the psymtabs, too! */
- ALL_SYMTABS (objfile, symtab)
- {
- /* Search the global and static blocks in this symtab for
- the closest symbol-address to the desired address. */
-
- for (blocknum = GLOBAL_BLOCK; blocknum <= STATIC_BLOCK; blocknum++)
- {
- QUIT;
- block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), blocknum);
- top = BLOCK_NSYMS (block);
- for (bot = 0; bot < top; bot++)
- {
- sym = BLOCK_SYM (block, bot);
- switch (SYMBOL_CLASS (sym))
- {
- case LOC_STATIC:
- case LOC_LABEL:
- sym_addr = SYMBOL_VALUE_ADDRESS (sym);
- break;
-
- case LOC_INDIRECT:
- sym_addr = SYMBOL_VALUE_ADDRESS (sym);
- /* An indirect symbol really lives at *sym_addr,
- * so an indirection needs to be done.
- * However, I am leaving this commented out because it's
- * expensive, and it's possible that symbolization
- * could be done without an active process (in
- * case this read_memory will fail). RT
- sym_addr = read_memory_unsigned_integer
- (sym_addr, TARGET_PTR_BIT / TARGET_CHAR_BIT);
- */
- break;
-
- case LOC_BLOCK:
- sym_addr = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
- break;
-
- default:
- continue;
- }
-
- if (sym_addr <= addr)
- if (sym_addr > best_sym_addr)
- {
- /* Quit if we found an exact match. */
- best_sym = sym;
- best_sym_addr = sym_addr;
- best_symtab = symtab;
- if (sym_addr == addr)
- goto done;
- }
- }
- }
- }
-
-done:
- if (symtabp)
- *symtabp = best_symtab;
- if (symaddrp)
- *symaddrp = best_sym_addr;
- return best_sym;
-}
-#endif /* 0 */
-
/* Find the source file and line number for a given PC value and SECTION.
Return a structure containing a symtab pointer, a line number,
and a pc range for the entire source line.
But what we want is the statement containing the instruction.
Fudge the pc to make sure we get that. */
- INIT_SAL (&val); /* initialize to zeroes */
+ init_sal (&val); /* initialize to zeroes */
+
+ /* It's tempting to assume that, if we can't find debugging info for
+ any function enclosing PC, that we shouldn't search for line
+ number info, either. However, GAS can emit line number info for
+ assembly files --- very helpful when debugging hand-written
+ assembly code. In such a case, we'd have no debug info for the
+ function, but we would have line info. */
if (notcurrent)
pc -= 1;
{
best = prev;
best_symtab = s;
- /* If another line is in the linetable, and its PC is closer
- than the best_end we currently have, take it as best_end. */
- if (i < len && (best_end == 0 || best_end > item->pc))
- best_end = item->pc;
+
+ /* Discard BEST_END if it's before the PC of the current BEST. */
+ if (best_end <= best->pc)
+ best_end = 0;
}
+
+ /* If another line (denoted by ITEM) is in the linetable and its
+ PC is after BEST's PC, but before the current BEST_END, then
+ use ITEM's PC as the new best_end. */
+ if (best && i < len && item->pc > best->pc
+ && (best_end == 0 || best_end > item->pc))
+ best_end = item->pc;
}
if (!best_symtab)
val.end = alt->pc;
}
}
+ else if (best->line == 0)
+ {
+ /* If our best fit is in a range of PC's for which no line
+ number info is available (line number is zero) then we didn't
+ find any valid line information. */
+ val.pc = pc;
+ }
else
{
val.symtab = best_symtab;
return p;
}
- switch (*p)
- {
- case '!':
- case '=':
- case '*':
- case '/':
- case '%':
- case '^':
- if (p[1] == '=')
- *end = p + 2;
- else
+ while (*p)
+ switch (*p)
+ {
+ case '\\': /* regexp quoting */
+ if (p[1] == '*')
+ {
+ if (p[2] == '=') /* 'operator\*=' */
+ *end = p + 3;
+ else /* 'operator\*' */
+ *end = p + 2;
+ return p;
+ }
+ else if (p[1] == '[')
+ {
+ if (p[2] == ']')
+ error ("mismatched quoting on brackets, try 'operator\\[\\]'");
+ else if (p[2] == '\\' && p[3] == ']')
+ {
+ *end = p + 4; /* 'operator\[\]' */
+ return p;
+ }
+ else
+ error ("nothing is allowed between '[' and ']'");
+ }
+ else
+ {
+ /* Gratuitous qoute: skip it and move on. */
+ p++;
+ continue;
+ }
+ break;
+ case '!':
+ case '=':
+ case '*':
+ case '/':
+ case '%':
+ case '^':
+ if (p[1] == '=')
+ *end = p + 2;
+ else
+ *end = p + 1;
+ return p;
+ case '<':
+ case '>':
+ case '+':
+ case '-':
+ case '&':
+ case '|':
+ if (p[0] == '-' && p[1] == '>')
+ {
+ /* Struct pointer member operator 'operator->'. */
+ if (p[2] == '*')
+ {
+ *end = p + 3; /* 'operator->*' */
+ return p;
+ }
+ else if (p[2] == '\\')
+ {
+ *end = p + 4; /* Hopefully 'operator->\*' */
+ return p;
+ }
+ else
+ {
+ *end = p + 2; /* 'operator->' */
+ return p;
+ }
+ }
+ if (p[1] == '=' || p[1] == p[0])
+ *end = p + 2;
+ else
+ *end = p + 1;
+ return p;
+ case '~':
+ case ',':
*end = p + 1;
- return p;
- case '<':
- case '>':
- case '+':
- case '-':
- case '&':
- case '|':
- if (p[1] == '=' || p[1] == p[0])
+ return p;
+ case '(':
+ if (p[1] != ')')
+ error ("`operator ()' must be specified without whitespace in `()'");
*end = p + 2;
- else
- *end = p + 1;
- return p;
- case '~':
- case ',':
- *end = p + 1;
- return p;
- case '(':
- if (p[1] != ')')
- error ("`operator ()' must be specified without whitespace in `()'");
- *end = p + 2;
- return p;
- case '?':
- if (p[1] != ':')
- error ("`operator ?:' must be specified without whitespace in `?:'");
- *end = p + 2;
- return p;
- case '[':
- if (p[1] != ']')
- error ("`operator []' must be specified without whitespace in `[]'");
- *end = p + 2;
- return p;
- default:
- error ("`operator %s' not supported", p);
- break;
- }
+ return p;
+ case '?':
+ if (p[1] != ':')
+ error ("`operator ?:' must be specified without whitespace in `?:'");
+ *end = p + 2;
+ return p;
+ case '[':
+ if (p[1] != ']')
+ error ("`operator []' must be specified without whitespace in `[]'");
+ *end = p + 2;
+ return p;
+ default:
+ error ("`operator %s' not supported", p);
+ break;
+ }
+
*end = "";
return *end;
}
\f
-/* 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. */
-static void
-output_source_filename (char *name, int *first)
+/* If FILE is not already in the table of files, 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. */
+static int
+filename_seen (const char *file, int add, int *first)
{
- /* Table of files printed so far. Since a single source file can
- result in several partial symbol tables, we need to avoid printing
- it more than once. Note: if some of the psymtabs are read in and
- some are not, it gets printed both under "Source files for which
- symbols have been read" and "Source files for which symbols will
- be read in on demand". I consider this a reasonable way to deal
- with the situation. I'm not sure whether this can also happen for
- symtabs; it doesn't hurt to check. */
- static char **tab = NULL;
+ /* 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;
-
- char **p;
+ const char **p;
if (*first)
{
if (tab == NULL)
- tab = (char **) xmalloc (tab_alloc_size * sizeof (*tab));
+ tab = (const char **) xmalloc (tab_alloc_size * sizeof (*tab));
tab_cur_size = 0;
}
- /* Is NAME in tab? */
+ /* Is FILE in tab? */
for (p = tab; p < tab + tab_cur_size; p++)
- if (STREQ (*p, name))
- /* Yes; don't print it again. */
- return;
- /* No; add it to tab. */
- if (tab_cur_size == tab_alloc_size)
+ if (strcmp (*p, file) == 0)
+ return 1;
+
+ /* No; maybe add it to tab. */
+ if (add)
{
- tab_alloc_size *= 2;
- tab = (char **) xrealloc ((char *) tab, tab_alloc_size * sizeof (*tab));
+ 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;
}
- tab[tab_cur_size++] = name;
+ return 0;
+}
+
+/* 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. */
+static void
+output_source_filename (char *name, int *first)
+{
+ /* Since a single source file can result in several partial symbol
+ tables, we need to avoid printing it more than once. Note: if
+ some of the psymtabs are read in and some are not, it gets
+ printed both under "Source files for which symbols have been
+ read" and "Source files for which symbols will be read in on
+ demand". I consider this a reasonable way to deal with the
+ situation. I'm not sure whether this can also happen for
+ symtabs; it doesn't hurt to check. */
+
+ /* Was NAME already seen? */
+ if (filename_seen (name, 1, first))
+ {
+ /* Yes; don't print it again. */
+ return;
+ }
+ /* No; print it and reset *FIRST. */
if (*first)
{
*first = 0;
{
for (i = 0; i < nfiles; i++)
{
- if (strcmp (files[i], basename (file)) == 0)
+ if (strcmp (files[i], lbasename (file)) == 0)
return 1;
}
}
return make_cleanup (do_free_search_symbols_cleanup, symbols);
}
+/* Helper function for sort_search_symbols and qsort. Can only
+ sort symbols, not minimal symbols. */
+static int
+compare_search_syms (const void *sa, const void *sb)
+{
+ struct symbol_search **sym_a = (struct symbol_search **) sa;
+ struct symbol_search **sym_b = (struct symbol_search **) sb;
+
+ return strcmp (SYMBOL_SOURCE_NAME ((*sym_a)->symbol),
+ SYMBOL_SOURCE_NAME ((*sym_b)->symbol));
+}
+
+/* Sort the ``nfound'' symbols in the list after prevtail. Leave
+ prevtail where it is, but update its next pointer to point to
+ the first of the sorted symbols. */
+static struct symbol_search *
+sort_search_symbols (struct symbol_search *prevtail, int nfound)
+{
+ struct symbol_search **symbols, *symp, *old_next;
+ int i;
+
+ symbols = (struct symbol_search **) xmalloc (sizeof (struct symbol_search *)
+ * nfound);
+ symp = prevtail->next;
+ for (i = 0; i < nfound; i++)
+ {
+ symbols[i] = symp;
+ symp = symp->next;
+ }
+ /* Generally NULL. */
+ old_next = symp;
+
+ qsort (symbols, nfound, sizeof (struct symbol_search *),
+ compare_search_syms);
+
+ symp = prevtail;
+ for (i = 0; i < nfound; i++)
+ {
+ symp->next = symbols[i];
+ symp = symp->next;
+ }
+ symp->next = old_next;
+
+ xfree (symbols);
+ return symp;
+}
/* Search the symbol table for matches to the regular expression REGEXP,
returning the results in *MATCHES.
and constants (enums)
free_search_symbols should be called when *MATCHES is no longer needed.
+
+ The results are sorted locally; each symtab's global and static blocks are
+ separately alphabetized.
*/
void
search_symbols (char *regexp, namespace_enum kind, int nfiles, char *files[],
struct symbol_search *tail;
struct cleanup *old_chain = NULL;
- if (kind < LABEL_NAMESPACE)
+ if (kind < VARIABLES_NAMESPACE)
error ("must search on specific namespace");
ourtype = types[(int) (kind - VARIABLES_NAMESPACE)];
/* If wrong number of spaces, fix it. */
if (fix >= 0)
{
- char *tmp = (char *) alloca (opend - opname + 10);
+ char *tmp = (char *) alloca (8 + fix + strlen (opname) + 1);
sprintf (tmp, "operator%.*s%s", fix, " ", opname);
regexp = tmp;
}
if (bv != prev_bv)
for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++)
{
+ struct symbol_search *prevtail = tail;
+ int nfound = 0;
b = BLOCKVECTOR_BLOCK (bv, i);
- /* Skip the sort if this block is always sorted. */
- if (!BLOCK_SHOULD_SORT (b))
- sort_block_syms (b);
- for (j = 0; j < BLOCK_NSYMS (b); j++)
+ ALL_BLOCK_SYMBOLS (b, j, sym)
{
QUIT;
- sym = BLOCK_SYM (b, j);
if (file_matches (s->filename, files, nfiles)
&& ((regexp == NULL || SYMBOL_MATCHES_REGEXP (sym))
&& ((kind == VARIABLES_NAMESPACE && SYMBOL_CLASS (sym) != LOC_TYPEDEF
psr->msymbol = NULL;
psr->next = NULL;
if (tail == NULL)
- {
- sr = psr;
- old_chain = make_cleanup_free_search_symbols (sr);
- }
+ sr = psr;
else
tail->next = psr;
tail = psr;
+ nfound ++;
+ }
+ }
+ if (nfound > 0)
+ {
+ if (prevtail == NULL)
+ {
+ struct symbol_search dummy;
+
+ dummy.next = sr;
+ tail = sort_search_symbols (&dummy, nfound);
+ sr = dummy.next;
+
+ old_chain = make_cleanup_free_search_symbols (sr);
}
+ else
+ tail = sort_search_symbols (prevtail, nfound);
}
}
prev_bv = bv;
printf_filtered (";\n");
}
- else
- {
-#if 0
- /* Tiemann says: "info methods was never implemented." */
- char *demangled_name;
- c_type_print_base (TYPE_FN_FIELD_TYPE (t, block),
- gdb_stdout, 0, 0);
- c_type_print_varspec_prefix (TYPE_FN_FIELD_TYPE (t, block),
- gdb_stdout, 0);
- if (TYPE_FN_FIELD_STUB (t, block))
- check_stub_method (TYPE_DOMAIN_TYPE (type), j, block);
- demangled_name =
- cplus_demangle (TYPE_FN_FIELD_PHYSNAME (t, block),
- DMGL_ANSI | DMGL_PARAMS);
- if (demangled_name == NULL)
- fprintf_filtered (stream, "<badly mangled name %s>",
- TYPE_FN_FIELD_PHYSNAME (t, block));
- else
- {
- fputs_filtered (demangled_name, stream);
- xfree (demangled_name);
- }
-#endif
- }
}
/* This help function for symtab_symbol_info() prints information
static void
print_msymbol_info (struct minimal_symbol *msymbol)
{
- printf_filtered (" %08lx %s\n",
- (unsigned long) SYMBOL_VALUE_ADDRESS (msymbol),
- SYMBOL_SOURCE_NAME (msymbol));
+ char *tmp;
+
+ if (TARGET_ADDR_BIT <= 32)
+ tmp = local_hex_string_custom (SYMBOL_VALUE_ADDRESS (msymbol)
+ & (CORE_ADDR) 0xffffffff,
+ "08l");
+ else
+ tmp = local_hex_string_custom (SYMBOL_VALUE_ADDRESS (msymbol),
+ "016l");
+ printf_filtered ("%s %s\n",
+ tmp, SYMBOL_SOURCE_NAME (msymbol));
}
/* This is the guts of the commands "info functions", "info types", and
symtab_symbol_info (regexp, TYPES_NAMESPACE, from_tty);
}
-#if 0
-/* Tiemann says: "info methods was never implemented." */
-static void
-methods_info (char *regexp)
-{
- symtab_symbol_info (regexp, METHODS_NAMESPACE, 0, from_tty);
-}
-#endif /* 0 */
-
/* Breakpoint all functions matching regular expression. */
-#ifdef UI_OUT
+
void
rbreak_command_wrapper (char *regexp, int from_tty)
{
rbreak_command (regexp, from_tty);
}
-#endif
+
static void
rbreak_command (char *regexp, int from_tty)
{
return;
}
- /* Clip any symbol names that we've already considered. (This is a
- time optimization) */
-
- for (i = 0; i < return_val_index; ++i)
- {
- if (STREQ (symname, return_val[i]))
- {
- return;
- }
- }
-
/* We have a match for a completion, so add SYMNAME to the current list
of matches. Note that the name is moved to freshly malloc'd space. */
strcat (new, symname);
}
- /* Recheck for duplicates if we intend to add a modified symbol. */
- if (word != sym_text)
- {
- for (i = 0; i < return_val_index; ++i)
- {
- if (STREQ (new, return_val[i]))
- {
- xfree (new);
- return;
- }
- }
- }
-
if (return_val_index + 3 > return_val_size)
{
newsize = (return_val_size *= 2) * sizeof (char *);
}
}
-/* Return a NULL terminated array of all symbols (regardless of class) which
- begin by matching TEXT. If the answer is no symbols, then the return value
- is an array which contains only a NULL pointer.
+/* Return a NULL terminated array of all symbols (regardless of class)
+ which begin by matching TEXT. If the answer is no symbols, then
+ the return value is an array which contains only a NULL pointer.
Problem: All of the symbols have to be copied because readline frees them.
I'm not going to worry about this; hopefully there won't be that many. */
else if (quote_found == '"')
/* A double-quoted string is never a symbol, nor does it make sense
to complete it any other way. */
- return NULL;
+ {
+ return_val = (char **) xmalloc (sizeof (char *));
+ return_val[0] = NULL;
+ return return_val;
+ }
else
{
/* It is not a quoted string. Break it based on the characters
/* Search upwards from currently selected frame (so that we can
complete on local vars. */
- for (b = get_selected_block (); b != NULL; b = BLOCK_SUPERBLOCK (b))
+ for (b = get_selected_block (0); b != NULL; b = BLOCK_SUPERBLOCK (b))
{
if (!BLOCK_SUPERBLOCK (b))
{
/* Also catch fields of types defined in this places which match our
text string. Only complete on types visible from current context. */
- for (i = 0; i < BLOCK_NSYMS (b); i++)
+ ALL_BLOCK_SYMBOLS (b, i, sym)
{
- sym = BLOCK_SYM (b, i);
COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
if (SYMBOL_CLASS (sym) == LOC_TYPEDEF)
{
{
QUIT;
b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
- for (i = 0; i < BLOCK_NSYMS (b); i++)
+ ALL_BLOCK_SYMBOLS (b, i, sym)
{
- sym = BLOCK_SYM (b, i);
COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
}
}
/* Don't do this block twice. */
if (b == surrounding_static_block)
continue;
- for (i = 0; i < BLOCK_NSYMS (b); i++)
+ ALL_BLOCK_SYMBOLS (b, i, sym)
{
- sym = BLOCK_SYM (b, i);
COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
}
}
return (return_val);
}
+/* Like make_symbol_completion_list, but returns a list of symbols
+ defined in a source file FILE. */
+
+char **
+make_file_symbol_completion_list (char *text, char *word, char *srcfile)
+{
+ register struct symbol *sym;
+ register struct symtab *s;
+ register struct block *b;
+ register int i;
+ /* The symbol we are completing on. Points in same buffer as text. */
+ char *sym_text;
+ /* Length of sym_text. */
+ int sym_text_len;
+
+ /* Now look for the symbol we are supposed to complete on.
+ FIXME: This should be language-specific. */
+ {
+ char *p;
+ char quote_found;
+ char *quote_pos = NULL;
+
+ /* First see if this is a quoted string. */
+ quote_found = '\0';
+ for (p = text; *p != '\0'; ++p)
+ {
+ if (quote_found != '\0')
+ {
+ if (*p == quote_found)
+ /* Found close quote. */
+ quote_found = '\0';
+ else if (*p == '\\' && p[1] == quote_found)
+ /* A backslash followed by the quote character
+ doesn't end the string. */
+ ++p;
+ }
+ else if (*p == '\'' || *p == '"')
+ {
+ quote_found = *p;
+ quote_pos = p;
+ }
+ }
+ if (quote_found == '\'')
+ /* A string within single quotes can be a symbol, so complete on it. */
+ sym_text = quote_pos + 1;
+ else if (quote_found == '"')
+ /* A double-quoted string is never a symbol, nor does it make sense
+ to complete it any other way. */
+ {
+ return_val = (char **) xmalloc (sizeof (char *));
+ return_val[0] = NULL;
+ return return_val;
+ }
+ else
+ {
+ /* It is not a quoted string. Break it based on the characters
+ which are in symbols. */
+ while (p > text)
+ {
+ if (isalnum (p[-1]) || p[-1] == '_' || p[-1] == '\0')
+ --p;
+ else
+ break;
+ }
+ sym_text = p;
+ }
+ }
+
+ sym_text_len = strlen (sym_text);
+
+ return_val_size = 10;
+ return_val_index = 0;
+ return_val = (char **) xmalloc ((return_val_size + 1) * sizeof (char *));
+ return_val[0] = NULL;
+
+ /* Find the symtab for SRCFILE (this loads it if it was not yet read
+ in). */
+ s = lookup_symtab (srcfile);
+ if (s == NULL)
+ {
+ /* 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. */
+
+ b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
+ ALL_BLOCK_SYMBOLS (b, i, sym)
+ {
+ COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
+ }
+
+ b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
+ ALL_BLOCK_SYMBOLS (b, i, sym)
+ {
+ COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
+ }
+
+ return (return_val);
+}
+
+/* A helper function for make_source_files_completion_list. It adds
+ another file name to a list of possible completions, growing the
+ list as necessary. */
+
+static void
+add_filename_to_list (const char *fname, char *text, char *word,
+ char ***list, int *list_used, int *list_alloced)
+{
+ char *new;
+ size_t fnlen = strlen (fname);
+
+ if (*list_used + 1 >= *list_alloced)
+ {
+ *list_alloced *= 2;
+ *list = (char **) xrealloc ((char *) *list,
+ *list_alloced * sizeof (char *));
+ }
+
+ if (word == text)
+ {
+ /* Return exactly fname. */
+ new = xmalloc (fnlen + 5);
+ strcpy (new, fname);
+ }
+ else if (word > text)
+ {
+ /* Return some portion of fname. */
+ new = xmalloc (fnlen + 5);
+ strcpy (new, fname + (word - text));
+ }
+ else
+ {
+ /* Return some of TEXT plus fname. */
+ new = xmalloc (fnlen + (text - word) + 5);
+ strncpy (new, word, text - word);
+ new[text - word] = '\0';
+ strcat (new, fname);
+ }
+ (*list)[*list_used] = new;
+ (*list)[++*list_used] = NULL;
+}
+
+static int
+not_interesting_fname (const char *fname)
+{
+ static const char *illegal_aliens[] = {
+ "_globals_", /* inserted by coff_symtab_read */
+ NULL
+ };
+ int i;
+
+ for (i = 0; illegal_aliens[i]; i++)
+ {
+ if (strcmp (fname, illegal_aliens[i]) == 0)
+ return 1;
+ }
+ return 0;
+}
+
+/* Return a NULL terminated array of all source files whose names
+ begin with matching TEXT. The file names are looked up in the
+ symbol tables of this program. If the answer is no matchess, then
+ the return value is an array which contains only a NULL pointer. */
+
+char **
+make_source_files_completion_list (char *text, char *word)
+{
+ register struct symtab *s;
+ register struct partial_symtab *ps;
+ register struct objfile *objfile;
+ int first = 1;
+ int list_alloced = 1;
+ int list_used = 0;
+ size_t text_len = strlen (text);
+ char **list = (char **) xmalloc (list_alloced * sizeof (char *));
+ const char *base_name;
+
+ list[0] = NULL;
+
+ if (!have_full_symbols () && !have_partial_symbols ())
+ return list;
+
+ ALL_SYMTABS (objfile, s)
+ {
+ if (not_interesting_fname (s->filename))
+ continue;
+ if (!filename_seen (s->filename, 1, &first)
+#if HAVE_DOS_BASED_FILE_SYSTEM
+ && strncasecmp (s->filename, text, text_len) == 0
+#else
+ && strncmp (s->filename, text, text_len) == 0
+#endif
+ )
+ {
+ /* This file matches for a completion; add it to the current
+ list of matches. */
+ add_filename_to_list (s->filename, text, word,
+ &list, &list_used, &list_alloced);
+ }
+ else
+ {
+ /* NOTE: We allow the user to type a base name when the
+ debug info records leading directories, but not the other
+ way around. This is what subroutines of breakpoint
+ command do when they parse file names. */
+ base_name = lbasename (s->filename);
+ if (base_name != s->filename
+ && !filename_seen (base_name, 1, &first)
+#if HAVE_DOS_BASED_FILE_SYSTEM
+ && strncasecmp (base_name, text, text_len) == 0
+#else
+ && strncmp (base_name, text, text_len) == 0
+#endif
+ )
+ add_filename_to_list (base_name, text, word,
+ &list, &list_used, &list_alloced);
+ }
+ }
+
+ ALL_PSYMTABS (objfile, ps)
+ {
+ if (not_interesting_fname (ps->filename))
+ continue;
+ if (!ps->readin)
+ {
+ if (!filename_seen (ps->filename, 1, &first)
+#if HAVE_DOS_BASED_FILE_SYSTEM
+ && strncasecmp (ps->filename, text, text_len) == 0
+#else
+ && strncmp (ps->filename, text, text_len) == 0
+#endif
+ )
+ {
+ /* This file matches for a completion; add it to the
+ current list of matches. */
+ add_filename_to_list (ps->filename, text, word,
+ &list, &list_used, &list_alloced);
+
+ }
+ else
+ {
+ base_name = lbasename (ps->filename);
+ if (base_name != ps->filename
+ && !filename_seen (base_name, 1, &first)
+#if HAVE_DOS_BASED_FILE_SYSTEM
+ && strncasecmp (base_name, text, text_len) == 0
+#else
+ && strncmp (base_name, text, text_len) == 0
+#endif
+ )
+ add_filename_to_list (base_name, text, word,
+ &list, &list_used, &list_alloced);
+ }
+ }
+ }
+
+ return list;
+}
+
/* Determine if PC is in the prologue of a function. The prologue is the area
between the first instruction of a function, and the first executable line.
Returns 1 if PC *might* be in prologue, 0 if definately *not* in prologue.
/* Begin overload resolution functions */
+
+static char *
+remove_params (const char *demangled_name)
+{
+ const char *argp;
+ char *new_name;
+ int depth;
+
+ if (demangled_name == NULL)
+ return NULL;
+
+ /* First find the end of the arg list. */
+ argp = strrchr (demangled_name, ')');
+ if (argp == NULL)
+ return NULL;
+
+ /* Back up to the beginning. */
+ depth = 1;
+
+ while (argp-- > demangled_name)
+ {
+ if (*argp == ')')
+ depth ++;
+ else if (*argp == '(')
+ {
+ depth --;
+
+ if (depth == 0)
+ break;
+ }
+ }
+ if (depth != 0)
+ internal_error (__FILE__, __LINE__,
+ "bad demangled name %s\n", demangled_name);
+ while (argp[-1] == ' ' && argp > demangled_name)
+ argp --;
+
+ new_name = xmalloc (argp - demangled_name + 1);
+ memcpy (new_name, demangled_name, argp - demangled_name);
+ new_name[argp - demangled_name] = '\0';
+ return new_name;
+}
+
/* Helper routine for make_symbol_completion_list. */
static int sym_return_val_size;
{
int newsize;
int i;
+ char *sym_name;
+
+ /* If there is no type information, we can't do anything, so skip */
+ if (SYMBOL_TYPE (sym) == NULL)
+ return;
+
+ /* skip any symbols that we've already considered. */
+ for (i = 0; i < sym_return_val_index; ++i)
+ if (!strcmp (SYMBOL_NAME (sym), SYMBOL_NAME (sym_return_val[i])))
+ return;
/* Get the demangled name without parameters */
- char *sym_name = cplus_demangle (SYMBOL_NAME (sym), DMGL_ARM | DMGL_ANSI);
+ sym_name = remove_params (SYMBOL_DEMANGLED_NAME (sym));
if (!sym_name)
- {
- sym_name = (char *) xmalloc (strlen (SYMBOL_NAME (sym)) + 1);
- strcpy (sym_name, SYMBOL_NAME (sym));
- }
+ return;
/* skip symbols that cannot match */
if (strcmp (sym_name, oload_name) != 0)
return;
}
- /* If there is no type information, we can't do anything, so skip */
- if (SYMBOL_TYPE (sym) == NULL)
- return;
-
- /* skip any symbols that we've already considered. */
- for (i = 0; i < sym_return_val_index; ++i)
- if (!strcmp (SYMBOL_NAME (sym), SYMBOL_NAME (sym_return_val[i])))
- return;
+ xfree (sym_name);
/* We have a match for an overload instance, so add SYM to the current list
* of overload instances */
}
sym_return_val[sym_return_val_index++] = sym;
sym_return_val[sym_return_val_index] = NULL;
-
- xfree (sym_name);
}
/* Return a null-terminated list of pointers to function symbols that
/* Length of name. */
int oload_name_len = 0;
- /* Look for the symbol we are supposed to complete on.
- * FIXME: This should be language-specific. */
+ /* Look for the symbol we are supposed to complete on. */
- oload_name = cplus_demangle (SYMBOL_NAME (fsym), DMGL_ARM | DMGL_ANSI);
+ oload_name = remove_params (SYMBOL_DEMANGLED_NAME (fsym));
if (!oload_name)
{
- oload_name = (char *) xmalloc (strlen (SYMBOL_NAME (fsym)) + 1);
- strcpy (oload_name, SYMBOL_NAME (fsym));
+ sym_return_val_size = 1;
+ sym_return_val = (struct symbol **) xmalloc (2 * sizeof (struct symbol *));
+ sym_return_val[0] = fsym;
+ sym_return_val[1] = NULL;
+
+ return sym_return_val;
}
oload_name_len = strlen (oload_name);
/* Search upwards from currently selected frame (so that we can
complete on local vars. */
- for (b = get_selected_block (); b != NULL; b = BLOCK_SUPERBLOCK (b))
+ for (b = get_selected_block (0); b != NULL; b = BLOCK_SUPERBLOCK (b))
{
if (!BLOCK_SUPERBLOCK (b))
{
/* Also catch fields of types defined in this places which match our
text string. Only complete on types visible from current context. */
- for (i = 0; i < BLOCK_NSYMS (b); i++)
+ ALL_BLOCK_SYMBOLS (b, i, sym)
{
- sym = BLOCK_SYM (b, i);
overload_list_add_symbol (sym, oload_name);
}
}
{
QUIT;
b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
- for (i = 0; i < BLOCK_NSYMS (b); i++)
+ ALL_BLOCK_SYMBOLS (b, i, sym)
{
- sym = BLOCK_SYM (b, i);
overload_list_add_symbol (sym, oload_name);
}
}
/* Don't do this block twice. */
if (b == surrounding_static_block)
continue;
- for (i = 0; i < BLOCK_NSYMS (b); i++)
+ ALL_BLOCK_SYMBOLS (b, i, sym)
{
- sym = BLOCK_SYM (b, i);
overload_list_add_symbol (sym, oload_name);
}
}
decode_line_spec (char *string, int funfirstline)
{
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, funfirstline,
- current_source_symtab, current_source_line,
+ cursal.symtab, cursal.line,
(char ***) NULL);
+
if (*string)
error ("Junk at end of line specification: %s", string);
return sals;
}
+/* Track MAIN */
+static char *name_of_main;
+
+void
+set_main_name (const char *name)
+{
+ if (name_of_main != NULL)
+ {
+ xfree (name_of_main);
+ name_of_main = NULL;
+ }
+ if (name != NULL)
+ {
+ name_of_main = xstrdup (name);
+ }
+}
+
+char *
+main_name (void)
+{
+ if (name_of_main != NULL)
+ return name_of_main;
+ else
+ return "main";
+}
+
+
void
_initialize_symtab (void)
{
add_info ("types", types_info,
"All type names, or those matching REGEXP.");
-#if 0
- add_info ("methods", methods_info,
- "All method names, or those matching REGEXP::REGEXP.\n\
-If the class qualifier is omitted, it is assumed to be the current scope.\n\
-If the first REGEXP is omitted, then all methods matching the second REGEXP\n\
-are listed.");
-#endif
add_info ("sources", sources_info,
"Source files in the program.");