OSDN Git Service

* mn10300.md (adddi3, subdi3): Remove expanders and patterns.
[pf3gnuchains/gcc-fork.git] / gcc / mips-tfile.c
index 32cd7da..4cd18d0 100644 (file)
@@ -2,9 +2,9 @@
    contain debugging information specified by the GNU compiler
    in the form of comments (the mips assembler does not support
    assembly access to debug information).
-   Contributed by:  Michael Meissner, meissner@osf.org
-   Copyright (C) 1991 Free Software Foundation, Inc.
-
+   Copyright (C) 1991, 1993, 1994. 1995 Free Software Foundation, Inc.
+   Contributed by Michael Meissner, meissner@osf.org
+   
 This file is part of GNU CC.
 
 GNU CC is free software; you can redistribute it and/or modify
@@ -19,7 +19,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 \f
 /* Here is a brief description of the MIPS ECOFF symbol table.  The
@@ -193,7 +194,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
            stLocal       -- local variable
            stLabel       -- label
            stProc        -- External Procedure
-           stBlock       -- beginnning of block
+           stBlock       -- beginning of block
            stEnd         -- end (of anything)
            stMember      -- member (of anything)
            stTypedef     -- type definition
@@ -262,7 +263,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        Procedures Tables            384           1          52
        Local Symbols                436          16         192
        Optimization Symbols           0           0           0
-       Auxilary Symbols             628          39         156
+       Auxiliary Symbols            628          39         156
        Local Strings                784          80          80
        External Strings             864         144         144
        File Tables                 1008           2         144
@@ -598,9 +599,13 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 */
 \f
 
-#include <stdio.h>
-#include "gvarargs.h"
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
 #include "config.h"
+#include <stdio.h>
 
 #ifndef __SABER__
 #define saber_stop()
@@ -614,6 +619,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 typedef void *PTR_T;
 typedef const void *CPTR_T;
 #define __proto(x) x
+#ifndef VPROTO
+#define PVPROTO(ARGS)          ARGS
+#define VPROTO(ARGS)            ARGS
+#define VA_START(va_list,var)  va_start(va_list,var)
+#endif
 #else
 
 #if defined(_STDIO_H_) || defined(__STDIO_H__)         /* Ultrix 4.0, SGI */
@@ -627,6 +637,11 @@ typedef char *CPTR_T;
 
 #define __proto(x) ()
 #define const
+#ifndef VPROTO
+#define PVPROTO(ARGS)          ()
+#define VPROTO(ARGS)            (va_alist) va_dcl
+#define VA_START(va_list,var)  va_start(va_list)
+#endif
 #endif
 
 /* Do to size_t being defined in sys/types.h and different
@@ -637,8 +652,12 @@ typedef char *CPTR_T;
    the fact that including stddef.h gets you GCC's version
    instead of the standard one it's not worth it to fix it.  */
 
+#if defined(__OSF1__) || defined(__OSF__) || defined(__osf__)
+#define Size_t         long unsigned int
+#else
 #define Size_t         unsigned int
-#define Ptrdiff_t      int
+#endif
+#define Ptrdiff_t      long
 
 /* The following might be called from obstack or malloc,
    so they can't be static.  */
@@ -652,8 +671,14 @@ extern PTR_T       xcalloc         __proto((Size_t, Size_t));
 extern PTR_T   xrealloc        __proto((PTR_T, Size_t));
 extern void    xfree           __proto((PTR_T));
 
-extern void    fatal();        /* can't use prototypes here */
-extern void    error();
+#ifdef HAVE_VPRINTF
+extern void    fatal           PVPROTO((const char *format, ...));
+extern void    error           PVPROTO((const char *format, ...));
+#else
+/* We must not provide any prototype here, even if ANSI C.  */
+extern void    fatal           __proto(());
+extern void    error           __proto(());
+#endif
 
 \f
 #ifndef MIPS_DEBUGGING_INFO
@@ -674,9 +699,13 @@ main ()
 
 #else                          /* MIPS_DEBUGGING defined */
 \f
+/* The local and global symbols have a field index, so undo any defines
+   of index -> strchr and rindex -> strrchr.  */
+
+#undef rindex
+#undef index
 
 #include <sys/types.h>
-#include <a.out.h>
 #include <string.h>
 #include <ctype.h>
 #include <fcntl.h>
@@ -684,6 +713,12 @@ main ()
 #include <signal.h>
 #include <sys/stat.h>
 
+#ifndef CROSS_COMPILE
+#include <a.out.h>
+#else
+#include "mips/a.out.h"
+#endif /* CROSS_COMPILE */
+
 #if defined (USG) || defined (NO_STAB_H)
 #include "gstab.h"  /* If doing DBX on sysV, use our own stab.h.  */
 #else
@@ -723,7 +758,7 @@ extern int errno;                   /* MIPS errno.h doesn't declare this */
   (isalnum (ch) || (ch) == '_' || (ch) == '.' || (ch) == '$')
 
 \f
-/* Redefination of of storage classes as an enumeration for better
+/* Redefinition of of storage classes as an enumeration for better
    debugging.  */
 
 typedef enum sc {
@@ -763,7 +798,7 @@ typedef enum st {
   st_Local     = stLocal,      /* local variable */
   st_Label     = stLabel,      /* label */
   st_Proc      = stProc,       /*     "      "  Procedure */
-  st_Block     = stBlock,      /* beginnning of block */
+  st_Block     = stBlock,      /* beginning of block */
   st_End       = stEnd,        /* end (of anything) */
   st_Member    = stMember,     /* member (of anything  - struct/union/enum */
   st_Typedef   = stTypedef,    /* type definition */
@@ -775,7 +810,7 @@ typedef enum st {
   st_Str       = stStr,        /* string */
   st_Number    = stNumber,     /* pure number (ie. 4 NOR 2+2) */
   st_Expr      = stExpr,       /* 2+2 vs. 4 */
-  st_Type      = stType,       /* post-coersion SER */
+  st_Type      = stType,       /* post-coercion SER */
   st_Max       = stMax         /* max type+1 */
 } st_t;
 
@@ -904,7 +939,7 @@ typedef enum coff_dt {
 typedef enum hash_state {
   hash_no      = 0,            /* don't hash type */
   hash_yes     = 1,            /* ok to hash type, or use previous hash */
-  hash_record  = 2             /* ok to record hash, but don't use prev. */
+  hash_record  = 2             /* ok to record hash, but don't use prev.  */
 } hash_state_t;
 
 
@@ -923,7 +958,7 @@ enum alloc_type {
 };
 
 \f
-#define WORD_ALIGN(x)  (((x) + 3) & ~3)
+#define WORD_ALIGN(x)  (((x) + (sizeof (long) - 1)) & ~ (sizeof (long) - 1))
 #define DWORD_ALIGN(x) (((x) + 7) & ~7)
 
 
@@ -979,15 +1014,15 @@ typedef struct varray {
 #endif
 
 #define INIT_VARRAY(type) {    /* macro to initialize a varray */      \
-  (vlinks_t *)0,               /* first */                             \
-  (vlinks_t *)0,               /* last */                              \
+  (vlinks_t *) 0,              /* first */                             \
+  (vlinks_t *) 0,              /* last */                              \
   0,                           /* num_allocated */                     \
   sizeof (type),               /* object_size */                       \
   OBJECTS_PER_PAGE (type),     /* objects_per_page */                  \
   OBJECTS_PER_PAGE (type),     /* objects_last_page */                 \
 }
 
-/* Master type for indexes within the symbol table. */
+/* Master type for indexes within the symbol table.  */
 typedef unsigned long symint_t;
 
 
@@ -1021,7 +1056,7 @@ typedef struct tag {
   struct forward *forward_ref; /* list of forward references */
   bt_t           basic_type;   /* bt_Struct, bt_Union, or bt_Enum */
   symint_t       ifd;          /* file # tag defined in */
-  symint_t       index;        /* index within file's local symbols */
+  symint_t       indx;         /* index within file's local symbols */
 } tag_t;
 
 
@@ -1055,7 +1090,7 @@ typedef struct shash {
   struct shash *next;          /* next hash value */
   char         *string;        /* string we are hashing */
   symint_t      len;           /* string length */
-  symint_t      index;         /* index within string table */
+  symint_t      indx;          /* index within string table */
   EXTR         *esym_ptr;      /* global symbol pointer */
   SYMR         *sym_ptr;       /* local symbol pointer */
   SYMR         *end_ptr;       /* symbol pointer to end block */
@@ -1076,7 +1111,7 @@ typedef struct shash {
 typedef struct thash {
   struct thash *next;          /* next hash value */
   AUXU          type;          /* type we are hashing */
-  symint_t      index;         /* index within string table */
+  symint_t      indx;          /* index within string table */
 } thash_t;
 
 
@@ -1125,7 +1160,7 @@ static efdr_t init_file =
     langC,             /* lang:        language for this file */
     1,                 /* fMerge:      whether this file can be merged */
     0,                 /* fReadin:     true if read in (not just created) */
-#if BYTES_BIG_ENDIAN
+#ifdef HOST_WORDS_BIG_ENDIAN
     1,                 /* fBigendian:  if 1, compiled on big endian machine */
 #else
     0,                 /* fBigendian:  if 1, compiled on big endian machine */
@@ -1136,12 +1171,12 @@ static efdr_t init_file =
     0,                 /* cbLine:      size of lines for this file */
   },
 
-  (FDR *)0,            /* orig_fdr:    original file header pointer */
-  (char *)0,           /* name:        pointer to filename */
+  (FDR *) 0,           /* orig_fdr:    original file header pointer */
+  (char *) 0,          /* name:        pointer to filename */
   0,                   /* name_len:    length of filename */
   0,                   /* void_type:   ptr to aux node for void type */
   0,                   /* int_type:    ptr to aux node for int type */
-  (scope_t *)0,                /* cur_scope:   current scope being processed */
+  (scope_t *) 0,       /* cur_scope:   current scope being processed */
   0,                   /* file_index:  current file # */
   0,                   /* nested_scopes: # nested scopes */
   INIT_VARRAY (char),  /* strings:     local string varray */
@@ -1149,9 +1184,9 @@ static efdr_t init_file =
   INIT_VARRAY (PDR),   /* procs:       procedure varray */
   INIT_VARRAY (AUXU),  /* aux_syms:    auxiliary symbols varray */
 
-  (struct efdr *)0,    /* next_file:   next file structure */
+  (struct efdr *) 0,   /* next_file:   next file structure */
 
-  (shash_t **)0,       /* shash_head:  string hash table */
+  (shash_t **) 0,      /* shash_head:  string hash table */
   { 0 },               /* thash_head:  type hash table */
 };
 
@@ -1555,17 +1590,17 @@ static EXTR     *orig_ext_syms;                 /* external symbols */
 #define CHECK(num,max,str) \
   (((unsigned long)num > (unsigned long)max) ? out_of_bounds (num, max, str, __LINE__) : 0)
 
-#define ORIG_LINENUM(index)    (CHECK ((index), orig_sym_hdr.cbLine,    "line#"), (index) + orig_linenum)
-#define ORIG_DENSE(index)      (CHECK ((index), orig_sym_hdr.idnMax,    "dense"), (index) + orig_dense)
-#define ORIG_PROCS(index)      (CHECK ((index), orig_sym_hdr.ipdMax,    "procs"), (index) + orig_procs)
-#define ORIG_FILES(index)      (CHECK ((index), orig_sym_hdr.ifdMax,    "funcs"), (index) + orig_files)
-#define ORIG_LSYMS(index)      (CHECK ((index), orig_sym_hdr.isymMax,   "lsyms"), (index) + orig_local_syms)
-#define ORIG_LSTRS(index)      (CHECK ((index), orig_sym_hdr.issMax,    "lstrs"), (index) + orig_local_strs)
-#define ORIG_ESYMS(index)      (CHECK ((index), orig_sym_hdr.iextMax,   "esyms"), (index) + orig_ext_syms)
-#define ORIG_ESTRS(index)      (CHECK ((index), orig_sym_hdr.issExtMax, "estrs"), (index) + orig_ext_strs)
-#define ORIG_OPT(index)                (CHECK ((index), orig_sym_hdr.ioptMax,   "opt"),   (index) + orig_opt_syms)
-#define ORIG_AUX(index)                (CHECK ((index), orig_sym_hdr.iauxMax,   "aux"),   (index) + orig_aux_syms)
-#define ORIG_RFDS(index)       (CHECK ((index), orig_sym_hdr.crfd,      "rfds"),  (index) + orig_rfds)
+#define ORIG_LINENUM(indx)     (CHECK ((indx), orig_sym_hdr.cbLine,    "line#"), (indx) + orig_linenum)
+#define ORIG_DENSE(indx)       (CHECK ((indx), orig_sym_hdr.idnMax,    "dense"), (indx) + orig_dense)
+#define ORIG_PROCS(indx)       (CHECK ((indx), orig_sym_hdr.ipdMax,    "procs"), (indx) + orig_procs)
+#define ORIG_FILES(indx)       (CHECK ((indx), orig_sym_hdr.ifdMax,    "funcs"), (indx) + orig_files)
+#define ORIG_LSYMS(indx)       (CHECK ((indx), orig_sym_hdr.isymMax,   "lsyms"), (indx) + orig_local_syms)
+#define ORIG_LSTRS(indx)       (CHECK ((indx), orig_sym_hdr.issMax,    "lstrs"), (indx) + orig_local_strs)
+#define ORIG_ESYMS(indx)       (CHECK ((indx), orig_sym_hdr.iextMax,   "esyms"), (indx) + orig_ext_syms)
+#define ORIG_ESTRS(indx)       (CHECK ((indx), orig_sym_hdr.issExtMax, "estrs"), (indx) + orig_ext_strs)
+#define ORIG_OPT(indx)         (CHECK ((indx), orig_sym_hdr.ioptMax,   "opt"),   (indx) + orig_opt_syms)
+#define ORIG_AUX(indx)         (CHECK ((indx), orig_sym_hdr.iauxMax,   "aux"),   (indx) + orig_aux_syms)
+#define ORIG_RFDS(indx)                (CHECK ((indx), orig_sym_hdr.crfd,      "rfds"),  (indx) + orig_rfds)
 
 /* Various other statics.  */
 static HDRR    symbolic_header;                /* symbolic header */
@@ -1574,17 +1609,17 @@ static PDR     *cur_proc_ptr    = (PDR *) 0;    /* current procedure header */
 static SYMR    *cur_oproc_begin        = (SYMR *) 0;   /* original proc. sym begin info */
 static SYMR    *cur_oproc_end  = (SYMR *) 0;   /* original proc. sym end info */
 static PDR     *cur_oproc_ptr  = (PDR *) 0;    /* current original procedure*/
-static thead_t *cur_tag_head   = (thead_t *)0; /* current tag head */
+static thead_t *cur_tag_head   = (thead_t *) 0;/* current tag head */
 static long    file_offset     = 0;            /* current file offset */
 static long    max_file_offset = 0;            /* maximum file offset */
-static FILE    *object_stream  = (FILE *)0;    /* file desc. to output .o */
-static FILE    *obj_in_stream  = (FILE *)0;    /* file desc. to input .o */
-static char    *progname       = (char *)0;    /* program name for errors */
+static FILE    *object_stream  = (FILE *) 0;   /* file desc. to output .o */
+static FILE    *obj_in_stream  = (FILE *) 0;   /* file desc. to input .o */
+static char    *progname       = (char *) 0;   /* program name for errors */
 static char    *input_name     = "stdin";      /* name of input file */
-static char    *object_name    = (char *)0;    /* tmp. name of object file */
-static char    *obj_in_name    = (char *)0;    /* name of input object file */
-static char    *cur_line_start = (char *)0;    /* current line read in */
-static char    *cur_line_ptr   = (char *)0;    /* ptr within current line */
+static char    *object_name    = (char *) 0;   /* tmp. name of object file */
+static char    *obj_in_name    = (char *) 0;   /* name of input object file */
+static char    *cur_line_start = (char *) 0;   /* current line read in */
+static char    *cur_line_ptr   = (char *) 0;   /* ptr within current line */
 static unsigned        cur_line_nbytes = 0;            /* # bytes for current line */
 static unsigned        cur_line_alloc  = 0;            /* # bytes total in buffer */
 static long    line_number     = 0;            /* current input line number */
@@ -1717,65 +1752,25 @@ STATIC void       free_scope            __proto((scope_t *));
 STATIC void      free_tag              __proto((tag_t *));
 STATIC void      free_thead            __proto((thead_t *));
 
-/* rms: The following is a very bad idea.
-   It's easy for these to conflict with definitions on certain systems.
-   All system calls and library functions
-   for which an implicit definition will work
-   should be left implicit.
-   I deleted the declarations for open and fstat.  */
-/* Prototypes for library functions used.  */
-#if !defined(NO_LIB_PROTOTYPE) && !defined(_OSF_SOURCE) && !defined(_STDIO_H_)
-extern char  *strchr           __proto((const char *, int));
-extern char  *strrchr          __proto((const char *, int));
-extern int    strcmp           __proto((const char *, const char *));
-extern long   strtol           __proto((const char *, char **, int));
-extern int    memcmp           __proto((CPTR_T, CPTR_T, Size_t));
-extern time_t time             __proto((time_t *));
-extern int    fputc            __proto((int, FILE *));
-extern int    vprintf          __proto((const char *, va_list));
-extern int    vfprintf         __proto((FILE *, const char *, va_list));
-extern int    vsprintf         __proto((char *, const char *, va_list));
-extern int    fclose           __proto((FILE *));
-extern int    fseek            __proto((FILE *, long, int));
-extern long   ftell            __proto((FILE *));
-extern FILE  *fopen            __proto((const char *, const char *));
-extern FILE  *freopen          __proto((const char *, const char *, FILE *));
-extern int    fflush           __proto((FILE *));
-extern void   perror           __proto((const char *));
-extern void   exit             __proto((int));
-extern int    rename           __proto((const char *, const char *));
-
-#ifndef sgi
-extern int    setvbuf          __proto((FILE *, char *, int, int));
-extern int    fputs            __proto((char *, FILE *));
-#endif
-#endif
+STATIC char     *local_index           __proto((const char *, int));
+STATIC char     *local_rindex          __proto((const char *, int));
 
-extern char  *sbrk             __proto((int));
-
-#ifndef HAS_STDLIB_H
-extern PTR_T  malloc           __proto((Size_t));
-extern PTR_T  calloc           __proto((Size_t, Size_t));
-extern PTR_T  realloc          __proto((PTR_T, Size_t));
-extern void   free             __proto((PTR_T));
-extern int    getopt           __proto((int, char **, const char *));
-#endif
-
-#ifndef HAS_UNISTD_H
-extern int    close            __proto((int));
-extern int    write            __proto((int, CPTR_T, Size_t));
-extern int    read             __proto((int, PTR_T, Size_t));
-extern long   lseek            __proto((int, long, int));
-extern int    ftruncate                __proto((int, long));
+#ifndef __alpha
+extern char  *sbrk                     __proto((int));
+extern void   free                     __proto((PTR_T));
 #endif
-
-extern char  *mktemp           __proto((char *));
+extern char  *mktemp                   __proto((char *));
+extern long   strtol                   __proto((const char *, char **, int));
 
 extern char *optarg;
 extern int   optind;
 extern int   opterr;
 extern char *version_string;
+#ifndef NO_SYS_SIGLIST
+#ifndef DONT_DECLARE_SYS_SIGLIST
 extern char *sys_siglist[NSIG + 1];
+#endif
+#endif
 
 #ifndef SEEK_SET       /* Symbolic constants for the "fseek" function: */
 #define        SEEK_SET 0      /* Set file pointer to offset */
@@ -1787,10 +1782,10 @@ extern char *sys_siglist[NSIG + 1];
 /* List of assembler pseudo ops and beginning sequences that need
    special actions.  Someday, this should be a hash table, and such,
    but for now a linear list of names and calls to memcmp will
-   do...... */
+   do......  */
 
 typedef struct _pseudo_ops {
-  const char *name;                    /* pseduo-op in ascii */
+  const char *name;                    /* pseudo-op in ascii */
   int len;                             /* length of name to compare */
   void (*func) __proto((const char *));        /* function to handle line */
 } pseudo_ops_t;
@@ -1831,7 +1826,7 @@ add_varray_page (vp)
   new_links->start_index = vp->num_allocated;
   vp->objects_last_page = 0;
 
-  if (vp->first == (vlinks_t *)0)              /* first allocation? */
+  if (vp->first == (vlinks_t *) 0)             /* first allocation? */
     vp->first = vp->last = new_links;
   else
     {                                          /* 2nd or greater allocation */
@@ -1865,10 +1860,10 @@ hash_string (text, hash_len, hash_tbl, ret_hash_index)
   hi &= (1 << HASHBITS) - 1;
   hi %= SHASH_SIZE;
 
-  if (ret_hash_index != (symint_t *)0)
+  if (ret_hash_index != (symint_t *) 0)
     *ret_hash_index = hi;
 
-  for (ptr = hash_tbl[hi]; ptr != (shash_t *)0; ptr = ptr->next)
+  for (ptr = hash_tbl[hi]; ptr != (shash_t *) 0; ptr = ptr->next)
     if (hash_len == ptr->len
        && first_ch == ptr->string[0]
        && memcmp ((CPTR_T) text, (CPTR_T) ptr->string, hash_len) == 0)
@@ -1898,14 +1893,14 @@ add_string (vp, hash_tbl, start, end_p1, ret_hash)
     fatal ("String too big (%ld bytes)", (long) len);
 
   hash_ptr = hash_string (start, len, hash_tbl, &hi);
-  if (hash_ptr == (shash_t *)0)
+  if (hash_ptr == (shash_t *) 0)
     {
       register char *p;
 
       if (vp->objects_last_page + len >= PAGE_USIZE)
        {
-         vp->num_allocated =
-           ((vp->num_allocated + PAGE_USIZE - 1) / PAGE_USIZE) * PAGE_USIZE;
+         vp->num_allocated
+           ((vp->num_allocated + PAGE_USIZE - 1) / PAGE_USIZE) * PAGE_USIZE;
          add_varray_page (vp);
        }
 
@@ -1914,9 +1909,8 @@ add_string (vp, hash_tbl, start, end_p1, ret_hash)
       hash_tbl[hi] = hash_ptr;
 
       hash_ptr->len = len;
-      hash_ptr->index = vp->num_allocated;
-      hash_ptr->string = p =
-       & vp->last->datum->byte[ vp->objects_last_page ];
+      hash_ptr->indx = vp->num_allocated;
+      hash_ptr->string = p = & vp->last->datum->byte[ vp->objects_last_page ];
 
       vp->objects_last_page += len+1;
       vp->num_allocated += len+1;
@@ -1927,10 +1921,10 @@ add_string (vp, hash_tbl, start, end_p1, ret_hash)
       *p = '\0';
     }
 
-  if (ret_hash != (shash_t **)0)
+  if (ret_hash != (shash_t **) 0)
     *ret_hash = hash_ptr;
 
-  return hash_ptr->index;
+  return hash_ptr->indx;
 }
 
 \f
@@ -1953,7 +1947,7 @@ add_local_symbol (str_start, str_end_p1, type, storage, value, indx)
   register tag_t *ptag_next;
   register varray_t *vp = &cur_file_ptr->symbols;
   register int scope_delta = 0;
-  shash_t *hash_ptr = (shash_t *)0;
+  shash_t *hash_ptr = (shash_t *) 0;
 
   if (vp->objects_last_page == vp->objects_per_page)
     add_varray_page (vp);
@@ -1964,7 +1958,7 @@ add_local_symbol (str_start, str_end_p1, type, storage, value, indx)
   psym->st = (unsigned) type;
   psym->sc = (unsigned) storage;
   psym->index = indx;
-  psym->iss = (str_start == (const char *)0)
+  psym->iss = (str_start == (const char *) 0)
                ? 0
                : add_string (&cur_file_ptr->strings,
                              &cur_file_ptr->shash_head[0],
@@ -1979,7 +1973,7 @@ add_local_symbol (str_start, str_end_p1, type, storage, value, indx)
 
   /* Save the symbol within the hash table if this is a static
      item, and it has a name.  */
-  if (hash_ptr != (shash_t *)0
+  if (hash_ptr != (shash_t *) 0
       && (type == st_Global || type == st_Static || type == st_Label
          || type == st_Proc || type == st_StaticProc))
     hash_ptr->sym_ptr = psym;
@@ -2036,10 +2030,10 @@ add_local_symbol (str_start, str_end_p1, type, storage, value, indx)
              cur_tag_head = ptag_head->prev;
 
              for (ptag = ptag_head->first_tag;
-                  ptag != (tag_t *)0;
+                  ptag != (tag_t *) 0;
                   ptag = ptag_next)
                {
-                 if (ptag->forward_ref != (forward_t *)0)
+                 if (ptag->forward_ref != (forward_t *) 0)
                    add_unknown_tag (ptag);
 
                  ptag_next = ptag->same_block;
@@ -2057,7 +2051,7 @@ add_local_symbol (str_start, str_end_p1, type, storage, value, indx)
            psym->iss = pscope->lsym->iss;      /* blk end gets same name */
 
          if (begin_type == st_File || begin_type == st_Block)
-           pscope->lsym->index = ret+1; /* block begin gets next sym # */
+           pscope->lsym->index = ret+1;        /* block begin gets next sym # */
 
          /* Functions push two or more aux words as follows:
             1st word: index+1 of the end symbol
@@ -2073,7 +2067,10 @@ add_local_symbol (str_start, str_end_p1, type, storage, value, indx)
              if (last_func_eptr)
                {
                  last_func_eptr->ifd = cur_file_ptr->file_index;
-                 last_func_eptr->asym.index = type;
+
+                 /* The index for an external st_Proc symbol is the index
+                    of the st_Proc symbol in the local symbol table.  */
+                 last_func_eptr->asym.index = psym->index;
                }
            }
 
@@ -2122,7 +2119,7 @@ add_ext_symbol (str_start, str_end_p1, type, storage, value, indx, ifd)
 {
   register EXTR *psym;
   register varray_t *vp = &ext_symbols;
-  shash_t *hash_ptr = (shash_t *)0;
+  shash_t *hash_ptr = (shash_t *) 0;
 
   if (debug > 1)
     {
@@ -2149,7 +2146,7 @@ add_ext_symbol (str_start, str_end_p1, type, storage, value, indx, ifd)
   psym->asym.st    = (unsigned) type;
   psym->asym.sc    = (unsigned) storage;
   psym->asym.index = indx;
-  psym->asym.iss   = (str_start == (const char *)0)
+  psym->asym.iss   = (str_start == (const char *) 0)
                        ? 0
                        : add_string (&ext_strings,
                                      &ext_str_hash[0],
@@ -2166,7 +2163,7 @@ add_ext_symbol (str_start, str_end_p1, type, storage, value, indx, ifd)
 
 STATIC symint_t
 add_aux_sym_symint (aux_word)
-     symint_t aux_word;                /* auxilary information word */
+     symint_t aux_word;                /* auxiliary information word */
 {
   register AUXU *aux_ptr;
   register efdr_t *file_ptr = cur_file_ptr;
@@ -2235,7 +2232,7 @@ add_aux_sym_tir (t, state, hash_tbl)
 
 
   /* For anything that adds additional information, we must not hash,
-     so check here, and reset our state. */
+     so check here, and reset our state.  */
 
   if (state != hash_no
       && (t->type_qualifiers[0] == tq_Array
@@ -2265,27 +2262,27 @@ add_aux_sym_tir (t, state, hash_tbl)
       hi %= THASH_SIZE;
 
       for (hash_ptr = hash_tbl[hi];
-          hash_ptr != (thash_t *)0;
+          hash_ptr != (thash_t *) 0;
           hash_ptr = hash_ptr->next)
        {
          if (aux.isym == hash_ptr->type.isym)
            break;
        }
 
-      if (hash_ptr != (thash_t *)0 && state == hash_yes)
-       return hash_ptr->index;
+      if (hash_ptr != (thash_t *) 0 && state == hash_yes)
+       return hash_ptr->indx;
 
-      if (hash_ptr == (thash_t *)0)
+      if (hash_ptr == (thash_t *) 0)
        {
          hash_ptr = allocate_thash ();
          hash_ptr->next = hash_tbl[hi];
          hash_ptr->type = aux;
-         hash_ptr->index = vp->num_allocated;
+         hash_ptr->indx = vp->num_allocated;
          hash_tbl[hi] = hash_ptr;
        }
     }
 
-  /* Everything is set up, add the aux symbol. */
+  /* Everything is set up, add the aux symbol.  */
   if (vp->objects_last_page == vp->objects_per_page)
     add_varray_page (vp);
 
@@ -2316,7 +2313,7 @@ add_aux_sym_tir (t, state, hash_tbl)
       || t->basic_type == bt_Enum)
     {
       register symint_t file_index = t->tag_ptr->ifd;
-      register symint_t sym_index  = t->tag_ptr->index;
+      register symint_t sym_index  = t->tag_ptr->indx;
 
       if (t->unknown_tag)
        {
@@ -2353,15 +2350,15 @@ add_aux_sym_tir (t, state, hash_tbl)
                               cur_file_ptr->int_type);
 
       (void) add_aux_sym_symint (cur_file_ptr->file_index);    /* file index*/
-      (void) add_aux_sym_symint ((symint_t)0);                 /* low bound */
+      (void) add_aux_sym_symint ((symint_t) 0);                        /* low bound */
       (void) add_aux_sym_symint (t->dimensions[i] - 1);                /* high bound*/
       (void) add_aux_sym_symint ((t->dimensions[i] == 0)       /* stride */
                              ? 0
                              : (t->sizes[i] * 8) / t->dimensions[i]);
     };
 
-  /* NOTE:  Mips documentation claism that the bitfield width goes here.
-     But it needs to be emitted earlier. */
+  /* NOTE:  Mips documentation claims that the bitfield width goes here.
+     But it needs to be emitted earlier.  */
 
   return ret;
 }
@@ -2370,10 +2367,10 @@ add_aux_sym_tir (t, state, hash_tbl)
 /* Add a tag to the tag table (unless it already exists).  */
 
 STATIC tag_t *
-get_tag (tag_start, tag_end_p1, index, basic_type)
+get_tag (tag_start, tag_end_p1, indx, basic_type)
      const char *tag_start;            /* 1st byte of tag name */
      const char *tag_end_p1;           /* 1st byte after tag name */
-     symint_t index;                   /* index of tag start block */
+     symint_t indx;                    /* index of tag start block */
      bt_t basic_type;                  /* bt_Struct, bt_Union, or bt_Enum */
 {
   shash_t *hash_ptr;
@@ -2381,17 +2378,17 @@ get_tag (tag_start, tag_end_p1, index, basic_type)
   hash_ptr = hash_string (tag_start,
                          tag_end_p1 - tag_start,
                          &tag_hash[0],
-                         (symint_t *)0);
+                         (symint_t *) 0);
 
-  if (hash_ptr != (shash_t *)0
-      && hash_ptr->tag_ptr != (tag_t *)0)
+  if (hash_ptr != (shash_t *) 0
+      && hash_ptr->tag_ptr != (tag_t *) 0)
   {
     tag_ptr = hash_ptr->tag_ptr;
-    if (index != indexNil)
+    if (indx != indexNil)
       {
        tag_ptr->basic_type = basic_type;
        tag_ptr->ifd        = cur_file_ptr->file_index;
-       tag_ptr->index      = index;
+       tag_ptr->indx       = indx;
       }
     return tag_ptr;
   }
@@ -2407,8 +2404,8 @@ get_tag (tag_start, tag_end_p1, index, basic_type)
   tag_ptr->hash_ptr    = hash_ptr;
   tag_ptr->same_name   = hash_ptr->tag_ptr;
   tag_ptr->basic_type  = basic_type;
-  tag_ptr->index       = index;
-  tag_ptr->ifd         = (index == indexNil) ? -1 : cur_file_ptr->file_index;
+  tag_ptr->indx                = indx;
+  tag_ptr->ifd         = (indx == indexNil) ? -1 : cur_file_ptr->file_index;
   tag_ptr->same_block  = cur_tag_head->first_tag;
 
   cur_tag_head->first_tag = tag_ptr;
@@ -2451,17 +2448,17 @@ add_unknown_tag (ptag)
                                name_end_p1,
                                st_Block,
                                sc_Info,
-                               (symint_t)0,
-                               (symint_t)0);
+                               (symint_t) 0,
+                               (symint_t) 0);
 
   (void) add_local_symbol (name_start,
                           name_end_p1,
                           st_End,
                           sc_Info,
-                          (symint_t)0,
-                          (symint_t)0);
+                          (symint_t) 0,
+                          (symint_t) 0);
 
-  while (f_next != (forward_t *)0)
+  while (f_next != (forward_t *) 0)
     {
       f_cur  = f_next;
       f_next = f_next->next;
@@ -2493,7 +2490,7 @@ add_procedure (func_start, func_end_p1)
   register shash_t *shash_ptr = hash_string (func_start,
                                            func_end_p1 - func_start,
                                            &orig_str_hash[0],
-                                           (symint_t *)0);
+                                           (symint_t *) 0);
 
   if (debug)
     fputc ('\n', stderr);
@@ -2507,15 +2504,14 @@ add_procedure (func_start, func_end_p1)
 
 
   /* Did the assembler create this procedure?  If so, get the PDR information.  */
-  cur_oproc_ptr = (PDR *)0;
-  if (shash_ptr != (shash_t *)0)
+  cur_oproc_ptr = (PDR *) 0;
+  if (shash_ptr != (shash_t *) 0)
     {
       register PDR *old_proc_ptr = shash_ptr->proc_ptr;
       register SYMR *sym_ptr = shash_ptr->sym_ptr;
-      register FDR *orig_fdr = file_ptr->orig_fdr;
 
-      if (old_proc_ptr != (PDR *)0
-         && sym_ptr != (SYMR *)0
+      if (old_proc_ptr != (PDR *) 0
+         && sym_ptr != (SYMR *) 0
          && ((st_t)sym_ptr->st == st_Proc || (st_t)sym_ptr->st == st_StaticProc))
        {
          cur_oproc_begin = sym_ptr;
@@ -2528,17 +2524,17 @@ add_procedure (func_start, func_end_p1)
        }
     }
 
-  if (cur_oproc_ptr == (PDR *)0)
+  if (cur_oproc_ptr == (PDR *) 0)
     error ("Did not find a PDR block for %.*s", func_end_p1 - func_start, func_start);
 
-  /* Determine the start of symbols. */
+  /* Determine the start of symbols.  */
   new_proc_ptr->isym = file_ptr->symbols.num_allocated;
 
   /* Push the start of the function.  */
   (void) add_local_symbol (func_start, func_end_p1,
                           proc_type, sc_Text,
                           value,
-                          (symint_t)0);
+                          (symint_t) 0);
 }
 
 \f
@@ -2562,7 +2558,7 @@ add_file (file_start, file_end_p1)
 
   /* See if the file has already been created.  */
   for (file_ptr = first_file;
-       file_ptr != (efdr_t *)0;
+       file_ptr != (efdr_t *) 0;
        file_ptr = file_ptr->next_file)
     {
       if (first_ch == file_ptr->name[0]
@@ -2574,14 +2570,14 @@ add_file (file_start, file_end_p1)
        }
     }
 
-  /* If this is a new file, create it. */
-  if (file_ptr == (efdr_t *)0)
+  /* If this is a new file, create it.  */
+  if (file_ptr == (efdr_t *) 0)
     {
       if (file_desc.objects_last_page == file_desc.objects_per_page)
        add_varray_page (&file_desc);
 
-      file_ptr = cur_file_ptr =
-       &file_desc.last->datum->file[ file_desc.objects_last_page++ ];
+      file_ptr = cur_file_ptr
+       &file_desc.last->datum->file[ file_desc.objects_last_page++ ];
       *file_ptr = init_file;
 
       file_ptr->file_index = file_desc.num_allocated++;
@@ -2594,7 +2590,7 @@ add_file (file_start, file_end_p1)
                  &file_ptr->shash_head[0],
                  &zero_bytes[0],
                  &zero_bytes[0],
-                 (shash_t **)0);
+                 (shash_t **) 0);
 
       if (file_end_p1 - file_start > PAGE_USIZE-2)
        fatal ("Filename goes over one page boundary.");
@@ -2602,7 +2598,7 @@ add_file (file_start, file_end_p1)
       /* Push the start of the filename. We assume that the filename
          will be stored at string offset 1.  */
       (void) add_local_symbol (file_start, file_end_p1, st_File, sc_Text,
-                              (symint_t)0, (symint_t)0);
+                              (symint_t) 0, (symint_t) 0);
       file_ptr->fdr.rss = 1;
       file_ptr->name = &file_ptr->strings.last->datum->byte[1];
       file_ptr->name_len = file_end_p1 - file_start;
@@ -2736,23 +2732,30 @@ st_to_string(symbol_type)
 }
 
 \f
-/* Read a line from standard input, and return the start of the
-   buffer (which is grows if the line is too big).  */
+/* Read a line from standard input, and return the start of the buffer
+   (which is grows if the line is too big).  We split lines at the
+   semi-colon, and return each logical line independently.  */
 
 STATIC char *
 read_line __proto((void))
 {
+  static   int line_split_p    = 0;
+  register int string_p                = 0;
+  register int comment_p       = 0;
   register int ch;
   register char *ptr;
 
-  if (cur_line_start == (char *)0)
+  if (cur_line_start == (char *) 0)
     {                          /* allocate initial page */
       cur_line_start = (char *) allocate_page ();
       cur_line_alloc = PAGE_SIZE;
     }
 
+  if (!line_split_p)
+    line_number++;
+
+  line_split_p = 0;
   cur_line_nbytes = 0;
-  line_number++;
 
   for (ptr = cur_line_start; (ch = getchar ()) != EOF; *ptr++ = ch)
     {
@@ -2775,13 +2778,34 @@ read_line __proto((void))
          cur_line_ptr = cur_line_start;
          return cur_line_ptr;
        }
+
+      else if (ch == '\0')
+       error ("Null character found in input");
+
+      else if (!comment_p)
+       {
+         if (ch == '"')
+           string_p = !string_p;
+
+         else if (ch == '#')
+           comment_p++;
+
+         else if (ch == ';' && !string_p)
+           {
+             line_split_p = 1;
+             *ptr++ = '\n';
+             *ptr = '\0';
+             cur_line_ptr = cur_line_start;
+             return cur_line_ptr;
+           }
+       }
     }
 
   if (ferror (stdin))
     pfatal_with_name (input_name);
 
-  cur_line_ptr = (char *)0;
-  return (char *)0;
+  cur_line_ptr = (char *) 0;
+  return (char *) 0;
 }
 
 \f
@@ -2796,13 +2820,13 @@ parse_begin (start)
   int ch;
   shash_t *hash_ptr;                   /* hash pointer to lookup label */
 
-  if (cur_file_ptr == (efdr_t *)0)
+  if (cur_file_ptr == (efdr_t *) 0)
     {
       error ("#.begin directive without a preceding .file directive");
       return;
     }
 
-  if (cur_proc_ptr == (PDR *)0)
+  if (cur_proc_ptr == (PDR *) 0)
     {
       error ("#.begin directive without a preceding .ent directive");
       return;
@@ -2814,24 +2838,24 @@ parse_begin (start)
   hash_ptr = hash_string (start,
                          end_p1 - start,
                          &orig_str_hash[0],
-                         (symint_t *)0);
+                         (symint_t *) 0);
 
-  if (hash_ptr == (shash_t *)0)
+  if (hash_ptr == (shash_t *) 0)
     {
       error ("Label %.*s not found for #.begin", end_p1 - start, start);
       return;
     }
 
-  if (cur_oproc_begin == (SYMR *)0)
+  if (cur_oproc_begin == (SYMR *) 0)
     {
       error ("Procedure table %.*s not found for #.begin", end_p1 - start, start);
       return;
     }
 
-  (void) add_local_symbol ((const char *)0, (const char *)0,
+  (void) add_local_symbol ((const char *) 0, (const char *) 0,
                           st_Block, sc_Text,
-                          (symint_t)hash_ptr->sym_ptr->value - cur_oproc_begin->value,
-                          (symint_t)0);
+                          (symint_t) hash_ptr->sym_ptr->value - cur_oproc_begin->value,
+                          (symint_t) 0);
 }
 
 \f
@@ -2846,13 +2870,13 @@ parse_bend (start)
   int ch;
   shash_t *hash_ptr;                   /* hash pointer to lookup label */
 
-  if (cur_file_ptr == (efdr_t *)0)
+  if (cur_file_ptr == (efdr_t *) 0)
     {
       error ("#.begin directive without a preceding .file directive");
       return;
     }
 
-  if (cur_proc_ptr == (PDR *)0)
+  if (cur_proc_ptr == (PDR *) 0)
     {
       error ("#.bend directive without a preceding .ent directive");
       return;
@@ -2864,24 +2888,24 @@ parse_bend (start)
   hash_ptr = hash_string (start,
                          end_p1 - start,
                          &orig_str_hash[0],
-                         (symint_t *)0);
+                         (symint_t *) 0);
 
-  if (hash_ptr == (shash_t *)0)
+  if (hash_ptr == (shash_t *) 0)
     {
       error ("Label %.*s not found for #.bend", end_p1 - start, start);
       return;
     }
 
-  if (cur_oproc_begin == (SYMR *)0)
+  if (cur_oproc_begin == (SYMR *) 0)
     {
       error ("Procedure table %.*s not found for #.bend", end_p1 - start, start);
       return;
     }
 
-  (void) add_local_symbol ((const char *)0, (const char *)0,
+  (void) add_local_symbol ((const char *) 0, (const char *) 0,
                           st_End, sc_Text,
                           (symint_t)hash_ptr->sym_ptr->value - cur_oproc_begin->value,
-                          (symint_t)0);
+                          (symint_t) 0);
 }
 
 \f
@@ -2905,15 +2929,15 @@ parse_def (name_start)
   const char *arg_start;                       /* start of current argument */
   const char *arg_end_p1;                      /* end+1 of current argument */
   const char *name_end_p1;                     /* end+1 of label */
-  const char *tag_start          = (const char *)0;    /* start of tag name */
-  const char *tag_end_p1  = (const char *)0;   /* end+1 of tag name */
+  const char *tag_start          = (const char *) 0;   /* start of tag name */
+  const char *tag_end_p1  = (const char *) 0;  /* end+1 of tag name */
   sc_t storage_class     = sc_Nil;
   st_t symbol_type       = st_Nil;
   type_info_t t;
-  EXTR *eptr             = (EXTR *)0;          /* ext. sym equivalent to def*/
+  EXTR *eptr             = (EXTR *) 0;         /* ext. sym equivalent to def*/
   int is_function        = 0;                  /* != 0 if function */
   symint_t value         = 0;
-  symint_t index         = cur_file_ptr->void_type;
+  symint_t indx                  = cur_file_ptr->void_type;
   int error_line         = 0;
   symint_t arg_number;
   symint_t temp_array[ N_TQ ];
@@ -2929,14 +2953,19 @@ parse_def (name_start)
 
 
   /* Search for the end of the name being defined.  */
-  for (name_end_p1 = name_start; (ch = *name_end_p1) != ';'; name_end_p1++)
+  /* Allow spaces and such in names for G++ templates, which produce stabs
+     that look like:
+
+     #.def   SMANIP<long unsigned int>; .scl 10; .type 0x8; .size 8; .endef */
+
+  for (name_end_p1 = name_start; (ch = *name_end_p1) != ';' && ch != '\0'; name_end_p1++)
+    ;
+
+  if (ch == '\0')
     {
-      if (ch == '\0' || isspace (ch))
-       {
-         error_line = __LINE__;
-         saber_stop ();
-         goto bomb_out;
-       }
+      error_line = __LINE__;
+      saber_stop ();
+      goto bomb_out;
     }
 
   /* Parse the remaining subdirectives now.  */
@@ -2973,7 +3002,7 @@ parse_def (name_start)
 
       /* Pick up the subdirective argument now.  */
       arg_was_number = arg_number = 0;
-      arg_end_p1 = (const char *)0;
+      arg_end_p1 = (const char *) 0;
       arg_start = dir_end_p1+1;
       ch = *arg_start;
       while (ch == ' ' || ch == '\t')
@@ -2995,16 +3024,20 @@ parse_def (name_start)
        }
 
       if (!arg_was_number)
-       for (arg_end_p1 = arg_start+1; (ch = *arg_end_p1) != ';'; arg_end_p1++)
-         {
-           if (ch == '\0' || isspace (ch))
-             {
-               error_line = __LINE__;
-               saber_stop ();
-               goto bomb_out;
-             }
-         }
+       {
+         /* Allow spaces and such in names for G++ templates.  */
+         for (arg_end_p1 = arg_start+1;
+              (ch = *arg_end_p1) != ';' && ch != '\0';
+              arg_end_p1++)
+           ;
 
+         if (ch == '\0')
+           {
+             error_line = __LINE__;
+             saber_stop ();
+             goto bomb_out;
+           }
+       }
 
       /* Classify the directives now.  */
       len = dir_end_p1 - dir_start;
@@ -3166,7 +3199,7 @@ parse_def (name_start)
 
              /* If this is a function, ignore it, so that we don't get
                 two entries (one from the .ent, and one for the .def
-                that preceedes it).  Save the type information so that
+                that precedes it).  Save the type information so that
                 the end block can properly add it after the begin block
                 index.  For MIPS knows what reason, we must strip off
                 the function type at this point.  */
@@ -3204,7 +3237,7 @@ parse_def (name_start)
 
              /* If the value is not an integer value, it must be the
                 name of a static or global item.  Look up the name in
-                the orignal symbol table to pick up the storage
+                the original symbol table to pick up the storage
                 class, symbol type, etc.  */
              else
                {
@@ -3214,20 +3247,20 @@ parse_def (name_start)
                  ext_hash_ptr = hash_string (arg_start,
                                              arg_end_p1 - arg_start,
                                              &ext_str_hash[0],
-                                             (symint_t *)0);
+                                             (symint_t *) 0);
 
-                 if (ext_hash_ptr != (shash_t *)0
-                     && ext_hash_ptr->esym_ptr != (EXTR *)0)
+                 if (ext_hash_ptr != (shash_t *) 0
+                     && ext_hash_ptr->esym_ptr != (EXTR *) 0)
                    eptr = ext_hash_ptr->esym_ptr;
 
                  orig_hash_ptr = hash_string (arg_start,
                                               arg_end_p1 - arg_start,
                                               &orig_str_hash[0],
-                                              (symint_t *)0);
+                                              (symint_t *) 0);
 
-                 if ((orig_hash_ptr == (shash_t *)0
-                      || orig_hash_ptr->sym_ptr == (SYMR *)0)
-                     && eptr == (EXTR *)0)
+                 if ((orig_hash_ptr == (shash_t *) 0
+                      || orig_hash_ptr->sym_ptr == (SYMR *) 0)
+                     && eptr == (EXTR *) 0)
                    {
                      fprintf (stderr, "warning, %.*s not found in original or external symbol tables, value defaults to 0\n",
                               arg_end_p1 - arg_start,
@@ -3236,8 +3269,8 @@ parse_def (name_start)
                    }
                  else
                    {
-                     SYMR *ptr = (orig_hash_ptr != (shash_t *)0
-                                  && orig_hash_ptr->sym_ptr != (SYMR *)0)
+                     SYMR *ptr = (orig_hash_ptr != (shash_t *) 0
+                                  && orig_hash_ptr->sym_ptr != (SYMR *) 0)
                                        ? orig_hash_ptr->sym_ptr
                                        : &eptr->asym;
 
@@ -3261,7 +3294,7 @@ parse_def (name_start)
     }
 
 
-  t.extra_sizes = (tag_start != (char *)0);
+  t.extra_sizes = (tag_start != (char *) 0);
   if (t.num_dims > 0)
     {
       int diff = t.num_dims - t.num_sizes;
@@ -3287,12 +3320,17 @@ parse_def (name_start)
 
          t.num_sizes = i + 1;
          for ( i--; i >= 0; i-- )
-           t.sizes[ i ] = t.sizes[ i+1 ] / t.dimensions[ i+1 ];
+           {
+             if (t.dimensions[ i+1 ])
+               t.sizes[ i ] = t.sizes[ i+1 ] / t.dimensions[ i+1 ];
+             else
+               t.sizes[ i ] = t.sizes[ i+1 ];
+           }
        }
     }
 
   else if (symbol_type == st_Member && t.num_sizes - t.extra_sizes == 1)
-    { /* Is this a bitfield?  This is indicated by a structure memeber
+    { /* Is this a bitfield?  This is indicated by a structure member
         having a size field that isn't an array.  */
 
       t.bitfield = 1;
@@ -3303,10 +3341,10 @@ parse_def (name_start)
      type word in the aux. symbol table.  */
 
   if (symbol_type == st_Block || symbol_type == st_End)
-    index = 0;
+    indx = 0;
 
   else if (inside_enumeration)
-    index = cur_file_ptr->void_type;
+    indx = cur_file_ptr->void_type;
 
   else
     {
@@ -3314,7 +3352,7 @@ parse_def (name_start)
          || t.basic_type == bt_Union
          || t.basic_type == bt_Enum)
        {
-         if (tag_start == (char *)0)
+         if (tag_start == (char *) 0)
            {
              error ("No tag specified for %.*s",
                     name_end_p1 - name_start,
@@ -3333,20 +3371,20 @@ parse_def (name_start)
          return;
        }
 
-      index = add_aux_sym_tir (&t,
-                              hash_yes,
-                              &cur_file_ptr->thash_head[0]);
+      indx = add_aux_sym_tir (&t,
+                             hash_yes,
+                             &cur_file_ptr->thash_head[0]);
     }
 
 
   /* If this is an external or static symbol, update the appropriate
      external symbol.  */
 
-  if (eptr != (EXTR *)0
-      && (eptr->asym.index == indexNil || cur_proc_ptr == (PDR *)0))
+  if (eptr != (EXTR *) 0
+      && (eptr->asym.index == indexNil || cur_proc_ptr == (PDR *) 0))
     {
       eptr->ifd = cur_file_ptr->file_index;
-      eptr->asym.index = index;
+      eptr->asym.index = indx;
     }
 
 
@@ -3380,7 +3418,7 @@ parse_def (name_start)
         that any error reporting above gives the correct name.  */
 
     case st_End:
-      name_start = name_end_p1 = (const char *)0;
+      name_start = name_end_p1 = (const char *) 0;
       value = inside_enumeration = 0;
       break;
 
@@ -3388,7 +3426,7 @@ parse_def (name_start)
       /* Members of structures and unions that aren't bitfields, need
         to adjust the value from a byte offset to a bit offset.
         Members of enumerations do not have the value adjusted, and
-        can be distinquished by index == indexNil.  For enumerations,
+        can be distinguished by indx == indexNil.  For enumerations,
         update the maximum enumeration value.  */
 
     case st_Member:
@@ -3402,14 +3440,14 @@ parse_def (name_start)
   /* Add the symbol, except for global symbols outside of functions,
      for which the external symbol table is fine enough.  */
 
-  if (eptr == (EXTR *)0
+  if (eptr == (EXTR *) 0
       || eptr->asym.st == (int)st_Nil
-      || cur_proc_ptr != (PDR *)0)
+      || cur_proc_ptr != (PDR *) 0)
     {
       symint_t isym = add_local_symbol (name_start, name_end_p1,
                                        symbol_type, storage_class,
                                        value,
-                                       index);
+                                       indx);
 
       /* deal with struct, union, and enum tags.  */
       if (symbol_type == st_Block)
@@ -3427,7 +3465,7 @@ parse_def (name_start)
          forward_t *f_next = tag_ptr->forward_ref;
          forward_t *f_cur;
 
-         while (f_next != (forward_t *)0)
+         while (f_next != (forward_t *) 0)
            {
              f_cur  = f_next;
              f_next = f_next->next;
@@ -3438,7 +3476,7 @@ parse_def (name_start)
              free_forward (f_cur);
            }
 
-         tag_ptr->forward_ref = (forward_t *)0;
+         tag_ptr->forward_ref = (forward_t *) 0;
         }
     }
 
@@ -3467,13 +3505,13 @@ parse_end (start)
   register symint_t value;
   register FDR *orig_fdr;
 
-  if (cur_file_ptr == (efdr_t *)0)
+  if (cur_file_ptr == (efdr_t *) 0)
     {
       error (".end directive without a preceding .file directive");
       return;
     }
 
-  if (cur_proc_ptr == (PDR *)0)
+  if (cur_proc_ptr == (PDR *) 0)
     {
       error (".end directive without a preceding .ent directive");
       return;
@@ -3503,7 +3541,7 @@ parse_end (start)
 
   orig_fdr = cur_file_ptr->orig_fdr;
   value = 0;
-  if (orig_fdr != (FDR *)0 && cur_oproc_end != (SYMR *)0)
+  if (orig_fdr != (FDR *)0 && cur_oproc_end != (SYMR *) 0)
     value = cur_oproc_end->value;
 
   else
@@ -3512,9 +3550,9 @@ parse_end (start)
   (void) add_local_symbol (start_func, end_func_p1,
                           st_End, sc_Text,
                           value,
-                          (symint_t)0);
+                          (symint_t) 0);
 
-  cur_proc_ptr = cur_oproc_ptr = (PDR *)0;
+  cur_proc_ptr = cur_oproc_ptr = (PDR *) 0;
 }
 
 \f
@@ -3527,13 +3565,13 @@ parse_ent (start)
   register const char *start_func, *end_func_p1;
   register int ch;
 
-  if (cur_file_ptr == (efdr_t *)0)
+  if (cur_file_ptr == (efdr_t *) 0)
     {
       error (".ent directive without a preceding .file directive");
       return;
     }
 
-  if (cur_proc_ptr != (PDR *)0)
+  if (cur_proc_ptr != (PDR *) 0)
     {
       error ("second .ent directive found before .end directive");
       return;
@@ -3567,14 +3605,14 @@ parse_file (start)
 
   (void) strtol (start, &p, 0);
   if (start == p
-      || (start_name = strchr (p, '"')) == (char *)0
-      || (end_name_p1 = strrchr (++start_name, '"')) == (char *)0)
+      || (start_name = local_index (p, '"')) == (char *) 0
+      || (end_name_p1 = local_rindex (++start_name, '"')) == (char *) 0)
     {
-      error ("Illegal .file directive");
+      error ("Invalid .file directive");
       return;
     }
 
-  if (cur_proc_ptr != (PDR *)0)
+  if (cur_proc_ptr != (PDR *) 0)
     {
       error ("No way to handle .file within .ent/.end section");
       return;
@@ -3588,11 +3626,11 @@ parse_file (start)
 
 static void
 mark_stabs (start)
-     char *start;                      /* Start of directive (ignored) */
+     const char *start;                        /* Start of directive (ignored) */
 {
   if (!stabs_seen)
     {
-      /* Add a dummy @stabs dymbol. */
+      /* Add a dummy @stabs symbol.  */
       stabs_seen = 1;
       (void) add_local_symbol (stabs_symbol,
                               stabs_symbol + sizeof (stabs_symbol),
@@ -3635,7 +3673,7 @@ STATIC void
 parse_stabs_common (string_start, string_end, rest)
      const char *string_start;         /* start of string or NULL */
      const char *string_end;           /* end+1 of string or NULL */
-     const char *rest;                 /* rest of the directive. */
+     const char *rest;                 /* rest of the directive.  */
 {
   efdr_t *save_file_ptr = cur_file_ptr;
   symint_t code;
@@ -3651,7 +3689,7 @@ parse_stabs_common (string_start, string_end, rest)
   /* Read code from stabs.  */
   if (!isdigit (*rest))
     {
-      error ("Illegal .stabs/.stabn directive, code is non-numeric");
+      error ("Invalid .stabs/.stabn directive, code is non-numeric");
       return;
     }
 
@@ -3665,39 +3703,48 @@ parse_stabs_common (string_start, string_end, rest)
 
   if (code == (int)N_SLINE)
     {
-      SYMR *sym_ptr;
+      SYMR *sym_ptr, dummy_symr;
       shash_t *shash_ptr;
 
       /* Skip ,0, */
       if (p[0] != ',' || p[1] != '0' || p[2] != ',' || !isdigit (p[3]))
        {
-         error ("Illegal line number .stabs/.stabn directive");
+         error ("Invalid line number .stabs/.stabn directive");
          return;
        }
 
       code = strtol (p+3, &p, 0);
       ch = *++p;
-      if (code <= 0 || p[-1] != ',' || isdigit (ch) || !IS_ASM_IDENT (ch))
+      if (p[-1] != ',' || isdigit (ch) || !IS_ASM_IDENT (ch))
+       {
+         error ("Invalid line number .stabs/.stabn directive");
+         return;
+       }
+
+      dummy_symr.index = code;
+      if (dummy_symr.index != code)
        {
-         error ("Illegal line number .stabs/.stabn directive");
+         error ("Line number (%d) for .stabs/.stabn directive cannot fit in index field (20 bits)",
+                code);
+
          return;
        }
 
       shash_ptr = hash_string (p,
                               strlen (p) - 1,
                               &orig_str_hash[0],
-                              (symint_t *)0);
+                              (symint_t *) 0);
 
-      if (shash_ptr == (shash_t *)0
-         || (sym_ptr = shash_ptr->sym_ptr) == (SYMR *)0)
+      if (shash_ptr == (shash_t *) 0
+         || (sym_ptr = shash_ptr->sym_ptr) == (SYMR *) 0)
        {
-         error ("Illegal .stabs/.stabn directive, value not found");
+         error ("Invalid .stabs/.stabn directive, value not found");
          return;
        }
 
       if ((st_t) sym_ptr->st != st_Label)
        {
-         error ("Illegal line number .stabs/.stabn directive");
+         error ("Invalid line number .stabs/.stabn directive");
          return;
        }
 
@@ -3707,18 +3754,22 @@ parse_stabs_common (string_start, string_end, rest)
     }
   else
     {
-      /* Skip ,0,0, */
-      if (p[0] != ',' || p[1] != '0' || p[2] != ',' || p[3] != '0' || p[4] != ',')
-       {
-         error ("Illegal .stabs/.stabn directive, mandatory 0 isn't");
-         return;
-       }
-
-      p += 5;
+      /* Skip ,<num>,<num>, */
+      if (*p++ != ',')
+       goto failure;
+      for (; isdigit (*p); p++)
+       ;
+      if (*p++ != ',')
+       goto failure;
+      for (; isdigit (*p); p++)
+       ;
+      if (*p++ != ',')
+       goto failure;
       ch = *p;
       if (!IS_ASM_IDENT (ch) && ch != '-')
        {
-         error ("Illegal .stabs/.stabn directive, bad character");
+       failure:
+         error ("Invalid .stabs/.stabn directive, bad character");
          return;
        }
 
@@ -3729,32 +3780,53 @@ parse_stabs_common (string_start, string_end, rest)
          value = strtol (p, &p, 0);
          if (*p != '\n')
            {
-             error ("Illegal .stabs/.stabn directive, stuff after numeric value");
+             error ("Invalid .stabs/.stabn directive, stuff after numeric value");
              return;
            }
        }
       else if (!IS_ASM_IDENT (ch))
        {
-         error ("Illegal .stabs/.stabn directive, bad character");
+         error ("Invalid .stabs/.stabn directive, bad character");
          return;
        }
       else
        {
          SYMR *sym_ptr;
-         shash_t *shash_ptr = hash_string (p,
-                                           strlen (p) - 1,
-                                           &orig_str_hash[0],
-                                           (symint_t *)0);
+         shash_t *shash_ptr;
+         const char *start, *end_p1;
 
-         if (shash_ptr == (shash_t *)0
-             || (sym_ptr = shash_ptr->sym_ptr) == (SYMR *)0)
+         start = p;
+         if ((end_p1 = strchr (start, '+')) == (char *) 0)
            {
-             error ("Illegal .stabs/.stabn directive, value not found");
-             return;
+             if ((end_p1 = strchr (start, '-')) == (char *) 0)
+               end_p1 = start + strlen(start) - 1;
            }
 
-         /* Traditionally, N_LBRAC and N_RBRAC are *not* relocated. */
-         if (code == (int)N_LBRAC || code == (int)N_RBRAC)
+         shash_ptr = hash_string (start,
+                                  end_p1 - start,
+                                  &orig_str_hash[0],
+                                  (symint_t *) 0);
+
+         if (shash_ptr == (shash_t *) 0
+             || (sym_ptr = shash_ptr->sym_ptr) == (SYMR *) 0)
+           {
+             shash_ptr = hash_string (start,
+                                      end_p1 - start,
+                                      &ext_str_hash[0],
+                                      (symint_t *) 0);
+
+             if (shash_ptr == (shash_t *) 0
+                 || shash_ptr->esym_ptr == (EXTR *) 0)
+               {
+                 error ("Invalid .stabs/.stabn directive, value not found");
+                 return;
+               }
+             else
+               sym_ptr = &(shash_ptr->esym_ptr->asym);
+           }
+
+         /* Traditionally, N_LBRAC and N_RBRAC are *not* relocated.  */
+         if (code == (int) N_LBRAC || code == (int) N_RBRAC)
            {
              sc = scNil;
              st = stNil;
@@ -3765,6 +3837,27 @@ parse_stabs_common (string_start, string_end, rest)
              st = (st_t) sym_ptr->st;
            }
          value = sym_ptr->value;
+
+         ch = *end_p1++;
+         if (ch != '\n')
+           {
+             if (((!isdigit (*end_p1)) && (*end_p1 != '-'))
+                 || ((ch != '+') && (ch != '-')))
+               {
+                 error ("Invalid .stabs/.stabn directive, badly formed value");
+                 return;
+               }
+             if (ch == '+')
+               value += strtol (end_p1, &p, 0);
+             else if (ch == '-')
+               value -= strtol (end_p1, &p, 0);
+
+             if (*p != '\n')
+               {
+                 error ("Invalid .stabs/.stabn directive, stuff after numeric value");
+                 return;
+               }
+           }
        }
       code = MIPS_MARK_STAB(code);
     }
@@ -3779,11 +3872,11 @@ STATIC void
 parse_stabs (start)
      const char *start;                        /* start of directive */
 {
-  const char *end = strchr (start+1, '"');
+  const char *end = local_index (start+1, '"');
 
-  if (*start != '"' || end == (const char *)0 || end[1] != ',')
+  if (*start != '"' || end == (const char *) 0 || end[1] != ',')
     {
-      error ("Illegal .stabs directive, no string");
+      error ("Invalid .stabs directive, no string");
       return;
     }
 
@@ -3795,7 +3888,7 @@ STATIC void
 parse_stabn (start)
      const char *start;                        /* start of directive */
 {
-  parse_stabs_common ((const char *)0, (const char *)0, start);
+  parse_stabs_common ((const char *) 0, (const char *) 0, start);
 }
 
 \f
@@ -3821,7 +3914,7 @@ parse_input __proto((void))
   ptag_head->prev = cur_tag_head;
   cur_tag_head = ptag_head;
 
-  while ((p = read_line ()) != (char *)0)
+  while ((p = read_line ()) != (char *) 0)
     {
       /* Skip leading blanks */
       while (isspace (*p))
@@ -3846,10 +3939,10 @@ parse_input __proto((void))
   cur_tag_head = ptag_head->prev;
 
   for (ptag = ptag_head->first_tag;
-       ptag != (tag_t *)0;
+       ptag != (tag_t *) 0;
        ptag = ptag_next)
     {
-      if (ptag->forward_ref != (forward_t *)0)
+      if (ptag->forward_ref != (forward_t *) 0)
        add_unknown_tag (ptag);
 
       ptag_next = ptag->same_block;
@@ -3892,14 +3985,50 @@ update_headers __proto((void))
      for the filename.  */
 
   for (file_ptr = first_file;
-       file_ptr != (efdr_t *)0;
+       file_ptr != (efdr_t *) 0;
        file_ptr = file_ptr->next_file)
     {
+      register SYMR *sym_start;
+      register SYMR *sym;
+      register SYMR *sym_end_p1;
+      register FDR *fd_ptr = file_ptr->orig_fdr;
+
       cur_file_ptr = file_ptr;
-      (void) add_local_symbol ((const char *)0, (const char *)0,
+
+      /* Copy st_Static symbols from the original local symbol table if
+        they did not get added to the new local symbol table.
+        This happens with stabs-in-ecoff or if the source file is
+        compiled without debugging.  */
+      sym_start = ORIG_LSYMS (fd_ptr->isymBase);
+      sym_end_p1 = sym_start + fd_ptr->csym;
+      for (sym = sym_start; sym < sym_end_p1; sym++)
+       {
+         if ((st_t)sym->st == st_Static)
+           {
+             register char *str = ORIG_LSTRS (fd_ptr->issBase + sym->iss);
+             register Size_t len = strlen (str);
+             register shash_t *hash_ptr;
+
+             /* Ignore internal labels.  */
+             if (str[0] == '$' && str[1] == 'L')
+               continue;
+             hash_ptr = hash_string (str,
+                                     (Ptrdiff_t)len,
+                                     &file_ptr->shash_head[0],
+                                     (symint_t *) 0);
+             if (hash_ptr == (shash_t *) 0)
+               {
+                 (void) add_local_symbol (str, str + len,
+                                          (st_t)sym->st, (sc_t)sym->sc,
+                                          (symint_t)sym->value,
+                                          (symint_t)indexNil);
+               }
+           }
+       }
+      (void) add_local_symbol ((const char *) 0, (const char *) 0,
                               st_End, sc_Text,
-                              (symint_t)0,
-                              (symint_t)0);
+                              (symint_t) 0,
+                              (symint_t) 0);
 
       file_ptr->fdr.cpd = file_ptr->procs.num_allocated;
       file_ptr->fdr.ipdFirst = symbolic_header.ipdMax;
@@ -3918,12 +4047,17 @@ update_headers __proto((void))
       symbolic_header.issMax += file_ptr->fdr.cbSs;
     }
 
+#ifndef ALIGN_SYMTABLE_OFFSET
+#define ALIGN_SYMTABLE_OFFSET(OFFSET) (OFFSET)
+#endif
 
+  file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
   i = WORD_ALIGN (symbolic_header.cbLine);     /* line numbers */
   if (i > 0)
     {
       symbolic_header.cbLineOffset = file_offset;
       file_offset += i;
+      file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
     }
 
   i = symbolic_header.ioptMax;                 /* optimization symbols */
@@ -3931,6 +4065,7 @@ update_headers __proto((void))
     {
       symbolic_header.cbOptOffset = file_offset;
       file_offset += i * sizeof (OPTR);
+      file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
     }
 
   i = symbolic_header.idnMax;                  /* dense numbers */
@@ -3938,6 +4073,7 @@ update_headers __proto((void))
     {
       symbolic_header.cbDnOffset = file_offset;
       file_offset += i * sizeof (DNR);
+      file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
     }
 
   i = symbolic_header.ipdMax;                  /* procedure tables */
@@ -3945,6 +4081,7 @@ update_headers __proto((void))
     {
       symbolic_header.cbPdOffset = file_offset;
       file_offset += i * sizeof (PDR);
+      file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
     }
 
   i = symbolic_header.isymMax;                 /* local symbols */
@@ -3952,13 +4089,15 @@ update_headers __proto((void))
     {
       symbolic_header.cbSymOffset = file_offset;
       file_offset += i * sizeof (SYMR);
+      file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
     }
 
-  i = symbolic_header.iauxMax;                 /* aux syms. */
+  i = symbolic_header.iauxMax;                 /* aux syms.  */
   if (i > 0)
     {
       symbolic_header.cbAuxOffset = file_offset;
       file_offset += i * sizeof (TIR);
+      file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
     }
 
   i = WORD_ALIGN (symbolic_header.issMax);     /* local strings */
@@ -3966,6 +4105,7 @@ update_headers __proto((void))
     {
       symbolic_header.cbSsOffset = file_offset;
       file_offset += i;
+      file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
     }
 
   i = WORD_ALIGN (symbolic_header.issExtMax);  /* external strings */
@@ -3973,6 +4113,7 @@ update_headers __proto((void))
     {
       symbolic_header.cbSsExtOffset = file_offset;
       file_offset += i;
+      file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
     }
 
   i = symbolic_header.ifdMax;                  /* file tables */
@@ -3980,6 +4121,7 @@ update_headers __proto((void))
     {
       symbolic_header.cbFdOffset = file_offset;
       file_offset += i * sizeof (FDR);
+      file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
     }
 
   i = symbolic_header.crfd;                    /* relative file descriptors */
@@ -3987,6 +4129,7 @@ update_headers __proto((void))
     {
       symbolic_header.cbRfdOffset = file_offset;
       file_offset += i * sizeof (symint_t);
+      file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
     }
 
   i = symbolic_header.iextMax;                 /* external symbols */
@@ -3994,6 +4137,7 @@ update_headers __proto((void))
     {
       symbolic_header.cbExtOffset = file_offset;
       file_offset += i * sizeof (EXTR);
+      file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
     }
 }
 
@@ -4020,9 +4164,9 @@ write_varray (vp, offset, str)
       && fseek (object_stream, (long)offset, SEEK_SET) < 0)
     pfatal_with_name (object_name);
 
-  for (ptr = vp->first; ptr != (vlinks_t *)0; ptr = ptr->next)
+  for (ptr = vp->first; ptr != (vlinks_t *) 0; ptr = ptr->next)
     {
-      num_write = (ptr->next == (vlinks_t *)0)
+      num_write = (ptr->next == (vlinks_t *) 0)
        ? vp->objects_last_page * vp->object_size
        : vp->objects_per_page  * vp->object_size;
 
@@ -4140,7 +4284,7 @@ write_object __proto((void))
     {
       offset = symbolic_header.cbPdOffset;
       for (file_ptr = first_file;
-          file_ptr != (efdr_t *)0;
+          file_ptr != (efdr_t *) 0;
           file_ptr = file_ptr->next_file)
        {
          write_varray (&file_ptr->procs, offset, "Procedure tables");
@@ -4152,7 +4296,7 @@ write_object __proto((void))
     {
       offset = symbolic_header.cbSymOffset;
       for (file_ptr = first_file;
-          file_ptr != (efdr_t *)0;
+          file_ptr != (efdr_t *) 0;
           file_ptr = file_ptr->next_file)
        {
          write_varray (&file_ptr->symbols, offset, "Local symbols");
@@ -4164,7 +4308,7 @@ write_object __proto((void))
     {
       offset = symbolic_header.cbAuxOffset;
       for (file_ptr = first_file;
-          file_ptr != (efdr_t *)0;
+          file_ptr != (efdr_t *) 0;
           file_ptr = file_ptr->next_file)
        {
          write_varray (&file_ptr->aux_syms, offset, "Aux. symbols");
@@ -4176,7 +4320,7 @@ write_object __proto((void))
     {
       offset = symbolic_header.cbSsOffset;
       for (file_ptr = first_file;
-          file_ptr != (efdr_t *)0;
+          file_ptr != (efdr_t *) 0;
           file_ptr = file_ptr->next_file)
        {
          write_varray (&file_ptr->strings, offset, "Local strings");
@@ -4196,7 +4340,7 @@ write_object __proto((void))
 
       file_offset = offset;
       for (file_ptr = first_file;
-          file_ptr != (efdr_t *)0;
+          file_ptr != (efdr_t *) 0;
           file_ptr = file_ptr->next_file)
        {
          if (debug)
@@ -4272,7 +4416,7 @@ read_seek (size, offset, str)
   long sys_read = 0;
 
   if (size == 0)               /* nothing to read */
-    return (page_t *)0;
+    return (page_t *) 0;
 
   if (debug)
     fprintf (stderr, "\trseek\tsize = %7u, offset = %7u, currently at %7u, %s\n",
@@ -4301,8 +4445,8 @@ read_seek (size, offset, str)
          if (sys_read != difference)
            fatal ("Wanted to read %d bytes from %s, system returned %d",
                   size,
-                  sys_read,
-                  obj_in_name);
+                  obj_in_name,
+                  sys_read);
        }
       else if (fseek (obj_in_stream, offset, SEEK_SET) < 0)
        pfatal_with_name (obj_in_name);
@@ -4315,8 +4459,8 @@ read_seek (size, offset, str)
   if (sys_read != size)
     fatal ("Wanted to read %d bytes from %s, system returned %d",
           size,
-          sys_read,
-          obj_in_name);
+          obj_in_name,
+          sys_read);
 
   file_offset = offset + size;
 
@@ -4369,9 +4513,6 @@ copy_object __proto((void))
           sys_read);
 
 
-  if (orig_file_header.f_flags != 0)
-    fatal ("Non-zero flags encountered in %s filehdr", input_name);
-
   if (orig_file_header.f_nsyms != sizeof (HDRR))
     fatal ("%s symbolic header wrong size (%d bytes, should be %d)",
           input_name, orig_file_header.f_nsyms, sizeof (HDRR));
@@ -4401,7 +4542,7 @@ copy_object __proto((void))
      sections, so in theory no extra seeks are done.
 
      For simplicity sake, round each read up to a page boundary,
-     we may want to revisit this later.... */
+     we may want to revisit this later....  */
 
   file_offset =  orig_file_header.f_symptr + sizeof (struct filehdr);
 
@@ -4480,9 +4621,9 @@ copy_object __proto((void))
       && orig_files->caux == 0)
     {
       char *filename = orig_local_strs + (orig_files->issBase + orig_files->rss);
-      char *suffix = strrchr (filename, '.');
+      char *suffix = local_rindex (filename, '.');
 
-      if (suffix != (char *)0 && strcmp (suffix, ".s") == 0)
+      if (suffix != (char *) 0 && strcmp (suffix, ".s") == 0)
        delete_ifd = 1;
     }
 
@@ -4529,7 +4670,7 @@ copy_object __proto((void))
                             (st_t) eptr->asym.st,
                             (sc_t) eptr->asym.sc,
                             eptr->asym.value,
-                            (symint_t)((eptr->asym.index == indexNil) ? indexNil : 0),
+                            (symint_t) ((eptr->asym.index == indexNil) ? indexNil : 0),
                             (ifd < orig_sym_hdr.ifdMax) ? remap_file_number[ ifd ] : ifd);
     }
 
@@ -4594,7 +4735,7 @@ copy_object __proto((void))
                                                           &orig_str_hash[0],
                                                           &hash_index);
 
-               if (shash_ptr != (shash_t *)0)
+               if (shash_ptr != (shash_t *) 0)
                  error ("internal error, %s is already in original symbol table", str);
 
                else
@@ -4604,7 +4745,7 @@ copy_object __proto((void))
                    orig_str_hash[hash_index] = shash_ptr;
 
                    shash_ptr->len = len;
-                   shash_ptr->index = indexNil;
+                   shash_ptr->indx = indexNil;
                    shash_ptr->string = str;
                    shash_ptr->sym_ptr = sym;
                  }
@@ -4622,9 +4763,9 @@ copy_object __proto((void))
                      register shash_t *shash_ptr = hash_string (str,
                                                                 (Ptrdiff_t)len,
                                                                 &orig_str_hash[0],
-                                                                (symint_t *)0);
+                                                                (symint_t *) 0);
 
-                     if (shash_ptr != (shash_t *)0)
+                     if (shash_ptr != (shash_t *) 0)
                        shash_ptr->end_ptr = sym;
                    }
                }
@@ -4652,9 +4793,9 @@ copy_object __proto((void))
          register shash_t *shash_ptr = hash_string (str,
                                                     (Ptrdiff_t)len,
                                                     &orig_str_hash[0],
-                                                    (symint_t *)0);
+                                                    (symint_t *) 0);
 
-         if (shash_ptr == (shash_t *)0)
+         if (shash_ptr == (shash_t *) 0)
            error ("internal error, function %s is not in original symbol table", str);
 
          else
@@ -4670,12 +4811,12 @@ copy_object __proto((void))
 
   /* Copy all of the object file up to the symbol table.  Originally
      we were going to use ftruncate, but that doesn't seem to work
-     on Ultrix 3.1.... */
+     on Ultrix 3.1....  */
 
-  if (fseek (obj_in_stream, (long)0, SEEK_SET) != 0)
+  if (fseek (obj_in_stream, (long) 0, SEEK_SET) != 0)
     pfatal_with_name (obj_in_name);
 
-  if (fseek (object_stream, (long)0, SEEK_SET) != 0)
+  if (fseek (object_stream, (long) 0, SEEK_SET) != 0)
     pfatal_with_name (object_name);
 
   for (remaining = orig_file_header.f_symptr;
@@ -4714,7 +4855,7 @@ main (argc, argv)
      char *argv[];
 {
   int iflag = 0;
-  char *p = strrchr (argv[0], '/');
+  char *p = local_rindex (argv[0], '/');
   char *num_end;
   int option;
   int i;
@@ -4769,7 +4910,7 @@ main (argc, argv)
        break;
 
       case 'I':
-       if (rename_output || obj_in_name != (char *)0)
+       if (rename_output || obj_in_name != (char *) 0)
          had_errors++;
        else
          rename_output = 1;
@@ -4777,7 +4918,7 @@ main (argc, argv)
        /* fall through to 'i' case.  */
 
       case 'i':
-       if (obj_in_name == (char *)0)
+       if (obj_in_name == (char *) 0)
          {
            obj_in_name = optarg;
            iflag++;
@@ -4787,7 +4928,7 @@ main (argc, argv)
        break;
 
       case 'o':
-       if (object_name == (char *)0)
+       if (object_name == (char *) 0)
          object_name = optarg;
        else
          had_errors++;
@@ -4798,22 +4939,22 @@ main (argc, argv)
        break;
       }
 
-  if (obj_in_name == (char *)0 && optind <= argc - 2)
+  if (obj_in_name == (char *) 0 && optind <= argc - 2)
     obj_in_name = argv[--argc];
 
-  if (object_name == (char *)0 && optind <= argc - 2)
+  if (object_name == (char *) 0 && optind <= argc - 2)
     object_name = argv[--argc];
 
   /* If there is an output name, but no input name use
      the same file for both, deleting the name between
      opening it for input and opening it for output.  */
-  if (obj_in_name == (char *)0 && object_name != (char *)0)
+  if (obj_in_name == (char *) 0 && object_name != (char *)0)
     {
       obj_in_name = object_name;
       delete_input = 1;
     }
 
-  if (object_name == (char *)0 || had_errors || optind != argc - 1)
+  if (object_name == (char *) 0 || had_errors || optind != argc - 1)
     {
       fprintf (stderr, "Calling Sequence:\n");
       fprintf (stderr, "\tmips-tfile [-d <num>] [-v] [-i <o-in-file>] -o <o-out-file> <s-file> (or)\n");
@@ -4838,7 +4979,7 @@ main (argc, argv)
       fputc ('\n', stderr);
     }
 
-  if (obj_in_name == (char *)0)
+  if (obj_in_name == (char *) 0)
     obj_in_name = object_name;
 
   if (rename_output && rename (object_name, obj_in_name) != 0)
@@ -4883,14 +5024,14 @@ main (argc, argv)
   /* Must open input before output, since the output may be the same file, and
      we need to get the input handle before truncating it.  */
   obj_in_stream = fopen (obj_in_name, "r");
-  if (obj_in_stream == (FILE *)0)
+  if (obj_in_stream == (FILE *) 0)
     pfatal_with_name (obj_in_name);
 
   if (delete_input && unlink (obj_in_name) != 0)
     pfatal_with_name (obj_in_name);
 
   object_stream = fopen (object_name, "w");
-  if (object_stream == (FILE *)0)
+  if (object_stream == (FILE *) 0)
     pfatal_with_name (object_name);
 
   if (strcmp (argv[optind], "-") != 0)
@@ -4931,8 +5072,12 @@ STATIC void
 catch_signal (signum)
      int signum;
 {
-  (void) signal (signum, SIG_DFL);     /* just in case... */
+  (void) signal (signum, SIG_DFL);     /* just in case...  */
+#ifdef NO_SYS_SIGLIST
+  fatal ("caught signal");
+#else
   fatal (sys_siglist[signum]);
+#endif  
 }
 
 /* Print a fatal error message.  NAME is the text.
@@ -4942,7 +5087,7 @@ void
 pfatal_with_name (msg)
      char *msg;
 {
-  int save_errno = errno;              /* just in case.... */
+  int save_errno = errno;              /* just in case....  */
   if (line_number > 0)
     fprintf (stderr, "%s, %s:%ld ", progname, input_name, line_number);
   else
@@ -4963,17 +5108,17 @@ pfatal_with_name (msg)
    ORIG_xxx macros, but the function never returns.  */
 
 static int
-out_of_bounds (index, max, str, prog_line)
-     symint_t index;           /* index that is out of bounds */
+out_of_bounds (indx, max, str, prog_line)
+     symint_t indx;            /* index that is out of bounds */
      symint_t max;             /* maximum index */
      const char *str;          /* string to print out */
      int prog_line;            /* line number within mips-tfile.c */
 {
-  if (index < max)             /* just in case */
+  if (indx < max)              /* just in case */
     return 0;
 
   fprintf (stderr, "%s, %s:%ld index %u is out of bounds for %s, max is %u, mips-tfile.c line# %d\n",
-          progname, input_name, line_number, index, str, max, prog_line);
+          progname, input_name, line_number, indx, str, max, prog_line);
 
   exit (1);
   return 0;                    /* turn off warning messages */
@@ -5130,7 +5275,7 @@ allocate_scope __proto((void))
 
 #ifndef MALLOC_CHECK
   ptr = alloc_counts[ (int)alloc_type_scope ].free_list.f_scope;
-  if (ptr != (scope_t *)0)
+  if (ptr != (scope_t *) 0)
     alloc_counts[ (int)alloc_type_scope ].free_list.f_scope = ptr->free;
 
   else
@@ -5287,7 +5432,7 @@ allocate_tag __proto((void))
 
 #ifndef MALLOC_CHECK
   ptr = alloc_counts[ (int)alloc_type_tag ].free_list.f_tag;
-  if (ptr != (tag_t *)0)
+  if (ptr != (tag_t *) 0)
     alloc_counts[ (int)alloc_type_tag ].free_list.f_tag = ptr->free;
 
   else
@@ -5345,7 +5490,7 @@ allocate_forward __proto((void))
 
 #ifndef MALLOC_CHECK
   ptr = alloc_counts[ (int)alloc_type_forward ].free_list.f_forward;
-  if (ptr != (forward_t *)0)
+  if (ptr != (forward_t *) 0)
     alloc_counts[ (int)alloc_type_forward ].free_list.f_forward = ptr->free;
 
   else
@@ -5403,7 +5548,7 @@ allocate_thead __proto((void))
 
 #ifndef MALLOC_CHECK
   ptr = alloc_counts[ (int)alloc_type_thead ].free_list.f_thead;
-  if (ptr != (thead_t *)0)
+  if (ptr != (thead_t *) 0)
     alloc_counts[ (int)alloc_type_thead ].free_list.f_thead = ptr->free;
 
   else
@@ -5450,26 +5595,33 @@ free_thead (ptr)
 
 }
 
-#endif /* MIPS_DEBUGGING_INFO *?
+#endif /* MIPS_DEBUGGING_INFO */
 
 \f
+#ifdef HAVE_VPRINTF
+
 /* Output an error message and exit */
 
 /*VARARGS*/
 void
-fatal (va_alist)
-     va_dcl
+fatal VPROTO((const char *format, ...))
 {
-  va_list ap;
+#ifndef __STDC__
   char *format;
+#endif
+  va_list ap;
+
+  VA_START (ap, format);
+
+#ifndef __STDC__
+  format = va_arg (ap, char *);
+#endif
 
   if (line_number > 0)
     fprintf (stderr, "%s, %s:%ld ", progname, input_name, line_number);
   else
     fprintf (stderr, "%s:", progname);
 
-  va_start(ap);
-  format = va_arg (ap, char *);
   vfprintf (stderr, format, ap);
   va_end (ap);
   fprintf (stderr, "\n");
@@ -5482,19 +5634,24 @@ fatal (va_alist)
 
 /*VARARGS*/
 void
-error (va_alist) 
-     va_dcl
+error VPROTO((const char *format, ...))
 {
-  va_list ap;
+#ifndef __STDC__
   char *format;
+#endif
+  va_list ap;
+
+  VA_START (ap, format);
+
+#ifndef __STDC__
+  format = va_arg (ap, char *);
+#endif
 
   if (line_number > 0)
     fprintf (stderr, "%s, %s:%ld ", progname, input_name, line_number);
   else
     fprintf (stderr, "%s:", progname);
 
-  va_start(ap);
-  format = va_arg (ap, char *);
   vfprintf (stderr, format, ap);
   fprintf (stderr, "\n");
   if (line_number > 0)
@@ -5506,6 +5663,27 @@ error (va_alist)
   saber_stop ();
 }
 
+#else /* not HAVE_VPRINTF */
+
+void
+fatal (msg, arg1, arg2)
+     char *msg, *arg1, *arg2;
+{
+  error (msg, arg1, arg2);
+  exit (1);
+}
+
+void
+error (msg, arg1, arg2)
+     char *msg, *arg1, *arg2;
+{
+  fprintf (stderr, "%s: ", progname);
+  fprintf (stderr, msg, arg1, arg2);
+  fprintf (stderr, "\n");
+}
+
+#endif /* not HAVE_VPRINTF */
+
 /* More 'friendly' abort that prints the line and file.
    config.h can #define abort fancy_abort if you like that sort of thing.  */
 
@@ -5586,3 +5764,40 @@ xfree (ptr)
 
   free (ptr);
 }
+
+\f
+/* Define our own index/rindex, since the local and global symbol
+   structures as defined by MIPS has an 'index' field.  */
+
+STATIC char *
+local_index (str, sentinel)
+     const char *str;
+     int sentinel;
+{
+  int ch;
+
+  for ( ; (ch = *str) != sentinel; str++)
+    {
+      if (ch == '\0')
+       return (char *) 0;
+    }
+
+  return (char *)str;
+}
+
+STATIC char *
+local_rindex (str, sentinel)
+     const char *str;
+     int sentinel;
+{
+  int ch;
+  const char *ret = (const char *) 0;
+
+  for ( ; (ch = *str) != '\0'; str++)
+    {
+      if (ch == sentinel)
+       ret = str;
+    }
+
+  return (char *)ret;
+}