import gdb-1999-10-11 snapshot
[deliverable/binutils-gdb.git] / gdb / dwarfread.c
index 8a9cebd29491dd01bd6fcce3dd958ed0e889a93d..18727c2b923024b162ea60de4bdf3efb6ecd87c7 100644 (file)
 /* DWARF debugging format support for GDB.
-   Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+   Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1998
+   Free Software Foundation, Inc.
    Written by Fred Fish at Cygnus Support.  Portions based on dbxread.c,
    mipsread.c, coffread.c, and dwarfread.c from a Data General SVR4 gdb port.
 
-This file is part of GDB.
+   This file is part of GDB.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 /*
 
-FIXME: Figure out how to get the frame pointer register number in the
-execution environment of the target.  Remove R_FP kludge
+   FIXME: Do we need to generate dependencies in partial symtabs?
+   (Perhaps we don't need to).
 
-FIXME: Add generation of dependencies list to partial symtab code.
+   FIXME: Resolve minor differences between what information we put in the
+   partial symbol table and what dbxread puts in.  For example, we don't yet
+   put enum constants there.  And dbxread seems to invent a lot of typedefs
+   we never see.  Use the new printpsym command to see the partial symbol table
+   contents.
 
-FIXME: Resolve minor differences between what information we put in the
-partial symbol table and what dbxread puts in.  For example, we don't yet
-put enum constants there.  And dbxread seems to invent a lot of typedefs
-we never see.  Use the new printpsym command to see the partial symbol table
-contents.
+   FIXME: Figure out a better way to tell gdb about the name of the function
+   contain the user's entry point (I.E. main())
 
-FIXME: Figure out a better way to tell gdb about the name of the function
-contain the user's entry point (I.E. main())
+   FIXME: See other FIXME's and "ifdef 0" scattered throughout the code for
+   other things to work on, if you get bored. :-)
 
-FIXME: See other FIXME's and "ifdef 0" scattered throughout the code for
-other things to work on, if you get bored. :-)
-
-*/
+ */
 
 #include "defs.h"
-#include <varargs.h>
-#include <fcntl.h>
-#include <string.h>
-
-#include "bfd.h"
 #include "symtab.h"
 #include "gdbtypes.h"
 #include "symfile.h"
 #include "objfiles.h"
-#include "libbfd.h"    /* FIXME Secret Internal BFD stuff (bfd_read) */
 #include "elf/dwarf.h"
 #include "buildsym.h"
+#include "demangle.h"
+#include "expression.h"                /* Needed for enum exp_opcode in language.h, sigh... */
+#include "language.h"
+#include "complaints.h"
 
-#ifdef MAINTENANCE     /* Define to 1 to compile in some maintenance stuff */
-#define SQUAWK(stuff) dwarfwarn stuff
-#else
-#define SQUAWK(stuff)
-#endif
+#include <fcntl.h>
+#include "gdb_string.h"
 
-#ifndef R_FP           /* FIXME */
-#define R_FP 14                /* Kludge to get frame pointer register number */
-#endif
+/* Some macros to provide DIE info for complaints. */
+
+#define DIE_ID (curdie!=NULL ? curdie->die_ref : 0)
+#define DIE_NAME (curdie!=NULL && curdie->at_name!=NULL) ? curdie->at_name : ""
+
+/* Complaints that can be issued during DWARF debug info reading. */
+
+struct complaint no_bfd_get_N =
+{
+  "DIE @ 0x%x \"%s\", no bfd support for %d byte data object", 0, 0
+};
+
+struct complaint malformed_die =
+{
+  "DIE @ 0x%x \"%s\", malformed DIE, bad length (%d bytes)", 0, 0
+};
+
+struct complaint bad_die_ref =
+{
+  "DIE @ 0x%x \"%s\", reference to DIE (0x%x) outside compilation unit", 0, 0
+};
+
+struct complaint unknown_attribute_form =
+{
+  "DIE @ 0x%x \"%s\", unknown attribute form (0x%x)", 0, 0
+};
+
+struct complaint unknown_attribute_length =
+{
+  "DIE @ 0x%x \"%s\", unknown attribute length, skipped remaining attributes", 0, 0
+};
+
+struct complaint unexpected_fund_type =
+{
+  "DIE @ 0x%x \"%s\", unexpected fundamental type 0x%x", 0, 0
+};
+
+struct complaint unknown_type_modifier =
+{
+  "DIE @ 0x%x \"%s\", unknown type modifier %u", 0, 0
+};
+
+struct complaint volatile_ignored =
+{
+  "DIE @ 0x%x \"%s\", type modifier 'volatile' ignored", 0, 0
+};
+
+struct complaint const_ignored =
+{
+  "DIE @ 0x%x \"%s\", type modifier 'const' ignored", 0, 0
+};
+
+struct complaint botched_modified_type =
+{
+  "DIE @ 0x%x \"%s\", botched modified type decoding (mtype 0x%x)", 0, 0
+};
+
+struct complaint op_deref2 =
+{
+  "DIE @ 0x%x \"%s\", OP_DEREF2 address 0x%x not handled", 0, 0
+};
+
+struct complaint op_deref4 =
+{
+  "DIE @ 0x%x \"%s\", OP_DEREF4 address 0x%x not handled", 0, 0
+};
+
+struct complaint basereg_not_handled =
+{
+  "DIE @ 0x%x \"%s\", BASEREG %d not handled", 0, 0
+};
+
+struct complaint dup_user_type_allocation =
+{
+  "DIE @ 0x%x \"%s\", internal error: duplicate user type allocation", 0, 0
+};
+
+struct complaint dup_user_type_definition =
+{
+  "DIE @ 0x%x \"%s\", internal error: duplicate user type definition", 0, 0
+};
+
+struct complaint missing_tag =
+{
+  "DIE @ 0x%x \"%s\", missing class, structure, or union tag", 0, 0
+};
+
+struct complaint bad_array_element_type =
+{
+  "DIE @ 0x%x \"%s\", bad array element type attribute 0x%x", 0, 0
+};
+
+struct complaint subscript_data_items =
+{
+  "DIE @ 0x%x \"%s\", can't decode subscript data items", 0, 0
+};
+
+struct complaint unhandled_array_subscript_format =
+{
+  "DIE @ 0x%x \"%s\", array subscript format 0x%x not handled yet", 0, 0
+};
+
+struct complaint unknown_array_subscript_format =
+{
+  "DIE @ 0x%x \"%s\", unknown array subscript format %x", 0, 0
+};
+
+struct complaint not_row_major =
+{
+  "DIE @ 0x%x \"%s\", array not row major; not handled correctly", 0, 0
+};
+
+struct complaint missing_at_name =
+{
+  "DIE @ 0x%x, AT_name tag missing", 0, 0
+};
 
 typedef unsigned int DIE_REF;  /* Reference to a DIE */
 
@@ -70,8 +177,22 @@ typedef unsigned int DIE_REF;       /* Reference to a DIE */
 #define GCC_PRODUCER "GNU C "
 #endif
 
-#define STREQ(a,b)             (strcmp(a,b)==0)
-#define STREQN(a,b,n)          (strncmp(a,b,n)==0)
+#ifndef GPLUS_PRODUCER
+#define GPLUS_PRODUCER "GNU C++ "
+#endif
+
+#ifndef LCC_PRODUCER
+#define LCC_PRODUCER "NCR C/C++"
+#endif
+
+#ifndef CHILL_PRODUCER
+#define CHILL_PRODUCER "GNU Chill "
+#endif
+
+/* Provide a default mapping from a DWARF register number to a gdb REGNUM.  */
+#ifndef DWARF_REG_TO_REGNUM
+#define DWARF_REG_TO_REGNUM(num) (num)
+#endif
 
 /* Flags to target_to_host() that tell whether or not the data object is
    expected to be signed.  Used, for example, when fetching a signed
@@ -124,8 +245,8 @@ typedef unsigned int DIE_REF;       /* Reference to a DIE */
 
 /* External variables referenced. */
 
-extern int info_verbose;               /* From main.c; nonzero => verbose */
-extern char *warning_pre_print;                /* From utils.c */
+extern int info_verbose;       /* From main.c; nonzero => verbose */
+extern char *warning_pre_print;        /* From utils.c */
 
 /* The DWARF debugging information consists of two major pieces,
    one is a block of DWARF Information Entries (DIE's) and the other
@@ -151,95 +272,110 @@ extern char *warning_pre_print;          /* From utils.c */
    we may want to test for the presence of some attributes in the DIE,
    such as AT_low_pc, without restricting the values of the field,
    we need someway to note that we found such an attribute.
-   
+
  */
-   
+
 typedef char BLOCK;
 
-struct dieinfo {
-  char *               die;            /* Pointer to the raw DIE data */
-  unsigned long        die_length;     /* Length of the raw DIE data */
-  DIE_REF              die_ref;        /* Offset of this DIE */
-  unsigned short       die_tag;        /* Tag for this DIE */
-  unsigned long                at_padding;
-  unsigned long                at_sibling;
-  BLOCK *              at_location;
-  char *               at_name;
-  unsigned short       at_fund_type;
-  BLOCK *              at_mod_fund_type;
-  unsigned long                at_user_def_type;
-  BLOCK *              at_mod_u_d_type;
-  unsigned short       at_ordering;
-  BLOCK *              at_subscr_data;
-  unsigned long                at_byte_size;
-  unsigned short       at_bit_offset;
-  unsigned long                at_bit_size;
-  BLOCK *              at_element_list;
-  unsigned long                at_stmt_list;
-  unsigned long                at_low_pc;
-  unsigned long                at_high_pc;
-  unsigned long                at_language;
-  unsigned long                at_member;
-  unsigned long                at_discr;
-  BLOCK *              at_discr_value;
-  unsigned short       at_visibility;
-  unsigned long                at_import;
-  BLOCK *              at_string_length;
-  char *               at_comp_dir;
-  char *               at_producer;
-  unsigned long                at_frame_base;
-  unsigned long                at_start_scope;
-  unsigned long                at_stride_size;
-  unsigned long                at_src_info;
-  char *               at_prototyped;
-  unsigned int         has_at_low_pc:1;
-  unsigned int         has_at_stmt_list:1;
-  unsigned int         short_element_list:1;
-};
+struct dieinfo
+  {
+    char *die;                 /* Pointer to the raw DIE data */
+    unsigned long die_length;  /* Length of the raw DIE data */
+    DIE_REF die_ref;           /* Offset of this DIE */
+    unsigned short die_tag;    /* Tag for this DIE */
+    unsigned long at_padding;
+    unsigned long at_sibling;
+    BLOCK *at_location;
+    char *at_name;
+    unsigned short at_fund_type;
+    BLOCK *at_mod_fund_type;
+    unsigned long at_user_def_type;
+    BLOCK *at_mod_u_d_type;
+    unsigned short at_ordering;
+    BLOCK *at_subscr_data;
+    unsigned long at_byte_size;
+    unsigned short at_bit_offset;
+    unsigned long at_bit_size;
+    BLOCK *at_element_list;
+    unsigned long at_stmt_list;
+    CORE_ADDR at_low_pc;
+    CORE_ADDR at_high_pc;
+    unsigned long at_language;
+    unsigned long at_member;
+    unsigned long at_discr;
+    BLOCK *at_discr_value;
+    BLOCK *at_string_length;
+    char *at_comp_dir;
+    char *at_producer;
+    unsigned long at_start_scope;
+    unsigned long at_stride_size;
+    unsigned long at_src_info;
+    char *at_prototyped;
+    unsigned int has_at_low_pc:1;
+    unsigned int has_at_stmt_list:1;
+    unsigned int has_at_byte_size:1;
+    unsigned int short_element_list:1;
+
+    /* Kludge to identify register variables */
+
+    unsigned int isreg;
+
+    /* Kludge to identify optimized out variables */
+
+    unsigned int optimized_out;
+
+    /* Kludge to identify basereg references.
+       Nonzero if we have an offset relative to a basereg.  */
+
+    unsigned int offreg;
+
+    /* Kludge to identify which base register is it relative to.  */
+
+    unsigned int basereg;
+  };
 
-static int diecount;   /* Approximate count of dies for compilation unit */
+static int diecount;           /* Approximate count of dies for compilation unit */
 static struct dieinfo *curdie; /* For warnings and such */
 
-static char *dbbase;   /* Base pointer to dwarf info */
-static int dbroff;     /* Relative offset from start of .debug section */
-static char *lnbase;   /* Base pointer to line section */
-static int isreg;      /* Kludge to identify register variables */
-static int offreg;     /* Kludge to identify basereg references */
+static char *dbbase;           /* Base pointer to dwarf info */
+static int dbsize;             /* Size of dwarf info in bytes */
+static int dbroff;             /* Relative offset from start of .debug section */
+static char *lnbase;           /* Base pointer to line section */
 
+/* This value is added to each symbol value.  FIXME:  Generalize to 
+   the section_offsets structure used by dbxread (once this is done,
+   pass the appropriate section number to end_symtab).  */
 static CORE_ADDR baseaddr;     /* Add to each symbol value */
 
-/* Each partial symbol table entry contains a pointer to private data for the
-   read_symtab() function to use when expanding a partial symbol table entry
-   to a full symbol table entry.  For DWARF debugging info, this data is
-   contained in the following structure and macros are provided for easy
-   access to the members given a pointer to a partial symbol table entry.
-
-   dbfoff      Always the absolute file offset to the start of the ".debug"
-               section for the file containing the DIE's being accessed.
-
-   dbroff      Relative offset from the start of the ".debug" access to the
-               first DIE to be accessed.  When building the partial symbol
-               table, this value will be zero since we are accessing the
-               entire ".debug" section.  When expanding a partial symbol
-               table entry, this value will be the offset to the first
-               DIE for the compilation unit containing the symbol that
-               triggers the expansion.
-
-   dblength    The size of the chunk of DIE's being examined, in bytes.
-
-   lnfoff      The absolute file offset to the line table fragment.  Ignored
-               when building partial symbol tables, but used when expanding
-               them, and contains the absolute file offset to the fragment
-               of the ".line" section containing the line numbers for the
-               current compilation unit.
- */
-
-struct dwfinfo {
-  int dbfoff;          /* Absolute file offset to start of .debug section */
-  int dbroff;          /* Relative offset from start of .debug section */
-  int dblength;                /* Size of the chunk of DIE's being examined */
-  int lnfoff;          /* Absolute file offset to line table fragment */
-};
+/* The section offsets used in the current psymtab or symtab.  FIXME,
+   only used to pass one value (baseaddr) at the moment.  */
+static struct section_offsets *base_section_offsets;
+
+/* We put a pointer to this structure in the read_symtab_private field
+   of the psymtab.  */
+
+struct dwfinfo
+  {
+    /* Always the absolute file offset to the start of the ".debug"
+       section for the file containing the DIE's being accessed.  */
+    file_ptr dbfoff;
+    /* Relative offset from the start of the ".debug" section to the
+       first DIE to be accessed.  When building the partial symbol
+       table, this value will be zero since we are accessing the
+       entire ".debug" section.  When expanding a partial symbol
+       table entry, this value will be the offset to the first
+       DIE for the compilation unit containing the symbol that
+       triggers the expansion.  */
+    int dbroff;
+    /* The size of the chunk of DIE's being examined, in bytes.  */
+    int dblength;
+    /* The absolute file offset to the line table fragment.  Ignored
+       when building partial symbol tables, but used when expanding
+       them, and contains the absolute file offset to the fragment
+       of the ".line" section containing the line numbers for the
+       current compilation unit.  */
+    file_ptr lnfoff;
+  };
 
 #define DBFOFF(p) (((struct dwfinfo *)((p)->read_symtab_private))->dbfoff)
 #define DBROFF(p) (((struct dwfinfo *)((p)->read_symtab_private))->dbroff)
@@ -278,23 +414,57 @@ struct pending **list_in_scope = &file_symbols;
    we can divide any DIE offset by 4 to obtain a unique index into this fixed
    size array.  Since each element is a 4 byte pointer, it takes exactly as
    much memory to hold this array as to hold the DWARF info for a given
-   compilation unit.  But it gets freed as soon as we are done with it. */
+   compilation unit.  But it gets freed as soon as we are done with it.
+   This has worked well in practice, as a reasonable tradeoff between memory
+   consumption and speed, without having to resort to much more complicated
+   algorithms. */
 
 static struct type **utypes;   /* Pointer to array of user type pointers */
 static int numutypes;          /* Max number of user type pointers */
 
+/* Maintain an array of referenced fundamental types for the current
+   compilation unit being read.  For DWARF version 1, we have to construct
+   the fundamental types on the fly, since no information about the
+   fundamental types is supplied.  Each such fundamental type is created by
+   calling a language dependent routine to create the type, and then a
+   pointer to that type is then placed in the array at the index specified
+   by it's FT_<TYPENAME> value.  The array has a fixed size set by the
+   FT_NUM_MEMBERS compile time constant, which is the number of predefined
+   fundamental types gdb knows how to construct. */
+
+static struct type *ftypes[FT_NUM_MEMBERS];    /* Fundamental types */
+
+/* Record the language for the compilation unit which is currently being
+   processed.  We know it once we have seen the TAG_compile_unit DIE,
+   and we need it while processing the DIE's for that compilation unit.
+   It is eventually saved in the symtab structure, but we don't finalize
+   the symtab struct until we have processed all the DIE's for the
+   compilation unit.  We also need to get and save a pointer to the 
+   language struct for this language, so we can call the language
+   dependent routines for doing things such as creating fundamental
+   types. */
+
+static enum language cu_language;
+static const struct language_defn *cu_language_defn;
+
 /* Forward declarations of static functions so we don't have to worry
    about ordering within this file.  */
 
+static void
+free_utypes PARAMS ((PTR));
+
 static int
 attribute_size PARAMS ((unsigned int));
 
-static unsigned long
-target_to_host PARAMS ((char *, int, int, struct objfile *));
+static CORE_ADDR
+  target_to_host PARAMS ((char *, int, int, struct objfile *));
 
 static void
 add_enum_psymbol PARAMS ((struct dieinfo *, struct objfile *));
 
+static void
+handle_producer PARAMS ((char *));
+
 static void
 read_file_scope PARAMS ((struct dieinfo *, char *, char *, struct objfile *));
 
@@ -305,22 +475,16 @@ static void
 read_lexical_block_scope PARAMS ((struct dieinfo *, char *, char *,
                                  struct objfile *));
 
-static void
-dwarfwarn ();
-
 static void
 scan_partial_symbols PARAMS ((char *, char *, struct objfile *));
 
 static void
-scan_compilation_units PARAMS ((char *, char *, char *, unsigned int,
-                               unsigned int, struct objfile *));
+scan_compilation_units PARAMS ((char *, char *, file_ptr,
+                               file_ptr, struct objfile *));
 
 static void
 add_partial_symbol PARAMS ((struct dieinfo *, struct objfile *));
 
-static void
-init_psymbol_list PARAMS ((struct objfile *, int));
-
 static void
 basicdieinfo PARAMS ((struct dieinfo *, char *, struct objfile *));
 
@@ -333,7 +497,7 @@ dwarf_psymtab_to_symtab PARAMS ((struct partial_symtab *));
 static void
 psymtab_to_symtab_1 PARAMS ((struct partial_symtab *));
 
-static struct symtab *
+static void
 read_ofile_symtab PARAMS ((struct partial_symtab *));
 
 static void
@@ -344,16 +508,19 @@ read_structure_scope PARAMS ((struct dieinfo *, char *, char *,
                              struct objfile *));
 
 static struct type *
-decode_array_element_type PARAMS ((char *));
+  decode_array_element_type PARAMS ((char *));
 
 static struct type *
-decode_subscr_data PARAMS ((char *, char *));
+  decode_subscript_data_item PARAMS ((char *, char *));
 
 static void
 dwarf_read_array_type PARAMS ((struct dieinfo *));
 
 static void
-read_tag_pointer_type PARAMS ((struct dieinfo *dip));
+read_tag_pointer_type PARAMS ((struct dieinfo * dip));
+
+static void
+read_tag_string_type PARAMS ((struct dieinfo * dip));
 
 static void
 read_subroutine_type PARAMS ((struct dieinfo *, char *, char *));
@@ -362,228 +529,268 @@ static void
 read_enumeration PARAMS ((struct dieinfo *, char *, char *, struct objfile *));
 
 static struct type *
-struct_type PARAMS ((struct dieinfo *, char *, char *, struct objfile *));
+  struct_type PARAMS ((struct dieinfo *, char *, char *, struct objfile *));
 
 static struct type *
-enum_type PARAMS ((struct dieinfo *, struct objfile *));
+  enum_type PARAMS ((struct dieinfo *, struct objfile *));
 
 static void
 decode_line_numbers PARAMS ((char *));
 
 static struct type *
-decode_die_type PARAMS ((struct dieinfo *));
+  decode_die_type PARAMS ((struct dieinfo *));
 
 static struct type *
-decode_mod_fund_type PARAMS ((char *));
+  decode_mod_fund_type PARAMS ((char *));
 
 static struct type *
-decode_mod_u_d_type PARAMS ((char *));
+  decode_mod_u_d_type PARAMS ((char *));
 
 static struct type *
-decode_modified_type PARAMS ((unsigned char *, unsigned int, int));
+  decode_modified_type PARAMS ((char *, unsigned int, int));
 
 static struct type *
-decode_fund_type PARAMS ((unsigned int));
+  decode_fund_type PARAMS ((unsigned int));
 
 static char *
-create_name PARAMS ((char *, struct obstack *));
+  create_name PARAMS ((char *, struct obstack *));
 
 static struct type *
-lookup_utype PARAMS ((DIE_REF));
+  lookup_utype PARAMS ((DIE_REF));
 
 static struct type *
-alloc_utype PARAMS ((DIE_REF, struct type *));
+  alloc_utype PARAMS ((DIE_REF, struct type *));
 
 static struct symbol *
-new_symbol PARAMS ((struct dieinfo *, struct objfile *));
+  new_symbol PARAMS ((struct dieinfo *, struct objfile *));
+
+static void
+synthesize_typedef PARAMS ((struct dieinfo *, struct objfile *,
+                           struct type *));
 
 static int
-locval PARAMS ((char *));
+locval PARAMS ((struct dieinfo *));
 
 static void
-record_minimal_symbol PARAMS ((char *, CORE_ADDR, enum minimal_symbol_type,
-                              struct objfile *));
+set_cu_language PARAMS ((struct dieinfo *));
+
+static struct type *
+  dwarf_fundamental_type PARAMS ((struct objfile *, int));
+
 
 /*
 
-GLOBAL FUNCTION
+   LOCAL FUNCTION
 
-       dwarf_build_psymtabs -- build partial symtabs from DWARF debug info
+   dwarf_fundamental_type -- lookup or create a fundamental type
 
-SYNOPSIS
+   SYNOPSIS
 
-       void dwarf_build_psymtabs (int desc, char *filename, CORE_ADDR addr,
-            int mainline, unsigned int dbfoff, unsigned int dbsize,
-            unsigned int lnoffset, unsigned int lnsize,
-            struct objfile *objfile)
+   struct type *
+   dwarf_fundamental_type (struct objfile *objfile, int typeid)
 
-DESCRIPTION
+   DESCRIPTION
 
-       This function is called upon to build partial symtabs from files
-       containing DIE's (Dwarf Information Entries) and DWARF line numbers.
+   DWARF version 1 doesn't supply any fundamental type information,
+   so gdb has to construct such types.  It has a fixed number of
+   fundamental types that it knows how to construct, which is the
+   union of all types that it knows how to construct for all languages
+   that it knows about.  These are enumerated in gdbtypes.h.
 
-       It is passed a file descriptor for an open file containing the DIES
-       and line number information, the corresponding filename for that
-       file, a base address for relocating the symbols, a flag indicating
-       whether or not this debugging information is from a "main symbol
-       table" rather than a shared library or dynamically linked file,
-       and file offset/size pairs for the DIE information and line number
-       information.
+   As an example, assume we find a DIE that references a DWARF
+   fundamental type of FT_integer.  We first look in the ftypes
+   array to see if we already have such a type, indexed by the
+   gdb internal value of FT_INTEGER.  If so, we simply return a
+   pointer to that type.  If not, then we ask an appropriate
+   language dependent routine to create a type FT_INTEGER, using
+   defaults reasonable for the current target machine, and install
+   that type in ftypes for future reference.
 
-RETURNS
+   RETURNS
 
-       No return value.
+   Pointer to a fundamental type.
 
  */
 
-void
-dwarf_build_psymtabs (desc, filename, addr, mainline, dbfoff, dbsize,
-                     lnoffset, lnsize, objfile)
-     int desc;
-     char *filename;
-     CORE_ADDR addr;
-     int mainline;
-     unsigned int dbfoff;
-     unsigned int dbsize;
-     unsigned int lnoffset;
-     unsigned int lnsize;
+static struct type *
+dwarf_fundamental_type (objfile, typeid)
      struct objfile *objfile;
+     int typeid;
 {
-  struct cleanup *back_to;
-  
-  current_objfile = objfile;
-  dbbase = xmalloc (dbsize);
-  dbroff = 0;
-  if ((lseek (desc, dbfoff, 0) != dbfoff) ||
-      (read (desc, dbbase, dbsize) != dbsize))
+  if (typeid < 0 || typeid >= FT_NUM_MEMBERS)
     {
-      free (dbbase);
-      error ("can't read DWARF data from '%s'", filename);
+      error ("internal error - invalid fundamental type id %d", typeid);
     }
-  back_to = make_cleanup (free, dbbase);
-  
-  /* If we are reinitializing, or if we have never loaded syms yet, init.
-     Since we have no idea how many DIES we are looking at, we just guess
-     some arbitrary value. */
-  
-  if (mainline || objfile -> global_psymbols.size == 0 ||
-      objfile -> static_psymbols.size == 0)
+
+  /* Look for this particular type in the fundamental type vector.  If one is
+     not found, create and install one appropriate for the current language
+     and the current target machine. */
+
+  if (ftypes[typeid] == NULL)
     {
-      init_psymbol_list (objfile, 1024);
+      ftypes[typeid] = cu_language_defn->la_fund_type (objfile, typeid);
     }
-  
-  /* Save the relocation factor where everybody can see it.  */
-
-  baseaddr = addr;
 
-  /* Follow the compilation unit sibling chain, building a partial symbol
-     table entry for each one.  Save enough information about each compilation
-     unit to locate the full DWARF information later. */
-  
-  scan_compilation_units (filename, dbbase, dbbase + dbsize,
-                         dbfoff, lnoffset, objfile);
-  
-  do_cleanups (back_to);
-  current_objfile = NULL;
+  return (ftypes[typeid]);
 }
 
-
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       record_minimal_symbol -- add entry to gdb's minimal symbol table
+   set_cu_language -- set local copy of language for compilation unit
 
-SYNOPSIS
+   SYNOPSIS
 
-       static void record_minimal_symbol (char *name, CORE_ADDR address,
-                                         enum minimal_symbol_type ms_type,
-                                         struct objfile *objfile)
+   void
+   set_cu_language (struct dieinfo *dip)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Given a pointer to the name of a symbol that should be added to the
-       minimal symbol table, and the address associated with that
-       symbol, records this information for later use in building the
-       minimal symbol table.
+   Decode the language attribute for a compilation unit DIE and
+   remember what the language was.  We use this at various times
+   when processing DIE's for a given compilation unit.
+
+   RETURNS
+
+   No return value.
 
  */
 
 static void
-record_minimal_symbol (name, address, ms_type, objfile)
-     char *name;
-     CORE_ADDR address;
-     enum minimal_symbol_type ms_type;
-     struct objfile *objfile;
+set_cu_language (dip)
+     struct dieinfo *dip;
 {
-  name = obsavestring (name, strlen (name), &objfile -> symbol_obstack);
-  prim_record_minimal_symbol (name, address, ms_type);
+  switch (dip->at_language)
+    {
+    case LANG_C89:
+    case LANG_C:
+      cu_language = language_c;
+      break;
+    case LANG_C_PLUS_PLUS:
+      cu_language = language_cplus;
+      break;
+    case LANG_CHILL:
+      cu_language = language_chill;
+      break;
+    case LANG_MODULA2:
+      cu_language = language_m2;
+      break;
+    case LANG_FORTRAN77:
+    case LANG_FORTRAN90:
+      cu_language = language_fortran;
+      break;
+    case LANG_ADA83:
+    case LANG_COBOL74:
+    case LANG_COBOL85:
+    case LANG_PASCAL83:
+      /* We don't know anything special about these yet. */
+      cu_language = language_unknown;
+      break;
+    default:
+      /* If no at_language, try to deduce one from the filename */
+      cu_language = deduce_language_from_filename (dip->at_name);
+      break;
+    }
+  cu_language_defn = language_def (cu_language);
 }
 
 /*
 
-LOCAL FUNCTION
+   GLOBAL FUNCTION
 
-       dwarfwarn -- issue a DWARF related warning
+   dwarf_build_psymtabs -- build partial symtabs from DWARF debug info
 
-DESCRIPTION
+   SYNOPSIS
 
-       Issue warnings about DWARF related things that aren't serious enough
-       to warrant aborting with an error, but should not be ignored either.
-       This includes things like detectable corruption in DIE's, missing
-       DIE's, unimplemented features, etc.
+   void dwarf_build_psymtabs (struct objfile *objfile,
+   int mainline, file_ptr dbfoff, unsigned int dbfsize,
+   file_ptr lnoffset, unsigned int lnsize)
 
-       In general, running across tags or attributes that we don't recognize
-       is not considered to be a problem and we should not issue warnings
-       about such.
+   DESCRIPTION
 
-NOTES
+   This function is called upon to build partial symtabs from files
+   containing DIE's (Dwarf Information Entries) and DWARF line numbers.
 
-       We mostly follow the example of the error() routine, but without
-       returning to command level.  It is arguable about whether warnings
-       should be issued at all, and if so, where they should go (stdout or
-       stderr).
+   It is passed a bfd* containing the DIES
+   and line number information, the corresponding filename for that
+   file, a base address for relocating the symbols, a flag indicating
+   whether or not this debugging information is from a "main symbol
+   table" rather than a shared library or dynamically linked file,
+   and file offset/size pairs for the DIE information and line number
+   information.
 
-       We assume that curdie is valid and contains at least the basic
-       information for the DIE where the problem was noticed.
-*/
+   RETURNS
 
-static void
-dwarfwarn (va_alist)
-     va_dcl
-{
-  va_list ap;
-  char *fmt;
-  
-  va_start (ap);
-  fmt = va_arg (ap, char *);
-  warning_setup ();
-  fprintf (stderr, "warning: DWARF ref 0x%x: ", curdie -> die_ref);
-  if (curdie -> at_name)
-    {
-      fprintf (stderr, "'%s': ", curdie -> at_name);
-    }
-  vfprintf (stderr, fmt, ap);
-  fprintf (stderr, "\n");
-  fflush (stderr);
-  va_end (ap);
+   No return value.
+
+ */
+
+void
+dwarf_build_psymtabs (objfile, mainline, dbfoff, dbfsize,
+                     lnoffset, lnsize)
+     struct objfile *objfile;
+     int mainline;
+     file_ptr dbfoff;
+     unsigned int dbfsize;
+     file_ptr lnoffset;
+     unsigned int lnsize;
+{
+  bfd *abfd = objfile->obfd;
+  struct cleanup *back_to;
+
+  current_objfile = objfile;
+  dbsize = dbfsize;
+  dbbase = xmalloc (dbsize);
+  dbroff = 0;
+  if ((bfd_seek (abfd, dbfoff, SEEK_SET) != 0) ||
+      (bfd_read (dbbase, dbsize, 1, abfd) != dbsize))
+    {
+      free (dbbase);
+      error ("can't read DWARF data from '%s'", bfd_get_filename (abfd));
+    }
+  back_to = make_cleanup (free, dbbase);
+
+  /* If we are reinitializing, or if we have never loaded syms yet, init.
+     Since we have no idea how many DIES we are looking at, we just guess
+     some arbitrary value. */
+
+  if (mainline || objfile->global_psymbols.size == 0 ||
+      objfile->static_psymbols.size == 0)
+    {
+      init_psymbol_list (objfile, 1024);
+    }
+
+  /* Save the relocation factor where everybody can see it.  */
+
+  base_section_offsets = objfile->section_offsets;
+  baseaddr = ANOFFSET (objfile->section_offsets, 0);
+
+  /* Follow the compilation unit sibling chain, building a partial symbol
+     table entry for each one.  Save enough information about each compilation
+     unit to locate the full DWARF information later. */
+
+  scan_compilation_units (dbbase, dbbase + dbsize, dbfoff, lnoffset, objfile);
+
+  do_cleanups (back_to);
+  current_objfile = NULL;
 }
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       read_lexical_block_scope -- process all dies in a lexical block
+   read_lexical_block_scope -- process all dies in a lexical block
 
-SYNOPSIS
+   SYNOPSIS
 
-       static void read_lexical_block_scope (struct dieinfo *dip,
-               char *thisdie, char *enddie)
+   static void read_lexical_block_scope (struct dieinfo *dip,
+   char *thisdie, char *enddie)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Process all the DIES contained within a lexical block scope.
-       Start a new scope, process the dies, and then close the scope.
+   Process all the DIES contained within a lexical block scope.
+   Start a new scope, process the dies, and then close the scope.
 
  */
 
@@ -596,34 +803,34 @@ read_lexical_block_scope (dip, thisdie, enddie, objfile)
 {
   register struct context_stack *new;
 
-  (void) push_context (0, dip -> at_low_pc);
-  process_dies (thisdie + dip -> die_length, enddie, objfile);
+  push_context (0, dip->at_low_pc);
+  process_dies (thisdie + dip->die_length, enddie, objfile);
   new = pop_context ();
   if (local_symbols != NULL)
     {
-      finish_block (0, &local_symbols, new -> old_blocks, new -> start_addr,
-                   dip -> at_high_pc, objfile);
+      finish_block (0, &local_symbols, new->old_blocks, new->start_addr,
+                   dip->at_high_pc, objfile);
     }
-  local_symbols = new -> locals;
+  local_symbols = new->locals;
 }
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       lookup_utype -- look up a user defined type from die reference
+   lookup_utype -- look up a user defined type from die reference
 
-SYNOPSIS
+   SYNOPSIS
 
-       static type *lookup_utype (DIE_REF die_ref)
+   static type *lookup_utype (DIE_REF die_ref)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Given a DIE reference, lookup the user defined type associated with
-       that DIE, if it has been registered already.  If not registered, then
-       return NULL.  Alloc_utype() can be called to register an empty
-       type for this reference, which will be filled in later when the
-       actual referenced DIE is processed.
+   Given a DIE reference, lookup the user defined type associated with
+   that DIE, if it has been registered already.  If not registered, then
+   return NULL.  Alloc_utype() can be called to register an empty
+   type for this reference, which will be filled in later when the
+   actual referenced DIE is processed.
  */
 
 static struct type *
@@ -632,11 +839,11 @@ lookup_utype (die_ref)
 {
   struct type *type = NULL;
   int utypeidx;
-  
+
   utypeidx = (die_ref - dbroff) / 4;
   if ((utypeidx < 0) || (utypeidx >= numutypes))
     {
-      dwarfwarn ("reference to DIE (0x%x) outside compilation unit", die_ref);
+      complain (&bad_die_ref, DIE_ID, DIE_NAME);
     }
   else
     {
@@ -648,23 +855,23 @@ lookup_utype (die_ref)
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       alloc_utype  -- add a user defined type for die reference
+   alloc_utype  -- add a user defined type for die reference
 
-SYNOPSIS
+   SYNOPSIS
 
-       static type *alloc_utype (DIE_REF die_ref, struct type *utypep)
+   static type *alloc_utype (DIE_REF die_ref, struct type *utypep)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Given a die reference DIE_REF, and a possible pointer to a user
-       defined type UTYPEP, register that this reference has a user
-       defined type and either use the specified type in UTYPEP or
-       make a new empty type that will be filled in later.
+   Given a die reference DIE_REF, and a possible pointer to a user
+   defined type UTYPEP, register that this reference has a user
+   defined type and either use the specified type in UTYPEP or
+   make a new empty type that will be filled in later.
 
-       We should only be called after calling lookup_utype() to verify that
-       there is not currently a type registered for DIE_REF.
+   We should only be called after calling lookup_utype() to verify that
+   there is not currently a type registered for DIE_REF.
  */
 
 static struct type *
@@ -674,28 +881,24 @@ alloc_utype (die_ref, utypep)
 {
   struct type **typep;
   int utypeidx;
-  
+
   utypeidx = (die_ref - dbroff) / 4;
   typep = utypes + utypeidx;
   if ((utypeidx < 0) || (utypeidx >= numutypes))
     {
-      utypep = lookup_fundamental_type (current_objfile, FT_INTEGER);
-      dwarfwarn ("reference to DIE (0x%x) outside compilation unit", die_ref);
+      utypep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+      complain (&bad_die_ref, DIE_ID, DIE_NAME);
     }
   else if (*typep != NULL)
     {
       utypep = *typep;
-      SQUAWK (("internal error: dup user type allocation"));
+      complain (&dup_user_type_allocation, DIE_ID, DIE_NAME);
     }
   else
     {
       if (utypep == NULL)
        {
-         utypep = (struct type *)
-           obstack_alloc (&current_objfile -> type_obstack,
-                          sizeof (struct type));
-         (void) memset (utypep, 0, sizeof (struct type));
-         TYPE_OBJFILE (utypep) = current_objfile;
+         utypep = alloc_type (current_objfile);
        }
       *typep = utypep;
     }
@@ -704,19 +907,46 @@ alloc_utype (die_ref, utypep)
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       decode_die_type -- return a type for a specified die
+   free_utypes -- free the utypes array and reset pointer & count
 
-SYNOPSIS
+   SYNOPSIS
 
-       static struct type *decode_die_type (struct dieinfo *dip)
+   static void free_utypes (PTR dummy)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Given a pointer to a die information structure DIP, decode the
-       type of the die and return a pointer to the decoded type.  All
-       dies without specific types default to type int.
+   Called via do_cleanups to free the utypes array, reset the pointer to NULL,
+   and set numutypes back to zero.  This ensures that the utypes does not get
+   referenced after being freed.
+ */
+
+static void
+free_utypes (dummy)
+     PTR dummy;
+{
+  free (utypes);
+  utypes = NULL;
+  numutypes = 0;
+}
+
+
+/*
+
+   LOCAL FUNCTION
+
+   decode_die_type -- return a type for a specified die
+
+   SYNOPSIS
+
+   static struct type *decode_die_type (struct dieinfo *dip)
+
+   DESCRIPTION
+
+   Given a pointer to a die information structure DIP, decode the
+   type of the die and return a pointer to the decoded type.  All
+   dies without specific types default to type int.
  */
 
 static struct type *
@@ -724,51 +954,51 @@ decode_die_type (dip)
      struct dieinfo *dip;
 {
   struct type *type = NULL;
-  
-  if (dip -> at_fund_type != 0)
+
+  if (dip->at_fund_type != 0)
     {
-      type = decode_fund_type (dip -> at_fund_type);
+      type = decode_fund_type (dip->at_fund_type);
     }
-  else if (dip -> at_mod_fund_type != NULL)
+  else if (dip->at_mod_fund_type != NULL)
     {
-      type = decode_mod_fund_type (dip -> at_mod_fund_type);
+      type = decode_mod_fund_type (dip->at_mod_fund_type);
     }
-  else if (dip -> at_user_def_type)
+  else if (dip->at_user_def_type)
     {
-      if ((type = lookup_utype (dip -> at_user_def_type)) == NULL)
+      if ((type = lookup_utype (dip->at_user_def_type)) == NULL)
        {
-         type = alloc_utype (dip -> at_user_def_type, NULL);
+         type = alloc_utype (dip->at_user_def_type, NULL);
        }
     }
-  else if (dip -> at_mod_u_d_type)
+  else if (dip->at_mod_u_d_type)
     {
-      type = decode_mod_u_d_type (dip -> at_mod_u_d_type);
+      type = decode_mod_u_d_type (dip->at_mod_u_d_type);
     }
   else
     {
-      type = lookup_fundamental_type (current_objfile, FT_INTEGER);
+      type = dwarf_fundamental_type (current_objfile, FT_VOID);
     }
   return (type);
 }
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       struct_type -- compute and return the type for a struct or union
+   struct_type -- compute and return the type for a struct or union
 
-SYNOPSIS
+   SYNOPSIS
 
-       static struct type *struct_type (struct dieinfo *dip, char *thisdie,
-           char *enddie, struct objfile *objfile)
+   static struct type *struct_type (struct dieinfo *dip, char *thisdie,
+   char *enddie, struct objfile *objfile)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Given pointer to a die information structure for a die which
-       defines a union or structure (and MUST define one or the other),
-       and pointers to the raw die data that define the range of dies which
-       define the members, compute and return the user defined type for the
-       structure or union.
+   Given pointer to a die information structure for a die which
+   defines a union or structure (and MUST define one or the other),
+   and pointers to the raw die data that define the range of dies which
+   define the members, compute and return the user defined type for the
+   structure or union.
  */
 
 static struct type *
@@ -779,56 +1009,59 @@ struct_type (dip, thisdie, enddie, objfile)
      struct objfile *objfile;
 {
   struct type *type;
-  struct nextfield {
-    struct nextfield *next;
-    struct field field;
-  };
+  struct nextfield
+    {
+      struct nextfield *next;
+      struct field field;
+    };
   struct nextfield *list = NULL;
   struct nextfield *new;
   int nfields = 0;
   int n;
-  char *tpart1;
   struct dieinfo mbr;
   char *nextdie;
-  
-  if ((type = lookup_utype (dip -> die_ref)) == NULL)
+  int anonymous_size;
+
+  if ((type = lookup_utype (dip->die_ref)) == NULL)
     {
       /* No forward references created an empty type, so install one now */
-      type = alloc_utype (dip -> die_ref, NULL);
+      type = alloc_utype (dip->die_ref, NULL);
     }
-  INIT_CPLUS_SPECIFIC(type);
-  switch (dip -> die_tag)
+  INIT_CPLUS_SPECIFIC (type);
+  switch (dip->die_tag)
     {
-      case TAG_structure_type:
-        TYPE_CODE (type) = TYPE_CODE_STRUCT;
-       tpart1 = "struct";
-       break;
-      case TAG_union_type:
-       TYPE_CODE (type) = TYPE_CODE_UNION;
-       tpart1 = "union";
-       break;
-      default:
-       /* Should never happen */
-       TYPE_CODE (type) = TYPE_CODE_UNDEF;
-       tpart1 = "???";
-       SQUAWK (("missing structure or union tag"));
-       break;
+    case TAG_class_type:
+      TYPE_CODE (type) = TYPE_CODE_CLASS;
+      break;
+    case TAG_structure_type:
+      TYPE_CODE (type) = TYPE_CODE_STRUCT;
+      break;
+    case TAG_union_type:
+      TYPE_CODE (type) = TYPE_CODE_UNION;
+      break;
+    default:
+      /* Should never happen */
+      TYPE_CODE (type) = TYPE_CODE_UNDEF;
+      complain (&missing_tag, DIE_ID, DIE_NAME);
+      break;
     }
   /* Some compilers try to be helpful by inventing "fake" names for
      anonymous enums, structures, and unions, like "~0fake" or ".0fake".
      Thanks, but no thanks... */
-  if (dip -> at_name != NULL
-      && *dip -> at_name != '~'
-      && *dip -> at_name != '.')
-    {
-      TYPE_NAME (type) = obconcat (&objfile -> type_obstack,
-                                  tpart1, " ", dip -> at_name);
-    }
-  if (dip -> at_byte_size != 0)
-    {
-      TYPE_LENGTH (type) = dip -> at_byte_size;
-    }
-  thisdie += dip -> die_length;
+  if (dip->at_name != NULL
+      && *dip->at_name != '~'
+      && *dip->at_name != '.')
+    {
+      TYPE_TAG_NAME (type) = obconcat (&objfile->type_obstack,
+                                      "", "", dip->at_name);
+    }
+  /* Use whatever size is known.  Zero is a valid size.  We might however
+     wish to check has_at_byte_size to make sure that some byte size was
+     given explicitly, but DWARF doesn't specify that explicit sizes of
+     zero have to present, so complaining about missing sizes should 
+     probably not be the default. */
+  TYPE_LENGTH (type) = dip->at_byte_size;
+  thisdie += dip->die_length;
   while (thisdie < enddie)
     {
       basicdieinfo (&mbr, thisdie, objfile);
@@ -850,33 +1083,57 @@ struct_type (dip, thisdie, enddie, objfile)
        case TAG_member:
          /* Get space to record the next field's data.  */
          new = (struct nextfield *) alloca (sizeof (struct nextfield));
-         new -> next = list;
+         new->next = list;
          list = new;
          /* Save the data.  */
-         list -> field.name = savestring (mbr.at_name, strlen (mbr.at_name));
-         list -> field.type = decode_die_type (&mbr);
-         list -> field.bitpos = 8 * locval (mbr.at_location);
+         list->field.name =
+           obsavestring (mbr.at_name, strlen (mbr.at_name),
+                         &objfile->type_obstack);
+         FIELD_TYPE (list->field) = decode_die_type (&mbr);
+         FIELD_BITPOS (list->field) = 8 * locval (&mbr);
          /* Handle bit fields. */
-         list -> field.bitsize = mbr.at_bit_size;
-#if BITS_BIG_ENDIAN
-         /* For big endian bits, the at_bit_offset gives the additional
-            bit offset from the MSB of the containing anonymous object to
-            the MSB of the field.  We don't have to do anything special
-            since we don't need to know the size of the anonymous object. */
-         list -> field.bitpos += mbr.at_bit_offset;
-#else
-         /* For little endian bits, we need to have a non-zero at_bit_size,
-            so that we know we are in fact dealing with a bitfield.  Compute
-            the bit offset to the MSB of the anonymous object, subtract off
-            the number of bits from the MSB of the field to the MSB of the
-            object, and then subtract off the number of bits of the field
-            itself.  The result is the bit offset of the LSB of the field. */
-         if (mbr.at_bit_size > 0)
+         FIELD_BITSIZE (list->field) = mbr.at_bit_size;
+         if (BITS_BIG_ENDIAN)
            {
-             list -> field.bitpos +=
-               mbr.at_byte_size * 8 - mbr.at_bit_offset - mbr.at_bit_size;
+             /* For big endian bits, the at_bit_offset gives the
+                additional bit offset from the MSB of the containing
+                anonymous object to the MSB of the field.  We don't
+                have to do anything special since we don't need to
+                know the size of the anonymous object. */
+             FIELD_BITPOS (list->field) += mbr.at_bit_offset;
+           }
+         else
+           {
+             /* For little endian bits, we need to have a non-zero
+                at_bit_size, so that we know we are in fact dealing
+                with a bitfield.  Compute the bit offset to the MSB
+                of the anonymous object, subtract off the number of
+                bits from the MSB of the field to the MSB of the
+                object, and then subtract off the number of bits of
+                the field itself.  The result is the bit offset of
+                the LSB of the field. */
+             if (mbr.at_bit_size > 0)
+               {
+                 if (mbr.has_at_byte_size)
+                   {
+                     /* The size of the anonymous object containing
+                        the bit field is explicit, so use the
+                        indicated size (in bytes). */
+                     anonymous_size = mbr.at_byte_size;
+                   }
+                 else
+                   {
+                     /* The size of the anonymous object containing
+                        the bit field matches the size of an object
+                        of the bit field's type.  DWARF allows
+                        at_byte_size to be left out in such cases, as
+                        a debug information size optimization. */
+                     anonymous_size = TYPE_LENGTH (list->field.type);
+                   }
+                 FIELD_BITPOS (list->field) +=
+                   anonymous_size * 8 - mbr.at_bit_offset - mbr.at_bit_size;
+               }
            }
-#endif
          nfields++;
          break;
        default:
@@ -898,49 +1155,48 @@ struct_type (dip, thisdie, enddie, objfile)
     {
       TYPE_NFIELDS (type) = nfields;
       TYPE_FIELDS (type) = (struct field *)
-       obstack_alloc (&objfile -> type_obstack,
-                      sizeof (struct field) * nfields);
+       TYPE_ALLOC (type, sizeof (struct field) * nfields);
       /* Copy the saved-up fields into the field vector.  */
-      for (n = nfields; list; list = list -> next)
+      for (n = nfields; list; list = list->next)
        {
-         TYPE_FIELD (type, --n) = list -> field;
-       }       
+         TYPE_FIELD (type, --n) = list->field;
+       }
     }
   return (type);
 }
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       read_structure_scope -- process all dies within struct or union
+   read_structure_scope -- process all dies within struct or union
 
-SYNOPSIS
+   SYNOPSIS
 
-       static void read_structure_scope (struct dieinfo *dip,
-               char *thisdie, char *enddie, struct objfile *objfile)
+   static void read_structure_scope (struct dieinfo *dip,
+   char *thisdie, char *enddie, struct objfile *objfile)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Called when we find the DIE that starts a structure or union
-       scope (definition) to process all dies that define the members
-       of the structure or union.  DIP is a pointer to the die info
-       struct for the DIE that names the structure or union.
+   Called when we find the DIE that starts a structure or union
+   scope (definition) to process all dies that define the members
+   of the structure or union.  DIP is a pointer to the die info
+   struct for the DIE that names the structure or union.
 
-NOTES
+   NOTES
+
+   Note that we need to call struct_type regardless of whether or not
+   the DIE has an at_name attribute, since it might be an anonymous
+   structure or union.  This gets the type entered into our set of
+   user defined types.
+
+   However, if the structure is incomplete (an opaque struct/union)
+   then suppress creating a symbol table entry for it since gdb only
+   wants to find the one with the complete definition.  Note that if
+   it is complete, we just call new_symbol, which does it's own
+   checking about whether the struct/union is anonymous or not (and
+   suppresses creating a symbol table entry itself).
 
-       Note that we need to call struct_type regardless of whether or not
-       the DIE has an at_name attribute, since it might be an anonymous
-       structure or union.  This gets the type entered into our set of
-       user defined types.
-
-       However, if the structure is incomplete (an opaque struct/union)
-       then suppress creating a symbol table entry for it since gdb only
-       wants to find the one with the complete definition.  Note that if
-       it is complete, we just call new_symbol, which does it's own
-       checking about whether the struct/union is anonymous or not (and
-       suppresses creating a symbol table entry itself).
-       
  */
 
 static void
@@ -952,34 +1208,39 @@ read_structure_scope (dip, thisdie, enddie, objfile)
 {
   struct type *type;
   struct symbol *sym;
-  
+
   type = struct_type (dip, thisdie, enddie, objfile);
   if (!(TYPE_FLAGS (type) & TYPE_FLAG_STUB))
     {
-      if ((sym = new_symbol (dip, objfile)) != NULL)
+      sym = new_symbol (dip, objfile);
+      if (sym != NULL)
        {
          SYMBOL_TYPE (sym) = type;
+         if (cu_language == language_cplus)
+           {
+             synthesize_typedef (dip, objfile, type);
+           }
        }
     }
 }
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       decode_array_element_type -- decode type of the array elements
+   decode_array_element_type -- decode type of the array elements
 
-SYNOPSIS
+   SYNOPSIS
 
-       static struct type *decode_array_element_type (char *scan, char *end)
+   static struct type *decode_array_element_type (char *scan, char *end)
 
-DESCRIPTION
+   DESCRIPTION
 
-       As the last step in decoding the array subscript information for an
-       array DIE, we need to decode the type of the array elements.  We are
-       passed a pointer to this last part of the subscript information and
-       must return the appropriate type.  If the type attribute is not
-       recognized, just warn about the problem and return type int.
+   As the last step in decoding the array subscript information for an
+   array DIE, we need to decode the type of the array elements.  We are
+   passed a pointer to this last part of the subscript information and
+   must return the appropriate type.  If the type attribute is not
+   recognized, just warn about the problem and return type int.
  */
 
 static struct type *
@@ -991,92 +1252,107 @@ decode_array_element_type (scan)
   unsigned short attribute;
   unsigned short fundtype;
   int nbytes;
-  
+
   attribute = target_to_host (scan, SIZEOF_ATTRIBUTE, GET_UNSIGNED,
                              current_objfile);
   scan += SIZEOF_ATTRIBUTE;
   if ((nbytes = attribute_size (attribute)) == -1)
     {
-      SQUAWK (("bad array element type attribute 0x%x", attribute));
-      typep = lookup_fundamental_type (current_objfile, FT_INTEGER);
+      complain (&bad_array_element_type, DIE_ID, DIE_NAME, attribute);
+      typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
     }
   else
     {
       switch (attribute)
        {
-         case AT_fund_type:
-           fundtype = target_to_host (scan, nbytes, GET_UNSIGNED,
-                                      current_objfile);
-           typep = decode_fund_type (fundtype);
-           break;
-         case AT_mod_fund_type:
-           typep = decode_mod_fund_type (scan);
-           break;
-         case AT_user_def_type:
-           die_ref = target_to_host (scan, nbytes, GET_UNSIGNED,
-                                     current_objfile);
-           if ((typep = lookup_utype (die_ref)) == NULL)
-             {
-               typep = alloc_utype (die_ref, NULL);
-             }
-           break;
-         case AT_mod_u_d_type:
-           typep = decode_mod_u_d_type (scan);
-           break;
-         default:
-           SQUAWK (("bad array element type attribute 0x%x", attribute));
-           typep = lookup_fundamental_type (current_objfile, FT_INTEGER);
-           break;
-         }
+       case AT_fund_type:
+         fundtype = target_to_host (scan, nbytes, GET_UNSIGNED,
+                                    current_objfile);
+         typep = decode_fund_type (fundtype);
+         break;
+       case AT_mod_fund_type:
+         typep = decode_mod_fund_type (scan);
+         break;
+       case AT_user_def_type:
+         die_ref = target_to_host (scan, nbytes, GET_UNSIGNED,
+                                   current_objfile);
+         if ((typep = lookup_utype (die_ref)) == NULL)
+           {
+             typep = alloc_utype (die_ref, NULL);
+           }
+         break;
+       case AT_mod_u_d_type:
+         typep = decode_mod_u_d_type (scan);
+         break;
+       default:
+         complain (&bad_array_element_type, DIE_ID, DIE_NAME, attribute);
+         typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+         break;
+       }
     }
   return (typep);
 }
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       decode_subscr_data -- decode array subscript and element type data
+   decode_subscript_data_item -- decode array subscript item
 
-SYNOPSIS
+   SYNOPSIS
 
-       static struct type *decode_subscr_data (char *scan, char *end)
+   static struct type *
+   decode_subscript_data_item (char *scan, char *end)
 
-DESCRIPTION
+   DESCRIPTION
+
+   The array subscripts and the data type of the elements of an
+   array are described by a list of data items, stored as a block
+   of contiguous bytes.  There is a data item describing each array
+   dimension, and a final data item describing the element type.
+   The data items are ordered the same as their appearance in the
+   source (I.E. leftmost dimension first, next to leftmost second,
+   etc).
+
+   The data items describing each array dimension consist of four
+   parts: (1) a format specifier, (2) type type of the subscript
+   index, (3) a description of the low bound of the array dimension,
+   and (4) a description of the high bound of the array dimension.
+
+   The last data item is the description of the type of each of
+   the array elements.
 
-       The array subscripts and the data type of the elements of an
-       array are described by a list of data items, stored as a block
-       of contiguous bytes.  There is a data item describing each array
-       dimension, and a final data item describing the element type.
-       The data items are ordered the same as their appearance in the
-       source (I.E. leftmost dimension first, next to leftmost second,
-       etc).
+   We are passed a pointer to the start of the block of bytes
+   containing the remaining data items, and a pointer to the first
+   byte past the data.  This function recursively decodes the
+   remaining data items and returns a type.
 
-       We are passed a pointer to the start of the block of bytes
-       containing the data items, and a pointer to the first byte past
-       the data.  This function decodes the data and returns a type.
+   If we somehow fail to decode some data, we complain about it
+   and return a type "array of int".
 
-BUGS
-       FIXME:  This code only implements the forms currently used
-       by the AT&T and GNU C compilers.
+   BUGS
+   FIXME:  This code only implements the forms currently used
+   by the AT&T and GNU C compilers.
 
-       The end pointer is supplied for error checking, maybe we should
-       use it for that...
+   The end pointer is supplied for error checking, maybe we should
+   use it for that...
  */
 
 static struct type *
-decode_subscr_data (scan, end)
+decode_subscript_data_item (scan, end)
      char *scan;
      char *end;
 {
-  struct type *typep = NULL;
-  struct type *nexttype;
+  struct type *typep = NULL;   /* Array type we are building */
+  struct type *nexttype;       /* Type of each element (may be array) */
+  struct type *indextype;      /* Type of this index */
+  struct type *rangetype;
   unsigned int format;
   unsigned short fundtype;
   unsigned long lowbound;
   unsigned long highbound;
   int nbytes;
-  
+
   format = target_to_host (scan, SIZEOF_FORMAT_SPECIFIER, GET_UNSIGNED,
                           current_objfile);
   scan += SIZEOF_FORMAT_SPECIFIER;
@@ -1088,36 +1364,23 @@ decode_subscr_data (scan, end)
     case FMT_FT_C_C:
       fundtype = target_to_host (scan, SIZEOF_FMT_FT, GET_UNSIGNED,
                                 current_objfile);
+      indextype = decode_fund_type (fundtype);
       scan += SIZEOF_FMT_FT;
-      if (fundtype != FT_integer && fundtype != FT_signed_integer
-         && fundtype != FT_unsigned_integer)
+      nbytes = TARGET_FT_LONG_SIZE (current_objfile);
+      lowbound = target_to_host (scan, nbytes, GET_UNSIGNED, current_objfile);
+      scan += nbytes;
+      highbound = target_to_host (scan, nbytes, GET_UNSIGNED, current_objfile);
+      scan += nbytes;
+      nexttype = decode_subscript_data_item (scan, end);
+      if (nexttype == NULL)
        {
-         SQUAWK (("array subscripts must be integral types, not type 0x%x",
-                  fundtype));
-       }
-      else
-       {
-         nbytes = TARGET_FT_LONG_SIZE (current_objfile);
-         lowbound = target_to_host (scan, nbytes, GET_UNSIGNED,
-                                    current_objfile);
-         scan += nbytes;
-         highbound = target_to_host (scan, nbytes, GET_UNSIGNED,
-                                     current_objfile);
-         scan += nbytes;
-         nexttype = decode_subscr_data (scan, end);
-         if (nexttype != NULL)
-           {
-             typep = (struct type *)
-               obstack_alloc (&current_objfile -> type_obstack,
-                              sizeof (struct type));
-             (void) memset (typep, 0, sizeof (struct type));
-             TYPE_OBJFILE (typep) = current_objfile;
-             TYPE_CODE (typep) = TYPE_CODE_ARRAY;
-             TYPE_LENGTH (typep) = TYPE_LENGTH (nexttype);
-             TYPE_LENGTH (typep) *= (highbound - lowbound) + 1;
-             TYPE_TARGET_TYPE (typep) = nexttype;
-           }               
+         /* Munged subscript data or other problem, fake it. */
+         complain (&subscript_data_items, DIE_ID, DIE_NAME);
+         nexttype = dwarf_fundamental_type (current_objfile, FT_INTEGER);
        }
+      rangetype = create_range_type ((struct type *) NULL, indextype,
+                                    lowbound, highbound);
+      typep = create_array_type ((struct type *) NULL, nexttype, rangetype);
       break;
     case FMT_FT_C_X:
     case FMT_FT_X_C:
@@ -1126,10 +1389,16 @@ decode_subscr_data (scan, end)
     case FMT_UT_C_X:
     case FMT_UT_X_C:
     case FMT_UT_X_X:
-      SQUAWK (("array subscript format 0x%x not handled yet", format));
+      complain (&unhandled_array_subscript_format, DIE_ID, DIE_NAME, format);
+      nexttype = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+      rangetype = create_range_type ((struct type *) NULL, nexttype, 0, 0);
+      typep = create_array_type ((struct type *) NULL, nexttype, rangetype);
       break;
     default:
-      SQUAWK (("unknown array subscript format %x", format));
+      complain (&unknown_array_subscript_format, DIE_ID, DIE_NAME, format);
+      nexttype = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+      rangetype = create_range_type ((struct type *) NULL, nexttype, 0, 0);
+      typep = create_array_type ((struct type *) NULL, nexttype, rangetype);
       break;
     }
   return (typep);
@@ -1137,18 +1406,18 @@ decode_subscr_data (scan, end)
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       dwarf_read_array_type -- read TAG_array_type DIE
+   dwarf_read_array_type -- read TAG_array_type DIE
 
-SYNOPSIS
+   SYNOPSIS
 
-       static void dwarf_read_array_type (struct dieinfo *dip)
+   static void dwarf_read_array_type (struct dieinfo *dip)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Extract all information from a TAG_array_type DIE and add to
-       the user defined type vector.
+   Extract all information from a TAG_array_type DIE and add to
+   the user defined type vector.
  */
 
 static void
@@ -1161,60 +1430,59 @@ dwarf_read_array_type (dip)
   char *subend;
   unsigned short blocksz;
   int nbytes;
-  
-  if (dip -> at_ordering != ORD_row_major)
+
+  if (dip->at_ordering != ORD_row_major)
     {
       /* FIXME:  Can gdb even handle column major arrays? */
-      SQUAWK (("array not row major; not handled correctly"));
+      complain (&not_row_major, DIE_ID, DIE_NAME);
     }
-  if ((sub = dip -> at_subscr_data) != NULL)
+  if ((sub = dip->at_subscr_data) != NULL)
     {
       nbytes = attribute_size (AT_subscr_data);
       blocksz = target_to_host (sub, nbytes, GET_UNSIGNED, current_objfile);
       subend = sub + nbytes + blocksz;
       sub += nbytes;
-      type = decode_subscr_data (sub, subend);
-      if (type == NULL)
+      type = decode_subscript_data_item (sub, subend);
+      if ((utype = lookup_utype (dip->die_ref)) == NULL)
        {
-         if ((utype = lookup_utype (dip -> die_ref)) == NULL)
-           {
-             utype = alloc_utype (dip -> die_ref, NULL);
-           }
-         TYPE_CODE (utype) = TYPE_CODE_ARRAY;
-         TYPE_TARGET_TYPE (utype) = 
-           lookup_fundamental_type (current_objfile, FT_INTEGER);
-         TYPE_LENGTH (utype) = 1 * TYPE_LENGTH (TYPE_TARGET_TYPE (utype));
+         /* Install user defined type that has not been referenced yet. */
+         alloc_utype (dip->die_ref, type);
+       }
+      else if (TYPE_CODE (utype) == TYPE_CODE_UNDEF)
+       {
+         /* Ick!  A forward ref has already generated a blank type in our
+            slot, and this type probably already has things pointing to it
+            (which is what caused it to be created in the first place).
+            If it's just a place holder we can plop our fully defined type
+            on top of it.  We can't recover the space allocated for our
+            new type since it might be on an obstack, but we could reuse
+            it if we kept a list of them, but it might not be worth it
+            (FIXME). */
+         *utype = *type;
        }
       else
        {
-         if ((utype = lookup_utype (dip -> die_ref)) == NULL)
-           {
-             (void) alloc_utype (dip -> die_ref, type);
-           }
-         else
-           {
-             TYPE_CODE (utype) = TYPE_CODE_ARRAY;
-             TYPE_LENGTH (utype) = TYPE_LENGTH (type);
-             TYPE_TARGET_TYPE (utype) = TYPE_TARGET_TYPE (type);
-           }
+         /* Double ick!  Not only is a type already in our slot, but
+            someone has decorated it.  Complain and leave it alone. */
+         complain (&dup_user_type_definition, DIE_ID, DIE_NAME);
        }
     }
 }
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       read_tag_pointer_type -- read TAG_pointer_type DIE
+   read_tag_pointer_type -- read TAG_pointer_type DIE
 
-SYNOPSIS
+   SYNOPSIS
 
-       static void read_tag_pointer_type (struct dieinfo *dip)
+   static void read_tag_pointer_type (struct dieinfo *dip)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Extract all information from a TAG_pointer_type DIE and add to
-       the user defined type vector.
+   Extract all information from a TAG_pointer_type DIE and add to
+   the user defined type vector.
  */
 
 static void
@@ -1223,12 +1491,12 @@ read_tag_pointer_type (dip)
 {
   struct type *type;
   struct type *utype;
-  
+
   type = decode_die_type (dip);
-  if ((utype = lookup_utype (dip -> die_ref)) == NULL)
+  if ((utype = lookup_utype (dip->die_ref)) == NULL)
     {
       utype = lookup_pointer_type (type);
-      (void) alloc_utype (dip -> die_ref, utype);
+      alloc_utype (dip->die_ref, utype);
     }
   else
     {
@@ -1236,39 +1504,100 @@ read_tag_pointer_type (dip)
       TYPE_POINTER_TYPE (type) = utype;
 
       /* We assume the machine has only one representation for pointers!  */
-      /* FIXME:  This confuses host<->target data representations, and is a
-        poor assumption besides. */
-      
-      TYPE_LENGTH (utype) = sizeof (char *);
+      /* FIXME:  Possably a poor assumption  */
+      TYPE_LENGTH (utype) = TARGET_PTR_BIT / TARGET_CHAR_BIT;
       TYPE_CODE (utype) = TYPE_CODE_PTR;
     }
 }
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       read_subroutine_type -- process TAG_subroutine_type dies
+   read_tag_string_type -- read TAG_string_type DIE
 
-SYNOPSIS
+   SYNOPSIS
 
-       static void read_subroutine_type (struct dieinfo *dip, char thisdie,
-               char *enddie)
+   static void read_tag_string_type (struct dieinfo *dip)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Handle DIES due to C code like:
+   Extract all information from a TAG_string_type DIE and add to
+   the user defined type vector.  It isn't really a user defined
+   type, but it behaves like one, with other DIE's using an
+   AT_user_def_type attribute to reference it.
+ */
 
-       struct foo {
-           int (*funcp)(int a, long l);  (Generates TAG_subroutine_type DIE)
-           int b;
-       };
+static void
+read_tag_string_type (dip)
+     struct dieinfo *dip;
+{
+  struct type *utype;
+  struct type *indextype;
+  struct type *rangetype;
+  unsigned long lowbound = 0;
+  unsigned long highbound;
 
-NOTES
+  if (dip->has_at_byte_size)
+    {
+      /* A fixed bounds string */
+      highbound = dip->at_byte_size - 1;
+    }
+  else
+    {
+      /* A varying length string.  Stub for now.  (FIXME) */
+      highbound = 1;
+    }
+  indextype = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+  rangetype = create_range_type ((struct type *) NULL, indextype, lowbound,
+                                highbound);
+
+  utype = lookup_utype (dip->die_ref);
+  if (utype == NULL)
+    {
+      /* No type defined, go ahead and create a blank one to use. */
+      utype = alloc_utype (dip->die_ref, (struct type *) NULL);
+    }
+  else
+    {
+      /* Already a type in our slot due to a forward reference. Make sure it
+         is a blank one.  If not, complain and leave it alone. */
+      if (TYPE_CODE (utype) != TYPE_CODE_UNDEF)
+       {
+         complain (&dup_user_type_definition, DIE_ID, DIE_NAME);
+         return;
+       }
+    }
+
+  /* Create the string type using the blank type we either found or created. */
+  utype = create_string_type (utype, rangetype);
+}
+
+/*
+
+   LOCAL FUNCTION
+
+   read_subroutine_type -- process TAG_subroutine_type dies
+
+   SYNOPSIS
+
+   static void read_subroutine_type (struct dieinfo *dip, char thisdie,
+   char *enddie)
+
+   DESCRIPTION
+
+   Handle DIES due to C code like:
+
+   struct foo {
+   int (*funcp)(int a, long l);  (Generates TAG_subroutine_type DIE)
+   int b;
+   };
+
+   NOTES
 
-       The parameter DIES are currently ignored.  See if gdb has a way to
-       include this info in it's type system, and decode them if so.  Is
-       this what the type structure's "arg_types" field is for?  (FIXME)
+   The parameter DIES are currently ignored.  See if gdb has a way to
+   include this info in it's type system, and decode them if so.  Is
+   this what the type structure's "arg_types" field is for?  (FIXME)
  */
 
 static void
@@ -1279,7 +1608,7 @@ read_subroutine_type (dip, thisdie, enddie)
 {
   struct type *type;           /* Type that this function returns */
   struct type *ftype;          /* Function that returns above type */
-  
+
   /* Decode the type that this subroutine returns */
 
   type = decode_die_type (dip);
@@ -1287,45 +1616,48 @@ read_subroutine_type (dip, thisdie, enddie)
   /* Check to see if we already have a partially constructed user
      defined type for this DIE, from a forward reference. */
 
-  if ((ftype = lookup_utype (dip -> die_ref)) == NULL)
+  if ((ftype = lookup_utype (dip->die_ref)) == NULL)
     {
       /* This is the first reference to one of these types.  Make
-        a new one and place it in the user defined types. */
+         a new one and place it in the user defined types. */
       ftype = lookup_function_type (type);
-      (void) alloc_utype (dip -> die_ref, ftype);
+      alloc_utype (dip->die_ref, ftype);
     }
-  else
+  else if (TYPE_CODE (ftype) == TYPE_CODE_UNDEF)
     {
       /* We have an existing partially constructed type, so bash it
-        into the correct type. */
+         into the correct type. */
       TYPE_TARGET_TYPE (ftype) = type;
-      TYPE_FUNCTION_TYPE (type) = ftype;
       TYPE_LENGTH (ftype) = 1;
       TYPE_CODE (ftype) = TYPE_CODE_FUNC;
     }
+  else
+    {
+      complain (&dup_user_type_definition, DIE_ID, DIE_NAME);
+    }
 }
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       read_enumeration -- process dies which define an enumeration
+   read_enumeration -- process dies which define an enumeration
 
-SYNOPSIS
+   SYNOPSIS
 
-       static void read_enumeration (struct dieinfo *dip, char *thisdie,
-               char *enddie, struct objfile *objfile)
+   static void read_enumeration (struct dieinfo *dip, char *thisdie,
+   char *enddie, struct objfile *objfile)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Given a pointer to a die which begins an enumeration, process all
-       the dies that define the members of the enumeration.
+   Given a pointer to a die which begins an enumeration, process all
+   the dies that define the members of the enumeration.
 
-NOTES
+   NOTES
 
-       Note that we need to call enum_type regardless of whether or not we
-       have a symbol, since we might have an enum without a tag name (thus
-       no symbol for the tagname).
+   Note that we need to call enum_type regardless of whether or not we
+   have a symbol, since we might have an enum without a tag name (thus
+   no symbol for the tagname).
  */
 
 static void
@@ -1337,43 +1669,48 @@ read_enumeration (dip, thisdie, enddie, objfile)
 {
   struct type *type;
   struct symbol *sym;
-  
+
   type = enum_type (dip, objfile);
-  if ((sym = new_symbol (dip, objfile)) != NULL)
+  sym = new_symbol (dip, objfile);
+  if (sym != NULL)
     {
       SYMBOL_TYPE (sym) = type;
+      if (cu_language == language_cplus)
+       {
+         synthesize_typedef (dip, objfile, type);
+       }
     }
 }
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       enum_type -- decode and return a type for an enumeration
+   enum_type -- decode and return a type for an enumeration
 
-SYNOPSIS
+   SYNOPSIS
 
-       static type *enum_type (struct dieinfo *dip, struct objfile *objfile)
+   static type *enum_type (struct dieinfo *dip, struct objfile *objfile)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Given a pointer to a die information structure for the die which
-       starts an enumeration, process all the dies that define the members
-       of the enumeration and return a type pointer for the enumeration.
+   Given a pointer to a die information structure for the die which
+   starts an enumeration, process all the dies that define the members
+   of the enumeration and return a type pointer for the enumeration.
 
-       At the same time, for each member of the enumeration, create a
-       symbol for it with namespace VAR_NAMESPACE and class LOC_CONST,
-       and give it the type of the enumeration itself.
+   At the same time, for each member of the enumeration, create a
+   symbol for it with namespace VAR_NAMESPACE and class LOC_CONST,
+   and give it the type of the enumeration itself.
 
-NOTES
+   NOTES
 
-       Note that the DWARF specification explicitly mandates that enum
-       constants occur in reverse order from the source program order,
-       for "consistency" and because this ordering is easier for many
-       compilers to generate. (Draft 6, sec 3.8.5, Enumeration type
-       Entries).  Because gdb wants to see the enum members in program
-       source order, we have to ensure that the order gets reversed while
-       we are processing them.
+   Note that the DWARF specification explicitly mandates that enum
+   constants occur in reverse order from the source program order,
+   for "consistency" and because this ordering is easier for many
+   compilers to generate. (Draft 6, sec 3.8.5, Enumeration type
+   Entries).  Because gdb wants to see the enum members in program
+   source order, we have to ensure that the order gets reversed while
+   we are processing them.
  */
 
 static struct type *
@@ -1382,10 +1719,11 @@ enum_type (dip, objfile)
      struct objfile *objfile;
 {
   struct type *type;
-  struct nextfield {
-    struct nextfield *next;
-    struct field field;
-  };
+  struct nextfield
+    {
+      struct nextfield *next;
+      struct field field;
+    };
   struct nextfield *list = NULL;
   struct nextfield *new;
   int nfields = 0;
@@ -1395,30 +1733,31 @@ enum_type (dip, objfile)
   unsigned short blocksz;
   struct symbol *sym;
   int nbytes;
-  
-  if ((type = lookup_utype (dip -> die_ref)) == NULL)
+  int unsigned_enum = 1;
+
+  if ((type = lookup_utype (dip->die_ref)) == NULL)
     {
       /* No forward references created an empty type, so install one now */
-      type = alloc_utype (dip -> die_ref, NULL);
+      type = alloc_utype (dip->die_ref, NULL);
     }
   TYPE_CODE (type) = TYPE_CODE_ENUM;
   /* Some compilers try to be helpful by inventing "fake" names for
      anonymous enums, structures, and unions, like "~0fake" or ".0fake".
      Thanks, but no thanks... */
-  if (dip -> at_name != NULL
-      && *dip -> at_name != '~'
-      && *dip -> at_name != '.')
+  if (dip->at_name != NULL
+      && *dip->at_name != '~'
+      && *dip->at_name != '.')
     {
-      TYPE_NAME (type) = obconcat (&objfile -> type_obstack, "enum",
-                                  " ", dip -> at_name);
+      TYPE_TAG_NAME (type) = obconcat (&objfile->type_obstack,
+                                      "", "", dip->at_name);
     }
-  if (dip -> at_byte_size != 0)
+  if (dip->at_byte_size != 0)
     {
-      TYPE_LENGTH (type) = dip -> at_byte_size;
+      TYPE_LENGTH (type) = dip->at_byte_size;
     }
-  if ((scan = dip -> at_element_list) != NULL)
+  if ((scan = dip->at_element_list) != NULL)
     {
-      if (dip -> short_element_list)
+      if (dip->short_element_list)
        {
          nbytes = attribute_size (AT_short_element_list);
        }
@@ -1432,44 +1771,50 @@ enum_type (dip, objfile)
       while (scan < listend)
        {
          new = (struct nextfield *) alloca (sizeof (struct nextfield));
-         new -> next = list;
+         new->next = list;
          list = new;
-         list -> field.type = NULL;
-         list -> field.bitsize = 0;
-         list -> field.bitpos =
+         FIELD_TYPE (list->field) = NULL;
+         FIELD_BITSIZE (list->field) = 0;
+         FIELD_BITPOS (list->field) =
            target_to_host (scan, TARGET_FT_LONG_SIZE (objfile), GET_SIGNED,
                            objfile);
          scan += TARGET_FT_LONG_SIZE (objfile);
-         list -> field.name = savestring (scan, strlen (scan));
+         list->field.name = obsavestring (scan, strlen (scan),
+                                          &objfile->type_obstack);
          scan += strlen (scan) + 1;
          nfields++;
          /* Handcraft a new symbol for this enum member. */
          sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
                                                 sizeof (struct symbol));
-         (void) memset (sym, 0, sizeof (struct symbol));
-         SYMBOL_NAME (sym) = create_name (list -> field.name,
+         memset (sym, 0, sizeof (struct symbol));
+         SYMBOL_NAME (sym) = create_name (list->field.name,
                                           &objfile->symbol_obstack);
+         SYMBOL_INIT_LANGUAGE_SPECIFIC (sym, cu_language);
          SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
          SYMBOL_CLASS (sym) = LOC_CONST;
          SYMBOL_TYPE (sym) = type;
-         SYMBOL_VALUE (sym) = list -> field.bitpos;
+         SYMBOL_VALUE (sym) = FIELD_BITPOS (list->field);
+         if (SYMBOL_VALUE (sym) < 0)
+           unsigned_enum = 0;
          add_symbol_to_list (sym, list_in_scope);
        }
       /* Now create the vector of fields, and record how big it is. This is
-        where we reverse the order, by pulling the members of the list in
-        reverse order from how they were inserted.  If we have no fields
-        (this is apparently possible in C++) then skip building a field
-        vector. */
+         where we reverse the order, by pulling the members off the list in
+         reverse order from how they were inserted.  If we have no fields
+         (this is apparently possible in C++) then skip building a field
+         vector. */
       if (nfields > 0)
        {
+         if (unsigned_enum)
+           TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
          TYPE_NFIELDS (type) = nfields;
          TYPE_FIELDS (type) = (struct field *)
            obstack_alloc (&objfile->symbol_obstack, sizeof (struct field) * nfields);
          /* Copy the saved-up fields into the field vector.  */
-         for (n = 0; (n < nfields) && (list != NULL); list = list -> next)
+         for (n = 0; (n < nfields) && (list != NULL); list = list->next)
            {
-             TYPE_FIELD (type, n++) = list -> field;
-           }   
+             TYPE_FIELD (type, n++) = list->field;
+           }
        }
     }
   return (type);
@@ -1477,23 +1822,23 @@ enum_type (dip, objfile)
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       read_func_scope -- process all dies within a function scope
+   read_func_scope -- process all dies within a function scope
 
-DESCRIPTION
+   DESCRIPTION
+
+   Process all dies within a given function scope.  We are passed
+   a die information structure pointer DIP for the die which
+   starts the function scope, and pointers into the raw die data
+   that define the dies within the function scope.
 
-       Process all dies within a given function scope.  We are passed
-       a die information structure pointer DIP for the die which
-       starts the function scope, and pointers into the raw die data
-       that define the dies within the function scope.
-
-       For now, we ignore lexical block scopes within the function.
-       The problem is that AT&T cc does not define a DWARF lexical
-       block scope for the function itself, while gcc defines a
-       lexical block scope for the function.  We need to think about
-       how to handle this difference, or if it is even a problem.
-       (FIXME)
+   For now, we ignore lexical block scopes within the function.
+   The problem is that AT&T cc does not define a DWARF lexical
+   block scope for the function itself, while gcc defines a
+   lexical block scope for the function.  We need to think about
+   how to handle this difference, or if it is even a problem.
+   (FIXME)
  */
 
 static void
@@ -1504,49 +1849,107 @@ read_func_scope (dip, thisdie, enddie, objfile)
      struct objfile *objfile;
 {
   register struct context_stack *new;
-  
-  if (objfile -> ei.entry_point >= dip -> at_low_pc &&
-      objfile -> ei.entry_point <  dip -> at_high_pc)
+
+  /* AT_name is absent if the function is described with an
+     AT_abstract_origin tag.
+     Ignore the function description for now to avoid GDB core dumps.
+     FIXME: Add code to handle AT_abstract_origin tags properly.  */
+  if (dip->at_name == NULL)
     {
-      objfile -> ei.entry_func_lowpc = dip -> at_low_pc;
-      objfile -> ei.entry_func_highpc = dip -> at_high_pc;
+      complain (&missing_at_name, DIE_ID);
+      return;
     }
-  if (STREQ (dip -> at_name, "main"))  /* FIXME: hardwired name */
+
+  if (objfile->ei.entry_point >= dip->at_low_pc &&
+      objfile->ei.entry_point < dip->at_high_pc)
     {
-      objfile -> ei.main_func_lowpc = dip -> at_low_pc;
-      objfile -> ei.main_func_highpc = dip -> at_high_pc;
+      objfile->ei.entry_func_lowpc = dip->at_low_pc;
+      objfile->ei.entry_func_highpc = dip->at_high_pc;
     }
-  new = push_context (0, dip -> at_low_pc);
-  new -> name = new_symbol (dip, objfile);
+  new = push_context (0, dip->at_low_pc);
+  new->name = new_symbol (dip, objfile);
   list_in_scope = &local_symbols;
-  process_dies (thisdie + dip -> die_length, enddie, objfile);
+  process_dies (thisdie + dip->die_length, enddie, objfile);
   new = pop_context ();
   /* Make a block for the local symbols within.  */
-  finish_block (new -> name, &local_symbols, new -> old_blocks,
-               new -> start_addr, dip -> at_high_pc, objfile);
+  finish_block (new->name, &local_symbols, new->old_blocks,
+               new->start_addr, dip->at_high_pc, objfile);
   list_in_scope = &file_symbols;
 }
 
+
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       read_file_scope -- process all dies within a file scope
+   handle_producer -- process the AT_producer attribute
+
+   DESCRIPTION
+
+   Perform any operations that depend on finding a particular
+   AT_producer attribute.
+
+ */
+
+static void
+handle_producer (producer)
+     char *producer;
+{
+
+  /* If this compilation unit was compiled with g++ or gcc, then set the
+     processing_gcc_compilation flag. */
+
+  if (STREQN (producer, GCC_PRODUCER, strlen (GCC_PRODUCER)))
+    {
+      char version = producer[strlen (GCC_PRODUCER)];
+      processing_gcc_compilation = (version == '2' ? 2 : 1);
+    }
+  else
+    {
+      processing_gcc_compilation =
+       STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER))
+       || STREQN (producer, CHILL_PRODUCER, strlen (CHILL_PRODUCER));
+    }
+
+  /* Select a demangling style if we can identify the producer and if
+     the current style is auto.  We leave the current style alone if it
+     is not auto.  We also leave the demangling style alone if we find a
+     gcc (cc1) producer, as opposed to a g++ (cc1plus) producer. */
+
+  if (AUTO_DEMANGLING)
+    {
+      if (STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER)))
+       {
+         set_demangling_style (GNU_DEMANGLING_STYLE_STRING);
+       }
+      else if (STREQN (producer, LCC_PRODUCER, strlen (LCC_PRODUCER)))
+       {
+         set_demangling_style (LUCID_DEMANGLING_STYLE_STRING);
+       }
+    }
+}
 
-DESCRIPTION
 
-       Process all dies within a given file scope.  We are passed a
-       pointer to the die information structure for the die which
-       starts the file scope, and pointers into the raw die data which
-       mark the range of dies within the file scope.
-
-       When the partial symbol table is built, the file offset for the line
-       number table for each compilation unit is saved in the partial symbol
-       table entry for that compilation unit.  As the symbols for each
-       compilation unit are read, the line number table is read into memory
-       and the variable lnbase is set to point to it.  Thus all we have to
-       do is use lnbase to access the line number table for the current
-       compilation unit.
+/*
+
+   LOCAL FUNCTION
+
+   read_file_scope -- process all dies within a file scope
+
+   DESCRIPTION
+
+   Process all dies within a given file scope.  We are passed a
+   pointer to the die information structure for the die which
+   starts the file scope, and pointers into the raw die data which
+   mark the range of dies within the file scope.
+
+   When the partial symbol table is built, the file offset for the line
+   number table for each compilation unit is saved in the partial symbol
+   table entry for that compilation unit.  As the symbols for each
+   compilation unit are read, the line number table is read into memory
+   and the variable lnbase is set to point to it.  Thus all we have to
+   do is use lnbase to access the line number table for the current
+   compilation unit.
  */
 
 static void
@@ -1558,59 +1961,51 @@ read_file_scope (dip, thisdie, enddie, objfile)
 {
   struct cleanup *back_to;
   struct symtab *symtab;
-  
-  if (objfile -> ei.entry_point >= dip -> at_low_pc &&
-      objfile -> ei.entry_point <  dip -> at_high_pc)
+
+  if (objfile->ei.entry_point >= dip->at_low_pc &&
+      objfile->ei.entry_point < dip->at_high_pc)
     {
-      objfile -> ei.entry_file_lowpc = dip -> at_low_pc;
-      objfile -> ei.entry_file_highpc = dip -> at_high_pc;
+      objfile->ei.entry_file_lowpc = dip->at_low_pc;
+      objfile->ei.entry_file_highpc = dip->at_high_pc;
     }
-  if (dip -> at_producer != NULL)
+  set_cu_language (dip);
+  if (dip->at_producer != NULL)
     {
-      processing_gcc_compilation =
-       STREQN (dip -> at_producer, GCC_PRODUCER, strlen (GCC_PRODUCER));
+      handle_producer (dip->at_producer);
     }
   numutypes = (enddie - thisdie) / 4;
   utypes = (struct type **) xmalloc (numutypes * sizeof (struct type *));
-  back_to = make_cleanup (free, utypes);
-  (void) memset (utypes, 0, numutypes * sizeof (struct type *));
-  start_symtab (dip -> at_name, NULL, dip -> at_low_pc);
+  back_to = make_cleanup (free_utypes, NULL);
+  memset (utypes, 0, numutypes * sizeof (struct type *));
+  memset (ftypes, 0, FT_NUM_MEMBERS * sizeof (struct type *));
+  start_symtab (dip->at_name, dip->at_comp_dir, dip->at_low_pc);
+  record_debugformat ("DWARF 1");
   decode_line_numbers (lnbase);
-  process_dies (thisdie + dip -> die_length, enddie, objfile);
-  symtab = end_symtab (dip -> at_high_pc, 0, 0, objfile);
-  /* FIXME:  The following may need to be expanded for other languages */
-  switch (dip -> at_language)
-    {
-      case LANG_C89:
-      case LANG_C:
-       symtab -> language = language_c;
-       break;
-      case LANG_C_PLUS_PLUS:
-       symtab -> language = language_cplus;
-       break;
-      default:
-       ;
+  process_dies (thisdie + dip->die_length, enddie, objfile);
+
+  symtab = end_symtab (dip->at_high_pc, objfile, 0);
+  if (symtab != NULL)
+    {
+      symtab->language = cu_language;
     }
   do_cleanups (back_to);
-  utypes = NULL;
-  numutypes = 0;
 }
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       process_dies -- process a range of DWARF Information Entries
+   process_dies -- process a range of DWARF Information Entries
 
-SYNOPSIS
+   SYNOPSIS
 
-       static void process_dies (char *thisdie, char *enddie,
-                                 struct objfile *objfile)
+   static void process_dies (char *thisdie, char *enddie,
+   struct objfile *objfile)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Process all DIE's in a specified range.  May be (and almost
-       certainly will be) called recursively.
+   Process all DIE's in a specified range.  May be (and almost
+   certainly will be) called recursively.
  */
 
 static void
@@ -1621,7 +2016,7 @@ process_dies (thisdie, enddie, objfile)
 {
   char *nextdie;
   struct dieinfo di;
-  
+
   while (thisdie < enddie)
     {
       basicdieinfo (&di, thisdie, objfile);
@@ -1644,10 +2039,21 @@ process_dies (thisdie, enddie, objfile)
            {
              nextdie = thisdie + di.die_length;
            }
+#ifdef SMASH_TEXT_ADDRESS
+         /* I think that these are always text, not data, addresses.  */
+         SMASH_TEXT_ADDRESS (di.at_low_pc);
+         SMASH_TEXT_ADDRESS (di.at_high_pc);
+#endif
          switch (di.die_tag)
            {
            case TAG_compile_unit:
-             read_file_scope (&di, thisdie, nextdie, objfile);
+             /* Skip Tag_compile_unit if we are already inside a compilation
+                unit, we are unable to handle nested compilation units
+                properly (FIXME).  */
+             if (current_subfile == NULL)
+               read_file_scope (&di, thisdie, nextdie, objfile);
+             else
+               nextdie = thisdie + di.die_length;
              break;
            case TAG_global_subroutine:
            case TAG_subroutine:
@@ -1659,6 +2065,7 @@ process_dies (thisdie, enddie, objfile)
            case TAG_lexical_block:
              read_lexical_block_scope (&di, thisdie, nextdie, objfile);
              break;
+           case TAG_class_type:
            case TAG_structure_type:
            case TAG_union_type:
              read_structure_scope (&di, thisdie, nextdie, objfile);
@@ -1675,8 +2082,11 @@ process_dies (thisdie, enddie, objfile)
            case TAG_pointer_type:
              read_tag_pointer_type (&di);
              break;
+           case TAG_string_type:
+             read_tag_string_type (&di);
+             break;
            default:
-             (void) new_symbol (&di, objfile);
+             new_symbol (&di, objfile);
              break;
            }
        }
@@ -1686,62 +2096,62 @@ process_dies (thisdie, enddie, objfile)
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       decode_line_numbers -- decode a line number table fragment
+   decode_line_numbers -- decode a line number table fragment
 
-SYNOPSIS
+   SYNOPSIS
 
-       static void decode_line_numbers (char *tblscan, char *tblend,
-               long length, long base, long line, long pc)
+   static void decode_line_numbers (char *tblscan, char *tblend,
+   long length, long base, long line, long pc)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Translate the DWARF line number information to gdb form.
+   Translate the DWARF line number information to gdb form.
 
-       The ".line" section contains one or more line number tables, one for
-       each ".line" section from the objects that were linked.
+   The ".line" section contains one or more line number tables, one for
+   each ".line" section from the objects that were linked.
 
-       The AT_stmt_list attribute for each TAG_source_file entry in the
-       ".debug" section contains the offset into the ".line" section for the
-       start of the table for that file.
+   The AT_stmt_list attribute for each TAG_source_file entry in the
+   ".debug" section contains the offset into the ".line" section for the
+   start of the table for that file.
 
-       The table itself has the following structure:
+   The table itself has the following structure:
 
-       <table length><base address><source statement entry>
-       4 bytes       4 bytes       10 bytes
+   <table length><base address><source statement entry>
+   4 bytes       4 bytes       10 bytes
 
-       The table length is the total size of the table, including the 4 bytes
-       for the length information.
+   The table length is the total size of the table, including the 4 bytes
+   for the length information.
 
-       The base address is the address of the first instruction generated
-       for the source file.
+   The base address is the address of the first instruction generated
+   for the source file.
 
-       Each source statement entry has the following structure:
+   Each source statement entry has the following structure:
 
-       <line number><statement position><address delta>
-       4 bytes      2 bytes             4 bytes
+   <line number><statement position><address delta>
+   4 bytes      2 bytes             4 bytes
 
-       The line number is relative to the start of the file, starting with
-       line 1.
+   The line number is relative to the start of the file, starting with
+   line 1.
 
-       The statement position either -1 (0xFFFF) or the number of characters
-       from the beginning of the line to the beginning of the statement.
+   The statement position either -1 (0xFFFF) or the number of characters
+   from the beginning of the line to the beginning of the statement.
 
-       The address delta is the difference between the base address and
-       the address of the first instruction for the statement.
+   The address delta is the difference between the base address and
+   the address of the first instruction for the statement.
 
-       Note that we must copy the bytes from the packed table to our local
-       variables before attempting to use them, to avoid alignment problems
-       on some machines, particularly RISC processors.
+   Note that we must copy the bytes from the packed table to our local
+   variables before attempting to use them, to avoid alignment problems
+   on some machines, particularly RISC processors.
 
-BUGS
+   BUGS
 
-       Does gdb expect the line numbers to be sorted?  They are now by
-       chance/luck, but are not required to be.  (FIXME)
+   Does gdb expect the line numbers to be sorted?  They are now by
+   chance/luck, but are not required to be.  (FIXME)
 
-       The line with number 0 is unused, gdb apparently can discover the
-       span of the last line some other way. How?  (FIXME)
+   The line with number 0 is unused, gdb apparently can discover the
+   span of the last line some other way. How?  (FIXME)
  */
 
 static void
@@ -1754,7 +2164,7 @@ decode_line_numbers (linetable)
   unsigned long base;
   unsigned long line;
   unsigned long pc;
-  
+
   if (linetable != NULL)
     {
       tblscan = tblend = linetable;
@@ -1785,116 +2195,117 @@ decode_line_numbers (linetable)
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       locval -- compute the value of a location attribute
+   locval -- compute the value of a location attribute
 
-SYNOPSIS
+   SYNOPSIS
 
-       static int locval (char *loc)
+   static int locval (struct dieinfo *dip)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Given pointer to a string of bytes that define a location, compute
-       the location and return the value.
+   Given pointer to a string of bytes that define a location, compute
+   the location and return the value.
+   A location description containing no atoms indicates that the
+   object is optimized out. The optimized_out flag is set for those,
+   the return value is meaningless.
 
-       When computing values involving the current value of the frame pointer,
-       the value zero is used, which results in a value relative to the frame
-       pointer, rather than the absolute value.  This is what GDB wants
-       anyway.
-    
-       When the result is a register number, the global isreg flag is set,
-       otherwise it is cleared.  This is a kludge until we figure out a better
-       way to handle the problem.  Gdb's design does not mesh well with the
-       DWARF notion of a location computing interpreter, which is a shame
-       because the flexibility goes unused.
+   When computing values involving the current value of the frame pointer,
+   the value zero is used, which results in a value relative to the frame
+   pointer, rather than the absolute value.  This is what GDB wants
+   anyway.
 
-NOTES
+   When the result is a register number, the isreg flag is set, otherwise
+   it is cleared.  This is a kludge until we figure out a better
+   way to handle the problem.  Gdb's design does not mesh well with the
+   DWARF notion of a location computing interpreter, which is a shame
+   because the flexibility goes unused.
 
-       Note that stack[0] is unused except as a default error return.
-       Note that stack overflow is not yet handled.
+   NOTES
+
+   Note that stack[0] is unused except as a default error return.
+   Note that stack overflow is not yet handled.
  */
 
 static int
-locval (loc)
-     char *loc;
+locval (dip)
+     struct dieinfo *dip;
 {
   unsigned short nbytes;
   unsigned short locsize;
   auto long stack[64];
   int stacki;
+  char *loc;
   char *end;
-  long regno;
   int loc_atom_code;
   int loc_value_size;
-  
+
+  loc = dip->at_location;
   nbytes = attribute_size (AT_location);
   locsize = target_to_host (loc, nbytes, GET_UNSIGNED, current_objfile);
   loc += nbytes;
   end = loc + locsize;
   stacki = 0;
   stack[stacki] = 0;
-  isreg = 0;
-  offreg = 0;
+  dip->isreg = 0;
+  dip->offreg = 0;
+  dip->optimized_out = 1;
   loc_value_size = TARGET_FT_LONG_SIZE (current_objfile);
   while (loc < end)
     {
+      dip->optimized_out = 0;
       loc_atom_code = target_to_host (loc, SIZEOF_LOC_ATOM_CODE, GET_UNSIGNED,
                                      current_objfile);
       loc += SIZEOF_LOC_ATOM_CODE;
       switch (loc_atom_code)
        {
-         case 0:
-           /* error */
-           loc = end;
-           break;
-         case OP_REG:
-           /* push register (number) */
-           stack[++stacki] = target_to_host (loc, loc_value_size,
-                                             GET_UNSIGNED, current_objfile);
-           loc += loc_value_size;
-           isreg = 1;
-           break;
-         case OP_BASEREG:
-           /* push value of register (number) */
-           /* Actually, we compute the value as if register has 0 */
-           offreg = 1;
-           regno = target_to_host (loc, loc_value_size, GET_UNSIGNED,
-                                   current_objfile);
-           loc += loc_value_size;
-           if (regno == R_FP)
-             {
-               stack[++stacki] = 0;
-             }
-           else
-             {
-               stack[++stacki] = 0;
-               SQUAWK (("BASEREG %d not handled!", regno));
-             }
-           break;
-         case OP_ADDR:
-           /* push address (relocated address) */
-           stack[++stacki] = target_to_host (loc, loc_value_size,
-                                             GET_UNSIGNED, current_objfile);
-           loc += loc_value_size;
-           break;
-         case OP_CONST:
-           /* push constant (number)   FIXME: signed or unsigned! */
-           stack[++stacki] = target_to_host (loc, loc_value_size,
-                                             GET_SIGNED, current_objfile);
-           loc += loc_value_size;
-           break;
-         case OP_DEREF2:
-           /* pop, deref and push 2 bytes (as a long) */
-           SQUAWK (("OP_DEREF2 address 0x%x not handled", stack[stacki]));
-           break;
-         case OP_DEREF4:       /* pop, deref and push 4 bytes (as a long) */
-           SQUAWK (("OP_DEREF4 address 0x%x not handled", stack[stacki]));
-           break;
-         case OP_ADD:  /* pop top 2 items, add, push result */
-           stack[stacki - 1] += stack[stacki];
-           stacki--;
-           break;
+       case 0:
+         /* error */
+         loc = end;
+         break;
+       case OP_REG:
+         /* push register (number) */
+         stack[++stacki]
+           = DWARF_REG_TO_REGNUM (target_to_host (loc, loc_value_size,
+                                                  GET_UNSIGNED,
+                                                  current_objfile));
+         loc += loc_value_size;
+         dip->isreg = 1;
+         break;
+       case OP_BASEREG:
+         /* push value of register (number) */
+         /* Actually, we compute the value as if register has 0, so the
+            value ends up being the offset from that register.  */
+         dip->offreg = 1;
+         dip->basereg = target_to_host (loc, loc_value_size, GET_UNSIGNED,
+                                        current_objfile);
+         loc += loc_value_size;
+         stack[++stacki] = 0;
+         break;
+       case OP_ADDR:
+         /* push address (relocated address) */
+         stack[++stacki] = target_to_host (loc, loc_value_size,
+                                           GET_UNSIGNED, current_objfile);
+         loc += loc_value_size;
+         break;
+       case OP_CONST:
+         /* push constant (number)   FIXME: signed or unsigned! */
+         stack[++stacki] = target_to_host (loc, loc_value_size,
+                                           GET_SIGNED, current_objfile);
+         loc += loc_value_size;
+         break;
+       case OP_DEREF2:
+         /* pop, deref and push 2 bytes (as a long) */
+         complain (&op_deref2, DIE_ID, DIE_NAME, stack[stacki]);
+         break;
+       case OP_DEREF4: /* pop, deref and push 4 bytes (as a long) */
+         complain (&op_deref4, DIE_ID, DIE_NAME, stack[stacki]);
+         break;
+       case OP_ADD:            /* pop top 2 items, add, push result */
+         stack[stacki - 1] += stack[stacki];
+         stacki--;
+         break;
        }
     }
   return (stack[stacki]);
@@ -1902,47 +2313,48 @@ locval (loc)
 
 /*
 
-LOCAL FUNCTION
-
-       read_ofile_symtab -- build a full symtab entry from chunk of DIE's
+   LOCAL FUNCTION
 
-SYNOPSIS
+   read_ofile_symtab -- build a full symtab entry from chunk of DIE's
 
-       static struct symtab *read_ofile_symtab (struct partial_symtab *pst)
+   SYNOPSIS
 
-DESCRIPTION
+   static void read_ofile_symtab (struct partial_symtab *pst)
 
-       When expanding a partial symbol table entry to a full symbol table
-       entry, this is the function that gets called to read in the symbols
-       for the compilation unit.
+   DESCRIPTION
 
-       Returns a pointer to the newly constructed symtab (which is now
-       the new first one on the objfile's symtab list).
+   When expanding a partial symbol table entry to a full symbol table
+   entry, this is the function that gets called to read in the symbols
+   for the compilation unit.  A pointer to the newly constructed symtab,
+   which is now the new first one on the objfile's symtab list, is
+   stashed in the partial symbol table entry.
  */
 
-static struct symtab *
+static void
 read_ofile_symtab (pst)
      struct partial_symtab *pst;
 {
   struct cleanup *back_to;
   unsigned long lnsize;
-  int foffset;
+  file_ptr foffset;
   bfd *abfd;
   char lnsizedata[SIZEOF_LINETBL_LENGTH];
 
-  abfd = pst -> objfile -> obfd;
-  current_objfile = pst -> objfile;
+  abfd = pst->objfile->obfd;
+  current_objfile = pst->objfile;
 
   /* Allocate a buffer for the entire chunk of DIE's for this compilation
      unit, seek to the location in the file, and read in all the DIE's. */
 
   diecount = 0;
-  dbbase = xmalloc (DBLENGTH(pst));
-  dbroff = DBROFF(pst);
-  foffset = DBFOFF(pst) + dbroff;
-  baseaddr = pst -> addr;
-  if (bfd_seek (abfd, foffset, 0) ||
-      (bfd_read (dbbase, DBLENGTH(pst), 1, abfd) != DBLENGTH(pst)))
+  dbsize = DBLENGTH (pst);
+  dbbase = xmalloc (dbsize);
+  dbroff = DBROFF (pst);
+  foffset = DBFOFF (pst) + dbroff;
+  base_section_offsets = pst->section_offsets;
+  baseaddr = ANOFFSET (pst->section_offsets, 0);
+  if (bfd_seek (abfd, foffset, SEEK_SET) ||
+      (bfd_read (dbbase, dbsize, 1, abfd) != dbsize))
     {
       free (dbbase);
       error ("can't read DWARF data");
@@ -1957,16 +2369,16 @@ read_ofile_symtab (pst)
   lnbase = NULL;
   if (LNFOFF (pst))
     {
-      if (bfd_seek (abfd, LNFOFF (pst), 0) ||
+      if (bfd_seek (abfd, LNFOFF (pst), SEEK_SET) ||
          (bfd_read ((PTR) lnsizedata, sizeof (lnsizedata), 1, abfd) !=
           sizeof (lnsizedata)))
        {
          error ("can't read DWARF line number table size");
        }
       lnsize = target_to_host (lnsizedata, SIZEOF_LINETBL_LENGTH,
-                              GET_UNSIGNED, pst -> objfile);
+                              GET_UNSIGNED, pst->objfile);
       lnbase = xmalloc (lnsize);
-      if (bfd_seek (abfd, LNFOFF (pst), 0) ||
+      if (bfd_seek (abfd, LNFOFF (pst), SEEK_SET) ||
          (bfd_read (lnbase, lnsize, 1, abfd) != lnsize))
        {
          free (lnbase);
@@ -1975,97 +2387,101 @@ read_ofile_symtab (pst)
       make_cleanup (free, lnbase);
     }
 
-  process_dies (dbbase, dbbase + DBLENGTH(pst), pst -> objfile);
+  process_dies (dbbase, dbbase + dbsize, pst->objfile);
   do_cleanups (back_to);
   current_objfile = NULL;
-  return (pst -> objfile -> symtabs);
+  pst->symtab = pst->objfile->symtabs;
 }
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       psymtab_to_symtab_1 -- do grunt work for building a full symtab entry
+   psymtab_to_symtab_1 -- do grunt work for building a full symtab entry
 
-SYNOPSIS
+   SYNOPSIS
 
-       static void psymtab_to_symtab_1 (struct partial_symtab *pst)
+   static void psymtab_to_symtab_1 (struct partial_symtab *pst)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Called once for each partial symbol table entry that needs to be
-       expanded into a full symbol table entry.
+   Called once for each partial symbol table entry that needs to be
+   expanded into a full symbol table entry.
 
-*/
+ */
 
 static void
 psymtab_to_symtab_1 (pst)
      struct partial_symtab *pst;
 {
   int i;
-  
+  struct cleanup *old_chain;
+
   if (pst != NULL)
     {
       if (pst->readin)
        {
          warning ("psymtab for %s already read in.  Shouldn't happen.",
-                  pst -> filename);
+                  pst->filename);
        }
       else
        {
          /* Read in all partial symtabs on which this one is dependent */
-         for (i = 0; i < pst -> number_of_dependencies; i++)
+         for (i = 0; i < pst->number_of_dependencies; i++)
            {
-             if (!pst -> dependencies[i] -> readin)
+             if (!pst->dependencies[i]->readin)
                {
                  /* Inform about additional files that need to be read in. */
                  if (info_verbose)
                    {
-                     fputs_filtered (" ", stdout);
+                     fputs_filtered (" ", gdb_stdout);
                      wrap_here ("");
-                     fputs_filtered ("and ", stdout);
+                     fputs_filtered ("and ", gdb_stdout);
                      wrap_here ("");
                      printf_filtered ("%s...",
-                                      pst -> dependencies[i] -> filename);
+                                      pst->dependencies[i]->filename);
                      wrap_here ("");
-                     fflush (stdout);          /* Flush output */
+                     gdb_flush (gdb_stdout);   /* Flush output */
                    }
-                 psymtab_to_symtab_1 (pst -> dependencies[i]);
+                 psymtab_to_symtab_1 (pst->dependencies[i]);
                }
-           }     
-         if (DBLENGTH (pst))           /* Otherwise it's a dummy */
+           }
+         if (DBLENGTH (pst))   /* Otherwise it's a dummy */
            {
-             pst -> symtab = read_ofile_symtab (pst);
+             buildsym_init ();
+             old_chain = make_cleanup (really_free_pendings, 0);
+             read_ofile_symtab (pst);
              if (info_verbose)
                {
                  printf_filtered ("%d DIE's, sorting...", diecount);
                  wrap_here ("");
-                 fflush (stdout);
+                 gdb_flush (gdb_stdout);
                }
-             sort_symtab_syms (pst -> symtab);
+             sort_symtab_syms (pst->symtab);
+             do_cleanups (old_chain);
            }
-         pst -> readin = 1;
+         pst->readin = 1;
        }
     }
 }
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       dwarf_psymtab_to_symtab -- build a full symtab entry from partial one
+   dwarf_psymtab_to_symtab -- build a full symtab entry from partial one
 
-SYNOPSIS
+   SYNOPSIS
 
-       static void dwarf_psymtab_to_symtab (struct partial_symtab *pst)
+   static void dwarf_psymtab_to_symtab (struct partial_symtab *pst)
 
-DESCRIPTION
+   DESCRIPTION
 
-       This is the DWARF support entry point for building a full symbol
-       table entry from a partial symbol table entry.  We are passed a
-       pointer to the partial symbol table entry that needs to be expanded.
+   This is the DWARF support entry point for building a full symbol
+   table entry from a partial symbol table entry.  We are passed a
+   pointer to the partial symbol table entry that needs to be expanded.
 
-*/
+ */
 
 static void
 dwarf_psymtab_to_symtab (pst)
@@ -2074,40 +2490,40 @@ dwarf_psymtab_to_symtab (pst)
 
   if (pst != NULL)
     {
-      if (pst -> readin)
+      if (pst->readin)
        {
          warning ("psymtab for %s already read in.  Shouldn't happen.",
-                  pst -> filename);
+                  pst->filename);
        }
       else
        {
-         if (DBLENGTH (pst) || pst -> number_of_dependencies)
+         if (DBLENGTH (pst) || pst->number_of_dependencies)
            {
              /* Print the message now, before starting serious work, to avoid
-                disconcerting pauses.  */
+                disconcerting pauses.  */
              if (info_verbose)
                {
                  printf_filtered ("Reading in symbols for %s...",
-                                  pst -> filename);
-                 fflush (stdout);
+                                  pst->filename);
+                 gdb_flush (gdb_stdout);
                }
-             
+
              psymtab_to_symtab_1 (pst);
-             
-#if 0        /* FIXME:  Check to see what dbxread is doing here and see if
-                we need to do an equivalent or is this something peculiar to
-                stabs/a.out format.
-                Match with global symbols.  This only needs to be done once,
-                after all of the symtabs and dependencies have been read in.
-                */
-             scan_file_globals (pst -> objfile);
+
+#if 0                          /* FIXME:  Check to see what dbxread is doing here and see if
+                                  we need to do an equivalent or is this something peculiar to
+                                  stabs/a.out format.
+                                  Match with global symbols.  This only needs to be done once,
+                                  after all of the symtabs and dependencies have been read in.
+                                */
+             scan_file_globals (pst->objfile);
 #endif
-             
+
              /* Finish up the verbose info message.  */
              if (info_verbose)
                {
                  printf_filtered ("done.\n");
-                 fflush (stdout);
+                 gdb_flush (gdb_stdout);
                }
            }
        }
@@ -2116,65 +2532,17 @@ dwarf_psymtab_to_symtab (pst)
 
 /*
 
-LOCAL FUNCTION
-
-       init_psymbol_list -- initialize storage for partial symbols
-
-SYNOPSIS
+   LOCAL FUNCTION
 
-       static void init_psymbol_list (struct objfile *objfile, int total_symbols)
+   add_enum_psymbol -- add enumeration members to partial symbol table
 
-DESCRIPTION
+   DESCRIPTION
 
-       Initializes storage for all of the partial symbols that will be
-       created by dwarf_build_psymtabs and subsidiaries.
+   Given pointer to a DIE that is known to be for an enumeration,
+   extract the symbolic names of the enumeration members and add
+   partial symbols for them.
  */
 
-static void
-init_psymbol_list (objfile, total_symbols)
-     struct objfile *objfile;
-     int total_symbols;
-{
-  /* Free any previously allocated psymbol lists.  */
-  
-  if (objfile -> global_psymbols.list)
-    {
-      mfree (objfile -> md, (PTR)objfile -> global_psymbols.list);
-    }
-  if (objfile -> static_psymbols.list)
-    {
-      mfree (objfile -> md, (PTR)objfile -> static_psymbols.list);
-    }
-  
-  /* Current best guess is that there are approximately a twentieth
-     of the total symbols (in a debugging file) are global or static
-     oriented symbols */
-  
-  objfile -> global_psymbols.size = total_symbols / 10;
-  objfile -> static_psymbols.size = total_symbols / 10;
-  objfile -> global_psymbols.next =
-    objfile -> global_psymbols.list = (struct partial_symbol *)
-      xmmalloc (objfile -> md, objfile -> global_psymbols.size
-                            * sizeof (struct partial_symbol));
-  objfile -> static_psymbols.next =
-    objfile -> static_psymbols.list = (struct partial_symbol *)
-      xmmalloc (objfile -> md, objfile -> static_psymbols.size
-                            * sizeof (struct partial_symbol));
-}
-
-/*
-
-LOCAL FUNCTION
-
-       add_enum_psymbol -- add enumeration members to partial symbol table
-
-DESCRIPTION
-
-       Given pointer to a DIE that is known to be for an enumeration,
-       extract the symbolic names of the enumeration members and add
-       partial symbols for them.
-*/
-
 static void
 add_enum_psymbol (dip, objfile)
      struct dieinfo *dip;
@@ -2184,10 +2552,10 @@ add_enum_psymbol (dip, objfile)
   char *listend;
   unsigned short blocksz;
   int nbytes;
-  
-  if ((scan = dip -> at_element_list) != NULL)
+
+  if ((scan = dip->at_element_list) != NULL)
     {
-      if (dip -> short_element_list)
+      if (dip->short_element_list)
        {
          nbytes = attribute_size (AT_short_element_list);
        }
@@ -2201,8 +2569,9 @@ add_enum_psymbol (dip, objfile)
       while (scan < listend)
        {
          scan += TARGET_FT_LONG_SIZE (objfile);
-         ADD_PSYMBOL_TO_LIST (scan, strlen (scan), VAR_NAMESPACE, LOC_CONST,
-                              objfile -> static_psymbols, 0);
+         add_psymbol_to_list (scan, strlen (scan), VAR_NAMESPACE, LOC_CONST,
+                              &objfile->static_psymbols, 0, 0, cu_language,
+                              objfile);
          scan += strlen (scan) + 1;
        }
     }
@@ -2210,79 +2579,81 @@ add_enum_psymbol (dip, objfile)
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       add_partial_symbol -- add symbol to partial symbol table
+   add_partial_symbol -- add symbol to partial symbol table
 
-DESCRIPTION
+   DESCRIPTION
 
-       Given a DIE, if it is one of the types that we want to
-       add to a partial symbol table, finish filling in the die info
-       and then add a partial symbol table entry for it.
+   Given a DIE, if it is one of the types that we want to
+   add to a partial symbol table, finish filling in the die info
+   and then add a partial symbol table entry for it.
 
-*/
+   NOTES
+
+   The caller must ensure that the DIE has a valid name attribute.
+ */
 
 static void
 add_partial_symbol (dip, objfile)
      struct dieinfo *dip;
      struct objfile *objfile;
 {
-  switch (dip -> die_tag)
+  switch (dip->die_tag)
     {
     case TAG_global_subroutine:
-      record_minimal_symbol (dip -> at_name, dip -> at_low_pc, mst_text,
-                           objfile);
-      ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
+      add_psymbol_to_list (dip->at_name, strlen (dip->at_name),
                           VAR_NAMESPACE, LOC_BLOCK,
-                          objfile -> global_psymbols,
-                          dip -> at_low_pc);
+                          &objfile->global_psymbols,
+                          0, dip->at_low_pc, cu_language, objfile);
       break;
     case TAG_global_variable:
-      record_minimal_symbol (dip -> at_name, locval (dip -> at_location),
-                           mst_data, objfile);
-      ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
+      add_psymbol_to_list (dip->at_name, strlen (dip->at_name),
                           VAR_NAMESPACE, LOC_STATIC,
-                          objfile -> global_psymbols,
-                          0);
+                          &objfile->global_psymbols,
+                          0, 0, cu_language, objfile);
       break;
     case TAG_subroutine:
-      ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
+      add_psymbol_to_list (dip->at_name, strlen (dip->at_name),
                           VAR_NAMESPACE, LOC_BLOCK,
-                          objfile -> static_psymbols,
-                          dip -> at_low_pc);
+                          &objfile->static_psymbols,
+                          0, dip->at_low_pc, cu_language, objfile);
       break;
     case TAG_local_variable:
-      ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
+      add_psymbol_to_list (dip->at_name, strlen (dip->at_name),
                           VAR_NAMESPACE, LOC_STATIC,
-                          objfile -> static_psymbols,
-                          0);
+                          &objfile->static_psymbols,
+                          0, 0, cu_language, objfile);
       break;
     case TAG_typedef:
-      ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
+      add_psymbol_to_list (dip->at_name, strlen (dip->at_name),
                           VAR_NAMESPACE, LOC_TYPEDEF,
-                          objfile -> static_psymbols,
-                          0);
+                          &objfile->static_psymbols,
+                          0, 0, cu_language, objfile);
       break;
+    case TAG_class_type:
     case TAG_structure_type:
     case TAG_union_type:
-      ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
-                          STRUCT_NAMESPACE, LOC_TYPEDEF,
-                          objfile -> static_psymbols,
-                          0);
-      break;
     case TAG_enumeration_type:
-      if (dip -> at_name)
+      /* Do not add opaque aggregate definitions to the psymtab.  */
+      if (!dip->has_at_byte_size)
+       break;
+      add_psymbol_to_list (dip->at_name, strlen (dip->at_name),
+                          STRUCT_NAMESPACE, LOC_TYPEDEF,
+                          &objfile->static_psymbols,
+                          0, 0, cu_language, objfile);
+      if (cu_language == language_cplus)
        {
-         ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
-                              STRUCT_NAMESPACE, LOC_TYPEDEF,
-                              objfile -> static_psymbols,
-                              0);
+         /* For C++, these implicitly act as typedefs as well. */
+         add_psymbol_to_list (dip->at_name, strlen (dip->at_name),
+                              VAR_NAMESPACE, LOC_TYPEDEF,
+                              &objfile->static_psymbols,
+                              0, 0, cu_language, objfile);
        }
-      add_enum_psymbol (dip, objfile);
       break;
     }
 }
-
+/* *INDENT-OFF* */
 /*
 
 LOCAL FUNCTION
@@ -2293,15 +2664,50 @@ DESCRIPTION
 
        Process the DIE's within a single compilation unit, looking for
        interesting DIE's that contribute to the partial symbol table entry
-       for this compilation unit.  Since we cannot follow any sibling
-       chains without reading the complete DIE info for every DIE,
-       it is probably faster to just sequentially check each one to
-       see if it is one of the types we are interested in, and if so,
-       then extract all the attributes info and generate a partial
-       symbol table entry.
+       for this compilation unit.
 
 NOTES
 
+       There are some DIE's that may appear both at file scope and within
+       the scope of a function.  We are only interested in the ones at file
+       scope, and the only way to tell them apart is to keep track of the
+       scope.  For example, consider the test case:
+
+               static int i;
+               main () { int j; }
+
+       for which the relevant DWARF segment has the structure:
+       
+               0x51:
+               0x23   global subrtn   sibling     0x9b
+                                      name        main
+                                      fund_type   FT_integer
+                                      low_pc      0x800004cc
+                                      high_pc     0x800004d4
+                                           
+               0x74:
+               0x23   local var       sibling     0x97
+                                      name        j
+                                      fund_type   FT_integer
+                                      location    OP_BASEREG 0xe
+                                                  OP_CONST 0xfffffffc
+                                                  OP_ADD
+               0x97:
+               0x4         
+               
+               0x9b:
+               0x1d   local var       sibling     0xb8
+                                      name        i
+                                      fund_type   FT_integer
+                                      location    OP_ADDR 0x800025dc
+                                           
+               0xb8:
+               0x4         
+
+       We want to include the symbol 'i' in the partial symbol table, but
+       not the symbol 'j'.  In essence, we want to skip all the dies within
+       the scope of a TAG_global_subroutine DIE.
+
        Don't attempt to add anonymous structures or unions since they have
        no name.  Anonymous enumerations however are processed, because we
        want to extract their member names (the check for a tag name is
@@ -2311,6 +2717,9 @@ NOTES
        where the actual definition occurs, rather than just a reference
        to an external.
  */
+/* *INDENT-ON* */
+
+
 
 static void
 scan_partial_symbols (thisdie, enddie, objfile)
@@ -2319,8 +2728,9 @@ scan_partial_symbols (thisdie, enddie, objfile)
      struct objfile *objfile;
 {
   char *nextdie;
+  char *temp;
   struct dieinfo di;
-  
+
   while (thisdie < enddie)
     {
       basicdieinfo (&di, thisdie, objfile);
@@ -2337,6 +2747,29 @@ scan_partial_symbols (thisdie, enddie, objfile)
            {
            case TAG_global_subroutine:
            case TAG_subroutine:
+             completedieinfo (&di, objfile);
+             if (di.at_name && (di.has_at_low_pc || di.at_location))
+               {
+                 add_partial_symbol (&di, objfile);
+                 /* If there is a sibling attribute, adjust the nextdie
+                    pointer to skip the entire scope of the subroutine.
+                    Apply some sanity checking to make sure we don't 
+                    overrun or underrun the range of remaining DIE's */
+                 if (di.at_sibling != 0)
+                   {
+                     temp = dbbase + di.at_sibling - dbroff;
+                     if ((temp < thisdie) || (temp >= enddie))
+                       {
+                         complain (&bad_die_ref, DIE_ID, DIE_NAME,
+                                   di.at_sibling);
+                       }
+                     else
+                       {
+                         nextdie = temp;
+                       }
+                   }
+               }
+             break;
            case TAG_global_variable:
            case TAG_local_variable:
              completedieinfo (&di, objfile);
@@ -2346,6 +2779,7 @@ scan_partial_symbols (thisdie, enddie, objfile)
                }
              break;
            case TAG_typedef:
+           case TAG_class_type:
            case TAG_structure_type:
            case TAG_union_type:
              completedieinfo (&di, objfile);
@@ -2356,7 +2790,11 @@ scan_partial_symbols (thisdie, enddie, objfile)
              break;
            case TAG_enumeration_type:
              completedieinfo (&di, objfile);
-             add_partial_symbol (&di, objfile);
+             if (di.at_name)
+               {
+                 add_partial_symbol (&di, objfile);
+               }
+             add_enum_psymbol (&di, objfile);
              break;
            }
        }
@@ -2366,54 +2804,53 @@ scan_partial_symbols (thisdie, enddie, objfile)
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       scan_compilation_units -- build a psymtab entry for each compilation
+   scan_compilation_units -- build a psymtab entry for each compilation
 
-DESCRIPTION
+   DESCRIPTION
 
-       This is the top level dwarf parsing routine for building partial
-       symbol tables.
-
-       It scans from the beginning of the DWARF table looking for the first
-       TAG_compile_unit DIE, and then follows the sibling chain to locate
-       each additional TAG_compile_unit DIE.
-   
-       For each TAG_compile_unit DIE it creates a partial symtab structure,
-       calls a subordinate routine to collect all the compilation unit's
-       global DIE's, file scope DIEs, typedef DIEs, etc, and then links the
-       new partial symtab structure into the partial symbol table.  It also
-       records the appropriate information in the partial symbol table entry
-       to allow the chunk of DIE's and line number table for this compilation
-       unit to be located and re-read later, to generate a complete symbol
-       table entry for the compilation unit.
-
-       Thus it effectively partitions up a chunk of DIE's for multiple
-       compilation units into smaller DIE chunks and line number tables,
-       and associates them with a partial symbol table entry.
+   This is the top level dwarf parsing routine for building partial
+   symbol tables.
 
-NOTES
+   It scans from the beginning of the DWARF table looking for the first
+   TAG_compile_unit DIE, and then follows the sibling chain to locate
+   each additional TAG_compile_unit DIE.
 
-       If any compilation unit has no line number table associated with
-       it for some reason (a missing at_stmt_list attribute, rather than
-       just one with a value of zero, which is valid) then we ensure that
-       the recorded file offset is zero so that the routine which later
-       reads line number table fragments knows that there is no fragment
-       to read.
+   For each TAG_compile_unit DIE it creates a partial symtab structure,
+   calls a subordinate routine to collect all the compilation unit's
+   global DIE's, file scope DIEs, typedef DIEs, etc, and then links the
+   new partial symtab structure into the partial symbol table.  It also
+   records the appropriate information in the partial symbol table entry
+   to allow the chunk of DIE's and line number table for this compilation
+   unit to be located and re-read later, to generate a complete symbol
+   table entry for the compilation unit.
 
-RETURNS
+   Thus it effectively partitions up a chunk of DIE's for multiple
+   compilation units into smaller DIE chunks and line number tables,
+   and associates them with a partial symbol table entry.
 
-       Returns no value.
+   NOTES
+
+   If any compilation unit has no line number table associated with
+   it for some reason (a missing at_stmt_list attribute, rather than
+   just one with a value of zero, which is valid) then we ensure that
+   the recorded file offset is zero so that the routine which later
+   reads line number table fragments knows that there is no fragment
+   to read.
+
+   RETURNS
+
+   Returns no value.
 
  */
 
 static void
-scan_compilation_units (filename, thisdie, enddie, dbfoff, lnoffset, objfile)
-     char *filename;
+scan_compilation_units (thisdie, enddie, dbfoff, lnoffset, objfile)
      char *thisdie;
      char *enddie;
-     unsigned int dbfoff;
-     unsigned int lnoffset;
+     file_ptr dbfoff;
+     file_ptr lnoffset;
      struct objfile *objfile;
 {
   char *nextdie;
@@ -2421,7 +2858,7 @@ scan_compilation_units (filename, thisdie, enddie, dbfoff, lnoffset, objfile)
   struct partial_symtab *pst;
   int culength;
   int curoff;
-  int curlnoffset;
+  file_ptr curlnoffset;
 
   while (thisdie < enddie)
     {
@@ -2437,6 +2874,7 @@ scan_compilation_units (filename, thisdie, enddie, dbfoff, lnoffset, objfile)
       else
        {
          completedieinfo (&di, objfile);
+         set_cu_language (&di);
          if (di.at_sibling != 0)
            {
              nextdie = dbbase + di.at_sibling - dbroff;
@@ -2451,55 +2889,55 @@ scan_compilation_units (filename, thisdie, enddie, dbfoff, lnoffset, objfile)
 
          /* First allocate a new partial symbol table structure */
 
-         pst = start_psymtab_common (objfile, baseaddr, di.at_name,
-                                     di.at_low_pc,
-                                     objfile -> global_psymbols.next,
-                                     objfile -> static_psymbols.next);
+         pst = start_psymtab_common (objfile, base_section_offsets,
+                                     di.at_name, di.at_low_pc,
+                                     objfile->global_psymbols.next,
+                                     objfile->static_psymbols.next);
 
-         pst -> texthigh = di.at_high_pc;
-         pst -> read_symtab_private = (char *)
-             obstack_alloc (&objfile -> psymbol_obstack,
-                            sizeof (struct dwfinfo));
+         pst->texthigh = di.at_high_pc;
+         pst->read_symtab_private = (char *)
+           obstack_alloc (&objfile->psymbol_obstack,
+                          sizeof (struct dwfinfo));
          DBFOFF (pst) = dbfoff;
          DBROFF (pst) = curoff;
          DBLENGTH (pst) = culength;
-         LNFOFF (pst)  = curlnoffset;
-         pst -> read_symtab = dwarf_psymtab_to_symtab;
+         LNFOFF (pst) = curlnoffset;
+         pst->read_symtab = dwarf_psymtab_to_symtab;
 
          /* Now look for partial symbols */
 
          scan_partial_symbols (thisdie + di.die_length, nextdie, objfile);
 
-         pst -> n_global_syms = objfile -> global_psymbols.next -
-           (objfile -> global_psymbols.list + pst -> globals_offset);
-         pst -> n_static_syms = objfile -> static_psymbols.next - 
-           (objfile -> static_psymbols.list + pst -> statics_offset);
+         pst->n_global_syms = objfile->global_psymbols.next -
+           (objfile->global_psymbols.list + pst->globals_offset);
+         pst->n_static_syms = objfile->static_psymbols.next -
+           (objfile->static_psymbols.list + pst->statics_offset);
          sort_pst_symbols (pst);
          /* If there is already a psymtab or symtab for a file of this name,
             remove it. (If there is a symtab, more drastic things also
             happen.)  This happens in VxWorks.  */
-         free_named_symtabs (pst -> filename);
+         free_named_symtabs (pst->filename);
        }
-      thisdie = nextdie;      
+      thisdie = nextdie;
     }
 }
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       new_symbol -- make a symbol table entry for a new symbol
+   new_symbol -- make a symbol table entry for a new symbol
 
-SYNOPSIS
+   SYNOPSIS
 
-       static struct symbol *new_symbol (struct dieinfo *dip,
-                                         struct objfile *objfile)
+   static struct symbol *new_symbol (struct dieinfo *dip,
+   struct objfile *objfile)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Given a pointer to a DWARF information entry, figure out if we need
-       to make a symbol table entry for it, and if so, create a new entry
-       and return a pointer to it.
+   Given a pointer to a DWARF information entry, figure out if we need
+   to make a symbol table entry for it, and if so, create a new entry
+   and return a pointer to it.
  */
 
 static struct symbol *
@@ -2508,29 +2946,41 @@ new_symbol (dip, objfile)
      struct objfile *objfile;
 {
   struct symbol *sym = NULL;
-  
-  if (dip -> at_name != NULL)
+
+  if (dip->at_name != NULL)
     {
-      sym = (struct symbol *) obstack_alloc (&objfile -> symbol_obstack,
+      sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
                                             sizeof (struct symbol));
-      (void) memset (sym, 0, sizeof (struct symbol));
-      SYMBOL_NAME (sym) = create_name (dip -> at_name, &objfile->symbol_obstack);
+      OBJSTAT (objfile, n_syms++);
+      memset (sym, 0, sizeof (struct symbol));
+      SYMBOL_NAME (sym) = create_name (dip->at_name,
+                                      &objfile->symbol_obstack);
       /* default assumptions */
       SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
       SYMBOL_CLASS (sym) = LOC_STATIC;
       SYMBOL_TYPE (sym) = decode_die_type (dip);
-      switch (dip -> die_tag)
+
+      /* If this symbol is from a C++ compilation, then attempt to cache the
+         demangled form for future reference.  This is a typical time versus
+         space tradeoff, that was decided in favor of time because it sped up
+         C++ symbol lookups by a factor of about 20. */
+
+      SYMBOL_LANGUAGE (sym) = cu_language;
+      SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack);
+      switch (dip->die_tag)
        {
        case TAG_label:
-         SYMBOL_VALUE (sym) = dip -> at_low_pc;
+         SYMBOL_VALUE_ADDRESS (sym) = dip->at_low_pc;
          SYMBOL_CLASS (sym) = LOC_LABEL;
          break;
        case TAG_global_subroutine:
        case TAG_subroutine:
-         SYMBOL_VALUE (sym) = dip -> at_low_pc;
+         SYMBOL_VALUE_ADDRESS (sym) = dip->at_low_pc;
          SYMBOL_TYPE (sym) = lookup_function_type (SYMBOL_TYPE (sym));
+         if (dip->at_prototyped)
+           TYPE_FLAGS (SYMBOL_TYPE (sym)) |= TYPE_FLAG_PROTOTYPED;
          SYMBOL_CLASS (sym) = LOC_BLOCK;
-         if (dip -> die_tag == TAG_global_subroutine)
+         if (dip->die_tag == TAG_global_subroutine)
            {
              add_symbol_to_list (sym, &global_symbols);
            }
@@ -2540,44 +2990,64 @@ new_symbol (dip, objfile)
            }
          break;
        case TAG_global_variable:
-         if (dip -> at_location != NULL)
+         if (dip->at_location != NULL)
            {
-             SYMBOL_VALUE (sym) = locval (dip -> at_location);
+             SYMBOL_VALUE_ADDRESS (sym) = locval (dip);
              add_symbol_to_list (sym, &global_symbols);
              SYMBOL_CLASS (sym) = LOC_STATIC;
              SYMBOL_VALUE (sym) += baseaddr;
            }
          break;
        case TAG_local_variable:
-         if (dip -> at_location != NULL)
+         if (dip->at_location != NULL)
            {
-             SYMBOL_VALUE (sym) = locval (dip -> at_location);
-             add_symbol_to_list (sym, list_in_scope);
-             if (isreg)
+             int loc = locval (dip);
+             if (dip->optimized_out)
+               {
+                 SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
+               }
+             else if (dip->isreg)
                {
                  SYMBOL_CLASS (sym) = LOC_REGISTER;
                }
-             else if (offreg)
+             else if (dip->offreg)
                {
-                 SYMBOL_CLASS (sym) = LOC_LOCAL;
+                 SYMBOL_CLASS (sym) = LOC_BASEREG;
+                 SYMBOL_BASEREG (sym) = dip->basereg;
                }
              else
                {
                  SYMBOL_CLASS (sym) = LOC_STATIC;
                  SYMBOL_VALUE (sym) += baseaddr;
                }
+             if (SYMBOL_CLASS (sym) == LOC_STATIC)
+               {
+                 /* LOC_STATIC address class MUST use SYMBOL_VALUE_ADDRESS,
+                    which may store to a bigger location than SYMBOL_VALUE. */
+                 SYMBOL_VALUE_ADDRESS (sym) = loc;
+               }
+             else
+               {
+                 SYMBOL_VALUE (sym) = loc;
+               }
+             add_symbol_to_list (sym, list_in_scope);
            }
          break;
        case TAG_formal_parameter:
-         if (dip -> at_location != NULL)
+         if (dip->at_location != NULL)
            {
-             SYMBOL_VALUE (sym) = locval (dip -> at_location);
+             SYMBOL_VALUE (sym) = locval (dip);
            }
          add_symbol_to_list (sym, list_in_scope);
-         if (isreg)
+         if (dip->isreg)
            {
              SYMBOL_CLASS (sym) = LOC_REGPARM;
            }
+         else if (dip->offreg)
+           {
+             SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
+             SYMBOL_BASEREG (sym) = dip->basereg;
+           }
          else
            {
              SYMBOL_CLASS (sym) = LOC_ARG;
@@ -2587,6 +3057,7 @@ new_symbol (dip, objfile)
          /* From varargs functions; gdb doesn't seem to have any interest in
             this information, so just ignore it for now. (FIXME?) */
          break;
+       case TAG_class_type:
        case TAG_structure_type:
        case TAG_union_type:
        case TAG_enumeration_type:
@@ -2611,26 +3082,72 @@ new_symbol (dip, objfile)
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       decode_mod_fund_type -- decode a modified fundamental type
+   synthesize_typedef -- make a symbol table entry for a "fake" typedef
 
-SYNOPSIS
+   SYNOPSIS
 
-       static struct type *decode_mod_fund_type (char *typedata)
+   static void synthesize_typedef (struct dieinfo *dip,
+   struct objfile *objfile,
+   struct type *type);
 
-DESCRIPTION
+   DESCRIPTION
+
+   Given a pointer to a DWARF information entry, synthesize a typedef
+   for the name in the DIE, using the specified type.
+
+   This is used for C++ class, structs, unions, and enumerations to
+   set up the tag name as a type.
+
+ */
+
+static void
+synthesize_typedef (dip, objfile, type)
+     struct dieinfo *dip;
+     struct objfile *objfile;
+     struct type *type;
+{
+  struct symbol *sym = NULL;
+
+  if (dip->at_name != NULL)
+    {
+      sym = (struct symbol *)
+       obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol));
+      OBJSTAT (objfile, n_syms++);
+      memset (sym, 0, sizeof (struct symbol));
+      SYMBOL_NAME (sym) = create_name (dip->at_name,
+                                      &objfile->symbol_obstack);
+      SYMBOL_INIT_LANGUAGE_SPECIFIC (sym, cu_language);
+      SYMBOL_TYPE (sym) = type;
+      SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+      add_symbol_to_list (sym, list_in_scope);
+    }
+}
+
+/*
+
+   LOCAL FUNCTION
+
+   decode_mod_fund_type -- decode a modified fundamental type
+
+   SYNOPSIS
+
+   static struct type *decode_mod_fund_type (char *typedata)
 
-       Decode a block of data containing a modified fundamental
-       type specification.  TYPEDATA is a pointer to the block,
-       which starts with a length containing the size of the rest
-       of the block.  At the end of the block is a fundmental type
-       code value that gives the fundamental type.  Everything
-       in between are type modifiers.
+   DESCRIPTION
 
-       We simply compute the number of modifiers and call the general
-       function decode_modified_type to do the actual work.
-*/
+   Decode a block of data containing a modified fundamental
+   type specification.  TYPEDATA is a pointer to the block,
+   which starts with a length containing the size of the rest
+   of the block.  At the end of the block is a fundmental type
+   code value that gives the fundamental type.  Everything
+   in between are type modifiers.
+
+   We simply compute the number of modifiers and call the general
+   function decode_modified_type to do the actual work.
+ */
 
 static struct type *
 decode_mod_fund_type (typedata)
@@ -2639,7 +3156,7 @@ decode_mod_fund_type (typedata)
   struct type *typep = NULL;
   unsigned short modcount;
   int nbytes;
-  
+
   /* Get the total size of the block, exclusive of the size itself */
 
   nbytes = attribute_size (AT_mod_fund_type);
@@ -2658,26 +3175,26 @@ decode_mod_fund_type (typedata)
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       decode_mod_u_d_type -- decode a modified user defined type
+   decode_mod_u_d_type -- decode a modified user defined type
 
-SYNOPSIS
+   SYNOPSIS
 
-       static struct type *decode_mod_u_d_type (char *typedata)
+   static struct type *decode_mod_u_d_type (char *typedata)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Decode a block of data containing a modified user defined
-       type specification.  TYPEDATA is a pointer to the block,
-       which consists of a two byte length, containing the size
-       of the rest of the block.  At the end of the block is a
-       four byte value that gives a reference to a user defined type.
-       Everything in between are type modifiers.
+   Decode a block of data containing a modified user defined
+   type specification.  TYPEDATA is a pointer to the block,
+   which consists of a two byte length, containing the size
+   of the rest of the block.  At the end of the block is a
+   four byte value that gives a reference to a user defined type.
+   Everything in between are type modifiers.
 
-       We simply compute the number of modifiers and call the general
-       function decode_modified_type to do the actual work.
-*/
+   We simply compute the number of modifiers and call the general
+   function decode_modified_type to do the actual work.
+ */
 
 static struct type *
 decode_mod_u_d_type (typedata)
@@ -2686,7 +3203,7 @@ decode_mod_u_d_type (typedata)
   struct type *typep = NULL;
   unsigned short modcount;
   int nbytes;
-  
+
   /* Get the total size of the block, exclusive of the size itself */
 
   nbytes = attribute_size (AT_mod_u_d_type);
@@ -2705,56 +3222,56 @@ decode_mod_u_d_type (typedata)
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       decode_modified_type -- decode modified user or fundamental type
+   decode_modified_type -- decode modified user or fundamental type
 
-SYNOPSIS
+   SYNOPSIS
 
-       static struct type *decode_modified_type (unsigned char *modifiers,
-           unsigned short modcount, int mtype)
+   static struct type *decode_modified_type (char *modifiers,
+   unsigned short modcount, int mtype)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Decode a modified type, either a modified fundamental type or
-       a modified user defined type.  MODIFIERS is a pointer to the
-       block of bytes that define MODCOUNT modifiers.  Immediately
-       following the last modifier is a short containing the fundamental
-       type or a long containing the reference to the user defined
-       type.  Which one is determined by MTYPE, which is either
-       AT_mod_fund_type or AT_mod_u_d_type to indicate what modified
-       type we are generating.
-
-       We call ourself recursively to generate each modified type,`
-       until MODCOUNT reaches zero, at which point we have consumed
-       all the modifiers and generate either the fundamental type or
-       user defined type.  When the recursion unwinds, each modifier
-       is applied in turn to generate the full modified type.
+   Decode a modified type, either a modified fundamental type or
+   a modified user defined type.  MODIFIERS is a pointer to the
+   block of bytes that define MODCOUNT modifiers.  Immediately
+   following the last modifier is a short containing the fundamental
+   type or a long containing the reference to the user defined
+   type.  Which one is determined by MTYPE, which is either
+   AT_mod_fund_type or AT_mod_u_d_type to indicate what modified
+   type we are generating.
 
-NOTES
+   We call ourself recursively to generate each modified type,`
+   until MODCOUNT reaches zero, at which point we have consumed
+   all the modifiers and generate either the fundamental type or
+   user defined type.  When the recursion unwinds, each modifier
+   is applied in turn to generate the full modified type.
 
-       If we find a modifier that we don't recognize, and it is not one
-       of those reserved for application specific use, then we issue a
-       warning and simply ignore the modifier.
+   NOTES
 
-BUGS
+   If we find a modifier that we don't recognize, and it is not one
+   of those reserved for application specific use, then we issue a
+   warning and simply ignore the modifier.
 
-       We currently ignore MOD_const and MOD_volatile.  (FIXME)
+   BUGS
+
+   We currently ignore MOD_const and MOD_volatile.  (FIXME)
 
  */
 
 static struct type *
 decode_modified_type (modifiers, modcount, mtype)
-     unsigned char *modifiers;
+     char *modifiers;
      unsigned int modcount;
      int mtype;
 {
   struct type *typep = NULL;
   unsigned short fundtype;
   DIE_REF die_ref;
-  unsigned char modifier;
+  char modifier;
   int nbytes;
-  
+
   if (modcount == 0)
     {
       switch (mtype)
@@ -2775,8 +3292,8 @@ decode_modified_type (modifiers, modcount, mtype)
            }
          break;
        default:
-         SQUAWK (("botched modified type decoding (mtype 0x%x)", mtype));
-         typep = lookup_fundamental_type (current_objfile, FT_INTEGER);
+         complain (&botched_modified_type, DIE_ID, DIE_NAME, mtype);
+         typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
          break;
        }
     }
@@ -2786,24 +3303,25 @@ decode_modified_type (modifiers, modcount, mtype)
       typep = decode_modified_type (modifiers, --modcount, mtype);
       switch (modifier)
        {
-         case MOD_pointer_to:
-           typep = lookup_pointer_type (typep);
-           break;
-         case MOD_reference_to:
-           typep = lookup_reference_type (typep);
-           break;
-         case MOD_const:
-           SQUAWK (("type modifier 'const' ignored"));         /* FIXME */
-           break;
-         case MOD_volatile:
-           SQUAWK (("type modifier 'volatile' ignored"));      /* FIXME */
-           break;
-         default:
-           if (!(MOD_lo_user <= modifier && modifier <= MOD_hi_user))
-             {
-               SQUAWK (("unknown type modifier %u", modifier));
-             }
-           break;
+       case MOD_pointer_to:
+         typep = lookup_pointer_type (typep);
+         break;
+       case MOD_reference_to:
+         typep = lookup_reference_type (typep);
+         break;
+       case MOD_const:
+         complain (&const_ignored, DIE_ID, DIE_NAME);  /* FIXME */
+         break;
+       case MOD_volatile:
+         complain (&volatile_ignored, DIE_ID, DIE_NAME);       /* FIXME */
+         break;
+       default:
+         if (!(MOD_lo_user <= (unsigned char) modifier
+               && (unsigned char) modifier <= MOD_hi_user))
+           {
+             complain (&unknown_type_modifier, DIE_ID, DIE_NAME, modifier);
+           }
+         break;
        }
     }
   return (typep);
@@ -2811,153 +3329,158 @@ decode_modified_type (modifiers, modcount, mtype)
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       decode_fund_type -- translate basic DWARF type to gdb base type
+   decode_fund_type -- translate basic DWARF type to gdb base type
 
-DESCRIPTION
+   DESCRIPTION
 
-       Given an integer that is one of the fundamental DWARF types,
-       translate it to one of the basic internal gdb types and return
-       a pointer to the appropriate gdb type (a "struct type *").
+   Given an integer that is one of the fundamental DWARF types,
+   translate it to one of the basic internal gdb types and return
+   a pointer to the appropriate gdb type (a "struct type *").
 
-NOTES
+   NOTES
 
-       If we encounter a fundamental type that we are unprepared to
-       deal with, and it is not in the range of those types defined
-       as application specific types, then we issue a warning and
-       treat the type as an "int".
-*/
+   For robustness, if we are asked to translate a fundamental
+   type that we are unprepared to deal with, we return int so
+   callers can always depend upon a valid type being returned,
+   and so gdb may at least do something reasonable by default.
+   If the type is not in the range of those types defined as
+   application specific types, we also issue a warning.
+ */
 
 static struct type *
 decode_fund_type (fundtype)
      unsigned int fundtype;
 {
   struct type *typep = NULL;
-  
+
   switch (fundtype)
     {
 
     case FT_void:
-      typep = lookup_fundamental_type (current_objfile, FT_VOID);
+      typep = dwarf_fundamental_type (current_objfile, FT_VOID);
       break;
-    
+
     case FT_boolean:           /* Was FT_set in AT&T version */
-      typep = lookup_fundamental_type (current_objfile, FT_BOOLEAN);
+      typep = dwarf_fundamental_type (current_objfile, FT_BOOLEAN);
       break;
 
     case FT_pointer:           /* (void *) */
-      typep = lookup_fundamental_type (current_objfile, FT_VOID);
+      typep = dwarf_fundamental_type (current_objfile, FT_VOID);
       typep = lookup_pointer_type (typep);
       break;
-    
+
     case FT_char:
-      typep = lookup_fundamental_type (current_objfile, FT_CHAR);
+      typep = dwarf_fundamental_type (current_objfile, FT_CHAR);
       break;
-    
+
     case FT_signed_char:
-      typep = lookup_fundamental_type (current_objfile, FT_SIGNED_CHAR);
+      typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_CHAR);
       break;
 
     case FT_unsigned_char:
-      typep = lookup_fundamental_type (current_objfile, FT_UNSIGNED_CHAR);
+      typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_CHAR);
       break;
-    
+
     case FT_short:
-      typep = lookup_fundamental_type (current_objfile, FT_SHORT);
+      typep = dwarf_fundamental_type (current_objfile, FT_SHORT);
       break;
 
     case FT_signed_short:
-      typep = lookup_fundamental_type (current_objfile, FT_SIGNED_SHORT);
+      typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_SHORT);
       break;
-    
+
     case FT_unsigned_short:
-      typep = lookup_fundamental_type (current_objfile, FT_UNSIGNED_SHORT);
+      typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_SHORT);
       break;
-    
+
     case FT_integer:
-      typep = lookup_fundamental_type (current_objfile, FT_INTEGER);
+      typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
       break;
 
     case FT_signed_integer:
-      typep = lookup_fundamental_type (current_objfile, FT_SIGNED_INTEGER);
+      typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_INTEGER);
       break;
-    
+
     case FT_unsigned_integer:
-      typep = lookup_fundamental_type (current_objfile, FT_UNSIGNED_INTEGER);
+      typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_INTEGER);
       break;
-    
+
     case FT_long:
-      typep = lookup_fundamental_type (current_objfile, FT_LONG);
+      typep = dwarf_fundamental_type (current_objfile, FT_LONG);
       break;
 
     case FT_signed_long:
-      typep = lookup_fundamental_type (current_objfile, FT_SIGNED_LONG);
+      typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_LONG);
       break;
-    
+
     case FT_unsigned_long:
-      typep = lookup_fundamental_type (current_objfile, FT_UNSIGNED_LONG);
+      typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_LONG);
       break;
-    
+
     case FT_long_long:
-      typep = lookup_fundamental_type (current_objfile, FT_LONG_LONG);
+      typep = dwarf_fundamental_type (current_objfile, FT_LONG_LONG);
       break;
 
     case FT_signed_long_long:
-      typep = lookup_fundamental_type (current_objfile, FT_SIGNED_LONG_LONG);
+      typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_LONG_LONG);
       break;
 
     case FT_unsigned_long_long:
-      typep = lookup_fundamental_type (current_objfile, FT_UNSIGNED_LONG_LONG);
+      typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_LONG_LONG);
       break;
 
     case FT_float:
-      typep = lookup_fundamental_type (current_objfile, FT_FLOAT);
+      typep = dwarf_fundamental_type (current_objfile, FT_FLOAT);
       break;
-    
+
     case FT_dbl_prec_float:
-      typep = lookup_fundamental_type (current_objfile, FT_DBL_PREC_FLOAT);
+      typep = dwarf_fundamental_type (current_objfile, FT_DBL_PREC_FLOAT);
       break;
-    
+
     case FT_ext_prec_float:
-      typep = lookup_fundamental_type (current_objfile, FT_EXT_PREC_FLOAT);
+      typep = dwarf_fundamental_type (current_objfile, FT_EXT_PREC_FLOAT);
       break;
-    
+
     case FT_complex:
-      typep = lookup_fundamental_type (current_objfile, FT_COMPLEX);
+      typep = dwarf_fundamental_type (current_objfile, FT_COMPLEX);
       break;
-    
+
     case FT_dbl_prec_complex:
-      typep = lookup_fundamental_type (current_objfile, FT_DBL_PREC_COMPLEX);
+      typep = dwarf_fundamental_type (current_objfile, FT_DBL_PREC_COMPLEX);
       break;
-    
+
     case FT_ext_prec_complex:
-      typep = lookup_fundamental_type (current_objfile, FT_EXT_PREC_COMPLEX);
+      typep = dwarf_fundamental_type (current_objfile, FT_EXT_PREC_COMPLEX);
       break;
-    
+
     }
 
-  if ((typep == NULL) && !(FT_lo_user <= fundtype && fundtype <= FT_hi_user))
+  if (typep == NULL)
     {
-      SQUAWK (("unexpected fundamental type 0x%x", fundtype));
-      typep = lookup_fundamental_type (current_objfile, FT_VOID);
+      typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+      if (!(FT_lo_user <= fundtype && fundtype <= FT_hi_user))
+       {
+         complain (&unexpected_fund_type, DIE_ID, DIE_NAME, fundtype);
+       }
     }
-    
+
   return (typep);
 }
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       create_name -- allocate a fresh copy of a string on an obstack
+   create_name -- allocate a fresh copy of a string on an obstack
 
-DESCRIPTION
+   DESCRIPTION
 
-       Given a pointer to a string and a pointer to an obstack, allocates
-       a fresh copy of the string on the specified obstack.
+   Given a pointer to a string and a pointer to an obstack, allocates
+   a fresh copy of the string on the specified obstack.
 
-*/
+ */
 
 static char *
 create_name (name, obstackp)
@@ -2969,56 +3492,62 @@ create_name (name, obstackp)
 
   length = strlen (name) + 1;
   newname = (char *) obstack_alloc (obstackp, length);
-  (void) strcpy (newname, name);
+  strcpy (newname, name);
   return (newname);
 }
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       basicdieinfo -- extract the minimal die info from raw die data
+   basicdieinfo -- extract the minimal die info from raw die data
 
-SYNOPSIS
+   SYNOPSIS
 
-       void basicdieinfo (char *diep, struct dieinfo *dip,
-                          struct objfile *objfile)
+   void basicdieinfo (char *diep, struct dieinfo *dip,
+   struct objfile *objfile)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Given a pointer to raw DIE data, and a pointer to an instance of a
-       die info structure, this function extracts the basic information
-       from the DIE data required to continue processing this DIE, along
-       with some bookkeeping information about the DIE.
+   Given a pointer to raw DIE data, and a pointer to an instance of a
+   die info structure, this function extracts the basic information
+   from the DIE data required to continue processing this DIE, along
+   with some bookkeeping information about the DIE.
 
-       The information we absolutely must have includes the DIE tag,
-       and the DIE length.  If we need the sibling reference, then we
-       will have to call completedieinfo() to process all the remaining
-       DIE information.
+   The information we absolutely must have includes the DIE tag,
+   and the DIE length.  If we need the sibling reference, then we
+   will have to call completedieinfo() to process all the remaining
+   DIE information.
 
-       Note that since there is no guarantee that the data is properly
-       aligned in memory for the type of access required (indirection
-       through anything other than a char pointer), and there is no
-       guarantee that it is in the same byte order as the gdb host,
-       we call a function which deals with both alignment and byte
-       swapping issues.  Possibly inefficient, but quite portable.
+   Note that since there is no guarantee that the data is properly
+   aligned in memory for the type of access required (indirection
+   through anything other than a char pointer), and there is no
+   guarantee that it is in the same byte order as the gdb host,
+   we call a function which deals with both alignment and byte
+   swapping issues.  Possibly inefficient, but quite portable.
 
-       We also take care of some other basic things at this point, such
-       as ensuring that the instance of the die info structure starts
-       out completely zero'd and that curdie is initialized for use
-       in error reporting if we have a problem with the current die.
+   We also take care of some other basic things at this point, such
+   as ensuring that the instance of the die info structure starts
+   out completely zero'd and that curdie is initialized for use
+   in error reporting if we have a problem with the current die.
 
-NOTES
+   NOTES
 
-       All DIE's must have at least a valid length, thus the minimum
-       DIE size is SIZEOF_DIE_LENGTH.  In order to have a valid tag, the
-       DIE size must be at least SIZEOF_DIE_TAG larger, otherwise they
-       are forced to be TAG_padding DIES.
+   All DIE's must have at least a valid length, thus the minimum
+   DIE size is SIZEOF_DIE_LENGTH.  In order to have a valid tag, the
+   DIE size must be at least SIZEOF_DIE_TAG larger, otherwise they
+   are forced to be TAG_padding DIES.
 
-       Padding DIES must be at least SIZEOF_DIE_LENGTH in length, implying
-       that if a padding DIE is used for alignment and the amount needed is
-       less than SIZEOF_DIE_LENGTH, then the padding DIE has to be big
-       enough to align to the next alignment boundry.
+   Padding DIES must be at least SIZEOF_DIE_LENGTH in length, implying
+   that if a padding DIE is used for alignment and the amount needed is
+   less than SIZEOF_DIE_LENGTH, then the padding DIE has to be big
+   enough to align to the next alignment boundry.
+
+   We do some basic sanity checking here, such as verifying that the
+   length of the die would not cause it to overrun the recorded end of
+   the buffer holding the DIE info.  If we find a DIE that is either
+   too small or too large, we force it's length to zero which should
+   cause the caller to take appropriate action.
  */
 
 static void
@@ -3028,56 +3557,58 @@ basicdieinfo (dip, diep, objfile)
      struct objfile *objfile;
 {
   curdie = dip;
-  (void) memset (dip, 0, sizeof (struct dieinfo));
-  dip -> die = diep;
-  dip -> die_ref = dbroff + (diep - dbbase);
-  dip -> die_length = target_to_host (diep, SIZEOF_DIE_LENGTH, GET_UNSIGNED,
-                                     objfile);
-  if (dip -> die_length < SIZEOF_DIE_LENGTH)
+  memset (dip, 0, sizeof (struct dieinfo));
+  dip->die = diep;
+  dip->die_ref = dbroff + (diep - dbbase);
+  dip->die_length = target_to_host (diep, SIZEOF_DIE_LENGTH, GET_UNSIGNED,
+                                   objfile);
+  if ((dip->die_length < SIZEOF_DIE_LENGTH) ||
+      ((diep + dip->die_length) > (dbbase + dbsize)))
     {
-      dwarfwarn ("malformed DIE, bad length (%d bytes)", dip -> die_length);
+      complain (&malformed_die, DIE_ID, DIE_NAME, dip->die_length);
+      dip->die_length = 0;
     }
-  else if (dip -> die_length < (SIZEOF_DIE_LENGTH + SIZEOF_DIE_TAG))
+  else if (dip->die_length < (SIZEOF_DIE_LENGTH + SIZEOF_DIE_TAG))
     {
-      dip -> die_tag = TAG_padding;
+      dip->die_tag = TAG_padding;
     }
   else
     {
       diep += SIZEOF_DIE_LENGTH;
-      dip -> die_tag = target_to_host (diep, SIZEOF_DIE_TAG, GET_UNSIGNED,
-                                      objfile);
+      dip->die_tag = target_to_host (diep, SIZEOF_DIE_TAG, GET_UNSIGNED,
+                                    objfile);
     }
 }
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       completedieinfo -- finish reading the information for a given DIE
+   completedieinfo -- finish reading the information for a given DIE
 
-SYNOPSIS
+   SYNOPSIS
 
-       void completedieinfo (struct dieinfo *dip, struct objfile *objfile)
+   void completedieinfo (struct dieinfo *dip, struct objfile *objfile)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Given a pointer to an already partially initialized die info structure,
-       scan the raw DIE data and finish filling in the die info structure
-       from the various attributes found.
-   
-       Note that since there is no guarantee that the data is properly
-       aligned in memory for the type of access required (indirection
-       through anything other than a char pointer), and there is no
-       guarantee that it is in the same byte order as the gdb host,
-       we call a function which deals with both alignment and byte
-       swapping issues.  Possibly inefficient, but quite portable.
+   Given a pointer to an already partially initialized die info structure,
+   scan the raw DIE data and finish filling in the die info structure
+   from the various attributes found.
 
-NOTES
+   Note that since there is no guarantee that the data is properly
+   aligned in memory for the type of access required (indirection
+   through anything other than a char pointer), and there is no
+   guarantee that it is in the same byte order as the gdb host,
+   we call a function which deals with both alignment and byte
+   swapping issues.  Possibly inefficient, but quite portable.
 
-       Each time we are called, we increment the diecount variable, which
-       keeps an approximate count of the number of dies processed for
-       each compilation unit.  This information is presented to the user
-       if the info_verbose flag is set.
+   NOTES
+
+   Each time we are called, we increment the diecount variable, which
+   keeps an approximate count of the number of dies processed for
+   each compilation unit.  This information is presented to the user
+   if the info_verbose flag is set.
 
  */
 
@@ -3091,10 +3622,10 @@ completedieinfo (dip, objfile)
   unsigned short attr;         /* Current attribute being scanned */
   unsigned short form;         /* Form of the attribute */
   int nbytes;                  /* Size of next field to read */
-  
+
   diecount++;
-  diep = dip -> die;
-  end = diep + dip -> die_length;
+  diep = dip->die;
+  end = diep + dip->die_length;
   diep += SIZEOF_DIE_LENGTH + SIZEOF_DIE_TAG;
   while (diep < end)
     {
@@ -3102,129 +3633,128 @@ completedieinfo (dip, objfile)
       diep += SIZEOF_ATTRIBUTE;
       if ((nbytes = attribute_size (attr)) == -1)
        {
-         SQUAWK (("unknown attribute length, skipped remaining attributes"));;
+         complain (&unknown_attribute_length, DIE_ID, DIE_NAME);
          diep = end;
          continue;
        }
       switch (attr)
        {
        case AT_fund_type:
-         dip -> at_fund_type = target_to_host (diep, nbytes, GET_UNSIGNED,
-                                               objfile);
+         dip->at_fund_type = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                             objfile);
          break;
        case AT_ordering:
-         dip -> at_ordering = target_to_host (diep, nbytes, GET_UNSIGNED,
-                                              objfile);
+         dip->at_ordering = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                            objfile);
          break;
        case AT_bit_offset:
-         dip -> at_bit_offset = target_to_host (diep, nbytes, GET_UNSIGNED,
-                                                objfile);
-         break;
-       case AT_visibility:
-         dip -> at_visibility = target_to_host (diep, nbytes, GET_UNSIGNED,
-                                                objfile);
+         dip->at_bit_offset = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                              objfile);
          break;
        case AT_sibling:
-         dip -> at_sibling = target_to_host (diep, nbytes, GET_UNSIGNED,
-                                             objfile);
+         dip->at_sibling = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                           objfile);
          break;
        case AT_stmt_list:
-         dip -> at_stmt_list = target_to_host (diep, nbytes, GET_UNSIGNED,
-                                               objfile);
-         dip -> has_at_stmt_list = 1;
+         dip->at_stmt_list = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                             objfile);
+         dip->has_at_stmt_list = 1;
          break;
        case AT_low_pc:
-         dip -> at_low_pc = target_to_host (diep, nbytes, GET_UNSIGNED,
-                                            objfile);
-         dip -> at_low_pc += baseaddr;
-         dip -> has_at_low_pc = 1;
+         dip->at_low_pc = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                          objfile);
+         dip->at_low_pc += baseaddr;
+         dip->has_at_low_pc = 1;
          break;
        case AT_high_pc:
-         dip -> at_high_pc = target_to_host (diep, nbytes, GET_UNSIGNED,
-                                             objfile);
-         dip -> at_high_pc += baseaddr;
+         dip->at_high_pc = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                           objfile);
+         dip->at_high_pc += baseaddr;
          break;
        case AT_language:
-         dip -> at_language = target_to_host (diep, nbytes, GET_UNSIGNED,
-                                              objfile);
+         dip->at_language = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                            objfile);
          break;
        case AT_user_def_type:
-         dip -> at_user_def_type = target_to_host (diep, nbytes,
-                                                   GET_UNSIGNED, objfile);
+         dip->at_user_def_type = target_to_host (diep, nbytes,
+                                                 GET_UNSIGNED, objfile);
          break;
        case AT_byte_size:
-         dip -> at_byte_size = target_to_host (diep, nbytes, GET_UNSIGNED,
-                                               objfile);
+         dip->at_byte_size = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                             objfile);
+         dip->has_at_byte_size = 1;
          break;
        case AT_bit_size:
-         dip -> at_bit_size = target_to_host (diep, nbytes, GET_UNSIGNED,
-                                              objfile);
+         dip->at_bit_size = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                            objfile);
          break;
        case AT_member:
-         dip -> at_member = target_to_host (diep, nbytes, GET_UNSIGNED,
-                                            objfile);
+         dip->at_member = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                          objfile);
          break;
        case AT_discr:
-         dip -> at_discr = target_to_host (diep, nbytes, GET_UNSIGNED,
-                                           objfile);
-         break;
-       case AT_import:
-         dip -> at_import = target_to_host (diep, nbytes, GET_UNSIGNED,
-                                            objfile);
+         dip->at_discr = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                         objfile);
          break;
        case AT_location:
-         dip -> at_location = diep;
+         dip->at_location = diep;
          break;
        case AT_mod_fund_type:
-         dip -> at_mod_fund_type = diep;
+         dip->at_mod_fund_type = diep;
          break;
        case AT_subscr_data:
-         dip -> at_subscr_data = diep;
+         dip->at_subscr_data = diep;
          break;
        case AT_mod_u_d_type:
-         dip -> at_mod_u_d_type = diep;
+         dip->at_mod_u_d_type = diep;
          break;
        case AT_element_list:
-         dip -> at_element_list = diep;
-         dip -> short_element_list = 0;
+         dip->at_element_list = diep;
+         dip->short_element_list = 0;
          break;
        case AT_short_element_list:
-         dip -> at_element_list = diep;
-         dip -> short_element_list = 1;
+         dip->at_element_list = diep;
+         dip->short_element_list = 1;
          break;
        case AT_discr_value:
-         dip -> at_discr_value = diep;
+         dip->at_discr_value = diep;
          break;
        case AT_string_length:
-         dip -> at_string_length = diep;
+         dip->at_string_length = diep;
          break;
        case AT_name:
-         dip -> at_name = diep;
+         dip->at_name = diep;
          break;
        case AT_comp_dir:
-         dip -> at_comp_dir = diep;
+         /* For now, ignore any "hostname:" portion, since gdb doesn't
+            know how to deal with it.  (FIXME). */
+         dip->at_comp_dir = strrchr (diep, ':');
+         if (dip->at_comp_dir != NULL)
+           {
+             dip->at_comp_dir++;
+           }
+         else
+           {
+             dip->at_comp_dir = diep;
+           }
          break;
        case AT_producer:
-         dip -> at_producer = diep;
-         break;
-       case AT_frame_base:
-         dip -> at_frame_base = target_to_host (diep, nbytes, GET_UNSIGNED,
-                                                objfile);
+         dip->at_producer = diep;
          break;
        case AT_start_scope:
-         dip -> at_start_scope = target_to_host (diep, nbytes, GET_UNSIGNED,
-                                                 objfile);
+         dip->at_start_scope = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                               objfile);
          break;
        case AT_stride_size:
-         dip -> at_stride_size = target_to_host (diep, nbytes, GET_UNSIGNED,
-                                                 objfile);
+         dip->at_stride_size = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                               objfile);
          break;
        case AT_src_info:
-         dip -> at_src_info = target_to_host (diep, nbytes, GET_UNSIGNED,
-                                              objfile);
+         dip->at_src_info = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                            objfile);
          break;
        case AT_prototyped:
-         dip -> at_prototyped = diep;
+         dip->at_prototyped = diep;
          break;
        default:
          /* Found an attribute that we are unprepared to handle.  However
@@ -3260,8 +3790,7 @@ completedieinfo (dip, objfile)
          diep += strlen (diep) + 1;
          break;
        default:
-         SQUAWK (("unknown attribute form (0x%x)", form));
-         SQUAWK (("unknown attribute length, skipped remaining attributes"));;
+         complain (&unknown_attribute_form, DIE_ID, DIE_NAME, form);
          diep = end;
          break;
        }
@@ -3270,79 +3799,81 @@ completedieinfo (dip, objfile)
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       target_to_host -- swap in target data to host
+   target_to_host -- swap in target data to host
 
-SYNOPSIS
+   SYNOPSIS
 
-       target_to_host (char *from, int nbytes, int signextend,
-                       struct objfile *objfile)
+   target_to_host (char *from, int nbytes, int signextend,
+   struct objfile *objfile)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Given pointer to data in target format in FROM, a byte count for
-       the size of the data in NBYTES, a flag indicating whether or not
-       the data is signed in SIGNEXTEND, and a pointer to the current
-       objfile in OBJFILE, convert the data to host format and return
-       the converted value.
+   Given pointer to data in target format in FROM, a byte count for
+   the size of the data in NBYTES, a flag indicating whether or not
+   the data is signed in SIGNEXTEND, and a pointer to the current
+   objfile in OBJFILE, convert the data to host format and return
+   the converted value.
 
-NOTES
+   NOTES
 
-       FIXME:  If we read data that is known to be signed, and expect to
-       use it as signed data, then we need to explicitly sign extend the
-       result until the bfd library is able to do this for us.
+   FIXME:  If we read data that is known to be signed, and expect to
+   use it as signed data, then we need to explicitly sign extend the
+   result until the bfd library is able to do this for us.
+
+   FIXME: Would a 32 bit target ever need an 8 byte result?
 
  */
 
-static unsigned long
+static CORE_ADDR
 target_to_host (from, nbytes, signextend, objfile)
      char *from;
      int nbytes;
      int signextend;           /* FIXME:  Unused */
      struct objfile *objfile;
 {
-  unsigned long rtnval;
+  CORE_ADDR rtnval;
 
   switch (nbytes)
     {
-      case 8:
-        rtnval = bfd_get_64 (objfile -> obfd, (bfd_byte *) from);
-       break;
-      case 4:
-       rtnval = bfd_get_32 (objfile -> obfd, (bfd_byte *) from);
-       break;
-      case 2:
-       rtnval = bfd_get_16 (objfile -> obfd, (bfd_byte *) from);
-       break;
-      case 1:
-       rtnval = bfd_get_8 (objfile -> obfd, (bfd_byte *) from);
-       break;
-      default:
-       dwarfwarn ("no bfd support for %d byte data object", nbytes);
-       rtnval = 0;
-       break;
+    case 8:
+      rtnval = bfd_get_64 (objfile->obfd, (bfd_byte *) from);
+      break;
+    case 4:
+      rtnval = bfd_get_32 (objfile->obfd, (bfd_byte *) from);
+      break;
+    case 2:
+      rtnval = bfd_get_16 (objfile->obfd, (bfd_byte *) from);
+      break;
+    case 1:
+      rtnval = bfd_get_8 (objfile->obfd, (bfd_byte *) from);
+      break;
+    default:
+      complain (&no_bfd_get_N, DIE_ID, DIE_NAME, nbytes);
+      rtnval = 0;
+      break;
     }
   return (rtnval);
 }
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       attribute_size -- compute size of data for a DWARF attribute
+   attribute_size -- compute size of data for a DWARF attribute
 
-SYNOPSIS
+   SYNOPSIS
 
-       static int attribute_size (unsigned int attr)
+   static int attribute_size (unsigned int attr)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Given a DWARF attribute in ATTR, compute the size of the first
-       piece of data associated with this attribute and return that
-       size.
+   Given a DWARF attribute in ATTR, compute the size of the first
+   piece of data associated with this attribute and return that
+   size.
 
-       Returns -1 for unrecognized attributes.
+   Returns -1 for unrecognized attributes.
 
  */
 
@@ -3356,28 +3887,28 @@ attribute_size (attr)
   form = FORM_FROM_ATTR (attr);
   switch (form)
     {
-      case FORM_STRING:                /* A variable length field is next */
-        nbytes = 0;
-       break;
-      case FORM_DATA2:         /* Next 2 byte field is the data itself */
-      case FORM_BLOCK2:                /* Next 2 byte field is a block length */
-       nbytes = 2;
-       break;
-      case FORM_DATA4:         /* Next 4 byte field is the data itself */
-      case FORM_BLOCK4:                /* Next 4 byte field is a block length */
-      case FORM_REF:           /* Next 4 byte field is a DIE offset */
-       nbytes = 4;
-       break;
-      case FORM_DATA8:         /* Next 8 byte field is the data itself */
-       nbytes = 8;
-       break;
-      case FORM_ADDR:          /* Next field size is target sizeof(void *) */
-       nbytes = TARGET_FT_POINTER_SIZE (objfile);
-       break;
-      default:
-       SQUAWK (("unknown attribute form (0x%x)", form));
-       nbytes = -1;
-       break;
-      }
+    case FORM_STRING:          /* A variable length field is next */
+      nbytes = 0;
+      break;
+    case FORM_DATA2:           /* Next 2 byte field is the data itself */
+    case FORM_BLOCK2:          /* Next 2 byte field is a block length */
+      nbytes = 2;
+      break;
+    case FORM_DATA4:           /* Next 4 byte field is the data itself */
+    case FORM_BLOCK4:          /* Next 4 byte field is a block length */
+    case FORM_REF:             /* Next 4 byte field is a DIE offset */
+      nbytes = 4;
+      break;
+    case FORM_DATA8:           /* Next 8 byte field is the data itself */
+      nbytes = 8;
+      break;
+    case FORM_ADDR:            /* Next field size is target sizeof(void *) */
+      nbytes = TARGET_FT_POINTER_SIZE (objfile);
+      break;
+    default:
+      complain (&unknown_attribute_form, DIE_ID, DIE_NAME, form);
+      nbytes = -1;
+      break;
+    }
   return (nbytes);
 }
This page took 0.093805 seconds and 4 git commands to generate.