* complaints.c: New file, code moved from utils.c.
[deliverable/binutils-gdb.git] / gdb / dbxread.c
index 27ffcc1f347883d6cc6a0247079e6cc16d837d82..a8595973cd805c9bfeb64e76e7244076343f9ac5 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 (tiemann@mcc.com)
-
-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!
-*/
-\f
-#include "param.h"
+   Copyright 1986, 1987, 1988, 1989, 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* This module provides three functions: dbx_symfile_init,
+   which initializes to read a symbol file; dbx_new_init, which 
+   discards existing cached information when all symbols are being
+   discarded; and dbx_symfile_read, which reads a symbol table
+   from a file.
+
+   dbx_symfile_read only does the minimum work necessary for letting the
+   user "name" things symbolically; it does not read the entire symtab.
+   Instead, it reads the external and static symbols and puts them in partial
+   symbol tables.  When more extensive information is requested of a
+   file, the corresponding partial symbol table is mutated into a full
+   fledged symbol table by going back and reading the symbols
+   for real.  dbx_psymtab_to_symtab() is the function that does this */
+
+#include "defs.h"
+#include <string.h>
+
+#if defined(USG) || defined(__CYGNUSCLIB__)
+#include <sys/types.h>
+#include <fcntl.h>
+#define L_SET 0
+#define L_INCR 1
+#endif
 
-#ifdef READ_DBX_FORMAT
+#ifdef GDB_TARGET_IS_HPPA
+/* We don't want to use HP-UX's nlists. */
+#define _NLIST_INCLUDED
+#endif
 
-#include <a.out.h>
-#include <stab.h>
-#include <stdio.h>
 #include <obstack.h>
 #include <sys/param.h>
+#ifndef        NO_SYS_FILE
 #include <sys/file.h>
+#endif
 #include <sys/stat.h>
-#include "defs.h"
-#include "initialize.h"
+#include <ctype.h>
 #include "symtab.h"
-
-static void add_symbol_to_list ();
-static void read_dbx_symtab ();
-static void process_one_symbol ();
-static struct type *read_type ();
-static struct type *read_range_type ();
-static struct type *read_enum_type ();
-static struct type *read_struct_type ();
-static long read_number ();
-static void finish_block ();
-static struct blockvector *make_blockvector ();
-static struct symbol *define_symbol ();
-static void start_subfile ();
-static int hashname ();
-static void hash_symsegs ();
-
-extern struct symtab *read_symsegs ();
-extern void free_all_symtabs ();
-
-/* C++ */
-static struct type **read_args ();
-
-/* Macro for number of symbol table entries (in usual a.out format).
-   Some machines override this definition.  */
-#ifndef NUMBER_OF_SYMBOLS
-#define NUMBER_OF_SYMBOLS (hdr.a_syms / sizeof (struct nlist))
+#include "breakpoint.h"
+#include "command.h"
+#include "target.h"
+#include "gdbcore.h"           /* for bfd stuff */
+#include "libbfd.h"            /* FIXME Secret internal BFD stuff (bfd_read) */
+#ifdef GDB_TARGET_IS_HPPA
+#include "libhppa.h"
+#include "syms.h"
+#else
+#include "libaout.h"           /* FIXME Secret internal BFD stuff for a.out */
 #endif
+#include "symfile.h"
+#include "objfiles.h"
+#include "buildsym.h"
+#include "stabsread.h"
+#include "gdb-stabs.h"
+#include "demangle.h"
+#include "language.h"          /* Needed inside partial-stab.h */
+#include "complaints.h"
+
+#include "aout/aout64.h"
+#include "aout/stab_gnu.h"     /* We always use GNU stabs, not native, now */
+
+/* Each partial symbol table entry contains a pointer to private data for the
+   read_symtab() function to use when expanding a partial symbol table entry
+   to a full symbol table entry.
+
+   For dbxread this structure contains the offset within the file symbol table
+   of first local symbol for this file, and length (in bytes) of the section
+   of the symbol table devoted to this file's symbols (actually, the section
+   bracketed may contain more than just this file's symbols).  It also contains
+   further information needed to locate the symbols if they are in an ELF file.
+
+   If ldsymlen is 0, the only reason for this thing's existence is the
+   dependency list.  Nothing else will happen when it is read in.  */
+
+#define LDSYMOFF(p) (((struct symloc *)((p)->read_symtab_private))->ldsymoff)
+#define LDSYMLEN(p) (((struct symloc *)((p)->read_symtab_private))->ldsymlen)
+#define SYMLOC(p) ((struct symloc *)((p)->read_symtab_private))
+#define SYMBOL_SIZE(p) (SYMLOC(p)->symbol_size)
+#define SYMBOL_OFFSET(p) (SYMLOC(p)->symbol_offset)
+#define STRING_OFFSET(p) (SYMLOC(p)->string_offset)
+#define FILE_STRING_OFFSET(p) (SYMLOC(p)->file_string_offset)
+
+struct symloc {
+  int ldsymoff;
+  int ldsymlen;
+  int symbol_size;
+  int symbol_offset;
+  int string_offset;
+  int file_string_offset;
+};
 
-/* Macro for file-offset of symbol table (in usual a.out format).  */
-#ifndef SYMBOL_TABLE_OFFSET
-#define SYMBOL_TABLE_OFFSET N_SYMOFF (hdr)
+/* Macro to determine which symbols to ignore when reading the first symbol
+   of a file.  Some machines override this definition. */
+#ifndef IGNORE_SYMBOL
+/* This code is used on Ultrix systems.  Ignore it */
+#define IGNORE_SYMBOL(type)  (type == (int)N_NSYMS)
 #endif
 
-/* Macro for file-offset of string table (in usual a.out format).  */
-#ifndef STRING_TABLE_OFFSET
-#define STRING_TABLE_OFFSET (N_SYMOFF (hdr) + hdr.a_syms)
+/* 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
 
-/* Macro to store the length of the string table data in INTO.  */
-#ifndef READ_STRING_TABLE_SIZE
-#define READ_STRING_TABLE_SIZE(INTO)           \
-{ val = myread (desc, &INTO, sizeof INTO);     \
-  if (val < 0) perror_with_name (name); }
+/* Macro for name of symbol to indicate a file compiled with gcc2. */
+#ifndef GCC2_COMPILED_FLAG_SYMBOL
+#define GCC2_COMPILED_FLAG_SYMBOL "gcc2_compiled."
 #endif
 
-/* Macro to declare variables to hold the file's header data.  */
-#ifndef DECLARE_FILE_HEADERS
-#define DECLARE_FILE_HEADERS  struct exec hdr
-#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.  */
 
-/* Macro to read the header data from descriptor DESC and validate it.
-   NAME is the file name, for error messages.  */
-#ifndef READ_FILE_HEADERS
-#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); }
+#ifndef BELIEVE_PCC_PROMOTION
+#define BELIEVE_PCC_PROMOTION 0
 #endif
-\f
-START_FILE
-
-/* Chain of symtabs made from reading the file's symsegs.
-   These symtabs do not go into symtab_list themselves,
-   but the information is copied from them when appropriate
-   to make the symtabs that will exist permanently.  */
-
-static struct symtab *symseg_chain;
-
-/* Symseg symbol table for the file whose data we are now processing.
-   It is one of those in symseg_chain.  Or 0, for a compilation that
-   has no symseg.  */
-
-static struct symtab *current_symseg;
-
-/* Name of source file whose symbol data we are now processing.
-   This comes from a symbol of type N_SO.  */
-
-static char *last_source_file;
-
-/* Core address of start of text of current source file.
-   This too comes from the N_SO symbol.  */
-
-static CORE_ADDR last_source_start_addr;
-
-/* End of the text segment of the executable file,
-   as found in the symbol _etext.  */
-
-static CORE_ADDR end_of_text_addr;
-
-/* The list of sub-source-files within the current individual compilation.
-   Each file gets its own symtab with its own linetable and associated info,
-   but they all share one blockvector.  */
-
-struct subfile
-{
-  struct subfile *next;
-  char *name;
-  struct linetable *line_vector;
-  int line_vector_length;
-  int line_vector_index;
-  int prev_line_number;
-};
-
-static struct subfile *subfiles;
-
-static struct subfile *current_subfile;
-
-/* Count symbols as they are processed, for error messages.  */
-
-static int symnum;
-
-/* Vector of types defined so far, indexed by their dbx type numbers.
-   (In newer sun systems, dbx uses a pair of numbers in parens,
-    as in "(SUBFILENUM,NUMWITHINSUBFILE)".  Then these numbers must be
-    translated through the type_translations hash table to get
-    the index into the type vector.)  */
 
-static struct typevector *type_vector;
+/* Nonzero means give verbose info on gdb action.  From main.c.  */
+extern int info_verbose;
 
-/* Number of elements allocated for type_vector currently.  */
+/* The BFD for this file -- implicit parameter to next_symbol_text.  */
 
-static int type_vector_length;
+static bfd *symfile_bfd;
 
-/* Vector of line number information.  */
+/* The size of each symbol in the symbol file (in external form).
+   This is set by dbx_symfile_read when building psymtabs, and by
+   dbx_psymtab_to_symtab when building symtabs.  */
 
-static struct linetable *line_vector;
+static unsigned symbol_size;
 
-/* Index of next entry to go in line_vector_index.  */
+/* This is the offset of the symbol table in the executable file */
+static unsigned symbol_table_offset;
 
-static int line_vector_index;
+/* This is the offset of the string table in the executable file */
+static unsigned string_table_offset;
 
-/* Last line number recorded in the line vector.  */
+/* For elf+stab executables, the n_strx field is not a simple index
+   into the string table.  Instead, each .o file has a base offset
+   in the string table, and the associated symbols contain offsets
+   from this base.  The following two variables contain the base
+   offset for the current and next .o files. */
+static unsigned int file_string_table_offset;
+static unsigned int next_file_string_table_offset;
 
-static int prev_line_number;
+/* Complaints about the symbols we have encountered.  */
 
-/* Number of elements allocated for line_vector currently.  */
+struct complaint lbrac_complaint = 
+  {"bad block start address patched", 0, 0};
 
-static int line_vector_length;
+struct complaint string_table_offset_complaint =
+  {"bad string table offset in symbol %d", 0, 0};
 
-/* 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.  */
+struct complaint unknown_symtype_complaint =
+  {"unknown symbol type %s", 0, 0};
 
-#define HASHSIZE 127
-static struct symbol *global_sym_chain[HASHSIZE];
+struct complaint lbrac_rbrac_complaint =
+  {"block start larger than block end", 0, 0};
 
-/* Record the symbols defined for each context in a list.
-   We don't create a struct block for the context until we
-   know how long to make it.  */
+struct complaint lbrac_unmatched_complaint =
+  {"unmatched N_LBRAC before symtab pos %d", 0, 0};
 
-#define PENDINGSIZE 100
+struct complaint lbrac_mismatch_complaint =
+  {"N_LBRAC/N_RBRAC symbol mismatch at symtab pos %d", 0, 0};
 
-struct pending
-{
-  struct pending *next;
-  int nsyms;
-  struct symbol *symbol[PENDINGSIZE];
-};
-
-/* List of free `struct pending' structures for reuse.  */
-struct pending *free_pendings;
-
-/* Here are the three lists that symbols are put on.  */
-
-struct pending *file_symbols;  /* static at top level, and types */
-
-struct pending *global_symbols;        /* global functions and variables */
-
-struct pending *local_symbols; /* everything local to lexical context */
+struct complaint repeated_header_complaint =
+  {"\"repeated\" header file not previously seen, at symtab pos %d", 0, 0};
 
-/* Stack representing unclosed lexical contexts
-   (that will become blocks, eventually).  */
+struct complaint repeated_header_name_complaint =
+  {"\"repeated\" header file not previously seen, named %s", 0, 0};
+\f
+/* 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 context_stack
+struct header_file_location
 {
-  struct pending *locals;
-  struct pending_block *old_blocks;
-  struct symbol *name;
-  CORE_ADDR start_addr;
-  int depth;
+  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 */
 };
 
-struct context_stack *context_stack;
-
-/* Index of first unused entry in context stack.  */
-int context_stack_depth;
-
-/* Currently allocated size of context stack.  */
+/* The actual list and controling variables */
+static struct header_file_location *bincl_list, *next_bincl;
+static int bincls_allocated;
 
-int context_stack_size;
+/* Local function prototypes */
 
-/* Nonzero if within a function (so symbols should be local,
-   if nothing says specifically).  */
+static void
+free_header_files PARAMS ((void));
 
-int within_function;
+static void
+init_header_files PARAMS ((void));
 
-/* List of blocks already made (lexical contexts already closed).
-   This is used at the end to make the blockvector.  */
+static struct pending *
+copy_pending PARAMS ((struct pending *, int, struct pending *));
 
-struct pending_block
-{
-  struct pending_block *next;
-  struct block *block;
-};
+static struct symtab *
+read_ofile_symtab PARAMS ((struct objfile *, int, int, CORE_ADDR, int, 
+                          struct section_offsets *));
 
-struct pending_block *pending_blocks;
+static void
+dbx_psymtab_to_symtab PARAMS ((struct partial_symtab *));
 
-extern CORE_ADDR first_object_file_end;        /* From blockframe.c */
+static void
+dbx_psymtab_to_symtab_1 PARAMS ((struct partial_symtab *));
 
-/* File name symbols were loaded from.  */
+static void
+read_dbx_symtab PARAMS ((struct section_offsets *, struct objfile *,
+                        CORE_ADDR, int));
 
-static char *symfile;
+static void
+free_bincl_list PARAMS ((struct objfile *));
 
-static int
-xxmalloc (n)
-{
-  int v = malloc (n);
-  if (v == 0)
-    abort ();
-  return v;
-}
+static struct partial_symtab *
+find_corresponding_bincl_psymtab PARAMS ((char *, int));
 
-/* Make a copy of the string at PTR with SIZE characters in the symbol obstack
-   (and add a null character at the end in the copy).
-   Returns the address of the copy.  */
+static void
+add_bincl_to_list PARAMS ((struct partial_symtab *, char *, int));
 
-static char *
-obsavestring (ptr, size)
-     char *ptr;
-     int size;
-{
-  register char *p = (char *) obstack_alloc (symbol_obstack, size + 1);
-  /* Open-coded bcopy--saves function call time.
-     These strings are usually short.  */
-  {
-    register char *p1 = ptr;
-    register char *p2 = p;
-    char *end = ptr + size;
-    while (p1 != end)
-      *p2++ = *p1++;
-  }
-  p[size] = 0;
-  return p;
-}
+static void
+init_bincl_list PARAMS ((int, struct objfile *));
 
-/* Concatenate strings S1, S2 and S3; return the new string.
-   Space is found in the symbol_obstack.  */
+static void
+init_psymbol_list PARAMS ((struct objfile *));
 
 static char *
-obconcat (s1, s2, s3)
-     char *s1, *s2, *s3;
-{
-  register int len = strlen (s1) + strlen (s2) + strlen (s3) + 1;
-  register char *val = (char *) obstack_alloc (symbol_obstack, len);
-  strcpy (val, s1);
-  strcat (val, s2);
-  strcat (val, s3);
-  return val;
-}
-\f
-/* Support for Sun changes to dbx symbol format */
-
-/* For each identified header file, we have a table of types defined
-   in that header file.
-
-   header_files maps header file names to their type tables.
-   It is a vector of n_header_files elements.
-   Each element describes one header file.
-   It contains a vector of types.
-
-   Sometimes it can happen that the same header file produces
-   different results when included in different places.
-   This can result from conditionals or from different
-   things done before including the file.
-   When this happens, there are multiple entries for the file in this table,
-   one entry for each distinct set of results.
-   The entries are distinguished by the INSTANCE field.
-   The INSTANCE field appears in the N_BINCL and N_EXCL symbol table and is
-   used to match header-file references to their corresponding data.  */
-
-struct header_file
-{
-  char *name;                  /* Name of header file */
-  int instance;                        /* Numeric code distinguishing instances
-                                  of one header file that produced
-                                  different results when included.
-                                  It comes from the N_BINCL or N_EXCL.  */
-  struct type **vector;                /* Pointer to vector of types */
-  int length;                  /* Allocated length (# elts) of that vector */
-};
-
-static struct header_file *header_files;
-
-static int n_header_files;
-
-static int n_allocated_header_files;
-
-/* 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
-   and TYPENUM is the number within that header file.
-   TYPENUM is the index within the vector of types for that header file.
+dbx_next_symbol_text PARAMS ((void));
 
-   FILENUM == 1 is special; it refers to the main source of the object file,
-   and not to any header file.  FILENUM != 1 is interpreted by looking it up
-   in the following table, which contains indices in header_files.  */
+static void
+fill_symbuf PARAMS ((bfd *));
 
-static int *this_object_header_files;
+static void
+dbx_symfile_init PARAMS ((struct objfile *));
 
-static int n_this_object_header_files;
+static void
+dbx_new_init PARAMS ((struct objfile *));
 
-static int n_allocated_this_object_header_files;
+static void
+dbx_symfile_read PARAMS ((struct objfile *, struct section_offsets *, int));
 
-/* When a header file is getting special overriding definitions
-   for one source file, record here the header_files index
-   of its normal definition vector.
-   At other times, this is -1.  */
+static void
+dbx_symfile_finish PARAMS ((struct objfile *));
 
-static int header_file_prev_index;
+static void
+record_minimal_symbol PARAMS ((char *, CORE_ADDR, int, struct objfile *));
 
-/* At the start of reading dbx symbols, allocate our tables.  */
+static void
+add_new_header_file PARAMS ((char *, int));
 
 static void
-init_header_files ()
-{
-  n_allocated_header_files = 10;
-  header_files = (struct header_file *) xxmalloc (10 * sizeof (struct header_file));
-  n_header_files = 0;
+add_old_header_file PARAMS ((char *, int));
 
-  n_allocated_this_object_header_files = 10;
-  this_object_header_files = (int *) xxmalloc (10 * sizeof (int));
-}
+static void
+add_this_object_header_file PARAMS ((int));
 
-/* At the end of reading dbx symbols, free our tables.  */
+/* Free up old header file tables */
 
 static void
 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 != NULL)
+    {
+      for (i = 0; i < n_header_files; i++)
+       {
+         free (header_files[i].name);
+       }
+      free ((PTR)header_files);
+      header_files = NULL;
+      n_header_files = 0;
+    }
+  if (this_object_header_files)
+    {
+      free ((PTR)this_object_header_files);
+      this_object_header_files = NULL;
+    }
+  n_allocated_header_files = 0;
+  n_allocated_this_object_header_files = 0;
 }
 
-/* Called at the start of each object file's symbols.
-   Clear out the mapping of header file numbers to header files.  */
+/* Allocate new header file tables */
 
 static void
-new_object_header_files ()
+init_header_files ()
 {
-  /* Leave FILENUM of 0 free for builtin types and this file's types.  */
-  n_this_object_header_files = 1;
-  header_file_prev_index = -1;
+  n_header_files = 0;
+  n_allocated_header_files = 10;
+  header_files = (struct header_file *)
+    xmalloc (10 * sizeof (struct header_file));
+
+  n_allocated_this_object_header_files = 10;
+  this_object_header_files = (int *) xmalloc (10 * sizeof (int));
 }
 
 /* Add header file number I for this object file
@@ -401,7 +324,7 @@ add_this_object_header_file (i)
     {
       n_allocated_this_object_header_files *= 2;
       this_object_header_files
-       = (int *) xrealloc (this_object_header_files,
+       = (int *) xrealloc ((char *) this_object_header_files,
                            n_allocated_this_object_header_files * sizeof (int));
     }
 
@@ -427,8 +350,8 @@ add_old_header_file (name, instance)
        add_this_object_header_file (i);
        return;
       }
-  error ("Invalid symbol data: \"repeated\" header file that hasn't been seen before, at symtab pos %d.",
-        symnum);
+  complain (&repeated_header_complaint, symnum);
+  complain (&repeated_header_name_complaint, name);
 }
 
 /* Add to this file a "new" header file: definitions for its types follow.
@@ -448,130 +371,30 @@ add_new_header_file (name, instance)
      int instance;
 {
   register int i;
-  register struct header_file *p = header_files;
-  header_file_prev_index = -1;
-
-#if 0
-  /* This code was used before I knew about the instance codes.
-     My first hypothesis is that it is not necessary now
-     that instance codes are handled.  */
-
-  /* Has this header file a previous definition?
-     If so, make a new entry anyway so that this use in this source file
-     gets a separate entry.  Later source files get the old entry.
-     Record here the index of the old entry, so that any type indices
-     not previously defined can get defined in the old entry as
-     well as in the new one.  */
-
-  for (i = 0; i < n_header_files; i++)
-    if (!strcmp (p[i].name, name))
-      {
-       header_file_prev_index = i;
-      }
-
-#endif
 
   /* Make sure there is room for one more header file.  */
 
   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 ((char *) 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
-    = (struct type **) xxmalloc (10 * sizeof (struct type *));
-  bzero (header_files[i].vector, 10 * sizeof (struct type *));
+    = (struct type **) xmalloc (10 * sizeof (struct type *));
+  memset (header_files[i].vector, 0, 10 * sizeof (struct type *));
 
   add_this_object_header_file (i);
 }
 
-/* Look up a dbx type-number pair.  Return the address of the slot
-   where the type for that number-pair is stored.
-   The number-pair is in TYPENUMS.
-
-   This can be used for finding the type associated with that pair
-   or for associating a new type with the pair.  */
-
-static struct type **
-dbx_lookup_type (typenums)
-     int typenums[2];
-{
-  register int filenum = typenums[0], index = typenums[1];
-
-  if (filenum < 0 || filenum >= n_this_object_header_files)
-    error ("Invalid symbol data: type number (%d,%d) out of range at symtab pos %d.",
-          filenum, index, symnum);
-
-  if (filenum == 0)
-    {
-      /* Type is defined outside of header files.
-        Find it in this object file's type vector.  */
-      if (index >= type_vector_length)
-       {
-         type_vector_length *= 2;
-         type_vector = (struct typevector *)
-           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);
-       }
-      return &type_vector->type[index];
-    }
-  else
-    {
-      register int real_filenum = this_object_header_files[filenum];
-      register struct header_file *f;
-
-      if (real_filenum >= n_header_files)
-       abort ();
-
-      f = &header_files[real_filenum];
-
-      if (index >= f->length)
-       {
-         f->length *= 2;
-         f->vector = (struct type **)
-           xrealloc (f->vector, f->length * sizeof (struct type *));
-         bzero (&f->vector[f->length / 2],
-                f->length * sizeof (struct type *) / 2);
-       }
-      return &f->vector[index];
-    }
-}
-
-/* Make sure there is a type allocated for type numbers TYPENUMS
-   and return the type object.
-   This can create an empty (zeroed) type object.  */
-
-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;
-
-  /* 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;
-    }
-  return type;
-}
-
 #if 0
 static struct type **
 explicit_lookup_type (real_filenum, index)
@@ -591,1158 +414,1341 @@ explicit_lookup_type (real_filenum, index)
 }
 #endif
 \f
-/* maintain the lists of symbols and blocks */
-
-/* Add a symbol to one of the lists of symbols.  */
 static void
-add_symbol_to_list (symbol, listhead)
-     struct symbol *symbol;
-     struct pending **listhead;
+record_minimal_symbol (name, address, type, objfile)
+     char *name;
+     CORE_ADDR address;
+     int type;
+     struct objfile *objfile;
 {
-  /* We keep PENDINGSIZE symbols in each link of the list.
-     If we don't have a link with room in it, add a new link.  */
-  if (*listhead == 0 || (*listhead)->nsyms == PENDINGSIZE)
-    {
-      register struct pending *link;
-      if (free_pendings)
-       {
-         link = free_pendings;
-         free_pendings = link->next;
-       }
-      else
-       link = (struct pending *) xxmalloc (sizeof (struct pending));
-
-      link->next = *listhead;
-      *listhead = link;
-      link->nsyms = 0;
-    }
+  enum minimal_symbol_type ms_type;
+
+  switch (type &~ N_EXT) {
+    case N_TEXT:  ms_type = mst_text; break;
+    case N_DATA:  ms_type = mst_data; break;
+    case N_BSS:   ms_type = mst_bss;  break;
+    case N_ABS:   ms_type = mst_abs;  break;
+#ifdef N_SETV
+    case N_SETV:  ms_type = mst_data; break;
+#endif
+    default:      ms_type = mst_unknown; break;
+  }
 
-  (*listhead)->symbol[(*listhead)->nsyms++] = symbol;
+  prim_record_minimal_symbol (obsavestring (name, strlen (name), &objfile -> symbol_obstack),
+                            address, ms_type);
 }
+\f
+/* Scan and build partial symbols for a symbol file.
+   We have been initialized by a call to dbx_symfile_init, which 
+   put all the relevant info into a "struct dbx_symfile_info",
+   hung off the objfile structure.
 
-/* At end of reading syms, or in case of quit,
-   really free as many `struct pending's as we can easily find.  */
+   SECTION_OFFSETS contains offsets relative to which the symbols in the
+   various sections are (depending where the sections were actually loaded).
+   MAINLINE is true if we are reading the main symbol
+   table (as opposed to a shared lib or dynamically loaded file).  */
 
 static void
-really_free_pendings ()
+dbx_symfile_read (objfile, section_offsets, mainline)
+     struct objfile *objfile;
+     struct section_offsets *section_offsets;
+     int mainline;     /* FIXME comments above */
 {
-  struct pending *next, *next1;
-  struct pending_block *bnext, *bnext1;
-
-  for (next = free_pendings; next; next = next1)
-    {
-      next1 = next->next;
-      free (next);
-    }
-  free_pendings = 0;
-
-  for (bnext = pending_blocks; bnext; bnext = bnext1)
-    {
-      bnext1 = bnext->next;
-      free (bnext);
-    }
-  pending_blocks = 0;
-
-  for (next = file_symbols; next; next = next1)
-    {
-      next1 = next->next;
-      free (next);
-    }
-  for (next = global_symbols; next; next = next1)
-    {
-      next1 = next->next;
-      free (next);
-    }
-}
+  bfd *sym_bfd;
+  int val;
 
-/* Take one of the lists of symbols and make a block from it.
-   Keep the order the symbols have in the list (reversed from the input file).
-   Put the block on the list of pending blocks.  */
+  sym_bfd = objfile->obfd;
+  val = bfd_seek (objfile->obfd, DBX_SYMTAB_OFFSET (objfile), L_SET);
+  if (val < 0)
+    perror_with_name (objfile->name);
 
-static void
-finish_block (symbol, listhead, old_blocks, start, end)
-     struct symbol *symbol;
-     struct pending **listhead;
-     struct pending_block *old_blocks;
-     CORE_ADDR start, end;
-{
-  register struct pending *next, *next1;
-  register struct block *block;
-  register struct pending_block *pblock;
-  struct pending_block *opblock;
-  register int i;
+  /* If we are reinitializing, or if we have never loaded syms yet, init */
+  if (mainline || objfile->global_psymbols.size == 0 || objfile->static_psymbols.size == 0)
+    init_psymbol_list (objfile);
 
-  /* Count the length of the list of symbols.  */
+#ifdef GDB_TARGET_IS_HPPA
+  symbol_size = obj_dbx_symbol_entry_size (sym_bfd);
+#else
+  symbol_size = DBX_SYMBOL_SIZE (objfile);
+#endif
+  symbol_table_offset = DBX_SYMTAB_OFFSET (objfile);
 
-  for (next = *listhead, i = 0; next; i += next->nsyms, next = next->next);
+  pending_blocks = 0;
+  make_cleanup (really_free_pendings, 0);
 
-  block = (struct block *) obstack_alloc (symbol_obstack,
-                                         sizeof (struct block) + (i - 1) * sizeof (struct symbol *));
+  init_minimal_symbol_collection ();
+  make_cleanup (discard_minimal_symbols, 0);
 
-  /* Copy the symbols into the block.  */
+  /* Now that the symbol table data of the executable file are all in core,
+     process them and define symbols accordingly.  */
 
-  BLOCK_NSYMS (block) = i;
-  for (next = *listhead; next; next = next->next)
-    {
-      register int j;
-      for (j = next->nsyms - 1; j >= 0; j--)
-       BLOCK_SYM (block, --i) = next->symbol[j];
-    }
+  read_dbx_symtab (section_offsets, objfile,
+                  bfd_section_vma  (sym_bfd, DBX_TEXT_SECT (objfile)),
+                  bfd_section_size (sym_bfd, DBX_TEXT_SECT (objfile)));
 
-  BLOCK_START (block) = start;
-  BLOCK_END (block) = end;
-  BLOCK_SUPERBLOCK (block) = 0;        /* Filled in when containing block is made */
+  /* Install any minimal symbols that have been collected as the current
+     minimal symbols for this objfile. */
 
-  /* Put the block in as the value of the symbol that names it.  */
+  install_minimal_symbols (objfile);
 
-  if (symbol)
-    {
-      SYMBOL_BLOCK_VALUE (symbol) = block;
-      BLOCK_FUNCTION (block) = symbol;
-    }
-  else
-    BLOCK_FUNCTION (block) = 0;
+  if (!have_partial_symbols ()) {
+    wrap_here ("");
+    printf_filtered ("(no debugging symbols found)...");
+    wrap_here ("");
+  }
+}
 
-  /* Now "free" the links of the list, and empty the list.  */
+/* Initialize anything that needs initializing when a completely new
+   symbol file is specified (not just adding some symbols from another
+   file, e.g. a shared library).  */
 
-  for (next = *listhead; next; next = next1)
-    {
-      next1 = next->next;
-      next->next = free_pendings;
-      free_pendings = next;
-    }
-  *listhead = 0;
+static void
+dbx_new_init (ignore)
+     struct objfile *ignore;
+{
+  stabsread_new_init ();
+  buildsym_new_init ();
+  init_header_files ();
+}
 
-  /* Install this block as the superblock
-     of all blocks made since the start of this scope
-     that don't have superblocks yet.  */
 
-  opblock = 0;
-  for (pblock = pending_blocks; pblock != old_blocks; pblock = pblock->next)
-    {
-      if (BLOCK_SUPERBLOCK (pblock->block) == 0)
-       BLOCK_SUPERBLOCK (pblock->block) = block;
-      opblock = pblock;
-    }
+/* dbx_symfile_init ()
+   is the dbx-specific initialization routine for reading symbols.
+   It is passed a struct objfile which contains, among other things,
+   the BFD for the file whose symbols are being read, and a slot for a pointer
+   to "private data" which we fill with goodies.
 
-  /* Record this block on the list of all blocks in the file.
-     Put it after opblock, or at the beginning if opblock is 0.
-     This puts the block in the list after all its subblocks.  */
+   We read the string table into malloc'd space and stash a pointer to it.
 
-  /* 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->block = block;
-  if (opblock)
-    {
-      pblock->next = opblock->next;
-      opblock->next = pblock;
-    }
-  else
-    {
-      pblock->next = pending_blocks;
-      pending_blocks = pblock;
-    }
-}
+   Since BFD doesn't know how to read debug symbols in a format-independent
+   way (and may never do so...), we have to do it ourselves.  We will never
+   be called unless this is an a.out (or very similar) file. 
+   FIXME, there should be a cleaner peephole into the BFD environment here.  */
 
-static struct blockvector *
-make_blockvector ()
+static void
+dbx_symfile_init (objfile)
+     struct objfile *objfile;
 {
-  register struct pending_block *next, *next1;
-  register struct blockvector *blockvector;
-  register int i;
+  int val;
+  bfd *sym_bfd = objfile->obfd;
+  char *name = bfd_get_filename (sym_bfd);
+  unsigned char size_temp[4];
+
+  /* Allocate struct to keep track of the symfile */
+  objfile->sym_private = (PTR)
+    xmmalloc (objfile -> md, sizeof (struct dbx_symfile_info));
+
+  /* FIXME POKING INSIDE BFD DATA STRUCTURES */
+#ifdef GDB_TARGET_IS_HPPA
+#define STRING_TABLE_OFFSET  (sym_bfd->origin + obj_dbx_str_filepos (sym_bfd))
+#define SYMBOL_TABLE_OFFSET  (sym_bfd->origin + obj_dbx_sym_filepos (sym_bfd))
+#define HP_STRING_TABLE_OFFSET  (sym_bfd->origin + obj_hp_str_filepos (sym_bfd))
+#define HP_SYMBOL_TABLE_OFFSET  (sym_bfd->origin + obj_hp_sym_filepos (sym_bfd))
+#else
+#define        STRING_TABLE_OFFSET     (sym_bfd->origin + obj_str_filepos (sym_bfd))
+#define        SYMBOL_TABLE_OFFSET     (sym_bfd->origin + obj_sym_filepos (sym_bfd))
+#endif
+  /* FIXME POKING INSIDE BFD DATA STRUCTURES */
 
-  /* Count the length of the list of blocks.  */
+  DBX_SYMFILE_INFO (objfile)->stab_section_info = NULL;
+  DBX_TEXT_SECT (objfile) = bfd_get_section_by_name (sym_bfd, ".text");
+  if (!DBX_TEXT_SECT (objfile))
+    error ("Can't find .text section in symbol file");
 
-  for (next = pending_blocks, i = 0; next; next = next->next, i++);
+#ifdef GDB_TARGET_IS_HPPA
+  HP_SYMCOUNT (objfile) = obj_hp_sym_count (sym_bfd);
+  DBX_SYMCOUNT (objfile) = obj_dbx_sym_count (sym_bfd);
+#else
+  DBX_SYMBOL_SIZE (objfile) = obj_symbol_entry_size (sym_bfd);
+  DBX_SYMCOUNT (objfile) = bfd_get_symcount (sym_bfd);
+#endif
+  DBX_SYMTAB_OFFSET (objfile) = SYMBOL_TABLE_OFFSET;
+
+  /* Read the string table and stash it away in the psymbol_obstack.  It is
+     only needed as long as we need to expand psymbols into full symbols,
+     so when we blow away the psymbol the string table goes away as well.
+     Note that gdb used to use the results of attempting to malloc the
+     string table, based on the size it read, as a form of sanity check
+     for botched byte swapping, on the theory that a byte swapped string
+     table size would be so totally bogus that the malloc would fail.  Now
+     that we put in on the psymbol_obstack, we can't do this since gdb gets
+     a fatal error (out of virtual memory) if the size is bogus.  We can
+     however at least check to see if the size is zero or some negative
+     value. */
+
+#ifdef GDB_TARGET_IS_HPPA
+  DBX_STRINGTAB_SIZE (objfile) = obj_dbx_stringtab_size (sym_bfd);
+  HP_STRINGTAB_SIZE (objfile) = obj_hp_stringtab_size (sym_bfd);
+#else
+  val = bfd_seek (sym_bfd, STRING_TABLE_OFFSET, L_SET);
+  if (val < 0)
+    perror_with_name (name);
 
-  blockvector = (struct blockvector *) obstack_alloc (symbol_obstack, sizeof (struct blockvector) + (i - 1) * sizeof (struct block *));
+  val = bfd_read ((PTR)size_temp, sizeof (long), 1, sym_bfd);
+  if (val < 0)
+    perror_with_name (name);
 
-  /* Copy the blocks into the blockvector.
-     This is done in reverse order, which happens to put
-     the blocks into the proper order (ascending starting address).
-     finish_block has hair to insert each block into the list
-     after its subblocks in order to make sure this is true.  */
+  DBX_STRINGTAB_SIZE (objfile) = bfd_h_get_32 (sym_bfd, size_temp);
+#endif
 
-  BLOCKVECTOR_NBLOCKS (blockvector) = i;
-  for (next = pending_blocks; next; next = next->next)
-    BLOCKVECTOR_BLOCK (blockvector, --i) = next->block;
+  if (DBX_STRINGTAB_SIZE (objfile) <= 0)
+    error ("ridiculous string table size (%d bytes).",
+          DBX_STRINGTAB_SIZE (objfile));
+
+  DBX_STRINGTAB (objfile) =
+    (char *) obstack_alloc (&objfile -> psymbol_obstack,
+                           DBX_STRINGTAB_SIZE (objfile));
+#ifdef GDB_TARGET_IS_HPPA
+  if (HP_STRINGTAB_SIZE (objfile) <= 0)
+    error ("ridiculous string table size (%d bytes).",
+          HP_STRINGTAB_SIZE (objfile));
+
+  HP_STRINGTAB (objfile) =
+    (char *) obstack_alloc (&objfile -> psymbol_obstack,
+                           HP_STRINGTAB_SIZE (objfile));
+#endif
 
-#if 0 /* Now we make the links in the obstack, so don't free them.  */
-  /* Now free the links of the list, and empty the list.  */
+  /* Now read in the string table in one big gulp.  */
 
-  for (next = pending_blocks; next; next = next1)
-    {
-      next1 = next->next;
-      free (next);
-    }
+  val = bfd_seek (sym_bfd, STRING_TABLE_OFFSET, L_SET);
+  if (val < 0)
+    perror_with_name (name);
+  val = bfd_read (DBX_STRINGTAB (objfile), DBX_STRINGTAB_SIZE (objfile), 1,
+                 sym_bfd);
+  if (val != DBX_STRINGTAB_SIZE (objfile))
+    perror_with_name (name);
+#ifdef GDB_TARGET_IS_HPPA
+  val = bfd_seek (sym_bfd, HP_STRING_TABLE_OFFSET, L_SET);
+  if (val < 0)
+    perror_with_name (name);
+  val = bfd_read (HP_STRINGTAB (objfile), HP_STRINGTAB_SIZE (objfile), 1,
+                 sym_bfd);
+  if (val != HP_STRINGTAB_SIZE (objfile))
+    perror_with_name (name);
+#endif
+#ifdef GDB_TARGET_IS_HPPA
+  HP_SYMTAB_OFFSET (objfile) = HP_SYMBOL_TABLE_OFFSET;
 #endif
-  pending_blocks = 0;
-
-  return blockvector;
 }
-\f
-/* Manage the vector of line numbers.  */
-
-static
-record_line (line, pc)
-     int line;
-     CORE_ADDR pc;
-{
-  /* Ignore the dummy line number in libg.o */
-
-  if (line == 0xffff)
-    return;
 
-  /* Make sure line vector is big enough.  */
+/* Perform any local cleanups required when we are done with a particular
+   objfile.  I.E, we are in the process of discarding all symbol information
+   for an objfile, freeing up all memory held for it, and unlinking the
+   objfile struct from the global list of known objfiles. */
 
-  if (line_vector_index + 1 >= line_vector_length)
+static void
+dbx_symfile_finish (objfile)
+     struct objfile *objfile;
+{
+  if (objfile->sym_private != NULL)
     {
-      line_vector_length *= 2;
-      line_vector = (struct linetable *)
-       xrealloc (line_vector,
-                 sizeof (struct linetable) + line_vector_length * sizeof (int));
-      current_subfile->line_vector = line_vector;
+      mfree (objfile -> md, objfile->sym_private);
     }
-
-  /* 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;
+  free_header_files ();
 }
-\f
-/* Start a new symtab for a new source file.
-   This is called when a dbx symbol of type N_SO is seen;
-   it indicates the start of data for one original source file.  */
-
-static void
-start_symtab (name, start_addr)
-     char *name;
-     CORE_ADDR start_addr;
-{
-  register struct symtab *s;
-
-  last_source_file = name;
-  last_source_start_addr = start_addr;
-  file_symbols = 0;
-  global_symbols = 0;
-  within_function = 0;
-
-  /* Context stack is initially empty, with room for 10 levels.  */
-  context_stack
-    = (struct context_stack *) xxmalloc (10 * sizeof (struct context_stack));
-  context_stack_size = 10;
-  context_stack_depth = 0;
 
-  new_object_header_files ();
+\f
+/* Buffer for reading the symbol table entries.  */
+static struct internal_nlist symbuf[4096];
+static int symbuf_idx;
+static int symbuf_end;
 
-  for (s = symseg_chain; s; s = s->next)
-    if (s->ldsymoff == symnum * sizeof (struct nlist))
-      break;
-  current_symseg = s;
-  if (s != 0)
-    return;
+/* Name of last function encountered.  Used in Solaris to approximate
+   object file boundaries.  */
+static char *last_function_name;
 
-  type_vector_length = 160;
-  type_vector = (struct typevector *) xxmalloc (sizeof (struct typevector) + type_vector_length * sizeof (struct type *));
-  bzero (type_vector->type, type_vector_length * sizeof (struct type *));
+/* The address in memory of the string table of the object file we are
+   reading (which might not be the "main" object file, but might be a
+   shared library or some other dynamically loaded thing).  This is set
+   by read_dbx_symtab when building psymtabs, and by read_ofile_symtab 
+   when building symtabs, and is used only by next_symbol_text.  */
+static char *stringtab_global;
 
-  /* Initialize the list of sub source files with one entry
-     for this file (the top-level source file).  */
+/* Refill the symbol table input buffer
+   and set the variables that control fetching entries from it.
+   Reports an error if no data available.
+   This function can read past the end of the symbol table
+   (into the string table) but this does no harm.  */
 
-  subfiles = 0;
-  current_subfile = 0;
-  start_subfile (name);
+static void
+fill_symbuf (sym_bfd)
+     bfd *sym_bfd;
+{
+  int nbytes = bfd_read ((PTR)symbuf, sizeof (symbuf), 1, sym_bfd);
+  if (nbytes < 0)
+    perror_with_name (bfd_get_filename (sym_bfd));
+  else if (nbytes == 0)
+    error ("Premature end of file reading symbol table");
+  symbuf_end = nbytes / symbol_size;
+  symbuf_idx = 0;
 }
+#ifdef GDB_TARGET_IS_HPPA
+/* same as above for the HP symbol table */
 
-/* Handle an N_SOL symbol, which indicates the start of
-   code that came from an included (or otherwise merged-in)
-   source file with a different name.  */
+static struct symbol_dictionary_record hp_symbuf[4096];
+static int hp_symbuf_idx;
+static int hp_symbuf_end;
 
-static void
-start_subfile (name)
-     char *name;
+static int
+fill_hp_symbuf (sym_bfd)
+     bfd *sym_bfd;
 {
-  register struct subfile *subfile;
+  int nbytes = bfd_read ((PTR)hp_symbuf, sizeof (hp_symbuf), 1, sym_bfd);
+  if (nbytes <= 0)
+    error ("error or end of file reading symbol table");
+  hp_symbuf_end = nbytes / sizeof (struct symbol_dictionary_record);
+  hp_symbuf_idx = 0;
+  return 1;
+}
+#endif
 
-  /* Save the current subfile's line vector data.  */
+#define SWAP_SYMBOL(symp, abfd) \
+  { \
+    (symp)->n_strx = bfd_h_get_32(abfd,                        \
+                               (unsigned char *)&(symp)->n_strx);      \
+    (symp)->n_desc = bfd_h_get_16 (abfd,                       \
+                               (unsigned char *)&(symp)->n_desc);      \
+    (symp)->n_value = bfd_h_get_32 (abfd,                      \
+                               (unsigned char *)&(symp)->n_value);     \
+  }
 
-  if (current_subfile)
-    {
-      current_subfile->line_vector_index = line_vector_index;
-      current_subfile->line_vector_length = line_vector_length;
-      current_subfile->prev_line_number = prev_line_number;
-    }
-
-  /* See if this subfile is already known as a subfile of the
-     current main source file.  */
-
-  for (subfile = subfiles; subfile; subfile = subfile->next)
-    {
-      if (!strcmp (subfile->name, name))
-       {
-         line_vector = subfile->line_vector;
-         line_vector_index = subfile->line_vector_index;
-         line_vector_length = subfile->line_vector_length;
-         prev_line_number = subfile->prev_line_number;
-         current_subfile = subfile;
-         return;
-       }
-    }
+/* Invariant: The symbol pointed to by symbuf_idx is the first one
+   that hasn't been swapped.  Swap the symbol at the same time
+   that symbuf_idx is incremented.  */
 
-  /* This subfile is not known.  Add an entry for it.  */
-
-  line_vector_index = 0;
-  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));
-
-  /* Make an entry for this subfile in the list of all subfiles
-     of the current main source file.  */
+/* dbx allows the text of a symbol name to be continued into the
+   next symbol name!  When such a continuation is encountered
+   (a \ at the end of the text of a name)
+   call this function to get the continuation.  */
 
-  subfile = (struct subfile *) xxmalloc (sizeof (struct subfile));
-  subfile->next = subfiles;
-  subfile->name = savestring (name, strlen (name));
-  subfile->line_vector = line_vector;
-  subfiles = subfile;
-  current_subfile = subfile;
+static char *
+dbx_next_symbol_text ()
+{
+  if (symbuf_idx == symbuf_end)
+    fill_symbuf (symfile_bfd);
+  symnum++;
+  SWAP_SYMBOL(&symbuf[symbuf_idx], symfile_bfd);
+  return symbuf[symbuf_idx++].n_strx + stringtab_global
+         + file_string_table_offset;
 }
-
-/* Finish the symbol definitions for one main source file,
-   close off all the lexical contexts for that file
-   (creating struct block's for them), then make the struct symtab
-   for that file and put it in the list of all such.
-
-   END_ADDR is the address of the end of the file's text.  */
+\f
+/* Initializes storage for all of the partial symbols that will be
+   created by read_dbx_symtab and subsidiaries.  */
 
 static void
-end_symtab (end_addr)
-     CORE_ADDR end_addr;
+init_psymbol_list (objfile)
+     struct objfile *objfile;
 {
-  register struct symtab *symtab;
-  register struct blockvector *blockvector;
-  register struct subfile *subfile;
-  register struct linetable *lv;
-  struct subfile *nextsub;
+  /* Free any previously allocated psymbol lists.  */
+  if (objfile -> global_psymbols.list)
+    mfree (objfile -> md, (PTR)objfile -> global_psymbols.list);
+  if (objfile -> static_psymbols.list)
+    mfree (objfile -> md, (PTR)objfile -> static_psymbols.list);
+
+  /* Current best guess is that there are approximately a twentieth
+     of the total symbols (in a debugging file) are global or static
+     oriented symbols */
+#ifdef GDB_TARGET_IS_HPPA
+  objfile -> global_psymbols.size = (DBX_SYMCOUNT (objfile) + 
+                                    HP_SYMCOUNT (objfile)) / 10;
+  objfile -> static_psymbols.size = (DBX_SYMCOUNT (objfile) +
+                                    HP_SYMCOUNT (objfile)) / 10;
+#else
+  objfile -> global_psymbols.size = DBX_SYMCOUNT (objfile) / 10;
+  objfile -> static_psymbols.size = DBX_SYMCOUNT (objfile) / 10;
+#endif
+  objfile -> global_psymbols.next = objfile -> global_psymbols.list = (struct partial_symbol *)
+    xmmalloc (objfile -> md, objfile -> global_psymbols.size * sizeof (struct partial_symbol));
+  objfile -> static_psymbols.next = objfile -> static_psymbols.list = (struct partial_symbol *)
+    xmmalloc (objfile -> md, objfile -> static_psymbols.size * sizeof (struct partial_symbol));
+}
 
-  if (current_symseg != 0)
-    {
-      last_source_file = 0;
-      current_symseg = 0;
-      return;
-    }
+/* Initialize the list of bincls to contain none and have some
+   allocated.  */
 
-  /* Finish the lexical context of the last function in the file;
-     pop the context stack.  */
+static void
+init_bincl_list (number, objfile)
+     int number;
+     struct objfile *objfile;
+{
+  bincls_allocated = number;
+  next_bincl = bincl_list = (struct header_file_location *)
+    xmmalloc (objfile -> md, bincls_allocated * sizeof(struct header_file_location));
+}
 
-  if (context_stack_depth > 0)
-    {
-      register struct context_stack *cstk;
-      context_stack_depth--;
-      cstk = &context_stack[context_stack_depth];
-      /* Make a block for the local symbols within.  */
-      finish_block (cstk->name, &local_symbols, cstk->old_blocks,
-                   cstk->start_addr, end_addr);
-    }
+/* Add a bincl to the list.  */
 
-  /* 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);
-  blockvector = make_blockvector ();
+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 *)
+       xmrealloc (pst->objfile->md, (char *)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;
+}
 
-  current_subfile->line_vector_index = line_vector_index;
+/* Given a name, value pair, find the corresponding
+   bincl in the list.  Return the partial symtab associated
+   with that header_file_location.  */
 
-  /* Now create the symtab objects proper, one for each subfile.  */
-  /* (The main file is one of them.)  */
+static struct partial_symtab *
+find_corresponding_bincl_psymtab (name, instance)
+     char *name;
+     int instance;
+{
+  struct header_file_location *bincl;
 
-  for (subfile = subfiles; subfile; subfile = nextsub)
-    {
-      symtab = (struct symtab *) xxmalloc (sizeof (struct symtab));
-      symtab->free_ptr = 0;
-
-      /* Fill in its components.  */
-      symtab->blockvector = blockvector;
-      type_vector->length = type_vector_length;
-      symtab->typevector = type_vector;
-      symtab->free_code = free_linetable;
-      if (subfile->next == 0)
-       symtab->free_ptr = (char *) type_vector;
-
-      symtab->filename = subfile->name;
-      lv = subfile->line_vector;
-      lv->nitems = subfile->line_vector_index;
-      symtab->linetable = (struct linetable *)
-       xrealloc (lv, sizeof (struct linetable) + lv->nitems * sizeof (int));
-      symtab->nlines = 0;
-      symtab->line_charpos = 0;
-
-      /* Link the new symtab into the list of such.  */
-      symtab->next = symtab_list;
-      symtab_list = symtab;
-
-      nextsub = subfile->next;
-      free (subfile);
-    }
+  for (bincl = bincl_list; bincl < next_bincl; bincl++)
+    if (bincl->instance == instance
+       && !strcmp (name, bincl->name))
+      return bincl->pst;
 
-  type_vector = 0;
-  type_vector_length = -1;
-  line_vector = 0;
-  line_vector_length = -1;
-  last_source_file = 0;
+  return (struct partial_symtab *) 0;
 }
-\f
-#ifdef N_BINCL
 
-/* Handle the N_BINCL and N_EINCL symbol types
-   that act like N_SOL for switching source files
-   (different subfiles, as we call them) within one object file,
-   but using a stack rather than in an arbitrary order.  */
+/* Free the storage allocated for the bincl list.  */
 
-struct subfile_stack
+static void
+free_bincl_list (objfile)
+     struct objfile *objfile;
 {
-  struct subfile_stack *next;
-  char *name;
-  int prev_index;
-};
+  mfree (objfile -> md, (PTR)bincl_list);
+  bincls_allocated = 0;
+}
 
-struct subfile_stack *subfile_stack;
+/* 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.
+   SYMFILE_NAME is the name of the file we are reading from
+   and SECTION_OFFSETS is the set of offsets for the various sections
+   of the file (a set of zeros if the mainline program).  */
 
 static void
-push_subfile ()
+read_dbx_symtab (section_offsets, objfile, text_addr, text_size)
+     struct section_offsets *section_offsets;
+     struct objfile *objfile;
+     CORE_ADDR text_addr;
+     int text_size;
 {
-  register struct subfile_stack *tem
-    = (struct subfile_stack *) xxmalloc (sizeof (struct subfile_stack));
-
-  tem->next = subfile_stack;
-  subfile_stack = tem;
-  if (current_subfile == 0 || current_subfile->name == 0)
-    abort ();
-  tem->name = current_subfile->name;
-  tem->prev_index = header_file_prev_index;
-}
+  register struct internal_nlist *bufp = 0;    /* =0 avoids gcc -Wall glitch */
+  register char *namestring;
+  int nsl;
+  int past_first_source_file = 0;
+  CORE_ADDR last_o_file_start = 0;
+  struct cleanup *old_chain;
+  bfd *abfd;
+#ifdef GDB_TARGET_IS_HPPA
+  /* HP stuff */
+  struct symbol_dictionary_record *hp_bufp;
+  int hp_symnum;
+  /* A hack: the first text symbol in the debugging library */
+  int dbsubc_addr = 0;
+#endif
 
-static char *
-pop_subfile ()
-{
-  register char *name;
-  register struct subfile_stack *link = subfile_stack;
 
-  if (link == 0)
-    abort ();
+  /* End of the text segment of the executable file.  */
+  CORE_ADDR end_of_text_addr;
 
-  name = link->name;
-  subfile_stack = link->next;
-  header_file_prev_index = link->prev_index;
-  free (link);
+  /* Current partial symtab */
+  struct partial_symtab *pst;
 
-  return name;
-}
-#endif /* Have N_BINCL */
-\f
-/* Accumulate the misc functions in bunches of 127.
-   At the end, copy them all into one newly allocated structure.  */
+  /* List of current psymtab's include files */
+  char **psymtab_include_list;
+  int includes_allocated;
+  int includes_used;
 
-#define MISC_BUNCH_SIZE 127
+  /* Index within current psymtab dependency list */
+  struct partial_symtab **dependency_list;
+  int dependencies_used, dependencies_allocated;
 
-struct misc_bunch
-{
-  struct misc_bunch *next;
-  struct misc_function contents[MISC_BUNCH_SIZE];
-};
+  /* FIXME.  We probably want to change stringtab_global rather than add this
+     while processing every symbol entry.  FIXME.  */
+  file_string_table_offset = 0;
+  next_file_string_table_offset = 0;
 
-/* Bunch currently being filled up.
-   The next field points to chain of filled bunches.  */
+#ifdef GDB_TARGET_IS_HPPA
+  stringtab_global = HP_STRINGTAB (objfile);
+#else
+  stringtab_global = DBX_STRINGTAB (objfile);
+#endif
+  
+  pst = (struct partial_symtab *) 0;
 
-static struct misc_bunch *misc_bunch;
+  includes_allocated = 30;
+  includes_used = 0;
+  psymtab_include_list = (char **) alloca (includes_allocated *
+                                          sizeof (char *));
 
-/* Number of slots filled in current bunch.  */
+  dependencies_allocated = 30;
+  dependencies_used = 0;
+  dependency_list =
+    (struct partial_symtab **) alloca (dependencies_allocated *
+                                      sizeof (struct partial_symtab *));
 
-static int misc_bunch_index;
+  old_chain = make_cleanup (free_objfile, objfile);
 
-/* Total number of misc functions recorded so far.  */
+  /* Init bincl list */
+  init_bincl_list (20, objfile);
+  make_cleanup (free_bincl_list, objfile);
 
-static int misc_count;
+  last_source_file = NULL;
 
-static void
-init_misc_functions ()
-{
-  misc_count = 0;
-  misc_bunch = 0;
-  misc_bunch_index = MISC_BUNCH_SIZE;
-}
+#ifdef END_OF_TEXT_DEFAULT
+  end_of_text_addr = END_OF_TEXT_DEFAULT;
+#else
+  end_of_text_addr = text_addr + section_offsets->offsets[SECT_OFF_TEXT]
+                              + text_size;     /* Relocate */
+#endif
 
-static void
-record_misc_function (name, address)
-     char *name;
-     CORE_ADDR address;
-{
-  register struct misc_bunch *new;
+  symfile_bfd = objfile->obfd; /* For next_text_symbol */
+  abfd = objfile->obfd;
+  symbuf_end = symbuf_idx = 0;
+  next_symbol_text_func = dbx_next_symbol_text;
+
+#ifdef GDB_TARGET_IS_HPPA
+  /* On pa machines, the global symbols are all in the regular HP-UX
+     symbol table. Read them in first. */
+
+  hp_symbuf_end = hp_symbuf_idx = 0;
+  bfd_seek (abfd, HP_SYMTAB_OFFSET (objfile), L_SET);
+
+  for (hp_symnum = 0; hp_symnum < HP_SYMCOUNT (objfile); hp_symnum++)
+    {
+      int dbx_type;
+
+      QUIT;
+      if (hp_symbuf_idx == hp_symbuf_end)
+        fill_hp_symbuf (abfd);
+      hp_bufp = &hp_symbuf[hp_symbuf_idx++];
+      switch (hp_bufp->symbol_type)
+        {
+        case ST_SYM_EXT:
+        case ST_ARG_EXT:
+          continue;
+        case ST_CODE:
+        case ST_PRI_PROG:
+        case ST_SEC_PROG:
+        case ST_ENTRY:
+        case ST_MILLICODE:
+          dbx_type = N_TEXT;
+          hp_bufp->symbol_value &= ~3; /* clear out permission bits */
+          break;
+        case ST_DATA:
+          dbx_type = N_DATA;
+          break;
+#ifdef KERNELDEBUG
+        case ST_ABSOLUTE:
+          {
+            extern int kernel_debugging;
+            if (!kernel_debugging)
+              continue;
+            dbx_type = N_ABS;
+            break;
+          }
+#endif
+        default:
+          continue;
+        }
+      /* Use the address of dbsubc to finish the last psymtab. */
+      if (hp_bufp->symbol_type == ST_CODE &&
+          HP_STRINGTAB (objfile)[hp_bufp->name.n_strx] == '_' &&
+          !strcmp (HP_STRINGTAB (objfile) + hp_bufp->name.n_strx, "_dbsubc"))
+        dbsubc_addr = hp_bufp->symbol_value;
+      if (hp_bufp->symbol_scope == SS_UNIVERSAL)
+        {
+          if (hp_bufp->name.n_strx > HP_STRINGTAB_SIZE (objfile))
+            error ("Invalid symbol data; bad HP string table offset: %d",
+                   hp_bufp->name.n_strx);
+          /* A hack, but gets the job done. */
+          if (!strcmp (hp_bufp->name.n_strx + HP_STRINGTAB (objfile), 
+                      "$START$"))
+           objfile -> ei.entry_file_lowpc = hp_bufp->symbol_value;
+          if (!strcmp (hp_bufp->name.n_strx + HP_STRINGTAB (objfile), 
+                      "_sr4export"))
+           objfile -> ei.entry_file_highpc = hp_bufp->symbol_value;
+          record_minimal_symbol (hp_bufp->name.n_strx + HP_STRINGTAB (objfile),
+                                hp_bufp->symbol_value, dbx_type | N_EXT, 
+                                objfile);
+        }
+    }
+  bfd_seek (abfd, DBX_SYMTAB_OFFSET (objfile), L_SET);
+#endif
 
-  if (misc_bunch_index == MISC_BUNCH_SIZE)
+  for (symnum = 0; symnum < DBX_SYMCOUNT (objfile); symnum++)
     {
-      new = (struct misc_bunch *) xxmalloc (sizeof (struct misc_bunch));
-      misc_bunch_index = 0;
-      new->next = misc_bunch;
-      misc_bunch = new;
-    }
-  misc_bunch->contents[misc_bunch_index].name = name;
-  misc_bunch->contents[misc_bunch_index].address = address;
-  misc_bunch_index++;
-  misc_count++;
-}
+      /* Get the symbol for this run and pull out some info */
+      QUIT;    /* allow this to be interruptable */
+      if (symbuf_idx == symbuf_end)
+       fill_symbuf (abfd);
+      bufp = &symbuf[symbuf_idx++];
 
-static int
-compare_misc_functions (fn1, fn2)
-     struct misc_function *fn1, *fn2;
-{
-  /* Return a signed result based on unsigned comparisons
-     so that we sort into unsigned numeric order.  */
-  if (fn1->address < fn2->address)
-    return -1;
-  if (fn1->address > fn2->address)
-    return 1;
-  return 0;
-}
+      /*
+       * Special case to speed up readin.
+       */
+      if (bufp->n_type == (unsigned char)N_SLINE) continue;
 
-static void
-discard_misc_bunches ()
-{
-  register struct misc_bunch *next;
+      SWAP_SYMBOL (bufp, abfd);
 
-  while (misc_bunch)
-    {
-      next = misc_bunch->next;
-      free (misc_bunch);
-      misc_bunch = next;
-    }
-}
+      /* Ok.  There is a lot of code duplicated in the rest of this
+         switch statement (for efficiency reasons).  Since I don't
+         like duplicating code, I will do my penance here, and
+         describe the code which is duplicated:
 
-static void
-condense_misc_bunches ()
-{
-  register int i, j;
-  register struct misc_bunch *bunch;
-#ifdef NAMES_HAVE_UNDERSCORE
-  int offset = 1;
-#else
-  int offset = 0;
+        *) The assignment to namestring.
+        *) The call to strchr.
+        *) 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.  If the string table index is invalid, 
+   give a fake name, and print a single error message per symbol file read,
+   rather than abort the symbol reading or flood the user with messages.  */
+
+/*FIXME: Too many adds and indirections in here for the inner loop.  */
+#define SET_NAMESTRING()\
+  if (((unsigned)bufp->n_strx + file_string_table_offset) >=           \
+      DBX_STRINGTAB_SIZE (objfile)) {                                  \
+    complain (&string_table_offset_complaint, symnum);                 \
+    namestring = "foo";                                                        \
+  } else                                                               \
+    namestring = bufp->n_strx + file_string_table_offset +             \
+                DBX_STRINGTAB (objfile)
+
+#define CUR_SYMBOL_TYPE bufp->n_type
+#define CUR_SYMBOL_VALUE bufp->n_value
+#define DBXREAD_ONLY
+#define START_PSYMTAB(ofile,secoff,fname,low,symoff,global_syms,static_syms)\
+  start_psymtab(ofile, secoff, fname, low, symoff, global_syms, static_syms)
+#define END_PSYMTAB(pst,ilist,ninc,c_off,c_text,dep_list,n_deps)\
+  end_psymtab(pst,ilist,ninc,c_off,c_text,dep_list,n_deps)
+
+#include "partial-stab.h"
+    }
+
+  /* If there's stuff to be cleaned up, clean it up.  */
+#ifndef GDB_TARGET_IS_HPPA
+  if (DBX_SYMCOUNT (objfile) > 0                       /* We have some syms */
+/*FIXME, does this have a bug at start address 0? */
+      && last_o_file_start
+      && objfile -> ei.entry_point < bufp->n_value
+      && objfile -> ei.entry_point >= last_o_file_start)
+    {
+      objfile -> ei.entry_file_lowpc = last_o_file_start;
+      objfile -> ei.entry_file_highpc = bufp->n_value;
+    }
 #endif
 
-  misc_function_vector
-    = (struct misc_function *)
-      xxmalloc (misc_count * sizeof (struct misc_function));
-
-  j = 0;
-  bunch = misc_bunch;
-  while (bunch)
+  if (pst)
     {
-      for (i = 0; i < misc_bunch_index; i++)
-       {
-         misc_function_vector[j] = bunch->contents[i];
-         misc_function_vector[j].name
-           = obconcat (misc_function_vector[j].name
-                       + (misc_function_vector[j].name[0] == '_' ? offset : 0),
-                       "", "");
-         j++;
-       }
-      bunch = bunch->next;
-      misc_bunch_index = MISC_BUNCH_SIZE;
+#ifdef GDB_TARGET_IS_HPPA
+      end_psymtab (pst, psymtab_include_list, includes_used,
+                  symnum * symbol_size, dbsubc_addr,
+                  dependency_list, dependencies_used);
+#else
+      end_psymtab (pst, psymtab_include_list, includes_used,
+                  symnum * symbol_size, end_of_text_addr,
+                  dependency_list, dependencies_used);
+#endif
     }
 
-  misc_function_count = j;
-
-  /* Sort the misc functions by address.  */
-
-  qsort (misc_function_vector, j, sizeof (struct misc_function),
-        compare_misc_functions);
+  free_bincl_list (objfile);
+  discard_cleanups (old_chain);
 }
-\f
-/* Call sort_syms to sort alphabetically
-   the symbols of each block of each symtab.  */
 
-static int
-compare_symbols (s1, s2)
-     struct symbol **s1, **s2;
-{
-  register int namediff;
+/* Allocate and partially fill a partial symtab.  It will be
+   completely filled at the end of the symbol list.
 
-  /* Compare the initial characters.  */
-  namediff = SYMBOL_NAME (*s1)[0] - SYMBOL_NAME (*s2)[0];
-  if (namediff != 0) return namediff;
+   SYMFILE_NAME is the name of the symbol-file we are reading from, and ADDR
+   is the address relative to which its symbols are (incremental) or 0
+   (normal). */
 
-  /* If they match, compare the rest of the names.  */
-  namediff = strcmp (SYMBOL_NAME (*s1), SYMBOL_NAME (*s2));
-  if (namediff != 0) return namediff;
 
-  /* For symbols of the same name, registers should come first.  */
-  return ((SYMBOL_CLASS (*s2) == LOC_REGISTER)
-         - (SYMBOL_CLASS (*s1) == LOC_REGISTER));
+struct partial_symtab *
+start_psymtab (objfile, section_offsets,
+              filename, textlow, ldsymoff, global_syms, static_syms)
+     struct objfile *objfile;
+     struct section_offsets *section_offsets;
+     char *filename;
+     CORE_ADDR textlow;
+     int ldsymoff;
+     struct partial_symbol *global_syms;
+     struct partial_symbol *static_syms;
+{
+  struct partial_symtab *result =
+      start_psymtab_common(objfile, section_offsets,
+                          filename, textlow, global_syms, static_syms);
+
+  result->read_symtab_private = (char *)
+    obstack_alloc (&objfile -> psymbol_obstack, sizeof (struct symloc));
+  LDSYMOFF(result) = ldsymoff;
+  result->read_symtab = dbx_psymtab_to_symtab;
+  SYMBOL_SIZE(result) = symbol_size;
+  SYMBOL_OFFSET(result) = symbol_table_offset;
+  STRING_OFFSET(result) = string_table_offset;
+  FILE_STRING_OFFSET(result) = file_string_table_offset;
+
+  /* If we're handling an ELF file, drag some section-relocation info
+     for this source file out of the ELF symbol table, to compensate for
+     Sun brain death.  This replaces the section_offsets in this psymtab,
+     if successful.  */
+  elfstab_offset_sections (objfile, result);
+
+  return result;
 }
 
-static void
-sort_syms ()
-{
-  register struct symtab *s;
-  int i, nbl;
-  register struct blockvector *bv;
-  register struct block *b;
+/* 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.
 
-  for (s = symtab_list; s; s = s->next)
-    {
-      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
-       }
-    }
-}
-\f
-/* This is the symbol-file command.  Read the file, analyze its symbols,
-   and add a struct symtab to symtab_list.  */
+   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. ***
+   */
 
 void
-symbol_file_command (name)
-     char *name;
+end_psymtab (pst, include_list, num_includes, capping_symbol_offset,
+            capping_text, dependency_list, number_dependencies)
+     struct partial_symtab *pst;
+     char **include_list;
+     int num_includes;
+     int capping_symbol_offset;
+     CORE_ADDR capping_text;
+     struct partial_symtab **dependency_list;
+     int number_dependencies;
+/*     struct partial_symbol *capping_global, *capping_static;*/
 {
-  register int desc;
-  DECLARE_FILE_HEADERS;
-  struct nlist *nlist;
-  char *stringtab;
-  long buffer;
-  register int val;
-  extern void close ();
-  struct cleanup *old_chain;
-  struct symtab *symseg;
-  struct stat statbuf;
-
-  dont_repeat ();
+  int i;
+  struct partial_symtab *p1;
+  struct objfile *objfile = pst -> objfile;
+
+  if (capping_symbol_offset != -1)
+      LDSYMLEN(pst) = capping_symbol_offset - LDSYMOFF(pst);
+  pst->texthigh = capping_text;
+
+  /* Under Solaris, the N_SO symbols always have a value of 0,
+     instead of the usual address of the .o file.  Therefore,
+     we have to do some tricks to fill in texthigh and textlow.
+     The first trick is in partial-stab.h: if we see a static
+     or global function, and the textlow for the current pst
+     is still 0, then we use that function's address for 
+     the textlow of the pst.
+
+     Now, to fill in texthigh, we remember the last function seen
+     in the .o file (also in partial-stab.h).  Also, there's a hack in
+     bfd/elf.c and gdb/elfread.c to pass the ELF st_size field
+     to here via the misc_info field.  Therefore, we can fill in
+     a reliable texthigh by taking the address plus size of the
+     last function in the file.
+
+     Unfortunately, that does not cover the case where the last function
+     in the file is static.  See the paragraph below for more comments
+     on this situation.
+
+     Finally, if we have a valid textlow for the current file, we run
+     down the partial_symtab_list filling in previous texthighs that
+     are still unknown.  */
+
+  if (pst->texthigh == 0 && last_function_name) {
+    char *p;
+    int n;
+    struct minimal_symbol *minsym;
+
+    p = strchr (last_function_name, ':');
+    if (p == NULL)
+      p = last_function_name;
+    n = p - last_function_name;
+    p = alloca (n + 1);
+    strncpy (p, last_function_name, n);
+    p[n] = 0;
+    
+    minsym = lookup_minimal_symbol (p, objfile);
+
+    if (minsym) {
+      pst->texthigh = minsym->address + (int)minsym->info;
+    } else {
+      /* This file ends with a static function, and it's
+        difficult to imagine how hard it would be to track down
+        the elf symbol.  Luckily, most of the time no one will notice,
+        since the next file will likely be compiled with -g, so
+        the code below will copy the first fuction's start address 
+        back to our texthigh variable.  (Also, if this file is the
+        last one in a dynamically linked program, texthigh already
+        has the right value.)  If the next file isn't compiled
+        with -g, then the last function in this file winds up owning
+        all of the text space up to the next -g file, or the end (minus
+        shared libraries).  This only matters for single stepping,
+        and even then it will still work, except that it will single
+        step through all of the covered functions, instead of setting
+        breakpoints around them as it usualy does.  This makes it
+        pretty slow, but at least it doesn't fail.
+
+        We can fix this with a fairly big change to bfd, but we need
+        to coordinate better with Cygnus if we want to do that.  FIXME.  */
+    }
+    last_function_name = NULL;
+  }
 
-  if (name == 0)
-    {
-      if (symtab_list && !query ("Discard symbol table? ", 0))
-       error ("Not confirmed.");
-      free_all_symtabs ();
-      return;
+  /* this test will be true if the last .o file is only data */
+  if (pst->textlow == 0)
+    pst->textlow = pst->texthigh;
+
+  /* If we know our own starting text address, then walk through all other
+     psymtabs for this objfile, and if any didn't know their ending text
+     address, set it to our starting address.  Take care to not set our
+     own ending address to our starting address, nor to set addresses on
+     `dependency' files that have both textlow and texthigh zero.  */
+  if (pst->textlow) {
+    ALL_OBJFILE_PSYMTABS (objfile, p1) {
+      if (p1->texthigh == 0  && p1->textlow != 0 && p1 != pst) {
+       p1->texthigh = pst->textlow;
+       /* if this file has only data, then make textlow match texthigh */
+       if (p1->textlow == 0)
+         p1->textlow = p1->texthigh;
+      }
     }
-
-  if (symtab_list && !query ("Load new symbol table from \"%s\"? ", name))
-    error ("Not confirmed.");
-
-  {
-    char *absolute_name;
-    desc = openp (getenv ("PATH"), 1, name, O_RDONLY, 0, &absolute_name);
-    if (desc < 0)
-      perror_with_name (name);
-    else
-      name = absolute_name;
   }
 
-  old_chain = make_cleanup (close, desc);
-  make_cleanup (free_current_contents, &name);
+  /* End of kludge for patching Solaris textlow and texthigh.  */
+
 
-  READ_FILE_HEADERS (desc, name);
+  pst->n_global_syms =
+    objfile->global_psymbols.next - (objfile->global_psymbols.list + pst->globals_offset);
+  pst->n_static_syms =
+    objfile->static_psymbols.next - (objfile->static_psymbols.list + pst->statics_offset);
 
-  if (NUMBER_OF_SYMBOLS == 0)
+  pst->number_of_dependencies = number_dependencies;
+  if (number_dependencies)
     {
-      if (symfile)
-       free (symfile);
-      symfile = 0;
-      free_all_symtabs ();
-      printf ("%s has no symbol-table; symbols discarded.\n", name);
-      fflush (stdout);
-      return;
+      pst->dependencies = (struct partial_symtab **)
+       obstack_alloc (&objfile->psymbol_obstack,
+                      number_dependencies * sizeof (struct partial_symtab *));
+      memcpy (pst->dependencies, dependency_list,
+            number_dependencies * sizeof (struct partial_symtab *));
     }
-
-  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)
-    stringtab = (char *) alloca (buffer);
   else
-    stringtab = NULL;
-  if (stringtab == NULL)
-    error ("ridiculous string table size: %d bytes", name, buffer);
-
-  bcopy (&buffer, stringtab, sizeof buffer);
-  val = myread (desc, stringtab + sizeof buffer, buffer - sizeof buffer);
-  if (val < 0)
-    perror_with_name (name);
+    pst->dependencies = 0;
+
+  for (i = 0; i < num_includes; i++)
+    {
+      struct partial_symtab *subpst =
+       allocate_psymtab (include_list[i], objfile);
+
+      subpst->section_offsets = pst->section_offsets;
+      subpst->read_symtab_private =
+         (char *) obstack_alloc (&objfile->psymbol_obstack,
+                                 sizeof (struct symloc));
+      LDSYMOFF(subpst) =
+       LDSYMLEN(subpst) =
+         subpst->textlow =
+           subpst->texthigh = 0;
+
+      /* We could save slight bits of space by only making one of these,
+        shared by the entire set of include files.  FIXME-someday.  */
+      subpst->dependencies = (struct partial_symtab **)
+       obstack_alloc (&objfile->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->readin = 0;
+      subpst->symtab = 0;
+      subpst->read_symtab = dbx_psymtab_to_symtab;
+    }
+
+  sort_pst_symbols (pst);
+
+  /* If there is already a psymtab or symtab for a file of this name, remove it.
+     (If there is a symtab, more drastic things also happen.)
+     This happens in VxWorks.  */
+  free_named_symtabs (pst->filename);
+
+  if (num_includes == 0
+   && number_dependencies == 0
+   && pst->n_global_syms == 0
+   && pst->n_static_syms == 0) {
+    /* Throw away this psymtab, it's empty.  We can't deallocate it, since
+       it is on the obstack, but we can forget to chain it on the list.  */
+    struct partial_symtab *prev_pst;
+
+    /* First, snip it out of the psymtab chain */
+
+    if (pst->objfile->psymtabs == pst)
+      pst->objfile->psymtabs = pst->next;
+    else
+      for (prev_pst = pst->objfile->psymtabs; prev_pst; prev_pst = pst->next)
+       if (prev_pst->next == pst)
+         prev_pst->next = pst->next;
 
-  /* Throw away the old symbol table.  */
+    /* Next, put it on a free list for recycling */
 
-  if (symfile)
-    free (symfile);
-  symfile = 0;
-  free_all_symtabs ();
+    pst->next = pst->objfile->free_psymtabs;
+    pst->objfile->free_psymtabs = pst;
+  }
+}
+\f
+static void
+dbx_psymtab_to_symtab_1 (pst)
+     struct partial_symtab *pst;
+{
+  struct cleanup *old_chain;
+  int i;
+  
+  if (!pst)
+    return;
 
-  /* Empty the hash table of global syms looking for values.  */
-  bzero (global_sym_chain, sizeof global_sym_chain);
+  if (pst->readin)
+    {
+      fprintf (stderr, "Psymtab for %s already read in.  Shouldn't happen.\n",
+              pst->filename);
+      return;
+    }
 
-#ifdef READ_GDB_SYMSEGS
-  /* That puts us at the symsegs.  Read them.  */
-  symseg_chain = read_symsegs (desc, name);
-  hash_symsegs ();
+  /* Read in all partial symtabs 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)
+         {
+           fputs_filtered (" ", stdout);
+           wrap_here ("");
+           fputs_filtered ("and ", stdout);
+           wrap_here ("");
+           printf_filtered ("%s...", pst->dependencies[i]->filename);
+           wrap_here ("");             /* Flush output */
+           fflush (stdout);
+         }
+       dbx_psymtab_to_symtab_1 (pst->dependencies[i]);
+      }
 
-  /* 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)
+  if (LDSYMLEN(pst))           /* Otherwise it's a dummy */
     {
-      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;
-       }
-    }
+      /* Init stuff necessary for reading in symbols */
+      stabsread_init ();
+      buildsym_init ();
+      old_chain = make_cleanup (really_free_pendings, 0);
+      file_string_table_offset = FILE_STRING_OFFSET (pst);
+#ifdef GDB_TARGET_IS_HPPA
+      symbol_size = obj_dbx_symbol_entry_size (pst->objfile->obfd);
 #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.  */
-  symseg_chain = 0;
+      symbol_size = SYMBOL_SIZE (pst);
 #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);
-
-  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);
-
-  /* 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.  */
+      /* Read in this file's symbols */
+      bfd_seek (pst->objfile->obfd, SYMBOL_OFFSET (pst), L_SET);
+      pst->symtab =
+       read_ofile_symtab (pst->objfile, LDSYMOFF(pst), LDSYMLEN(pst),
+                          pst->textlow, pst->texthigh - pst->textlow,
+                          pst->section_offsets);
+      sort_symtab_syms (pst->symtab);
 
-  sort_syms ();
-
-  /* Go over the misc functions and install them in vector.  */
-
-  condense_misc_bunches ();
-
-  /* Don't allow char * to have a typename (else would get caddr_t.)  */
-
-  TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0;
+      do_cleanups (old_chain);
+    }
 
-  /* Make a default for file to list.  */
+  pst->readin = 1;
+}
 
-  select_source_symtab (symtab_list);
+/* Read in all of the symbols for a given psymtab for real.
+   Be verbose about it if the user wants that.  */
 
-  symfile = savestring (name, strlen (name));
+static void
+dbx_psymtab_to_symtab (pst)
+     struct partial_symtab *pst;
+{
+  bfd *sym_bfd;
 
-  do_cleanups (old_chain);
+  if (!pst)
+    return;
 
-  /* Free the symtabs made by read_symsegs, but not their contents,
-     which have been copied into symtabs on symtab_list.  */
-  while (symseg_chain)
+  if (pst->readin)
     {
-      register struct symtab *s = symseg_chain->next;
-      free (symseg_chain);
-      symseg_chain = s;
+      fprintf (stderr, "Psymtab for %s already read in.  Shouldn't happen.\n",
+              pst->filename);
+      return;
     }
 
-  printf ("done.\n");
-  fflush (stdout);
-}
-
-/* Return name of file symbols were loaded from, or 0 if none..  */
-
-char *
-get_sym_file ()
-{
-  return symfile;
-}
-\f
-/* Buffer for reading the symbol table entries.  */
-static struct nlist symbuf[2048];
-static int symbuf_idx;
-static int symbuf_end;
-
-/* I/O descriptor for reading the symbol table.  */
-static int symtab_input_desc;
+  if (LDSYMLEN(pst) || 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);
+       }
 
-/* The address of the string table
-   of the object file we are reading (as copied into core).  */
-static char *stringtab_global;
+      sym_bfd = pst->objfile->obfd;
 
-/* Refill the symbol table input buffer
-   and set the variables that control fetching entries from it.
-   Reports an error if no data available.
-   This function can read past the end of the symbol table
-   (into the string table) but this does no harm.  */
+      next_symbol_text_func = dbx_next_symbol_text;
 
-static int
-fill_symbuf ()
-{
-  int nbytes = myread (symtab_input_desc, symbuf, sizeof (symbuf));
-  if (nbytes <= 0)
-    error ("error or end of file reading symbol table");
-  symbuf_end = nbytes / sizeof (struct nlist);
-  symbuf_idx = 0;
-  return 1;
-}
+      dbx_psymtab_to_symtab_1 (pst);
 
-/* dbx allows the text of a symbol name to be continued into the
-   next symbol name!  When such a continuation is encountered
-   (a \ at the end of the text of a name)
-   call this function to get the continuation.  */
+      /* Match with global symbols.  This only needs to be done once,
+         after all of the symtabs and dependencies have been read in.   */
+      scan_file_globals (pst->objfile);
 
-static char *
-next_symbol_text ()
-{
-  if (symbuf_idx == symbuf_end)
-    fill_symbuf ();
-  symnum++;
-  return symbuf[symbuf_idx++].n_un.n_strx + stringtab_global;
+      /* Finish up the debug error message.  */
+      if (info_verbose)
+       printf_filtered ("done.\n");
+    }
 }
-\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.  */
 
-static void
-read_dbx_symtab (desc, stringtab, nlistlen)
-     int desc;
-     register char *stringtab;
-     register int nlistlen;
+/* 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
+   SYM_OFFSET is the offset within the file of
+   the beginning of the symbols we want to read
+   SYM_SIZE is the size of the symbol info to read in.
+   TEXT_OFFSET is the beginning of the text segment we are reading symbols for
+   TEXT_SIZE is the size of the text segment read in.
+   SECTION_OFFSETS are the relocation offsets which get added to each symbol. */
+
+static struct symtab *
+read_ofile_symtab (objfile, sym_offset, sym_size, text_offset, text_size,
+                  section_offsets)
+     struct objfile *objfile;
+     int sym_offset;
+     int sym_size;
+     CORE_ADDR text_offset;
+     int text_size;
+     struct section_offsets *section_offsets;
 {
   register char *namestring;
-  register struct symbol *sym, *prev;
-  int hash;
-  int num_object_files = 0;
-  struct cleanup *old_chain;
+  register struct internal_nlist *bufp;
+  unsigned char type;
+  unsigned max_symnum;
+  register bfd *abfd;
+  struct symtab *rtn;
 
-#ifdef N_BINCL
-  subfile_stack = 0;
-#endif
-
-  old_chain = make_cleanup (free_all_symtabs, 0);
-  stringtab_global = stringtab;
-  last_source_file = 0;
+  current_objfile = objfile;
+  subfile_stack = NULL;
 
-#ifdef END_OF_TEXT_DEFAULT
-  end_of_text_addr = END_OF_TEXT_DEFAULT;
+#ifdef GDB_TARGET_IS_HPPA
+  stringtab_global = HP_STRINGTAB (objfile);
+#else
+  stringtab_global = DBX_STRINGTAB (objfile);
 #endif
+  last_source_file = NULL;
 
-  symtab_input_desc = desc;
+  abfd = objfile->obfd;
+  symfile_bfd = objfile->obfd; /* Implicit param to next_text_symbol */
   symbuf_end = symbuf_idx = 0;
 
-  for (symnum = 0; symnum < nlistlen; symnum++)
-    {
-      struct nlist *bufp;
-      int type;
+  /* 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.
 
-      QUIT;    /* allow this to be interruptable */
-      if (symbuf_idx == symbuf_end)
-       fill_symbuf ();
+     Detecting this in read_dbx_symtab
+     would slow down initial readin, so we look for it here instead.  */
+  if (!processing_acc_compilation && sym_offset >= (int)symbol_size)
+    {
+      bfd_seek (symfile_bfd, sym_offset - symbol_size, L_INCR);
+      fill_symbuf (abfd);
       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)))
+      SWAP_SYMBOL (bufp, abfd);
+
+      SET_NAMESTRING ();
+
+      processing_gcc_compilation = 0;
+      if (bufp->n_type == N_TEXT)
        {
-         if (num_object_files++ == 1)
-           first_object_file_end = bufp->n_value;
-         if (last_source_file)
-           end_symtab (bufp->n_value);
+         if (strcmp (namestring, GCC_COMPILED_FLAG_SYMBOL) == 0)
+           processing_gcc_compilation = 1;
+         else if (strcmp (namestring, GCC2_COMPILED_FLAG_SYMBOL) == 0)
+           processing_gcc_compilation = 2;
        }
-      else if (type & N_EXT || type == N_TEXT
-#ifdef N_NBTEXT
-              || type == N_NBTEXT
-#endif
-              )
+
+      /* Try to select a C++ demangling based on the compilation unit
+        producer. */
+
+      if (processing_gcc_compilation)
        {
-         int used_up = 0;
-
-         /* Record the location of _etext.  */
-         if (type == (N_TEXT | N_EXT)
-             && !strcmp (namestring, "_etext"))
-           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)
+#if 1    /* Works, but is experimental.  -fnf */
+         if (AUTO_DEMANGLING)
            {
-             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 (
-#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 */
-                     )
-                   {
-                     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];
-
-                     used_up = 1;
-                   }
-                 else
-                   {
-                     prev = sym;
-                     sym = (struct symbol *) SYMBOL_VALUE (sym);
-                   }
-               }
+             set_demangling_style (GNU_DEMANGLING_STYLE_STRING);
            }
-
-         /* 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);
+#endif
        }
     }
+  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.  */
+      bfd_seek (symfile_bfd, sym_offset, L_INCR);
+      processing_gcc_compilation = 0;
+    }
 
-  if (last_source_file)
-    end_symtab (end_of_text_addr);
-
-  discard_cleanups (old_chain);
-}
+  if (symbuf_idx == symbuf_end)
+    fill_symbuf (abfd);
+  bufp = &symbuf[symbuf_idx];
+  if (bufp->n_type != (unsigned char)N_SO)
+    error("First symbol in segment of executable not a source symbol");
 
-static int
-hashname (name)
-     char *name;
-{
-  register char *p = name;
-  register int total = p[0];
-  register int c;
+  max_symnum = sym_size / symbol_size;
 
-  c = p[1];
-  total += c << 2;
-  if (c)
+  for (symnum = 0;
+       symnum < max_symnum;
+       symnum++)
     {
-      c = p[2];
-      total += c << 4;
-      if (c)
-       total += p[3] << 6;
-    }
+      QUIT;                    /* Allow this to be interruptable */
+      if (symbuf_idx == symbuf_end)
+       fill_symbuf(abfd);
+      bufp = &symbuf[symbuf_idx++];
+      SWAP_SYMBOL (bufp, abfd);
 
-  /* Ensure result is positive.  */
-  if (total < 0) total += (1000 << 6);
-  return total % HASHSIZE;
-}
+      type = bufp->n_type;
 
-/* Put all appropriate global symbols in the symseg data
-   onto the hash chains so that their addresses will be stored
-   when seen later in loader global symbols.  */
+      SET_NAMESTRING ();
 
-static void
-hash_symsegs ()
-{
-  /* Look at each symbol in each block in each symseg symtab.  */
-  struct symtab *s;
-  for (s = symseg_chain; s; s = s->next)
-    {
-      register int n;
-      for (n = BLOCKVECTOR_NBLOCKS (BLOCKVECTOR (s)) - 1; n >= 0; n--)
+      if (type & N_STAB) {
+         process_one_symbol (type, bufp->n_desc, bufp->n_value,
+                             namestring, section_offsets, objfile);
+      }
+      /* We skip checking for a new .o or -l file; that should never
+         happen in this routine. */
+      else if (type == N_TEXT)
        {
-         register struct block *b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), n);
-         register int i;
-         for (i = BLOCK_NSYMS (b) - 1; i >= 0; i--)
+         /* 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.  */
+
+         if (strcmp (namestring, GCC_COMPILED_FLAG_SYMBOL) == 0)
+           processing_gcc_compilation = 1;
+         else if (strcmp (namestring, GCC2_COMPILED_FLAG_SYMBOL) == 0)
+           processing_gcc_compilation = 2;
+
+#if 1    /* Works, but is experimental.  -fnf */
+         if (AUTO_DEMANGLING)
            {
-             register struct symbol *sym = BLOCK_SYM (b, i);
-
-             /* Put the symbol on a chain if its value is an address
-                that is figured out by the loader.  */
-
-             if (SYMBOL_CLASS (sym) == LOC_EXTERNAL)
-               {
-                 register int hash = hashname (SYMBOL_NAME (sym));
-                 SYMBOL_VALUE (sym) = (int) global_sym_chain[hash];
-                 global_sym_chain[hash] = sym;
-                 SYMBOL_CLASS (sym) = LOC_STATIC;
-               }
+             set_demangling_style (GNU_DEMANGLING_STYLE_STRING);
            }
+#endif
        }
-    }
+      else if (type & N_EXT || type == (unsigned char)N_TEXT
+              || type == (unsigned char)N_NBTEXT
+              ) {
+         /* 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. */
+         ;
+        }
+    }
+
+  current_objfile = NULL;
+
+  /* In a Solaris elf file, this variable, which comes from the
+     value of the N_SO symbol, will still be 0.  Luckily, text_offset,
+     which comes from pst->textlow is correct. */
+  if (last_source_start_addr == 0)
+    last_source_start_addr = text_offset;
+
+  rtn = end_symtab (text_offset + text_size, 0, 0, objfile);
+  end_stabs ();
+  return (rtn);
 }
 \f
-static void
-process_one_symbol (type, desc, value, name)
+/* This handles a single symbol from the symbol-file, building symbols
+   into a GDB symtab.  It takes these arguments and an implicit argument.
+
+   TYPE is the type field of the ".stab" symbol entry.
+   DESC is the desc field of the ".stab" entry.
+   VALU is the value field of the ".stab" entry.
+   NAME is the symbol name, in our address space.
+   SECTION_OFFSETS is a set of amounts by which the sections of this object
+          file were relocated when it was loaded into memory.
+          All symbols that refer
+         to memory locations need to be offset by these amounts.
+   OBJFILE is the object file from which we are reading symbols.
+              It is used in end_symtab.  */
+
+void
+process_one_symbol (type, desc, valu, name, section_offsets, objfile)
      int type, desc;
-     CORE_ADDR value;
+     CORE_ADDR valu;
      char *name;
+     struct section_offsets *section_offsets;
+     struct objfile *objfile;
 {
+#ifndef SUN_FIXED_LBRAC_BUG
+  /* This records the last pc address we've seen.  We depend on there being
+     an SLINE or FUN or SO before the first LBRAC, since the variable does
+     not get reset in between reads of different symbol files.  */
+  static CORE_ADDR last_pc_address;
+#endif
   register struct context_stack *new;
+  /* This remembers the address of the start of a function.  It is used
+     because in Solaris 2, N_LBRAC, N_RBRAC, and N_SLINE entries are
+     relative to the current function's start address.  On systems
+     other than Solaris 2, this just holds the SECT_OFF_TEXT value, and is
+     used to relocate these symbol types rather than SECTION_OFFSETS.  */
+  static CORE_ADDR function_start_offset;
+  char *colon_pos;
+
+#ifndef        BLOCK_ADDRESS_FUNCTION_RELATIVE
+  /* N_LBRAC, N_RBRAC and N_SLINE entries are not relative to the
+     function start address, so just use the text offset.  */
+  function_start_offset = ANOFFSET (section_offsets, SECT_OFF_TEXT);
+#endif
 
   /* Something is wrong if we see real data before
      seeing a source file name.  */
 
-  if (last_source_file == 0 && type != N_SO)
+  if (last_source_file == NULL && type != (unsigned char)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.  */
+      /* Currently this ignores N_ENTRY on Gould machines, N_NSYM on machines
+        where that code is defined.  */
+      if (IGNORE_SYMBOL (type))
        return;
 
-      if (type == N_SLINE && desc == -1)
-       /* This code is used by the Sun4 coimpiler; ignore it.  */
-       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;
+      /* FIXME, this should not be an error, since it precludes extending
+         the symbol table information in this way...  */
+      error ("Invalid symbol data: does not start by identifying a source file.");
     }
 
   switch (type)
     {
     case N_FUN:
     case N_FNAME:
+#if 0
+/* It seems that the Sun ANSI C compiler (acc) replaces N_FUN with N_GSYM and
+   N_STSYM with a type code of f or F.  Can't enable this until we get some
+   stuff straightened out with psymtabs.  FIXME. */
+
+    case N_GSYM:
+    case N_STSYM:
+#endif /* 0 */
+
+      /* Relocate for dynamic loading */
+      valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+
       /* Either of these types of symbols indicates the start of
         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 = strchr (name, ':');
+      if (!colon_pos++
+         || (*colon_pos != 'f' && *colon_pos != 'F'))
+       {
+         define_symbol (valu, name, desc, type, objfile);
+         break;
+       }
+
+#ifndef SUN_FIXED_LBRAC_BUG
+      last_pc_address = valu;  /* Save for SunOS bug circumcision */
+#endif
+
+#ifdef BLOCK_ADDRESS_FUNCTION_RELATIVE
+      /* On Solaris 2.0 compilers, the block addresses and N_SLINE's
+        are relative to the start of the function.  On normal systems,
+        and when using gcc on Solaris 2.0, these addresses are just
+        absolute, or relative to the N_SO, depending on
+        BLOCK_ADDRESS_ABSOLUTE.  */
+      function_start_offset = valu;    
+#endif
 
       within_function = 1;
       if (context_stack_depth > 0)
        {
-         new = &context_stack[--context_stack_depth];
+         new = pop_context ();
          /* Make a block for the local symbols within.  */
          finish_block (new->name, &local_symbols, new->old_blocks,
-                       new->start_addr, value);
+                       new->start_addr, valu, objfile);
        }
       /* Stack must be empty now.  */
       if (context_stack_depth != 0)
-       error ("Invalid symbol data: unmatched N_LBRAC before symtab pos %d.",
-              symnum);
+       complain (&lbrac_unmatched_complaint, symnum);
 
-      new = &context_stack[context_stack_depth++];
-      new->old_blocks = pending_blocks;
-      new->start_addr = value;
-      new->name = define_symbol (value, name, desc);
-      local_symbols = 0;
+      new = push_context (0, valu);
+      new->name = define_symbol (valu, name, desc, type, objfile);
       break;
 
     case N_LBRAC:
       /* This "symbol" just indicates the start of an inner lexical
         context within a function.  */
 
-      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));
-       }
+#if defined(BLOCK_ADDRESS_ABSOLUTE) || defined(BLOCK_ADDRESS_FUNCTION_RELATIVE)
+      /* Relocate for dynamic loading and Sun ELF acc fn-relative syms.  */
+      valu += function_start_offset;
+#else
+      /* On most machines, the block addresses are relative to the
+        N_SO, the linker did not relocate them (sigh).  */
+      valu += last_source_start_addr;
+#endif
 
-      new = &context_stack[context_stack_depth++];
-      new->depth = desc;
-      new->locals = local_symbols;
-      new->old_blocks = pending_blocks;
-      new->start_addr = value;
-      new->name = 0;
-      local_symbols = 0;
+#ifndef SUN_FIXED_LBRAC_BUG
+      if (valu < last_pc_address) {
+       /* Patch current LBRAC pc value to match last handy pc value */
+       complain (&lbrac_complaint);
+       valu = last_pc_address;
+      }
+#endif
+      new = push_context (desc, valu);
       break;
 
     case N_RBRAC:
       /* This "symbol" just indicates the end of an inner lexical
-        context that was started with N_RBRAC.  */
-      new = &context_stack[--context_stack_depth];
+        context that was started with N_LBRAC.  */
+
+#if defined(BLOCK_ADDRESS_ABSOLUTE) || defined(BLOCK_ADDRESS_FUNCTION_RELATIVE)
+      /* Relocate for dynamic loading and Sun ELF acc fn-relative syms.  */
+      valu += function_start_offset;
+#else
+      /* On most machines, the block addresses are relative to the
+        N_SO, the linker did not relocate them (sigh).  */
+      valu += last_source_start_addr;
+#endif
+
+      new = pop_context();
       if (desc != new->depth)
-       error ("Invalid symbol data: N_LBRAC/N_RBRAC symbol mismatch, symtab pos %d.", symnum);
-      local_symbols = new->locals;
+       complain (&lbrac_mismatch_complaint, symnum);
+
+      /* Some compilers put the variable decls inside of an
+         LBRAC/RBRAC block.  This macro should be nonzero if this
+        is true.  DESC is N_DESC from the N_RBRAC symbol.
+        GCC_P is true if we've detected the GCC_COMPILED_SYMBOL
+        or the GCC2_COMPILED_SYMBOL.  */
+#if !defined (VARIABLES_INSIDE_BLOCK)
+#define VARIABLES_INSIDE_BLOCK(desc, gcc_p) 0
+#endif
+
+      /* Can only use new->locals as local symbols here if we're in
+         gcc or on a machine that puts them before the lbrack.  */
+      if (!VARIABLES_INSIDE_BLOCK(desc, processing_gcc_compilation))
+       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,22 +1756,37 @@ 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.  */
-      if (local_symbols && context_stack_depth > 1)
+        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.  */
+      if (local_symbols
+         && (context_stack_depth
+             > !VARIABLES_INSIDE_BLOCK(desc, processing_gcc_compilation)))
        {
-         /* Muzzle a compiler bug that makes end > start.  */
-         if (new->start_addr > value)
-           new->start_addr = value;
+         /* FIXME Muzzle a compiler bug that makes end < start.  */
+         if (new->start_addr > valu)
+           {
+             complain (&lbrac_rbrac_complaint);
+             new->start_addr = valu;
+           }
          /* Make a block for the local symbols within.  */
          finish_block (0, &local_symbols, new->old_blocks,
-                       new->start_addr + last_source_start_addr,
-                       value + last_source_start_addr);
+                       new->start_addr, valu, objfile);
        }
+      else
+       {
+         within_function = 0;
+       }
+      if (VARIABLES_INSIDE_BLOCK(desc, processing_gcc_compilation))
+       /* Now pop locals of block just finished.  */
+       local_symbols = new->locals;
       break;
 
     case N_FN:
-      /* This kind of symbol supposedly indicates the start
-        of an object file.  In fact this type does not appear.  */
+    case N_FN_SEQ:
+      /* This kind of symbol indicates the start of an object file.  */
+      /* Relocate for dynamic loading */
+      valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
       break;
 
     case N_SO:
@@ -1773,1485 +1794,406 @@ 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.  */
+      /* Relocate for dynamic loading */
+      valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+
+#ifndef SUN_FIXED_LBRAC_BUG
+      last_pc_address = valu;  /* Save for SunOS bug circumcision */
+#endif
+  
+#ifdef PCC_SOL_BROKEN
+      /* pcc bug, occasionally puts out SO for SOL.  */
+      if (context_stack_depth > 0)
+       {
+         start_subfile (name, NULL);
+         break;
+       }
+#endif
       if (last_source_file)
-       end_symtab (value);
-      start_symtab (name, value);
+       {
+         /* Check if previous symbol was also an N_SO (with some
+            sanity checks).  If so, that one was actually the directory
+            name, and the current one is the real file name.
+            Patch things up. */           
+         if (previous_stab_code == N_SO)
+           {
+             patch_subfile_names (current_subfile, name);
+             break;            /* Ignore repeated SOs */
+           }
+         end_symtab (valu, 0, 0, objfile);
+         end_stabs ();
+       }
+      start_stabs ();
+      start_symtab (name, NULL, valu);
       break;
 
+
     case N_SOL:
       /* This type of symbol indicates the start of data for
         a sub-source-file, one whose contents were copied or
         included in the compilation of the main source file
         (whose name was given in the N_SO symbol.)  */
-      start_subfile (name);
+      /* Relocate for dynamic loading */
+      valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+      start_subfile (name, current_subfile->dirname);
       break;
 
-#ifdef N_BINCL
     case N_BINCL:
       push_subfile ();
-      add_new_header_file (name, value);
-      start_subfile (name);
+      add_new_header_file (name, valu);
+      start_subfile (name, current_subfile->dirname);
       break;
 
     case N_EINCL:
-      start_subfile (pop_subfile ());
+      start_subfile (pop_subfile (), current_subfile->dirname);
       break;
 
     case N_EXCL:
-      add_old_header_file (name, value);
+      add_old_header_file (name, valu);
       break;
-#endif /* have N_BINCL */
 
     case N_SLINE:
       /* This type of "symbol" really just records
         one line-number -- core-address correspondence.
         Enter it in the line list for this symbol table.  */
-      record_line (desc, value);
+      /* Relocate for dynamic loading and for ELF acc fn-relative syms.  */
+      valu += function_start_offset;
+#ifndef SUN_FIXED_LBRAC_BUG
+      last_pc_address = valu;  /* Save for SunOS bug circumcision */
+#endif
+      record_line (current_subfile, desc, valu);
       break;
 
     case N_BCOMM:
-    case N_ECOMM:
-    case N_ECOML:
-    case N_LENG:
+      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;
 
-    default:
-      if (name)
-       define_symbol (value, name, desc);
-    }
-}
-\f
-/************************ READ_ADDL_SYM() ***********************************/
-
-static void
-read_addl_syms (desc, stringtab, nlistlen, text_addr, text_size)
-     int desc;
-     register char *stringtab;
-     register int nlistlen;
-     unsigned text_addr;
-     int text_size;
-{
-  FILE *stream = fdopen (desc, "r");
-  register char *namestring;
-  register struct symbol *sym, *prev;
-  int hash;
-  int num_object_files = 0;
-
-#ifdef N_BINCL
-  subfile_stack = 0;
-#endif
-
-  last_source_file = 0;
-  bzero (global_sym_chain, sizeof global_sym_chain);
-  symtab_input_desc = desc;
-  stringtab_global = stringtab;
-  fill_symbuf ();
-
-  for (symnum = 0; symnum < nlistlen; symnum++)
-    {
-      struct nlist *bufp;
-      int 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 : "";
+    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 symbol *sym =
+         (struct symbol *) xmmalloc (objfile -> md, sizeof (struct symbol));
+       memset (sym, 0, sizeof *sym);
+       SYMBOL_NAME (sym) = savestring (name, strlen (name));
+       SYMBOL_CLASS (sym) = LOC_BLOCK;
+       SYMBOL_NAMESPACE (sym) = (enum namespace)((long)
+         copy_pending (local_symbols, common_block_i, common_block));
+       i = hashname (SYMBOL_NAME (sym));
+       SYMBOL_VALUE_CHAIN (sym) = global_sym_chain[i];
+       global_sym_chain[i] = sym;
+       common_block = 0;
+       break;
+      }
 
-      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;        
+    /* The following symbol types need to have the appropriate offset added
+       to their value; then we process symbol definitions in the name.  */
+
+    case N_STSYM:              /* Static symbol in data seg */
+    case N_LCSYM:              /* Static symbol in BSS seg */
+    case N_ROSYM:              /* Static symbol in Read-only data seg */
+     /* HORRID HACK DEPT.  However, it's Sun's furgin' fault.  FIXME.
+       Solaris2's stabs-in-coff makes *most* symbols relative
+       but leaves a few absolute.  N_STSYM and friends sit on the fence.
+       .stab "foo:S...",N_STSYM        is absolute (ld relocates it)
+       .stab "foo:V...",N_STSYM        is relative (section base subtracted).
+       This leaves us no choice but to search for the 'S' or 'V'...
+       (or pass the whole section_offsets stuff down ONE MORE function
+       call level, which we really don't want to do).  */
+      {
+       char *p;
+       p = strchr (name, ':');
+       if (p != 0 && p[1] == 'S')
+         {
+           /* FIXME!  We relocate it by the TEXT offset, in case the
+              whole module moved in memory.  But this is wrong, since
+              the sections can side around independently.  */
+           valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+           goto define_a_symbol;
+         }
+       /* Since it's not the kludge case, re-dispatch to the right handler. */
+       switch (type) {
+       case N_STSYM:   goto case_N_STSYM;
+       case N_LCSYM:   goto case_N_LCSYM;
+       case N_ROSYM:   goto case_N_ROSYM;
+       default:        abort();
        }
+      }
 
-      type = bufp->n_type;
+    case_N_STSYM:              /* Static symbol in data seg */
+    case N_DSLINE:             /* Source line number, data seg */
+      valu += ANOFFSET (section_offsets, SECT_OFF_DATA);
+      goto define_a_symbol;
+
+    case_N_LCSYM:              /* Static symbol in BSS seg */
+    case N_BSLINE:             /* Source line number, bss seg */
+    /*   N_BROWS:      overlaps with N_BSLINE */
+      valu += ANOFFSET (section_offsets, SECT_OFF_BSS);
+      goto define_a_symbol;
+
+    case_N_ROSYM:              /* Static symbol in Read-only data seg */
+      valu += ANOFFSET (section_offsets, SECT_OFF_RODATA);
+      goto define_a_symbol;
+
+    case N_ENTRY:              /* Alternate entry point */
+      /* Relocate for dynamic loading */
+      valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+      goto define_a_symbol;
+
+    /* The following symbol types don't need the address field relocated,
+       since it is either unused, or is absolute.  */
+    define_a_symbol:
+    case N_GSYM:               /* Global variable */
+    case N_NSYMS:              /* Number of symbols (ultrix) */
+    case N_NOMAP:              /* No map?  (ultrix) */
+    case N_RSYM:               /* Register variable */
+    case N_DEFD:               /* Modula-2 GNU module dependency */
+    case N_SSYM:               /* Struct or union element */
+    case N_LSYM:               /* Local symbol in stack */
+    case N_PSYM:               /* Parameter variable */
+    case N_LENG:               /* Length of preceding symbol type */
+      if (name)
+       define_symbol (valu, name, desc, type, objfile);
+      break;
 
-      if (type & N_STAB)
-       process_one_symbol (type, bufp->n_desc,
-                           bufp->n_value, namestring);
-      /* A static text symbol whose name ends in ".o"
-        can only mean 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 ((type == N_TEXT
-#ifdef N_NBTEXT
-               || type == N_NBTEXT
-#endif
-               )
-              && (!strcmp (namestring + strlen (namestring) - 2, ".o"))
-              || ! strcmp (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
-#endif
-              )
+    /* We use N_OPT to carry the gcc2_compiled flag.  Sun uses it
+       for a bunch of other flags, too.  Someday we may parse their
+       flags; for now we ignore theirs and hope they'll ignore ours.  */
+    case N_OPT:                        /* Solaris 2:  Compiler options */
+      if (name)
        {
-         int used_up = 0;
-
-         /* Record the location of _etext.  */
-         if (type == (N_TEXT | N_EXT)
-             && !strcmp (namestring, "_etext"))
-           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)
+         if (strcmp (name, GCC2_COMPILED_FLAG_SYMBOL) == 0)
            {
-             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;)
+             processing_gcc_compilation = 2;
+#if 1        /* Works, but is experimental.  -fnf */
+             if (AUTO_DEMANGLING)
                {
-                 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 */
-                     )
-                   {
-                     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];
-
-                     used_up = 1;
-                   }
-                 else
-                   {
-                     prev = sym;
-                     sym = (struct symbol *) SYMBOL_VALUE (sym);
-                   }
+                 set_demangling_style (GNU_DEMANGLING_STYLE_STRING);
                }
-           }
-
-         /* 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);
-       }
-    }
-
-  if (last_source_file)
-    end_symtab (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.  */
-
-void
-add_file_command (arg_string)
-     char* arg_string;
-{ 
-  register int desc;
-  struct exec hdr;
-  struct nlist *nlist;
-  char *stringtab;
-  long buffer;
-  register int val;
-  extern void close ();
-  struct cleanup *old_chain;
-  char* name;
-  unsigned text_addr;
-
-  if (arg_string == 0)
-    error ("add-file takes a file name and an address");
-
-  for( ; *arg_string == ' '; arg_string++ );
-  name = arg_string;
-  for( ; *arg_string && *arg_string != ' ' ; arg_string++ );
-  *arg_string++ = (char) 0;
-
-  if (name[0] == 0)
-    error ("add-file takes a file name and an address");
-
-  text_addr = parse_and_eval_address (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);
-
-      old_chain = make_cleanup (close, desc);
-      make_cleanup (free_current_contents, &name);
-
-      val = myread (desc, &hdr, sizeof hdr);
-      if (val < 0)
-       perror_with_name (name);
-
-      if (N_BADMAG (hdr))
-       error ("File \"%s\" has a bad header.", name);
-
-      if (hdr.a_syms == 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);
-      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);
-
-      /* That puts us at the symsegs.  Read them. ########## Also need other
-        changes if they exist. */
-
-      /* 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);
-
-      printf ("Reading symbol data from %s...", name);
-      fflush (stdout);
-
-      init_misc_functions ();
-      make_cleanup (discard_misc_bunches, 0);
-      init_header_files ();
-      make_cleanup (free_header_files, 0);
-
-      read_addl_syms (desc, stringtab, hdr.a_syms / sizeof(struct nlist),
-                     text_addr, hdr.a_text) ;
-
-      /* Sort symbols alphabetically within each block.  */
-
-      sort_syms ();
-
-      /* Go over the all misc functions and install them in vector.  */
-
-      condense_addl_misc_bunches ();
-
-      /* Don't allow char * to have a typename (else would get caddr_t.)  */
-
-      TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0;
-
-      /* Make a default for file to list.  */
-
-      select_source_symtab (symtab_list);
-
-      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;
-       }
-
-      printf ("done.\n");
-      fflush (stdout);
-    }
-  else error ("Not confirmed.");
-}
-\f
-static struct symbol *
-define_symbol (value, string, desc)
-     int value;
-     char *string;
-     int desc;
-{
-  register struct symbol *sym
-    = (struct symbol *) obstack_alloc (symbol_obstack, sizeof (struct symbol));
-  char *p = (char *) index (string, ':');
-  int deftype;
-  register int i;
-
-  /* Ignore syms with empty names.  */
-  if (string[0] == 0)
-    return 0;
-
-  SYMBOL_NAME (sym)
-    = (char *) obstack_alloc (symbol_obstack, ((p - string) + 1));
-  /* Open-coded bcopy--saves function call time.  */
-  {
-    register char *p1 = string;
-    register char *p2 = SYMBOL_NAME (sym);
-    while (p1 != p)
-      *p2++ = *p1++;
-    *p2++ = '\0';
-  }
-  p++;
-  /* Determine the type of name being defined.  */
-  if ((*p >= '0' && *p <= '9') || *p == '(')
-    deftype = 'l';
-  else
-    deftype = *p++;
-
-  /* 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.  */
-  if (deftype == 'c')
-    {
-      if (*p++ != '=')
-       error ("Invalid symbol data at symtab pos %d.", symnum);
-      switch (*p++)
-       {
-       case 'r':
-         {
-           double d = atof (p);
-           char *value;
-
-           SYMBOL_TYPE (sym) = builtin_type_double;
-           value = (char *) obstack_alloc (symbol_obstack, sizeof (double));
-           bcopy (&d, value, sizeof (double));
-           SYMBOL_VALUE_BYTES (sym) = value;
-           SYMBOL_CLASS (sym) = LOC_CONST;
-         }
-         break;
-       case 'i':
-         {
-           SYMBOL_TYPE (sym) = builtin_type_int;
-           SYMBOL_VALUE (sym) = atoi (p);
-           SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
-         }
-         break;
-       default:
-         error ("Invalid symbol data at symtab pos %d.", symnum);
-       }
-      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
-      add_symbol_to_list (sym, &file_symbols);
-      return sym;
-    }
-
-  /* Now usually comes a number that says which data type,
-     and possibly more stuff to define the type
-     (all of which is handled by read_type)  */
-
-  if (deftype == 'p' && *p == 'F')
-    /* pF is a two-letter code that means a function parameter in Fortran.
-       The type-number specifies the type of the return value.
-       Translate it into a pointer-to-function type.  */
-    {
-      p++;
-      SYMBOL_TYPE (sym)
-       = lookup_pointer_type (lookup_function_type (read_type (&p)));
-    }
-  else
-    {
-      struct type *type = read_type (&p);
-
-      if ((deftype == 'F' || deftype == 'f')
-         && TYPE_CODE (type) != TYPE_CODE_FUNC)
-       SYMBOL_TYPE (sym) = lookup_function_type (type);
-      else
-       SYMBOL_TYPE (sym) = type;
-    }
-
-  switch (deftype)
-    {
-    case 'f':
-      SYMBOL_CLASS (sym) = LOC_BLOCK;
-      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
-      add_symbol_to_list (sym, &file_symbols);
-      break;
-
-    case 'F':
-      SYMBOL_CLASS (sym) = LOC_BLOCK;
-      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
-      add_symbol_to_list (sym, &global_symbols);
-      break;
-
-    case 'G':
-      /* For a class G (global) symbol, it appears that the
-        value is not correct.  It is necessary to search for the
-        corresponding linker definition to find the value.
-        These definitions appear at the end of the namelist.  */
-      i = hashname (SYMBOL_NAME (sym));
-      SYMBOL_VALUE (sym) = (int) global_sym_chain[i];
-      global_sym_chain[i] = sym;
-      SYMBOL_CLASS (sym) = LOC_STATIC;
-      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
-      add_symbol_to_list (sym, &global_symbols);
-      break;
-
-      /* This case is faked by a conditional above,
-        when there is no code letter in the dbx data.
-        Dbx data never actually contains 'l'.  */
-    case 'l':
-      SYMBOL_CLASS (sym) = LOC_LOCAL;
-      SYMBOL_VALUE (sym) = value;
-      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
-      add_symbol_to_list (sym, &local_symbols);
-      break;
-
-    case 'p':
-      SYMBOL_CLASS (sym) = LOC_ARG;
-      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)
-       break;
-      /* If PCC says a parameter is a short or a char,
-        it is really an int.  */
-      if (SYMBOL_TYPE (sym) == builtin_type_char
-         || SYMBOL_TYPE (sym) == builtin_type_short)
-       SYMBOL_TYPE (sym) = builtin_type_int;
-      else if (SYMBOL_TYPE (sym) == builtin_type_unsigned_char
-              || SYMBOL_TYPE (sym) == builtin_type_unsigned_short)
-       SYMBOL_TYPE (sym) = builtin_type_unsigned_int;
-      break;
-
-    case 'P':
-      SYMBOL_CLASS (sym) = LOC_REGPARM;
-      SYMBOL_VALUE (sym) = 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_NAMESPACE (sym) = VAR_NAMESPACE;
-      add_symbol_to_list (sym, &local_symbols);
-      break;
-
-    case 'S':
-      /* Static symbol at top level of file */
-      SYMBOL_CLASS (sym) = LOC_STATIC;
-      SYMBOL_VALUE (sym) = value;
-      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
-      add_symbol_to_list (sym, &file_symbols);
-      break;
-
-    case 't':
-      SYMBOL_CLASS (sym) = LOC_TYPEDEF;
-      SYMBOL_VALUE (sym) = value;
-      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
-      if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0
-         && (TYPE_FLAGS (SYMBOL_TYPE (sym)) & TYPE_FLAG_PERM) == 0)
-       TYPE_NAME (SYMBOL_TYPE (sym)) =
-         obsavestring (SYMBOL_NAME (sym),
-                       strlen (SYMBOL_NAME (sym)));
-      /* C++ vagaries: we may have a type which is derived from
-        a base type which did not have its name defined when the
-        derived class was output.  We fill in the derived class's
-        base part member's name here in that case.  */
-      else if ((TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT
-               || 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;
 
-    case 'T':
-      SYMBOL_CLASS (sym) = LOC_TYPEDEF;
-      SYMBOL_VALUE (sym) = value;
-      SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
-      if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0
-         && (TYPE_FLAGS (SYMBOL_TYPE (sym)) & TYPE_FLAG_PERM) == 0)
-       TYPE_NAME (SYMBOL_TYPE (sym))
-         = obconcat ("",
-                     (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_ENUM
-                      ? "enum "
-                      : (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT
-                         ? "struct " : "union ")),
-                     SYMBOL_NAME (sym));
-      add_symbol_to_list (sym, &file_symbols);
+    /* The following symbol types can be ignored.  */
+    case N_OBJ:                        /* Solaris 2:  Object file dir and name */
+    /*   N_UNDF:                  Solaris 2:  file separator mark */
+    /*   N_UNDF: -- we will never encounter it, since we only process one
+                   file's symbols at once.  */
+    case N_ENDM:               /* Solaris 2:  End of module */
+    case N_MAIN:               /* Name of main routine.  */
       break;
-
-    case 'V':
-    case 'v':
-      /* Static symbol of local scope */
-      SYMBOL_CLASS (sym) = LOC_STATIC;
-      SYMBOL_VALUE (sym) = value;
-      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
-      add_symbol_to_list (sym, &local_symbols);
-      break;
-
+      
+    /* The following symbol types we don't know how to process.  Handle
+       them in a "default" way, but complain to people who care.  */
     default:
-      error ("Invalid symbol data: unknown symbol-type code `%c' at symtab pos %d.", deftype, symnum);
+    case N_CATCH:              /* Exception handler catcher */
+    case N_EHDECL:             /* Exception handler name */
+    case N_PC:                 /* Global symbol in Pascal */
+    case N_M2C:                        /* Modula-2 compilation unit */
+    /*   N_MOD2:       overlaps with N_EHDECL */
+    case N_SCOPE:              /* Modula-2 scope information */
+    case N_ECOML:              /* End common (local name) */
+    case N_NBTEXT:             /* Gould Non-Base-Register symbols??? */
+    case N_NBDATA:
+    case N_NBBSS:
+    case N_NBSTS:
+    case N_NBLCS:
+      complain (&unknown_symtype_complaint, local_hex_string(type));
+      if (name)
+       define_symbol (valu, name, desc, type, objfile);
     }
-  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.  */
 
-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);
-    }
+  previous_stab_code = type;
 }
-
-/* Read a dbx type reference or definition;
-   return the type that is meant.
-   This can be just a number, in which case it references
-   a type already defined and placed in type_vector.
-   Or the number can be followed by an =, in which case
-   it means to define a new type according to the text that
-   follows the =.  */
-
-static
-struct type *
-read_type (pp)
-     register char **pp;
+\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;
+    int begi;
+    struct pending *end;
 {
-  register struct type *type = 0;
-  register int n;
-  struct type *type1;
-  int typenums[2];
-  int xtypenums[2];
-
-  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;
-  switch ((*pp)[-1])
-    {
-    case 'x':
-      type = dbx_alloc_type (typenums);
-      /* Set the type code according to the following letter.  */
-      switch ((*pp)[0])
-       {
-       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;
-       }
-      /* 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);
-
-    case '0':
-    case '1':
-    case '2':
-    case '3':
-    case '4':
-    case '5':
-    case '6':
-    case '7':
-    case '8':
-    case '9':
-    case '(':
-      (*pp)--;
-      read_type_number (pp, xtypenums);
-      type = *dbx_lookup_type (xtypenums);
-      if (type == 0)
-       type = builtin_type_void;
-      *dbx_lookup_type (typenums) = type;
-      break;
-      
-    case '*':
-      type = dbx_alloc_type (typenums);
-      smash_to_pointer_type (type, read_type (pp));
-      break;
-
-    case '@':
-      {
-       struct type *domain = read_type (pp);
-       char c;
-       struct type *memtype;
-
-       if (*(*pp)++ != ',')
-         error ("invalid member type data format, at symtab pos %d.",
-                symnum);
-
-       memtype = read_type (pp);
-       type = dbx_alloc_type (typenums);
-       smash_to_member_type (type, domain, memtype);
-      }
-      break;
-
-    case '&':
-      type = dbx_alloc_type (typenums);
-      smash_to_reference_type (type, read_type (pp));
-      break;
-
-    case 'f':
-      type = dbx_alloc_type (typenums);
-      smash_to_function_type (type, read_type (pp));
-      break;
-
-    case 'r':
-      type = read_range_type (pp, typenums);
-      *dbx_lookup_type (typenums) = type;
-      break;
-
-    case 'e':
-      type = dbx_alloc_type (typenums);
-      type = read_enum_type (pp, type);
-      *dbx_lookup_type (typenums) = type;
-      break;
-
-    case 's':
-      type = dbx_alloc_type (typenums);
-      type = read_struct_type (pp, type);
-      break;
-
-    case 'u':
-      type = dbx_alloc_type (typenums);
-      type = read_struct_type (pp, type);
-      TYPE_CODE (type) = TYPE_CODE_UNION;
-      break;
-
-    case 'a':
-      /* Define an array type.  */
-      type = dbx_alloc_type (typenums);
-
-      /* 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;
-      break;
-
-    default:
-      error ("Invalid symbol data: unrecognized type-code `%c' at symtab pos %d.",
-            (*pp)[-1], symnum);
-    }
-
-  if (type == 0)
-    abort ();
+  struct pending *new = 0;
+  struct pending *next;
 
-#if 0
-  /* If this is an overriding temporary alteration for a header file's
-     contents, and this type number is unknown in the global definition,
-     put this type into the global definition at this type number.  */
-  if (header_file_prev_index >= 0)
+  for (next = beg; next != 0 && (next != end || begi < end->nsyms);
+       next = next->next, begi = 0)
     {
-      register struct type **tp
-        = explicit_lookup_type (header_file_prev_index, typenums[1]);
-      if (*tp == 0)
-       *tp = type;
+      register int j;
+      for (j = begi; j < next->nsyms; j++)
+       add_symbol_to_list (next->symbol[j], &new);
     }
-#endif
-  return type;
+  return new;
 }
 \f
-/* This page contains subroutines of read_type.  */
-
-/* Read the description of a structure (or union type)
-   and return an object describing the type.  */
+/* Scan and build partial symbols for an ELF symbol file.
+   This ELF file has already been processed to get its minimal symbols,
+   and any DWARF symbols that were in it.
+
+   This routine is the equivalent of dbx_symfile_init and dbx_symfile_read
+   rolled into one.
+
+   OBJFILE is the object file we are reading symbols from.
+   ADDR is the address relative to which the symbols are (e.g.
+   the base address of the text segment).
+   MAINLINE is true if we are reading the main symbol
+   table (as opposed to a shared lib or dynamically loaded file).
+   STABOFFSET and STABSIZE define the location in OBJFILE where the .stab
+   section exists.
+   STABSTROFFSET and STABSTRSIZE define the location in OBJFILE where the
+   .stabstr section exists.
+
+   This routine is mostly copied from dbx_symfile_init and dbx_symfile_read,
+   adjusted for elf details. */
 
-static struct type *
-read_struct_type (pp, type)
-     char **pp;
-     register struct type *type;
+void
+elfstab_build_psymtabs (objfile, section_offsets, mainline, 
+                              staboffset, stabsize,
+                              stabstroffset, stabstrsize)
+      struct objfile *objfile;
+      struct section_offsets *section_offsets;
+      int mainline;
+      file_ptr staboffset;
+      unsigned int stabsize;
+      file_ptr stabstroffset;
+      unsigned int stabstrsize;
 {
-  struct nextfield
-    {
-      struct nextfield *next;
-      int visibility;
-      struct field field;
-    };
-
-  struct next_fnfield
-    {
-      struct next_fnfield *next;
-      int visibility;
-      struct fn_field fn_field;
-    };
-
-  struct next_fnfieldlist
-    {
-      struct next_fnfieldlist *next;
-      struct fn_fieldlist fn_fieldlist;
-    };
-
-  register struct nextfield *list = 0;
-  struct nextfield *new;
-  int totalsize;
-  char *name;
-  register char *p;
-  int nfields = 0;
-  register int n;
-
-  register struct next_fnfieldlist *mainlist = 0;
-  int nfn_fields = 0;
-  struct type *baseclass = NULL;
-  int read_possible_virtual_info = 0;
-
-  TYPE_CODE (type) = TYPE_CODE_STRUCT;
-
-  /* First comes the total size in bytes.  */
-
-  TYPE_LENGTH (type) = read_number (pp, 0);
-
-  /* C++: Now, if the class is a derived class, then the next character
-     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.  */
-  if (**pp == '!')
-    {
-      int i, n_baseclasses, offset;
-      struct type **baseclass_vec;
-      struct type *baseclass;
-      int via_public, 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 ();
-         switch (*(*pp)++)
-           {
-           case '0':
-             via_virtual = 0;
-             break;
-           case '1':
-             via_virtual = 1;
-             break;
-           default:
-             error ("Invalid symbol data: bad visibility format at symtab pos %d.",
-                    symnum);
-           }
-         switch (*(*pp)++)
-           {
-           case '0':
-             via_public = 0;
-             break;
-           case '2':
-             via_public = 1;
-             break;
-           default:
-             error ("Invalid symbol data: bad visibility format at symtab pos %d.",
-                    symnum);
-           }
-         offset = read_number (pp, ',');
-         baseclass = read_type (pp);
-         *pp += 1;             /* skip trailing ';' */
-         baseclass_vec[i] = lookup_basetype_type (baseclass, offset, via_virtual, via_public);
-
-         /* Make this baseclass visible for structure-printing purposes.  */
-         new = (struct nextfield *) alloca (sizeof (struct nextfield));
-         new->next = list;
-         list = new;
-         list->field.type = baseclass_vec[i];
-         list->field.name = TYPE_NAME (baseclass_vec[i]);
-         list->field.bitpos = offset;
-         list->field.bitsize = 0;      /* this should be an unpacked field! */
-         nfields++;
-       }
-      TYPE_N_BASECLASSES (type) = n_baseclasses;
-      TYPE_BASECLASSES (type) = baseclass_vec;
-    }
-
-  /* Now come the fields, as NAME:?TYPENUM,BITPOS,BITSIZE; for each one.
-     At the end, we see a semicolon instead of a field.
-
-     In C++, this may wind up being NAME:?TYPENUM:PHYSNAME; for
-     a static field.
-
-     The `?' is a placeholder for one of '+' (public visibility),
-     '0' (protected visibility), and '-' (private visibility).  */
-
-  while (**pp != ';')
-    {
-      int visibility;
-
-      /* Check for and handle cretinous dbx symbol name continuation!  */
-      if (**pp == '\\') *pp = next_symbol_text ();
-
-      /* Get space to record the next field's data.  */
-      new = (struct nextfield *) alloca (sizeof (struct nextfield));
-      new->next = list;
-      list = new;
-
-      /* Read the data.  */
-      p = *pp;
-      while (*p != ':') p++;
-      list->field.name = obsavestring (*pp, p - *pp);
-
-      /* 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.  */
-      if (**pp == '/')
-       {
-         switch (*++*pp)
-           {
-           case '0':
-             visibility = 0;
-             *pp += 1;
-             break;
-
-           case '1':
-             visibility = 1;
-             *pp += 1;
-             break;
-
-           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.",
-              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++;
-    }
-
-  /* Now come the method fields, as NAME::methods
-     where each method is of the form TYPENUM,ARGS,...:PHYSNAME;
-     At the end, we see a semicolon instead of a field.
-
-     For the case of overloaded operators, the format is
-     OPERATOR::*.methods, where OPERATOR is the string "operator",
-     `*' holds the place for an operator name (such as `+=')
-     and `.' marks the end of the operator name.  */
-  if (p[1] == ':')
-    {
-      /* Now, read in the methods.  To simplify matters, we
-        "unread" the name that has been read, so that we can
-        start from the top.  */
-
-      p = *pp;
-
-      /* chill the list of fields: the last entry (at the head)
-         is a partially constructed entry which we now scrub.  */
-      list = list->next;
-
-      /* For each list of method lists... */
-      do
-       {
-         int i;
-         struct next_fnfield *sublist = 0;
-         struct fn_field *fn_fields = 0;
-         int length = 0;
-         struct next_fnfieldlist *new_mainlist =
-           (struct next_fnfieldlist *)alloca (sizeof (struct next_fnfieldlist));
-
-         /* read in the name.  */
-         while (*p != ':') p++;
-         if ((*pp)[0] == 'o' && (*pp)[1] == 'p' && (*pp)[2] == '$')
-           {
-             static char opname[32] = "operator ";
-             char *o = opname + 9;
-
-             /* Skip past '::'.  */
-             p += 2;
-             while (*p != '.')
-               *o++ = *p++;
-             new_mainlist->fn_fieldlist.name = savestring (opname, o - opname);
-             /* Skip past '.'  */
-             *pp = p + 1;
-           }
-         else
-           {
-             i = 0;
-             new_mainlist->fn_fieldlist.name = savestring (*pp, p - *pp);
-             /* Skip past '::'.  */
-             *pp = p + 2;
-           }
-
-         do
-           {
-             struct next_fnfield *new_sublist =
-               (struct next_fnfield *)alloca (sizeof (struct next_fnfield));
-
-             /* Check for and handle cretinous dbx symbol name continuation!  */
-             if (**pp == '\\') *pp = next_symbol_text ();
-
-             new_sublist->fn_field.type = read_type (pp);
-             new_sublist->fn_field.args = read_args (pp, ':');
-             p = *pp;
-             while (*p != ';') p++;
-             new_sublist->fn_field.physname = savestring (*pp, p - *pp);
-             *pp = p + 1;
-             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;
-
-             new_sublist->next = sublist;
-             sublist = new_sublist;
-             length++;
-           }
-         while (**pp != ';');
-
-         *pp += 1;
-
-         new_mainlist->fn_fieldlist.fn_fields =
-           (struct fn_field *) obstack_alloc (symbol_obstack,
-                                              sizeof (struct fn_field) * length);
-         TYPE_FN_PRIVATE_BITS (new_mainlist->fn_fieldlist) =
-           (int *) obstack_alloc (symbol_obstack,
-                                  sizeof (int) * (1 + (length >> 5)));
-
-         TYPE_FN_PROTECTED_BITS (new_mainlist->fn_fieldlist) =
-           (int *) obstack_alloc (symbol_obstack,
-                                  sizeof (int) * (1 + (length >> 5)));
-
-         for (i = length; sublist; sublist = sublist->next)
-           {
-             new_mainlist->fn_fieldlist.fn_fields[--i] = sublist->fn_field;
-             if (sublist->visibility == 0)
-               B_SET (new_mainlist->fn_fieldlist.private_fn_field_bits, i);
-             else if (sublist->visibility == 1)
-               B_SET (new_mainlist->fn_fieldlist.protected_fn_field_bits, i);
-           }
-
-         new_mainlist->fn_fieldlist.length = length;
-         new_mainlist->next = mainlist;
-         mainlist = new_mainlist;
-         nfn_fields++;
-       }
-      while (**pp != ';');
-    }
-  *pp += 1;
-
-  /* Now create the vector of fields, and record how big it is.  */
-
-  TYPE_NFIELDS (type) = nfields;
-  TYPE_FIELDS (type) = (struct field *) obstack_alloc (symbol_obstack,
-                                                      sizeof (struct field) * nfields);
-  TYPE_FIELD_PRIVATE_BITS (type) =
-    (int *) obstack_alloc (symbol_obstack,
-                          sizeof (int) * (1 + (nfields >> 5)));
-  TYPE_FIELD_PROTECTED_BITS (type) =
-    (int *) obstack_alloc (symbol_obstack,
-                          sizeof (int) * (1 + (nfields >> 5)));
-
-  TYPE_NFN_FIELDS (type) = nfn_fields;
-  TYPE_NFN_FIELDS_TOTAL (type) = nfn_fields;
-  if (baseclass)
-    TYPE_NFN_FIELDS_TOTAL (type) += TYPE_NFN_FIELDS_TOTAL (baseclass);
-
-  TYPE_FN_FIELDLISTS (type) =
-    (struct fn_fieldlist *) obstack_alloc (symbol_obstack,
-                                          sizeof (struct fn_fieldlist) * nfn_fields);
-
-  /* Copy the saved-up fields into the field vector.  */
-
-  for (n = nfields; list; list = list->next)
-    {
-      TYPE_FIELD (type, --n) = list->field;
-      if (list->visibility == 0)
-       SET_TYPE_FIELD_PRIVATE (type, n);
-      else if (list->visibility == 1)
-       SET_TYPE_FIELD_PROTECTED (type, n);
-    }
-
-  for (n = nfn_fields; mainlist; mainlist = mainlist->next)
-    TYPE_FN_FIELDLISTS (type)[--n] = mainlist->fn_fieldlist;
-
-  if (**pp == '~')
-    {
-      *pp += 1;
+  int val;
+  bfd *sym_bfd = objfile->obfd;
+  char *name = bfd_get_filename (sym_bfd);
+  struct dbx_symfile_info *info;
+
+  /* There is already a dbx_symfile_info allocated by our caller.
+     It might even contain some info from the ELF symtab to help us.  */
+  info = (struct dbx_symfile_info *) objfile->sym_private;
+
+  DBX_TEXT_SECT (objfile) = bfd_get_section_by_name (sym_bfd, ".text");
+  if (!DBX_TEXT_SECT (objfile))
+    error ("Can't find .text section in symbol file");
+
+#define        ELF_STABS_SYMBOL_SIZE   12      /* XXX FIXME XXX */
+  DBX_SYMBOL_SIZE    (objfile) = ELF_STABS_SYMBOL_SIZE;
+  DBX_SYMCOUNT       (objfile) = stabsize / DBX_SYMBOL_SIZE (objfile);
+  DBX_STRINGTAB_SIZE (objfile) = stabstrsize;
+  DBX_SYMTAB_OFFSET  (objfile) = staboffset;
+  
+  if (stabstrsize < 0) /* FIXME:  stabstrsize is unsigned; never true! */
+    error ("ridiculous string table size: %d bytes", stabstrsize);
+  DBX_STRINGTAB (objfile) = (char *)
+    obstack_alloc (&objfile->psymbol_obstack, stabstrsize+1);
 
-      if (**pp == '=')
-       {
-         TYPE_FLAGS (type)
-           |= TYPE_FLAG_HAS_CONSTRUCTOR | TYPE_FLAG_HAS_DESTRUCTOR;
-         *pp += 1;
-       }
-      else if (**pp == '+')
-       {
-         TYPE_FLAGS (type) |= TYPE_FLAG_HAS_CONSTRUCTOR;
-         *pp += 1;
-       }
-      else if (**pp == '-')
-       {
-         TYPE_FLAGS (type) |= TYPE_FLAG_HAS_DESTRUCTOR;
-         *pp += 1;
-       }
+  /* Now read in the string table in one big gulp.  */
 
-      /* Read either a '%' or the final ';'.  */
-      if (*(*pp)++ == '%')
-       {
-         /* Now we must record the virtual function table pointer's
-            field information.  */
+  val = bfd_seek (sym_bfd, stabstroffset, L_SET);
+  if (val < 0)
+    perror_with_name (name);
+  val = bfd_read (DBX_STRINGTAB (objfile), stabstrsize, 1, sym_bfd);
+  if (val != stabstrsize)
+    perror_with_name (name);
 
-         struct type *t;
-         int i;
+  stabsread_new_init ();
+  buildsym_new_init ();
+  free_header_files ();
+  init_header_files ();
+  install_minimal_symbols (objfile);
 
-         t = read_type (pp);
-         p = (*pp)++;
-         while (*p != ';') p++;
-         TYPE_VPTR_BASETYPE (type) = t;
-         if (type == t)
-           {
-             if (TYPE_FIELD_NAME (t, 0) == 0)
-               TYPE_VPTR_FIELDNO (type) = i = 0;
-             else for (i = TYPE_NFIELDS (t) - 1; i >= 0; --i)
-               if (! strncmp (TYPE_FIELD_NAME (t, i), *pp,
-                              strlen (TYPE_FIELD_NAME (t, i))))
-                 {
-                   TYPE_VPTR_FIELDNO (type) = i;
-                   break;
-                 }
-             if (i < 0)
-               error ("virtual function table field not found");
-           }
-         else
-           TYPE_VPTR_FIELDNO (type) = TYPE_VPTR_FIELDNO (TYPE_BASECLASS (type, 1));
-         *pp = p + 1;
-       }
-      else
-       {
-         TYPE_VPTR_BASETYPE (type) = 0;
-         TYPE_VPTR_FIELDNO (type) = -1;
-       }
-    }
-  else
-    {
-      TYPE_VPTR_BASETYPE (type) = 0;
-      TYPE_VPTR_FIELDNO (type) = -1;
-    }
+  processing_acc_compilation = 1;
 
-  return type;
+  /* In an elf file, we've already installed the minimal symbols that came
+     from the elf (non-stab) symbol table, so always act like an
+     incremental load here. */
+  dbx_symfile_read (objfile, section_offsets, 0);
 }
+\f
+/* Parse the user's idea of an offset for dynamic linking, into our idea
+   of how to represent it for fast symbol reading.  */
 
-/* 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.  */
-
-static struct type *
-read_enum_type (pp, type)
-     register char **pp;
-     register struct type *type;
+struct section_offsets *
+dbx_symfile_offsets (objfile, addr)
+     struct objfile *objfile;
+     CORE_ADDR addr;
 {
-  register char *p;
-  char *name;
-  register long n;
-  register struct symbol *sym;
-  int nsyms = 0;
-  struct pending **symlist;
-  struct pending *osyms, *syms;
-  int o_nsyms;
-
-  if (within_function)
-    symlist = &local_symbols;
-  else
-    symlist = &file_symbols;
-  osyms = *symlist;
-  o_nsyms = osyms ? osyms->nsyms : 0;
-
-  /* Read the value-names and their values.
-     The input syntax is NAME:VALUE,NAME:VALUE, and so on.
-     A semicolon instead of a NAME means the end.  */
-  while (**pp && **pp != ';')
-    {
-      /* Check for and handle cretinous dbx symbol name continuation!  */
-      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;
-      SYMBOL_CLASS (sym) = LOC_CONST;
-      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
-      SYMBOL_VALUE (sym) = n;
-      add_symbol_to_list (sym, symlist);
-      nsyms++;
-    }
-
-  (*pp)++;                     /* Skip the semicolon.  */
-
-  /* Now fill in the fields of the type-structure.  */
-
-  TYPE_LENGTH (type) = sizeof (int);
-  TYPE_CODE (type) = TYPE_CODE_ENUM;
-  TYPE_NFIELDS (type) = nsyms;
-  TYPE_FIELDS (type) = (struct field *) obstack_alloc (symbol_obstack, sizeof (struct field) * nsyms);
-
-  /* Find the symbols for the values and put them into the type.
-     The symbols can be found in the symlist that we put them on
-     to cause them to be defined.  osyms contains the old value
-     of that symlist; everything up to there was defined by us.  */
-
-  for (syms = *symlist, n = nsyms; syms; syms = syms->next)
-    {
-      int j = 0;
-      if (syms == osyms)
-       j = o_nsyms;
-      for (; j < syms->nsyms; j++)
-       {
-         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;
-       }
-      if (syms == osyms)
-       break;
-    }
-
-  return type;
-}
+  struct section_offsets *section_offsets;
+  int i;
+  section_offsets = (struct section_offsets *)
+    obstack_alloc (&objfile -> psymbol_obstack,
+                  sizeof (struct section_offsets) +
+                         sizeof (section_offsets->offsets) * (SECT_OFF_MAX-1));
+
+  for (i = 0; i < SECT_OFF_MAX; i++)
+    ANOFFSET (section_offsets, i) = addr;
   
-static struct type *
-read_range_type (pp, typenums)
-     char **pp;
-     int typenums[2];
-{
-  char *errp = *pp;
-  int rangenums[2];
-  int n1, n2, n3;
-
-  /* First comes a type we are a subrange of.
-     In practice it is usually 0, 1 or the type being defined.  */
-  read_type_number (pp, rangenums);
-  n1 = rangenums[1];
-
-  /* A semicolon should now follow; skip it.  */
-  if (**pp == ';')
-    (*pp)++;
-
-  /* The remaining two operands are usually lower and upper bounds
-     of the range.  But in some special cases they mean something else.  */
-  n2 = read_number (pp, ';');
-  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)
-    return builtin_type_void;
-
-  /* If n3 is zero and n2 is not, we want a floating type,
-     and n2 is the width in bytes.
-
-     Fortran programs appear to use this for complex types also,
-     and they give no way to distinguish between double and single-complex!
-     We don't have complex types, so we would lose on all fortran files!
-     So return type `double' for all of those.  It won't work right
-     for the complex values, but at least it makes the file loadable.  */
-
-  if (n3 == 0 && n2 > 0)
-    {
-      if (n2 == sizeof (float))
-       return builtin_type_float;
-      return builtin_type_double;
-    }
-
-  /* If the upper bound is -1, it must really be an unsigned int.  */
-
-  else if (n2 == 0 && n3 == -1)
-    {
-      if (sizeof (int) == sizeof (long))
-       return builtin_type_unsigned_int;
-      else
-       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.  */
-
-  else if (n2 == 0 && n1 == 1)
-    {
-      /* an unsigned type */
-      if (n3 == (1 << (8 * sizeof (int))) - 1)
-       return builtin_type_unsigned_int;
-      if (n3 == (1 << (8 * sizeof (short))) - 1)
-       return builtin_type_unsigned_short;
-      if (n3 == (1 << (8 * sizeof (char))) - 1)
-       return builtin_type_unsigned_char;
-    }
-  else
-    {
-      /* a signed type */
-      if (n3 == (1 << (8 * sizeof (int) - 1)) - 1)
-       return builtin_type_int;
-      if (n3 == (1 << (8 * sizeof (long) - 1)) - 1)
-        return builtin_type_long;
-      if (n3 == (1 << (8 * sizeof (short) - 1)) - 1)
-       return builtin_type_short;
-      if (n3 == (1 << (8 * sizeof (char) - 1)) - 1)
-       return builtin_type_char;
-    }
-  error ("Invalid symbol data: range type spec %s at symtab pos %d.",
-        errp - 1, symnum);
+  return section_offsets;
 }
-
-/* Read a number from the string pointed to by *PP.
-   The value of *PP is advanced over the number.
-   If END is nonzero, the character that ends the
-   number must match END, or an error happens;
-   and that character is skipped if it does match.
-   If END is zero, *PP is left pointing to that character.  */
-
-static long
-read_number (pp, end)
-     char **pp;
-     int end;
+\f
+/* Register our willingness to decode symbols for SunOS and a.out and
+   b.out files handled by BFD... */
+static struct sym_fns sunos_sym_fns =
 {
-  register char *p = *pp;
-  register long n = 0;
-  register int c;
-  int sign = 1;
-
-  /* Handle an optional leading minus sign.  */
-
-  if (*p == '-')
-    {
-      sign = -1;
-      p++;
-    }
-
-  /* Read the digits, as far as they go.  */
-
-  while ((c = *p++) >= '0' && c <= '9')
-    {
-      n *= 10;
-      n += c - '0';
-    }
-  if (end)
-    {
-      if (c != end)
-       error ("Invalid symbol data: invalid character \\%03o at symbol pos %d.", c, symnum);
-    }
-  else
-    --p;
-
-  *pp = p;
-  return n * sign;
-}
+  "sunOs",             /* sym_name: name or name prefix of BFD target type */
+  6,                   /* sym_namelen: number of significant sym_name chars */
+  dbx_new_init,                /* sym_new_init: init anything gbl to entire symtab */
+  dbx_symfile_init,    /* sym_init: read initial info, setup for sym_read() */
+  dbx_symfile_read,    /* sym_read: read a symbol file into symtab */
+  dbx_symfile_finish,  /* sym_finish: finished with file, cleanup */
+  dbx_symfile_offsets, /* sym_offsets: parse user's offsets to internal form */
+  NULL                 /* next: pointer to next struct sym_fns */
+};
 
-/* Read in an argument list. This is a list of types. It is terminated with
-   a ':', FYI. Return the list of types read in. */
-static struct type **
-read_args (pp, end)
-     char **pp;
-     int end;
+static struct sym_fns aout_sym_fns =
 {
-  struct type *types[1024], **rval; /* allow for fns of 1023 parameters */
-  int n = 0;
-
-  while (**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!  */
-      if (**pp == '\\')
-       *pp = next_symbol_text ();
-      
-      types[n++] = read_type (pp);
-    }
-  *pp += 1;                    /* get past `end' (the ':' character) */
-
-  if (n == 1)
-    {
-      rval = (struct type **) xmalloc (2 * sizeof (struct type *));
-    }
-  else if (TYPE_CODE (types[n-1]) != TYPE_CODE_VOID)
-    {
-      rval = (struct type **) xmalloc ((n + 1) * sizeof (struct type *));
-      bzero (rval + n, sizeof (struct type *));
-    }
-  else
-    {
-      rval = (struct type **) xmalloc (n * sizeof (struct type *));
-    }
-  bcopy (types, rval, n * sizeof (struct type *));
-  return rval;
-}
+  "a.out",             /* sym_name: name or name prefix of BFD target type */
+  5,                   /* sym_namelen: number of significant sym_name chars */
+  dbx_new_init,                /* sym_new_init: init anything gbl to entire symtab */
+  dbx_symfile_init,    /* sym_init: read initial info, setup for sym_read() */
+  dbx_symfile_read,    /* sym_read: read a symbol file into symtab */
+  dbx_symfile_finish,  /* sym_finish: finished with file, cleanup */
+  dbx_symfile_offsets, /* sym_offsets: parse user's offsets to internal form */
+  NULL                 /* next: pointer to next struct sym_fns */
+};
 
-/* This function is really horrible, but to avoid it, there would need
-   to be more filling in of forward references.  */
-int
-fill_in_vptr_fieldno (type)
-     struct type *type;
+static struct sym_fns bout_sym_fns =
 {
-  if (TYPE_VPTR_FIELDNO (type) < 0)
-    TYPE_VPTR_FIELDNO (type) = fill_in_vptr_fieldno (TYPE_BASECLASS (type, 1));
-  return TYPE_VPTR_FIELDNO (type);
-}
+  "b.out",             /* sym_name: name or name prefix of BFD target type */
+  5,                   /* sym_namelen: number of significant sym_name chars */
+  dbx_new_init,                /* sym_new_init: init anything gbl to entire symtab */
+  dbx_symfile_init,    /* sym_init: read initial info, setup for sym_read() */
+  dbx_symfile_read,    /* sym_read: read a symbol file into symtab */
+  dbx_symfile_finish,  /* sym_finish: finished with file, cleanup */
+  dbx_symfile_offsets, /* sym_offsets: parse user's offsets to internal form */
+  NULL                 /* next: pointer to next struct sym_fns */
+};
 
-static
-initialize ()
+/* This is probably a mistake.  FIXME.  Why can't the HP's use an ordinary
+   file format name with an -hppa suffix?  */
+static struct sym_fns hppa_sym_fns =
 {
-  symfile = 0;
-
-  add_com ("symbol-file", class_files, symbol_file_command,
-          "Load symbol table (in dbx format) from executable file FILE.");
+  "hppa",              /* sym_name: name or name prefix of BFD target type */
+  4,                   /* sym_namelen: number of significant sym_name chars */
+  dbx_new_init,                /* sym_new_init: init anything gbl to entire symtab */
+  dbx_symfile_init,    /* sym_init: read initial info, setup for sym_read() */
+  dbx_symfile_read,    /* sym_read: read a symbol file into symtab */
+  dbx_symfile_finish,  /* sym_finish: finished with file, cleanup */
+  dbx_symfile_offsets, /* sym_offsets: parse user's offsets to internal form */
+  NULL                 /* next: pointer to next struct sym_fns */
+};
 
-  add_com ("add-file", class_files, add_file_command,
-           "Load the symbols from FILE, assuming its codes is at TEXT_START.") ;
+void
+_initialize_dbxread ()
+{
+  add_symtab_fns(&sunos_sym_fns);
+  add_symtab_fns(&aout_sym_fns);
+  add_symtab_fns(&bout_sym_fns);
+  add_symtab_fns(&hppa_sym_fns);
 }
-
-END_FILE
-
-#endif /* READ_DBX_FORMAT */
This page took 0.078331 seconds and 4 git commands to generate.