/* Symbol table lookup for the GNU debugger, GDB.
- Copyright 1986, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 1998
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
+ 1996, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
This file is part of GDB.
#include "language.h"
#include "demangle.h"
#include "inferior.h"
+#include "linespec.h"
+#include "filenames.h" /* for FILENAME_CMP */
#include "obstack.h"
#include "gdb_string.h"
#include "gdb_stat.h"
#include <ctype.h>
+#include "cp-abi.h"
/* Prototype for one function in parser-defs.h,
instead of including that entire file. */
/* Prototypes for local functions */
-static int find_methods (struct type *, char *, struct symbol **);
-
static void completion_list_add_name (char *, char *, int, char *, char *);
-static void build_canonical_line_spec (struct symtab_and_line *,
- char *, char ***);
-
-static struct symtabs_and_lines decode_line_2 (struct symbol *[],
- int, int, char ***);
-
static void rbreak_command (char *, int);
static void types_info (char *, int);
static void output_source_filename (char *, int *);
-char *operator_chars (char *, char **);
-
static int find_line_common (struct linetable *, int, int *);
+/* This one is used by linespec.c */
+
+char *operator_chars (char *p, char **end);
+
static struct partial_symbol *lookup_partial_symbol (struct partial_symtab *,
const char *, int,
namespace_enum);
-static struct symtab *lookup_symtab_1 (char *);
+static struct symtab *lookup_symtab_1 (const 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 void cplusplus_hint (char *);
static struct symbol *find_active_alias (struct symbol *sym, CORE_ADDR addr);
const struct block *block_found;
-char no_symtab_msg[] = "No symbol table is loaded. Use the \"file\" command.";
-
/* 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 */
in the symtab filename will also work. */
static struct symtab *
-lookup_symtab_1 (char *name)
+lookup_symtab_1 (const char *name)
{
register struct symtab *s;
register struct partial_symtab *ps;
- register char *slash;
register struct objfile *objfile;
got_symtab:
/* First, search for an exact match */
ALL_SYMTABS (objfile, s)
- if (STREQ (name, s->filename))
- return s;
-
- slash = strchr (name, '/');
+ if (FILENAME_CMP (name, s->filename) == 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 (basename (s->filename), name) == 0)
return s;
}
of variations if the first lookup doesn't work. */
struct symtab *
-lookup_symtab (char *name)
+lookup_symtab (const char *name)
{
register struct symtab *s;
#if 0
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;
ALL_PSYMTABS (objfile, pst)
{
- if (STREQ (name, pst->filename))
+ if (FILENAME_CMP (name, pst->filename) == 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 (basename (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));
- is_full_physname_constructor =
- ((physname[0] == '_' && physname[1] == '_' &&
- (isdigit (physname[2]) || physname[2] == 'Q' || physname[2] == 't'))
- || (strncmp (physname, "__ct", 4) == 0));
+ if (is_operator_name (field_name))
+ return xstrdup (physname);
+
+ is_full_physname_constructor = is_constructor_name (physname);
is_constructor =
is_full_physname_constructor || (newname && STREQ (field_name, newname));
sprintf (buf, "__%s%s%d", const_prefix, volatile_prefix, len);
}
mangled_name_len = ((is_constructor ? 0 : strlen (field_name))
- + strlen (buf) + len
- + strlen (physname)
- + 1);
-
- /* Only needed for GNU-mangled names. ANSI-mangled names
- work with the normal mechanisms. */
- if (OPNAME_PREFIX_P (field_name))
- {
- const char *opname = cplus_mangle_opname (field_name + 3, 0);
- if (opname == NULL)
- error ("No mangling for \"%s\"", field_name);
- mangled_name_len += strlen (opname);
- mangled_name = (char *) xmalloc (mangled_name_len);
+ + strlen (buf) + len + strlen (physname) + 1);
- strncpy (mangled_name, field_name, 3);
- mangled_name[3] = '\0';
- strcat (mangled_name, opname);
- }
- else
{
mangled_name = (char *) xmalloc (mangled_name_len);
if (is_constructor)
can probably assume it will never hit the C++ code). */
struct symbol *
-lookup_symbol (const char *name, register const struct block *block,
+lookup_symbol (const char *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;
- struct blockvector *bv;
- register struct objfile *objfile = NULL;
- register struct block *b;
- register struct minimal_symbol *msymbol;
+ char *modified_name = NULL;
+ char *modified_name2 = NULL;
+ int needtofreename = 0;
+ struct symbol *returnval;
if (case_sensitivity == case_sensitive_off)
{
for (i= 0; i < len; i++)
copy[i] = tolower (name[i]);
copy[len] = 0;
- name = copy;
+ 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);
+ if (needtofreename)
+ xfree (modified_name2);
+
+ 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)
+{
+ 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;
+
+
/* Search specified block and its superiors. */
while (block != 0)
{
/* This is a mangled variable, look it up by its
mangled name. */
- return lookup_symbol (SYMBOL_NAME (msymbol), block,
- namespace, is_a_field_of_this, symtab);
+ return lookup_symbol_aux (SYMBOL_NAME (msymbol), block,
+ namespace, is_a_field_of_this, symtab);
}
/* There are no debug symbols for this file, or we are looking
for an unmangled variable.
&& 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), block,
+ namespace, is_a_field_of_this, symtab);
}
}
}
{
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_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
{
/* Reset the linear search flag so if the binary search fails, we
won't do the linear search once unless we find some reason to
- do so, such as finding a C++ symbol during the binary search.
- Note that for C++ modules, ALL the symbols in a block should
- end up marked as C++ symbols. */
+ do so */
do_linear_search = 0;
top = BLOCK_NSYMS (block);
}
inc = (inc >> 1) + bot;
sym = BLOCK_SYM (block, inc);
- if (!do_linear_search
- && (SYMBOL_LANGUAGE (sym) == language_cplus
- || SYMBOL_LANGUAGE (sym) == language_java
- ))
+ if (!do_linear_search && (SYMBOL_LANGUAGE (sym) == language_java))
{
do_linear_search = 1;
}
- if (SYMBOL_NAME (sym)[0] < name[0])
+ if (SYMBOL_SOURCE_NAME (sym)[0] < name[0])
{
bot = inc;
}
- else if (SYMBOL_NAME (sym)[0] > name[0])
+ else if (SYMBOL_SOURCE_NAME (sym)[0] > name[0])
{
top = inc;
}
- else if (STRCMP (SYMBOL_NAME (sym), name) < 0)
+ else if (strcmp (SYMBOL_SOURCE_NAME (sym), name) < 0)
{
bot = inc;
}
while (bot < top)
{
sym = BLOCK_SYM (block, bot);
- inc = SYMBOL_NAME (sym)[0] - name[0];
- if (inc == 0)
- {
- inc = STRCMP (SYMBOL_NAME (sym), name);
- }
- if (inc == 0 && SYMBOL_NAMESPACE (sym) == namespace)
- {
- return (sym);
- }
- if (inc > 0)
+ if (SYMBOL_NAMESPACE (sym) == namespace &&
+ SYMBOL_MATCHES_NAME (sym, name))
{
- break;
+ return sym;
}
bot++;
}
}
#endif /* 0 */
-/* Find the source file and line number for a given PC value and section.
+/* 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.
The value's .pc field is NOT the specified pc.
{
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)
return find_pc_sect_line (pc, section, notcurrent);
}
\f
-
-static struct symtab *find_line_symtab (struct symtab *, int, int *, int *);
-
/* Find line number LINE in any symtab whose name is the same as
SYMTAB.
If not found, return NULL. */
-static struct symtab *
+struct symtab *
find_line_symtab (struct symtab *symtab, int line, int *index, int *exact_match)
{
int exact;
If the argument FUNFIRSTLINE is nonzero, we want the first line
of real code inside the function. */
-static struct symtab_and_line
-find_function_start_sal (struct symbol *sym, int);
-
-static struct symtab_and_line
+struct symtab_and_line
find_function_start_sal (struct symbol *sym, int funfirstline)
{
CORE_ADDR pc;
return sal;
}
-\f
+
/* If P is of the form "operator[ \t]+..." where `...' is
some legitimate operator text, return a pointer to the
beginning of the substring of the operator text.
*end = "";
return *end;
}
+\f
-/* Return the number of methods described for TYPE, including the
- methods from types it derives from. This can't be done in the symbol
- reader because the type of the baseclass might still be stubbed
- when the definition of the derived class is parsed. */
-
-static int total_number_of_methods (struct type *type);
-
+/* 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
-total_number_of_methods (struct type *type)
+filename_seen (const char *file, int add, int *first)
{
- int n;
- int count;
-
- CHECK_TYPEDEF (type);
- if (TYPE_CPLUS_SPECIFIC (type) == NULL)
- return 0;
- count = TYPE_NFN_FIELDS_TOTAL (type);
-
- for (n = 0; n < TYPE_N_BASECLASSES (type); n++)
- count += total_number_of_methods (TYPE_BASECLASS (type, n));
-
- return count;
-}
-
-/* Recursive helper function for decode_line_1.
- Look for methods named NAME in type T.
- Return number of matches.
- Put matches in SYM_ARR, which should have been allocated with
- a size of total_number_of_methods (T) * sizeof (struct symbol *).
- Note that this function is g++ specific. */
+ /* 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;
-static int
-find_methods (struct type *t, char *name, struct symbol **sym_arr)
-{
- int i1 = 0;
- int ibase;
- struct symbol *sym_class;
- char *class_name = type_name_no_tag (t);
-
- /* Ignore this class if it doesn't have a name. This is ugly, but
- unless we figure out how to get the physname without the name of
- the class, then the loop can't do any good. */
- if (class_name
- && (sym_class = lookup_symbol (class_name,
- (struct block *) NULL,
- STRUCT_NAMESPACE,
- (int *) NULL,
- (struct symtab **) NULL)))
+ if (*first)
{
- int method_counter;
-
- /* FIXME: Shouldn't this just be CHECK_TYPEDEF (t)? */
- t = SYMBOL_TYPE (sym_class);
+ if (tab == NULL)
+ tab = (const char **) xmalloc (tab_alloc_size * sizeof (*tab));
+ tab_cur_size = 0;
+ }
- /* Loop over each method name. At this level, all overloads of a name
- are counted as a single name. There is an inner loop which loops over
- each overload. */
+ /* Is FILE in tab? */
+ for (p = tab; p < tab + tab_cur_size; p++)
+ if (strcmp (*p, file) == 0)
+ return 1;
- for (method_counter = TYPE_NFN_FIELDS (t) - 1;
- method_counter >= 0;
- --method_counter)
+ /* No; maybe add it to tab. */
+ if (add)
+ {
+ if (tab_cur_size == tab_alloc_size)
{
- int field_counter;
- char *method_name = TYPE_FN_FIELDLIST_NAME (t, method_counter);
- char dem_opname[64];
-
- if (strncmp (method_name, "__", 2) == 0 ||
- strncmp (method_name, "op", 2) == 0 ||
- strncmp (method_name, "type", 4) == 0)
- {
- if (cplus_demangle_opname (method_name, dem_opname, DMGL_ANSI))
- method_name = dem_opname;
- else if (cplus_demangle_opname (method_name, dem_opname, 0))
- method_name = dem_opname;
- }
-
- if (STREQ (name, method_name))
- /* Find all the overloaded methods with that name. */
- for (field_counter = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
- field_counter >= 0;
- --field_counter)
- {
- struct fn_field *f;
- char *phys_name;
-
- f = TYPE_FN_FIELDLIST1 (t, method_counter);
-
- if (TYPE_FN_FIELD_STUB (f, field_counter))
- {
- char *tmp_name;
-
- tmp_name = gdb_mangle_name (t,
- method_counter,
- field_counter);
- phys_name = alloca (strlen (tmp_name) + 1);
- strcpy (phys_name, tmp_name);
- free (tmp_name);
- }
- else
- phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
-
- /* Destructor is handled by caller, dont add it to the list */
- if (DESTRUCTOR_PREFIX_P (phys_name))
- continue;
-
- sym_arr[i1] = lookup_symbol (phys_name,
- NULL, VAR_NAMESPACE,
- (int *) NULL,
- (struct symtab **) NULL);
- if (sym_arr[i1])
- i1++;
- else
- {
- /* This error message gets printed, but the method
- still seems to be found
- fputs_filtered("(Cannot find method ", gdb_stdout);
- fprintf_symbol_filtered (gdb_stdout, phys_name,
- language_cplus,
- DMGL_PARAMS | DMGL_ANSI);
- fputs_filtered(" - possibly inlined.)\n", gdb_stdout);
- */
- }
- }
+ tab_alloc_size *= 2;
+ tab = (const char **) xrealloc ((char *) tab,
+ tab_alloc_size * sizeof (*tab));
}
+ tab[tab_cur_size++] = file;
}
- /* Only search baseclasses if there is no match yet, since names in
- derived classes override those in baseclasses.
-
- FIXME: The above is not true; it is only true of member functions
- if they have the same number of arguments (??? - section 13.1 of the
- ARM says the function members are not in the same scope but doesn't
- really spell out the rules in a way I understand. In any case, if
- the number of arguments differ this is a case in which we can overload
- rather than hiding without any problem, and gcc 2.4.5 does overload
- rather than hiding in this case). */
-
- if (i1 == 0)
- for (ibase = 0; ibase < TYPE_N_BASECLASSES (t); ibase++)
- i1 += find_methods (TYPE_BASECLASS (t, ibase), name, sym_arr + i1);
-
- return i1;
+ return 0;
}
-/* Helper function for decode_line_1.
- Build a canonical line spec in CANONICAL if it is non-NULL and if
- the SAL has a symtab.
- If SYMNAME is non-NULL the canonical line spec is `filename:symname'.
- If SYMNAME is NULL the line number from SAL is used and the canonical
- line spec is `filename:linenum'. */
-
+/* 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
-build_canonical_line_spec (struct symtab_and_line *sal, char *symname,
- char ***canonical)
+output_source_filename (char *name, int *first)
{
- char **canonical_arr;
- char *canonical_name;
- char *filename;
- struct symtab *s = sal->symtab;
-
- if (s == (struct symtab *) NULL
- || s->filename == (char *) NULL
- || canonical == (char ***) NULL)
- return;
-
- canonical_arr = (char **) xmalloc (sizeof (char *));
- *canonical = canonical_arr;
+ /* 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. */
- filename = s->filename;
- if (symname != NULL)
+ /* 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)
{
- canonical_name = xmalloc (strlen (filename) + strlen (symname) + 2);
- sprintf (canonical_name, "%s:%s", filename, symname);
+ *first = 0;
}
else
{
- canonical_name = xmalloc (strlen (filename) + 30);
- sprintf (canonical_name, "%s:%d", filename, sal->line);
+ printf_filtered (", ");
}
- canonical_arr[0] = canonical_name;
+
+ wrap_here ("");
+ fputs_filtered (name, gdb_stdout);
}
+static void
+sources_info (char *ignore, int from_tty)
+{
+ register struct symtab *s;
+ register struct partial_symtab *ps;
+ register struct objfile *objfile;
+ int first;
+
+ if (!have_full_symbols () && !have_partial_symbols ())
+ {
+ error ("No symbol table is loaded. Use the \"file\" command.");
+ }
+
+ printf_filtered ("Source files for which symbols have been read in:\n\n");
+
+ first = 1;
+ ALL_SYMTABS (objfile, s)
+ {
+ output_source_filename (s->filename, &first);
+ }
+ printf_filtered ("\n\n");
+
+ printf_filtered ("Source files for which symbols will be read in on demand:\n\n");
+ first = 1;
+ ALL_PSYMTABS (objfile, ps)
+ {
+ if (!ps->readin)
+ {
+ output_source_filename (ps->filename, &first);
+ }
+ }
+ printf_filtered ("\n");
+}
-/* Find an instance of the character C in the string S that is outside
- of all parenthesis pairs, single-quoted strings, and double-quoted
- strings. */
-static char *
-find_toplevel_char (char *s, char c)
+static int
+file_matches (char *file, char *files[], int nfiles)
{
- int quoted = 0; /* zero if we're not in quotes;
- '"' if we're in a double-quoted string;
- '\'' if we're in a single-quoted string. */
- int depth = 0; /* number of unclosed parens we've seen */
- char *scan;
+ int i;
- for (scan = s; *scan; scan++)
+ if (file != NULL && nfiles != 0)
{
- if (quoted)
+ for (i = 0; i < nfiles; i++)
{
- if (*scan == quoted)
- quoted = 0;
- else if (*scan == '\\' && *(scan + 1))
- scan++;
+ if (strcmp (files[i], basename (file)) == 0)
+ return 1;
}
- else if (*scan == c && ! quoted && depth == 0)
- return scan;
- else if (*scan == '"' || *scan == '\'')
- quoted = *scan;
- else if (*scan == '(')
- depth++;
- else if (*scan == ')' && depth > 0)
- depth--;
}
-
+ else if (nfiles == 0)
+ return 1;
return 0;
}
+/* Free any memory associated with a search. */
+void
+free_search_symbols (struct symbol_search *symbols)
+{
+ struct symbol_search *p;
+ struct symbol_search *next;
-/* Parse a string that specifies a line number.
- Pass the address of a char * variable; that variable will be
- advanced over the characters actually parsed.
+ for (p = symbols; p != NULL; p = next)
+ {
+ next = p->next;
+ xfree (p);
+ }
+}
- The string can be:
+static void
+do_free_search_symbols_cleanup (void *symbols)
+{
+ free_search_symbols (symbols);
+}
- LINENUM -- that line number in current file. PC returned is 0.
- FILE:LINENUM -- that line in that file. PC returned is 0.
- FUNCTION -- line number of openbrace of that function.
- PC returned is the start of the function.
- VARIABLE -- line number of definition of that variable.
- PC returned is 0.
- FILE:FUNCTION -- likewise, but prefer functions in that file.
- *EXPR -- line in which address EXPR appears.
+struct cleanup *
+make_cleanup_free_search_symbols (struct symbol_search *symbols)
+{
+ return make_cleanup (do_free_search_symbols_cleanup, symbols);
+}
- This may all be followed by an "if EXPR", which we ignore.
- FUNCTION may be an undebuggable function found in minimal symbol table.
+/* Search the symbol table for matches to the regular expression REGEXP,
+ returning the results in *MATCHES.
- If the argument FUNFIRSTLINE is nonzero, we want the first line
- of real code inside a function when a function is specified, and it is
- not OK to specify a variable or type to get its line number.
-
- DEFAULT_SYMTAB specifies the file to use if none is specified.
- It defaults to current_source_symtab.
- DEFAULT_LINE specifies the line number to use for relative
- line numbers (that start with signs). Defaults to current_source_line.
- If CANONICAL is non-NULL, store an array of strings containing the canonical
- line specs there if necessary. Currently overloaded member functions and
- line numbers or static functions without a filename yield a canonical
- line spec. The array and the line spec strings are allocated on the heap,
- it is the callers responsibility to free them.
-
- Note that it is possible to return zero for the symtab
- if no file is validly specified. Callers must check that.
- Also, the line number returned may be invalid. */
-
-/* We allow single quotes in various places. This is a hideous
- kludge, which exists because the completer can't yet deal with the
- lack of single quotes. FIXME: write a linespec_completer which we
- can use as appropriate instead of make_symbol_completion_list. */
+ Only symbols of KIND are searched:
+ FUNCTIONS_NAMESPACE - search all functions
+ TYPES_NAMESPACE - search all type names
+ METHODS_NAMESPACE - search all methods NOT IMPLEMENTED
+ VARIABLES_NAMESPACE - search all symbols, excluding functions, type names,
+ and constants (enums)
-struct symtabs_and_lines
-decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
- int default_line, char ***canonical)
+ free_search_symbols should be called when *MATCHES is no longer needed.
+ */
+void
+search_symbols (char *regexp, namespace_enum kind, int nfiles, char *files[],
+ struct symbol_search **matches)
{
- struct symtabs_and_lines values;
-#ifdef HPPA_COMPILER_BUG
- /* FIXME: The native HP 9000/700 compiler has a bug which appears
- when optimizing this file with target i960-vxworks. I haven't
- been able to construct a simple test case. The problem is that
- in the second call to SKIP_PROLOGUE below, the compiler somehow
- does not realize that the statement val = find_pc_line (...) will
- change the values of the fields of val. It extracts the elements
- into registers at the top of the block, and does not update the
- registers after the call to find_pc_line. You can check this by
- inserting a printf at the end of find_pc_line to show what values
- it is returning for val.pc and val.end and another printf after
- the call to see what values the function actually got (remember,
- this is compiling with cc -O, with this patch removed). You can
- also examine the assembly listing: search for the second call to
- skip_prologue; the LDO statement before the next call to
- find_pc_line loads the address of the structure which
- find_pc_line will return; if there is a LDW just before the LDO,
- which fetches an element of the structure, then the compiler
- still has the bug.
-
- Setting val to volatile avoids the problem. We must undef
- volatile, because the HPPA native compiler does not define
- __STDC__, although it does understand volatile, and so volatile
- will have been defined away in defs.h. */
-#undef volatile
- volatile struct symtab_and_line val;
-#define volatile /*nothing */
-#else
- struct symtab_and_line val;
-#endif
- register char *p, *p1;
- char *q, *pp, *ii, *p2;
-#if 0
- char *q1;
-#endif
register struct symtab *s;
-
+ register struct partial_symtab *ps;
+ register struct blockvector *bv;
+ struct blockvector *prev_bv = 0;
+ register struct block *b;
+ register int i = 0;
+ register int j;
register struct symbol *sym;
- /* The symtab that SYM was found in. */
- struct symtab *sym_symtab;
-
- register CORE_ADDR pc;
- register struct minimal_symbol *msymbol;
- char *copy;
- struct symbol *sym_class;
- int i1;
- int is_quoted;
- int is_quote_enclosed;
- int has_parens;
- int has_if = 0;
- int has_comma = 0;
- struct symbol **sym_arr;
- struct type *t;
- char *saved_arg = *argptr;
- extern char *gdb_completer_quote_characters;
-
- INIT_SAL (&val); /* initialize to zeroes */
+ struct partial_symbol **psym;
+ struct objfile *objfile;
+ struct minimal_symbol *msymbol;
+ char *val;
+ int found_misc = 0;
+ static enum minimal_symbol_type types[]
+ =
+ {mst_data, mst_text, mst_abs, mst_unknown};
+ static enum minimal_symbol_type types2[]
+ =
+ {mst_bss, mst_file_text, mst_abs, mst_unknown};
+ static enum minimal_symbol_type types3[]
+ =
+ {mst_file_data, mst_solib_trampoline, mst_abs, mst_unknown};
+ static enum minimal_symbol_type types4[]
+ =
+ {mst_file_bss, mst_text, mst_abs, mst_unknown};
+ enum minimal_symbol_type ourtype;
+ enum minimal_symbol_type ourtype2;
+ enum minimal_symbol_type ourtype3;
+ enum minimal_symbol_type ourtype4;
+ struct symbol_search *sr;
+ struct symbol_search *psr;
+ struct symbol_search *tail;
+ struct cleanup *old_chain = NULL;
- /* Defaults have defaults. */
+ if (kind < VARIABLES_NAMESPACE)
+ error ("must search on specific namespace");
- if (default_symtab == 0)
- {
- default_symtab = current_source_symtab;
- default_line = current_source_line;
- }
+ ourtype = types[(int) (kind - VARIABLES_NAMESPACE)];
+ ourtype2 = types2[(int) (kind - VARIABLES_NAMESPACE)];
+ ourtype3 = types3[(int) (kind - VARIABLES_NAMESPACE)];
+ ourtype4 = types4[(int) (kind - VARIABLES_NAMESPACE)];
- /* See if arg is *PC */
+ sr = *matches = NULL;
+ tail = NULL;
- if (**argptr == '*')
- {
- (*argptr)++;
- pc = parse_and_eval_address_1 (argptr);
-
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
-
- values.nelts = 1;
- values.sals[0] = find_pc_line (pc, 0);
- values.sals[0].pc = pc;
- values.sals[0].section = find_pc_overlay (pc);
-
- return values;
- }
-
- /* 'has_if' is for the syntax:
- * (gdb) break foo if (a==b)
- */
- if ((ii = strstr (*argptr, " if ")) != NULL ||
- (ii = strstr (*argptr, "\tif ")) != NULL ||
- (ii = strstr (*argptr, " if\t")) != NULL ||
- (ii = strstr (*argptr, "\tif\t")) != NULL ||
- (ii = strstr (*argptr, " if(")) != NULL ||
- (ii = strstr (*argptr, "\tif( ")) != NULL)
- has_if = 1;
- /* Temporarily zap out "if (condition)" to not
- * confuse the parenthesis-checking code below.
- * This is undone below. Do not change ii!!
- */
- if (has_if)
- {
- *ii = '\0';
- }
-
- /* Set various flags.
- * 'has_parens' is important for overload checking, where
- * we allow things like:
- * (gdb) break c::f(int)
- */
-
- /* Maybe arg is FILE : LINENUM or FILE : FUNCTION */
-
- is_quoted = (**argptr
- && strchr (gdb_completer_quote_characters, **argptr) != NULL);
-
- has_parens = ((pp = strchr (*argptr, '(')) != NULL
- && (pp = strrchr (pp, ')')) != NULL);
-
- /* Now that we're safely past the has_parens check,
- * put back " if (condition)" so outer layers can see it
- */
- if (has_if)
- *ii = ' ';
-
- /* Maybe we were called with a line range FILENAME:LINENUM,FILENAME:LINENUM
- and we must isolate the first half. Outer layers will call again later
- for the second half.
-
- Don't count commas that appear in argument lists of overloaded
- functions, or in quoted strings. It's stupid to go to this much
- trouble when the rest of the function is such an obvious roach hotel. */
- ii = find_toplevel_char (*argptr, ',');
- has_comma = (ii != 0);
-
- /* Temporarily zap out second half to not
- * confuse the code below.
- * This is undone below. Do not change ii!!
- */
- if (has_comma)
- {
- *ii = '\0';
- }
-
- /* Maybe arg is FILE : LINENUM or FILE : FUNCTION */
- /* May also be CLASS::MEMBER, or NAMESPACE::NAME */
- /* Look for ':', but ignore inside of <> */
-
- s = NULL;
- p = *argptr;
- if (p[0] == '"')
- {
- is_quote_enclosed = 1;
- p++;
- }
- else
- is_quote_enclosed = 0;
- for (; *p; p++)
- {
- if (p[0] == '<')
- {
- char *temp_end = find_template_name_end (p);
- if (!temp_end)
- error ("malformed template specification in command");
- p = temp_end;
- }
- /* Check for the end of the first half of the linespec. End of line,
- a tab, a double colon or the last single colon, or a space. But
- if enclosed in double quotes we do not break on enclosed spaces */
- if (!*p
- || p[0] == '\t'
- || ((p[0] == ':')
- && ((p[1] == ':') || (strchr (p + 1, ':') == NULL)))
- || ((p[0] == ' ') && !is_quote_enclosed))
- break;
- if (p[0] == '.' && strchr (p, ':') == NULL) /* Java qualified method. */
- {
- /* Find the *last* '.', since the others are package qualifiers. */
- for (p1 = p; *p1; p1++)
- {
- if (*p1 == '.')
- p = p1;
- }
- break;
- }
- }
- while (p[0] == ' ' || p[0] == '\t')
- p++;
-
- /* if the closing double quote was left at the end, remove it */
- if (is_quote_enclosed)
- {
- char *closing_quote = strchr (p, '"');
- if (closing_quote && closing_quote[1] == '\0')
- *closing_quote = '\0';
- }
-
- /* Now that we've safely parsed the first half,
- * put back ',' so outer layers can see it
- */
- if (has_comma)
- *ii = ',';
-
- if ((p[0] == ':' || p[0] == '.') && !has_parens)
- {
- /* C++ */
- /* ... or Java */
- if (is_quoted)
- *argptr = *argptr + 1;
- if (p[0] == '.' || p[1] == ':')
- {
- char *saved_arg2 = *argptr;
- char *temp_end;
- /* First check for "global" namespace specification,
- of the form "::foo". If found, skip over the colons
- and jump to normal symbol processing */
- if ((*argptr == p) || (p[-1] == ' ') || (p[-1] == '\t'))
- saved_arg2 += 2;
-
- /* We have what looks like a class or namespace
- scope specification (A::B), possibly with many
- levels of namespaces or classes (A::B::C::D).
-
- Some versions of the HP ANSI C++ compiler (as also possibly
- other compilers) generate class/function/member names with
- embedded double-colons if they are inside namespaces. To
- handle this, we loop a few times, considering larger and
- larger prefixes of the string as though they were single
- symbols. So, if the initially supplied string is
- A::B::C::D::foo, we have to look up "A", then "A::B",
- then "A::B::C", then "A::B::C::D", and finally
- "A::B::C::D::foo" as single, monolithic symbols, because
- A, B, C or D may be namespaces.
-
- Note that namespaces can nest only inside other
- namespaces, and not inside classes. So we need only
- consider *prefixes* of the string; there is no need to look up
- "B::C" separately as a symbol in the previous example. */
-
- p2 = p; /* save for restart */
- while (1)
- {
- /* Extract the class name. */
- p1 = p;
- while (p != *argptr && p[-1] == ' ')
- --p;
- copy = (char *) alloca (p - *argptr + 1);
- memcpy (copy, *argptr, p - *argptr);
- copy[p - *argptr] = 0;
-
- /* Discard the class name from the arg. */
- p = p1 + (p1[0] == ':' ? 2 : 1);
- while (*p == ' ' || *p == '\t')
- p++;
- *argptr = p;
-
- sym_class = lookup_symbol (copy, 0, STRUCT_NAMESPACE, 0,
- (struct symtab **) NULL);
-
- if (sym_class &&
- (t = check_typedef (SYMBOL_TYPE (sym_class)),
- (TYPE_CODE (t) == TYPE_CODE_STRUCT
- || TYPE_CODE (t) == TYPE_CODE_UNION)))
- {
- /* Arg token is not digits => try it as a function name
- Find the next token(everything up to end or next blank). */
- if (**argptr
- && strchr (gdb_completer_quote_characters, **argptr) != NULL)
- {
- p = skip_quoted (*argptr);
- *argptr = *argptr + 1;
- }
- else
- {
- p = *argptr;
- while (*p && *p != ' ' && *p != '\t' && *p != ',' && *p != ':')
- p++;
- }
-/*
- q = operator_chars (*argptr, &q1);
- if (q1 - q)
- {
- char *opname;
- char *tmp = alloca (q1 - q + 1);
- memcpy (tmp, q, q1 - q);
- tmp[q1 - q] = '\0';
- opname = cplus_mangle_opname (tmp, DMGL_ANSI);
- if (opname == NULL)
- {
- error_begin ();
- printf_filtered ("no mangling for \"%s\"\n", tmp);
- cplusplus_hint (saved_arg);
- return_to_top_level (RETURN_ERROR);
- }
- copy = (char*) alloca (3 + strlen(opname));
- sprintf (copy, "__%s", opname);
- p = q1;
- }
- else
- */
- {
- copy = (char *) alloca (p - *argptr + 1);
- memcpy (copy, *argptr, p - *argptr);
- copy[p - *argptr] = '\0';
- if (p != *argptr
- && copy[p - *argptr - 1]
- && strchr (gdb_completer_quote_characters,
- copy[p - *argptr - 1]) != NULL)
- copy[p - *argptr - 1] = '\0';
- }
-
- /* no line number may be specified */
- while (*p == ' ' || *p == '\t')
- p++;
- *argptr = p;
-
- sym = 0;
- i1 = 0; /* counter for the symbol array */
- sym_arr = (struct symbol **) alloca (total_number_of_methods (t)
- * sizeof (struct symbol *));
-
- if (destructor_name_p (copy, t))
- {
- /* Destructors are a special case. */
- int m_index, f_index;
-
- if (get_destructor_fn_field (t, &m_index, &f_index))
- {
- struct fn_field *f = TYPE_FN_FIELDLIST1 (t, m_index);
-
- sym_arr[i1] =
- lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, f_index),
- NULL, VAR_NAMESPACE, (int *) NULL,
- (struct symtab **) NULL);
- if (sym_arr[i1])
- i1++;
- }
- }
- else
- i1 = find_methods (t, copy, sym_arr);
- if (i1 == 1)
- {
- /* There is exactly one field with that name. */
- sym = sym_arr[0];
-
- if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
- {
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.nelts = 1;
- values.sals[0] = find_function_start_sal (sym,
- funfirstline);
- }
- else
- {
- values.nelts = 0;
- }
- return values;
- }
- if (i1 > 0)
- {
- /* There is more than one field with that name
- (overloaded). Ask the user which one to use. */
- return decode_line_2 (sym_arr, i1, funfirstline, canonical);
- }
- else
- {
- char *tmp;
-
- if (OPNAME_PREFIX_P (copy))
- {
- tmp = (char *) alloca (strlen (copy + 3) + 9);
- strcpy (tmp, "operator ");
- strcat (tmp, copy + 3);
- }
- else
- tmp = copy;
- error_begin ();
- if (tmp[0] == '~')
- printf_filtered
- ("the class `%s' does not have destructor defined\n",
- SYMBOL_SOURCE_NAME (sym_class));
- else
- printf_filtered
- ("the class %s does not have any method named %s\n",
- SYMBOL_SOURCE_NAME (sym_class), tmp);
- cplusplus_hint (saved_arg);
- return_to_top_level (RETURN_ERROR);
- }
- }
-
- /* Move pointer up to next possible class/namespace token */
- p = p2 + 1; /* restart with old value +1 */
- /* Move pointer ahead to next double-colon */
- while (*p && (p[0] != ' ') && (p[0] != '\t') && (p[0] != '\''))
- {
- if (p[0] == '<')
- {
- temp_end = find_template_name_end (p);
- if (!temp_end)
- error ("malformed template specification in command");
- p = temp_end;
- }
- else if ((p[0] == ':') && (p[1] == ':'))
- break; /* found double-colon */
- else
- p++;
- }
-
- if (*p != ':')
- break; /* out of the while (1) */
-
- p2 = p; /* save restart for next time around */
- *argptr = saved_arg2; /* restore argptr */
- } /* while (1) */
-
- /* Last chance attempt -- check entire name as a symbol */
- /* Use "copy" in preparation for jumping out of this block,
- to be consistent with usage following the jump target */
- copy = (char *) alloca (p - saved_arg2 + 1);
- memcpy (copy, saved_arg2, p - saved_arg2);
- /* Note: if is_quoted should be true, we snuff out quote here anyway */
- copy[p - saved_arg2] = '\000';
- /* Set argptr to skip over the name */
- *argptr = (*p == '\'') ? p + 1 : p;
- /* Look up entire name */
- sym = lookup_symbol (copy, 0, VAR_NAMESPACE, 0, &sym_symtab);
- s = (struct symtab *) 0;
- /* Prepare to jump: restore the " if (condition)" so outer layers see it */
- /* Symbol was found --> jump to normal symbol processing.
- Code following "symbol_found" expects "copy" to have the
- symbol name, "sym" to have the symbol pointer, "s" to be
- a specified file's symtab, and sym_symtab to be the symbol's
- symtab. */
- /* By jumping there we avoid falling through the FILE:LINE and
- FILE:FUNC processing stuff below */
- if (sym)
- goto symbol_found;
-
- /* Couldn't find any interpretation as classes/namespaces, so give up */
- error_begin ();
- /* The quotes are important if copy is empty. */
- printf_filtered
- ("Can't find member of namespace, class, struct, or union named \"%s\"\n", copy);
- cplusplus_hint (saved_arg);
- return_to_top_level (RETURN_ERROR);
- }
- /* end of C++ */
-
-
- /* Extract the file name. */
- p1 = p;
- while (p != *argptr && p[-1] == ' ')
- --p;
- if ((*p == '"') && is_quote_enclosed)
- --p;
- copy = (char *) alloca (p - *argptr + 1);
- if ((**argptr == '"') && is_quote_enclosed)
- {
- memcpy (copy, *argptr + 1, p - *argptr - 1);
- /* It may have the ending quote right after the file name */
- if (copy[p - *argptr - 2] == '"')
- copy[p - *argptr - 2] = 0;
- else
- copy[p - *argptr - 1] = 0;
- }
- else
- {
- memcpy (copy, *argptr, p - *argptr);
- copy[p - *argptr] = 0;
- }
-
- /* Find that file's data. */
- s = lookup_symtab (copy);
- if (s == 0)
- {
- if (!have_full_symbols () && !have_partial_symbols ())
- error (no_symtab_msg);
- error ("No source file named %s.", copy);
- }
-
- /* Discard the file name from the arg. */
- p = p1 + 1;
- while (*p == ' ' || *p == '\t')
- p++;
- *argptr = p;
- }
-#if 0
- /* No one really seems to know why this was added. It certainly
- breaks the command line, though, whenever the passed
- name is of the form ClassName::Method. This bit of code
- singles out the class name, and if funfirstline is set (for
- example, you are setting a breakpoint at this function),
- you get an error. This did not occur with earlier
- verions, so I am ifdef'ing this out. 3/29/99 */
- else
- {
- /* Check if what we have till now is a symbol name */
-
- /* We may be looking at a template instantiation such
- as "foo<int>". Check here whether we know about it,
- instead of falling through to the code below which
- handles ordinary function names, because that code
- doesn't like seeing '<' and '>' in a name -- the
- skip_quoted call doesn't go past them. So see if we
- can figure it out right now. */
-
- copy = (char *) alloca (p - *argptr + 1);
- memcpy (copy, *argptr, p - *argptr);
- copy[p - *argptr] = '\000';
- sym = lookup_symbol (copy, 0, VAR_NAMESPACE, 0, &sym_symtab);
- if (sym)
- {
- /* Yes, we have a symbol; jump to symbol processing */
- /* Code after symbol_found expects S, SYM_SYMTAB, SYM,
- and COPY to be set correctly */
- *argptr = (*p == '\'') ? p + 1 : p;
- s = (struct symtab *) 0;
- goto symbol_found;
- }
- /* Otherwise fall out from here and go to file/line spec
- processing, etc. */
- }
-#endif
-
- /* S is specified file's symtab, or 0 if no file specified.
- arg no longer contains the file name. */
-
- /* Check whether arg is all digits (and sign) */
-
- q = *argptr;
- if (*q == '-' || *q == '+')
- q++;
- while (*q >= '0' && *q <= '9')
- q++;
-
- if (q != *argptr && (*q == 0 || *q == ' ' || *q == '\t' || *q == ','))
- {
- /* We found a token consisting of all digits -- at least one digit. */
- enum sign
- {
- none, plus, minus
- }
- sign = none;
-
- /* We might need a canonical line spec if no file was specified. */
- int need_canonical = (s == 0) ? 1 : 0;
-
- /* This is where we need to make sure that we have good defaults.
- We must guarantee that this section of code is never executed
- when we are called with just a function name, since
- select_source_symtab calls us with such an argument */
-
- if (s == 0 && default_symtab == 0)
- {
- select_source_symtab (0);
- default_symtab = current_source_symtab;
- default_line = current_source_line;
- }
-
- if (**argptr == '+')
- sign = plus, (*argptr)++;
- else if (**argptr == '-')
- sign = minus, (*argptr)++;
- val.line = atoi (*argptr);
- switch (sign)
- {
- case plus:
- if (q == *argptr)
- val.line = 5;
- if (s == 0)
- val.line = default_line + val.line;
- break;
- case minus:
- if (q == *argptr)
- val.line = 15;
- if (s == 0)
- val.line = default_line - val.line;
- else
- val.line = 1;
- break;
- case none:
- break; /* No need to adjust val.line. */
- }
-
- while (*q == ' ' || *q == '\t')
- q++;
- *argptr = q;
- if (s == 0)
- s = default_symtab;
-
- /* It is possible that this source file has more than one symtab,
- and that the new line number specification has moved us from the
- default (in s) to a new one. */
- val.symtab = find_line_symtab (s, val.line, NULL, NULL);
- if (val.symtab == 0)
- val.symtab = s;
-
- val.pc = 0;
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.sals[0] = val;
- values.nelts = 1;
- if (need_canonical)
- build_canonical_line_spec (values.sals, NULL, canonical);
- return values;
- }
-
- /* Arg token is not digits => try it as a variable name
- Find the next token (everything up to end or next whitespace). */
-
- if (**argptr == '$') /* May be a convenience variable */
- p = skip_quoted (*argptr + (((*argptr)[1] == '$') ? 2 : 1)); /* One or two $ chars possible */
- else if (is_quoted)
- {
- p = skip_quoted (*argptr);
- if (p[-1] != '\'')
- error ("Unmatched single quote.");
- }
- else if (has_parens)
- {
- p = pp + 1;
- }
- else
- {
- p = skip_quoted (*argptr);
- }
-
- if (is_quote_enclosed && **argptr == '"')
- (*argptr)++;
-
- copy = (char *) alloca (p - *argptr + 1);
- memcpy (copy, *argptr, p - *argptr);
- copy[p - *argptr] = '\0';
- if (p != *argptr
- && copy[0]
- && copy[0] == copy[p - *argptr - 1]
- && strchr (gdb_completer_quote_characters, copy[0]) != NULL)
- {
- copy[p - *argptr - 1] = '\0';
- copy++;
- }
- while (*p == ' ' || *p == '\t')
- p++;
- *argptr = p;
-
- /* If it starts with $: may be a legitimate variable or routine name
- (e.g. HP-UX millicode routines such as $$dyncall), or it may
- be history value, or it may be a convenience variable */
-
- if (*copy == '$')
- {
- value_ptr valx;
- int index = 0;
- int need_canonical = 0;
-
- p = (copy[1] == '$') ? copy + 2 : copy + 1;
- while (*p >= '0' && *p <= '9')
- p++;
- if (!*p) /* reached end of token without hitting non-digit */
- {
- /* We have a value history reference */
- sscanf ((copy[1] == '$') ? copy + 2 : copy + 1, "%d", &index);
- valx = access_value_history ((copy[1] == '$') ? -index : index);
- if (TYPE_CODE (VALUE_TYPE (valx)) != TYPE_CODE_INT)
- error ("History values used in line specs must have integer values.");
- }
- else
- {
- /* Not all digits -- may be user variable/function or a
- convenience variable */
-
- /* Look up entire name as a symbol first */
- sym = lookup_symbol (copy, 0, VAR_NAMESPACE, 0, &sym_symtab);
- s = (struct symtab *) 0;
- need_canonical = 1;
- /* Symbol was found --> jump to normal symbol processing.
- Code following "symbol_found" expects "copy" to have the
- symbol name, "sym" to have the symbol pointer, "s" to be
- a specified file's symtab, and sym_symtab to be the symbol's
- symtab. */
- if (sym)
- goto symbol_found;
-
- /* If symbol was not found, look in minimal symbol tables */
- msymbol = lookup_minimal_symbol (copy, 0, 0);
- /* Min symbol was found --> jump to minsym processing. */
- if (msymbol)
- goto minimal_symbol_found;
-
- /* Not a user variable or function -- must be convenience variable */
- need_canonical = (s == 0) ? 1 : 0;
- valx = value_of_internalvar (lookup_internalvar (copy + 1));
- if (TYPE_CODE (VALUE_TYPE (valx)) != TYPE_CODE_INT)
- error ("Convenience variables used in line specs must have integer values.");
- }
-
- /* Either history value or convenience value from above, in valx */
- val.symtab = s ? s : default_symtab;
- val.line = value_as_long (valx);
- val.pc = 0;
-
- values.sals = (struct symtab_and_line *) xmalloc (sizeof val);
- values.sals[0] = val;
- values.nelts = 1;
-
- if (need_canonical)
- build_canonical_line_spec (values.sals, NULL, canonical);
-
- return values;
- }
-
-
- /* Look up that token as a variable.
- If file specified, use that file's per-file block to start with. */
-
- sym = lookup_symbol (copy,
- (s ? BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK)
- : get_selected_block ()),
- VAR_NAMESPACE, 0, &sym_symtab);
-
-symbol_found: /* We also jump here from inside the C++ class/namespace
- code on finding a symbol of the form "A::B::C" */
-
- if (sym != NULL)
- {
- if (SYMBOL_CLASS (sym) == LOC_BLOCK)
- {
- /* Arg is the name of a function */
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.sals[0] = find_function_start_sal (sym, funfirstline);
- values.nelts = 1;
-
- /* Don't use the SYMBOL_LINE; if used at all it points to
- the line containing the parameters or thereabouts, not
- the first line of code. */
-
- /* We might need a canonical line spec if it is a static
- function. */
- if (s == 0)
- {
- struct blockvector *bv = BLOCKVECTOR (sym_symtab);
- struct block *b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
- if (lookup_block_symbol (b, copy, VAR_NAMESPACE) != NULL)
- build_canonical_line_spec (values.sals, copy, canonical);
- }
- return values;
- }
- else
- {
- if (funfirstline)
- error ("\"%s\" is not a function", copy);
- else if (SYMBOL_LINE (sym) != 0)
- {
- /* We know its line number. */
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.nelts = 1;
- memset (&values.sals[0], 0, sizeof (values.sals[0]));
- values.sals[0].symtab = sym_symtab;
- values.sals[0].line = SYMBOL_LINE (sym);
- return values;
- }
- else
- /* This can happen if it is compiled with a compiler which doesn't
- put out line numbers for variables. */
- /* FIXME: Shouldn't we just set .line and .symtab to zero
- and return? For example, "info line foo" could print
- the address. */
- error ("Line number not known for symbol \"%s\"", copy);
- }
- }
-
- msymbol = lookup_minimal_symbol (copy, NULL, NULL);
-
-minimal_symbol_found: /* We also jump here from the case for variables
- that begin with '$' */
-
- if (msymbol != NULL)
- {
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.sals[0] = find_pc_sect_line (SYMBOL_VALUE_ADDRESS (msymbol),
- (struct sec *) 0, 0);
- values.sals[0].section = SYMBOL_BFD_SECTION (msymbol);
- if (funfirstline)
- {
- values.sals[0].pc += FUNCTION_START_OFFSET;
- values.sals[0].pc = SKIP_PROLOGUE (values.sals[0].pc);
- }
- values.nelts = 1;
- return values;
- }
-
- if (!have_full_symbols () &&
- !have_partial_symbols () && !have_minimal_symbols ())
- error (no_symtab_msg);
-
- error ("Function \"%s\" not defined.", copy);
- return values; /* for lint */
-}
-
-struct symtabs_and_lines
-decode_line_spec (char *string, int funfirstline)
-{
- struct symtabs_and_lines sals;
- if (string == 0)
- error ("Empty line specification.");
- sals = decode_line_1 (&string, funfirstline,
- current_source_symtab, current_source_line,
- (char ***) NULL);
- if (*string)
- error ("Junk at end of line specification: %s", string);
- return sals;
-}
-
-/* Given a list of NELTS symbols in SYM_ARR, return a list of lines to
- operate on (ask user if necessary).
- If CANONICAL is non-NULL return a corresponding array of mangled names
- as canonical line specs there. */
-
-static struct symtabs_and_lines
-decode_line_2 (sym_arr, nelts, funfirstline, canonical)
- struct symbol *sym_arr[];
- int nelts;
- int funfirstline;
- char ***canonical;
-{
- struct symtabs_and_lines values, return_values;
- char *args, *arg1;
- int i;
- char *prompt;
- char *symname;
- struct cleanup *old_chain;
- char **canonical_arr = (char **) NULL;
-
- values.sals = (struct symtab_and_line *)
- alloca (nelts * sizeof (struct symtab_and_line));
- return_values.sals = (struct symtab_and_line *)
- xmalloc (nelts * sizeof (struct symtab_and_line));
- old_chain = make_cleanup (free, return_values.sals);
-
- if (canonical)
- {
- canonical_arr = (char **) xmalloc (nelts * sizeof (char *));
- make_cleanup (free, canonical_arr);
- memset (canonical_arr, 0, nelts * sizeof (char *));
- *canonical = canonical_arr;
- }
-
- i = 0;
- printf_unfiltered ("[0] cancel\n[1] all\n");
- while (i < nelts)
- {
- INIT_SAL (&return_values.sals[i]); /* initialize to zeroes */
- INIT_SAL (&values.sals[i]);
- if (sym_arr[i] && SYMBOL_CLASS (sym_arr[i]) == LOC_BLOCK)
- {
- values.sals[i] = find_function_start_sal (sym_arr[i], funfirstline);
- printf_unfiltered ("[%d] %s at %s:%d\n",
- (i + 2),
- SYMBOL_SOURCE_NAME (sym_arr[i]),
- values.sals[i].symtab->filename,
- values.sals[i].line);
- }
- else
- printf_unfiltered ("?HERE\n");
- i++;
- }
-
- if ((prompt = getenv ("PS2")) == NULL)
- {
- prompt = "> ";
- }
- args = command_line_input (prompt, 0, "overload-choice");
-
- if (args == 0 || *args == 0)
- error_no_arg ("one or more choice numbers");
-
- i = 0;
- while (*args)
- {
- int num;
-
- arg1 = args;
- while (*arg1 >= '0' && *arg1 <= '9')
- arg1++;
- if (*arg1 && *arg1 != ' ' && *arg1 != '\t')
- error ("Arguments must be choice numbers.");
-
- num = atoi (args);
-
- if (num == 0)
- error ("cancelled");
- else if (num == 1)
- {
- if (canonical_arr)
- {
- for (i = 0; i < nelts; i++)
- {
- if (canonical_arr[i] == NULL)
- {
- symname = SYMBOL_NAME (sym_arr[i]);
- canonical_arr[i] = savestring (symname, strlen (symname));
- }
- }
- }
- memcpy (return_values.sals, values.sals,
- (nelts * sizeof (struct symtab_and_line)));
- return_values.nelts = nelts;
- discard_cleanups (old_chain);
- return return_values;
- }
-
- if (num >= nelts + 2)
- {
- printf_unfiltered ("No choice number %d.\n", num);
- }
- else
- {
- num -= 2;
- if (values.sals[num].pc)
- {
- if (canonical_arr)
- {
- symname = SYMBOL_NAME (sym_arr[num]);
- make_cleanup (free, symname);
- canonical_arr[i] = savestring (symname, strlen (symname));
- }
- return_values.sals[i++] = values.sals[num];
- values.sals[num].pc = 0;
- }
- else
- {
- printf_unfiltered ("duplicate request for %d ignored.\n", num);
- }
- }
-
- args = arg1;
- while (*args == ' ' || *args == '\t')
- args++;
- }
- return_values.nelts = i;
- discard_cleanups (old_chain);
- return return_values;
-}
-\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)
-{
- /* 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;
- /* 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;
-
- if (*first)
- {
- if (tab == NULL)
- tab = (char **) xmalloc (tab_alloc_size * sizeof (*tab));
- tab_cur_size = 0;
- }
-
- /* Is NAME 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)
- {
- tab_alloc_size *= 2;
- tab = (char **) xrealloc ((char *) tab, tab_alloc_size * sizeof (*tab));
- }
- tab[tab_cur_size++] = name;
-
- if (*first)
- {
- *first = 0;
- }
- else
- {
- printf_filtered (", ");
- }
-
- wrap_here ("");
- fputs_filtered (name, gdb_stdout);
-}
-
-static void
-sources_info (char *ignore, int from_tty)
-{
- register struct symtab *s;
- register struct partial_symtab *ps;
- register struct objfile *objfile;
- int first;
-
- if (!have_full_symbols () && !have_partial_symbols ())
- {
- error (no_symtab_msg);
- }
-
- printf_filtered ("Source files for which symbols have been read in:\n\n");
-
- first = 1;
- ALL_SYMTABS (objfile, s)
- {
- output_source_filename (s->filename, &first);
- }
- printf_filtered ("\n\n");
-
- printf_filtered ("Source files for which symbols will be read in on demand:\n\n");
-
- first = 1;
- ALL_PSYMTABS (objfile, ps)
- {
- if (!ps->readin)
- {
- output_source_filename (ps->filename, &first);
- }
- }
- printf_filtered ("\n");
-}
-
-static int
-file_matches (file, files, nfiles)
- char *file;
- char *files[];
- int nfiles;
-{
- int i;
-
- if (file != NULL && nfiles != 0)
- {
- for (i = 0; i < nfiles; i++)
- {
- if (strcmp (files[i], basename (file)) == 0)
- return 1;
- }
- }
- else if (nfiles == 0)
- return 1;
- return 0;
-}
-
-/* Free any memory associated with a search. */
-void
-free_search_symbols (struct symbol_search *symbols)
-{
- struct symbol_search *p;
- struct symbol_search *next;
-
- for (p = symbols; p != NULL; p = next)
- {
- next = p->next;
- free (p);
- }
-}
-
-static void
-do_free_search_symbols_cleanup (void *symbols)
-{
- free_search_symbols (symbols);
-}
-
-struct cleanup *
-make_cleanup_free_search_symbols (struct symbol_search *symbols)
-{
- return make_cleanup (do_free_search_symbols_cleanup, symbols);
-}
-
-
-/* Search the symbol table for matches to the regular expression REGEXP,
- returning the results in *MATCHES.
-
- Only symbols of KIND are searched:
- FUNCTIONS_NAMESPACE - search all functions
- TYPES_NAMESPACE - search all type names
- METHODS_NAMESPACE - search all methods NOT IMPLEMENTED
- VARIABLES_NAMESPACE - search all symbols, excluding functions, type names,
- and constants (enums)
-
- free_search_symbols should be called when *MATCHES is no longer needed.
- */
-void
-search_symbols (regexp, kind, nfiles, files, matches)
- char *regexp;
- namespace_enum kind;
- int nfiles;
- char *files[];
- struct symbol_search **matches;
-
-{
- register struct symtab *s;
- register struct partial_symtab *ps;
- register struct blockvector *bv;
- struct blockvector *prev_bv = 0;
- register struct block *b;
- register int i = 0;
- register int j;
- register struct symbol *sym;
- struct partial_symbol **psym;
- struct objfile *objfile;
- struct minimal_symbol *msymbol;
- char *val;
- int found_misc = 0;
- static enum minimal_symbol_type types[]
- =
- {mst_data, mst_text, mst_abs, mst_unknown};
- static enum minimal_symbol_type types2[]
- =
- {mst_bss, mst_file_text, mst_abs, mst_unknown};
- static enum minimal_symbol_type types3[]
- =
- {mst_file_data, mst_solib_trampoline, mst_abs, mst_unknown};
- static enum minimal_symbol_type types4[]
- =
- {mst_file_bss, mst_text, mst_abs, mst_unknown};
- enum minimal_symbol_type ourtype;
- enum minimal_symbol_type ourtype2;
- enum minimal_symbol_type ourtype3;
- enum minimal_symbol_type ourtype4;
- struct symbol_search *sr;
- struct symbol_search *psr;
- struct symbol_search *tail;
- struct cleanup *old_chain = NULL;
-
- if (kind < LABEL_NAMESPACE)
- error ("must search on specific namespace");
-
- ourtype = types[(int) (kind - VARIABLES_NAMESPACE)];
- ourtype2 = types2[(int) (kind - VARIABLES_NAMESPACE)];
- ourtype3 = types3[(int) (kind - VARIABLES_NAMESPACE)];
- ourtype4 = types4[(int) (kind - VARIABLES_NAMESPACE)];
-
- sr = *matches = NULL;
- tail = NULL;
-
- if (regexp != NULL)
+ if (regexp != NULL)
{
/* Make sure spacing is right for C++ operators.
This is just a courtesy to make the matching less sensitive
/* Typedef that is not a C++ class */
if (kind == TYPES_NAMESPACE
&& SYMBOL_NAMESPACE (sym) != STRUCT_NAMESPACE)
- c_typedef_print (SYMBOL_TYPE (sym), sym, gdb_stdout);
+ typedef_print (SYMBOL_TYPE (sym), sym, gdb_stdout);
/* variable, func, or typedef-that-is-c++-class */
else if (kind < TYPES_NAMESPACE ||
(kind == TYPES_NAMESPACE &&
else
{
fputs_filtered (demangled_name, stream);
- free (demangled_name);
+ xfree (demangled_name);
}
#endif
}
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 = longest_local_hex_string_custom (SYMBOL_VALUE_ADDRESS (msymbol)
+ & (CORE_ADDR) 0xffffffff,
+ "08l");
+ else
+ tmp = longest_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
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]))
- {
- free (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
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. */
+ char *tail = basename (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);
+ for (i = 0; i < BLOCK_NSYMS (b); i++)
+ {
+ sym = BLOCK_SYM (b, i);
+ COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
+ }
+
+ b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
+ for (i = 0; i < BLOCK_NSYMS (b); i++)
+ {
+ sym = BLOCK_SYM (b, i);
+ 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 *));
+ 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 = basename (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 = basename (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.
/* skip symbols that cannot match */
if (strcmp (sym_name, oload_name) != 0)
{
- free (sym_name);
+ xfree (sym_name);
return;
}
sym_return_val[sym_return_val_index++] = sym;
sym_return_val[sym_return_val_index] = NULL;
- free (sym_name);
+ xfree (sym_name);
}
/* Return a null-terminated list of pointers to function symbols that
}
}
- free (oload_name);
+ xfree (oload_name);
return (sym_return_val);
}
/* End of overload resolution functions */
\f
+struct symtabs_and_lines
+decode_line_spec (char *string, int funfirstline)
+{
+ struct symtabs_and_lines sals;
+ if (string == 0)
+ error ("Empty line specification.");
+ sals = decode_line_1 (&string, funfirstline,
+ current_source_symtab, current_source_line,
+ (char ***) NULL);
+ if (*string)
+ error ("Junk at end of line specification: %s", string);
+ return sals;
+}
void
_initialize_symtab (void)