/* Build symbol tables in GDB's internal format.
- Copyright (C) 1986-1991 Free Software Foundation, Inc.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991 Free Software Foundation, Inc.
This file is part of GDB.
make xcoffread.c more maintainable by sharing code. */
#include "defs.h"
-#include "param.h"
#include "obstack.h"
#include "symtab.h"
+#include "gdbtypes.h"
#include "breakpoint.h"
#include "gdbcore.h" /* for bfd stuff for symfile.h */
#include "symfile.h" /* Needed for "struct complaint" */
-#include "stab.gnu.h" /* We always use GNU stabs, not native */
-#include <stdio.h>
+#include "objfiles.h"
+#include "aout/stab_gnu.h" /* We always use GNU stabs, not native */
#include <string.h>
#include <ctype.h>
#include "buildsym.h" /* Our own declarations */
#undef EXTERN
-extern void qsort ();
-extern double atof ();
+static void
+patch_block_stabs PARAMS ((struct pending *, struct pending_stabs *,
+ struct objfile *));
-/* Things we export from outside, and probably shouldn't. FIXME. */
-extern void new_object_header_files ();
-extern char *next_symbol_text ();
-extern int hashname ();
-extern void patch_block_stabs (); /* AIX xcoffread.c */
-extern struct type *builtin_type (); /* AIX xcoffread.c */
-\f
+static void
+read_huge_number PARAMS ((char **, int, long *, int *));
+
+struct type *
+dbx_alloc_type PARAMS ((int [2], struct objfile *));
+
+static int
+compare_line_numbers PARAMS ((const void *, const void *));
+
+static struct blockvector *
+make_blockvector PARAMS ((struct objfile *));
+
+static void
+fix_common_block PARAMS ((struct symbol *, int));
-static void cleanup_undefined_types ();
-static void fix_common_block ();
+static void
+cleanup_undefined_types PARAMS ((void));
+
+static struct type *
+read_range_type PARAMS ((char **, int [2], struct objfile *));
+
+static struct type *
+read_enum_type PARAMS ((char **, struct type *, struct objfile *));
+
+static struct type *
+read_struct_type PARAMS ((char **, struct type *, struct objfile *));
+
+static struct type *
+read_array_type PARAMS ((char **, struct type *, struct objfile *));
+
+static struct type **
+read_args PARAMS ((char **, int, struct objfile *));
+
+\f
static const char vptr_name[] = { '_','v','p','t','r',CPLUS_MARKER,'\0' };
static const char vb_name[] = { '_','v','b',CPLUS_MARKER,'\0' };
#define BELIEVE_PCC_PROMOTION 0
#endif
+/* During some calls to read_type (and thus to read_range_type), this
+ contains the name of the type being defined. Range types are only
+ used in C as basic types. We use the name to distinguish the otherwise
+ identical basic types "int" and "long" and their unsigned versions.
+ FIXME, this should disappear with better type management. */
+
+static char *long_kludge_name;
+
/* Make a list of forward references which haven't been defined. */
static struct type **undef_types;
static int undef_types_allocated, undef_types_length;
Therefore GDB will not know about your class variables", 0, 0};
#endif
+struct complaint invalid_cpp_abbrev_complaint =
+ {"invalid C++ abbreviation `%s'", 0, 0};
+
+struct complaint invalid_cpp_type_complaint =
+ {"C++ abbreviated type name unknown at symtab pos %d", 0, 0};
+
+struct complaint member_fn_complaint =
+ {"member function type missing, got '%c'", 0, 0};
+
struct complaint const_vol_complaint =
- {"const/volatile indicator missing (ok if using g++ v1.x), got '%c'", 0, 0};
+ {"const/volatile indicator missing, got '%c'", 0, 0};
struct complaint error_type_complaint =
{"debug info mismatch between compiler and debugger", 0, 0};
struct complaint range_type_base_complaint =
{"base type %d of range type is not defined", 0, 0};
+
+struct complaint reg_value_complaint =
+ {"register number too large in symbol %s", 0, 0};
+\f
+int
+hashname (name)
+ char *name;
+{
+ register char *p = name;
+ register int total = p[0];
+ register int c;
+
+ c = p[1];
+ total += c << 2;
+ if (c)
+ {
+ c = p[2];
+ total += c << 4;
+ if (c)
+ total += p[3] << 6;
+ }
+
+ /* Ensure result is positive. */
+ if (total < 0) total += (1000 << 6);
+ return total % HASHSIZE;
+}
+
\f
/* Look up a dbx type-number pair. Return the address of the slot
where the type for that number-pair is stored.
register int filenum = typenums[0], index = typenums[1];
unsigned old_len;
+ if (filenum == -1) /* -1,-1 is for temporary types. */
+ return 0;
+
if (filenum < 0 || filenum >= n_this_object_header_files)
error ("Invalid symbol data: type number (%d,%d) out of range at symtab pos %d.",
filenum, index, symnum);
while (index >= type_vector_length)
type_vector_length *= 2;
type_vector = (struct type **)
- xrealloc (type_vector,
+ xrealloc ((char *) type_vector,
(type_vector_length * sizeof (struct type *)));
bzero (&type_vector[old_len],
(type_vector_length - old_len) * sizeof (struct type *));
while (index >= f->length)
f->length *= 2;
f->vector = (struct type **)
- xrealloc (f->vector, f->length * sizeof (struct type *));
+ xrealloc ((char *) f->vector, f->length * sizeof (struct type *));
bzero (&f->vector[f_orig_length],
(f->length - f_orig_length) * sizeof (struct type *));
}
}
}
-/* Create a type object. Occaisionally used when you need a type
- which isn't going to be given a type number. */
-
-struct type *
-dbx_create_type ()
-{
- register struct type *type =
- (struct type *) obstack_alloc (symbol_obstack, sizeof (struct type));
-
- bzero (type, sizeof (struct type));
- TYPE_VPTR_FIELDNO (type) = -1;
- TYPE_VPTR_BASETYPE (type) = 0;
- return type;
-}
-
/* Make sure there is a type allocated for type numbers TYPENUMS
and return the type object.
This can create an empty (zeroed) type object.
put into the type vector, and so may not be referred to by number. */
struct type *
-dbx_alloc_type (typenums)
+dbx_alloc_type (typenums, objfile)
int typenums[2];
+ struct objfile *objfile;
{
register struct type **type_addr;
- register struct type *type;
- if (typenums[0] != -1)
- {
- type_addr = dbx_lookup_type (typenums);
- type = *type_addr;
- }
- else
- {
- type_addr = 0;
- type = 0;
- }
+ if (typenums[0] == -1)
+ return alloc_type (objfile);
+
+ type_addr = dbx_lookup_type (typenums);
/* If we are referring to a type not known at all yet,
allocate an empty type for it.
We will fill it in later if we find out how. */
- if (type == 0)
- {
- type = dbx_create_type ();
- if (type_addr)
- *type_addr = type;
- }
-
- return type;
+ if (*type_addr == 0)
+ *type_addr = alloc_type (objfile);
+
+ return *type_addr;
}
\f
/* maintain the lists of symbols and blocks */
for (next = free_pendings; next; next = next1)
{
next1 = next->next;
- free (next);
+ free ((PTR)next);
}
free_pendings = 0;
for (bnext = pending_blocks; bnext; bnext = bnext1)
{
bnext1 = bnext->next;
- free (bnext);
+ free ((PTR)bnext);
}
#endif
pending_blocks = 0;
for (next = file_symbols; next; next = next1)
{
next1 = next->next;
- free (next);
+ free ((PTR)next);
}
file_symbols = 0;
for (next = global_symbols; next; next = next1)
{
next1 = next->next;
- free (next);
+ free ((PTR)next);
}
global_symbols = 0;
}
Put the block on the list of pending blocks. */
void
-finish_block (symbol, listhead, old_blocks, start, end)
+finish_block (symbol, listhead, old_blocks, start, end, objfile)
struct symbol *symbol;
struct pending **listhead;
struct pending_block *old_blocks;
CORE_ADDR start, end;
+ struct objfile *objfile;
{
register struct pending *next, *next1;
register struct block *block;
i += next->nsyms, next = next->next)
/*EMPTY*/;
- block = (struct block *) obstack_alloc (symbol_obstack,
+ block = (struct block *) obstack_alloc (&objfile -> symbol_obstack,
(sizeof (struct block) + ((i - 1) * sizeof (struct symbol *))));
/* Copy the symbols into the block. */
/* Allocate in the symbol_obstack to save time.
It wastes a little space. */
pblock = (struct pending_block *)
- obstack_alloc (symbol_obstack,
+ obstack_alloc (&objfile -> symbol_obstack,
sizeof (struct pending_block));
pblock->block = block;
if (opblock)
}
}
-struct blockvector *
-make_blockvector ()
+static struct blockvector *
+make_blockvector (objfile)
+ struct objfile *objfile;
{
register struct pending_block *next;
register struct blockvector *blockvector;
for (next = pending_blocks, i = 0; next; next = next->next, i++);
blockvector = (struct blockvector *)
- obstack_alloc (symbol_obstack,
+ obstack_alloc (&objfile -> symbol_obstack,
(sizeof (struct blockvector)
+ (i - 1) * sizeof (struct block *)));
if (BLOCK_START(BLOCKVECTOR_BLOCK (blockvector, i-1))
> BLOCK_START(BLOCKVECTOR_BLOCK (blockvector, i))) {
complain (&blockvector_complaint,
- BLOCK_START(BLOCKVECTOR_BLOCK (blockvector, i)));
+ (char *) BLOCK_START(BLOCKVECTOR_BLOCK (blockvector, i)));
}
}
#endif
current_subfile = subfile;
/* Save its name and compilation directory name */
- subfile->name = obsavestring (name, strlen (name));
+ subfile->name = strdup (name);
if (dirname == NULL)
subfile->dirname = NULL;
else
- subfile->dirname = obsavestring (dirname, strlen (dirname));
+ subfile->dirname = strdup (dirname);
/* Initialize line-number recording for this subfile. */
subfile->line_vector = 0;
if (current_subfile == 0 || current_subfile->name == 0)
abort ();
tem->name = current_subfile->name;
- tem->prev_index = header_file_prev_index;
}
char *
name = link->name;
subfile_stack = link->next;
- header_file_prev_index = link->prev_index;
- free (link);
+ free ((PTR)link);
return name;
}
{
subfile->line_vector_length *= 2;
subfile->line_vector = (struct linetable *)
- xrealloc (subfile->line_vector, (sizeof (struct linetable)
+ xrealloc ((char *) subfile->line_vector, (sizeof (struct linetable)
+ subfile->line_vector_length * sizeof (struct linetable_entry)));
}
/* Needed in order to sort line tables from IBM xcoff files. Sigh! */
-/* static */
-int
-compare_line_numbers (ln1, ln2)
- struct linetable_entry *ln1, *ln2;
+static int
+compare_line_numbers (ln1p, ln2p)
+ const PTR ln1p;
+ const PTR ln2p;
{
- return ln1->line - ln2->line;
+ return (((struct linetable_entry *) ln1p) -> line -
+ ((struct linetable_entry *) ln2p) -> line);
}
+
\f
/* Start a new symtab for a new source file.
This is called when a dbx symbol of type N_SO is seen;
file_symbols = 0;
global_symbols = 0;
global_stabs = 0; /* AIX COFF */
- file_stabs = 0; /* AIX COFF */
within_function = 0;
/* Context stack is initially empty. Allocate first one with room for
}
context_stack_depth = 0;
- new_object_header_files ();
+ /* Leave FILENUM of 0 free for builtin types and this file's types. */
+ n_this_object_header_files = 1;
type_vector_length = 0;
type_vector = (struct type **) 0;
start_subfile (name, dirname);
}
+/* for all the stabs in a given stab vector, build appropriate types
+ and fix their symbols in given symbol vector. */
+
+static void
+patch_block_stabs (symbols, stabs, objfile)
+ struct pending *symbols;
+ struct pending_stabs *stabs;
+ struct objfile *objfile;
+{
+ int ii;
+
+ if (stabs)
+ {
+
+ /* for all the stab entries, find their corresponding symbols and
+ patch their types! */
+
+ for (ii = 0; ii < stabs->count; ++ii)
+ {
+ char *name = stabs->stab[ii];
+ char *pp = (char*) strchr (name, ':');
+ struct symbol *sym = find_symbol_in_list (symbols, name, pp-name);
+ if (!sym)
+ {
+#ifndef IBM6000_TARGET
+ printf ("ERROR! stab symbol not found!\n"); /* FIXME */
+#endif
+ }
+ else
+ {
+ pp += 2;
+ if (*(pp-1) == 'F' || *(pp-1) == 'f')
+ {
+ SYMBOL_TYPE (sym) =
+ lookup_function_type (read_type (&pp, objfile));
+ }
+ else
+ {
+ SYMBOL_TYPE (sym) = read_type (&pp, objfile);
+ }
+ }
+ }
+ }
+}
+
/* Finish the symbol definitions for one main source file,
close off all the lexical contexts for that file
(creating struct block's for them), then make the struct symtab
cstk = &context_stack[context_stack_depth];
/* Make a block for the local symbols within. */
finish_block (cstk->name, &local_symbols, cstk->old_blocks,
- cstk->start_addr, end_addr);
+ cstk->start_addr, end_addr, objfile);
/* Debug: if context stack still has something in it, we are in
trouble. */
file_symbols is still good). */
cleanup_undefined_types ();
- /* Hooks for xcoffread.c */
- if (file_stabs) {
- patch_block_stabs (file_symbols, file_stabs);
- free (file_stabs);
- file_stabs = 0;
- }
-
if (global_stabs) {
- patch_block_stabs (global_symbols, global_stabs);
- free (global_stabs);
+ patch_block_stabs (global_symbols, global_stabs, objfile);
+ free ((PTR)global_stabs);
global_stabs = 0;
}
blockvector = NULL;
} else {
/* Define the STATIC_BLOCK and GLOBAL_BLOCK, and build the blockvector. */
- finish_block (0, &file_symbols, 0, last_source_start_addr, end_addr);
- finish_block (0, &global_symbols, 0, last_source_start_addr, end_addr);
- blockvector = make_blockvector ();
+ finish_block (0, &file_symbols, 0, last_source_start_addr, end_addr, objfile);
+ finish_block (0, &global_symbols, 0, last_source_start_addr, end_addr, objfile);
+ blockvector = make_blockvector (objfile);
}
+#ifdef PROCESS_LINENUMBER_HOOK
+ PROCESS_LINENUMBER_HOOK (); /* Needed for aixcoff. */
+#endif
+
/* Now create the symtab objects proper, one for each subfile. */
/* (The main file is the last one on the chain.) */
for (subfile = subfiles; subfile; subfile = nextsub)
{
+ int linetablesize;
/* If we have blocks of symbols, make a symtab.
Otherwise, just ignore this file and any line number info in it. */
symtab = 0;
if (blockvector) {
if (subfile->line_vector) {
/* First, shrink the linetable to make more memory. */
+ linetablesize = sizeof (struct linetable) +
+ subfile->line_vector->nitems * sizeof (struct linetable_entry);
subfile->line_vector = (struct linetable *)
- xrealloc (subfile->line_vector, (sizeof (struct linetable)
- + subfile->line_vector->nitems * sizeof (struct linetable_entry)));
+ xrealloc ((char *) subfile->line_vector, linetablesize);
if (sort_linevec)
qsort (subfile->line_vector->item, subfile->line_vector->nitems,
/* Fill in its components. */
symtab->blockvector = blockvector;
- symtab->linetable = subfile->line_vector;
+ if (subfile->line_vector)
+ {
+ /* Reallocate the line table on the symbol obstack */
+ symtab->linetable = (struct linetable *)
+ obstack_alloc (&objfile -> symbol_obstack, linetablesize);
+ memcpy (symtab->linetable, subfile->line_vector, linetablesize);
+ }
+ else
+ {
+ symtab->linetable = NULL;
+ }
symtab->dirname = subfile->dirname;
symtab->free_code = free_linetable;
symtab->free_ptr = 0;
- /* Link the new symtab into the list of such. */
- symtab->next = symtab_list;
- symtab_list = symtab;
- } else {
- /* No blocks for this file. Delete any line number info we have
- for it. */
- if (subfile->line_vector)
- free (subfile->line_vector);
+#ifdef IBM6000_TARGET
+ /* In case we need to duplicate symbol tables (to represent include
+ files), and in case our system needs relocation, we want to
+ relocate the main symbol table node only (for the main file,
+ not for the include files). */
+
+ symtab->nonreloc = TRUE;
+#endif
}
+ if (subfile->line_vector)
+ free ((PTR)subfile->line_vector);
nextsub = subfile->next;
- free (subfile);
+ free ((PTR)subfile);
}
+#ifdef IBM6000_TARGET
+ /* all include symbol tables are non-relocatable, except the main source
+ file's. */
+ if (symtab)
+ symtab->nonreloc = FALSE;
+#endif
+
if (type_vector)
free ((char *) type_vector);
type_vector = 0;
last_source_file = 0;
current_subfile = 0;
+ previous_stab_code = 0;
return symtab;
}
{
context_stack_size *= 2;
context_stack = (struct context_stack *)
- xrealloc (context_stack,
- (context_stack_size
- * sizeof (struct context_stack)));
+ xrealloc ((char *) context_stack,
+ (context_stack_size * sizeof (struct context_stack)));
}
new = &context_stack[context_stack_depth++];
/* Scan through all of the global symbols defined in the object file,
assigning values to the debugging symbols that need to be assigned
- to. Get these symbols from the misc function list. */
+ to. Get these symbols from the minimal symbol table. */
void
-scan_file_globals ()
+scan_file_globals (objfile)
+ struct objfile *objfile;
{
int hash;
- int mf;
+ struct minimal_symbol *msymbol;
+ struct symbol *sym, *prev;
- for (mf = 0; mf < misc_function_count; mf++)
+ for (msymbol = objfile -> msymbols; msymbol -> name != NULL; msymbol++)
{
- char *namestring = misc_function_vector[mf].name;
- struct symbol *sym, *prev;
-
QUIT;
prev = (struct symbol *) 0;
/* Get the hash index and check all the symbols
under that hash index. */
- hash = hashname (namestring);
+ hash = hashname (msymbol -> name);
for (sym = global_sym_chain[hash]; sym;)
{
- if (*namestring == SYMBOL_NAME (sym)[0]
- && !strcmp(namestring + 1, SYMBOL_NAME (sym) + 1))
+ if (*(msymbol -> name) == SYMBOL_NAME (sym)[0]
+ && !strcmp(msymbol -> name + 1, SYMBOL_NAME (sym) + 1))
{
/* Splice this symbol out of the hash chain and
assign the value we have to it. */
/* Note: this code might be executed several times for
the same symbol if there are multiple references. */
if (SYMBOL_CLASS (sym) == LOC_BLOCK)
- fix_common_block (sym, misc_function_vector[mf].address);
+ fix_common_block (sym, msymbol -> address);
else
- SYMBOL_VALUE_ADDRESS (sym) = misc_function_vector[mf].address;
+ SYMBOL_VALUE_ADDRESS (sym) = msymbol -> address;
if (prev)
sym = SYMBOL_VALUE_CHAIN (prev);
/* ARGSUSED */
struct symbol *
-define_symbol (valu, string, desc, type)
+define_symbol (valu, string, desc, type, objfile)
unsigned int valu;
char *string;
int desc;
int type;
+ struct objfile *objfile;
{
register struct symbol *sym;
char *p = (char *) strchr (string, ':');
int deftype;
int synonym = 0;
register int i;
+ struct type *temptype;
+
+#ifdef IBM6000_TARGET
+ /* We would like to eliminate nameless symbols, but keep their types.
+ E.g. stab entry ":t10=*2" should produce a type 10, which is a pointer
+ to type 2, but, should not creat a symbol to address that type. Since
+ the symbol will be nameless, there is no way any user can refer to it. */
+
+ int nameless;
+#endif
/* Ignore syms with empty names. */
if (string[0] == 0)
if (p == 0)
return 0;
- sym = (struct symbol *)obstack_alloc (symbol_obstack, sizeof (struct symbol));
+#ifdef IBM6000_TARGET
+ /* If a nameless stab entry, all we need is the type, not the symbol.
+ e.g. ":t10=*2" */
+ nameless = (p == string);
+#endif
+
+ sym = (struct symbol *)obstack_alloc (&objfile -> symbol_obstack, sizeof (struct symbol));
if (processing_gcc_compilation) {
/* GCC 2.x puts the line number in desc. SunOS apparently puts in the
switch (string[1])
{
case 't':
- SYMBOL_NAME (sym) = "this";
+ SYMBOL_NAME (sym) = obsavestring ("this", strlen ("this"),
+ &objfile -> symbol_obstack);
break;
case 'v': /* $vtbl_ptr_type */
/* Was: SYMBOL_NAME (sym) = "vptr"; */
goto normal;
case 'e':
- SYMBOL_NAME (sym) = "eh_throw";
+ SYMBOL_NAME (sym) = obsavestring ("eh_throw", strlen ("eh_throw"),
+ &objfile -> symbol_obstack);
break;
case '_':
{
normal:
SYMBOL_NAME (sym)
- = (char *) obstack_alloc (symbol_obstack, ((p - string) + 1));
+ = (char *) obstack_alloc (&objfile -> symbol_obstack, ((p - string) + 1));
/* Open-coded bcopy--saves function call time. */
{
register char *p1 = string;
Handle Sun-style local fortran array types 'ar...' .
(gnu@cygnus.com) -- this strchr() handles them properly?
(tiemann@cygnus.com) -- 'C' is for catch. */
+
+#ifdef IBM6000_TARGET
+
+ /* 'R' is for register parameters. */
+
+ if (!strchr ("cfFGpPrStTvVXCR", *p))
+#else
+
if (!strchr ("cfFGpPrStTvVXC", *p))
+#endif
deftype = 'l';
else
deftype = *p++;
double d = atof (p);
char *dbl_valu;
- SYMBOL_TYPE (sym) = builtin_type_double;
- dbl_valu =
- (char *) obstack_alloc (symbol_obstack, sizeof (double));
- bcopy (&d, dbl_valu, sizeof (double));
+ SYMBOL_TYPE (sym) = lookup_fundamental_type (objfile,
+ FT_DBL_PREC_FLOAT);
+ dbl_valu = (char *)
+ obstack_alloc (&objfile -> type_obstack,
+ sizeof (double));
+ memcpy (dbl_valu, &d, sizeof (double));
SWAP_TARGET_AND_HOST (dbl_valu, sizeof (double));
SYMBOL_VALUE_BYTES (sym) = dbl_valu;
SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
break;
case 'i':
{
- SYMBOL_TYPE (sym) = builtin_type_int;
+ SYMBOL_TYPE (sym) = lookup_fundamental_type (objfile,
+ FT_INTEGER);
SYMBOL_VALUE (sym) = atoi (p);
SYMBOL_CLASS (sym) = LOC_CONST;
}
{
p++;
SYMBOL_TYPE (sym)
- = lookup_pointer_type (lookup_function_type (read_type (&p)));
+ = lookup_pointer_type (lookup_function_type (read_type (&p, objfile)));
}
+
+#ifdef IBM6000_TARGET
+ else if (deftype == 'R')
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+#endif
+
else
{
struct type *type_read;
{
p += 1;
type_synonym_name = obsavestring (SYMBOL_NAME (sym),
- strlen (SYMBOL_NAME (sym)));
+ strlen (SYMBOL_NAME (sym)),
+ &objfile -> symbol_obstack);
}
- type_read = read_type (&p);
+ /* Here we save the name of the symbol for read_range_type, which
+ ends up reading in the basic types. In stabs, unfortunately there
+ is no distinction between "int" and "long" types except their
+ names. Until we work out a saner type policy (eliminating most
+ builtin types and using the names specified in the files), we
+ save away the name so that far away from here in read_range_type,
+ we can examine it to decide between "int" and "long". FIXME. */
+ long_kludge_name = SYMBOL_NAME (sym);
+
+ type_read = read_type (&p, objfile);
if ((deftype == 'F' || deftype == 'f')
&& TYPE_CODE (type_read) != TYPE_CODE_FUNC)
#if 0
/* This code doesn't work -- it needs to realloc and can't. */
struct type *new = (struct type *)
- obstack_alloc (symbol_obstack, sizeof (struct type));
+ obstack_alloc (&objfile -> type_obstack,
+ sizeof (struct type));
/* Generate a template for the type of this function. The
types of the arguments will be added as we read the symbol
table. */
*new = *lookup_function_type (type_read);
SYMBOL_TYPE(sym) = new;
+ TYPE_OBJFILE (new) = objfile;
in_function_type = new;
#else
SYMBOL_TYPE (sym) = lookup_function_type (type_read);
up). I made this code adapt so that it will offset the symbol
if it was pointing at an int-aligned location and not
otherwise. This way you can use the same gdb for 4.0.x and
- 4.1 systems. */
+ 4.1 systems.
- if (0 == SYMBOL_VALUE (sym) % sizeof (int))
+ If the parameter is shorter than an int, and is integral
+ (e.g. char, short, or unsigned equivalent), and is claimed to
+ be passed on an integer boundary, don't believe it! Offset the
+ parameter's address to the tail-end of that integer. */
+
+ temptype = lookup_fundamental_type (objfile, FT_INTEGER);
+ if (TYPE_LENGTH (SYMBOL_TYPE (sym)) < TYPE_LENGTH (temptype)
+ && TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_INT
+ && 0 == SYMBOL_VALUE (sym) % TYPE_LENGTH (temptype))
{
- if (SYMBOL_TYPE (sym) == builtin_type_char
- || SYMBOL_TYPE (sym) == builtin_type_unsigned_char)
- SYMBOL_VALUE (sym) += 3;
- else if (SYMBOL_TYPE (sym) == builtin_type_short
- || SYMBOL_TYPE (sym) == builtin_type_unsigned_short)
- SYMBOL_VALUE (sym) += 2;
+ SYMBOL_VALUE (sym) += TYPE_LENGTH (temptype)
+ - TYPE_LENGTH (SYMBOL_TYPE (sym));
}
break;
/* If PCC says a parameter is a short or a char,
it is really an int. */
- if (SYMBOL_TYPE (sym) == builtin_type_char
- || SYMBOL_TYPE (sym) == builtin_type_short)
- SYMBOL_TYPE (sym) = builtin_type_int;
- else if (SYMBOL_TYPE (sym) == builtin_type_unsigned_char
- || SYMBOL_TYPE (sym) == builtin_type_unsigned_short)
- SYMBOL_TYPE (sym) = builtin_type_unsigned_int;
+ temptype = lookup_fundamental_type (objfile, FT_INTEGER);
+ if (TYPE_LENGTH (SYMBOL_TYPE (sym)) < TYPE_LENGTH (temptype)
+ && TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_INT)
+ {
+ SYMBOL_TYPE (sym) = TYPE_UNSIGNED (SYMBOL_TYPE (sym))
+ ? lookup_fundamental_type (objfile, FT_UNSIGNED_INTEGER)
+ : temptype;
+ }
break;
#endif /* no BELIEVE_PCC_PROMOTION_TYPE. */
case 'P':
+ /* Parameter which is in a register. */
SYMBOL_CLASS (sym) = LOC_REGPARM;
SYMBOL_VALUE (sym) = STAB_REG_TO_REGNUM (valu);
+ if (SYMBOL_VALUE (sym) >= NUM_REGS)
+ {
+ complain (®_value_complaint, SYMBOL_NAME (sym));
+ SYMBOL_VALUE (sym) = SP_REGNUM; /* Known safe, though useless */
+ }
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
add_symbol_to_list (sym, &local_symbols);
break;
+#ifdef IBM6000_TARGET
+ case 'R':
+#endif
case 'r':
+ /* Register variable (either global or local). */
SYMBOL_CLASS (sym) = LOC_REGISTER;
SYMBOL_VALUE (sym) = STAB_REG_TO_REGNUM (valu);
+ if (SYMBOL_VALUE (sym) >= NUM_REGS)
+ {
+ complain (®_value_complaint, SYMBOL_NAME (sym));
+ SYMBOL_VALUE (sym) = SP_REGNUM; /* Known safe, though useless */
+ }
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
- add_symbol_to_list (sym, &local_symbols);
+ if (within_function)
+ add_symbol_to_list (sym, &local_symbols);
+ else
+ add_symbol_to_list (sym, &file_symbols);
break;
case 'S':
break;
case 't':
+#ifdef IBM6000_TARGET
+ /* For a nameless type, we don't want a create a symbol, thus we
+ did not use `sym'. Return without further processing. */
+
+ if (nameless) return NULL;
+#endif
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
SYMBOL_VALUE (sym) = valu;
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
- if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0
- && (TYPE_FLAGS (SYMBOL_TYPE (sym)) & TYPE_FLAG_PERM) == 0)
- TYPE_NAME (SYMBOL_TYPE (sym)) =
- obsavestring (SYMBOL_NAME (sym),
- strlen (SYMBOL_NAME (sym)));
- /* C++ vagaries: we may have a type which is derived from
- a base type which did not have its name defined when the
- derived class was output. We fill in the derived class's
- base part member's name here in that case. */
- else if ((TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT
+ /* C++ vagaries: we may have a type which is derived from
+ a base type which did not have its name defined when the
+ derived class was output. We fill in the derived class's
+ base part member's name here in that case. */
+ if (TYPE_NAME (SYMBOL_TYPE (sym)) != NULL)
+ if ((TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT
|| TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_UNION)
&& TYPE_N_BASECLASSES (SYMBOL_TYPE (sym)))
{
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
SYMBOL_VALUE (sym) = valu;
SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
- if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0
- && (TYPE_FLAGS (SYMBOL_TYPE (sym)) & TYPE_FLAG_PERM) == 0)
+ if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0)
TYPE_NAME (SYMBOL_TYPE (sym))
- = obconcat ("",
+ = obconcat (&objfile -> type_obstack, "",
(TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_ENUM
? "enum "
: (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT
if (synonym)
{
- register struct symbol *typedef_sym
- = (struct symbol *) obstack_alloc (symbol_obstack, sizeof (struct symbol));
+ register struct symbol *typedef_sym = (struct symbol *)
+ obstack_alloc (&objfile -> type_obstack,
+ sizeof (struct symbol));
SYMBOL_NAME (typedef_sym) = SYMBOL_NAME (sym);
SYMBOL_TYPE (typedef_sym) = SYMBOL_TYPE (sym);
{
undef_types_allocated *= 2;
undef_types = (struct type **)
- xrealloc (undef_types,
+ xrealloc ((char *) undef_types,
undef_types_allocated * sizeof (struct type *));
}
undef_types[undef_types_length++] = type;
}
-/* Add here something to go through each undefined type, see if it's
- still undefined, and do a full lookup if so. */
+/* Go through each undefined type, see if it's still undefined, and fix it
+ up if possible. We have two kinds of undefined types:
+
+ TYPE_CODE_ARRAY: Array whose target type wasn't defined yet.
+ Fix: update array length using the element bounds
+ and the target type's length.
+ TYPE_CODE_STRUCT, TYPE_CODE_UNION: Structure whose fields were not
+ yet defined at the time a pointer to it was made.
+ Fix: Do a full lookup on the struct/union tag. */
static void
cleanup_undefined_types ()
{
struct type **type;
- for (type = undef_types; type < undef_types + undef_types_length; type++)
- {
- /* Reasonable test to see if it's been defined since. */
- if (TYPE_NFIELDS (*type) == 0)
- {
- struct pending *ppt;
- int i;
- /* Name of the type, without "struct" or "union" */
- char *typename = TYPE_NAME (*type);
+ for (type = undef_types; type < undef_types + undef_types_length; type++) {
+ switch (TYPE_CODE (*type)) {
- if (!strncmp (typename, "struct ", 7))
- typename += 7;
- if (!strncmp (typename, "union ", 6))
- typename += 6;
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ case TYPE_CODE_ENUM:
+ {
+ /* Reasonable test to see if it's been defined since. */
+ if (TYPE_NFIELDS (*type) == 0)
+ {
+ struct pending *ppt;
+ int i;
+ /* Name of the type, without "struct" or "union" */
+ char *typename = TYPE_NAME (*type);
+
+ if (!strncmp (typename, "struct ", 7))
+ typename += 7;
+ if (!strncmp (typename, "union ", 6))
+ typename += 6;
+ if (!strncmp (typename, "enum ", 5))
+ typename += 5;
+
+ for (ppt = file_symbols; ppt; ppt = ppt->next)
+ for (i = 0; i < ppt->nsyms; i++)
+ {
+ struct symbol *sym = ppt->symbol[i];
+
+ if (SYMBOL_CLASS (sym) == LOC_TYPEDEF
+ && SYMBOL_NAMESPACE (sym) == STRUCT_NAMESPACE
+ && (TYPE_CODE (SYMBOL_TYPE (sym)) ==
+ TYPE_CODE (*type))
+ && !strcmp (SYMBOL_NAME (sym), typename))
+ memcpy (*type, SYMBOL_TYPE (sym), sizeof (struct type));
+ }
+ }
+ else
+ /* It has been defined; don't mark it as a stub. */
+ TYPE_FLAGS (*type) &= ~TYPE_FLAG_STUB;
+ }
+ break;
- for (ppt = file_symbols; ppt; ppt = ppt->next)
- for (i = 0; i < ppt->nsyms; i++)
- {
- struct symbol *sym = ppt->symbol[i];
-
- if (SYMBOL_CLASS (sym) == LOC_TYPEDEF
- && SYMBOL_NAMESPACE (sym) == STRUCT_NAMESPACE
- && (TYPE_CODE (SYMBOL_TYPE (sym)) ==
- TYPE_CODE (*type))
- && !strcmp (SYMBOL_NAME (sym), typename))
- bcopy (SYMBOL_TYPE (sym), *type, sizeof (struct type));
- }
+ case TYPE_CODE_ARRAY:
+ {
+ struct type *range_type;
+ int lower, upper;
+
+ if (TYPE_LENGTH (*type) != 0) /* Better be unknown */
+ goto badtype;
+ if (TYPE_NFIELDS (*type) != 1)
+ goto badtype;
+ range_type = TYPE_FIELD_TYPE (*type, 0);
+ if (TYPE_CODE (range_type) != TYPE_CODE_RANGE)
+ goto badtype;
+
+ /* Now recompute the length of the array type, based on its
+ number of elements and the target type's length. */
+ lower = TYPE_FIELD_BITPOS (range_type, 0);
+ upper = TYPE_FIELD_BITPOS (range_type, 1);
+ TYPE_LENGTH (*type) = (upper - lower + 1)
+ * TYPE_LENGTH (TYPE_TARGET_TYPE (*type));
}
- else
- /* It has been defined; don't mark it as a stub. */
- TYPE_FLAGS (*type) &= ~TYPE_FLAG_STUB;
+ break;
+
+ default:
+ badtype:
+ error ("GDB internal error. cleanup_undefined_types with bad\
+ type %d.", TYPE_CODE (*type));
+ break;
}
+ }
undef_types_length = 0;
}
\f
follows the =. */
struct type *
-read_type (pp)
+read_type (pp, objfile)
register char **pp;
+ struct objfile *objfile;
{
register struct type *type = 0;
struct type *type1;
or this is a forward reference to it. dbx_alloc_type handles
both cases. */
if (**pp != '=')
- return dbx_alloc_type (typenums);
+ return dbx_alloc_type (typenums, objfile);
/* Type is being defined here. */
#if 0 /* Callers aren't prepared for a NULL result! FIXME -- metin! */
}
to = type_name = (char *)
- obstack_alloc (symbol_obstack,
+ obstack_alloc (&objfile -> type_obstack,
(strlen (prefix) +
((char *) strchr (*pp, ':') - (*pp)) + 1));
&& (TYPE_CODE (SYMBOL_TYPE (sym)) == code)
&& !strcmp (SYMBOL_NAME (sym), type_name_only))
{
- obstack_free (symbol_obstack, type_name);
+ obstack_free (&objfile -> type_obstack, type_name);
type = SYMBOL_TYPE (sym);
return type;
}
structure for it, and keep track of it so we can
fill in the rest of the fields when we get the full
type. */
- type = dbx_alloc_type (typenums);
+ type = dbx_alloc_type (typenums, objfile);
TYPE_CODE (type) = code;
TYPE_NAME (type) = type_name;
-
+ INIT_CPLUS_SPECIFIC(type);
TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
add_undefined_type (type);
after_digits:
if (type == 0)
- type = builtin_type_void;
+ type = lookup_fundamental_type (objfile, FT_VOID);
if (typenums[0] != -1)
*dbx_lookup_type (typenums) = type;
break;
+ /* In the following types, we must be sure to overwrite any existing
+ type that the typenums refer to, rather than allocating a new one
+ and making the typenums point to the new one. This is because there
+ may already be pointers to the existing type (if it had been
+ forward-referenced), and we must change it to a pointer, function,
+ reference, or whatever, *in-place*. */
+
case '*':
- type1 = read_type (pp);
-/* FIXME -- we should be doing smash_to_XXX types here. */
-#if 0
- /* postponed type decoration should be allowed. */
- if (typenums[1] > 0 && typenums[1] < type_vector_length &&
- (type = type_vector[typenums[1]])) {
- smash_to_pointer_type (type, type1);
+ type1 = read_type (pp, objfile);
+ type = make_pointer_type (type1, dbx_lookup_type (typenums));
break;
- }
-#endif
- type = lookup_pointer_type (type1);
- if (typenums[0] != -1)
- *dbx_lookup_type (typenums) = type;
+
+ case '&': /* Reference to another type */
+ type1 = read_type (pp, objfile);
+ type = make_reference_type (type1, dbx_lookup_type (typenums));
+ break;
+
+ case 'f': /* Function returning another type */
+ type1 = read_type (pp, objfile);
+ type = make_function_type (type1, dbx_lookup_type (typenums));
break;
- case '@':
+/* FIXME -- we should be doing smash_to_XXX types here. */
+ case '@': /* Member (class & variable) type */
{
- struct type *domain = read_type (pp);
+ struct type *domain = read_type (pp, objfile);
struct type *memtype;
if (**pp != ',')
return error_type (pp);
++*pp;
- memtype = read_type (pp);
- type = dbx_alloc_type (typenums);
+ memtype = read_type (pp, objfile);
+ type = dbx_alloc_type (typenums, objfile);
smash_to_member_type (type, domain, memtype);
}
break;
- case '#':
+ case '#': /* Method (class & fn) type */
if ((*pp)[0] == '#')
{
/* We'll get the parameter types from the name. */
struct type *return_type;
*pp += 1;
- return_type = read_type (pp);
+ return_type = read_type (pp, objfile);
if (*(*pp)++ != ';')
- complain (&invalid_member_complaint, symnum);
+ complain (&invalid_member_complaint, (char *) symnum);
type = allocate_stub_method (return_type);
if (typenums[0] != -1)
*dbx_lookup_type (typenums) = type;
}
else
{
- struct type *domain = read_type (pp);
+ struct type *domain = read_type (pp, objfile);
struct type *return_type;
struct type **args;
error ("invalid member type data format, at symtab pos %d.",
symnum);
- return_type = read_type (pp);
- args = read_args (pp, ';');
- type = dbx_alloc_type (typenums);
+ return_type = read_type (pp, objfile);
+ args = read_args (pp, ';', objfile);
+ type = dbx_alloc_type (typenums, objfile);
smash_to_method_type (type, domain, return_type, args);
}
break;
- case '&':
- type1 = read_type (pp);
- type = lookup_reference_type (type1);
+ case 'r': /* Range type */
+ type = read_range_type (pp, typenums, objfile);
if (typenums[0] != -1)
*dbx_lookup_type (typenums) = type;
break;
- case 'f':
- type1 = read_type (pp);
- type = lookup_function_type (type1);
- if (typenums[0] != -1)
- *dbx_lookup_type (typenums) = type;
- break;
-
- case 'r':
- type = read_range_type (pp, typenums);
- if (typenums[0] != -1)
- *dbx_lookup_type (typenums) = type;
- break;
-
- case 'e':
- type = dbx_alloc_type (typenums);
- type = read_enum_type (pp, type);
+ case 'e': /* Enumeration type */
+ type = dbx_alloc_type (typenums, objfile);
+ type = read_enum_type (pp, type, objfile);
*dbx_lookup_type (typenums) = type;
break;
- case 's':
- type = dbx_alloc_type (typenums);
- TYPE_NAME (type) = type_synonym_name;
+ case 's': /* Struct type */
+ type = dbx_alloc_type (typenums, objfile);
+ if (!TYPE_NAME (type))
+ TYPE_NAME (type) = type_synonym_name;
type_synonym_name = 0;
- type = read_struct_type (pp, type);
+ type = read_struct_type (pp, type, objfile);
break;
- case 'u':
- type = dbx_alloc_type (typenums);
- TYPE_NAME (type) = type_synonym_name;
+ case 'u': /* Union type */
+ type = dbx_alloc_type (typenums, objfile);
+ if (!TYPE_NAME (type))
+ TYPE_NAME (type) = type_synonym_name;
type_synonym_name = 0;
- type = read_struct_type (pp, type);
+ type = read_struct_type (pp, type, objfile);
TYPE_CODE (type) = TYPE_CODE_UNION;
break;
- case 'a':
+ case 'a': /* Array type */
if (**pp != 'r')
return error_type (pp);
++*pp;
- type = dbx_alloc_type (typenums);
- type = read_array_type (pp, type);
+ type = dbx_alloc_type (typenums, objfile);
+ type = read_array_type (pp, type, objfile);
break;
default:
if (type == 0)
abort ();
-#if 0
- /* If this is an overriding temporary alteration for a header file's
- contents, and this type number is unknown in the global definition,
- put this type into the global definition at this type number. */
- if (header_file_prev_index >= 0)
- {
- register struct type **tp
- = explicit_lookup_type (header_file_prev_index, typenums[1]);
- if (*tp == 0)
- *tp = type;
- }
-#endif
return type;
}
\f
/* Read the description of a structure (or union type)
and return an object describing the type. */
-struct type *
-read_struct_type (pp, type)
+static struct type *
+read_struct_type (pp, type, objfile)
char **pp;
register struct type *type;
+ struct objfile *objfile;
{
/* Total number of methods defined in this class.
If the class defines two `f' methods, and one `g' method,
struct next_fnfield
{
struct next_fnfield *next;
- int visibility; /* 0=public, 1=protected, 2=public */
struct fn_field fn_field;
};
struct nextfield *new;
register char *p;
int nfields = 0;
+ int non_public_fields = 0;
register int n;
register struct next_fnfieldlist *mainlist = 0;
int nfn_fields = 0;
- if (TYPE_MAIN_VARIANT (type) == 0)
- {
- TYPE_MAIN_VARIANT (type) = type;
- }
-
TYPE_CODE (type) = TYPE_CODE_STRUCT;
+ INIT_CPLUS_SPECIFIC(type);
/* First comes the total size in bytes. */
*pp += 1;
+ ALLOCATE_CPLUS_STRUCT_TYPE(type);
+
n_baseclasses = read_number (pp, ',');
TYPE_FIELD_VIRTUAL_BITS (type) =
- (B_TYPE *) obstack_alloc (symbol_obstack, B_BYTES (n_baseclasses));
+ (B_TYPE *) obstack_alloc (&objfile -> type_obstack,
+ B_BYTES (n_baseclasses));
B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), n_baseclasses);
for (i = 0; i < n_baseclasses; i++)
{
case '0':
via_public = 0;
+ non_public_fields++;
break;
case '2':
via_public = 2;
this baseclass. Always zero in the absence of
multiple inheritance. */
offset = read_number (pp, ',');
- baseclass = read_type (pp);
+ baseclass = read_type (pp, objfile);
*pp += 1; /* skip trailing ';' */
/* Make this baseclass visible for structure-printing purposes. */
prefix = vb_name;
break;
default:
- error ("invalid abbreviation at symtab pos %d.", symnum);
+ complain (&invalid_cpp_abbrev_complaint, *pp);
+ prefix = "INVALID_C++_ABBREV";
+ break;
}
*pp = p + 1;
- context = read_type (pp);
+ context = read_type (pp, objfile);
name = type_name_no_tag (context);
if (name == 0)
{
- error ("type name unknown at symtab pos %d.", symnum);
- TYPE_NAME (context) = name;
+ complain (&invalid_cpp_type_complaint, (char *) symnum);
+ name = "FOO";
}
- list->field.name = obconcat (prefix, name, "");
+ list->field.name = obconcat (&objfile -> type_obstack,
+ prefix, name, "");
p = ++(*pp);
if (p[-1] != ':')
- error ("invalid abbreviation at symtab pos %d.", symnum);
- list->field.type = read_type (pp);
+ complain (&invalid_cpp_abbrev_complaint, *pp);
+ list->field.type = read_type (pp, objfile);
(*pp)++; /* Skip the comma. */
list->field.bitpos = read_number (pp, ';');
/* This field is unpacked. */
list->field.bitsize = 0;
+ list->visibility = 0; /* private */
+ non_public_fields++;
}
/* GNU C++ anonymous type. */
else if (*p == '_')
break;
else
- error ("invalid abbreviation at symtab pos %d.", symnum);
+ complain (&invalid_cpp_abbrev_complaint, *pp);
nfields++;
continue;
}
while (*p != ':') p++;
- list->field.name = obsavestring (*pp, p - *pp);
+ list->field.name = obsavestring (*pp, p - *pp,
+ &objfile -> type_obstack);
/* C++: Check to see if we have hit the methods yet. */
if (p[1] == ':')
{
case '0':
list->visibility = 0; /* private */
+ non_public_fields++;
*pp += 1;
break;
case '1':
list->visibility = 1; /* protected */
+ non_public_fields++;
*pp += 1;
break;
else /* normal dbx-style format. */
list->visibility = 2; /* public */
- list->field.type = read_type (pp);
+ list->field.type = read_type (pp, objfile);
if (**pp == ':')
{
/* Static class member. */
if ((list->field.bitsize == 8 * TYPE_LENGTH (list->field.type)
|| (TYPE_CODE (list->field.type) == TYPE_CODE_ENUM
&& (list->field.bitsize
- == 8 * TYPE_LENGTH (builtin_type_int))
+ == 8 * TYPE_LENGTH (lookup_fundamental_type (objfile, FT_INTEGER)))
)
)
&&
for this class's virtual functions. */
TYPE_NFIELDS (type) = nfields;
- TYPE_FIELDS (type) = (struct field *) obstack_alloc (symbol_obstack,
- sizeof (struct field) * nfields);
+ TYPE_FIELDS (type) = (struct field *)
+ obstack_alloc (&objfile -> type_obstack, sizeof (struct field) * nfields);
+
+ if (non_public_fields)
+ {
+ ALLOCATE_CPLUS_STRUCT_TYPE (type);
- TYPE_FIELD_PRIVATE_BITS (type) =
- (B_TYPE *) obstack_alloc (symbol_obstack, B_BYTES (nfields));
- B_CLRALL (TYPE_FIELD_PRIVATE_BITS (type), nfields);
+ TYPE_FIELD_PRIVATE_BITS (type) =
+ (B_TYPE *) obstack_alloc (&objfile -> type_obstack,
+ B_BYTES (nfields));
+ B_CLRALL (TYPE_FIELD_PRIVATE_BITS (type), nfields);
- TYPE_FIELD_PROTECTED_BITS (type) =
- (B_TYPE *) obstack_alloc (symbol_obstack, B_BYTES (nfields));
- B_CLRALL (TYPE_FIELD_PROTECTED_BITS (type), nfields);
+ TYPE_FIELD_PROTECTED_BITS (type) =
+ (B_TYPE *) obstack_alloc (&objfile -> type_obstack,
+ B_BYTES (nfields));
+ B_CLRALL (TYPE_FIELD_PROTECTED_BITS (type), nfields);
+ }
/* Copy the saved-up fields into the field vector. */
At the end, we see a semicolon instead of a field.
For the case of overloaded operators, the format is
- OPERATOR::*.methods, where OPERATOR is the string "operator",
+ op$::*.methods, where $ is the CPLUS_MARKER (usually '$'),
`*' holds the place for an operator name (such as `+=')
and `.' marks the end of the operator name. */
if (p[1] == ':')
"unread" the name that has been read, so that we can
start from the top. */
+ ALLOCATE_CPLUS_STRUCT_TYPE (type);
/* For each list of method lists... */
do
{
/* read in the name. */
while (*p != ':') p++;
-#if 0
if ((*pp)[0] == 'o' && (*pp)[1] == 'p' && (*pp)[2] == CPLUS_MARKER)
{
+ /* This is a completely wierd case. In order to stuff in the
+ names that might contain colons (the usual name delimiter),
+ Mike Tiemann defined a different name format which is
+ signalled if the identifier is "op$". In that case, the
+ format is "op$::XXXX." where XXXX is the name. This is
+ used for names like "+" or "=". YUUUUUUUK! FIXME! */
/* This lets the user type "break operator+".
We could just put in "+" as the name, but that wouldn't
work for "*". */
- /* I don't understand what this is trying to do.
- It seems completely bogus. -Per Bothner. */
static char opname[32] = {'o', 'p', CPLUS_MARKER};
char *o = opname + 3;
*pp = p + 1;
}
else
-#endif
+ {
main_fn_name = savestring (*pp, p - *pp);
- /* Skip past '::'. */
- *pp = p + 2;
+ /* Skip past '::'. */
+ *pp = p + 2;
+ }
new_mainlist->fn_fieldlist.name = main_fn_name;
do
{
if (**pp == '\\') *pp = next_symbol_text ();
- new_sublist->fn_field.type = read_type (pp);
+ new_sublist->fn_field.type = read_type (pp, objfile);
if (**pp != ':')
/* Invalid symtab info for method. */
return error_type (pp);
*pp += 1;
p = *pp;
while (*p != ';') p++;
+
/* If this is just a stub, then we don't have the
real name here. */
+ if (TYPE_FLAGS (new_sublist->fn_field.type) & TYPE_FLAG_STUB)
+ new_sublist->fn_field.is_stub = 1;
new_sublist->fn_field.physname = savestring (*pp, p - *pp);
*pp = p + 1;
- new_sublist->visibility = *(*pp)++ - '0';
+
+ /* Set this method's visibility fields. */
+ switch (*(*pp)++ - '0')
+ {
+ case 0:
+ new_sublist->fn_field.is_private = 1;
+ break;
+ case 1:
+ new_sublist->fn_field.is_protected = 1;
+ break;
+ }
+
if (**pp == '\\') *pp = next_symbol_text ();
switch (**pp)
{
new_sublist->fn_field.is_volatile = 1;
(*pp)++;
break;
+ case '*': /* File compiled with g++ version 1 -- no info */
+ case '?':
+ case '.':
+ break;
default:
- /* This probably just means we're processing a file compiled
- with g++ version 1. */
- complain(&const_vol_complaint, **pp);
+ complain (&const_vol_complaint, (char *) (long) **pp);
+ break;
}
switch (*(*pp)++)
/* Figure out from whence this virtual function came.
It may belong to virtual function table of
one of its baseclasses. */
- look_ahead_type = read_type (pp);
+ look_ahead_type = read_type (pp, objfile);
if (**pp == ':')
{ /* g++ version 1 overloaded methods. */ }
else
case '?':
/* static member function. */
new_sublist->fn_field.voffset = VOFFSET_STATIC;
+ if (strncmp (new_sublist->fn_field.physname,
+ main_fn_name, strlen (main_fn_name)))
+ new_sublist->fn_field.is_stub = 1;
break;
+
default:
- /* **pp == '.'. */
+ /* error */
+ complain (&member_fn_complaint, (char *) (long) (*pp)[-1]);
+ /* Fall through into normal member function. */
+
+ case '.':
/* normal member function. */
new_sublist->fn_field.voffset = 0;
new_sublist->fn_field.fcontext = 0;
*pp += 1;
new_mainlist->fn_fieldlist.fn_fields =
- (struct fn_field *) obstack_alloc (symbol_obstack,
+ (struct fn_field *) obstack_alloc (&objfile -> type_obstack,
sizeof (struct fn_field) * length);
- TYPE_FN_PRIVATE_BITS (new_mainlist->fn_fieldlist) =
- (B_TYPE *) obstack_alloc (symbol_obstack, B_BYTES (length));
- B_CLRALL (TYPE_FN_PRIVATE_BITS (new_mainlist->fn_fieldlist), length);
-
- TYPE_FN_PROTECTED_BITS (new_mainlist->fn_fieldlist) =
- (B_TYPE *) obstack_alloc (symbol_obstack, B_BYTES (length));
- B_CLRALL (TYPE_FN_PROTECTED_BITS (new_mainlist->fn_fieldlist), length);
-
for (i = length; (i--, sublist); sublist = sublist->next)
- {
- new_mainlist->fn_fieldlist.fn_fields[i] = sublist->fn_field;
- if (sublist->visibility == 0)
- B_SET (new_mainlist->fn_fieldlist.private_fn_field_bits, i);
- else if (sublist->visibility == 1)
- B_SET (new_mainlist->fn_fieldlist.protected_fn_field_bits, i);
- }
+ new_mainlist->fn_fieldlist.fn_fields[i] = sublist->fn_field;
new_mainlist->fn_fieldlist.length = length;
new_mainlist->next = mainlist;
mainlist = new_mainlist;
nfn_fields++;
total_length += length;
+ if (**pp == '\\') *pp = next_symbol_text ();
}
while (**pp != ';');
}
*pp += 1;
- TYPE_FN_FIELDLISTS (type) =
- (struct fn_fieldlist *) obstack_alloc (symbol_obstack,
- sizeof (struct fn_fieldlist) * nfn_fields);
- TYPE_NFN_FIELDS (type) = nfn_fields;
- TYPE_NFN_FIELDS_TOTAL (type) = total_length;
+ if (nfn_fields)
+ {
+ TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *)
+ obstack_alloc (&objfile -> type_obstack,
+ sizeof (struct fn_fieldlist) * nfn_fields);
+ TYPE_NFN_FIELDS (type) = nfn_fields;
+ TYPE_NFN_FIELDS_TOTAL (type) = total_length;
+ }
{
int i;
TYPE_NFN_FIELDS_TOTAL (TYPE_BASECLASS (type, i));
}
- for (n = nfn_fields; mainlist; mainlist = mainlist->next)
- TYPE_FN_FIELDLISTS (type)[--n] = mainlist->fn_fieldlist;
+ for (n = nfn_fields; mainlist; mainlist = mainlist->next) {
+ --n; /* Circumvent Sun3 compiler bug */
+ TYPE_FN_FIELDLISTS (type)[n] = mainlist->fn_fieldlist;
+ }
if (**pp == '~')
{
*pp += 1;
- if (**pp == '=')
+ if (**pp == '=' || **pp == '+' || **pp == '-')
{
- TYPE_FLAGS (type)
- |= TYPE_FLAG_HAS_CONSTRUCTOR | TYPE_FLAG_HAS_DESTRUCTOR;
- *pp += 1;
- }
- else if (**pp == '+')
- {
- TYPE_FLAGS (type) |= TYPE_FLAG_HAS_CONSTRUCTOR;
- *pp += 1;
- }
- else if (**pp == '-')
- {
- TYPE_FLAGS (type) |= TYPE_FLAG_HAS_DESTRUCTOR;
+ /* Obsolete flags that used to indicate the presence
+ of constructors and/or destructors. */
*pp += 1;
}
/* Read either a '%' or the final ';'. */
if (*(*pp)++ == '%')
{
+ /* We'd like to be able to derive the vtable pointer field
+ from the type information, but when it's inherited, that's
+ hard. A reason it's hard is because we may read in the
+ info about a derived class before we read in info about
+ the base class that provides the vtable pointer field.
+ Once the base info has been read, we could fill in the info
+ for the derived classes, but for the fact that by then,
+ we don't remember who needs what. */
+
+#if 0
+ int predicted_fieldno = -1;
+#endif
+
/* Now we must record the virtual function table pointer's
field information. */
struct type *t;
int i;
- t = read_type (pp);
+
+#if 0
+ {
+ /* In version 2, we derive the vfield ourselves. */
+ for (n = 0; n < nfields; n++)
+ {
+ if (! strncmp (TYPE_FIELD_NAME (type, n), vptr_name,
+ sizeof (vptr_name) -1))
+ {
+ predicted_fieldno = n;
+ break;
+ }
+ }
+ if (predicted_fieldno < 0)
+ for (n = 0; n < TYPE_N_BASECLASSES (type); n++)
+ if (! TYPE_FIELD_VIRTUAL (type, n)
+ && TYPE_VPTR_FIELDNO (TYPE_BASECLASS (type, n)) >= 0)
+ {
+ predicted_fieldno = TYPE_VPTR_FIELDNO (TYPE_BASECLASS (type, n));
+ break;
+ }
+ }
+#endif
+
+ t = read_type (pp, objfile);
p = (*pp)++;
while (*p != '\0' && *p != ';')
p++;
}
else for (i = TYPE_NFIELDS (t) - 1; i >= TYPE_N_BASECLASSES (t); --i)
if (! strncmp (TYPE_FIELD_NAME (t, i), vptr_name,
- sizeof (vptr_name) -1))
+ sizeof (vptr_name) -1))
{
TYPE_VPTR_FIELDNO (type) = i;
break;
}
else
TYPE_VPTR_FIELDNO (type) = TYPE_VPTR_FIELDNO (t);
+
+#if 0
+ if (TYPE_VPTR_FIELDNO (type) != predicted_fieldno)
+ error ("TYPE_VPTR_FIELDNO miscalculated");
+#endif
+
*pp = p + 1;
}
}
and create and return a suitable type object.
Also creates a range type which represents the bounds of that
array. */
-struct type *
-read_array_type (pp, type)
+static struct type *
+read_array_type (pp, type, objfile)
register char **pp;
register struct type *type;
+ struct objfile *objfile;
{
struct type *index_type, *element_type, *range_type;
int lower, upper;
Fortran adjustable arrays use Adigits or Tdigits for lower or upper;
for these, produce a type like float[][]. */
- index_type = read_type (pp);
+ index_type = read_type (pp, objfile);
if (**pp != ';')
/* Improper format of array type decl. */
return error_type (pp);
}
upper = read_number (pp, ';');
- element_type = read_type (pp);
+ element_type = read_type (pp, objfile);
if (adjustable)
{
{
/* Create range type. */
- range_type = (struct type *) obstack_alloc (symbol_obstack,
- sizeof (struct type));
+ range_type = (struct type *)
+ obstack_alloc (&objfile -> type_obstack, sizeof (struct type));
+ bzero (range_type, sizeof (struct type));
+ TYPE_OBJFILE (range_type) = objfile;
TYPE_CODE (range_type) = TYPE_CODE_RANGE;
TYPE_TARGET_TYPE (range_type) = index_type;
TYPE_NFIELDS (range_type) = 2;
TYPE_FIELDS (range_type) =
- (struct field *) obstack_alloc (symbol_obstack,
+ (struct field *) obstack_alloc (&objfile -> type_obstack,
2 * sizeof (struct field));
TYPE_FIELD_BITPOS (range_type, 0) = lower;
TYPE_FIELD_BITPOS (range_type, 1) = upper;
TYPE_LENGTH (type) = (upper - lower + 1) * TYPE_LENGTH (element_type);
TYPE_NFIELDS (type) = 1;
TYPE_FIELDS (type) =
- (struct field *) obstack_alloc (symbol_obstack,
+ (struct field *) obstack_alloc (&objfile -> type_obstack,
sizeof (struct field));
TYPE_FIELD_TYPE (type, 0) = range_type;
+ /* If we have an array whose element type is not yet known, but whose
+ bounds *are* known, record it to be adjusted at the end of the file. */
+ if (TYPE_LENGTH (element_type) == 0 && !adjustable)
+ add_undefined_type (type);
+
return type;
}
and create and return a suitable type object.
Also defines the symbols that represent the values of the type. */
-struct type *
-read_enum_type (pp, type)
+static struct type *
+read_enum_type (pp, type, objfile)
register char **pp;
register struct type *type;
+ struct objfile *objfile;
{
register char *p;
char *name;
struct pending *osyms, *syms;
int o_nsyms;
+#if 0
+ /* FIXME! The stabs produced by Sun CC merrily define things that ought
+ to be file-scope, between N_FN entries, using N_LSYM. What's a mother
+ to do? For now, force all enum values to file scope. */
if (within_function)
symlist = &local_symbols;
else
+#endif
symlist = &file_symbols;
osyms = *symlist;
o_nsyms = osyms ? osyms->nsyms : 0;
/* Read the value-names and their values.
The input syntax is NAME:VALUE,NAME:VALUE, and so on.
- A semicolon or comman instead of a NAME means the end. */
+ A semicolon or comma instead of a NAME means the end. */
while (**pp && **pp != ';' && **pp != ',')
{
/* Check for and handle cretinous dbx symbol name continuation! */
p = *pp;
while (*p != ':') p++;
- name = obsavestring (*pp, p - *pp);
+ name = obsavestring (*pp, p - *pp, &objfile -> symbol_obstack);
*pp = p + 1;
n = read_number (pp, ',');
- sym = (struct symbol *) obstack_alloc (symbol_obstack, sizeof (struct symbol));
+ sym = (struct symbol *) obstack_alloc (&objfile -> symbol_obstack, sizeof (struct symbol));
bzero (sym, sizeof (struct symbol));
SYMBOL_NAME (sym) = name;
SYMBOL_CLASS (sym) = LOC_CONST;
TYPE_LENGTH (type) = sizeof (int);
TYPE_CODE (type) = TYPE_CODE_ENUM;
TYPE_NFIELDS (type) = nsyms;
- TYPE_FIELDS (type) = (struct field *) obstack_alloc (symbol_obstack, sizeof (struct field) * nsyms);
+ TYPE_FIELDS (type) = (struct field *)
+ obstack_alloc (&objfile -> type_obstack,
+ sizeof (struct field) * nsyms);
/* Find the symbols for the values and put them into the type.
The symbols can be found in the symlist that we put them on
If encounter garbage, set *BITS to -1. */
-void
+static void
read_huge_number (pp, end, valu, bits)
char **pp;
int end;
}
}
-#define MAX_OF_C_TYPE(t) ((1 << (sizeof (t)*8 - 1)) - 1)
-#define MIN_OF_C_TYPE(t) (-(1 << (sizeof (t)*8 - 1)))
-
-struct type *
-read_range_type (pp, typenums)
+static struct type *
+read_range_type (pp, typenums, objfile)
char **pp;
int typenums[2];
+ struct objfile *objfile;
{
int rangenums[2];
long n2, n3;
/* Check for "long long". */
if (got_signed && nbits == TARGET_LONG_LONG_BIT)
- return builtin_type_long_long;
+ return (lookup_fundamental_type (objfile, FT_LONG_LONG));
if (got_unsigned && nbits == TARGET_LONG_LONG_BIT)
- return builtin_type_unsigned_long_long;
+ return (lookup_fundamental_type (objfile, FT_UNSIGNED_LONG_LONG));
if (got_signed || got_unsigned)
{
- result_type = (struct type *) obstack_alloc (symbol_obstack,
- sizeof (struct type));
+ result_type = (struct type *)
+ obstack_alloc (&objfile -> type_obstack,
+ sizeof (struct type));
bzero (result_type, sizeof (struct type));
+ TYPE_OBJFILE (result_type) = objfile;
TYPE_LENGTH (result_type) = nbits / TARGET_CHAR_BIT;
- TYPE_MAIN_VARIANT (result_type) = result_type;
TYPE_CODE (result_type) = TYPE_CODE_INT;
if (got_unsigned)
TYPE_FLAGS (result_type) |= TYPE_FLAG_UNSIGNED;
/* A type defined as a subrange of itself, with bounds both 0, is void. */
if (self_subrange && n2 == 0 && n3 == 0)
- return builtin_type_void;
+ return (lookup_fundamental_type (objfile, FT_VOID));
/* If n3 is zero and n2 is not, we want a floating type,
and n2 is the width in bytes.
and they give no way to distinguish between double and single-complex!
We don't have complex types, so we would lose on all fortran files!
So return type `double' for all of those. It won't work right
- for the complex values, but at least it makes the file loadable. */
+ for the complex values, but at least it makes the file loadable.
+
+ FIXME, we may be able to distinguish these by their names. FIXME. */
if (n3 == 0 && n2 > 0)
{
if (n2 == sizeof (float))
- return builtin_type_float;
- return builtin_type_double;
+ return (lookup_fundamental_type (objfile, FT_FLOAT));
+ return (lookup_fundamental_type (objfile, FT_DBL_PREC_FLOAT));
}
/* If the upper bound is -1, it must really be an unsigned int. */
else if (n2 == 0 && n3 == -1)
{
- /* FIXME -- this confuses host and target type sizes. */
- if (sizeof (int) == sizeof (long))
- return builtin_type_unsigned_int;
+ /* FIXME -- the only way to distinguish `unsigned int' from `unsigned
+ long' is to look at its name! */
+ if (
+ long_kludge_name && ((long_kludge_name[0] == 'u' /* unsigned */ &&
+ long_kludge_name[9] == 'l' /* long */)
+ || (long_kludge_name[0] == 'l' /* long unsigned */)))
+ return (lookup_fundamental_type (objfile, FT_UNSIGNED_LONG));
else
- return builtin_type_unsigned_long;
+ return (lookup_fundamental_type (objfile, FT_UNSIGNED_INTEGER));
}
/* Special case: char is defined (Who knows why) as a subrange of
itself with range 0-127. */
else if (self_subrange && n2 == 0 && n3 == 127)
- return builtin_type_char;
+ return (lookup_fundamental_type (objfile, FT_CHAR));
/* Assumptions made here: Subrange of self is equivalent to subrange
of int. FIXME: Host and target type-sizes assumed the same. */
+ /* FIXME: This is the *only* place in GDB that depends on comparing
+ some type to a builtin type with ==. Fix it! */
else if (n2 == 0
&& (self_subrange ||
- *dbx_lookup_type (rangenums) == builtin_type_int))
+ *dbx_lookup_type (rangenums) == lookup_fundamental_type (objfile, FT_INTEGER)))
{
/* an unsigned type */
#ifdef LONG_LONG
if (n3 == - sizeof (long long))
- return builtin_type_unsigned_long_long;
+ return (lookup_fundamental_type (objfile, FT_UNSIGNED_LONG_LONG));
#endif
+ /* FIXME -- the only way to distinguish `unsigned int' from `unsigned
+ long' is to look at its name! */
+ if (n3 == (unsigned long)~0L &&
+ long_kludge_name && ((long_kludge_name[0] == 'u' /* unsigned */ &&
+ long_kludge_name[9] == 'l' /* long */)
+ || (long_kludge_name[0] == 'l' /* long unsigned */)))
+ return (lookup_fundamental_type (objfile, FT_UNSIGNED_LONG));
if (n3 == (unsigned int)~0L)
- return builtin_type_unsigned_int;
- if (n3 == (unsigned long)~0L)
- return builtin_type_unsigned_long;
+ return (lookup_fundamental_type (objfile, FT_UNSIGNED_INTEGER));
if (n3 == (unsigned short)~0L)
- return builtin_type_unsigned_short;
+ return (lookup_fundamental_type (objfile, FT_UNSIGNED_SHORT));
if (n3 == (unsigned char)~0L)
- return builtin_type_unsigned_char;
+ return (lookup_fundamental_type (objfile, FT_UNSIGNED_CHAR));
}
#ifdef LONG_LONG
else if (n3 == 0 && n2 == -sizeof (long long))
- return builtin_type_long_long;
+ return (lookup_fundamental_type (objfile, FT_LONG_LONG));
#endif
else if (n2 == -n3 -1)
{
/* a signed type */
- if (n3 == (1 << (8 * sizeof (int) - 1)) - 1)
- return builtin_type_int;
- if (n3 == (1 << (8 * sizeof (long) - 1)) - 1)
- return builtin_type_long;
- if (n3 == (1 << (8 * sizeof (short) - 1)) - 1)
- return builtin_type_short;
- if (n3 == (1 << (8 * sizeof (char) - 1)) - 1)
- return builtin_type_char;
+ /* FIXME -- the only way to distinguish `int' from `long' is to look
+ at its name! */
+ if ((n3 ==(long)(((unsigned long)1 << (8 * sizeof (long) - 1)) - 1)) &&
+ long_kludge_name && long_kludge_name[0] == 'l' /* long */)
+ return (lookup_fundamental_type (objfile, FT_LONG));
+ if (n3 == (long)(((unsigned long)1 << (8 * sizeof (int) - 1)) - 1))
+ return (lookup_fundamental_type (objfile, FT_INTEGER));
+ if (n3 == ( 1 << (8 * sizeof (short) - 1)) - 1)
+ return (lookup_fundamental_type (objfile, FT_SHORT));
+ if (n3 == ( 1 << (8 * sizeof (char) - 1)) - 1)
+ return (lookup_fundamental_type (objfile, FT_CHAR));
}
/* We have a real range type on our hands. Allocate space and
if (self_subrange)
return error_type (pp);
- result_type = (struct type *) obstack_alloc (symbol_obstack,
- sizeof (struct type));
+ result_type = (struct type *)
+ obstack_alloc (&objfile -> type_obstack, sizeof (struct type));
bzero (result_type, sizeof (struct type));
+ TYPE_OBJFILE (result_type) = objfile;
TYPE_CODE (result_type) = TYPE_CODE_RANGE;
TYPE_TARGET_TYPE (result_type) = *dbx_lookup_type(rangenums);
if (TYPE_TARGET_TYPE (result_type) == 0) {
- complain (&range_type_base_complaint, rangenums[1]);
- TYPE_TARGET_TYPE (result_type) = builtin_type_int;
+ complain (&range_type_base_complaint, (char *) rangenums[1]);
+ TYPE_TARGET_TYPE (result_type) = lookup_fundamental_type (objfile, FT_INTEGER);
}
TYPE_NFIELDS (result_type) = 2;
TYPE_FIELDS (result_type) =
- (struct field *) obstack_alloc (symbol_obstack,
- 2 * sizeof (struct field));
+ (struct field *) obstack_alloc (&objfile -> type_obstack,
+ 2 * sizeof (struct field));
bzero (TYPE_FIELDS (result_type), 2 * sizeof (struct field));
TYPE_FIELD_BITPOS (result_type, 0) = n2;
TYPE_FIELD_BITPOS (result_type, 1) = n3;
-#if 0
-/* Note that TYPE_LENGTH (result_type) is just overridden a few
- statements down. What do we really need here? */
- /* We have to figure out how many bytes it takes to hold this
- range type. I'm going to assume that anything that is pushing
- the bounds of a long was taken care of above. */
- if (n2 >= MIN_OF_C_TYPE(char) && n3 <= MAX_OF_C_TYPE(char))
- TYPE_LENGTH (result_type) = 1;
- else if (n2 >= MIN_OF_C_TYPE(short) && n3 <= MAX_OF_C_TYPE(short))
- TYPE_LENGTH (result_type) = sizeof (short);
- else if (n2 >= MIN_OF_C_TYPE(int) && n3 <= MAX_OF_C_TYPE(int))
- TYPE_LENGTH (result_type) = sizeof (int);
- else if (n2 >= MIN_OF_C_TYPE(long) && n3 <= MAX_OF_C_TYPE(long))
- TYPE_LENGTH (result_type) = sizeof (long);
- else
- /* Ranged type doesn't fit within known sizes. */
- /* FIXME -- use "long long" here. */
- return error_type (pp);
-#endif
-
TYPE_LENGTH (result_type) = TYPE_LENGTH (TYPE_TARGET_TYPE (result_type));
return result_type;
/* Read in an argument list. This is a list of types, separated by commas
and terminated with END. Return the list of types read in, or (struct type
**)-1 if there is an error. */
-struct type **
-read_args (pp, end)
+static struct type **
+read_args (pp, end, objfile)
char **pp;
int end;
+ struct objfile *objfile;
{
/* FIXME! Remove this arbitrary limit! */
struct type *types[1024], **rval; /* allow for fns of 1023 parameters */
if (**pp == '\\')
*pp = next_symbol_text ();
- types[n++] = read_type (pp);
+ types[n++] = read_type (pp, objfile);
}
*pp += 1; /* get past `end' (the ':' character) */
{
rval = (struct type **) xmalloc (n * sizeof (struct type *));
}
- bcopy (types, rval, n * sizeof (struct type *));
+ memcpy (rval, types, n * sizeof (struct type *));
return rval;
}