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