* parse.c (write_dollar_variable): New function.
[deliverable/binutils-gdb.git] / gdb / dwarfread.c
index 6d635439fff11889592fbc5ae5ea32cde5e33703..ea401963057db98c697cb495fb31068d7c6f79d7 100644 (file)
@@ -1,5 +1,5 @@
 /* DWARF debugging format support for GDB.
-   Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+   Copyright (C) 1991, 1992, 1993, 1994, 1995 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.
 
@@ -17,14 +17,12 @@ 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.  */
+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: Add generation of dependencies list to partial symtab code.
+FIXME: Do we need to generate dependencies in partial symtabs?
+(Perhaps we don't need to).
 
 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
@@ -41,22 +39,20 @@ other things to work on, if you get bored. :-)
 */
 
 #include "defs.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"
 
-#include <varargs.h>
 #include <fcntl.h>
-#include <string.h>
-#include <sys/types.h>
+#include "gdb_string.h"
+
 #ifndef        NO_SYS_FILE
 #include <sys/file.h>
 #endif
@@ -66,15 +62,117 @@ other things to work on, if you get bored. :-)
 #define L_SET 0
 #endif
 
-#ifdef MAINTENANCE     /* Define to 1 to compile in some maintenance stuff */
-#define SQUAWK(stuff) dwarfwarn stuff
-#else
-#define SQUAWK(stuff)
-#endif
+/* Some macros to provide DIE info for complaints. */
 
-#ifndef R_FP           /* FIXME */
-#define R_FP 14                /* Kludge to get frame pointer register number */
-#endif
+#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
+};
 
 typedef unsigned int DIE_REF;  /* Reference to a DIE */
 
@@ -90,18 +188,14 @@ typedef unsigned int DIE_REF;      /* Reference to a DIE */
 #define LCC_PRODUCER "NCR C/C++"
 #endif
 
-#ifndef CFRONT_PRODUCER
-#define CFRONT_PRODUCER "CFRONT "      /* A wild a** guess... */
-#endif
-
-/* start-sanitize-chill */
 #ifndef CHILL_PRODUCER
 #define CHILL_PRODUCER "GNU Chill "
 #endif
-/* end-sanitize-chill */
 
-#define STREQ(a,b)             (strcmp(a,b)==0)
-#define STREQN(a,b,n)          (strncmp(a,b,n)==0)
+/* 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
@@ -206,8 +300,8 @@ struct dieinfo {
   unsigned long                at_bit_size;
   BLOCK *              at_element_list;
   unsigned long                at_stmt_list;
-  unsigned long                at_low_pc;
-  unsigned long                at_high_pc;
+  CORE_ADDR            at_low_pc;
+  CORE_ADDR            at_high_pc;
   unsigned long                at_language;
   unsigned long                at_member;
   unsigned long                at_discr;
@@ -233,47 +327,45 @@ 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 */
 static int isreg;      /* Kludge to identify register variables */
-static int offreg;     /* Kludge to identify basereg references */
+static int optimized_out;  /* Kludge to identify optimized out variables */
+/* Kludge to identify basereg references.  Nonzero if we have an offset
+   relative to a basereg.  */
+static int offreg;
+/* Which base register is it relative to?  */
+static int basereg;
 
 /* This value is added to each symbol value.  FIXME:  Generalize to 
-   the section_offsets structure used by dbxread.  */
+   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 */
 
 /* 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;
 
-/* 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.
- */
+/* We put a pointer to this structure in the read_symtab_private field
+   of the psymtab.  */
 
 struct dwfinfo {
-  file_ptr 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 */
-  file_ptr lnfoff;     /* Absolute file offset to line table fragment */
+  /* 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)
@@ -352,7 +444,7 @@ static const struct language_defn *cu_language_defn;
 static int
 attribute_size PARAMS ((unsigned int));
 
-static unsigned long
+static CORE_ADDR
 target_to_host PARAMS ((char *, int, int, struct objfile *));
 
 static void
@@ -371,9 +463,6 @@ 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 *));
 
@@ -384,9 +473,6 @@ scan_compilation_units PARAMS ((char *, char *, file_ptr,
 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 *));
 
@@ -399,7 +485,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
@@ -421,6 +507,9 @@ dwarf_read_array_type PARAMS ((struct dieinfo *));
 static void
 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 *));
 
@@ -470,10 +559,6 @@ synthesize_typedef PARAMS ((struct dieinfo *, struct objfile *,
 static int
 locval PARAMS ((char *));
 
-static void
-record_minimal_symbol PARAMS ((char *, CORE_ADDR, enum minimal_symbol_type,
-                              struct objfile *));
-
 static void
 set_cu_language PARAMS ((struct dieinfo *));
 
@@ -573,11 +658,9 @@ set_cu_language (dip)
       case LANG_C_PLUS_PLUS:
        cu_language = language_cplus;
        break;
-      /* start-sanitize-chill */
       case LANG_CHILL:
        cu_language = language_chill;
        break;
-      /* end-sanitize-chill */
       case LANG_MODULA2:
        cu_language = language_m2;
        break;
@@ -587,9 +670,13 @@ set_cu_language (dip)
       case LANG_FORTRAN77:
       case LANG_FORTRAN90:
       case LANG_PASCAL83:
-      default:
+       /* 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);
 }
@@ -677,88 +764,6 @@ dwarf_build_psymtabs (objfile, section_offsets, mainline, dbfoff, dbfsize,
   current_objfile = NULL;
 }
 
-
-/*
-
-LOCAL FUNCTION
-
-       record_minimal_symbol -- add entry to gdb's minimal symbol table
-
-SYNOPSIS
-
-       static void record_minimal_symbol (char *name, CORE_ADDR address,
-                                         enum minimal_symbol_type ms_type,
-                                         struct objfile *objfile)
-
-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.
-
- */
-
-static void
-record_minimal_symbol (name, address, ms_type, objfile)
-     char *name;
-     CORE_ADDR address;
-     enum minimal_symbol_type ms_type;
-     struct objfile *objfile;
-{
-  name = obsavestring (name, strlen (name), &objfile -> symbol_obstack);
-  prim_record_minimal_symbol (name, address, ms_type);
-}
-
-/*
-
-LOCAL FUNCTION
-
-       dwarfwarn -- issue a DWARF related warning
-
-DESCRIPTION
-
-       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.
-
-       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.
-
-NOTES
-
-       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).
-
-       We assume that curdie is valid and contains at least the basic
-       information for the DIE where the problem was noticed.
-*/
-
-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);
-}
-
 /*
 
 LOCAL FUNCTION
@@ -826,7 +831,7 @@ lookup_utype (die_ref)
   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
     {
@@ -870,12 +875,12 @@ alloc_utype (die_ref, utypep)
   if ((utypeidx < 0) || (utypeidx >= numutypes))
     {
       utypep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
-      dwarfwarn ("reference to DIE (0x%x) outside compilation unit", die_ref);
+      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
     {
@@ -973,7 +978,6 @@ struct_type (dip, thisdie, enddie, objfile)
   struct nextfield *new;
   int nfields = 0;
   int n;
-  char *tpart1;
   struct dieinfo mbr;
   char *nextdie;
   int anonymous_size;
@@ -988,21 +992,17 @@ struct_type (dip, thisdie, enddie, objfile)
     {
       case TAG_class_type:
         TYPE_CODE (type) = TYPE_CODE_CLASS;
-       tpart1 = "class";
        break;
       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 class, structure, or union tag"));
+       complain (&missing_tag, DIE_ID, DIE_NAME);
        break;
     }
   /* Some compilers try to be helpful by inventing "fake" names for
@@ -1012,8 +1012,8 @@ struct_type (dip, thisdie, enddie, objfile)
       && *dip -> at_name != '~'
       && *dip -> at_name != '.')
     {
-      TYPE_NAME (type) = obconcat (&objfile -> type_obstack,
-                                  tpart1, " ", 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
@@ -1053,39 +1053,47 @@ struct_type (dip, thisdie, enddie, objfile)
          list -> field.bitpos = 8 * locval (mbr.at_location);
          /* 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)
+         if (BITS_BIG_ENDIAN)
            {
-             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
+             /* 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)
                {
-                 /* 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);
+                 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);
+                   }
+                 list -> field.bitpos +=
+                   anonymous_size * 8 - mbr.at_bit_offset - mbr.at_bit_size;
                }
-             list -> field.bitpos +=
-               anonymous_size * 8 - mbr.at_bit_offset - mbr.at_bit_size;
            }
-#endif
          nfields++;
          break;
        default:
@@ -1210,7 +1218,7 @@ decode_array_element_type (scan)
   scan += SIZEOF_ATTRIBUTE;
   if ((nbytes = attribute_size (attribute)) == -1)
     {
-      SQUAWK (("bad array element type attribute 0x%x", attribute));
+      complain (&bad_array_element_type, DIE_ID, DIE_NAME, attribute);
       typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
     }
   else
@@ -1237,7 +1245,7 @@ decode_array_element_type (scan)
            typep = decode_mod_u_d_type (scan);
            break;
          default:
-           SQUAWK (("bad array element type attribute 0x%x", attribute));
+           complain (&bad_array_element_type, DIE_ID, DIE_NAME, attribute);
            typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
            break;
          }
@@ -1298,6 +1306,7 @@ decode_subscript_data_item (scan, end)
   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;
@@ -1326,11 +1335,12 @@ decode_subscript_data_item (scan, end)
       if (nexttype == NULL)
        {
          /* Munged subscript data or other problem, fake it. */
-         SQUAWK (("can't decode subscript data items"));
+         complain (&subscript_data_items, DIE_ID, DIE_NAME);
          nexttype = dwarf_fundamental_type (current_objfile, FT_INTEGER);
        }
-      typep = create_array_type ((struct type *) NULL, nexttype, indextype,
-                                lowbound, highbound);
+      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:
@@ -1339,14 +1349,16 @@ decode_subscript_data_item (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));
-      typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
-      typep = create_array_type ((struct type *) NULL, typep, typep, 0, 1);
+      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));
-      typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
-      typep = create_array_type ((struct type *) NULL, typep, typep, 0, 1);
+      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);
@@ -1382,7 +1394,7 @@ dwarf_read_array_type (dip)
   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)
     {
@@ -1412,7 +1424,7 @@ dwarf_read_array_type (dip)
        {
          /* Double ick!  Not only is a type already in our slot, but
             someone has decorated it.  Complain and leave it alone. */
-         SQUAWK (("duplicate user defined array type definition"));
+         complain (&dup_user_type_definition, DIE_ID, DIE_NAME);
        }
     }
 }
@@ -1462,6 +1474,69 @@ read_tag_pointer_type (dip)
 
 /*
 
+LOCAL FUNCTION
+
+       read_tag_string_type -- read TAG_string_type DIE
+
+SYNOPSIS
+
+       static void read_tag_string_type (struct dieinfo *dip)
+
+DESCRIPTION
+
+       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.
+ */
+
+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;
+
+  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
@@ -1515,13 +1590,12 @@ read_subroutine_type (dip, thisdie, enddie)
       /* We have an existing partially constructed type, so bash it
         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
     {
-      SQUAWK (("duplicate user defined function type definition"));
+      complain (&dup_user_type_definition, DIE_ID, DIE_NAME);
     }
 }
 
@@ -1634,8 +1708,8 @@ enum_type (dip, objfile)
       && *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)
     {
@@ -1675,6 +1749,7 @@ enum_type (dip, objfile)
          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;
@@ -1777,9 +1852,7 @@ handle_producer (producer)
 
   processing_gcc_compilation =
     STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER))
-      /* start-sanitize-chill */
       || STREQN (producer, CHILL_PRODUCER, strlen (CHILL_PRODUCER))
-      /* end-sanitize-chill */
       || STREQN (producer, GCC_PRODUCER, strlen (GCC_PRODUCER));
 
   /* Select a demangling style if we can identify the producer and if
@@ -1787,7 +1860,6 @@ handle_producer (producer)
      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 1 /* Works, but is experimental.  -fnf */
   if (AUTO_DEMANGLING)
     {
       if (STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER)))
@@ -1798,12 +1870,7 @@ handle_producer (producer)
        {
          set_demangling_style (LUCID_DEMANGLING_STYLE_STRING);
        }
-      else if (STREQN (producer, CFRONT_PRODUCER, strlen (CFRONT_PRODUCER)))
-       {
-         set_demangling_style (CFRONT_DEMANGLING_STYLE_STRING);
-       }
     }
-#endif
 }
 
 
@@ -1858,7 +1925,8 @@ read_file_scope (dip, thisdie, enddie, objfile)
   start_symtab (dip -> at_name, dip -> at_comp_dir, dip -> at_low_pc);
   decode_line_numbers (lnbase);
   process_dies (thisdie + dip -> die_length, enddie, objfile);
-  symtab = end_symtab (dip -> at_high_pc, 0, 0, objfile);
+
+  symtab = end_symtab (dip -> at_high_pc, 0, 0, objfile, 0);
   if (symtab != NULL)
     {
       symtab -> language = cu_language;
@@ -1916,10 +1984,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:
@@ -1948,6 +2027,9 @@ 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:
              new_symbol (&di, objfile);
              break;
@@ -2070,6 +2152,9 @@ DESCRIPTION
 
        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 global 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
@@ -2097,7 +2182,6 @@ locval (loc)
   auto long stack[64];
   int stacki;
   char *end;
-  long regno;
   int loc_atom_code;
   int loc_value_size;
   
@@ -2109,9 +2193,11 @@ locval (loc)
   stack[stacki] = 0;
   isreg = 0;
   offreg = 0;
+  optimized_out = 1;
   loc_value_size = TARGET_FT_LONG_SIZE (current_objfile);
   while (loc < end)
     {
+      optimized_out = 0;
       loc_atom_code = target_to_host (loc, SIZEOF_LOC_ATOM_CODE, GET_UNSIGNED,
                                      current_objfile);
       loc += SIZEOF_LOC_ATOM_CODE;
@@ -2123,27 +2209,22 @@ locval (loc)
            break;
          case OP_REG:
            /* push register (number) */
-           stack[++stacki] = target_to_host (loc, loc_value_size,
-                                             GET_UNSIGNED, current_objfile);
+           stack[++stacki]
+             = DWARF_REG_TO_REGNUM (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 */
+           /* Actually, we compute the value as if register has 0, so the
+              value ends up being the offset from that register.  */
            offreg = 1;
-           regno = target_to_host (loc, loc_value_size, GET_UNSIGNED,
-                                   current_objfile);
+           basereg = 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));
-             }
+           stack[++stacki] = 0;
            break;
          case OP_ADDR:
            /* push address (relocated address) */
@@ -2159,10 +2240,10 @@ locval (loc)
            break;
          case OP_DEREF2:
            /* pop, deref and push 2 bytes (as a long) */
-           SQUAWK (("OP_DEREF2 address 0x%x not handled", stack[stacki]));
+           complain (&op_deref2, DIE_ID, DIE_NAME, 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]));
+           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];
@@ -2181,19 +2262,18 @@ LOCAL FUNCTION
 
 SYNOPSIS
 
-       static struct symtab *read_ofile_symtab (struct partial_symtab *pst)
+       static void read_ofile_symtab (struct partial_symtab *pst)
 
 DESCRIPTION
 
        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.
-
-       Returns a pointer to the newly constructed symtab (which is now
-       the new first one on the objfile's symtab list).
+       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;
 {
@@ -2253,7 +2333,7 @@ read_ofile_symtab (pst)
   process_dies (dbbase, dbbase + dbsize, pst -> objfile);
   do_cleanups (back_to);
   current_objfile = NULL;
-  return (pst -> objfile -> symtabs);
+  pst -> symtab = pst -> objfile -> symtabs;
 }
 
 /*
@@ -2297,14 +2377,14 @@ psymtab_to_symtab_1 (pst)
                  /* 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);
                      wrap_here ("");
-                     fflush (stdout);          /* Flush output */
+                     gdb_flush (gdb_stdout);           /* Flush output */
                    }
                  psymtab_to_symtab_1 (pst -> dependencies[i]);
                }
@@ -2313,12 +2393,12 @@ psymtab_to_symtab_1 (pst)
            {
              buildsym_init ();
              old_chain = make_cleanup (really_free_pendings, 0);
-             pst -> symtab = read_ofile_symtab (pst);
+             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);
              do_cleanups (old_chain);
@@ -2368,7 +2448,7 @@ dwarf_psymtab_to_symtab (pst)
                {
                  printf_filtered ("Reading in symbols for %s...",
                                   pst -> filename);
-                 fflush (stdout);
+                 gdb_flush (gdb_stdout);
                }
              
              psymtab_to_symtab_1 (pst);
@@ -2386,7 +2466,7 @@ dwarf_psymtab_to_symtab (pst)
              if (info_verbose)
                {
                  printf_filtered ("done.\n");
-                 fflush (stdout);
+                 gdb_flush (gdb_stdout);
                }
            }
        }
@@ -2395,54 +2475,6 @@ dwarf_psymtab_to_symtab (pst)
 
 /*
 
-LOCAL FUNCTION
-
-       init_psymbol_list -- initialize storage for partial symbols
-
-SYNOPSIS
-
-       static void init_psymbol_list (struct objfile *objfile, int total_symbols)
-
-DESCRIPTION
-
-       Initializes storage for all of the partial symbols that will be
-       created by dwarf_build_psymtabs and subsidiaries.
- */
-
-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
@@ -2481,7 +2513,8 @@ add_enum_psymbol (dip, objfile)
        {
          scan += TARGET_FT_LONG_SIZE (objfile);
          ADD_PSYMBOL_TO_LIST (scan, strlen (scan), VAR_NAMESPACE, LOC_CONST,
-                              objfile -> static_psymbols, 0);
+                              objfile -> static_psymbols, 0, cu_language,
+                              objfile);
          scan += strlen (scan) + 1;
        }
     }
@@ -2512,54 +2545,53 @@ add_partial_symbol (dip, objfile)
   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),
                           VAR_NAMESPACE, LOC_BLOCK,
                           objfile -> global_psymbols,
-                          dip -> at_low_pc);
+                          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),
                           VAR_NAMESPACE, LOC_STATIC,
                           objfile -> global_psymbols,
-                          0);
+                          0, cu_language, objfile);
       break;
     case TAG_subroutine:
       ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
                           VAR_NAMESPACE, LOC_BLOCK,
                           objfile -> static_psymbols,
-                          dip -> at_low_pc);
+                          dip -> at_low_pc, cu_language, objfile);
       break;
     case TAG_local_variable:
       ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
                           VAR_NAMESPACE, LOC_STATIC,
                           objfile -> static_psymbols,
-                          0);
+                          0, cu_language, objfile);
       break;
     case TAG_typedef:
       ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
                           VAR_NAMESPACE, LOC_TYPEDEF,
                           objfile -> static_psymbols,
-                          0);
+                          0, cu_language, objfile);
       break;
     case TAG_class_type:
     case TAG_structure_type:
     case TAG_union_type:
     case TAG_enumeration_type:
+      /* 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)
        {
          /* 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);
        }
       break;
     }
@@ -2668,7 +2700,8 @@ scan_partial_symbols (thisdie, enddie, objfile)
                      temp = dbbase + di.at_sibling - dbroff;
                      if ((temp < thisdie) || (temp >= enddie))
                        {
-                         dwarfwarn ("reference to DIE (0x%x) outside compilation unit", di.at_sibling);
+                         complain (&bad_die_ref, DIE_ID, DIE_NAME,
+                                   di.at_sibling);
                        }
                      else
                        {
@@ -2865,6 +2898,14 @@ new_symbol (dip, objfile)
       SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
       SYMBOL_CLASS (sym) = LOC_STATIC;
       SYMBOL_TYPE (sym) = decode_die_type (dip);
+
+      /* 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:
@@ -2899,13 +2940,18 @@ new_symbol (dip, objfile)
            {
              SYMBOL_VALUE (sym) = locval (dip -> at_location);
              add_symbol_to_list (sym, list_in_scope);
-             if (isreg)
+             if (optimized_out)
+               {
+                 SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
+               }
+             else if (isreg)
                {
                  SYMBOL_CLASS (sym) = LOC_REGISTER;
                }
              else if (offreg)
                {
-                 SYMBOL_CLASS (sym) = LOC_LOCAL;
+                 SYMBOL_CLASS (sym) = LOC_BASEREG;
+                 SYMBOL_BASEREG (sym) = basereg;
                }
              else
                {
@@ -2924,6 +2970,11 @@ new_symbol (dip, objfile)
            {
              SYMBOL_CLASS (sym) = LOC_REGPARM;
            }
+         else if (offreg)
+           {
+             SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
+             SYMBOL_BASEREG (sym) = basereg;
+           }
          else
            {
              SYMBOL_CLASS (sym) = LOC_ARG;
@@ -2993,6 +3044,7 @@ synthesize_typedef (dip, objfile, type)
       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;
@@ -3166,7 +3218,7 @@ decode_modified_type (modifiers, modcount, mtype)
            }
          break;
        default:
-         SQUAWK (("botched modified type decoding (mtype 0x%x)", mtype));
+         complain (&botched_modified_type, DIE_ID, DIE_NAME, mtype);
          typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
          break;
        }
@@ -3184,17 +3236,16 @@ decode_modified_type (modifiers, modcount, mtype)
            typep = lookup_reference_type (typep);
            break;
          case MOD_const:
-           SQUAWK (("type modifier 'const' ignored"));         /* FIXME */
+           complain (&const_ignored, DIE_ID, DIE_NAME);  /* FIXME */
            break;
          case MOD_volatile:
-           SQUAWK (("type modifier 'volatile' ignored"));      /* FIXME */
+           complain (&volatile_ignored, DIE_ID, DIE_NAME); /* FIXME */
            break;
          default:
            if (!(MOD_lo_user <= (unsigned char) modifier
                  && (unsigned char) modifier <= MOD_hi_user))
              {
-               SQUAWK (("unknown type modifier %u",
-                        (unsigned char) modifier));
+               complain (&unknown_type_modifier, DIE_ID, DIE_NAME, modifier);
              }
            break;
        }
@@ -3337,7 +3388,7 @@ decode_fund_type (fundtype)
       typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
       if (!(FT_lo_user <= fundtype && fundtype <= FT_hi_user))
        {
-         SQUAWK (("unexpected fundamental type 0x%x", fundtype));
+         complain (&unexpected_fund_type, DIE_ID, DIE_NAME, fundtype);
        }
     }
     
@@ -3440,7 +3491,7 @@ basicdieinfo (dip, diep, 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))
@@ -3508,7 +3559,7 @@ 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;
        }
@@ -3665,8 +3716,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;
        }
@@ -3698,16 +3748,18 @@ NOTES
        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)
     {
@@ -3724,7 +3776,7 @@ target_to_host (from, nbytes, signextend, objfile)
        rtnval = bfd_get_8 (objfile -> obfd, (bfd_byte *) from);
        break;
       default:
-       dwarfwarn ("no bfd support for %d byte data object", nbytes);
+       complain (&no_bfd_get_N, DIE_ID, DIE_NAME, nbytes);
        rtnval = 0;
        break;
     }
@@ -3780,7 +3832,7 @@ attribute_size (attr)
        nbytes = TARGET_FT_POINTER_SIZE (objfile);
        break;
       default:
-       SQUAWK (("unknown attribute form (0x%x)", form));
+       complain (&unknown_attribute_form, DIE_ID, DIE_NAME, form);
        nbytes = -1;
        break;
       }
This page took 0.046176 seconds and 4 git commands to generate.