]> Git Repo - binutils.git/blobdiff - gdb/dbxread.c
gdb-3.4
[binutils.git] / gdb / dbxread.c
index 27ffcc1f347883d6cc6a0247079e6cc16d837d82..9c9f2bf5ebc4c3705791bb80120b193ed651b4ad 100644 (file)
 /* Read dbx symbol tables and convert to internal format, for GDB.
-   Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
-   Hacked by Michael Tiemann ([email protected])
-
-GDB is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY.  No author or distributor accepts responsibility to anyone
-for the consequences of using it or for whether it serves any
-particular purpose or works at all, unless he says so in writing.
-Refer to the GDB General Public License for full details.
-
-Everyone is granted permission to copy, modify and redistribute GDB,
-but only under the conditions described in the GDB General Public
-License.  A copy of this license is supposed to have been given to you
-along with GDB so you can know your rights and responsibilities.  It
-should be in a file named COPYING.  Among other things, the copyright
-notice and this notice must be preserved on all copies.
-
-In other words, go ahead and share GDB, but don't try to stop
-anyone else from sharing it farther.  Help stamp out software hoarding!
-*/
+   Copyright (C) 1986, 1987, 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 \f
 #include "param.h"
 
 #ifdef READ_DBX_FORMAT
 
+#ifdef USG
+#include <sys/types.h>
+#include <fcntl.h>
+#define L_SET 0
+#define L_INCR 1
+#endif
+
+#ifdef COFF_ENCAPSULATE
+#include "a.out.encap.h"
+#include "stab.gnu.h"
+#else
 #include <a.out.h>
 #include <stab.h>
+#endif
+#include <ctype.h>
+
+#ifndef NO_GNU_STABS
+/*
+ * Define specifically gnu symbols here.
+ */
+
+/* The following type indicates the definition of a symbol as being
+   an indirect reference to another symbol.  The other symbol
+   appears as an undefined reference, immediately following this symbol.
+
+   Indirection is asymmetrical.  The other symbol's value will be used
+   to satisfy requests for the indirect symbol, but not vice versa.
+   If the other symbol does not have a definition, libraries will
+   be searched to find a definition.  */
+#ifndef N_INDR
+#define N_INDR 0xa
+#endif
+
+/* The following symbols refer to set elements.
+   All the N_SET[ATDB] symbols with the same name form one set.
+   Space is allocated for the set in the text section, and each set
+   element's value is stored into one word of the space.
+   The first word of the space is the length of the set (number of elements).
+
+   The address of the set is made into an N_SETV symbol
+   whose name is the same as the name of the set.
+   This symbol acts like a N_DATA global symbol
+   in that it can satisfy undefined external references.  */
+
+#ifndef N_SETA
+#define        N_SETA  0x14            /* Absolute set element symbol */
+#endif                         /* This is input to LD, in a .o file.  */
+
+#ifndef N_SETT
+#define        N_SETT  0x16            /* Text set element symbol */
+#endif                         /* This is input to LD, in a .o file.  */
+
+#ifndef N_SETD
+#define        N_SETD  0x18            /* Data set element symbol */
+#endif                         /* This is input to LD, in a .o file.  */
+
+#ifndef N_SETB
+#define        N_SETB  0x1A            /* Bss set element symbol */
+#endif                         /* This is input to LD, in a .o file.  */
+
+/* Macros dealing with the set element symbols defined in a.out.h */
+#define        SET_ELEMENT_P(x)        ((x)>=N_SETA&&(x)<=(N_SETB|N_EXT))
+#define TYPE_OF_SET_ELEMENT(x) ((x)-N_SETA+N_ABS)
+
+#ifndef N_SETV
+#define N_SETV 0x1C            /* Pointer to set vector in data area.  */
+#endif                         /* This is output from LD.  */
+
+#ifndef N_WARNING
+#define N_WARNING 0x1E         /* Warning message to print if file included */
+#endif                         /* This is input to ld */
+
+#ifndef __GNU_STAB__
+
+/* Line number for the data section.  This is to be used to describe
+   the source location of a variable declaration.  */
+#ifndef N_DSLINE
+#define N_DSLINE (N_SLINE+N_DATA-N_TEXT)
+#endif
+
+/* Line number for the bss section.  This is to be used to describe
+   the source location of a variable declaration.  */
+#ifndef N_BSLINE
+#define N_BSLINE (N_SLINE+N_BSS-N_TEXT)
+#endif
+
+#endif /* not __GNU_STAB__ */
+#endif /* NO_GNU_STABS */
+
 #include <stdio.h>
 #include <obstack.h>
 #include <sys/param.h>
 #include <sys/file.h>
 #include <sys/stat.h>
 #include "defs.h"
-#include "initialize.h"
 #include "symtab.h"
 
+#ifndef COFF_FORMAT
+#ifndef AOUTHDR
+#define AOUTHDR                struct exec
+#endif
+#endif
+
 static void add_symbol_to_list ();
 static void read_dbx_symtab ();
 static void process_one_symbol ();
+static void free_all_psymbols ();
 static struct type *read_type ();
 static struct type *read_range_type ();
 static struct type *read_enum_type ();
 static struct type *read_struct_type ();
+static struct type *read_array_type ();
 static long read_number ();
 static void finish_block ();
 static struct blockvector *make_blockvector ();
@@ -48,18 +140,47 @@ static struct symbol *define_symbol ();
 static void start_subfile ();
 static int hashname ();
 static void hash_symsegs ();
+static struct pending *copy_pending ();
+static void fix_common_block ();
+
+static void add_undefined_type ();
+static void cleanup_undefined_types ();
+
+extern char *index();
 
 extern struct symtab *read_symsegs ();
 extern void free_all_symtabs ();
+extern void free_all_psymtabs ();
+extern void free_inclink_symtabs ();
 
 /* C++ */
 static struct type **read_args ();
 
+/* Macro to determine which symbols to ignore when reading the first symbol
+   of a file.  Some machines override this definition. */
+#ifdef N_NSYMS
+#ifndef IGNORE_SYMBOL
+/* This code is used on Ultrix systems.  Ignore it */
+#define IGNORE_SYMBOL(type)  (type == N_NSYMS)
+#endif
+#else
+#ifndef IGNORE_SYMBOL
+/* Don't ignore any symbols. */
+#define IGNORE_SYMBOL(type) (0)
+#endif
+#endif /* not N_NSYMS */
+
 /* Macro for number of symbol table entries (in usual a.out format).
    Some machines override this definition.  */
 #ifndef NUMBER_OF_SYMBOLS
+#ifdef COFF_HEADER
+#define NUMBER_OF_SYMBOLS \
+  ((COFF_HEADER(hdr) ? hdr.coffhdr.filehdr.f_nsyms : hdr.a_syms) /     \
+   sizeof (struct nlist))
+#else
 #define NUMBER_OF_SYMBOLS (hdr.a_syms / sizeof (struct nlist))
 #endif
+#endif
 
 /* Macro for file-offset of symbol table (in usual a.out format).  */
 #ifndef SYMBOL_TABLE_OFFSET
@@ -80,20 +201,80 @@ static struct type **read_args ();
 
 /* Macro to declare variables to hold the file's header data.  */
 #ifndef DECLARE_FILE_HEADERS
-#define DECLARE_FILE_HEADERS  struct exec hdr
+#define DECLARE_FILE_HEADERS  AOUTHDR hdr
 #endif
 
 /* Macro to read the header data from descriptor DESC and validate it.
    NAME is the file name, for error messages.  */
 #ifndef READ_FILE_HEADERS
+#ifdef HEADER_SEEK_FD
+#define READ_FILE_HEADERS(DESC, NAME)          \
+{ HEADER_SEEK_FD (DESC);                       \
+  val = myread (DESC, &hdr, sizeof hdr);       \
+  if (val < 0) perror_with_name (NAME);                \
+  if (N_BADMAG (hdr))                          \
+    error ("File \"%s\" not in executable format.", NAME); }
+#else
 #define READ_FILE_HEADERS(DESC, NAME)          \
 { val = myread (DESC, &hdr, sizeof hdr);       \
   if (val < 0) perror_with_name (NAME);                \
   if (N_BADMAG (hdr))                          \
     error ("File \"%s\" not in executable format.", NAME); }
 #endif
+#endif
+
+/* Non-zero if this is an object (.o) file, rather than an executable.
+   Distinguishing between the two is rarely necessary (and seems like
+   a hack, but there is no other way to do ADDR_OF_TEXT_SEGMENT
+   right for SunOS).  */
+#if !defined (IS_OBJECT_FILE)
+/* This will not work
+   if someone decides to make ld preserve relocation info.  */
+#define IS_OBJECT_FILE (hdr.a_trsize != 0)
+#endif
+
+/* Macro for size of text segment */
+#ifndef SIZE_OF_TEXT_SEGMENT
+#define SIZE_OF_TEXT_SEGMENT hdr.a_text
+#endif
+
+/* Get the address in debugged memory of the start
+   of the text segment.  */
+#if !defined (ADDR_OF_TEXT_SEGMENT)
+#if defined (N_TXTADDR)
+#define ADDR_OF_TEXT_SEGMENT (IS_OBJECT_FILE ? 0 : N_TXTADDR (hdr))
+#else /* no N_TXTADDR */
+#define ADDR_OF_TEXT_SEGMENT 0
+#endif /* no N_TXTADDR */
+#endif /* no ADDR_OF_TEXT_SEGMENT */
+
+/* Macro to get entry point from headers.  */
+#ifndef ENTRY_POINT
+#define ENTRY_POINT hdr.a_entry
+#endif
+
+/* Macro for name of symbol to indicate a file compiled with gcc. */
+#ifndef GCC_COMPILED_FLAG_SYMBOL
+#define GCC_COMPILED_FLAG_SYMBOL "gcc_compiled."
+#endif
+
+/* Convert stab register number (from `r' declaration) to a gdb REGNUM.  */
+
+#ifndef STAB_REG_TO_REGNUM
+#define STAB_REG_TO_REGNUM(VALUE) (VALUE)
+#endif
+
+/* Define this as 1 if a pcc declaration of a char or short argument
+   gives the correct address.  Otherwise assume pcc gives the
+   address of the corresponding int, which is not the same on a
+   big-endian machine.  */
+
+#ifndef BELIEVE_PCC_PROMOTION
+#define BELIEVE_PCC_PROMOTION 0
+#endif
 \f
-START_FILE
+/* Nonzero means give verbose info on gdb action.  From main.c.  */
+extern int info_verbose;
 
 /* Chain of symtabs made from reading the file's symsegs.
    These symtabs do not go into symtab_list themselves,
@@ -176,6 +357,8 @@ static int line_vector_length;
 /* Hash table of global symbols whose values are not known yet.
    They are chained thru the SYMBOL_VALUE, since we don't
    have the correct data for that slot yet.  */
+/* The use of the LOC_BLOCK code in this chain is nonstandard--
+   it refers to a FORTRAN common block rather than the usual meaning.  */
 
 #define HASHSIZE 127
 static struct symbol *global_sym_chain[HASHSIZE];
@@ -204,6 +387,15 @@ struct pending *global_symbols;    /* global functions and variables */
 
 struct pending *local_symbols; /* everything local to lexical context */
 
+/* List of symbols declared since the last BCOMM.  This list is a tail
+   of local_symbols.  When ECOMM is seen, the symbols on the list
+   are noted so their proper addresses can be filled in later,
+   using the common block base address gotten from the assembler
+   stabs.  */
+
+struct pending *common_block;
+int common_block_i;
+
 /* Stack representing unclosed lexical contexts
    (that will become blocks, eventually).  */
 
@@ -241,18 +433,48 @@ struct pending_block
 
 struct pending_block *pending_blocks;
 
-extern CORE_ADDR first_object_file_end;        /* From blockframe.c */
+extern CORE_ADDR startup_file_start;   /* From blockframe.c */
+extern CORE_ADDR startup_file_end;     /* From blockframe.c */
 
 /* File name symbols were loaded from.  */
 
 static char *symfile;
 
+/* Low and high symbol values (inclusive) for the global variable
+   entries in the symbol file. */
+
+static int first_global_sym, last_global_sym;
+
+/* Structures with which to manage partial symbol allocation.  */
+
+struct psymbol_allocation_list global_psymbols, static_psymbols;
+
+/* Global variable which, when set, indicates that we are processing a
+   .o file compiled with gcc */
+
+static unsigned char processing_gcc_compilation;
+
+/* Make a list of forward references which haven't been defined.  */
+static struct type **undef_types;
+static int undef_types_allocated, undef_types_length;
+
+  /* Setup a define to deal cleanly with the underscore problem */
+
+#ifdef NAMES_HAVE_UNDERSCORE
+#define HASH_OFFSET 1
+#else
+#define HASH_OFFSET 0
+#endif
+
 static int
 xxmalloc (n)
 {
   int v = malloc (n);
   if (v == 0)
-    abort ();
+    {
+      fprintf (stderr, "Virtual memory exhausted.\n");
+      abort ();
+    }
   return v;
 }
 
@@ -331,6 +553,23 @@ static int n_header_files;
 
 static int n_allocated_header_files;
 
+/* During initial symbol readin, we need to have a structure to keep
+   track of which psymtabs have which bincls in them.  This structure
+   is used during readin to setup the list of dependencies within each
+   partial symbol table. */
+
+struct header_file_location
+{
+  char *name;                  /* Name of header file */
+  int instance;                        /* See above */
+  struct partial_symtab *pst;  /* Partial symtab that has the
+                                  BINCL/EINCL defs for this file */
+};
+
+/* The actual list and controling variables */
+static struct header_file_location *bincl_list, *next_bincl;
+static int bincls_allocated;
+
 /* Within each object file, various header files are assigned numbers.
    A type is defined or referred to with a pair of numbers
    (FILENUM,TYPENUM) where FILENUM is the number of the header file
@@ -375,8 +614,9 @@ free_header_files ()
   register int i;
   for (i = 0; i < n_header_files; i++)
     free (header_files[i].name);
-  free (header_files);
-  free (this_object_header_files);
+  if (header_files) free (header_files);
+  if (this_object_header_files)
+    free (this_object_header_files);
 }
 
 /* Called at the start of each object file's symbols.
@@ -476,14 +716,16 @@ add_new_header_file (name, instance)
   if (n_header_files == n_allocated_header_files)
     {
       n_allocated_header_files *= 2;
-      header_files
-       = (struct header_file *) xrealloc (header_files, n_allocated_header_files * sizeof (struct header_file));
+      header_files = (struct header_file *)
+       xrealloc (header_files,
+                 (n_allocated_header_files
+                  * sizeof (struct header_file)));
     }
 
   /* Create an entry for this header file.  */
 
   i = n_header_files++;
-  header_files[i].name = name;
+  header_files[i].name = savestring (name, strlen(name));
   header_files[i].instance = instance;
   header_files[i].length = 10;
   header_files[i].vector
@@ -518,7 +760,9 @@ dbx_lookup_type (typenums)
        {
          type_vector_length *= 2;
          type_vector = (struct typevector *)
-           xrealloc (type_vector, sizeof (struct typevector) + type_vector_length * sizeof (struct type *));
+           xrealloc (type_vector,
+                     (sizeof (struct typevector)
+                      + type_vector_length * sizeof (struct type *)));
          bzero (&type_vector->type[type_vector_length / 2],
                 type_vector_length * sizeof (struct type *) / 2);
        }
@@ -546,29 +790,54 @@ dbx_lookup_type (typenums)
     }
 }
 
+/* Create a type object.  Occaisionally used when you need a type
+   which isn't going to be given a type number.  */
+
+static struct type *
+dbx_create_type ()
+{
+  register struct type *type =
+    (struct type *) obstack_alloc (symbol_obstack, sizeof (struct type));
+
+  bzero (type, sizeof (struct type));
+  TYPE_VPTR_FIELDNO (type) = -1;
+  return type;
+}
+
 /* Make sure there is a type allocated for type numbers TYPENUMS
    and return the type object.
-   This can create an empty (zeroed) type object.  */
+   This can create an empty (zeroed) type object.
+   TYPENUMS may be (-1, -1) to return a new type object that is not
+   put into the type vector, and so may not be referred to by number. */
 
 static struct type *
 dbx_alloc_type (typenums)
      int typenums[2];
 {
-  register struct type **type_addr = dbx_lookup_type (typenums);
-  register struct type *type = *type_addr;
+  register struct type **type_addr;
+  register struct type *type;
+
+  if (typenums[1] != -1)
+    {
+      type_addr = dbx_lookup_type (typenums);
+      type = *type_addr;
+    }
+  else
+    {
+      type_addr = 0;
+      type = 0;
+    }
 
   /* If we are referring to a type not known at all yet,
      allocate an empty type for it.
      We will fill it in later if we find out how.  */
   if (type == 0)
     {
-      type = (struct type *) obstack_alloc (symbol_obstack,
-                                           sizeof (struct type));
-      bzero (type, sizeof (struct type));
-      TYPE_VPTR_FIELDNO (type) = -1;
-      TYPE_MAIN_VARIANT (type) = type;
-      *type_addr = type;
+      type = dbx_create_type ();
+      if (type_addr)
+       *type_addr = type;
     }
+  
   return type;
 }
 
@@ -677,7 +946,9 @@ finish_block (symbol, listhead, old_blocks, start, end)
   for (next = *listhead, i = 0; next; i += next->nsyms, next = next->next);
 
   block = (struct block *) obstack_alloc (symbol_obstack,
-                                         sizeof (struct block) + (i - 1) * sizeof (struct symbol *));
+                                         (sizeof (struct block)
+                                          + ((i - 1)
+                                             * sizeof (struct symbol *))));
 
   /* Copy the symbols into the block.  */
 
@@ -692,6 +963,7 @@ finish_block (symbol, listhead, old_blocks, start, end)
   BLOCK_START (block) = start;
   BLOCK_END (block) = end;
   BLOCK_SUPERBLOCK (block) = 0;        /* Filled in when containing block is made */
+  BLOCK_GCC_COMPILED (block) = processing_gcc_compilation;
 
   /* Put the block in as the value of the symbol that names it.  */
 
@@ -731,8 +1003,9 @@ finish_block (symbol, listhead, old_blocks, start, end)
 
   /* Allocate in the symbol_obstack to save time.
      It wastes a little space.  */
-  pblock = (struct pending_block *) obstack_alloc (symbol_obstack,
-                                                  sizeof (struct pending_block));
+  pblock = (struct pending_block *)
+    obstack_alloc (symbol_obstack,
+                  sizeof (struct pending_block));
   pblock->block = block;
   if (opblock)
     {
@@ -757,7 +1030,10 @@ make_blockvector ()
 
   for (next = pending_blocks, i = 0; next; next = next->next, i++);
 
-  blockvector = (struct blockvector *) obstack_alloc (symbol_obstack, sizeof (struct blockvector) + (i - 1) * sizeof (struct block *));
+  blockvector = (struct blockvector *)
+    obstack_alloc (symbol_obstack,
+                  (sizeof (struct blockvector)
+                   + (i - 1) * sizeof (struct block *)));
 
   /* Copy the blocks into the blockvector.
      This is done in reverse order, which happens to put
@@ -785,11 +1061,12 @@ make_blockvector ()
 \f
 /* Manage the vector of line numbers.  */
 
-static
+static void
 record_line (line, pc)
      int line;
      CORE_ADDR pc;
 {
+  struct linetable_entry *e;
   /* Ignore the dummy line number in libg.o */
 
   if (line == 0xffff)
@@ -802,18 +1079,13 @@ record_line (line, pc)
       line_vector_length *= 2;
       line_vector = (struct linetable *)
        xrealloc (line_vector,
-                 sizeof (struct linetable) + line_vector_length * sizeof (int));
+                 (sizeof (struct linetable)
+                  + line_vector_length * sizeof (struct linetable_entry)));
       current_subfile->line_vector = line_vector;
     }
 
-  /* If this line is not continguous with previous one recorded,
-     record a line-number entry for it.  */
-  if (line != prev_line_number + 1)
-    line_vector->item[line_vector_index++] = - line;
-  prev_line_number = line;
-
-  /* Record the core address of the line.  */
-  line_vector->item[line_vector_index++] = pc;
+  e = line_vector->item + line_vector_index++;
+  e->line = line; e->pc = pc;
 }
 \f
 /* Start a new symtab for a new source file.
@@ -849,7 +1121,9 @@ start_symtab (name, start_addr)
     return;
 
   type_vector_length = 160;
-  type_vector = (struct typevector *) xxmalloc (sizeof (struct typevector) + type_vector_length * sizeof (struct type *));
+  type_vector = (struct typevector *)
+    xxmalloc (sizeof (struct typevector)
+             + type_vector_length * sizeof (struct type *));
   bzero (type_vector->type, type_vector_length * sizeof (struct type *));
 
   /* Initialize the list of sub source files with one entry
@@ -858,6 +1132,13 @@ start_symtab (name, start_addr)
   subfiles = 0;
   current_subfile = 0;
   start_subfile (name);
+
+#if 0 /* This is now set at the beginning of read_ofile_symtab */
+  /* Set default for compiler to pcc; assume that we aren't processing
+     a gcc compiled file until proved otherwise.  */
+
+  processing_gcc_compilation = 0;
+#endif
 }
 
 /* Handle an N_SOL symbol, which indicates the start of
@@ -901,7 +1182,8 @@ start_subfile (name)
   line_vector_length = 1000;
   prev_line_number = -2;       /* Force first line number to be explicit */
   line_vector = (struct linetable *)
-    xxmalloc (sizeof (struct linetable) + line_vector_length * sizeof (int));
+    xxmalloc (sizeof (struct linetable)
+             + line_vector_length * sizeof (struct linetable_entry));
 
   /* Make an entry for this subfile in the list of all subfiles
      of the current main source file.  */
@@ -951,6 +1233,11 @@ end_symtab (end_addr)
                    cstk->start_addr, end_addr);
     }
 
+  /* Cleanup any undefined types that have been left hanging around
+     (this needs to be done before the finish_blocks so that
+     file_symbols is still good).  */
+  cleanup_undefined_types ();
+
   /* Finish defining all the blocks of this symtab.  */
   finish_block (0, &file_symbols, 0, last_source_start_addr, end_addr);
   finish_block (0, &global_symbols, 0, last_source_start_addr, end_addr);
@@ -978,7 +1265,8 @@ end_symtab (end_addr)
       lv = subfile->line_vector;
       lv->nitems = subfile->line_vector_index;
       symtab->linetable = (struct linetable *)
-       xrealloc (lv, sizeof (struct linetable) + lv->nitems * sizeof (int));
+       xrealloc (lv, (sizeof (struct linetable)
+                      + lv->nitems * sizeof (struct linetable_entry)));
       symtab->nlines = 0;
       symtab->line_charpos = 0;
 
@@ -1078,9 +1366,10 @@ init_misc_functions ()
 }
 
 static void
-record_misc_function (name, address)
+record_misc_function (name, address, type)
      char *name;
      CORE_ADDR address;
+     int type;
 {
   register struct misc_bunch *new;
 
@@ -1093,6 +1382,15 @@ record_misc_function (name, address)
     }
   misc_bunch->contents[misc_bunch_index].name = name;
   misc_bunch->contents[misc_bunch_index].address = address;
+  misc_bunch->contents[misc_bunch_index].type = (unsigned char)
+    (type == (N_TEXT | N_EXT) ? mf_text :
+     (type == (N_DATA | N_EXT)
+#ifdef N_SETV
+      || type == (N_SETV | N_EXT)
+#endif
+      ) ? mf_data :
+     type == (N_BSS | N_EXT) ? mf_bss :
+     type == (N_ABS | N_EXT) ? mf_abs : mf_unknown);
   misc_bunch_index++;
   misc_count++;
 }
@@ -1123,8 +1421,12 @@ discard_misc_bunches ()
     }
 }
 
+/* INCLINK nonzero means bunches are from an incrementally-linked file.
+   Add them to the existing bunches.
+   Otherwise INCLINK is zero, and we start from scratch. */
 static void
-condense_misc_bunches ()
+condense_misc_bunches (inclink)
+     int inclink;
 {
   register int i, j;
   register struct misc_bunch *bunch;
@@ -1134,11 +1436,22 @@ condense_misc_bunches ()
   int offset = 0;
 #endif
 
-  misc_function_vector
-    = (struct misc_function *)
-      xxmalloc (misc_count * sizeof (struct misc_function));
+  if (inclink)
+    {
+      misc_function_vector
+       = (struct misc_function *)
+         xrealloc (misc_function_vector, (misc_count + misc_function_count)
+                   * sizeof (struct misc_function));
+      j = misc_function_count;
+    }
+  else
+    {
+      misc_function_vector
+       = (struct misc_function *)
+         xxmalloc (misc_count * sizeof (struct misc_function));
+      j = 0;
+    }
 
-  j = 0;
   bunch = misc_bunch;
   while (bunch)
     {
@@ -1155,11 +1468,15 @@ condense_misc_bunches ()
       misc_bunch_index = MISC_BUNCH_SIZE;
     }
 
-  misc_function_count = j;
+  if (inclink)
+    misc_function_count += misc_count;
+  else
+    misc_function_count = j;
 
   /* Sort the misc functions by address.  */
 
-  qsort (misc_function_vector, j, sizeof (struct misc_function),
+  qsort (misc_function_vector, misc_function_count,
+        sizeof (struct misc_function),
         compare_misc_functions);
 }
 \f
@@ -1185,54 +1502,72 @@ compare_symbols (s1, s2)
          - (SYMBOL_CLASS (*s1) == LOC_REGISTER));
 }
 
+static void sort_symtab_syms ();
+
 static void
 sort_syms ()
 {
   register struct symtab *s;
-  int i, nbl;
-  register struct blockvector *bv;
-  register struct block *b;
 
   for (s = symtab_list; s; s = s->next)
+    sort_symtab_syms (s);
+}
+
+static void
+sort_symtab_syms (s)
+     register struct symtab *s;
+{
+  register struct blockvector *bv = BLOCKVECTOR (s);
+  int nbl = BLOCKVECTOR_NBLOCKS (bv);
+  int i;
+  register struct block *b;
+
+  /* Note that in the following sort, we always make sure that
+     register debug symbol declarations always come before regular
+     debug symbol declarations (as might happen when parameters are
+     then put into registers by the compiler).  We do this by a
+     correct compare in compare_symbols, and by the reversal of the
+     symbols if we don't sort.  This works as long as a register debug
+     symbol always comes after a parameter debug symbol. */
+
+  /* This is no longer necessary; lookup_block_symbol now always
+     prefers some other declaration over a parameter declaration.  We
+     still sort the thing (that is necessary), but we don't reverse it
+     if we shouldn't sort it.  */
+
+  for (i = 0; i < nbl; i++)
     {
-      bv = BLOCKVECTOR (s);
-      nbl = BLOCKVECTOR_NBLOCKS (bv);
-      for (i = 0; i < nbl; i++)
-       {
-         b = BLOCKVECTOR_BLOCK (bv, i);
-         if (BLOCK_SHOULD_SORT (b))
-           qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b),
-                  sizeof (struct symbol *), compare_symbols);
-#if 0
-         else
-           {
-             int lastindex = BLOCK_NSYMS (b) - 1;
-             register int j;
-             for (j = (lastindex - 1) / 2; j >= 0; j--)
-               {
-                 register struct symbol *sym;
-                 sym = BLOCK_SYM (b, j);
-                 BLOCK_SYM (b, j) = BLOCK_SYM (b, lastindex - j);
-                 BLOCK_SYM (b, lastindex - j) = sym;
-               }
-           }
-#endif
-       }
+      b = BLOCKVECTOR_BLOCK (bv, i);
+      if (BLOCK_SHOULD_SORT (b))
+       qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b),
+              sizeof (struct symbol *), compare_symbols);
     }
 }
+
 \f
+extern struct symtab *psymtab_to_symtab ();
+
+/* The entry point.  */
+static CORE_ADDR entry_point;
+
 /* This is the symbol-file command.  Read the file, analyze its symbols,
    and add a struct symtab to symtab_list.  */
 
 void
-symbol_file_command (name)
+symbol_file_command (name, from_tty)
      char *name;
+     int from_tty;
 {
   register int desc;
   DECLARE_FILE_HEADERS;
   struct nlist *nlist;
+
+  /* The string table.  */
   char *stringtab;
+  
+  /* The size of the string table (buffer is a bizarre name...).  */
   long buffer;
+  
   register int val;
   extern void close ();
   struct cleanup *old_chain;
@@ -1243,13 +1578,23 @@ symbol_file_command (name)
 
   if (name == 0)
     {
-      if (symtab_list && !query ("Discard symbol table? ", 0))
+      if ((symtab_list || partial_symtab_list)
+         && from_tty
+         && !query ("Discard symbol table? ", 0))
        error ("Not confirmed.");
+      if (symfile)
+       free (symfile);
+      symfile = 0;
       free_all_symtabs ();
+      free_all_psymtabs ();
       return;
     }
 
-  if (symtab_list && !query ("Load new symbol table from \"%s\"? ", name))
+  name = tilde_expand (name);
+  make_cleanup (free, name);
+
+  if ((symtab_list || partial_symtab_list)
+      && !query ("Load new symbol table from \"%s\"? ", name))
     error ("Not confirmed.");
 
   {
@@ -1266,14 +1611,18 @@ symbol_file_command (name)
 
   READ_FILE_HEADERS (desc, name);
 
+  entry_point = ENTRY_POINT;
+
   if (NUMBER_OF_SYMBOLS == 0)
     {
       if (symfile)
        free (symfile);
       symfile = 0;
       free_all_symtabs ();
+      free_all_psymtabs ();
       printf ("%s has no symbol-table; symbols discarded.\n", name);
       fflush (stdout);
+      do_cleanups (old_chain);
       return;
     }
 
@@ -1284,75 +1633,61 @@ symbol_file_command (name)
   val = lseek (desc, STRING_TABLE_OFFSET, 0);
   if (val < 0)
     perror_with_name (name);
-  stat (name, &statbuf);
+  if (stat (name, &statbuf) == -1)
+    error ("internal: error in stat of already open file.");
   READ_STRING_TABLE_SIZE (buffer);
   if (buffer >= 0 && buffer < statbuf.st_size)
-    stringtab = (char *) alloca (buffer);
+    {
+#ifdef BROKEN_LARGE_ALLOCA
+      stringtab = (char *) xmalloc (buffer);
+      make_cleanup (free, stringtab);
+#else
+      stringtab = (char *) alloca (buffer);
+#endif
+    }
   else
     stringtab = NULL;
   if (stringtab == NULL)
-    error ("ridiculous string table size: %d bytes", name, buffer);
+    error ("ridiculous string table size: %d bytes", buffer);
 
-  bcopy (&buffer, stringtab, sizeof buffer);
-  val = myread (desc, stringtab + sizeof buffer, buffer - sizeof buffer);
+  /* Usually READ_STRING_TABLE_SIZE will have shifted the file pointer.
+     Occaisionally, it won't.  */
+  val = lseek (desc, STRING_TABLE_OFFSET, L_SET);
   if (val < 0)
     perror_with_name (name);
-
+  val = myread (desc, stringtab, buffer);
+  if (val < 0)
+    perror_with_name (name);
+  
   /* Throw away the old symbol table.  */
 
   if (symfile)
     free (symfile);
   symfile = 0;
   free_all_symtabs ();
+  free_all_psymtabs ();
 
   /* Empty the hash table of global syms looking for values.  */
   bzero (global_sym_chain, sizeof global_sym_chain);
 
-#ifdef READ_GDB_SYMSEGS
-  /* That puts us at the symsegs.  Read them.  */
-  symseg_chain = read_symsegs (desc, name);
-  hash_symsegs ();
-
-  /* Free the symtabs made by read_symsegs, but not their contents,
-     which have been copied into symtabs on symtab_list.  */
-  for (symseg = symseg_chain; symseg; symseg = symseg->next)
-    {
-      int i;
-      struct sourcevector *sv = (struct sourcevector *) symseg->linetable;
-
-      for (i = 0; i < sv->length; i++)
-       {
-         int j;
-         struct source *source = sv->source[i];
-         struct symtab *sp1
-           = (struct symtab *) xxmalloc (sizeof (struct symtab));
-
-         bcopy (symseg, sp1, sizeof (struct symtab));
-         sp1->filename = savestring (source->name, strlen (source->name));
-         sp1->linetable = &source->contents;
-         sp1->free_code = free_nothing;
-         sp1->free_ptr = (i == 0) ? (char *) symseg : 0;
-
-         sp1->next = symtab_list;
-         symtab_list = sp1;
-       }
-    }
-#else
-  /* Where people are using the 4.2 ld program, must not check for
-     symsegs, because that ld puts randonm garbage at the end of
-     the output file and that would trigger an error message.  */
+  /* Symsegs are no longer supported by GDB.  Setting symseg_chain to
+     0 is easier than finding all the symseg code and eliminating it.  */
   symseg_chain = 0;
-#endif
 
   /* Position to read the symbol table.  Do not read it all at once. */
   val = lseek (desc, SYMBOL_TABLE_OFFSET, 0);
   if (val < 0)
     perror_with_name (name);
 
+  /* Don't put these on the cleanup chain; they need to stick around
+     until the next call to symbol_file_command.  *Then* we'll free
+     them. */
+  free_header_files ();
+  init_header_files ();
+
   init_misc_functions ();
   make_cleanup (discard_misc_bunches, 0);
-  init_header_files ();
-  make_cleanup (free_header_files, 0);
+
   free_pendings = 0;
   pending_blocks = 0;
   file_symbols = 0;
@@ -1362,16 +1697,12 @@ symbol_file_command (name)
   /* Now that the symbol table data of the executable file are all in core,
      process them and define symbols accordingly.  Closes desc.  */
 
-  read_dbx_symtab (desc, stringtab, NUMBER_OF_SYMBOLS);
-  close (desc);
-
-  /* Sort symbols alphabetically within each block.  */
-
-  sort_syms ();
+  read_dbx_symtab (desc, stringtab, buffer, NUMBER_OF_SYMBOLS, 0,
+                  ADDR_OF_TEXT_SEGMENT, SIZE_OF_TEXT_SEGMENT);
 
   /* Go over the misc functions and install them in vector.  */
 
-  condense_misc_bunches ();
+  condense_misc_bunches (0);
 
   /* Don't allow char * to have a typename (else would get caddr_t.)  */
 
@@ -1379,11 +1710,13 @@ symbol_file_command (name)
 
   /* Make a default for file to list.  */
 
-  select_source_symtab (symtab_list);
-
   symfile = savestring (name, strlen (name));
 
-  do_cleanups (old_chain);
+  /* Call to select_source_symtab used to be here; it was using too
+     much time.  I'll make sure that list_sources can handle the lack
+     of current_source_symtab */
+
+  do_cleanups (old_chain);     /* Descriptor closed here */
 
   /* Free the symtabs made by read_symsegs, but not their contents,
      which have been copied into symtabs on symtab_list.  */
@@ -1394,6 +1727,9 @@ symbol_file_command (name)
       symseg_chain = s;
     }
 
+  if (!partial_symtab_list)
+    printf ("\n(no debugging symbols found)...");
+
   printf ("done.\n");
   fflush (stdout);
 }
@@ -1407,7 +1743,7 @@ get_sym_file ()
 }
 \f
 /* Buffer for reading the symbol table entries.  */
-static struct nlist symbuf[2048];
+static struct nlist symbuf[4096];
 static int symbuf_idx;
 static int symbuf_end;
 
@@ -1449,152 +1785,1340 @@ next_symbol_text ()
   return symbuf[symbuf_idx++].n_un.n_strx + stringtab_global;
 }
 \f
-/* Given pointers to a a.out symbol table in core containing  dbx style data,
-   analyze them and create struct symtab's describing the symbols.
-   NLISTLEN is the number of symbols in the symbol table.
-   We read them one at a time using stdio.
-   All symbol names are given as offsets relative to STRINGTAB.  */
+/*
+ * Initializes storage for all of the partial symbols that will be
+ * created by read_dbx_symtab and subsidiaries.
+ */
+void
+init_psymbol_list (total_symbols)
+     int total_symbols;
+{
+  /* Current best guess is that there are approximately a twentieth
+     of the total symbols (in a debugging file) are global or static
+     oriented symbols */
+  global_psymbols.size = total_symbols / 10;
+  static_psymbols.size = total_symbols / 10;
+  global_psymbols.next = global_psymbols.list = (struct partial_symbol *)
+    xmalloc (global_psymbols.size * sizeof (struct partial_symbol));
+  static_psymbols.next = static_psymbols.list = (struct partial_symbol *)
+    xmalloc (static_psymbols.size * sizeof (struct partial_symbol));
+}
+
+/*
+ * Initialize the list of bincls to contain none and have some
+ * allocated.
+ */
+static void
+init_bincl_list (number)
+     int number;
+{
+  bincls_allocated = number;
+  next_bincl = bincl_list = (struct header_file_location *)
+      xmalloc (bincls_allocated * sizeof(struct header_file_location));
+}
+
+/*
+ * Add a bincl to the list.
+ */
+static void
+add_bincl_to_list (pst, name, instance)
+     struct partial_symtab *pst;
+     char *name;
+     int instance;
+{
+  if (next_bincl >= bincl_list + bincls_allocated)
+    {
+      int offset = next_bincl - bincl_list;
+      bincls_allocated *= 2;
+      bincl_list = (struct header_file_location *)
+       xrealloc (bincl_list,
+                 bincls_allocated * sizeof (struct header_file_location));
+      next_bincl = bincl_list + offset;
+    }
+  next_bincl->pst = pst;
+  next_bincl->instance = instance;
+  next_bincl++->name = name;
+}
+
+/*
+ * Given a name, value pair, find the corresponding
+ * bincl in the list.  Return the partial symtab associated
+ * with that header_file_location.
+ */
+struct partial_symtab *
+find_corresponding_bincl_psymtab (name, instance)
+     char *name;
+     int instance;
+{
+  struct header_file_location *bincl;
+
+  for (bincl = bincl_list; bincl < next_bincl; bincl++)
+    if (bincl->instance == instance
+       && !strcmp (name, bincl->name))
+      return bincl->pst;
+
+  return (struct partial_symtab *) 0;
+}
+
+/*
+ * Free the storage allocated for the bincl list.
+ */
+static void
+free_bincl_list ()
+{
+  free (bincl_list);
+  bincls_allocated = 0;
+}
+
+static struct partial_symtab *start_psymtab ();
+static void add_psymtab_dependency ();
+static void end_psymtab();
+
+/* Given pointers to an a.out symbol table in core containing dbx
+   style data, setup partial_symtab's describing each source file for
+   which debugging information is available.  NLISTLEN is the number
+   of symbols in the symbol table.  All symbol names are given as
+   offsets relative to STRINGTAB.  STRINGTAB_SIZE is the size of
+   STRINGTAB.
+
+   I have no idea whether or not this routine should be setup to deal
+   with inclinks.  It seems reasonable to me that they be dealt with
+   standardly, so I am not going to make a strong effort to deal with
+   them here.
+   */
 
 static void
-read_dbx_symtab (desc, stringtab, nlistlen)
+read_dbx_symtab (desc, stringtab, stringtab_size, nlistlen, inclink,
+                text_addr, text_size)
      int desc;
      register char *stringtab;
+     register long stringtab_size;
      register int nlistlen;
+     int inclink;
+     unsigned text_addr;
+     int text_size;
 {
+  register struct nlist *bufp;
   register char *namestring;
-  register struct symbol *sym, *prev;
-  int hash;
-  int num_object_files = 0;
+  register struct partial_symbol *psym;
+  register struct psymbol_allocation_list *psymbol_struct;
+
+  int nsl;
+  int past_first_source_file = 0;
+  CORE_ADDR last_o_file_start = 0;
   struct cleanup *old_chain;
+  char *p;
+  enum namespace ns;
+  enum address_class class;
+
+#ifdef PROFILE_TYPES
+  int i;
+  int profile_types [256];
+  int strcmp_called = 0;
+  int autovars = 0;
+  int global_funs = 0;
+#endif
 
-#ifdef N_BINCL
-  subfile_stack = 0;
+  /* Current partial symtab */
+  struct partial_symtab *pst;
+
+  /* List of current psymtab's include files */
+  char **psymtab_include_list;
+  int includes_allocated;
+  int includes_used;
+
+  /* Index within current psymtab dependency list */
+  struct partial_symtab **dependency_list;
+  int dependencies_used, dependencies_allocated;
+
+#ifdef PROFILE_TYPES
+  for (i = 0; i < 256; i++)
+    profile_types[i] = 0;
 #endif
 
-  old_chain = make_cleanup (free_all_symtabs, 0);
   stringtab_global = stringtab;
+  
+  pst = (struct partial_symtab *) 0;
+
+  includes_allocated = 30;
+  includes_used = 0;
+  psymtab_include_list = (char **) alloca (includes_allocated *
+                                          sizeof (char *));
+
+  dependencies_allocated = 30;
+  dependencies_used = 0;
+  dependency_list =
+    (struct partial_symtab **) alloca (dependencies_allocated *
+                                      sizeof (struct partial_symtab *));
+
+  old_chain = make_cleanup (free_all_psymtabs, 0);
+
+  /* Init bincl list */
+  init_bincl_list (20);
+  make_cleanup (free_bincl_list, 0);
+
+  /* Setup global partial symbol list */
+  init_psymbol_list (nlistlen);
+
   last_source_file = 0;
 
 #ifdef END_OF_TEXT_DEFAULT
   end_of_text_addr = END_OF_TEXT_DEFAULT;
+#else
+  end_of_text_addr = text_addr + text_size;
 #endif
 
-  symtab_input_desc = desc;
+  symtab_input_desc = desc;    /* This is needed for fill_symbuf below */
   symbuf_end = symbuf_idx = 0;
 
   for (symnum = 0; symnum < nlistlen; symnum++)
     {
-      struct nlist *bufp;
-      int type;
-
+      /* Get the symbol for this run and pull out some info */
       QUIT;    /* allow this to be interruptable */
       if (symbuf_idx == symbuf_end)
        fill_symbuf ();
       bufp = &symbuf[symbuf_idx++];
-      type = bufp->n_type;
-      namestring = bufp->n_un.n_strx ? bufp->n_un.n_strx + stringtab : "";
 
-      if (type & N_STAB)
-       process_one_symbol (type, bufp->n_desc,
-                           bufp->n_value, namestring);
-      /* A static text symbol whose name ends in ".o"
-        or begins with "-l" means the start of another object file.
-        So end the symtab of the source file we have been processing.
-        This is how we avoid counting the libraries as part
-        or the last source file.
-        Also this way we find end of first object file (crt0).  */
-      else if (
-#ifdef N_NBTEXT
-              (type == N_NBTEXT)
-#else
-              (type == N_TEXT)
-#endif
-              && (!strcmp (namestring + strlen (namestring) - 2, ".o")
-              ||  !strncmp (namestring, "-l", 2)))
-       {
-         if (num_object_files++ == 1)
-           first_object_file_end = bufp->n_value;
-         if (last_source_file)
-           end_symtab (bufp->n_value);
-       }
-      else if (type & N_EXT || type == N_TEXT
-#ifdef N_NBTEXT
-              || type == N_NBTEXT
+#ifdef PROFILE_TYPES
+      profile_types[bufp->n_type]++;
 #endif
-              )
+
+      /*
+       * Special case to speed up readin.
+       */
+      if (bufp->n_type == N_SLINE) continue;
+
+      /* Ok.  There is a lot of code duplicated in the rest of this
+         switch statiement (for efficiency reasons).  Since I don't
+         like duplicating code, I will do my penance here, and
+         describe the code which is duplicated:
+
+        *) The assignment to namestring.
+        *) The call to index.
+        *) The addition of a partial symbol the the two partial
+           symbol lists.  This last is a large section of code, so
+           I've imbedded it in the following macro.
+        */
+      
+/* Set namestring based on bufp.  */
+#define SET_NAMESTRING()\
+  if (bufp->n_un.n_strx < 0 || bufp->n_un.n_strx >= stringtab_size)  \
+    error ("Invalid symbol data: bad string table offset: %d",       \
+          bufp->n_un.n_strx);                                       \
+  namestring = bufp->n_un.n_strx + stringtab
+
+#define        ADD_PSYMBOL_TO_LIST(NAME, NAMELENGTH, NAMESPACE, CLASS, LIST, VALUE)\
+  do {                                                                 \
+    if ((LIST).next >=                                                 \
+       (LIST).list + (LIST).size)                                      \
+      {                                                                        \
+       (LIST).list = (struct partial_symbol *)                         \
+         xrealloc ((LIST).list,                                        \
+                   ((LIST).size * 2                                    \
+                    * sizeof (struct partial_symbol)));                \
+       /* Next assumes we only went one over.  Should be good if       \
+          program works correctly */                                   \
+       (LIST).next =                                                   \
+         (LIST).list + (LIST).size;                                    \
+       (LIST).size *= 2;                                               \
+      }                                                                        \
+    psym = (LIST).next++;                                              \
+                                                                       \
+    SYMBOL_NAME (psym) = (char *) obstack_alloc (psymbol_obstack,      \
+                                                (NAMELENGTH) + 1);     \
+    strncpy (SYMBOL_NAME (psym), (NAME), (NAMELENGTH));                        \
+    SYMBOL_NAME (psym)[(NAMELENGTH)] = '\0';                           \
+    SYMBOL_NAMESPACE (psym) = (NAMESPACE);                             \
+    SYMBOL_CLASS (psym) = (CLASS);                                     \
+    SYMBOL_VALUE (psym) = (VALUE);                                     \
+  } while (0);
+
+
+      switch (bufp->n_type)
        {
-         int used_up = 0;
+         /*
+          * Standard, non-debugger, symbols
+          */
 
-         /* Record the location of _etext.  */
-         if (type == (N_TEXT | N_EXT)
-             && !strcmp (namestring, "_etext"))
+       case N_TEXT | N_EXT:
+         /* Catch etext */
+
+         SET_NAMESTRING();
+
+         if (namestring[6] == '\0' && namestring[5] == 't'
+             && namestring[4] == 'x' && namestring[3] == 'e'
+             && namestring[2] == 't' && namestring[1] == 'e'
+             && namestring[0] == '_')
            end_of_text_addr = bufp->n_value;
 
-         /* Global symbol: see if we came across a dbx definition
-            for a corresponding symbol.  If so, store the value.
-            Remove syms from the chain when their values are stored,
-            but search the whole chain, as there may be several syms
-            from different files with the same name.  */
-         if (type & N_EXT)
+         /* Figure out beginning and end of global linker symbol
+            section and put non-debugger specified symbols on
+            tmp_symchain */
+
+         last_global_sym = symnum;
+         if (!first_global_sym) first_global_sym = symnum;
+
+         record_misc_function (namestring, bufp->n_value,
+                               bufp->n_type); /* Always */
+
+         continue;
+
+#ifdef N_NBTEXT
+       case N_NBTEXT | N_EXT:
+#endif
+#ifdef N_NBDATA
+       case N_NBDATA | N_EXT:
+#endif
+#ifdef N_NBBSS
+       case N_NBBSS | N_EXT:
+#endif
+#ifdef N_SETV
+       case N_SETV | N_EXT:
+#endif
+       case N_ABS | N_EXT:
+       case N_DATA | N_EXT:
+       case N_BSS | N_EXT:
+         /* Figure out beginning and end of global linker symbol
+            section and put non-debugger specified symbols on
+            tmp_symchain */
+
+         SET_NAMESTRING();
+
+         last_global_sym = symnum;
+         if (!first_global_sym) first_global_sym = symnum;
+
+         /* Not really a function here, but... */
+         record_misc_function (namestring, bufp->n_value,
+                               bufp->n_type); /* Always */
+
+         continue;
+
+#ifdef N_NBTEXT
+       case N_NBTEXT:
+#endif
+#ifdef OFILE_FN_FLAGGED
+#if ! (N_FN & N_EXT)
+       case N_FN:
+#endif
+       case N_FN | N_EXT:
+#else
+       case N_TEXT:
+#endif
+         SET_NAMESTRING();
+         if ((namestring[0] == '-' && namestring[1] == 'l')
+             || (namestring [(nsl = strlen (namestring)) - 1] == 'o'
+                 && namestring [nsl - 2] == '.'))
            {
-             prev = 0;
-#ifdef NAMES_HAVE_UNDERSCORE
-             hash = hashname (namestring + 1);
-#else /* not NAMES_HAVE_UNDERSCORE */
-             hash = hashname (namestring);
-#endif /* not NAMES_HAVE_UNDERSCORE */
-             for (sym = global_sym_chain[hash];
-                  sym;)
+             if (entry_point < bufp->n_value
+                 && entry_point >= last_o_file_start)
                {
-                 if (
-#ifdef NAMES_HAVE_UNDERSCORE
-                     *namestring == '_'
-                     && namestring[1] == SYMBOL_NAME (sym)[0]
-                     &&
-                     !strcmp (namestring + 2, SYMBOL_NAME (sym) + 1)
-#else /* NAMES_HAVE_UNDERSCORE */
-                     namestring[0] == SYMBOL_NAME (sym)[0]
-                     &&
-                     !strcmp (namestring + 1, SYMBOL_NAME (sym) + 1)
-#endif /* NAMES_HAVE_UNDERSCORE */
-                     )
+                 startup_file_start = last_o_file_start;
+                 startup_file_end = bufp->n_value;
+               }
+             if (past_first_source_file && pst)
+               {
+                 end_psymtab (pst, psymtab_include_list, includes_used,
+                              symnum * sizeof (struct nlist), bufp->n_value,
+                              dependency_list, dependencies_used,
+                              global_psymbols.next, static_psymbols.next);
+                 pst = (struct partial_symtab *) 0;
+                 includes_used = 0;
+                 dependencies_used = 0;
+               }
+             else
+               past_first_source_file = 1;
+             last_o_file_start = bufp->n_value;
+           }
+         continue;
+
+#ifdef OFILE_FN_FLAGGED
+       case N_TEXT:
+#else
+#if ! (N_FN & N_EXT)
+       case N_FN:
+#endif
+       case N_FN | N_EXT:
+#endif
+       case N_UNDF:
+       case N_UNDF | N_EXT:
+       case N_ABS:
+       case N_DATA:
+       case N_BSS:
+#ifdef N_NBDATA
+       case N_NBDATA:
+#endif
+#ifdef N_NBBSS
+       case N_NBBSS:
+#endif
+
+         /* Keep going . . .*/
+
+         /*
+          * Special symbol types for GNU
+          */
+#ifdef N_INDR
+       case N_INDR:
+       case N_INDR | N_EXT:
+#endif
+#ifdef N_SETA
+       case N_SETA:
+       case N_SETA | N_EXT:
+       case N_SETT:
+       case N_SETT | N_EXT:
+       case N_SETD:
+       case N_SETD | N_EXT:
+       case N_SETB:
+       case N_SETB | N_EXT:
+       case N_SETV:
+#endif
+         continue;
+
+         /*
+          * Debugger symbols
+          */
+
+       case N_SO:
+         /* End the current partial symtab and start a new one */
+
+         SET_NAMESTRING();
+
+         if (pst && past_first_source_file)
+           {
+             end_psymtab (pst, psymtab_include_list, includes_used,
+                          symnum * sizeof (struct nlist), bufp->n_value,
+                          dependency_list, dependencies_used,
+                          global_psymbols.next, static_psymbols.next);
+             pst = (struct partial_symtab *) 0;
+             includes_used = 0;
+             dependencies_used = 0;
+           }
+         else
+           past_first_source_file = 1;
+
+         pst = start_psymtab (namestring, bufp->n_value,
+                              symnum * sizeof (struct nlist),
+                              global_psymbols.next, static_psymbols.next);
+
+         continue;
+
+#ifdef N_BINCL
+       case N_BINCL:
+         /* Add this bincl to the bincl_list for future EXCLs.  No
+            need to save the string; it'll be around until
+            read_dbx_symtab function return */
+
+         SET_NAMESTRING();
+
+         add_bincl_to_list (pst, namestring, bufp->n_value);
+
+         /* Mark down an include file in the current psymtab */
+
+         psymtab_include_list[includes_used++] = namestring;
+         if (includes_used >= includes_allocated)
+           {
+             char **orig = psymtab_include_list;
+
+             psymtab_include_list = (char **)
+               alloca ((includes_allocated *= 2) *
+                       sizeof (char *));
+             bcopy (orig, psymtab_include_list,
+                    includes_used * sizeof (char *));
+           }
+
+         continue;
+#endif
+
+       case N_SOL:
+         /* Mark down an include file in the current psymtab */
+
+         SET_NAMESTRING();
+
+         /* In C++, one may expect the same filename to come round many
+            times, when code is coming alternately from the main file
+            and from inline functions in other files. So I check to see
+            if this is a file we've seen before.
+
+            This seems to be a lot of time to be spending on N_SOL, but
+            things like "break expread.y:435" need to work (I
+            suppose the psymtab_include_list could be hashed or put
+            in a binary tree, if profiling shows this is a major hog).  */
+         {
+           register int i;
+           for (i = 0; i < includes_used; i++)
+             if (!strcmp (namestring, psymtab_include_list[i]))
+               {
+                 i = -1; 
+                 break;
+               }
+           if (i == -1)
+             continue;
+         }
+
+         psymtab_include_list[includes_used++] = namestring;
+         if (includes_used >= includes_allocated)
+           {
+             char **orig = psymtab_include_list;
+
+             psymtab_include_list = (char **)
+               alloca ((includes_allocated *= 2) *
+                       sizeof (char *));
+             bcopy (orig, psymtab_include_list,
+                    includes_used * sizeof (char *));
+           }
+         continue;
+
+       case N_LSYM:            /* Typedef or automatic variable. */
+         SET_NAMESTRING();
+
+         p = (char *) index (namestring, ':');
+
+         /* Skip if there is no :.  */
+         if (!p) continue;
+
+         switch (p[1])
+           {
+           case 'T':
+             ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+                                  STRUCT_NAMESPACE, LOC_TYPEDEF,
+                                  static_psymbols, bufp->n_value);
+             goto check_enum;
+           case 't':
+             ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+                                  VAR_NAMESPACE, LOC_TYPEDEF,
+                                  static_psymbols, bufp->n_value);
+           check_enum:
+             /* If this is an enumerated type, we need to
+                add all the enum constants to the partial symbol
+                table.  This does not cover enums without names, e.g.
+                "enum {a, b} c;" in C, but fortunately those are
+                rare.  There is no way for GDB to find those from the
+                enum type without spending too much time on it.  Thus
+                to solve this problem, the compiler needs to put out separate
+                constant symbols ('c' N_LSYMS) for enum constants in
+                enums without names.  */
+
+             /* We are looking for something of the form
+                <name> ":" ("t" | "T") [<number> "="] "e"
+                {<constant> ":" <value> ","} ";".  */
+
+             /* Skip over the colon and the 't' or 'T'.  */
+             p += 2;
+             /* This type may be given a number.  Skip over it.  */
+             while ((*p >= '0' && *p <= '9')
+                    || *p == '=')
+               p++;
+
+             if (*p++ == 'e')
+               {
+                 /* We have found an enumerated type.  */
+                 /* According to comments in read_enum_type
+                    a comma could end it instead of a semicolon.
+                    I don't know where that happens.
+                    Accept either.  */
+                 while (*p && *p != ';' && *p != ',')
                    {
-                     if (prev)
-                       SYMBOL_VALUE (prev) = SYMBOL_VALUE (sym);
-                     else
-                       global_sym_chain[hash]
-                         = (struct symbol *) SYMBOL_VALUE (sym);
-                     SYMBOL_VALUE (sym) = bufp->n_value;
-                     if (prev)
-                       sym = (struct symbol *) SYMBOL_VALUE (prev);
-                     else
-                       sym = global_sym_chain[hash];
+                     char *q;
+
+                     /* Check for and handle cretinous dbx symbol name
+                        continuation!  */
+                     if (*p == '\\')
+                       p = next_symbol_text ();
+
+                     /* Point to the character after the name
+                        of the enum constant.  */
+                     for (q = p; *q && *q != ':'; q++)
+                       ;
+                     /* Note that the value doesn't matter for
+                        enum constants in psymtabs, just in symtabs.  */
+                     ADD_PSYMBOL_TO_LIST (p, q - p,
+                                          VAR_NAMESPACE, LOC_CONST,
+                                          static_psymbols, 0);
+                     /* Point past the name.  */
+                     p = q;
+                     /* Skip over the value.  */
+                     while (*p && *p != ',')
+                       p++;
+                     /* Advance past the comma.  */
+                     if (*p)
+                       p++;
+                   }
+               }
+
+             continue;
+           case 'c':
+             /* Constant, e.g. from "const" in Pascal.  */
+             ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+                                  VAR_NAMESPACE, LOC_CONST,
+                                  static_psymbols, bufp->n_value);
+             continue;
+           default:
+#ifdef PROFILE_TYPES
+             if (isalpha(p[1]))
+                 printf ("Funny...LSYM with a letter that isn't a type\n");
+             autovars++;
+#endif
+             /* Skip if the thing following the : is
+                not a letter (which indicates declaration of a local
+                variable, which we aren't interested in).  */
+             continue;
+           }
+
+       case N_FUN:
+#if 0
+         /* This special-casing of N_FUN is just wrong; N_FUN
+            does not mean "function"; it means "text segment".
+            So N_FUN can go with 'V', etc. as well as 'f' or 'F'.  */
+
+         SET_NAMESTRING();
+
+         p = (char *) index (namestring, ':');
+
+         if (!p || p[1] == 'F') continue;
+
+#ifdef PROFILE_TYPES
+         if (p[1] != 'f')
+           printf ("Funny...FUN with a letter that isn't 'F' or 'f'.\n");
+         global_funs++;
+#endif
+
+         ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+                              VAR_NAMESPACE, LOC_BLOCK,
+                              static_psymbols, bufp->n_value);
+
+         continue;
+#endif /* 0 */
+       case N_GSYM:            /* Global (extern) variable; can be
+                                  data or bss (sigh).  */
+       case N_STSYM:           /* Data seg var -- static  */
+       case N_LCSYM:           /* BSS      "  */
+
+       /* Following may probably be ignored; I'll leave them here
+          for now (until I do Pascal and Modula 2 extensions).  */
+
+       case N_PC:              /* I may or may not need this; I
+                                  suspect not.  */
+#ifdef N_M2C
+       case N_M2C:             /* I suspect that I can ignore this here. */
+       case N_SCOPE:           /* Same.   */
+#endif
+
+         SET_NAMESTRING();
+
+         p = (char *) index (namestring, ':');
+         if (!p)
+           continue;           /* Not a debugging symbol.   */
+
+         process_symbol_for_psymtab:
+
+         /* Main processing section for debugging symbols which
+            the initial read through the symbol tables needs to worry
+            about.  If we reach this point, the symbol which we are
+            considering is definitely one we are interested in.
+            p must also contain the (valid) index into the namestring
+            which indicates the debugging type symbol.  */
+
+         switch (p[1])
+           {
+           case 'c':
+             ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+                                  VAR_NAMESPACE, LOC_CONST,
+                                  static_psymbols, bufp->n_value);
+             continue;
+           case 'S':
+             ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+                                  VAR_NAMESPACE, LOC_STATIC,
+                                  static_psymbols, bufp->n_value);
+             continue;
+           case 'G':
+             ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+                                  VAR_NAMESPACE, LOC_EXTERNAL,
+                                  global_psymbols, bufp->n_value);
+             continue;
+
+           case 't':
+             ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+                                  VAR_NAMESPACE, LOC_TYPEDEF,
+                                  global_psymbols, bufp->n_value);
+             continue;
+
+           case 'f':
+             ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+                                  VAR_NAMESPACE, LOC_BLOCK,
+                                  static_psymbols, bufp->n_value);
+             continue;
+
+             /* Two things show up here (hopefully); static symbols of
+                local scope (static used inside braces) or extensions
+                of structure symbols.  We can ignore both.  */
+           case 'V':
+           case '(':
+           case '0':
+           case '1':
+           case '2':
+           case '3':
+           case '4':
+           case '5':
+           case '6':
+           case '7':
+           case '8':
+           case '9':
+             /* Global functions are ignored here.  I'm not
+                sure what psymtab they go into (or just the misc
+                function vector).  */
+           case 'F':
+             continue;
+
+           default:
+             fatal ("Internal error: Unexpected debugging symbol type '%c' at symnum %d.\n",
+                    p[1], symnum);
+           }
+
+#ifdef N_BINCL
+       case N_EXCL:
+
+         SET_NAMESTRING();
+
+         /* Find the corresponding bincl and mark that psymtab on the
+            psymtab dependency list */
+         {
+           struct partial_symtab *needed_pst =
+             find_corresponding_bincl_psymtab (namestring, bufp->n_value);
+
+           /* If this include file was defined earlier in this file,
+              leave it alone.  */
+           if (needed_pst == pst) continue;
+
+           if (needed_pst)
+             {
+               int i;
+               int found = 0;
+
+               for (i = 0; i < dependencies_used; i++)
+                 if (dependency_list[i] == needed_pst)
+                   {
+                     found = 1;
+                     break;
+                   }
+
+               /* If it's already in the list, skip the rest.  */
+               if (found) continue;
+
+               dependency_list[dependencies_used++] = needed_pst;
+               if (dependencies_used >= dependencies_allocated)
+                 {
+                   struct partial_symtab **orig = dependency_list;
+                   dependency_list =
+                     (struct partial_symtab **)
+                       alloca ((dependencies_allocated *= 2)
+                               * sizeof (struct partial_symtab *));
+                   bcopy (orig, dependency_list,
+                          (dependencies_used
+                           * sizeof (struct partial_symtab *)));
+#ifdef DEBUG_INFO
+                   fprintf (stderr, "Had to reallocate dependency list.\n");
+                   fprintf (stderr, "New dependencies allocated: %d\n",
+                            dependencies_allocated);
+#endif
+                 }
+             }
+           else
+             error ("Invalid symbol data: \"repeated\" header file not previously seen, at symtab pos %d.",
+                    symnum);
+         }
+         continue;
+
+       case N_EINCL:
+#endif
+#ifdef N_DSLINE
+       case N_DSLINE:
+#endif
+#ifdef N_BSLINE
+       case N_BSLINE:
+#endif
+       case N_SSYM:            /* Claim: Structure or union element.
+                                  Hopefully, I can ignore this.  */
+       case N_ENTRY:           /* Alternate entry point; can ignore. */
+#ifdef N_MAIN
+       case N_MAIN:            /* Can definitely ignore this.   */
+#endif
+       case N_LENG:
+       case N_BCOMM:
+       case N_ECOMM:
+       case N_ECOML:
+       case N_FNAME:
+       case N_SLINE:
+       case N_RSYM:
+       case N_PSYM:
+       case N_LBRAC:
+       case N_RBRAC:
+         /* These symbols aren't interesting; don't worry about them */
+
+         continue;
+
+       default:
+         /* If we haven't found it yet, we've got problems */
+
+         if (IGNORE_SYMBOL (bufp->n_type))
+           continue;
+
+         fatal ("Bad symbol type 0x%x encountered in gdb scan", bufp->n_type);
+       }
+    }
+
+  /* If there's stuff to be cleaned up, clean it up.  */
+  if (entry_point < bufp->n_value
+      && entry_point >= last_o_file_start)
+    {
+      startup_file_start = last_o_file_start;
+      startup_file_end = bufp->n_value;
+    }
+
+  if (pst)
+    {
+      end_psymtab (pst, psymtab_include_list, includes_used,
+                  symnum * sizeof (struct nlist), end_of_text_addr,
+                  dependency_list, dependencies_used,
+                  global_psymbols.next, static_psymbols.next);
+      includes_used = 0;
+      dependencies_used = 0;
+      pst = (struct partial_symtab *) 0;
+    }
+
+  free_bincl_list ();
+  discard_cleanups (old_chain);
+#ifdef PROFILE_TYPES
+  {
+    int i, j;
+#define __define_stab(SYM, NUMBER, NAME)       {NUMBER, NAME},
+  static struct xyzzy {
+    unsigned char symnum;
+    char *name;
+  } tmp_list[] = {
+#include "stab.def"
+    {0x1, "eREF"},
+    {0x2, "ABS"},
+    {0x3, "eABS"},
+    {0x4, "TEXT"},
+    {0x5, "eTEXT"},
+    {0x6, "DATA"},
+    {0x7, "eDATA"},
+    {0x8, "BSS"},
+    {0x9, "eBSS"},
+    {0x12, "COMM"},
+    {0x13, "eCOMM"},
+    {0x1f, "FN"},
+    {0, "Unknown"},
+};
+    for (i = 0; i < 256; i++)
+      {
+       for (j = 0; j < (sizeof (tmp_list) / sizeof (struct xyzzy)) - 1; j++)
+         if (tmp_list[j].symnum == i)
+           break;
+       printf ("Symbol \"%s\" (0x%x) occured %d times.\n",
+               tmp_list[j].name, i, profile_types[i]);
+      }
+    printf ("Auto vars (under LSYM): %d\n", autovars);
+    printf ("Global funs (under FUN): %d\n", global_funs);
+  }
+#endif
+}
+
+/*
+ * Allocate and partially fill a partial symtab.  It will be
+ * completely filled at the end of the symbol list.
+ */
+static struct partial_symtab *
+start_psymtab (filename, textlow, ldsymoff, global_syms, static_syms)
+     char *filename;
+     int textlow;
+     int ldsymoff;
+     struct partial_symbol *global_syms;
+     struct partial_symbol *static_syms;
+{
+  struct partial_symtab *result =
+    (struct partial_symtab *) obstack_alloc (psymbol_obstack,
+                                            sizeof (struct partial_symtab));
+
+  result->filename =
+    (char *) obstack_alloc (psymbol_obstack,
+                           strlen (filename) + 1);
+  strcpy (result->filename, filename);
+
+  result->textlow = textlow;
+  result->ldsymoff = ldsymoff;
+
+  result->readin = 0;
+
+  result->globals_offset = global_syms - global_psymbols.list;
+  result->statics_offset = static_syms - static_psymbols.list;
+
+  result->n_global_syms = 0;
+  result->n_static_syms = 0;
+
+  return result;
+}
+
+static int
+compare_psymbols (s1, s2)
+     register struct partial_symbol *s1, *s2;
+{
+  register char
+    *st1 = SYMBOL_NAME (s1),
+    *st2 = SYMBOL_NAME (s2);
+
+  return (st1[0] - st2[0] ? st1[0] - st2[0] :
+         strcmp (st1 + 1, st2 + 1));
+}
+
+
+/* Close off the current usage of a partial_symbol table entry.  This
+   involves setting the correct number of includes (with a realloc),
+   setting the high text mark, setting the symbol length in the
+   executable, and setting the length of the global and static lists
+   of psymbols.
+
+   The global symbols and static symbols are then seperately sorted.
+
+   Then the partial symtab is put on the global list.
+   *** List variables and peculiarities of same. ***
+   */
+static void
+end_psymtab (pst, include_list, num_includes, capping_symbol_offset,
+            capping_text, dependency_list, number_dependencies,
+            capping_global, capping_static)
+     struct partial_symtab *pst;
+     char **include_list;
+     int num_includes;
+     int capping_symbol_offset;
+     int capping_text;
+     struct partial_symtab **dependency_list;
+     int number_dependencies;
+     struct partial_symbol *capping_global, *capping_static;
+{
+  int i;
+
+  pst->ldsymlen = capping_symbol_offset - pst->ldsymoff;
+  pst->texthigh = capping_text;
+
+  pst->n_global_syms =
+    capping_global - (global_psymbols.list + pst->globals_offset);
+  pst->n_static_syms =
+    capping_static - (static_psymbols.list + pst->statics_offset);
+
+  pst->dependencies = (struct partial_symtab **)
+    obstack_alloc (psymbol_obstack,
+                  number_dependencies * sizeof (struct partial_symtab *));
+  bcopy (dependency_list, pst->dependencies,
+        number_dependencies * sizeof (struct partial_symtab *));
+  pst->number_of_dependencies = number_dependencies;
+
+  for (i = 0; i < num_includes; i++)
+    {
+      /* Eventually, put this on obstack */
+      struct partial_symtab *subpst =
+       (struct partial_symtab *)
+         obstack_alloc (psymbol_obstack,
+                        sizeof (struct partial_symtab));
+
+      subpst->filename =
+       (char *) obstack_alloc (psymbol_obstack,
+                               strlen (include_list[i]) + 1);
+      strcpy (subpst->filename, include_list[i]);
+
+      subpst->ldsymoff =
+       subpst->ldsymlen =
+         subpst->textlow =
+           subpst->texthigh = 0;
+      subpst->readin = 0;
+
+      subpst->dependencies = (struct partial_symtab **)
+       obstack_alloc (psymbol_obstack,
+                      sizeof (struct partial_symtab *));
+      subpst->dependencies[0] = pst;
+      subpst->number_of_dependencies = 1;
+
+      subpst->globals_offset =
+       subpst->n_global_syms =
+         subpst->statics_offset =
+           subpst->n_static_syms = 0;
+
+      subpst->next = partial_symtab_list;
+      partial_symtab_list = subpst;
+    }
+
+  /* Sort the global list; don't sort the static list */
+  qsort (global_psymbols.list + pst->globals_offset, pst->n_global_syms,
+        sizeof (struct partial_symbol), compare_psymbols);
+
+  /* Put the psymtab on the psymtab list */
+  pst->next = partial_symtab_list;
+  partial_symtab_list = pst;
+}
+\f
+
+/* Helper routines for psymtab_to_symtab.  */
+static void scan_file_globals ();
+static void read_ofile_symtab ();
+
+static void
+psymtab_to_symtab_1 (pst, desc, stringtab, stringtab_size, sym_offset)
+     struct partial_symtab *pst;
+     int desc;
+     char *stringtab;
+     int stringtab_size;
+     int sym_offset;
+{
+  struct cleanup *old_chain;
+  int i;
+  
+  if (!pst)
+    return;
+
+  if (pst->readin)
+    {
+      fprintf (stderr, "Psymtab for %s already read in.  Shouldn't happen.\n",
+              pst->filename);
+      return;
+    }
+
+  /* Read in all partial symbtabs on which this one is dependent */
+  for (i = 0; i < pst->number_of_dependencies; i++)
+    if (!pst->dependencies[i]->readin)
+      {
+       /* Inform about additional files that need to be read in.  */
+       if (info_verbose)
+         {
+           printf_filtered (" and %s...", pst->dependencies[i]->filename);
+           fflush (stdout);
+         }
+       psymtab_to_symtab_1 (pst->dependencies[i], desc,
+                            stringtab, stringtab_size, sym_offset);
+      }
+
+  if (pst->ldsymlen)           /* Otherwise it's a dummy */
+    {
+      /* Init stuff necessary for reading in symbols */
+      free_pendings = 0;
+      pending_blocks = 0;
+      file_symbols = 0;
+      global_symbols = 0;
+      old_chain = make_cleanup (really_free_pendings, 0);
+
+      /* Read in this files symbols */
+      lseek (desc, sym_offset, L_SET);
+      read_ofile_symtab (desc, stringtab, stringtab_size,
+                        pst->ldsymoff,
+                        pst->ldsymlen, pst->textlow,
+                        pst->texthigh - pst->textlow, 0);
+      sort_symtab_syms (symtab_list); /* At beginning since just added */
+
+      do_cleanups (old_chain);
+    }
+
+  pst->readin = 1;
+}
+
+/*
+ * Read in all of the symbols for a given psymtab for real.  Return
+ * the value of the symtab you create.  Do not free the storage
+ * allocated to the psymtab; it may have pointers to it.
+ */
+struct symtab *
+psymtab_to_symtab(pst)
+     struct partial_symtab *pst;
+{
+  int desc;
+  DECLARE_FILE_HEADERS;
+  char *stringtab;
+  struct partial_symtab **list_patch;
+  int stsize, val;
+  struct stat statbuf;
+  struct cleanup *old_chain;
+  extern void close ();
+  int i;
+  struct symtab *result;
+  char *name = symfile;                /* Some of the macros require the */
+                               /* variable "name" to be defined in */
+                               /* the context in which they execute */
+                               /* (Yech!)  */
+
+  if (!pst)
+    return 0;
+
+  if (pst->readin)
+    {
+      fprintf (stderr, "Psymtab for %s already read in.  Shouldn't happen.\n",
+              pst->filename);
+      return 0;
+    }
+
+  if (!name)
+    error("No symbol file currently specified; use command symbol-file");
+
+  if (pst->ldsymlen || pst->number_of_dependencies)
+    {
+      /* Print the message now, before reading the string table,
+        to avoid disconcerting pauses.  */
+      if (info_verbose)
+       {
+         printf_filtered ("Reading in symbols for %s...", pst->filename);
+         fflush (stdout);
+       }
+
+      /* Open symbol file and read in string table */
+      stat (name, &statbuf);
+      desc = open(name, O_RDONLY, 0); /* symbol_file_command
+                                        guarrantees that the symbol file name
+                                        will be absolute, so there is no
+                                        need for openp */
+
+      old_chain = make_cleanup (close, desc);
+
+      if (desc < 0)
+       error("Symbol file not readable");
+
+      READ_FILE_HEADERS (desc, name);
+
+      /* Read in the string table */
+      lseek (desc, STRING_TABLE_OFFSET, L_SET);
+      READ_STRING_TABLE_SIZE (stsize);
+      if (stsize >= 0 && stsize < statbuf.st_size)
+       {
+#ifdef BROKEN_LARGE_ALLOCA
+         stringtab = (char *) xmalloc (stsize);
+         make_cleanup (free, stringtab);
+#else
+         stringtab = (char *) alloca (stsize);
+#endif
+       }
+      else
+       stringtab = NULL;
+      if (stringtab == NULL)
+       error ("ridiculous string table size: %d bytes", stsize);
+
+      /* Usually READ_STRING_TABLE_SIZE will have shifted the file pointer.
+        Occaisionally, it won't.  */
+      val = lseek (desc, STRING_TABLE_OFFSET, L_SET);
+      if (val < 0)
+       perror_with_name (name);
+      val = myread (desc, stringtab, stsize);
+      if (val < 0)
+       perror_with_name (name);
+
+      psymtab_to_symtab_1 (pst, desc, stringtab, stsize,
+                          SYMBOL_TABLE_OFFSET);
+
+      /* 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 ();
+
+      do_cleanups (old_chain);
+
+      /* Finish up the debug error message.  */
+      if (info_verbose)
+       printf_filtered ("done.\n");
+    }
+
+  /* Search through list for correct name. */
+  for (result = symtab_list; result; result = result->next)
+    if (!strcmp (result->filename, pst->filename))
+      return result;
+
+  return 0;
+}
+
+/*
+ * Scan through all of the global symbols defined in the object file,
+ * assigning values to the debugging symbols that need to be assigned
+ * to.  Get these symbols from the misc function list.
+ */
+static void
+scan_file_globals ()
+{
+  int hash;
+  int mf;
+
+  for (mf = 0; mf < misc_function_count; mf++)
+    {
+      char *namestring = misc_function_vector[mf].name;
+      struct symbol *sym, *prev;
+
+      QUIT;
+
+      prev = (struct symbol *) 0;
+
+      /* Get the hash index and check all the symbols
+        under that hash index. */
+
+      hash = hashname (namestring);
+
+      for (sym = global_sym_chain[hash]; sym;)
+       {
+         if (*namestring == SYMBOL_NAME (sym)[0]
+             && !strcmp(namestring + 1, SYMBOL_NAME (sym) + 1))
+           {
+             /* Splice this symbol out of the hash chain and
+                assign the value we have to it. */
+             if (prev)
+               SYMBOL_VALUE (prev) = SYMBOL_VALUE (sym);
+             else
+               global_sym_chain[hash]
+                 = (struct symbol *) SYMBOL_VALUE (sym);
+             
+             /* Check to see whether we need to fix up a common block.  */
+             /* Note: this code might be executed several times for
+                the same symbol if there are multiple references.  */
+             if (SYMBOL_CLASS (sym) == LOC_BLOCK)
+               fix_common_block (sym, misc_function_vector[mf].address);
+             else
+               SYMBOL_VALUE (sym) = misc_function_vector[mf].address;
+             
+             if (prev)
+               sym = (struct symbol *) SYMBOL_VALUE (prev);
+             else
+               sym = global_sym_chain[hash];
+           }
+         else
+           {
+             prev = sym;
+             sym = (struct symbol *) SYMBOL_VALUE (sym);
+           }
+       }
+    }
+}
+
+/*
+ * Read in a defined section of a specific object file's symbols.
+ *
+ * DESC is the file descriptor for the file, positioned at the
+ * beginning of the symtab
+ * STRINGTAB is a pointer to the files string
+ * table, already read in
+ * SYM_OFFSET is the offset within the file of
+ * the beginning of the symbols we want to read, NUM_SUMBOLS is the
+ * number of symbols to read
+ * TEXT_OFFSET is the offset to be added to
+ * all values of symbols coming in and
+ * TEXT_SIZE is the size of the text segment read in.
+ * OFFSET is a flag which indicates that the value of all of the
+ * symbols should be offset by TEXT_OFFSET (for the purposes of
+ * incremental linking).
+ */
+
+static void
+read_ofile_symtab (desc, stringtab, stringtab_size, sym_offset,
+                  sym_size, text_offset, text_size, offset)
+     int desc;
+     register char *stringtab;
+     int sym_offset;
+     int sym_size;
+     int text_offset;
+     int text_size;
+     int offset;
+{
+  register char *namestring;
+  register struct symbol *sym, *prev;
+  int hash;
+  struct cleanup *old_chain;
+  struct nlist *bufp;
+  unsigned char type;
+#ifdef N_BINCL
+  subfile_stack = 0;
+#endif
+
+  stringtab_global = stringtab;
+  last_source_file = 0;
+
+  symtab_input_desc = desc;
+  symbuf_end = symbuf_idx = 0;
 
-                     used_up = 1;
-                   }
-                 else
-                   {
-                     prev = sym;
-                     sym = (struct symbol *) SYMBOL_VALUE (sym);
-                   }
-               }
-           }
+  /* It is necessary to actually read one symbol *before* the start
+     of this symtab's symbols, because the GCC_COMPILED_FLAG_SYMBOL
+     occurs before the N_SO symbol.
 
-         /* Defined global or text symbol: record as a misc function
-            if it didn't give its address to a debugger symbol above.  */
-         if (type <= (N_TYPE | N_EXT)
-             && type != N_EXT
-             && ! used_up)
-           record_misc_function (namestring, bufp->n_value);
-       }
+     Detecting this in read_dbx_symtab
+     would slow down initial readin, so we look for it here instead.  */
+  if (sym_offset >= sizeof (struct nlist))
+    {
+      lseek (desc, sym_offset - sizeof (struct nlist), L_INCR);
+      fill_symbuf ();
+      bufp = &symbuf[symbuf_idx++];
+
+      if (bufp->n_un.n_strx < 0 || bufp->n_un.n_strx >= stringtab_size)
+       error ("Invalid symbol data: bad string table offset: %d",
+              bufp->n_un.n_strx);
+      namestring = bufp->n_un.n_strx + stringtab;
+
+      processing_gcc_compilation =
+       (bufp->n_type == N_TEXT
+        && !strcmp (namestring, GCC_COMPILED_FLAG_SYMBOL));
+    }
+  else
+    {
+      /* The N_SO starting this symtab is the first symbol, so we
+        better not check the symbol before it.  I'm not this can
+        happen, but it doesn't hurt to check for it.  */
+      lseek(desc, sym_offset, L_INCR);
+      processing_gcc_compilation = 0;
     }
 
-  if (last_source_file)
-    end_symtab (end_of_text_addr);
+  if (symbuf_idx == symbuf_end)
+    fill_symbuf();
+  bufp = &symbuf[symbuf_idx];
+  if ((unsigned char) bufp->n_type != N_SO)
+    fatal("First symbol in segment of executable not a source symbol");
+
+  for (symnum = 0;
+       symnum < sym_size / sizeof(struct nlist);
+       symnum++)
+    {
+      QUIT;                    /* Allow this to be interruptable */
+      if (symbuf_idx == symbuf_end)
+       fill_symbuf();
+      bufp = &symbuf[symbuf_idx++];
+      type = bufp->n_type;
 
-  discard_cleanups (old_chain);
-}
+      if (offset &&
+         (type == N_TEXT || type == N_DATA || type == N_BSS))
+       bufp->n_value += text_offset;
 
+      if (bufp->n_un.n_strx < 0 || bufp->n_un.n_strx >= stringtab_size)
+       error ("Invalid symbol data: bad string table offset: %d",
+              bufp->n_un.n_strx);
+      namestring = bufp->n_un.n_strx + stringtab;
+
+      if (type & N_STAB)
+       process_one_symbol(type, bufp->n_desc,
+                          bufp->n_value, namestring);
+      /* We skip checking for a new .o or -l file; that should never
+         happen in this routine. */
+      else if (type == N_TEXT
+              && !strcmp (namestring, GCC_COMPILED_FLAG_SYMBOL))
+       /* I don't think this code will ever be executed, because
+          the GCC_COMPILED_FLAG_SYMBOL usually is right before
+          the N_SO symbol which starts this source file.
+          However, there is no reason not to accept
+          the GCC_COMPILED_FLAG_SYMBOL anywhere.  */
+       processing_gcc_compilation = 1;
+      else if (type & N_EXT || type == N_TEXT
+#ifdef N_NBTEXT
+              || type == N_NBTEXT
+#endif
+              )
+         /* Global symbol: see if we came across a dbx defintion for
+            a corresponding symbol.  If so, store the value.  Remove
+            syms from the chain when their values are stored, but
+            search the whole chain, as there may be several syms from
+            different files with the same name. */
+         /* This is probably not true.  Since the files will be read
+            in one at a time, each reference to a global symbol will
+            be satisfied in each file as it appears. So we skip this
+            section. */
+       &stringtab_global;      /* For debugger; am I right? */
+    }
+  end_symtab (text_offset + text_size);
+}
+\f
 static int
 hashname (name)
      char *name;
@@ -1660,29 +3184,19 @@ process_one_symbol (type, desc, value, name)
      char *name;
 {
   register struct context_stack *new;
+  char *colon_pos;
 
   /* Something is wrong if we see real data before
      seeing a source file name.  */
 
   if (last_source_file == 0 && type != N_SO)
     {
-#ifdef N_NSYMS
-      /* This code is used on Ultrix; ignore this sym.  */
-      if (type == N_NSYMS)
-       return;
-#endif
-
-      if (type == N_ENTRY)
-       /* This code appears in libraries on Gould machines.  */
-       return;
-
-      if (type == N_SLINE && desc == -1)
-       /* This code is used by the Sun4 coimpiler; ignore it.  */
+      /* Currently this ignores N_ENTRY on Gould machines, N_NSYM on machines
+        where that code is defined.  */
+      if (IGNORE_SYMBOL (type))
        return;
 
-      /* This should give an aborting error.  */
-      printf ("Invalid symbol data: does not start by identifying a source file.\ntype == %d\n\n", type);
-      return;
+      error ("Invalid symbol data: does not start by identifying a source file.");
     }
 
   switch (type)
@@ -1693,6 +3207,16 @@ process_one_symbol (type, desc, value, name)
         a new function.  We must process its "name" normally for dbx,
         but also record the start of a new lexical context, and possibly
         also the end of the lexical context for the previous function.  */
+      /* This is not always true.  This type of symbol may indicate a
+         text segment variable.  */
+
+      colon_pos = index (name, ':');
+      if (!colon_pos++
+         || (*colon_pos != 'f' && *colon_pos != 'F'))
+       {
+         define_symbol (value, name, desc);
+         break;
+       }
 
       within_function = 1;
       if (context_stack_depth > 0)
@@ -1721,10 +3245,10 @@ process_one_symbol (type, desc, value, name)
       if (context_stack_depth == context_stack_size)
        {
          context_stack_size *= 2;
-         context_stack
-           = (struct context_stack *) xrealloc (context_stack,
-                                                context_stack_size
-                                                * sizeof (struct context_stack));
+         context_stack = (struct context_stack *)
+           xrealloc (context_stack,
+                     (context_stack_size
+                      * sizeof (struct context_stack)));
        }
 
       new = &context_stack[context_stack_depth++];
@@ -1738,11 +3262,19 @@ process_one_symbol (type, desc, value, name)
 
     case N_RBRAC:
       /* This "symbol" just indicates the end of an inner lexical
-        context that was started with N_RBRAC.  */
+        context that was started with N_LBRAC.  */
       new = &context_stack[--context_stack_depth];
       if (desc != new->depth)
        error ("Invalid symbol data: N_LBRAC/N_RBRAC symbol mismatch, symtab pos %d.", symnum);
-      local_symbols = new->locals;
+
+      /* Can only use new->locals as local symbols here if we're in
+         gcc or on a machine that puts them before the lbrack.  */
+      /* Some native compilers put the variable decls inside of an
+         LBRAC/RBRAC block.  */
+#ifdef VARIABLES_INSIDE_BLOCK
+      if (processing_gcc_compilation)
+#endif
+       local_symbols = new->locals;
 
       /* If this is not the outermost LBRAC...RBRAC pair in the
         function, its local symbols preceded it, and are the ones
@@ -1750,10 +3282,16 @@ process_one_symbol (type, desc, value, name)
 
         If this is the outermost LBRAC...RBRAC pair, there is no
         need to do anything; leave the symbols that preceded it
-        to be attached to the function's own block.  */
+        to be attached to the function's own block.  However, if
+        it is so, we need to indicate that we just moved outside
+        of the function.  */
+#ifdef VARIABLES_INSIDE_BLOCK
+      if (local_symbols && context_stack_depth > processing_gcc_compilation)
+#else
       if (local_symbols && context_stack_depth > 1)
+#endif
        {
-         /* Muzzle a compiler bug that makes end > start.  */
+         /* Muzzle a compiler bug that makes end < start.  */
          if (new->start_addr > value)
            new->start_addr = value;
          /* Make a block for the local symbols within.  */
@@ -1761,9 +3299,18 @@ process_one_symbol (type, desc, value, name)
                        new->start_addr + last_source_start_addr,
                        value + last_source_start_addr);
        }
+      else
+       {
+         within_function = 0;
+       }
+#ifdef VARIABLES_INSIDE_BLOCK
+      /* gcc: normal.  pcc: now pop locals of block just finished.  */
+      if (!processing_gcc_compilation)
+       local_symbols = new->locals;
+#endif
       break;
 
-    case N_FN:
+    case N_FN | N_EXT:
       /* This kind of symbol supposedly indicates the start
         of an object file.  In fact this type does not appear.  */
       break;
@@ -1773,6 +3320,14 @@ process_one_symbol (type, desc, value, name)
         for one source file.
         Finish the symbol table of the previous source file
         (if any) and start accumulating a new symbol table.  */
+#ifdef PCC_SOL_BROKEN
+      /* pcc bug, occasionally puts out SO for SOL.  */
+      if (context_stack_depth > 0)
+       {
+         start_subfile (name);
+         break;
+       }
+#endif
       if (last_source_file)
        end_symtab (value);
       start_symtab (name, value);
@@ -1810,7 +3365,36 @@ process_one_symbol (type, desc, value, name)
       break;
 
     case N_BCOMM:
+      if (common_block)
+       error ("Invalid symbol data: common within common at symtab pos %d",
+              symnum);
+      common_block = local_symbols;
+      common_block_i = local_symbols ? local_symbols->nsyms : 0;
+      break;
+
     case N_ECOMM:
+      /* Symbols declared since the BCOMM are to have the common block
+        start address added in when we know it.  common_block points to
+        the first symbol after the BCOMM in the local_symbols list;
+        copy the list and hang it off the symbol for the common block name
+        for later fixup.  */
+      {
+       int i;
+       struct pending *link = local_symbols;
+       struct symbol *sym =
+         (struct symbol *) xmalloc (sizeof (struct symbol));
+       bzero (sym, sizeof *sym);
+       SYMBOL_NAME (sym) = savestring (name, strlen (name));
+       SYMBOL_CLASS (sym) = LOC_BLOCK;
+       SYMBOL_NAMESPACE (sym) = (enum namespace)
+         copy_pending (local_symbols, common_block_i, common_block);
+       i = hashname (SYMBOL_NAME (sym));
+       SYMBOL_VALUE (sym) = (int) global_sym_chain[i];
+       global_sym_chain[i] = sym;
+       common_block = 0;
+       break;
+      }
+
     case N_ECOML:
     case N_LENG:
       break;
@@ -1821,7 +3405,52 @@ process_one_symbol (type, desc, value, name)
     }
 }
 \f
-/************************ READ_ADDL_SYM() ***********************************/
+/* This function was added for C++ functionality.  I presume that it
+   condenses the bunches formed by reading in an additional .o file
+   (incremental linking). */
+
+static void
+condense_addl_misc_bunches ()
+{
+  register int i, j;
+  register struct misc_bunch *bunch;
+#ifdef NAMES_HAVE_UNDERSCORE
+  int offset = 1;
+#else
+  int offset = 0;
+#endif
+
+  misc_function_vector
+    = (struct misc_function *)  xrealloc (misc_function_vector,
+                                         (misc_count + misc_function_count) * sizeof (struct misc_function));
+
+  j = misc_function_count;
+  bunch = misc_bunch;
+  while (bunch)
+    {
+      for (i = 0; i < misc_bunch_index; i++)
+       {
+         misc_function_vector[j] = bunch->contents[i];
+         misc_function_vector[j].name
+           = concat (misc_function_vector[j].name
+                     + (misc_function_vector[j].name[0] == '_' ? offset : 0),
+                     "", "");
+         j++;
+       }
+      bunch = bunch->next;
+      misc_bunch_index = MISC_BUNCH_SIZE;
+    }
+
+  misc_function_count += misc_count;
+
+  /* Sort the misc functions by address.  */
+
+  qsort (misc_function_vector, misc_function_count,
+        sizeof (struct misc_function),  compare_misc_functions);
+}
+\f
+
+/* Read in another .o file and create a symtab entry for it.*/
 
 static void
 read_addl_syms (desc, stringtab, nlistlen, text_addr, text_size)
@@ -1835,7 +3464,6 @@ read_addl_syms (desc, stringtab, nlistlen, text_addr, text_size)
   register char *namestring;
   register struct symbol *sym, *prev;
   int hash;
-  int num_object_files = 0;
 
 #ifdef N_BINCL
   subfile_stack = 0;
@@ -1850,20 +3478,20 @@ read_addl_syms (desc, stringtab, nlistlen, text_addr, text_size)
   for (symnum = 0; symnum < nlistlen; symnum++)
     {
       struct nlist *bufp;
-      int type;
+      unsigned char type;
 
       QUIT;    /* allow this to be interruptable */
       if (symbuf_idx == symbuf_end)
        fill_symbuf ();
       bufp = &symbuf[symbuf_idx++];
       type = bufp->n_type & N_TYPE;
-      namestring = bufp->n_un.n_strx ? bufp->n_un.n_strx + stringtab : "";
+      namestring = bufp->n_un.n_strx + stringtab;
 
       if( (type == N_TEXT) || (type == N_DATA) || (type == N_BSS) )
        {
          /* Relocate this file's symbol table information
             to the address it has been loaded into.  */
-         bufp->n_value += text_addr;        
+         bufp->n_value += text_addr;
        }
 
       type = bufp->n_type;
@@ -1883,10 +3511,8 @@ read_addl_syms (desc, stringtab, nlistlen, text_addr, text_size)
 #endif
                )
               && (!strcmp (namestring + strlen (namestring) - 2, ".o"))
-              || ! strcmp (namestring, "-l", 2))
+              || ! strncmp (namestring, "-l", 2))
        {
-         if (num_object_files++ == 1)
-           first_object_file_end = bufp->n_value;
          if (last_source_file)
            end_symtab (bufp->n_value);
        }
@@ -1903,6 +3529,13 @@ read_addl_syms (desc, stringtab, nlistlen, text_addr, text_size)
              && !strcmp (namestring, "_etext"))
            end_of_text_addr = bufp->n_value;
 
+#if 0
+         /* 25 Sep 89: The following seems to be stolen from
+            read_ofile_symtab, and is wrong here (i.e. there was no
+            first pass for add-file symbols).  */
+         /* This shouldn't be necessary, as we now do all of this work
+            in scan_global syms and all misc functions should have been
+            recorded on the first pass.  */
          /* Global symbol: see if we came across a dbx definition
             for a corresponding symbol.  If so, store the value.
             Remove syms from the chain when their values are stored,
@@ -1937,7 +3570,10 @@ read_addl_syms (desc, stringtab, nlistlen, text_addr, text_size)
                      else
                        global_sym_chain[hash]
                          = (struct symbol *) SYMBOL_VALUE (sym);
-                     SYMBOL_VALUE (sym) = bufp->n_value;
+                     if (SYMBOL_CLASS (sym) == LOC_BLOCK)
+                       fix_common_block (sym, bufp->n_value);
+                     else
+                       SYMBOL_VALUE (sym) = bufp->n_value;
                      if (prev)
                        sym = (struct symbol *) SYMBOL_VALUE (prev);
                      else
@@ -1958,7 +3594,9 @@ read_addl_syms (desc, stringtab, nlistlen, text_addr, text_size)
          if (type <= (N_TYPE | N_EXT)
              && type != N_EXT
              && ! used_up)
-           record_misc_function (namestring, bufp->n_value);
+           record_misc_function (namestring, bufp->n_value,
+                                 bufp->n_type);
+#endif /* 0 */
        }
     }
 
@@ -1968,69 +3606,35 @@ read_addl_syms (desc, stringtab, nlistlen, text_addr, text_size)
   fclose (stream);
 }
 
-/***************************** CONDENSE_ADDL_MISC_BUNCHES *******************/
-
-static void
-condense_addl_misc_bunches ()
-{ 
-  register int i, j;
-  register struct misc_bunch *bunch;
-#ifdef NAMES_HAVE_UNDERSCORE
-  int offset = 1;
-#else
-  int offset = 0;
-#endif
-
-  misc_function_vector
-    = (struct misc_function *)  xrealloc (misc_function_vector,
-                                         (misc_count + misc_function_count) * sizeof (struct misc_function));
-
-  j = misc_function_count;
-  bunch = misc_bunch;
-  while (bunch)
-    {
-      for (i = 0; i < misc_bunch_index; i++)
-       {
-         misc_function_vector[j] = bunch->contents[i];
-         misc_function_vector[j].name
-           = concat (misc_function_vector[j].name
-                     + (misc_function_vector[j].name[0] == '_' ? offset : 0),
-                     "", "");
-         j++;
-       }
-      bunch = bunch->next;
-      misc_bunch_index = MISC_BUNCH_SIZE;
-    }
-
-  misc_function_count += misc_count;
-
-  /* Sort the misc functions by address.  */
-
-  qsort (misc_function_vector, misc_function_count,
-        sizeof (struct misc_function),  compare_misc_functions);
-}
-\f
-/**************************** ADD_FILE_COMMAND() ****************************/
-/* This function allows the addition of incrementally linked object files.  */
+/* C++:
+   This function allows the addition of incrementally linked object files.
+   Since this has a fair amount of code in common with symbol_file_command,
+   it might be worthwhile to consolidate things, as was done with
+   read_dbx_symtab and condense_misc_bunches. */
 
 void
 add_file_command (arg_string)
      char* arg_string;
-{ 
+{
   register int desc;
-  struct exec hdr;
+  DECLARE_FILE_HEADERS;
   struct nlist *nlist;
   char *stringtab;
   long buffer;
   register int val;
   extern void close ();
   struct cleanup *old_chain;
-  char* name;
+  struct symtab *symseg;
+  struct stat statbuf;
+  char *name;
   unsigned text_addr;
 
   if (arg_string == 0)
     error ("add-file takes a file name and an address");
 
+  arg_string = tilde_expand (arg_string);
+  make_cleanup (free, arg_string);
+
   for( ; *arg_string == ' '; arg_string++ );
   name = arg_string;
   for( ; *arg_string && *arg_string != ' ' ; arg_string++ );
@@ -2043,93 +3647,132 @@ add_file_command (arg_string)
 
   dont_repeat ();
 
-  if (query ("add symbol table from filename \"%s\" at text_addr = 0x%x\n", name, text_addr))
-    {
-      desc = open (name, O_RDONLY);
-      if (desc < 0)
-       perror_with_name (name);
+  if (!query ("add symbol table from filename \"%s\" at text_addr = 0x%x\n",
+             name, text_addr))
+    error ("Not confirmed.");
 
-      old_chain = make_cleanup (close, desc);
-      make_cleanup (free_current_contents, &name);
+  desc = open (name, O_RDONLY);
+  if (desc < 0)
+    perror_with_name (name);
 
-      val = myread (desc, &hdr, sizeof hdr);
-      if (val < 0)
-       perror_with_name (name);
+  old_chain = make_cleanup (close, desc);
 
-      if (N_BADMAG (hdr))
-       error ("File \"%s\" has a bad header.", name);
+  READ_FILE_HEADERS (desc, name);
 
-      if (hdr.a_syms == 0)
-       {
-         printf ("%s does not have a symbol-table.\n", name);
-         fflush (stdout);
-         return;
-       }
+  if (NUMBER_OF_SYMBOLS == 0)
+    {
+      printf ("%s does not have a symbol-table.\n", name);
+      fflush (stdout);
+      return;
+    }
 
-      /* Now read the string table, all at once.  */
-      val = lseek (desc, N_SYMOFF (hdr) + hdr.a_syms, 0);
-      if (val < 0)
-       perror_with_name (name);
-      val = myread (desc, &buffer, sizeof buffer);
-      if (val < 0)
-       perror_with_name (name);
+  printf ("Reading symbol data from %s...", name);
+  fflush (stdout);
+
+  /* Now read the string table, all at once.  */
+  val = lseek (desc, STRING_TABLE_OFFSET, 0);
+  if (val < 0)
+    perror_with_name (name);
+  stat (name, &statbuf);
+  READ_STRING_TABLE_SIZE (buffer);
+  if (buffer >= 0 && buffer < statbuf.st_size)
+    {
+#ifdef BROKEN_LARGE_ALLOCA
+      stringtab = (char *) xmalloc (buffer);
+      make_cleanup (free, stringtab);
+#else
       stringtab = (char *) alloca (buffer);
-      bcopy (&buffer, stringtab, sizeof buffer);
-      val = myread (desc, stringtab + sizeof buffer, buffer - sizeof buffer);
-      if (val < 0)
-       perror_with_name (name);
+#endif
+    }
+  else
+    stringtab = NULL;
+  if (stringtab == NULL)
+    error ("ridiculous string table size: %d bytes", buffer);
 
-      /* That puts us at the symsegs.  Read them. ########## Also need other
-        changes if they exist. */
+  /* Usually READ_STRING_TABLE_SIZE will have shifted the file pointer.
+     Occaisionally, it won't.  */
+  val = lseek (desc, STRING_TABLE_OFFSET, 0);
+  if (val < 0)
+    perror_with_name (name);
+  val = myread (desc, stringtab, buffer);
+  if (val < 0)
+    perror_with_name (name);
 
-      /* Position to read the symbol table.  Do not read it all at once. */
-      val = lseek (desc, N_SYMOFF (hdr), 0);
-      if (val < 0)
-       perror_with_name (name);
+  /* Symsegs are no longer supported by GDB.  Setting symseg_chain to
+     0 is easier than finding all the symseg code and eliminating it.  */
+  symseg_chain = 0;
 
-      printf ("Reading symbol data from %s...", name);
-      fflush (stdout);
+  /* Position to read the symbol table.  Do not read it all at once. */
+  val = lseek (desc, SYMBOL_TABLE_OFFSET, 0);
+  if (val < 0)
+    perror_with_name (name);
 
-      init_misc_functions ();
-      make_cleanup (discard_misc_bunches, 0);
-      init_header_files ();
-      make_cleanup (free_header_files, 0);
+  init_misc_functions ();
+  make_cleanup (discard_misc_bunches, 0);
+  init_header_files ();
+  make_cleanup (free_header_files, 0);
+  free_pendings = 0;
+  pending_blocks = 0;
+  file_symbols = 0;
+  global_symbols = 0;
+  make_cleanup (really_free_pendings, 0);
 
-      read_addl_syms (desc, stringtab, hdr.a_syms / sizeof(struct nlist),
-                     text_addr, hdr.a_text) ;
+  read_addl_syms (desc, stringtab, NUMBER_OF_SYMBOLS, text_addr,
+                 SIZE_OF_TEXT_SEGMENT);
 
-      /* Sort symbols alphabetically within each block.  */
 
-      sort_syms ();
+  /* Sort symbols alphabetically within each block.  */
 
-      /* Go over the all misc functions and install them in vector.  */
+  sort_syms ();
 
-      condense_addl_misc_bunches ();
+  /* Go over the misc functions and install them in vector.  */
 
-      /* Don't allow char * to have a typename (else would get caddr_t.)  */
+  condense_addl_misc_bunches (1);
 
-      TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0;
+  /* Don't allow char * to have a typename (else would get caddr_t.)  */
 
-      /* Make a default for file to list.  */
+  TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0;
 
-      select_source_symtab (symtab_list);
+  do_cleanups (old_chain);
 
-      do_cleanups (old_chain);
+  /* Free the symtabs made by read_symsegs, but not their contents,
+     which have been copied into symtabs on symtab_list.  */
+  while (symseg_chain)
+    {
+      register struct symtab *s = symseg_chain->next;
+      free (symseg_chain);
+      symseg_chain = s;
+    }
 
-      /* Free the symtabs made by read_symsegs, but not their contents,
-        which have been copied into symtabs on symtab_list.  */
-      while (symseg_chain)
-       {
-         register struct symtab *s = symseg_chain->next;
-         free (symseg_chain);
-         symseg_chain = s;
-       }
+  printf ("done.\n");
+  fflush (stdout);
+}
+\f
+/* Read a number by which a type is referred to in dbx data,
+   or perhaps read a pair (FILENUM, TYPENUM) in parentheses.
+   Just a single number N is equivalent to (0,N).
+   Return the two numbers by storing them in the vector TYPENUMS.
+   TYPENUMS will then be used as an argument to dbx_lookup_type.  */
 
-      printf ("done.\n");
-      fflush (stdout);
+static void
+read_type_number (pp, typenums)
+     register char **pp;
+     register int *typenums;
+{
+  if (**pp == '(')
+    {
+      (*pp)++;
+      typenums[0] = read_number (pp, ',');
+      typenums[1] = read_number (pp, ')');
+    }
+  else
+    {
+      typenums[0] = 0;
+      typenums[1] = read_number (pp, 0);
     }
-  else error ("Not confirmed.");
 }
+
+
 \f
 static struct symbol *
 define_symbol (value, string, desc)
@@ -2147,6 +3790,10 @@ define_symbol (value, string, desc)
   if (string[0] == 0)
     return 0;
 
+  /* Ignore old-style symbols from cc -go  */
+  if (p == 0)
+    return 0;
+
   SYMBOL_NAME (sym)
     = (char *) obstack_alloc (symbol_obstack, ((p - string) + 1));
   /* Open-coded bcopy--saves function call time.  */
@@ -2166,7 +3813,10 @@ define_symbol (value, string, desc)
 
   /* c is a special case, not followed by a type-number.
      SYMBOL:c=iVALUE for an integer constant symbol.
-     SYMBOL:c=rVALUE for a floating constant symbol.  */
+     SYMBOL:c=rVALUE for a floating constant symbol.
+     SYMBOL:c=eTYPE,INTVALUE for an enum constant symbol.
+        e.g. "b:c=e6,0" for "const b = blob1"
+       (where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;").  */
   if (deftype == 'c')
     {
       if (*p++ != '=')
@@ -2182,14 +3832,30 @@ define_symbol (value, string, desc)
            value = (char *) obstack_alloc (symbol_obstack, sizeof (double));
            bcopy (&d, value, sizeof (double));
            SYMBOL_VALUE_BYTES (sym) = value;
-           SYMBOL_CLASS (sym) = LOC_CONST;
+           SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
          }
          break;
        case 'i':
          {
            SYMBOL_TYPE (sym) = builtin_type_int;
            SYMBOL_VALUE (sym) = atoi (p);
-           SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
+           SYMBOL_CLASS (sym) = LOC_CONST;
+         }
+         break;
+       case 'e':
+         /* SYMBOL:c=eTYPE,INTVALUE for an enum constant symbol.
+            e.g. "b:c=e6,0" for "const b = blob1"
+            (where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;").  */
+         {
+           int typenums[2];
+           
+           read_type_number (&p, typenums);
+           if (*p++ != ',')
+             error ("Invalid symbol data: no comma in enum const symbol");
+           
+           SYMBOL_TYPE (sym) = *dbx_lookup_type (typenums);
+           SYMBOL_VALUE (sym) = atoi (p);
+           SYMBOL_CLASS (sym) = LOC_CONST;
          }
          break;
        default:
@@ -2266,10 +3932,40 @@ define_symbol (value, string, desc)
       SYMBOL_VALUE (sym) = value;
       SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
       add_symbol_to_list (sym, &local_symbols);
-      /* DESC == 0 implies compiled with GCC.
-        In this case, if it says `short', believe it.  */
-      if (desc == 0)
+
+      /* If it's compiled, if it says `short', believe it.  */
+      if (processing_gcc_compilation || BELIEVE_PCC_PROMOTION)
        break;
+
+#if defined(BELIEVE_PCC_PROMOTION_TYPE)
+      /* This macro is defined on machines (e.g. sparc) where
+        we should believe the type of a PCC 'short' argument,
+        but shouldn't believe the address (the address is
+        the address of the corresponding int).  Note that
+        this is only different from the BELIEVE_PCC_PROMOTION
+        case on big-endian machines.
+
+        My guess is that this correction, as opposed to changing
+        the parameter to an 'int' (as done below, for PCC
+        on most machines), is the right thing to do
+        on all machines, but I don't want to risk breaking
+        something that already works.  On most PCC machines,
+        the sparc problem doesn't come up because the calling
+        function has to zero the top bytes (not knowing whether
+        the called function wants an int or a short), so there
+        is no practical difference between an int and a short
+        (except perhaps what happens when the GDB user types
+        "print short_arg = 0x10000;").  */
+      if (SYMBOL_TYPE (sym) == builtin_type_char
+         || SYMBOL_TYPE (sym) == builtin_type_unsigned_char)
+       SYMBOL_VALUE (sym) += 3;
+      if (SYMBOL_TYPE (sym) == builtin_type_short
+         || SYMBOL_TYPE (sym) == builtin_type_unsigned_short)
+       SYMBOL_VALUE (sym) += 2;
+      break;
+
+#else /* no BELIEVE_PCC_PROMOTION_TYPE.  */
+
       /* If PCC says a parameter is a short or a char,
         it is really an int.  */
       if (SYMBOL_TYPE (sym) == builtin_type_char
@@ -2280,16 +3976,18 @@ define_symbol (value, string, desc)
        SYMBOL_TYPE (sym) = builtin_type_unsigned_int;
       break;
 
+#endif /* no BELIEVE_PCC_PROMOTION_TYPE.  */
+
     case 'P':
       SYMBOL_CLASS (sym) = LOC_REGPARM;
-      SYMBOL_VALUE (sym) = value;
+      SYMBOL_VALUE (sym) = STAB_REG_TO_REGNUM (value);
       SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
       add_symbol_to_list (sym, &local_symbols);
       break;
 
     case 'r':
       SYMBOL_CLASS (sym) = LOC_REGISTER;
-      SYMBOL_VALUE (sym) = value;
+      SYMBOL_VALUE (sym) = STAB_REG_TO_REGNUM (value);
       SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
       add_symbol_to_list (sym, &local_symbols);
       break;
@@ -2311,19 +4009,20 @@ define_symbol (value, string, desc)
        TYPE_NAME (SYMBOL_TYPE (sym)) =
          obsavestring (SYMBOL_NAME (sym),
                        strlen (SYMBOL_NAME (sym)));
-      /* C++ vagaries: we may have a type which is derived from
-        a base type which did not have its name defined when the
-        derived class was output.  We fill in the derived class's
-        base part member's name here in that case.  */
-      else if ((TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT
-               || TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_UNION)
-              && TYPE_N_BASECLASSES (SYMBOL_TYPE (sym)))
-       {
-         int i;
-         for (i = TYPE_N_BASECLASSES (SYMBOL_TYPE (sym)); i > 0; i--)
-           if (TYPE_FIELD_NAME (SYMBOL_TYPE (sym), i-1) == 0)
-             TYPE_FIELD_NAME (SYMBOL_TYPE (sym), i-1) = TYPE_NAME (TYPE_BASECLASS (SYMBOL_TYPE (sym), i));
-       }
+       /* C++ vagaries: we may have a type which is derived from
+        a base type which did not have its name defined when the
+        derived class was output.  We fill in the derived class's
+        base part member's name here in that case.  */
+       else if ((TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT
+                || TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_UNION)
+               && TYPE_N_BASECLASSES (SYMBOL_TYPE (sym)))
+        {
+          int i;
+          for (i = TYPE_N_BASECLASSES (SYMBOL_TYPE (sym)); i > 0; i--)
+            if (TYPE_FIELD_NAME (SYMBOL_TYPE (sym), i - 1) == 0)
+              TYPE_FIELD_NAME (SYMBOL_TYPE (sym), i - 1) =
+                TYPE_NAME (TYPE_BASECLASS (SYMBOL_TYPE (sym), i));
+        }
 
       add_symbol_to_list (sym, &file_symbols);
       break;
@@ -2345,7 +4044,6 @@ define_symbol (value, string, desc)
       break;
 
     case 'V':
-    case 'v':
       /* Static symbol of local scope */
       SYMBOL_CLASS (sym) = LOC_STATIC;
       SYMBOL_VALUE (sym) = value;
@@ -2353,36 +4051,84 @@ define_symbol (value, string, desc)
       add_symbol_to_list (sym, &local_symbols);
       break;
 
+    case 'v':
+      /* Reference parameter */
+      SYMBOL_CLASS (sym) = LOC_REF_ARG;
+      SYMBOL_VALUE (sym) = value;
+      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+      add_symbol_to_list (sym, &local_symbols);
+      break;
+
     default:
       error ("Invalid symbol data: unknown symbol-type code `%c' at symtab pos %d.", deftype, symnum);
     }
   return sym;
 }
 \f
-/* Read a number by which a type is referred to in dbx data,
-   or perhaps read a pair (FILENUM, TYPENUM) in parentheses.
-   Just a single number N is equivalent to (0,N).
-   Return the two numbers by storing them in the vector TYPENUMS.
-   TYPENUMS will then be used as an argument to dbx_lookup_type.  */
-
+/* What about types defined as forward references inside of a small lexical
+   scope?  */
+/* Add a type to the list of undefined types to be checked through
+   once this file has been read in.  */
 static void
-read_type_number (pp, typenums)
-     register char **pp;
-     register int *typenums;
+add_undefined_type (type)
+     struct type *type;
 {
-  if (**pp == '(')
+  if (undef_types_length == undef_types_allocated)
     {
-      (*pp)++;
-      typenums[0] = read_number (pp, ',');
-      typenums[1] = read_number (pp, ')');
+      undef_types_allocated *= 2;
+      undef_types = (struct type **)
+       xrealloc (undef_types,
+                 undef_types_allocated * sizeof (struct type *));
     }
-  else
+  undef_types[undef_types_length++] = type;
+}
+
+/* Add here something to go through each undefined type, see if it's
+   still undefined, and do a full lookup if so.  */
+static void
+cleanup_undefined_types ()
+{
+  struct type **type, *ntype;
+  struct symbol *sym;
+
+  for (type = undef_types; type < undef_types + undef_types_length; type++)
     {
-      typenums[0] = 0;
-      typenums[1] = read_number (pp, 0);
+      struct type *ntype = 0;
+      /* Reasonable test to see if it's been defined since.  */
+      if (TYPE_NFIELDS (*type) == 0)
+       {
+         struct pending *ppt;
+         int i;
+         /* Name of the type, without "struct" or "union" */
+         char *typename = TYPE_NAME (*type);
+
+         if (!strncmp (typename, "struct ", 7))
+           typename += 7;
+         if (!strncmp (typename, "union ", 6))
+           typename += 6;
+
+         for (ppt = file_symbols; ppt; ppt = ppt->next)
+           for (i = 0; i < ppt->nsyms; i++)
+             {
+               struct symbol *sym = ppt->symbol[i];
+
+               if (SYMBOL_CLASS (sym) == LOC_TYPEDEF
+                   && SYMBOL_NAMESPACE (sym) == STRUCT_NAMESPACE
+                   && (TYPE_CODE (SYMBOL_TYPE (sym)) ==
+                       TYPE_CODE (*type))
+                   && !strcmp (SYMBOL_NAME (sym), typename))
+                 bcopy (SYMBOL_TYPE (sym), *type, sizeof (struct type));
+             }
+       }
+      else
+       /* It has been defined; don't mark it as a stub.  */
+       TYPE_FLAGS (*type) &= ~TYPE_FLAG_STUB;
     }
+  undef_types_length = 0;
 }
 
+
+\f
 /* Read a dbx type reference or definition;
    return the type that is meant.
    This can be just a number, in which case it references
@@ -2401,40 +4147,140 @@ read_type (pp)
   struct type *type1;
   int typenums[2];
   int xtypenums[2];
+  char *tmpc;
 
-  read_type_number (pp, typenums);
-
-  /* Detect random reference to type not yet defined.
-     Allocate a type object but leave it zeroed.  */
-  if (**pp != '=')
-    return dbx_alloc_type (typenums);
+  /* Read type number if present.  The type number may be omitted.
+     for instance in a two-dimensional array declared with type
+     "ar1;1;10;ar1;1;10;4".  */
+  if ((**pp >= '0' && **pp <= '9')
+      || **pp == '(')
+    {
+      read_type_number (pp, typenums);
+      
+      /* Detect random reference to type not yet defined.
+        Allocate a type object but leave it zeroed.  */
+      if (**pp != '=')
+       return dbx_alloc_type (typenums);
 
-  *pp += 2;
+      *pp += 2;
+    }
+  else
+    {
+      /* 'typenums=' not present, type is anonymous.  Read and return
+        the definition, but don't put it in the type vector.  */
+      typenums[0] = typenums[1] = -1;
+      *pp += 1;
+    }
+      
   switch ((*pp)[-1])
     {
     case 'x':
-      type = dbx_alloc_type (typenums);
-      /* Set the type code according to the following letter.  */
-      switch ((*pp)[0])
+      {
+       enum type_code code;
+
+       /* Used to index through file_symbols.  */
+       struct pending *ppt;
+       int i;
+       
+       /* Name including "struct", etc.  */
+       char *type_name;
+       
+       /* Name without "struct", etc.  */
+       char *type_name_only;
+
        {
-       case 's':
-         TYPE_CODE (type) = TYPE_CODE_STRUCT;
-         break;
-       case 'u':
-         TYPE_CODE (type) = TYPE_CODE_UNION;
-         break;
-       case 'e':
-         TYPE_CODE (type) = TYPE_CODE_ENUM;
-         break;
+         char *prefix;
+         char *from, *to;
+         
+         /* Set the type code according to the following letter.  */
+         switch ((*pp)[0])
+           {
+           case 's':
+             code = TYPE_CODE_STRUCT;
+             prefix = "struct ";
+             break;
+           case 'u':
+             code = TYPE_CODE_UNION;
+             prefix = "union ";
+             break;
+           case 'e':
+             code = TYPE_CODE_ENUM;
+             prefix = "enum ";
+             break;
+           default:
+             error ("Bad type cross reference at symnum: %d.", symnum);
+           }
+         
+         to = type_name = (char *)
+           obstack_alloc (symbol_obstack,
+                          (strlen (prefix) +
+                           ((char *) index (*pp, ':') - (*pp)) + 1));
+       
+         /* Copy the prefix.  */
+         from = prefix;
+         while (*to++ = *from++)
+           ;
+         to--; 
+       
+         type_name_only = to;
+
+         /* Copy the name.  */
+         from = *pp + 1;
+         while ((*to++ = *from++) != ':')
+           ;
+         *--to = '\0';
+         
+         /* Set the pointer ahead of the name which we just read.  */
+         *pp = from;
+       
+         /* Note: for C++, the cross reference may be to a base type which
+            has not yet been seen.  In this case, we skip to the comma,
+            which will mark the end of the base class name.  (The ':'
+            at the end of the base class name will be skipped as well.)
+            But sometimes (ie. when the cross ref is the last thing on
+            the line) there will be no ','.  */
+         from = (char *) index (*pp, ',');
+         if (from)
+           *pp = from;
        }
-      /* Skip the name the cross-ref points to.  */
-      /* Note: for C++, the cross reference may be to a base type which
-        has not yet been seen.  In this case, we skip to the comma,
-        which will mark the end of the base class name.  (The ':'
-        at the end of the base class name will be skipped as well.)  */
-      *pp = (char *) index (*pp, ':') + 1;
-      /* Just allocate the type and leave it zero if nothing known */
-      return dbx_alloc_type (typenums);
+
+       /* Now check to see whether the type has already been declared.  */
+       /* This is necessary at least in the case where the
+          program says something like
+            struct foo bar[5];
+          The compiler puts out a cross-reference; we better find
+          set the length of the structure correctly so we can
+          set the length of the array.  */
+       for (ppt = file_symbols; ppt; ppt = ppt->next)
+         for (i = 0; i < ppt->nsyms; i++)
+           {
+             struct symbol *sym = ppt->symbol[i];
+
+             if (SYMBOL_CLASS (sym) == LOC_TYPEDEF
+                 && SYMBOL_NAMESPACE (sym) == STRUCT_NAMESPACE
+                 && (TYPE_CODE (SYMBOL_TYPE (sym)) == code)
+                 && !strcmp (SYMBOL_NAME (sym), type_name_only))
+               {
+                 obstack_free (symbol_obstack, type_name);
+                 type = SYMBOL_TYPE (sym);
+                 return type;
+               }
+           }
+       
+       /* Didn't find the type to which this refers, so we must
+          be dealing with a forward reference.  Allocate a type
+          structure for it, and keep track of it so we can
+          fill in the rest of the fields when we get the full
+          type.  */
+       type = dbx_alloc_type (typenums);
+       TYPE_CODE (type) = code;
+       TYPE_NAME (type) = type_name;
+
+       TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
+
+       add_undefined_type (type);
+       return type;
+      }
 
     case '0':
     case '1':
@@ -2452,12 +4298,23 @@ read_type (pp)
       type = *dbx_lookup_type (xtypenums);
       if (type == 0)
        type = builtin_type_void;
-      *dbx_lookup_type (typenums) = type;
+      if (typenums[0] != -1)
+       *dbx_lookup_type (typenums) = type;
       break;
-      
+
     case '*':
-      type = dbx_alloc_type (typenums);
-      smash_to_pointer_type (type, read_type (pp));
+      type1 = read_type (pp);
+      if (TYPE_POINTER_TYPE (type1))
+       {
+         type = TYPE_POINTER_TYPE (type1);
+         if (typenums[0] != -1)
+           *dbx_lookup_type (typenums) = type;
+       }
+      else
+       {
+         type = dbx_alloc_type (typenums);
+         smash_to_pointer_type (type, type1);
+       }
       break;
 
     case '@':
@@ -2476,19 +4333,58 @@ read_type (pp)
       }
       break;
 
+    case '#':
+      {
+       struct type *domain = read_type (pp);
+       char c;
+       struct type *return_type;
+       struct type **args;
+
+       if (*(*pp)++ != ',')
+         error ("invalid member type data format, at symtab pos %d.",
+                symnum);
+
+       return_type = read_type (pp);
+       args = read_args (pp, ';');
+       type = dbx_alloc_type (typenums);
+       smash_to_method_type (type, domain, return_type, args);
+      }
+      break;
+
     case '&':
-      type = dbx_alloc_type (typenums);
-      smash_to_reference_type (type, read_type (pp));
+      type1 = read_type (pp);
+      if (TYPE_REFERENCE_TYPE (type1))
+       {
+         type = TYPE_REFERENCE_TYPE (type1);
+         if (typenums[0] != -1)
+           *dbx_lookup_type (typenums) = type;
+       }
+      else
+       {
+         type = dbx_alloc_type (typenums);
+         smash_to_reference_type (type, type1);
+       }
       break;
 
     case 'f':
-      type = dbx_alloc_type (typenums);
-      smash_to_function_type (type, read_type (pp));
+      type1 = read_type (pp);
+      if (TYPE_FUNCTION_TYPE (type1))
+       {
+         type = TYPE_FUNCTION_TYPE (type1);
+         if (typenums[0] != -1)
+           *dbx_lookup_type (typenums) = type;
+       }
+      else
+       {
+         type = dbx_alloc_type (typenums);
+         smash_to_function_type (type, type1);
+       }
       break;
 
     case 'r':
       type = read_range_type (pp, typenums);
-      *dbx_lookup_type (typenums) = type;
+      if (typenums[0] != -1)
+       *dbx_lookup_type (typenums) = type;
       break;
 
     case 'e':
@@ -2509,33 +4405,12 @@ read_type (pp)
       break;
 
     case 'a':
-      /* Define an array type.  */
-      type = dbx_alloc_type (typenums);
+      if (*(*pp)++ != 'r')
+       error ("Invalid symbol data: unrecognized type-code `a%c' %s %d.",
+              (*pp)[-1], "at symtab position", symnum);
 
-      /* dbx expresses array types in terms of a range type for the index,
-        and that range type is specified right inside the array type spec
-        making ar1;MIN;MAX;VALTYPE  */
-      if (!strncmp (*pp, "r1;0;", 5))
-       (*pp) += 5;
-      else if (!strncmp (*pp, "r(0,1);0;", 9))
-       (*pp) += 9;
-      else break;
-
-      TYPE_CODE (type) = TYPE_CODE_ARRAY;
-      /* In Fortran, an upper bound may be T... meaning a parameter specifies
-        the length of the data.  In this case, just pretend the bound is 1.
-        This happens only for array parameters, which are really passed
-        as pointers anyway, and we will translate them into such.  */
-      if (**pp == 'T')
-       {
-         n = 1;
-         while (**pp != ';')
-           (*pp)++;
-       }
-      else
-       n = read_number (pp, ';') + 1;
-      TYPE_TARGET_TYPE (type) = read_type (pp);
-      TYPE_LENGTH (type) = TYPE_LENGTH (TYPE_TARGET_TYPE (type)) * n;
+      type = dbx_alloc_type (typenums);
+      type = read_array_type (pp, type);
       break;
 
     default:
@@ -2604,6 +4479,11 @@ read_struct_type (pp, type)
   struct type *baseclass = NULL;
   int read_possible_virtual_info = 0;
 
+  if (TYPE_MAIN_VARIANT (type) == 0)
+    {
+      TYPE_MAIN_VARIANT (type) = type;
+    }
+
   TYPE_CODE (type) = TYPE_CODE_STRUCT;
 
   /* First comes the total size in bytes.  */
@@ -2614,22 +4494,36 @@ read_struct_type (pp, type)
      will be a '!', followed by the number of base classes derived from.
      Each element in the list contains visibility information,
      the offset of this base class in the derived structure,
-     and then the base type.  */
+     and then the base type. */
   if (**pp == '!')
     {
       int i, n_baseclasses, offset;
       struct type **baseclass_vec;
       struct type *baseclass;
-      int via_public, via_virtual;
+      int via_public;
+
+      /* Nonzero if it is a virtual baseclass, i.e.,
+
+        struct A{};
+        struct B{};
+        struct C : public B, public virtual A {};
+
+        B is a baseclass of C; A is a virtual baseclass for C.  This is a C++
+        2.0 language feature.  */
+      int via_virtual;
+
       *pp += 1;
 
       n_baseclasses = read_number (pp, ',');
       baseclass_vec = (struct type **)
        obstack_alloc (symbol_obstack,
                       (n_baseclasses) * sizeof (struct type **)) - 1;
+
       for (i = 1; i <= n_baseclasses; i++)
        {
-         if (**pp == '\\') *pp = next_symbol_text ();
+         if (**pp == '\\')
+           *pp = next_symbol_text ();
+
          switch (*(*pp)++)
            {
            case '0':
@@ -2639,9 +4533,10 @@ read_struct_type (pp, type)
              via_virtual = 1;
              break;
            default:
-             error ("Invalid symbol data: bad visibility format at symtab pos %d.",
+             error ("Invalid symbol data: bad visibility format at symtab pos %d",
                     symnum);
            }
+
          switch (*(*pp)++)
            {
            case '0':
@@ -2659,6 +4554,15 @@ read_struct_type (pp, type)
          *pp += 1;             /* skip trailing ';' */
          baseclass_vec[i] = lookup_basetype_type (baseclass, offset, via_virtual, via_public);
 
+          /* Since lookup_basetype_type can copy the type,
+            it might copy a stub type (complete with stub flag).
+            If so, we need to add it to the list of undefined types
+            to clean up later.  Even if lookup_basetype_type
+            didn't copy the type, adding it to the undefined list
+            will not do any harm.  */
+          if (TYPE_FLAGS(baseclass_vec[i]) & TYPE_FLAG_STUB)
+            add_undefined_type (baseclass_vec[i]);
+
          /* Make this baseclass visible for structure-printing purposes.  */
          new = (struct nextfield *) alloca (sizeof (struct nextfield));
          new->next = list;
@@ -2682,6 +4586,9 @@ read_struct_type (pp, type)
      The `?' is a placeholder for one of '+' (public visibility),
      '0' (protected visibility), and '-' (private visibility).  */
 
+  /* We better set p right now, in case there are no fields at all...    */
+  p = *pp;
+
   while (**pp != ';')
     {
       int visibility;
@@ -2699,13 +4606,13 @@ read_struct_type (pp, type)
       while (*p != ':') p++;
       list->field.name = obsavestring (*pp, p - *pp);
 
-      /* C++: Check to see if we have hit the methods yet.  */
+      /* C++: Check to see if we have hit the methods yet. */
       if (p[1] == ':')
        break;
 
       *pp = p + 1;
 
-      /* This means we have a visibility for a field coming.  */
+      /* This means we have a visibility for a field coming. */
       if (**pp == '/')
        {
          switch (*++*pp)
@@ -2715,51 +4622,95 @@ read_struct_type (pp, type)
              *pp += 1;
              break;
 
-           case '1':
-             visibility = 1;
-             *pp += 1;
-             break;
+           case '1':
+             visibility = 1;
+             *pp += 1;
+             break;
 
-           case '2':
-             visibility = 2;
-             *pp += 1;
-             break;
-           }
-       }
-      /* else normal dbx-style format.  */
+           case '2':
+             visibility = 2;
+             *pp += 1;
+             break;
+           }
+       }
+       /* else normal dbx-style format.  */
 
       list->field.type = read_type (pp);
       if (**pp == ':')
-       {
-         /* read a static member.  */
-         list->field.bitpos = (long)-1;
-         p = ++(*pp);
-         while (*p != ';') p++;
-         list->field.bitsize = (long) savestring (*pp, p - *pp);
-         *pp = p + 1;
-         nfields++;
-         continue;
-       }
-      else if (**pp != ',')
-       error ("Invalid symbol data: bad structure-type format at symtab pos %d.",
+       {
+         list->field.bitpos = (long)-1;
+         p = ++(*pp);
+         while (*p != ';') p++;
+         list->field.bitsize = (long) savestring (*pp, p - *pp);
+         *pp = p + 1;
+         nfields++;
+         continue;
+       }
+       else if (**pp != ',')
+        error ("Invalid symbol data: bad structure-type format at symtab pos %d.",
               symnum);
       (*pp)++;                 /* Skip the comma.  */
       list->field.bitpos = read_number (pp, ',');
       list->field.bitsize = read_number (pp, ';');
-      /* Detect an unpacked field and mark it as such.
-        dbx gives a bit size for all fields.
-        Note that forward refs cannot be packed,
-        and treat enums as if they had the width of ints.  */
-      if (TYPE_CODE (list->field.type) != TYPE_CODE_INT
-         && TYPE_CODE (list->field.type) != TYPE_CODE_ENUM)
-       list->field.bitsize = 0;
-      if ((list->field.bitsize == 8 * TYPE_LENGTH (list->field.type)
-          || (TYPE_CODE (list->field.type) == TYPE_CODE_ENUM
-              && list->field.bitsize == 8 * TYPE_LENGTH (builtin_type_int)))
-         &&
-         list->field.bitpos % 8 == 0)
-       list->field.bitsize = 0;
-      nfields++;
+
+#if 0
+      /* This is wrong because this is identical to the symbols
+        produced for GCC 0-size arrays.  For example:
+         typedef union {
+          int num;
+          char str[0];
+        } foo;
+        The code which dumped core in such circumstances should be
+        fixed not to dump core.  */
+
+      /* g++ -g0 can put out bitpos & bitsize zero for a static
+        field.  This does not give us any way of getting its
+        class, so we can't know its name.  But we can just
+        ignore the field so we don't dump core and other nasty
+        stuff.  */
+      if (list->field.bitpos == 0
+         && list->field.bitsize == 0)
+       {
+         /* Have we given the warning yet?  */
+         static int warning_given = 0;
+
+         /* Only give the warning once, no matter how many class
+            variables there are.  */
+         if (!warning_given)
+           {
+             warning_given = 1;
+             fprintf_filtered (stderr, "\n\
+Warning:  DBX-style class variable debugging information encountered.\n\
+You seem to have compiled your program with \
+\"g++ -g0\" instead of \"g++ -g\".\n\
+Therefore GDB will not know about your class variables.\n\
+");
+           }
+
+         /* Ignore this field.  */
+         list = list->next;
+       }
+      else
+#endif /* 0 */
+       {
+         /* Detect an unpacked field and mark it as such.
+            dbx gives a bit size for all fields.
+            Note that forward refs cannot be packed,
+            and treat enums as if they had the width of ints.  */
+         if (TYPE_CODE (list->field.type) != TYPE_CODE_INT
+             && TYPE_CODE (list->field.type) != TYPE_CODE_ENUM)
+           list->field.bitsize = 0;
+         if ((list->field.bitsize == 8 * TYPE_LENGTH (list->field.type)
+              || (TYPE_CODE (list->field.type) == TYPE_CODE_ENUM
+                  && (list->field.bitsize
+                      == 8 * TYPE_LENGTH (builtin_type_int))
+                  )
+              )
+             &&
+             list->field.bitpos % 8 == 0)
+           list->field.bitsize = 0;
+         nfields++;
+       }
     }
 
   /* Now come the method fields, as NAME::methods
@@ -2824,7 +4775,12 @@ read_struct_type (pp, type)
              if (**pp == '\\') *pp = next_symbol_text ();
 
              new_sublist->fn_field.type = read_type (pp);
-             new_sublist->fn_field.args = read_args (pp, ':');
+             if (**pp != ':')
+               error ("invalid symtab info for method at symbol number %d.",
+                      symnum);
+             *pp += 1;
+             new_sublist->fn_field.args =
+               TYPE_ARG_TYPES (new_sublist->fn_field.type);
              p = *pp;
              while (*p != ';') p++;
              new_sublist->fn_field.physname = savestring (*pp, p - *pp);
@@ -2832,10 +4788,22 @@ read_struct_type (pp, type)
              new_sublist->visibility = *(*pp)++ - '0';
              if (**pp == '\\') *pp = next_symbol_text ();
 
-             if (*(*pp)++ == '*')
-               new_sublist->fn_field.voffset = read_number (pp, ';') + 1;
-             else
-               new_sublist->fn_field.voffset = 0;
+             switch (*(*pp)++)
+               {
+               case '*':
+                 /* virtual member function, followed by index.  */
+                 new_sublist->fn_field.voffset = read_number (pp, ';') + 1;
+                 break;
+               case '?':
+                 /* static member function.  */
+                 new_sublist->fn_field.voffset = 1;
+                 break;
+               default:
+                 /* **pp == '.'.  */
+                 /* normal member function.  */
+                 new_sublist->fn_field.voffset = 0;
+                 break;
+               }
 
              new_sublist->next = sublist;
              sublist = new_sublist;
@@ -2872,6 +4840,7 @@ read_struct_type (pp, type)
        }
       while (**pp != ';');
     }
+
   *pp += 1;
 
   /* Now create the vector of fields, and record how big it is.  */
@@ -2976,6 +4945,83 @@ read_struct_type (pp, type)
   return type;
 }
 
+/* Read a definition of an array type,
+   and create and return a suitable type object.
+   Also creates a range type which represents the bounds of that
+   array.  */
+static struct type *
+read_array_type (pp, type)
+     register char **pp;
+     register struct type *type;
+{
+  struct type *index_type, *element_type, *range_type;
+  int lower, upper;
+  int adjustable = 0;
+
+  /* Format of an array type:
+     "ar<index type>;lower;upper;<array_contents_type>".  Put code in
+     to handle this.
+
+     Fortran adjustable arrays use Adigits or Tdigits for lower or upper;
+     for these, produce a type like float[][].  */
+
+  index_type = read_type (pp);
+  if (*(*pp)++ != ';')
+    error ("Invalid symbol data; improper format of array type decl.");
+
+  if (!(**pp >= '0' && **pp <= '9'))
+    {
+      *pp += 1;
+      adjustable = 1;
+    }
+  lower = read_number (pp, ';');
+
+  if (!(**pp >= '0' && **pp <= '9'))
+    {
+      *pp += 1;
+      adjustable = 1;
+    }
+  upper = read_number (pp, ';');
+  
+  element_type = read_type (pp);
+
+  if (adjustable)
+    {
+      lower = 0;
+      upper = -1;
+    }
+
+  {
+    /* Create range type.  */
+    range_type = (struct type *) obstack_alloc (symbol_obstack,
+                                               sizeof (struct type));
+    TYPE_CODE (range_type) = TYPE_CODE_RANGE;
+    TYPE_TARGET_TYPE (range_type) = index_type;
+
+    /* This should never be needed.  */
+    TYPE_LENGTH (range_type) = sizeof (int);
+
+    TYPE_NFIELDS (range_type) = 2;
+    TYPE_FIELDS (range_type) =
+      (struct field *) obstack_alloc (symbol_obstack,
+                                     2 * sizeof (struct field));
+    TYPE_FIELD_BITPOS (range_type, 0) = lower;
+    TYPE_FIELD_BITPOS (range_type, 1) = upper;
+  }
+
+  TYPE_CODE (type) = TYPE_CODE_ARRAY;
+  TYPE_TARGET_TYPE (type) = element_type;
+  TYPE_LENGTH (type) = (upper - lower + 1) * TYPE_LENGTH (element_type);
+  TYPE_NFIELDS (type) = 1;
+  TYPE_FIELDS (type) =
+    (struct field *) obstack_alloc (symbol_obstack,
+                                   sizeof (struct field));
+  TYPE_FIELD_TYPE (type, 0) = range_type;
+
+  return type;
+}
+
+
 /* Read a definition of an enumeration type,
    and create and return a suitable type object.
    Also defines the symbols that represent the values of the type.  */
@@ -3003,18 +5049,18 @@ read_enum_type (pp, type)
 
   /* Read the value-names and their values.
      The input syntax is NAME:VALUE,NAME:VALUE, and so on.
-     A semicolon instead of a NAME means the end.  */
-  while (**pp && **pp != ';')
+     A semicolon or comman instead of a NAME means the end.  */
+  while (**pp && **pp != ';' && **pp != ',')
     {
       /* Check for and handle cretinous dbx symbol name continuation!  */
-      if (**pp == '\\') *pp = next_symbol_text ();
+      if (**pp == '\\')        *pp = next_symbol_text ();
 
       p = *pp;
       while (*p != ':') p++;
       name = obsavestring (*pp, p - *pp);
       *pp = p + 1;
       n = read_number (pp, ',');
-      
+
       sym = (struct symbol *) obstack_alloc (symbol_obstack, sizeof (struct symbol));
       bzero (sym, sizeof (struct symbol));
       SYMBOL_NAME (sym) = name;
@@ -3025,7 +5071,8 @@ read_enum_type (pp, type)
       nsyms++;
     }
 
-  (*pp)++;                     /* Skip the semicolon.  */
+  if (**pp == ';')
+    (*pp)++;                   /* Skip the semicolon.  */
 
   /* Now fill in the fields of the type-structure.  */
 
@@ -3038,8 +5085,11 @@ read_enum_type (pp, type)
      The symbols can be found in the symlist that we put them on
      to cause them to be defined.  osyms contains the old value
      of that symlist; everything up to there was defined by us.  */
+  /* Note that we preserve the order of the enum constants, so
+     that in something like "enum {FOO, LAST_THING=FOO}" we print
+     FOO, not LAST_THING.  */
 
-  for (syms = *symlist, n = nsyms; syms; syms = syms->next)
+  for (syms = *symlist, n = 0; syms; syms = syms->next)
     {
       int j = 0;
       if (syms == osyms)
@@ -3048,10 +5098,10 @@ read_enum_type (pp, type)
        {
          struct symbol *sym = syms->symbol[j];
          SYMBOL_TYPE (sym) = type;
-         TYPE_FIELD_NAME (type, --n) = SYMBOL_NAME (sym);
-         TYPE_FIELD_VALUE (type, n) = SYMBOL_VALUE (sym);
-         TYPE_FIELD_BITPOS (type, n) = 0;
-         TYPE_FIELD_BITSIZE (type, n) = 0;
+         TYPE_FIELD_NAME (type, n) = SYMBOL_NAME (sym);
+         TYPE_FIELD_VALUE (type, n) = 0;
+         TYPE_FIELD_BITPOS (type, n) = SYMBOL_VALUE (sym);
+         TYPE_FIELD_BITSIZE (type, n++) = 0;
        }
       if (syms == osyms)
        break;
@@ -3059,7 +5109,10 @@ read_enum_type (pp, type)
 
   return type;
 }
-  
+
+#define        MAX_OF_TYPE(t)  ((1 << (sizeof (t) - 1)) - 1)
+#define MIN_OF_TYPE(t) (-(1 << (sizeof (t) - 1)))
+
 static struct type *
 read_range_type (pp, typenums)
      char **pp;
@@ -3067,12 +5120,15 @@ read_range_type (pp, typenums)
 {
   char *errp = *pp;
   int rangenums[2];
-  int n1, n2, n3;
+  int n2, n3;
+  int self_subrange;
+  struct type *result_type;
 
   /* First comes a type we are a subrange of.
-     In practice it is usually 0, 1 or the type being defined.  */
+     In C it is usually 0, 1 or the type being defined.  */
   read_type_number (pp, rangenums);
-  n1 = rangenums[1];
+  self_subrange = (rangenums[0] == typenums[0] &&
+                  rangenums[1] == typenums[1]);
 
   /* A semicolon should now follow; skip it.  */
   if (**pp == ';')
@@ -3084,8 +5140,7 @@ read_range_type (pp, typenums)
   n3 = read_number (pp, ';');
 
   /* A type defined as a subrange of itself, with bounds both 0, is void.  */
-  if (rangenums[0] == typenums[0] && rangenums[1] == typenums[1]
-      && n2 == 0 && n3 == 0)
+  if (self_subrange && n2 == 0 && n3 == 0)
     return builtin_type_void;
 
   /* If n3 is zero and n2 is not, we want a floating type,
@@ -3114,14 +5169,22 @@ read_range_type (pp, typenums)
        return builtin_type_unsigned_long;
     }
 
-  /* Detect unsigned subranges of int.  Int is normally 1.
-     Note that `char' is usually given bounds of 0 to 127,
-     and would therefore appear unsigned; but it is described
-     as a subrange of itself, so we reject it here.  */
+  /* Special case: char is defined (Who knows why) as a subrange of
+     itself with range 0-127.  */
+  else if (self_subrange && n2 == 0 && n3 == 127)
+    return builtin_type_char;
 
-  else if (n2 == 0 && n1 == 1)
+  /* Assumptions made here: Subrange of self is equivalent to subrange
+     of int.  */
+  else if (n2 == 0
+          && (self_subrange ||
+              *dbx_lookup_type (rangenums) == builtin_type_int))
     {
       /* an unsigned type */
+#ifdef LONG_LONG
+      if (n3 == - sizeof (long long))
+       return builtin_type_unsigned_long_long;
+#endif
       if (n3 == (1 << (8 * sizeof (int))) - 1)
        return builtin_type_unsigned_int;
       if (n3 == (1 << (8 * sizeof (short))) - 1)
@@ -3129,7 +5192,11 @@ read_range_type (pp, typenums)
       if (n3 == (1 << (8 * sizeof (char))) - 1)
        return builtin_type_unsigned_char;
     }
-  else
+#ifdef LONG_LONG
+  else if (n3 == 0 && n2 == -sizeof (long long))
+    return builtin_type_long_long;
+#endif  
+  else if (n2 == -n3 -1)
     {
       /* a signed type */
       if (n3 == (1 << (8 * sizeof (int) - 1)) - 1)
@@ -3141,8 +5208,49 @@ read_range_type (pp, typenums)
       if (n3 == (1 << (8 * sizeof (char) - 1)) - 1)
        return builtin_type_char;
     }
-  error ("Invalid symbol data: range type spec %s at symtab pos %d.",
-        errp - 1, symnum);
+
+  /* We have a real range type on our hands.  Allocate space and
+     return a real pointer.  */
+
+  /* At this point I don't have the faintest idea how to deal with
+     a self_subrange type; I'm going to assume that this is used
+     as an idiom, and that all of them are special cases.  So . . .  */
+  if (self_subrange)
+    error ("Type defined as subrange of itself.");
+
+  result_type = (struct type *) obstack_alloc (symbol_obstack,
+                                              sizeof (struct type));
+  bzero (result_type, sizeof (struct type));
+
+  TYPE_TARGET_TYPE (result_type) = (self_subrange ?
+                                   builtin_type_int :
+                                   *dbx_lookup_type(rangenums));
+
+  /* We have to figure out how many bytes it takes to hold this
+     range type.  I'm going to assume that anything that is pushing
+     the bounds of a long was taken care of above.  */
+  if (n2 >= MIN_OF_TYPE(char) && n3 <= MAX_OF_TYPE(char))
+    TYPE_LENGTH (result_type) = 1;
+  else if (n2 >= MIN_OF_TYPE(short) && n3 <= MAX_OF_TYPE(short))
+    TYPE_LENGTH (result_type) = sizeof (short);
+  else if (n2 >= MIN_OF_TYPE(int) && n3 <= MAX_OF_TYPE(int))
+    TYPE_LENGTH (result_type) = sizeof (int);
+  else if (n2 >= MIN_OF_TYPE(long) && n3 <= MAX_OF_TYPE(long))
+    TYPE_LENGTH (result_type) = sizeof (long);
+  else
+    error ("Ranged type doesn't fit within known sizes.");
+
+  TYPE_LENGTH (result_type) = TYPE_LENGTH (TYPE_TARGET_TYPE (result_type));
+  TYPE_CODE (result_type) = TYPE_CODE_RANGE;
+  TYPE_NFIELDS (result_type) = 2;
+  TYPE_FIELDS (result_type) =
+    (struct field *) obstack_alloc (symbol_obstack,
+                                   2 * sizeof (struct field));
+  bzero (TYPE_FIELDS (result_type), 2 * sizeof (struct field));
+  TYPE_FIELD_BITPOS (result_type, 0) = n2;
+  TYPE_FIELD_BITPOS (result_type, 1) = n3;
+
+  return result_type;
 }
 
 /* Read a number from the string pointed to by *PP.
@@ -3179,7 +5287,7 @@ read_number (pp, end)
     }
   if (end)
     {
-      if (c != end)
+      if (c && c != end)
        error ("Invalid symbol data: invalid character \\%03o at symbol pos %d.", c, symnum);
     }
   else
@@ -3204,10 +5312,11 @@ read_args (pp, end)
       if (**pp != ',')
        error ("Invalid argument list: no ',', at symtab pos %d", symnum);
       *pp += 1;
-      /* Check for and handle cretinous dbx symbol name continuation!  */
+
+      /* Check for and handle cretinous dbx symbol name continuation! */
       if (**pp == '\\')
        *pp = next_symbol_text ();
-      
+
       types[n++] = read_type (pp);
     }
   *pp += 1;                    /* get past `end' (the ':' character) */
@@ -3230,28 +5339,73 @@ read_args (pp, end)
 }
 
 /* This function is really horrible, but to avoid it, there would need
-   to be more filling in of forward references.  */
+   to be more filling in of forward references.  THIS SHOULD BE MOVED OUT
+   OF COFFREAD.C AND DBXREAD.C TO SOME PLACE WHERE IT CAN BE SHARED */
 int
 fill_in_vptr_fieldno (type)
      struct type *type;
 {
   if (TYPE_VPTR_FIELDNO (type) < 0)
-    TYPE_VPTR_FIELDNO (type) = fill_in_vptr_fieldno (TYPE_BASECLASS (type, 1));
+    TYPE_VPTR_FIELDNO (type) =
+      fill_in_vptr_fieldno (TYPE_BASECLASS (type, 1));
   return TYPE_VPTR_FIELDNO (type);
 }
+\f
+/* Copy a pending list, used to record the contents of a common
+   block for later fixup.  */
+static struct pending *
+copy_pending (beg, begi, end)
+    struct pending *beg, *end;
+    int begi;
+{
+  struct pending *new = 0;
+  struct pending *next;
 
-static
-initialize ()
+  for (next = beg; next != 0 && (next != end || begi < end->nsyms);
+       next = next->next, begi = 0)
+    {
+      register int j;
+      for (j = begi; j < next->nsyms; j++)
+       add_symbol_to_list (next->symbol[j], &new);
+    }
+  return new;
+}
+
+/* Add a common block's start address to the offset of each symbol
+   declared to be in it (by being between a BCOMM/ECOMM pair that uses
+   the common block name).  */
+
+static void
+fix_common_block (sym, value)
+    struct symbol *sym;
+    int value;
+{
+  struct pending *next = (struct pending *) SYMBOL_NAMESPACE (sym);
+  for ( ; next; next = next->next)
+    {
+      register int j;
+      for (j = next->nsyms - 1; j >= 0; j--)
+       SYMBOL_VALUE (next->symbol[j]) += value;
+    }
+}
+\f
+void
+_initialize_dbxread ()
 {
   symfile = 0;
+  header_files = (struct header_file *) 0;
+  this_object_header_files = (int *) 0;
+
+  undef_types_allocated = 20;
+  undef_types_length = 0;
+  undef_types = (struct type **) xmalloc (undef_types_allocated *
+                                         sizeof (struct type *));
 
   add_com ("symbol-file", class_files, symbol_file_command,
           "Load symbol table (in dbx format) from executable file FILE.");
 
   add_com ("add-file", class_files, add_file_command,
-           "Load the symbols from FILE, assuming its codes is at TEXT_START.") ;
+           "Load the symbols from FILE, assuming its code is at TEXT_START.") ;
 }
 
-END_FILE
-
 #endif /* READ_DBX_FORMAT */
This page took 0.138893 seconds and 4 git commands to generate.