* ecoff.c (ecoff_setup_ext): Renamed from ecoff_build_ext.
authorIan Lance Taylor <ian@airs.com>
Wed, 24 Nov 1993 07:42:03 +0000 (07:42 +0000)
committerIan Lance Taylor <ian@airs.com>
Wed, 24 Nov 1993 07:42:03 +0000 (07:42 +0000)
Changed to not actually build the external symbol information, as
that is now done by the ECOFF back end.
(ecoff_build_debug): Changed accordingly.
* ecoff.h (obj_ecoff_set_ext): Declare.   obj-format.c function
called by ecoff_setup_ext.
* config/obj-ecoff.c (ecoff_frob_file): If debug_info count is 0,
set corresponding pointer to NULL.  Don't set raw_size and
raw_syments.
(obj_ecoff_set_sym_index): Removed.
(obj_ecoff_set_ext): New function.
* config/obj-ecoff.h (obj_set_sym_index): Don't define.
(obj_ecoff_set_sym_index): Don't declare.
* config/obj-elf.c (obj_ecoff_set_ext, elf_get_extr,
elf_set_index): New functions used for ECOFF_DEBUGGING.
(elf_frob_file): Reworked ECOFF debug generation to use
new functions in bfd/ecofflink.c.

gas/ChangeLog
gas/config/obj-ecoff.c
gas/config/obj-elf.c

index 3fa1aff17d81d12a171798b9ea4222a7e0e2c85c..466ee196757ea38b1a76b36a25206d8f766f5442 100644 (file)
@@ -1,3 +1,29 @@
+Wed Nov 24 02:31:38 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * ecoff.c (ecoff_setup_ext): Renamed from ecoff_build_ext.
+       Changed to not actually build the external symbol information, as
+       that is now done by the ECOFF back end.
+       (ecoff_build_debug): Changed accordingly.
+       * ecoff.h (obj_ecoff_set_ext): Declare.   obj-format.c function
+       called by ecoff_setup_ext.
+       * config/obj-ecoff.c (ecoff_frob_file): If debug_info count is 0,
+       set corresponding pointer to NULL.  Don't set raw_size and
+       raw_syments.
+       (obj_ecoff_set_sym_index): Removed.
+       (obj_ecoff_set_ext): New function.
+       * config/obj-ecoff.h (obj_set_sym_index): Don't define.
+       (obj_ecoff_set_sym_index): Don't declare.
+       * config/obj-elf.c (obj_ecoff_set_ext, elf_get_extr,
+       elf_set_index): New functions used for ECOFF_DEBUGGING.
+       (elf_frob_file): Reworked ECOFF debug generation to use
+       new functions in bfd/ecofflink.c.
+
+Sun Nov 21 23:54:52 1993  Jeffrey A. Law  (law@snake.cs.utah.edu)
+
+       * config/tc-hppa.c (pa_def_subspaces): Only create the unwind
+       subspace for ELF.  In the SOM world, the linker is responsible
+       for creating the unwind subspaces.
+
 Fri Nov 19 16:25:09 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
 
        * config/obj-coffbfd.c: Use PARAMS rather than EXFUN.
index 9d5a913f10240a4c871596210fdf80bc5cea3ecd..7d997a42f816957d7d38d184b374de3f8720912f 100644 (file)
@@ -1,9 +1,7 @@
 /* ECOFF object file format.
    Copyright (C) 1993 Free Software Foundation, Inc.
    Contributed by Cygnus Support.
-   This file was put together by Ian Lance Taylor <ian@cygnus.com>.  A
-   good deal of it comes directly from mips-tfile.c, by Michael
-   Meissner <meissner@osf.org>.
+   This file was put together by Ian Lance Taylor <ian@cygnus.com>.
 
    This file is part of GAS.
 
 
 #include "as.h"
 #include "coff/internal.h"
-#include "coff/sym.h"
-#include "coff/symconst.h"
-#include "coff/ecoff.h"
-#include "aout/stab_gnu.h"
 #include "../bfd/libcoff.h"
 #include "../bfd/libecoff.h"
 
-#include <ctype.h>
+/* Almost all of the ECOFF support is actually in ecoff.c in the main
+   gas directory.  This file mostly just arranges to call that one at
+   the right times.  */
 
-/* Why isn't this in coff/sym.h?  */
-#define ST_RFDESCAPE 0xfff
-
-/* Why isn't this in listing.h?  */
-extern int listing;
-
-/* The ECOFF file format uses COFF style sections, but with a unique
-   debugging format.  We just build generic BFD sections since BFD
-   knows how to write them out.  The debugging format, however, we
-   must construct here; all BFD knows at the moment is to write it out
-   as a large block of data.
-
-   We support both COFF style debugging and stabs debugging (the stabs
-   symbols are encapsulated in COFF symbols).  This should let us
-   handle anything the compiler might throw at us.  Parsing the COFF
-   and stabs debugging information is similar to work done by COFF and
-   a.out targets, but since the result is completely different the
-   code is not shared.  */
-
-/* Here is a brief description of the MIPS ECOFF symbol table, by
-   Michael Meissner.  The MIPS symbol table has the following pieces:
-
-       Symbolic Header
-           |
-           +-- Auxiliary Symbols
-           |
-           +-- Dense number table
-           |
-           +-- Optimizer Symbols
-           |
-           +-- External Strings
-           |
-           +-- External Symbols
-           |
-           +-- Relative file descriptors
-           |
-           +-- File table
-                   |
-                   +-- Procedure table
-                   |
-                   +-- Line number table
-                   |
-                   +-- Local Strings
-                   |
-                   +-- Local Symbols
-
-   The symbolic header points to each of the other tables, and also
-   contains the number of entries.  It also contains a magic number
-   and MIPS compiler version number, such as 2.0.
-
-   The auxiliary table is a series of 32 bit integers, that are
-   referenced as needed from the local symbol table.  Unlike standard
-   COFF, the aux.  information does not follow the symbol that uses
-   it, but rather is a separate table.  In theory, this would allow
-   the MIPS compilers to collapse duplicate aux. entries, but I've not
-   noticed this happening with the 1.31 compiler suite.  The different
-   types of aux. entries are:
-
-    1) dnLow: Low bound on array dimension.
-
-    2) dnHigh: High bound on array dimension.
-
-    3) isym: Index to the local symbol which is the start of the
-       function for the end of function first aux. entry.
-
-    4) width: Width of structures and bitfields.
-
-    5) count: Count of ranges for variant part.
-
-    6) rndx: A relative index into the symbol table.  The relative
-       index field has two parts: rfd which is a pointer into the
-       relative file index table or ST_RFDESCAPE which says the next
-       aux. entry is the file number, and index: which is the pointer
-       into the local symbol within a given file table.  This is for
-       things like references to types defined in another file.
-
-    7) Type information: This is like the COFF type bits, except it
-       is 32 bits instead of 16; they still have room to add new
-       basic types; and they can handle more than 6 levels of array,
-       pointer, function, etc.  Each type information field contains
-       the following structure members:
-
-           a)  fBitfield: a bit that says this is a bitfield, and the
-               size in bits follows as the next aux. entry.
-
-           b)  continued: a bit that says the next aux. entry is a
-               continuation of the current type information (in case
-               there are more than 6 levels of array/ptr/function).
-
-           c)  bt: an integer containing the base type before adding
-               array, pointer, function, etc. qualifiers.  The
-               current base types that I have documentation for are:
-
-                       btNil           -- undefined 
-                       btAdr           -- address - integer same size as ptr
-                       btChar          -- character 
-                       btUChar         -- unsigned character 
-                       btShort         -- short 
-                       btUShort        -- unsigned short 
-                       btInt           -- int 
-                       btUInt          -- unsigned int 
-                       btLong          -- long 
-                       btULong         -- unsigned long 
-                       btFloat         -- float (real) 
-                       btDouble        -- Double (real) 
-                       btStruct        -- Structure (Record) 
-                       btUnion         -- Union (variant) 
-                       btEnum          -- Enumerated 
-                       btTypedef       -- defined via a typedef isymRef 
-                       btRange         -- subrange of int 
-                       btSet           -- pascal sets 
-                       btComplex       -- fortran complex 
-                       btDComplex      -- fortran double complex 
-                       btIndirect      -- forward or unnamed typedef 
-                       btFixedDec      -- Fixed Decimal 
-                       btFloatDec      -- Float Decimal 
-                       btString        -- Varying Length Character String 
-                       btBit           -- Aligned Bit String 
-                       btPicture       -- Picture
-                       btVoid          -- Void (MIPS cc revision >= 2.00)
-
-           d)  tq0 - tq5: type qualifier fields as needed.  The
-               current type qualifier fields I have documentation for
-               are:
-
-                       tqNil           -- no more qualifiers 
-                       tqPtr           -- pointer 
-                       tqProc          -- procedure 
-                       tqArray         -- array 
-                       tqFar           -- 8086 far pointers 
-                       tqVol           -- volatile 
-
-
-   The dense number table is used in the front ends, and disappears by
-   the time the .o is created.
-
-   With the 1.31 compiler suite, the optimization symbols don't seem
-   to be used as far as I can tell.
-
-   The linker is the first entity that creates the relative file
-   descriptor table, and I believe it is used so that the individual
-   file table pointers don't have to be rewritten when the objects are
-   merged together into the program file.
-
-   Unlike COFF, the basic symbol & string tables are split into
-   external and local symbols/strings.  The relocation information
-   only goes off of the external symbol table, and the debug
-   information only goes off of the internal symbol table.  The
-   external symbols can have links to an appropriate file index and
-   symbol within the file to give it the appropriate type information.
-   Because of this, the external symbols are actually larger than the
-   internal symbols (to contain the link information), and contain the
-   local symbol structure as a member, though this member is not the
-   first member of the external symbol structure (!).  I suspect this
-   split is to make strip easier to deal with.
-
-   Each file table has offsets for where the line numbers, local
-   strings, local symbols, and procedure table starts from within the
-   global tables, and the indexs are reset to 0 for each of those
-   tables for the file.
-
-   The procedure table contains the binary equivalents of the .ent
-   (start of the function address), .frame (what register is the
-   virtual frame pointer, constant offset from the register to obtain
-   the VFP, and what register holds the return address), .mask/.fmask
-   (bitmask of saved registers, and where the first register is stored
-   relative to the VFP) assembler directives.  It also contains the
-   low and high bounds of the line numbers if debugging is turned on.
-
-   The line number table is a compressed form of the normal COFF line
-   table.  Each line number entry is either 1 or 3 bytes long, and
-   contains a signed delta from the previous line, and an unsigned
-   count of the number of instructions this statement takes.
-
-   The local symbol table contains the following fields:
-
-    1) iss: index to the local string table giving the name of the
-       symbol.
-
-    2) value: value of the symbol (address, register number, etc.).
-
-    3) st: symbol type.  The current symbol types are:
-
-           stNil         -- Nuthin' special
-           stGlobal      -- external symbol
-           stStatic      -- static
-           stParam       -- procedure argument
-           stLocal       -- local variable
-           stLabel       -- label
-           stProc        -- External Procedure
-           stBlock       -- beginning of block
-           stEnd         -- end (of anything)
-           stMember      -- member (of anything)
-           stTypedef     -- type definition
-           stFile        -- file name
-           stRegReloc    -- register relocation
-           stForward     -- forwarding address
-           stStaticProc  -- Static procedure
-           stConstant    -- const
-
-    4) sc: storage class.  The current storage classes are:
-
-           scText        -- text symbol
-           scData        -- initialized data symbol
-           scBss         -- un-initialized data symbol
-           scRegister    -- value of symbol is register number
-           scAbs         -- value of symbol is absolute
-           scUndefined   -- who knows?
-           scCdbLocal    -- variable's value is IN se->va.??
-           scBits        -- this is a bit field
-           scCdbSystem   -- value is IN debugger's address space
-           scRegImage    -- register value saved on stack
-           scInfo        -- symbol contains debugger information
-           scUserStruct  -- addr in struct user for current process
-           scSData       -- load time only small data
-           scSBss        -- load time only small common
-           scRData       -- load time only read only data
-           scVar         -- Var parameter (fortranpascal)
-           scCommon      -- common variable
-           scSCommon     -- small common
-           scVarRegister -- Var parameter in a register
-           scVariant     -- Variant record
-           scSUndefined  -- small undefined(external) data
-           scInit        -- .init section symbol
-
-    5) index: pointer to a local symbol or aux. entry.
-
-
-
-   For the following program:
-
-       #include <stdio.h>
-
-       main(){
-               printf("Hello World!\n");
-               return 0;
-       }
-
-   Mips-tdump produces the following information:
-   
-   Global file header:
-       magic number             0x162
-       # sections               2
-       timestamp                645311799, Wed Jun 13 17:16:39 1990
-       symbolic header offset   284
-       symbolic header size     96
-       optional header          56
-       flags                    0x0
-   
-   Symbolic header, magic number = 0x7009, vstamp = 1.31:
-   
-       Info                      Offset      Number       Bytes
-       ====                      ======      ======      =====
-   
-       Line numbers                 380           4           4 [13]
-       Dense numbers                  0           0           0
-       Procedures Tables            384           1          52
-       Local Symbols                436          16         192
-       Optimization Symbols           0           0           0
-       Auxiliary Symbols            628          39         156
-       Local Strings                784          80          80
-       External Strings             864         144         144
-       File Tables                 1008           2         144
-       Relative Files                 0           0           0
-       External Symbols            1152          20         320
-   
-   File #0, "hello2.c"
-   
-       Name index  = 1          Readin      = No
-       Merge       = No         Endian      = LITTLE
-       Debug level = G2         Language    = C
-       Adr         = 0x00000000
-   
-       Info                       Start      Number        Size      Offset
-       ====                       =====      ======        ====      ======
-       Local strings                  0          15          15         784
-       Local symbols                  0           6          72         436
-       Line numbers                   0          13          13         380
-       Optimization symbols           0           0           0           0
-       Procedures                     0           1          52         384
-       Auxiliary symbols              0          14          56         628
-       Relative Files                 0           0           0           0
-   
-    There are 6 local symbols, starting at 436
-
-       Symbol# 0: "hello2.c"
-           End+1 symbol  = 6
-           String index  = 1
-           Storage class = Text        Index  = 6
-           Symbol type   = File        Value  = 0
-
-       Symbol# 1: "main"
-           End+1 symbol  = 5
-           Type          = int
-           String index  = 10
-           Storage class = Text        Index  = 12
-           Symbol type   = Proc        Value  = 0
-
-       Symbol# 2: ""
-           End+1 symbol  = 4
-           String index  = 0
-           Storage class = Text        Index  = 4
-           Symbol type   = Block       Value  = 8
-
-       Symbol# 3: ""
-           First symbol  = 2
-           String index  = 0
-           Storage class = Text        Index  = 2
-           Symbol type   = End         Value  = 28
-
-       Symbol# 4: "main"
-           First symbol  = 1
-           String index  = 10
-           Storage class = Text        Index  = 1
-           Symbol type   = End         Value  = 52
-
-       Symbol# 5: "hello2.c"
-           First symbol  = 0
-           String index  = 1
-           Storage class = Text        Index  = 0
-           Symbol type   = End         Value  = 0
-
-    There are 14 auxiliary table entries, starting at 628.
-
-       * #0               0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
-       * #1              24, [  24/      0], [ 6 0:0 0:0:0:0:0:0]
-       * #2               8, [   8/      0], [ 2 0:0 0:0:0:0:0:0]
-       * #3              16, [  16/      0], [ 4 0:0 0:0:0:0:0:0]
-       * #4              24, [  24/      0], [ 6 0:0 0:0:0:0:0:0]
-       * #5              32, [  32/      0], [ 8 0:0 0:0:0:0:0:0]
-       * #6              40, [  40/      0], [10 0:0 0:0:0:0:0:0]
-       * #7              44, [  44/      0], [11 0:0 0:0:0:0:0:0]
-       * #8              12, [  12/      0], [ 3 0:0 0:0:0:0:0:0]
-       * #9              20, [  20/      0], [ 5 0:0 0:0:0:0:0:0]
-       * #10             28, [  28/      0], [ 7 0:0 0:0:0:0:0:0]
-       * #11             36, [  36/      0], [ 9 0:0 0:0:0:0:0:0]
-         #12              5, [   5/      0], [ 1 1:0 0:0:0:0:0:0]
-         #13             24, [  24/      0], [ 6 0:0 0:0:0:0:0:0]
-
-    There are 1 procedure descriptor entries, starting at 0.
-
-       Procedure descriptor 0:
-           Name index   = 10          Name          = "main"
-           .mask 0x80000000,-4        .fmask 0x00000000,0
-           .frame $29,24,$31
-           Opt. start   = -1          Symbols start = 1
-           First line # = 3           Last line #   = 6
-           Line Offset  = 0           Address       = 0x00000000
-
-       There are 4 bytes holding line numbers, starting at 380.
-           Line           3,   delta     0,   count  2
-           Line           4,   delta     1,   count  3
-           Line           5,   delta     1,   count  2
-           Line           6,   delta     1,   count  6
-
-   File #1, "/usr/include/stdio.h"
-
-    Name index  = 1          Readin      = No
-    Merge       = Yes        Endian      = LITTLE
-    Debug level = G2         Language    = C
-    Adr         = 0x00000000
-
-    Info                       Start      Number        Size      Offset
-    ====                       =====      ======        ====      ======
-    Local strings                 15          65          65         799
-    Local symbols                  6          10         120         508
-    Line numbers                   0           0           0         380
-    Optimization symbols           0           0           0           0
-    Procedures                     1           0           0         436
-    Auxiliary symbols             14          25         100         684
-    Relative Files                 0           0           0           0
-
-    There are 10 local symbols, starting at 442
-
-       Symbol# 0: "/usr/include/stdio.h"
-           End+1 symbol  = 10
-           String index  = 1
-           Storage class = Text        Index  = 10
-           Symbol type   = File        Value  = 0
-
-       Symbol# 1: "_iobuf"
-           End+1 symbol  = 9
-           String index  = 22
-           Storage class = Info        Index  = 9
-           Symbol type   = Block       Value  = 20
-
-       Symbol# 2: "_cnt"
-           Type          = int
-           String index  = 29
-           Storage class = Info        Index  = 4
-           Symbol type   = Member      Value  = 0
-
-       Symbol# 3: "_ptr"
-           Type          = ptr to char
-           String index  = 34
-           Storage class = Info        Index  = 15
-           Symbol type   = Member      Value  = 32
-
-       Symbol# 4: "_base"
-           Type          = ptr to char
-           String index  = 39
-           Storage class = Info        Index  = 16
-           Symbol type   = Member      Value  = 64
-
-       Symbol# 5: "_bufsiz"
-           Type          = int
-           String index  = 45
-           Storage class = Info        Index  = 4
-           Symbol type   = Member      Value  = 96
-
-       Symbol# 6: "_flag"
-           Type          = short
-           String index  = 53
-           Storage class = Info        Index  = 3
-           Symbol type   = Member      Value  = 128
-
-       Symbol# 7: "_file"
-           Type          = char
-           String index  = 59
-           Storage class = Info        Index  = 2
-           Symbol type   = Member      Value  = 144
-
-       Symbol# 8: ""
-           First symbol  = 1
-           String index  = 0
-           Storage class = Info        Index  = 1
-           Symbol type   = End         Value  = 0
-
-       Symbol# 9: "/usr/include/stdio.h"
-           First symbol  = 0
-           String index  = 1
-           Storage class = Text        Index  = 0
-           Symbol type   = End         Value  = 0
-
-    There are 25 auxiliary table entries, starting at 642.
-
-       * #14             -1, [4095/1048575], [63 1:1 f:f:f:f:f:f]
-         #15          65544, [   8/     16], [ 2 0:0 1:0:0:0:0:0]
-         #16          65544, [   8/     16], [ 2 0:0 1:0:0:0:0:0]
-       * #17         196656, [  48/     48], [12 0:0 3:0:0:0:0:0]
-       * #18           8191, [4095/      1], [63 1:1 0:0:0:0:f:1]
-       * #19              1, [   1/      0], [ 0 1:0 0:0:0:0:0:0]
-       * #20          20479, [4095/      4], [63 1:1 0:0:0:0:f:4]
-       * #21              1, [   1/      0], [ 0 1:0 0:0:0:0:0:0]
-       * #22              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
-       * #23              2, [   2/      0], [ 0 0:1 0:0:0:0:0:0]
-       * #24            160, [ 160/      0], [40 0:0 0:0:0:0:0:0]
-       * #25              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
-       * #26              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
-       * #27              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
-       * #28              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
-       * #29              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
-       * #30              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
-       * #31              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
-       * #32              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
-       * #33              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
-       * #34              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
-       * #35              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
-       * #36              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
-       * #37              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
-       * #38              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
-
-    There are 0 procedure descriptor entries, starting at 1.
-
-   There are 20 external symbols, starting at 1152
-
-       Symbol# 0: "_iob"
-           Type          = array [3 {160}] of struct _iobuf { ifd = 1, index = 1 }
-           String index  = 0           Ifd    = 1
-           Storage class = Nil         Index  = 17
-           Symbol type   = Global      Value  = 60
-
-       Symbol# 1: "fopen"
-           String index  = 5           Ifd    = 1
-           Storage class = Nil         Index  = 1048575
-           Symbol type   = Proc        Value  = 0
-
-       Symbol# 2: "fdopen"
-           String index  = 11          Ifd    = 1
-           Storage class = Nil         Index  = 1048575
-           Symbol type   = Proc        Value  = 0
-
-       Symbol# 3: "freopen"
-           String index  = 18          Ifd    = 1
-           Storage class = Nil         Index  = 1048575
-           Symbol type   = Proc        Value  = 0
-
-       Symbol# 4: "popen"
-           String index  = 26          Ifd    = 1
-           Storage class = Nil         Index  = 1048575
-           Symbol type   = Proc        Value  = 0
-
-       Symbol# 5: "tmpfile"
-           String index  = 32          Ifd    = 1
-           Storage class = Nil         Index  = 1048575
-           Symbol type   = Proc        Value  = 0
-
-       Symbol# 6: "ftell"
-           String index  = 40          Ifd    = 1
-           Storage class = Nil         Index  = 1048575
-           Symbol type   = Proc        Value  = 0
-
-       Symbol# 7: "rewind"
-           String index  = 46          Ifd    = 1
-           Storage class = Nil         Index  = 1048575
-           Symbol type   = Proc        Value  = 0
-
-       Symbol# 8: "setbuf"
-           String index  = 53          Ifd    = 1
-           Storage class = Nil         Index  = 1048575
-           Symbol type   = Proc        Value  = 0
-
-       Symbol# 9: "setbuffer"
-           String index  = 60          Ifd    = 1
-           Storage class = Nil         Index  = 1048575
-           Symbol type   = Proc        Value  = 0
-
-       Symbol# 10: "setlinebuf"
-           String index  = 70          Ifd    = 1
-           Storage class = Nil         Index  = 1048575
-           Symbol type   = Proc        Value  = 0
-
-       Symbol# 11: "fgets"
-           String index  = 81          Ifd    = 1
-           Storage class = Nil         Index  = 1048575
-           Symbol type   = Proc        Value  = 0
-
-       Symbol# 12: "gets"
-           String index  = 87          Ifd    = 1
-           Storage class = Nil         Index  = 1048575
-           Symbol type   = Proc        Value  = 0
-
-       Symbol# 13: "ctermid"
-           String index  = 92          Ifd    = 1
-           Storage class = Nil         Index  = 1048575
-           Symbol type   = Proc        Value  = 0
-
-       Symbol# 14: "cuserid"
-           String index  = 100         Ifd    = 1
-           Storage class = Nil         Index  = 1048575
-           Symbol type   = Proc        Value  = 0
-
-       Symbol# 15: "tempnam"
-           String index  = 108         Ifd    = 1
-           Storage class = Nil         Index  = 1048575
-           Symbol type   = Proc        Value  = 0
-
-       Symbol# 16: "tmpnam"
-           String index  = 116         Ifd    = 1
-           Storage class = Nil         Index  = 1048575
-           Symbol type   = Proc        Value  = 0
-
-       Symbol# 17: "sprintf"
-           String index  = 123         Ifd    = 1
-           Storage class = Nil         Index  = 1048575
-           Symbol type   = Proc        Value  = 0
-
-       Symbol# 18: "main"
-           Type          = int
-           String index  = 131         Ifd    = 0
-           Storage class = Text        Index  = 1
-           Symbol type   = Proc        Value  = 0
-
-       Symbol# 19: "printf"
-           String index  = 136         Ifd    = 0
-           Storage class = Undefined   Index  = 1048575
-           Symbol type   = Proc        Value  = 0
-
-   The following auxiliary table entries were unused:
-
-    #0               0  0x00000000  void
-    #2               8  0x00000008  char
-    #3              16  0x00000010  short
-    #4              24  0x00000018  int
-    #5              32  0x00000020  long
-    #6              40  0x00000028  float
-    #7              44  0x0000002c  double
-    #8              12  0x0000000c  unsigned char
-    #9              20  0x00000014  unsigned short
-    #10             28  0x0000001c  unsigned int
-    #11             36  0x00000024  unsigned long
-    #14              0  0x00000000  void
-    #15             24  0x00000018  int
-    #19             32  0x00000020  long
-    #20             40  0x00000028  float
-    #21             44  0x0000002c  double
-    #22             12  0x0000000c  unsigned char
-    #23             20  0x00000014  unsigned short
-    #24             28  0x0000001c  unsigned int
-    #25             36  0x00000024  unsigned long
-    #26             48  0x00000030  struct no name { ifd = -1, index = 1048575 }
-\f
-*/
-/* Redefinition of of storage classes as an enumeration for better
-   debugging.  */
-
-typedef enum sc {
-  sc_Nil        = scNil,         /* no storage class */
-  sc_Text       = scText,        /* text symbol */
-  sc_Data       = scData,        /* initialized data symbol */
-  sc_Bss        = scBss,         /* un-initialized data symbol */
-  sc_Register   = scRegister,    /* value of symbol is register number */
-  sc_Abs        = scAbs,         /* value of symbol is absolute */
-  sc_Undefined  = scUndefined,   /* who knows? */
-  sc_CdbLocal   = scCdbLocal,    /* variable's value is IN se->va.?? */
-  sc_Bits       = scBits,        /* this is a bit field */
-  sc_CdbSystem  = scCdbSystem,   /* value is IN CDB's address space */
-  sc_RegImage   = scRegImage,    /* register value saved on stack */
-  sc_Info       = scInfo,        /* symbol contains debugger information */
-  sc_UserStruct         = scUserStruct,  /* addr in struct user for current process */
-  sc_SData      = scSData,       /* load time only small data */
-  sc_SBss       = scSBss,        /* load time only small common */
-  sc_RData      = scRData,       /* load time only read only data */
-  sc_Var        = scVar,         /* Var parameter (fortran,pascal) */
-  sc_Common     = scCommon,      /* common variable */
-  sc_SCommon    = scSCommon,     /* small common */
-  sc_VarRegister = scVarRegister, /* Var parameter in a register */
-  sc_Variant    = scVariant,     /* Variant record */
-  sc_SUndefined         = scSUndefined,  /* small undefined(external) data */
-  sc_Init       = scInit,        /* .init section symbol */
-  sc_Max        = scMax          /* Max storage class+1 */
-} sc_t;
-
-/* Redefinition of symbol type.  */
-
-typedef enum st {
-  st_Nil       = stNil,        /* Nuthin' special */
-  st_Global    = stGlobal,     /* external symbol */
-  st_Static    = stStatic,     /* static */
-  st_Param     = stParam,      /* procedure argument */
-  st_Local     = stLocal,      /* local variable */
-  st_Label     = stLabel,      /* label */
-  st_Proc      = stProc,       /*     "      "  Procedure */
-  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 */
-  st_File      = stFile,       /* file name */
-  st_RegReloc  = stRegReloc,   /* register relocation */
-  st_Forward   = stForward,    /* forwarding address */
-  st_StaticProc        = stStaticProc, /* load time only static procs */
-  st_Constant  = stConstant,   /* const */
-  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-coercion SER */
-  st_Max       = stMax         /* max type+1 */
-} st_t;
-
-/* Redefinition of type qualifiers.  */
-
-typedef enum tq {
-  tq_Nil       = tqNil,        /* bt is what you see */
-  tq_Ptr       = tqPtr,        /* pointer */
-  tq_Proc      = tqProc,       /* procedure */
-  tq_Array     = tqArray,      /* duh */
-  tq_Far       = tqFar,        /* longer addressing - 8086/8 land */
-  tq_Vol       = tqVol,        /* volatile */
-  tq_Max       = tqMax         /* Max type qualifier+1 */
-} tq_t;
-
-/* Redefinition of basic types.  */
-
-typedef enum bt {
-  bt_Nil       = btNil,        /* undefined */
-  bt_Adr       = btAdr,        /* address - integer same size as pointer */
-  bt_Char      = btChar,       /* character */
-  bt_UChar     = btUChar,      /* unsigned character */
-  bt_Short     = btShort,      /* short */
-  bt_UShort    = btUShort,     /* unsigned short */
-  bt_Int       = btInt,        /* int */
-  bt_UInt      = btUInt,       /* unsigned int */
-  bt_Long      = btLong,       /* long */
-  bt_ULong     = btULong,      /* unsigned long */
-  bt_Float     = btFloat,      /* float (real) */
-  bt_Double    = btDouble,     /* Double (real) */
-  bt_Struct    = btStruct,     /* Structure (Record) */
-  bt_Union     = btUnion,      /* Union (variant) */
-  bt_Enum      = btEnum,       /* Enumerated */
-  bt_Typedef   = btTypedef,    /* defined via a typedef, isymRef points */
-  bt_Range     = btRange,      /* subrange of int */
-  bt_Set       = btSet,        /* pascal sets */
-  bt_Complex   = btComplex,    /* fortran complex */
-  bt_DComplex  = btDComplex,   /* fortran double complex */
-  bt_Indirect  = btIndirect,   /* forward or unnamed typedef */
-  bt_FixedDec  = btFixedDec,   /* Fixed Decimal */
-  bt_FloatDec  = btFloatDec,   /* Float Decimal */
-  bt_String    = btString,     /* Varying Length Character String */
-  bt_Bit       = btBit,        /* Aligned Bit String */
-  bt_Picture   = btPicture,    /* Picture */
-  bt_Void      = btVoid,       /* Void */
-  bt_Max       = btMax         /* Max basic type+1 */
-} bt_t;
-
-#define N_TQ itqMax
-
-/* States for whether to hash type or not.  */
-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_state_t;
-
-/* Types of different sized allocation requests.  */
-enum alloc_type {
-  alloc_type_none,             /* dummy value */
-  alloc_type_scope,            /* nested scopes linked list */
-  alloc_type_vlinks,           /* glue linking pages in varray */
-  alloc_type_shash,            /* string hash element */
-  alloc_type_thash,            /* type hash element */
-  alloc_type_tag,              /* struct/union/tag element */
-  alloc_type_forward,          /* element to hold unknown tag */
-  alloc_type_thead,            /* head of type hash list */
-  alloc_type_varray,           /* general varray allocation */
-  alloc_type_lineno,           /* line number list */
-  alloc_type_last              /* last+1 element for array bounds */
-};
-
-/* Types of auxiliary type information.  */
-enum aux_type {
-  aux_tir,                     /* TIR type information */
-  aux_rndx,                    /* relative index into symbol table */
-  aux_dnLow,                   /* low dimension */
-  aux_dnHigh,                  /* high dimension */
-  aux_isym,                    /* symbol table index (end of proc) */
-  aux_iss,                     /* index into string space (not used) */
-  aux_width,                   /* width for non-default sized struc fields */
-  aux_count                    /* count of ranges for variant arm */
-};
-\f
-/* Structures to provide n-number of virtual arrays, each of which can
-   grow linearly, and which are written in the object file as
-   sequential pages.  On systems with a BSD malloc, the
-   MAX_CLUSTER_PAGES should be 1 less than a power of two, since
-   malloc adds it's overhead, and rounds up to the next power of 2.
-   Pages are linked together via a linked list.
-
-   If PAGE_SIZE is > 4096, the string length in the shash_t structure
-   can't be represented (assuming there are strings > 4096 bytes).  */
-
-#ifndef PAGE_SIZE
-#define PAGE_SIZE 4096         /* size of varray pages */
-#endif
-
-#define PAGE_USIZE ((unsigned long) PAGE_SIZE)
-
-
-#ifndef MAX_CLUSTER_PAGES      /* # pages to get from system */
-#define MAX_CLUSTER_PAGES 63
-#endif
-
-
-/* Linked list connecting separate page allocations.  */
-typedef struct vlinks {
-  struct vlinks        *prev;          /* previous set of pages */
-  struct vlinks *next;         /* next set of pages */
-  union  page   *datum;                /* start of page */
-  unsigned long         start_index;   /* starting index # of page */
-} vlinks_t;
-
-
-/* Virtual array header.  */
-typedef struct varray {
-  vlinks_t     *first;                 /* first page link */
-  vlinks_t     *last;                  /* last page link */
-  unsigned long         num_allocated;         /* # objects allocated */
-  unsigned short object_size;          /* size in bytes of each object */
-  unsigned short objects_per_page;     /* # objects that can fit on a page */
-  unsigned short objects_last_page;    /* # objects allocated on last page */
-} varray_t;
-
-#ifndef MALLOC_CHECK
-#define OBJECTS_PER_PAGE(type) (PAGE_SIZE / sizeof (type))
-#else
-#define OBJECTS_PER_PAGE(type) ((sizeof (type) > 1) ? 1 : PAGE_SIZE)
-#endif
-
-#define INIT_VARRAY(type) {    /* macro to initialize a varray */      \
-  (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. */
-typedef unsigned long symint_t;
-
-
-/* Linked list support for nested scopes (file, block, structure, etc.).  */
-typedef struct scope {
-  struct scope *prev;          /* previous scope level */
-  struct scope *free;          /* free list pointer */
-  struct localsym *lsym;       /* pointer to local symbol node */
-  st_t          type;          /* type of the node */
-} scope_t;
-
-
-/* For a local symbol we store a gas symbol as well as the debugging
-   information we generate.  The gas symbol will be NULL if this is
-   only a debugging symbol.  */
-typedef struct localsym {
-  const char *name;            /* symbol name */
-  symbolS *as_sym;             /* symbol as seen by gas */
-  struct efdr *file_ptr;       /* file pointer */
-  struct ecoff_proc *proc_ptr; /* proc pointer */
-  struct localsym *begin_ptr;  /* symbol at start of block */
-  struct ecoff_aux *index_ptr; /* index value to be filled in */
-  struct forward *forward_ref; /* forward references to this symbol */
-  long sym_index;              /* final symbol index */
-  SYMR ecoff_sym;              /* ECOFF debugging symbol */
-} localsym_t;
-
-
-/* For aux information we keep the type and the data.  */
-typedef struct ecoff_aux {
-  enum aux_type type;          /* aux type */
-  AUXU data;                   /* aux data */
-} aux_t;
-
-/* For a procedure we store the gas symbol as well as the PDR
-   debugging information.  */
-typedef struct ecoff_proc {
-  localsym_t *sym;             /* associated symbol */
-  PDR pdr;                     /* ECOFF debugging info */
-} proc_t;
-
-/* Number of proc_t structures allocated.  */
-static unsigned long proc_cnt;
-
-
-/* Forward reference list for tags referenced, but not yet defined.  */
-typedef struct forward {
-  struct forward *next;                /* next forward reference */
-  struct forward *free;                /* free list pointer */
-  aux_t                 *ifd_ptr;      /* pointer to store file index */
-  aux_t                 *index_ptr;    /* pointer to store symbol index */
-} forward_t;
-
-
-/* Linked list support for tags.  The first tag in the list is always
-   the current tag for that block.  */
-typedef struct tag {
-  struct tag    *free;         /* free list pointer */
-  struct shash  *hash_ptr;     /* pointer to the hash table head */
-  struct tag    *same_name;    /* tag with same name in outer scope */
-  struct tag    *same_block;   /* next tag defined in the same block.  */
-  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 */
-  localsym_t    *sym;          /* file's local symbols */
-} tag_t;
-
-
-/* Head of a block's linked list of tags.  */
-typedef struct thead {
-  struct thead *prev;          /* previous block */
-  struct thead *free;          /* free list pointer */
-  struct tag   *first_tag;     /* first tag in block defined */
-} thead_t;
-
-
-/* Union containing pointers to each the small structures which are freed up.  */
-typedef union small_free {
-  scope_t      *f_scope;       /* scope structure */
-  thead_t      *f_thead;       /* tag head structure */
-  tag_t                *f_tag;         /* tag element structure */
-  forward_t    *f_forward;     /* forward tag reference */
-} small_free_t;
-
-
-/* String hash table entry.  */
-
-typedef struct shash {
-  char         *string;        /* string we are hashing */
-  symint_t      indx;          /* index within string table */
-  EXTR         *esym_ptr;      /* global symbol pointer */
-  localsym_t   *sym_ptr;       /* local symbol pointer */
-  localsym_t   *end_ptr;       /* symbol pointer to end block */
-  tag_t                *tag_ptr;       /* tag pointer */
-  proc_t       *proc_ptr;      /* procedure descriptor pointer */
-} shash_t;
-
-
-/* Type hash table support.  The size of the hash table must fit
-   within a page with the other extended file descriptor information.
-   Because unique types which are hashed are fewer in number than
-   strings, we use a smaller hash value.  */
-
-#define HASHBITS 30
-
-#ifndef THASH_SIZE
-#define THASH_SIZE 113
-#endif
-
-typedef struct thash {
-  struct thash *next;          /* next hash value */
-  AUXU          type;          /* type we are hashing */
-  symint_t      indx;          /* index within string table */
-} thash_t;
-
-
-/* Extended file descriptor that contains all of the support necessary
-   to add things to each file separately.  */
-typedef struct efdr {
-  FDR           fdr;           /* File header to be written out */
-  FDR          *orig_fdr;      /* original file header */
-  char         *name;          /* filename */
-  symint_t      void_type;     /* aux. pointer to 'void' type */
-  symint_t      int_type;      /* aux. pointer to 'int' type */
-  scope_t      *cur_scope;     /* current nested scopes */
-  symint_t      file_index;    /* current file number */
-  int           nested_scopes; /* # nested scopes */
-  varray_t      strings;       /* local strings */
-  varray_t      symbols;       /* local symbols */
-  varray_t      procs;         /* procedures */
-  varray_t      aux_syms;      /* auxiliary symbols */
-  struct efdr  *next_file;     /* next file descriptor */
-                               /* string/type hash tables */
-  struct hash_control *str_hash;       /* string hash table */
-  thash_t      *thash_head[THASH_SIZE];
-} efdr_t;
-
-/* Pre-initialized extended file structure.  */
-static const efdr_t init_file = 
-{
-  {                    /* FDR structure */
-    0,                 /* adr:         memory address of beginning of file */
-    0,                 /* rss:         file name (of source, if known) */
-    0,                 /* issBase:     file's string space */
-    0,                 /* cbSs:        number of bytes in the ss */
-    0,                 /* isymBase:    beginning of symbols */
-    0,                 /* csym:        count file's of symbols */
-    0,                 /* ilineBase:   file's line symbols */
-    0,                 /* cline:       count of file's line symbols */
-    0,                 /* ioptBase:    file's optimization entries */
-    0,                 /* copt:        count of file's optimization entries */
-    0,                 /* ipdFirst:    start of procedures for this file */
-    0,                 /* cpd:         count of procedures for this file */
-    0,                 /* iauxBase:    file's auxiliary entries */
-    0,                 /* caux:        count of file's auxiliary entries */
-    0,                 /* rfdBase:     index into the file indirect table */
-    0,                 /* crfd:        count file indirect entries */
-    langC,             /* lang:        language for this file */
-    0,                 /* fMerge:      whether this file can be merged */
-    0,                 /* fReadin:     true if read in (not just created) */
-#ifdef TARGET_BYTES_BIG_ENDIAN
-    1,                 /* fBigendian:  if 1, compiled on big endian machine */
-#else
-    0,                 /* fBigendian:  if 1, compiled on big endian machine */
-#endif
-    GLEVEL_2,          /* glevel:      level this file was compiled with */
-    0,                 /* reserved:    reserved for future use */
-    0,                 /* cbLineOffset: byte offset from header for this file ln's */
-    0,                 /* cbLine:      size of lines for this file */
-  },
-
-  (FDR *)0,            /* orig_fdr:    original file header pointer */
-  (char *)0,           /* name:        pointer to 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 */
-  0,                   /* file_index:  current file # */
-  0,                   /* nested_scopes: # nested scopes */
-  INIT_VARRAY (char),  /* strings:     local string varray */
-  INIT_VARRAY (localsym_t),    /* symbols:     local symbols varray */
-  INIT_VARRAY (proc_t),        /* procs:       procedure varray */
-  INIT_VARRAY (aux_t), /* aux_syms:    auxiliary symbols varray */
-
-  (struct efdr *)0,    /* next_file:   next file structure */
-
-  (struct hash_control *)0,    /* str_hash:    string hash table */
-  { 0 },               /* thash_head:  type hash table */
-};
-
-
-static efdr_t *first_file;                     /* first file descriptor */
-static efdr_t **last_file_ptr = &first_file;   /* file descriptor tail */
-
-
-/* Line number information is kept in a list until the assembly is
-   finished.  */
-typedef struct lineno_list {
-  struct lineno_list *next;    /* next element in list */
-  efdr_t *file;                        /* file this line is in */
-  proc_t *proc;                        /* procedure this line is in */
-  fragS *frag;                 /* fragment this line number is in */
-  unsigned long paddr;         /* offset within fragment */
-  long lineno;                 /* actual line number */
-} lineno_list_t;
-
-static lineno_list_t *first_lineno;
-static lineno_list_t **last_lineno_ptr = &first_lineno;
-
-/* Sometimes there will be some .loc statements before a .ent.  We
-   keep them in this list so that we can fill in the procedure pointer
-   after we see the .ent.  */
-static lineno_list_t *noproc_lineno;
-
-/* Union of various things that are held in pages.  */
-typedef union page {
-  char         byte    [ PAGE_SIZE ];
-  unsigned char        ubyte   [ PAGE_SIZE ];
-  efdr_t       file    [ PAGE_SIZE / sizeof (efdr_t)        ];
-  FDR          ofile   [ PAGE_SIZE / sizeof (FDR)           ];
-  proc_t       proc    [ PAGE_SIZE / sizeof (proc_t)        ];
-  localsym_t   sym     [ PAGE_SIZE / sizeof (localsym_t)    ];
-  aux_t                aux     [ PAGE_SIZE / sizeof (aux_t)         ];
-  DNR          dense   [ PAGE_SIZE / sizeof (DNR)           ];
-  scope_t      scope   [ PAGE_SIZE / sizeof (scope_t)       ];
-  vlinks_t     vlinks  [ PAGE_SIZE / sizeof (vlinks_t)      ];
-  shash_t      shash   [ PAGE_SIZE / sizeof (shash_t)       ];
-  thash_t      thash   [ PAGE_SIZE / sizeof (thash_t)       ];
-  tag_t                tag     [ PAGE_SIZE / sizeof (tag_t)         ];
-  forward_t    forward [ PAGE_SIZE / sizeof (forward_t)     ];
-  thead_t      thead   [ PAGE_SIZE / sizeof (thead_t)       ];
-  lineno_list_t        lineno  [ PAGE_SIZE / sizeof (lineno_list_t) ];
-} page_t;
-
-
-/* Structure holding allocation information for small sized structures.  */
-typedef struct alloc_info {
-  char         *alloc_name;    /* name of this allocation type (must be first) */
-  page_t       *cur_page;      /* current page being allocated from */
-  small_free_t  free_list;     /* current free list if any */
-  int           unallocated;   /* number of elements unallocated on page */
-  int           total_alloc;   /* total number of allocations */
-  int           total_free;    /* total number of frees */
-  int           total_pages;   /* total number of pages allocated */
-} alloc_info_t;
-
-
-/* Type information collected together.  */
-typedef struct type_info {
-  bt_t       basic_type;               /* basic type */
-  int        orig_type;                /* original COFF-based type */
-  int        num_tq;                   /* # type qualifiers */
-  int        num_dims;                 /* # dimensions */
-  int        num_sizes;                /* # sizes */
-  int        extra_sizes;              /* # extra sizes not tied with dims */
-  tag_t *     tag_ptr;                 /* tag pointer */
-  int        bitfield;                 /* symbol is a bitfield */
-  tq_t       type_qualifiers[N_TQ];    /* type qualifiers (ptr, func, array)*/
-  symint_t    dimensions     [N_TQ];   /* dimensions for each array */
-  symint_t    sizes         [N_TQ+2];  /* sizes of each array slice + size of
-                                          struct/union/enum + bitfield size */
-} type_info_t;
-
-/* Pre-initialized type_info struct.  */
-static const type_info_t type_info_init = {
-  bt_Nil,                              /* basic type */
-  T_NULL,                              /* original COFF-based type */
-  0,                                   /* # type qualifiers */
-  0,                                   /* # dimensions */
-  0,                                   /* # sizes */
-  0,                                   /* sizes not tied with dims */
-  NULL,                                        /* ptr to tag */
-  0,                                   /* bitfield */
-  {                                    /* type qualifiers */
-    tq_Nil,
-    tq_Nil,
-    tq_Nil,
-    tq_Nil,
-    tq_Nil,
-    tq_Nil,
-  },
-  {                                    /* dimensions */
-    0,
-    0,
-    0,
-    0,
-    0,
-    0
-  },
-  {                                    /* sizes */
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-  },
-};
-
-/* Global hash table for the tags table and global table for file
-   descriptors.  */
-
-static varray_t file_desc      = INIT_VARRAY (efdr_t);
-
-static struct hash_control *tag_hash;
-
-/* Static types for int and void.  Also, remember the last function's
-   type (which is set up when we encounter the declaration for the
-   function, and used when the end block for the function is emitted.  */
-
-static type_info_t int_type_info;
-static type_info_t void_type_info;
-static type_info_t last_func_type_info;
-static symbolS *last_func_sym_value;
-
-
-/* Convert COFF basic type to ECOFF basic type.  The T_NULL type
-   really should use bt_Void, but this causes the current ecoff GDB to
-   issue unsupported type messages, and the Ultrix 4.00 dbx (aka MIPS
-   2.0) doesn't understand it, even though the compiler generates it.
-   Maybe this will be fixed in 2.10 or 2.20 of the MIPS compiler
-   suite, but for now go with what works.
-
-   It would make sense for the .type and .scl directives to use the
-   ECOFF numbers directly, rather than using the COFF numbers and
-   mapping them.  Unfortunately, this is historically what mips-tfile
-   expects, and changing gcc now would be a considerable pain (the
-   native compiler generates debugging information internally, rather
-   than via the assembler, so it will never use .type or .scl).  */
-
-static const bt_t map_coff_types[] = {
-  bt_Nil,                      /* T_NULL */
-  bt_Nil,                      /* T_ARG */
-  bt_Char,                     /* T_CHAR */
-  bt_Short,                    /* T_SHORT */
-  bt_Int,                      /* T_INT */
-  bt_Long,                     /* T_LONG */
-  bt_Float,                    /* T_FLOAT */
-  bt_Double,                   /* T_DOUBLE */
-  bt_Struct,                   /* T_STRUCT */
-  bt_Union,                    /* T_UNION */
-  bt_Enum,                     /* T_ENUM */
-  bt_Enum,                     /* T_MOE */
-  bt_UChar,                    /* T_UCHAR */
-  bt_UShort,                   /* T_USHORT */
-  bt_UInt,                     /* T_UINT */
-  bt_ULong                     /* T_ULONG */
-};
-
-/* Convert COFF storage class to ECOFF storage class.  */
-static const sc_t map_coff_storage[] = {
-  sc_Nil,                      /*   0: C_NULL */
-  sc_Abs,                      /*   1: C_AUTO    auto var */
-  sc_Undefined,                        /*   2: C_EXT     external */
-  sc_Data,                     /*   3: C_STAT    static */
-  sc_Register,                 /*   4: C_REG     register */
-  sc_Undefined,                        /*   5: C_EXTDEF  ??? */
-  sc_Text,                     /*   6: C_LABEL   label */
-  sc_Text,                     /*   7: C_ULABEL  user label */
-  sc_Info,                     /*   8: C_MOS     member of struct */
-  sc_Abs,                      /*   9: C_ARG     argument */
-  sc_Info,                     /*  10: C_STRTAG  struct tag */
-  sc_Info,                     /*  11: C_MOU     member of union */
-  sc_Info,                     /*  12: C_UNTAG   union tag */
-  sc_Info,                     /*  13: C_TPDEF   typedef */
-  sc_Data,                     /*  14: C_USTATIC ??? */
-  sc_Info,                     /*  15: C_ENTAG   enum tag */
-  sc_Info,                     /*  16: C_MOE     member of enum */
-  sc_Register,                 /*  17: C_REGPARM register parameter */
-  sc_Bits,                     /*  18; C_FIELD   bitfield */
-  sc_Nil,                      /*  19 */
-  sc_Nil,                      /*  20 */
-  sc_Nil,                      /*  21 */
-  sc_Nil,                      /*  22 */
-  sc_Nil,                      /*  23 */
-  sc_Nil,                      /*  24 */
-  sc_Nil,                      /*  25 */
-  sc_Nil,                      /*  26 */
-  sc_Nil,                      /*  27 */
-  sc_Nil,                      /*  28 */
-  sc_Nil,                      /*  29 */
-  sc_Nil,                      /*  30 */
-  sc_Nil,                      /*  31 */
-  sc_Nil,                      /*  32 */
-  sc_Nil,                      /*  33 */
-  sc_Nil,                      /*  34 */
-  sc_Nil,                      /*  35 */
-  sc_Nil,                      /*  36 */
-  sc_Nil,                      /*  37 */
-  sc_Nil,                      /*  38 */
-  sc_Nil,                      /*  39 */
-  sc_Nil,                      /*  40 */
-  sc_Nil,                      /*  41 */
-  sc_Nil,                      /*  42 */
-  sc_Nil,                      /*  43 */
-  sc_Nil,                      /*  44 */
-  sc_Nil,                      /*  45 */
-  sc_Nil,                      /*  46 */
-  sc_Nil,                      /*  47 */
-  sc_Nil,                      /*  48 */
-  sc_Nil,                      /*  49 */
-  sc_Nil,                      /*  50 */
-  sc_Nil,                      /*  51 */
-  sc_Nil,                      /*  52 */
-  sc_Nil,                      /*  53 */
-  sc_Nil,                      /*  54 */
-  sc_Nil,                      /*  55 */
-  sc_Nil,                      /*  56 */
-  sc_Nil,                      /*  57 */
-  sc_Nil,                      /*  58 */
-  sc_Nil,                      /*  59 */
-  sc_Nil,                      /*  60 */
-  sc_Nil,                      /*  61 */
-  sc_Nil,                      /*  62 */
-  sc_Nil,                      /*  63 */
-  sc_Nil,                      /*  64 */
-  sc_Nil,                      /*  65 */
-  sc_Nil,                      /*  66 */
-  sc_Nil,                      /*  67 */
-  sc_Nil,                      /*  68 */
-  sc_Nil,                      /*  69 */
-  sc_Nil,                      /*  70 */
-  sc_Nil,                      /*  71 */
-  sc_Nil,                      /*  72 */
-  sc_Nil,                      /*  73 */
-  sc_Nil,                      /*  74 */
-  sc_Nil,                      /*  75 */
-  sc_Nil,                      /*  76 */
-  sc_Nil,                      /*  77 */
-  sc_Nil,                      /*  78 */
-  sc_Nil,                      /*  79 */
-  sc_Nil,                      /*  80 */
-  sc_Nil,                      /*  81 */
-  sc_Nil,                      /*  82 */
-  sc_Nil,                      /*  83 */
-  sc_Nil,                      /*  84 */
-  sc_Nil,                      /*  85 */
-  sc_Nil,                      /*  86 */
-  sc_Nil,                      /*  87 */
-  sc_Nil,                      /*  88 */
-  sc_Nil,                      /*  89 */
-  sc_Nil,                      /*  90 */
-  sc_Nil,                      /*  91 */
-  sc_Nil,                      /*  92 */
-  sc_Nil,                      /*  93 */
-  sc_Nil,                      /*  94 */
-  sc_Nil,                      /*  95 */
-  sc_Nil,                      /*  96 */
-  sc_Nil,                      /*  97 */
-  sc_Nil,                      /*  98 */
-  sc_Nil,                      /*  99 */
-  sc_Text,                     /* 100: C_BLOCK  block start/end */
-  sc_Text,                     /* 101: C_FCN    function start/end */
-  sc_Info,                     /* 102: C_EOS    end of struct/union/enum */
-  sc_Nil,                      /* 103: C_FILE   file start */
-  sc_Nil,                      /* 104: C_LINE   line number */
-  sc_Nil,                      /* 105: C_ALIAS  combined type info */
-  sc_Nil,                      /* 106: C_HIDDEN ??? */
-};
-
-/* Convert COFF storage class to ECOFF symbol type.  */
-static const st_t map_coff_sym_type[] = {
-  st_Nil,                      /*   0: C_NULL */
-  st_Local,                    /*   1: C_AUTO    auto var */
-  st_Global,                   /*   2: C_EXT     external */
-  st_Static,                   /*   3: C_STAT    static */
-  st_Local,                    /*   4: C_REG     register */
-  st_Global,                   /*   5: C_EXTDEF  ??? */
-  st_Label,                    /*   6: C_LABEL   label */
-  st_Label,                    /*   7: C_ULABEL  user label */
-  st_Member,                   /*   8: C_MOS     member of struct */
-  st_Param,                    /*   9: C_ARG     argument */
-  st_Block,                    /*  10: C_STRTAG  struct tag */
-  st_Member,                   /*  11: C_MOU     member of union */
-  st_Block,                    /*  12: C_UNTAG   union tag */
-  st_Typedef,                  /*  13: C_TPDEF   typedef */
-  st_Static,                   /*  14: C_USTATIC ??? */
-  st_Block,                    /*  15: C_ENTAG   enum tag */
-  st_Member,                   /*  16: C_MOE     member of enum */
-  st_Param,                    /*  17: C_REGPARM register parameter */
-  st_Member,                   /*  18; C_FIELD   bitfield */
-  st_Nil,                      /*  19 */
-  st_Nil,                      /*  20 */
-  st_Nil,                      /*  21 */
-  st_Nil,                      /*  22 */
-  st_Nil,                      /*  23 */
-  st_Nil,                      /*  24 */
-  st_Nil,                      /*  25 */
-  st_Nil,                      /*  26 */
-  st_Nil,                      /*  27 */
-  st_Nil,                      /*  28 */
-  st_Nil,                      /*  29 */
-  st_Nil,                      /*  30 */
-  st_Nil,                      /*  31 */
-  st_Nil,                      /*  32 */
-  st_Nil,                      /*  33 */
-  st_Nil,                      /*  34 */
-  st_Nil,                      /*  35 */
-  st_Nil,                      /*  36 */
-  st_Nil,                      /*  37 */
-  st_Nil,                      /*  38 */
-  st_Nil,                      /*  39 */
-  st_Nil,                      /*  40 */
-  st_Nil,                      /*  41 */
-  st_Nil,                      /*  42 */
-  st_Nil,                      /*  43 */
-  st_Nil,                      /*  44 */
-  st_Nil,                      /*  45 */
-  st_Nil,                      /*  46 */
-  st_Nil,                      /*  47 */
-  st_Nil,                      /*  48 */
-  st_Nil,                      /*  49 */
-  st_Nil,                      /*  50 */
-  st_Nil,                      /*  51 */
-  st_Nil,                      /*  52 */
-  st_Nil,                      /*  53 */
-  st_Nil,                      /*  54 */
-  st_Nil,                      /*  55 */
-  st_Nil,                      /*  56 */
-  st_Nil,                      /*  57 */
-  st_Nil,                      /*  58 */
-  st_Nil,                      /*  59 */
-  st_Nil,                      /*  60 */
-  st_Nil,                      /*  61 */
-  st_Nil,                      /*  62 */
-  st_Nil,                      /*  63 */
-  st_Nil,                      /*  64 */
-  st_Nil,                      /*  65 */
-  st_Nil,                      /*  66 */
-  st_Nil,                      /*  67 */
-  st_Nil,                      /*  68 */
-  st_Nil,                      /*  69 */
-  st_Nil,                      /*  70 */
-  st_Nil,                      /*  71 */
-  st_Nil,                      /*  72 */
-  st_Nil,                      /*  73 */
-  st_Nil,                      /*  74 */
-  st_Nil,                      /*  75 */
-  st_Nil,                      /*  76 */
-  st_Nil,                      /*  77 */
-  st_Nil,                      /*  78 */
-  st_Nil,                      /*  79 */
-  st_Nil,                      /*  80 */
-  st_Nil,                      /*  81 */
-  st_Nil,                      /*  82 */
-  st_Nil,                      /*  83 */
-  st_Nil,                      /*  84 */
-  st_Nil,                      /*  85 */
-  st_Nil,                      /*  86 */
-  st_Nil,                      /*  87 */
-  st_Nil,                      /*  88 */
-  st_Nil,                      /*  89 */
-  st_Nil,                      /*  90 */
-  st_Nil,                      /*  91 */
-  st_Nil,                      /*  92 */
-  st_Nil,                      /*  93 */
-  st_Nil,                      /*  94 */
-  st_Nil,                      /*  95 */
-  st_Nil,                      /*  96 */
-  st_Nil,                      /*  97 */
-  st_Nil,                      /*  98 */
-  st_Nil,                      /*  99 */
-  st_Block,                    /* 100: C_BLOCK  block start/end */
-  st_Proc,                     /* 101: C_FCN    function start/end */
-  st_End,                      /* 102: C_EOS    end of struct/union/enum */
-  st_File,                     /* 103: C_FILE   file start */
-  st_Nil,                      /* 104: C_LINE   line number */
-  st_Nil,                      /* 105: C_ALIAS  combined type info */
-  st_Nil,                      /* 106: C_HIDDEN ??? */
-};
-
-
-/* Keep track of different sized allocation requests.  */
-static alloc_info_t alloc_counts[ (int)alloc_type_last ];
-\f
-/* Various statics.  */
-static efdr_t  *cur_file_ptr   = (efdr_t *) 0; /* current file desc. header */
-static proc_t  *cur_proc_ptr   = (proc_t *) 0; /* current procedure header */
-static thead_t *top_tag_head   = (thead_t *) 0; /* top level tag head */
-static thead_t *cur_tag_head   = (thead_t *) 0; /* current tag head */
-#ifdef ECOFF_DEBUG
-static int     debug           = 0;            /* trace functions */
-#endif
-static int     stabs_seen      = 0;            /* != 0 if stabs have been seen */
-
-
-/* Pseudo symbol to use when putting stabs into the symbol table.  */
-#ifndef STABS_SYMBOL
-#define STABS_SYMBOL "@stabs"
-#endif
-
-static char stabs_symbol[] = STABS_SYMBOL;
-\f
-/* Prototypes for functions defined in this file.  */
-
-static void add_varray_page PARAMS ((varray_t *vp));
-static symint_t add_string PARAMS ((varray_t *vp,
-                                   struct hash_control *hash_tbl,
-                                   const char *str,
-                                   shash_t **ret_hash));
-static localsym_t *add_ecoff_symbol PARAMS ((const char *str, st_t type,
-                                            sc_t storage, symbolS *sym,
-                                            symint_t value,
-                                            symint_t indx));
-static symint_t add_aux_sym_symint PARAMS ((symint_t aux_word));
-static symint_t add_aux_sym_rndx PARAMS ((int file_index,
-                                         symint_t sym_index));
-static symint_t add_aux_sym_tir PARAMS ((type_info_t *t,
-                                        hash_state_t state,
-                                        thash_t **hash_tbl));
-static tag_t *get_tag PARAMS ((const char *tag, localsym_t *sym,
-                              bt_t basic_type));
-static void add_unknown_tag PARAMS ((tag_t *ptag));
-static void add_procedure PARAMS ((char *func));
-static void add_file PARAMS ((const char *file_name, int indx));
-#ifdef ECOFF_DEBUG
-static char *sc_to_string PARAMS ((sc_t storage_class));
-static char *st_to_string PARAMS ((st_t symbol_type));
-#endif
-static void obj_ecoff_def PARAMS ((int));
-static void obj_ecoff_dim PARAMS ((int));
-static void obj_ecoff_endef PARAMS ((int));
-static void obj_ecoff_file PARAMS ((int));
-static void obj_ecoff_scl PARAMS ((int));
-static void obj_ecoff_size PARAMS ((int));
-static void obj_ecoff_tag PARAMS ((int));
-static void obj_ecoff_type PARAMS ((int));
-static void obj_ecoff_val PARAMS ((int));
-static void obj_ecoff_ent PARAMS ((int));
-static void obj_ecoff_begin PARAMS ((int));
-static void obj_ecoff_bend PARAMS ((int));
-static void obj_ecoff_end PARAMS ((int));
-static void obj_ecoff_fmask PARAMS ((int));
-static void obj_ecoff_frame PARAMS ((int));
-static void obj_ecoff_loc PARAMS ((int));
-static void obj_ecoff_mask PARAMS ((int));
-static void mark_stabs PARAMS ((int));
-static char *ecoff_add_bytes PARAMS ((char **buf, char **bufend,
-                                     char *bufptr, unsigned long need));
-static unsigned long ecoff_padding_adjust PARAMS ((char **buf,
-                                                  char **bufend,
-                                                  unsigned long offset,
-                                                  char **bufptrptr));
-static unsigned long ecoff_build_lineno PARAMS ((char **buf, char **bufend,
-                                                unsigned long offset,
-                                                long *linecntptr));
-static unsigned long ecoff_build_symbols PARAMS ((char **buf, char **bufend,
-                                                 unsigned long offset,
-                                                 char **extbuf,
-                                                 char **extbufend,
-                                                 unsigned long *extoffset,
-                                                 varray_t *ext_strings,
-                                                 struct hash_control *));
-static unsigned long ecoff_build_procs PARAMS ((char **buf, char **bufend,
-                                               unsigned long offset));
-static unsigned long ecoff_build_aux PARAMS ((char **buf, char **bufend,
-                                             unsigned long offset));
-static unsigned long ecoff_build_strings PARAMS ((char **buf, char **bufend,
-                                                 unsigned long offset,
-                                                 varray_t *vp));
-static unsigned long ecoff_build_ss PARAMS ((char **buf, char **bufend,
-                                            unsigned long offset));
-static unsigned long ecoff_build_fdr PARAMS ((char **buf, char **bufend,
-                                             unsigned long offset));
-static page_t *allocate_cluster PARAMS ((unsigned long npages));
-static page_t *allocate_page PARAMS ((void));
-static scope_t *allocate_scope PARAMS ((void));
-static void free_scope PARAMS ((scope_t *ptr));
-static vlinks_t *allocate_vlinks PARAMS ((void));
-static shash_t *allocate_shash PARAMS ((void));
-static thash_t *allocate_thash PARAMS ((void));
-static tag_t *allocate_tag PARAMS ((void));
-static void free_tag PARAMS ((tag_t *ptr));
-static forward_t *allocate_forward PARAMS ((void));
-static thead_t *allocate_thead PARAMS ((void));
-static void free_thead PARAMS ((thead_t *ptr));
-static lineno_list_t *allocate_lineno_list PARAMS ((void));
-
-/* Why isn't this in some header file somewhere?  In fact, is it even
-   necessary?  */
-#define SKIP_WHITESPACES() \
-  do \
-    { \
-      while (*input_line_pointer == ' ' \
-            || *input_line_pointer == '\t') \
-       ++input_line_pointer; \
-    } \
-  while (0)
-\f
-/* These are the pseudo-ops we support in this file.  Only those
-   relating to debugging information are supported here.
-
-   The following pseudo-ops from the Kane and Heinrich MIPS book
-   should be defined here, but are currently unsupported: .aent,
-   .bgnb, .endb, .verstamp, .vreg.
-
-   The following pseudo-ops from the Kane and Heinrich MIPS book are
-   MIPS CPU specific, and should be defined by tc-mips.c: .alias,
-   .extern, .galive, .gjaldef, .gjrlive, .livereg, .noalias, .option,
-   .rdata, .sdata, .set.
-
-   The following pseudo-ops from the Kane and Heinrich MIPS book are
-   not MIPS CPU specific, but are also not ECOFF specific.  I have
-   only listed the ones which are not already in read.c.  It's not
-   completely clear where these should be defined, but tc-mips.c is
-   probably the most reasonable place: .asciiz, .asm0, .endr, .err,
-   .half, .lab, .repeat, .struct, .weakext.  */
-
-const pseudo_typeS obj_pseudo_table[] =
-{
-  /* COFF style debugging information. .ln is not used; .loc is used
-     instead.  */
-  { "def",     obj_ecoff_def,          0 },
-  { "dim",     obj_ecoff_dim,          0 },
-  { "endef",   obj_ecoff_endef,        0 },
-  { "file",    obj_ecoff_file,         0 },
-  { "scl",     obj_ecoff_scl,          0 },
-  { "size",    obj_ecoff_size,         0 },
-  { "tag",     obj_ecoff_tag,          0 },
-  { "type",    obj_ecoff_type,         0 },
-  { "val",     obj_ecoff_val,          0 },
-
-  /* ECOFF specific debugging information.  */
-  { "begin",   obj_ecoff_begin,        0 },
-  { "bend",    obj_ecoff_bend,         0 },
-  { "end",     obj_ecoff_end,          0 },
-  { "ent",     obj_ecoff_ent,          0 },
-  { "fmask",   obj_ecoff_fmask,        0 },
-  { "frame",   obj_ecoff_frame,        0 },
-  { "loc",     obj_ecoff_loc,          0 },
-  { "mask",    obj_ecoff_mask,         0 },
-
-  /* Sentinel.  */
-  { NULL }
-};
-\f
-/* This function is called when the assembler starts up.  */
-
-void
-obj_read_begin_hook ()
-{
-  tag_hash = hash_new ();
-  top_tag_head = allocate_thead ();
-  top_tag_head->first_tag = (tag_t *) NULL;
-  top_tag_head->free = (thead_t *) NULL;
-  top_tag_head->prev = cur_tag_head;
-  cur_tag_head = top_tag_head;
-}
-
-/* This function is called when a symbol is created.  */
-
-void
-obj_symbol_new_hook (symbolP)
-     symbolS *symbolP;
-{
-  if (cur_file_ptr == (efdr_t *) NULL)
-    add_file ((const char *) NULL, 0);
-  symbolP->ecoff_file = cur_file_ptr;
-  symbolP->ecoff_symbol = 0;
-  symbolP->ecoff_undefined = 0;
-}
-\f
-/* Add a page to a varray object.  */
-
-static void
-add_varray_page (vp)
-     varray_t *vp;                             /* varray to add page to */
-{
-  vlinks_t *new_links = allocate_vlinks ();
-
-#ifdef MALLOC_CHECK
-  if (vp->object_size > 1)
-    new_links->datum = (page_t *) xcalloc (1, vp->object_size);
-  else
-#endif
-    new_links->datum = allocate_page ();
-
-  alloc_counts[(int)alloc_type_varray].total_alloc++;
-  alloc_counts[(int)alloc_type_varray].total_pages++;
-
-  new_links->start_index = vp->num_allocated;
-  vp->objects_last_page = 0;
-
-  if (vp->first == (vlinks_t *) NULL)          /* first allocation? */
-    vp->first = vp->last = new_links;
-  else
-    {                                          /* 2nd or greater allocation */
-      new_links->prev = vp->last;
-      vp->last->next = new_links;
-      vp->last = new_links;
-    }
-}
-\f
-/* Add a string (and null pad) to one of the string tables.  */
-
-static symint_t
-add_string (vp, hash_tbl, str, ret_hash)
-     varray_t *vp;                     /* string obstack */
-     struct hash_control *hash_tbl;    /* ptr to hash table */
-     const char *str;                  /* string */
-     shash_t **ret_hash;               /* return hash pointer */
-{
-  register unsigned long len = strlen (str);
-  register shash_t *hash_ptr;
-
-  if (len >= PAGE_USIZE)
-    as_fatal ("String too big (%lu bytes)", len);
-
-  hash_ptr = (shash_t *) hash_find (hash_tbl, str);
-  if (hash_ptr == (shash_t *) NULL)
-    {
-      register const char *err;
-
-      if (vp->objects_last_page + len >= PAGE_USIZE)
-        {
-          vp->num_allocated =
-            ((vp->num_allocated + PAGE_USIZE - 1) / PAGE_USIZE) * PAGE_USIZE;
-          add_varray_page (vp);
-        }
-
-      hash_ptr = allocate_shash ();
-      hash_ptr->indx = vp->num_allocated;
-
-      hash_ptr->string = &vp->last->datum->byte[vp->objects_last_page];
-
-      vp->objects_last_page += len + 1;
-      vp->num_allocated += len + 1;
-
-      strcpy (hash_ptr->string, str);
-
-      err = hash_insert (hash_tbl, str, (char *) hash_ptr);
-      if (err)
-       as_fatal ("Inserting \"%s\" into string hash table: %s",
-                 str, err);
-    }
-
-  if (ret_hash != (shash_t **) NULL)
-    *ret_hash = hash_ptr;
-
-  return hash_ptr->indx;
-}
-\f
-/* Add debugging information for a symbol.  */
-
-static localsym_t *
-add_ecoff_symbol (str, type, storage, sym_value, value, indx)
-     const char *str;                  /* symbol name */
-     st_t type;                                /* symbol type */
-     sc_t storage;                     /* storage class */
-     symbolS *sym_value;               /* associated symbol.  */
-     symint_t value;                   /* value of symbol */
-     symint_t indx;                    /* index to local/aux. syms */
-{
-  localsym_t *psym;
-  register scope_t *pscope;
-  register thead_t *ptag_head;
-  register tag_t *ptag;
-  register tag_t *ptag_next;
-  register varray_t *vp;
-  register int scope_delta = 0;
-  shash_t *hash_ptr = (shash_t *) NULL;
-
-  if (cur_file_ptr == (efdr_t *) NULL)
-    as_fatal ("no current file pointer");
-
-  vp = &cur_file_ptr->symbols;
-
- if (vp->objects_last_page == vp->objects_per_page)
-    add_varray_page (vp);
-
-  psym = &vp->last->datum->sym[ vp->objects_last_page++ ];
-
-  if (str == (const char *) NULL && sym_value != (symbolS *) NULL)
-    psym->name = S_GET_NAME (sym_value);
-  else
-    psym->name = str;
-  psym->as_sym = sym_value;
-  if (sym_value != (symbolS *) NULL)
-    sym_value->ecoff_symbol = 1;
-  psym->file_ptr = cur_file_ptr;
-  psym->proc_ptr = cur_proc_ptr;
-  psym->begin_ptr = (localsym_t *) NULL;
-  psym->index_ptr = (aux_t *) NULL;
-  psym->forward_ref = (forward_t *) NULL;
-  psym->sym_index = -1;
-  psym->ecoff_sym.value = value;
-  psym->ecoff_sym.st = (unsigned) type;
-  psym->ecoff_sym.sc = (unsigned) storage;
-  psym->ecoff_sym.index = indx;
-
-  /* If there is an associated symbol, we wait until the end of the
-     assembly before deciding where to put the name (it may be just an
-     external symbol).  Otherwise, this is just a debugging symbol and
-     the name should go with the current file.  */
-  if (sym_value == (symbolS *) NULL)
-    psym->ecoff_sym.iss = ((str == (const char *) NULL)
-                          ? 0
-                          : add_string (&cur_file_ptr->strings,
-                                        cur_file_ptr->str_hash,
-                                        str,
-                                        &hash_ptr));
-
-  ++vp->num_allocated;
-
-  if (ECOFF_IS_STAB (&psym->ecoff_sym))
-    return psym;
-
-  /* Save the symbol within the hash table if this is a static
-     item, and it has a name.  */
-  if (hash_ptr != (shash_t *) NULL
-      && (type == st_Global || type == st_Static || type == st_Label
-         || type == st_Proc || type == st_StaticProc))
-    hash_ptr->sym_ptr = psym;
-
-  /* push or pop a scope if appropriate.  */
-  switch (type)
-    {
-    default:
-      break;
-
-    case st_File:                      /* beginning of file */
-    case st_Proc:                      /* procedure */
-    case st_StaticProc:                        /* static procedure */
-    case st_Block:                     /* begin scope */
-      pscope = allocate_scope ();
-      pscope->prev = cur_file_ptr->cur_scope;
-      pscope->lsym = psym;
-      pscope->type = type;
-      cur_file_ptr->cur_scope = pscope;
-
-      if (type != st_File)
-       scope_delta = 1;
-
-      /* For every block type except file, struct, union, or
-        enumeration blocks, push a level on the tag stack.  We omit
-        file types, so that tags can span file boundaries.  */
-      if (type != st_File && storage != sc_Info)
-       {
-         ptag_head = allocate_thead ();
-         ptag_head->first_tag = 0;
-         ptag_head->prev = cur_tag_head;
-         cur_tag_head = ptag_head;
-       }
-      break;
-
-    case st_End:
-      pscope = cur_file_ptr->cur_scope;
-      if (pscope == (scope_t *) NULL)
-       as_fatal ("too many st_End's");
-      else
-       {
-         st_t begin_type = (st_t) pscope->lsym->ecoff_sym.st;
-
-         psym->begin_ptr = pscope->lsym;
-
-         if (begin_type != st_File)
-           scope_delta = -1;
-
-         /* Except for file, structure, union, or enumeration end
-            blocks remove all tags created within this scope.  */
-         if (begin_type != st_File && storage != sc_Info)
-           {
-             ptag_head = cur_tag_head;
-             cur_tag_head = ptag_head->prev;
-
-             for (ptag = ptag_head->first_tag;
-                  ptag != (tag_t *) NULL;
-                  ptag = ptag_next)
-               {
-                 if (ptag->forward_ref != (forward_t *) NULL)
-                   add_unknown_tag (ptag);
-
-                 ptag_next = ptag->same_block;
-                 ptag->hash_ptr->tag_ptr = ptag->same_name;
-                 free_tag (ptag);
-               }
-
-             free_thead (ptag_head);
-           }
-
-         cur_file_ptr->cur_scope = pscope->prev;
-
-         /* block begin gets next sym #.  This is set when we know
-            the symbol index value.  */
-
-         /* Functions push two or more aux words as follows:
-            1st word: index+1 of the end symbol (filled in later).
-            2nd word: type of the function (plus any aux words needed).
-            Also, tie the external pointer back to the function begin symbol.  */
-         if (begin_type != st_File && begin_type != st_Block)
-           {
-             symint_t ty;
-             varray_t *svp = &cur_file_ptr->aux_syms;
-
-             pscope->lsym->ecoff_sym.index = add_aux_sym_symint (0);
-             pscope->lsym->index_ptr =
-               &svp->last->datum->aux[svp->objects_last_page - 1];
-             ty = add_aux_sym_tir (&last_func_type_info,
-                                   hash_no,
-                                   &cur_file_ptr->thash_head[0]);
-/*
-             if (last_func_sym_value != (symbolS *) NULL)
-               {
-                 last_func_sym_value->ifd = cur_file_ptr->file_index;
-                 last_func_sym_value->index = ty;
-               }
- */
-           }
-
-         free_scope (pscope);
-       }
-    }
-
-  cur_file_ptr->nested_scopes += scope_delta;
-
-#ifdef ECOFF_DEBUG
-  if (debug && type != st_File
-      && (debug > 2 || type == st_Block || type == st_End
-         || type == st_Proc || type == st_StaticProc))
-    {
-      char *sc_str = sc_to_string (storage);
-      char *st_str = st_to_string (type);
-      int depth = cur_file_ptr->nested_scopes + (scope_delta < 0);
-
-      fprintf (stderr,
-              "\tlsym\tv= %10ld, depth= %2d, sc= %-12s",
-              value, depth, sc_str);
-
-      if (str_start && str_end_p1 - str_start > 0)
-       fprintf (stderr, " st= %-11s name= %.*s\n", st_str, str_end_p1 - str_start, str_start);
-      else
-       {
-         unsigned long len = strlen (st_str);
-         fprintf (stderr, " st= %.*s\n", len-1, st_str);
-       }
-    }
-#endif
-
-  return psym;
-}
-\f
-/* Add an auxiliary symbol (passing a symint).  This is actually used
-   for integral aux types, not just symints.  */
-
-static symint_t
-add_aux_sym_symint (aux_word)
-     symint_t aux_word;                /* auxiliary information word */
-{
-  register varray_t *vp;
-  register aux_t *aux_ptr;
-
-  if (cur_file_ptr == (efdr_t *) NULL)
-    as_fatal ("no current file pointer");
-
-  vp = &cur_file_ptr->aux_syms;
-
-  if (vp->objects_last_page == vp->objects_per_page)
-    add_varray_page (vp);
-
-  aux_ptr = &vp->last->datum->aux[vp->objects_last_page++];
-  aux_ptr->type = aux_isym;
-  aux_ptr->data.isym = aux_word;
-
-  return vp->num_allocated++;
-}
-
-
-/* Add an auxiliary symbol (passing a file/symbol index combo).  */
-
-static symint_t
-add_aux_sym_rndx (file_index, sym_index)
-     int file_index;
-     symint_t sym_index;
-{
-  register varray_t *vp;
-  register aux_t *aux_ptr;
-
-  if (cur_file_ptr == (efdr_t *) NULL)
-    as_fatal ("no current file pointer");
-
-  vp = &cur_file_ptr->aux_syms;
-
-  if (vp->objects_last_page == vp->objects_per_page)
-    add_varray_page (vp);
-
-  aux_ptr = &vp->last->datum->aux[vp->objects_last_page++];
-  aux_ptr->type = aux_rndx;
-  aux_ptr->data.rndx.rfd   = file_index;
-  aux_ptr->data.rndx.index = sym_index;
-
-  return vp->num_allocated++;
-}
-\f
-/* Add an auxiliary symbol (passing the basic type and possibly
-   type qualifiers).  */
-
-static symint_t
-add_aux_sym_tir (t, state, hash_tbl)
-     type_info_t *t;           /* current type information */
-     hash_state_t state;       /* whether to hash type or not */
-     thash_t **hash_tbl;       /* pointer to hash table to use */
-{
-  register varray_t *vp;
-  register aux_t *aux_ptr;
-  static AUXU init_aux;
-  symint_t ret;
-  int i;
-  AUXU aux;
-
-  if (cur_file_ptr == (efdr_t *) NULL)
-    as_fatal ("no current file pointer");
-
-  vp = &cur_file_ptr->aux_syms;
-
-  aux = init_aux;
-  aux.ti.bt = (int) t->basic_type;
-  aux.ti.continued = 0;
-  aux.ti.fBitfield = t->bitfield;
-
-  aux.ti.tq0 = (int) t->type_qualifiers[0];
-  aux.ti.tq1 = (int) t->type_qualifiers[1];
-  aux.ti.tq2 = (int) t->type_qualifiers[2];
-  aux.ti.tq3 = (int) t->type_qualifiers[3];
-  aux.ti.tq4 = (int) t->type_qualifiers[4];
-  aux.ti.tq5 = (int) t->type_qualifiers[5];
-
-
-  /* For anything that adds additional information, we must not hash,
-     so check here, and reset our state. */
-
-  if (state != hash_no
-      && (t->type_qualifiers[0] == tq_Array
-         || t->type_qualifiers[1] == tq_Array
-         || t->type_qualifiers[2] == tq_Array
-         || t->type_qualifiers[3] == tq_Array
-         || t->type_qualifiers[4] == tq_Array
-         || t->type_qualifiers[5] == tq_Array
-         || t->basic_type == bt_Struct
-         || t->basic_type == bt_Union
-         || t->basic_type == bt_Enum
-         || t->bitfield
-         || t->num_dims > 0))
-    state = hash_no;
-
-  /* See if we can hash this type, and save some space, but some types
-     can't be hashed (because they contain arrays or continuations),
-     and others can be put into the hash list, but cannot use existing
-     types because other aux entries precede this one.  */
-
-  if (state != hash_no)
-    {
-      register thash_t *hash_ptr;
-      register symint_t hi;
-
-      hi = aux.isym & ((1 << HASHBITS) - 1);
-      hi %= THASH_SIZE;
-
-      for (hash_ptr = hash_tbl[hi];
-          hash_ptr != (thash_t *)0;
-          hash_ptr = hash_ptr->next)
-       {
-         if (aux.isym == hash_ptr->type.isym)
-           break;
-       }
-
-      if (hash_ptr != (thash_t *) NULL && state == hash_yes)
-       return hash_ptr->indx;
-
-      if (hash_ptr == (thash_t *) NULL)
-       {
-         hash_ptr = allocate_thash ();
-         hash_ptr->next = hash_tbl[hi];
-         hash_ptr->type = aux;
-         hash_ptr->indx = vp->num_allocated;
-         hash_tbl[hi] = hash_ptr;
-       }
-    }
-
-  /* Everything is set up, add the aux symbol. */
-  if (vp->objects_last_page == vp->objects_per_page)
-    add_varray_page (vp);
-
-  aux_ptr = &vp->last->datum->aux[ vp->objects_last_page++ ];
-  aux_ptr->type = aux_tir;
-  aux_ptr->data = aux;
-
-  ret = vp->num_allocated++;
-
-  /* Add bitfield length if it exists.
-     
-     NOTE:  Mips documentation claims bitfield goes at the end of the
-     AUX record, but the DECstation compiler emits it here.
-     (This would only make a difference for enum bitfields.)
-
-     Also note:  We use the last size given since gcc may emit 2
-     for an enum bitfield.  */
-
-  if (t->bitfield)
-    (void) add_aux_sym_symint ((symint_t)t->sizes[t->num_sizes-1]);
-
-
-  /* Add tag information if needed.  Structure, union, and enum
-     references add 2 aux symbols: a [file index, symbol index]
-     pointer to the structure type, and the current file index.  */
-
-  if (t->basic_type == bt_Struct
-      || t->basic_type == bt_Union
-      || t->basic_type == bt_Enum)
-    {
-      register symint_t file_index = t->tag_ptr->ifd;
-      register localsym_t *sym  = t->tag_ptr->sym;
-      register forward_t *forward_ref = allocate_forward ();
-
-      if (sym != (localsym_t *) NULL)
-       {
-         forward_ref->next = sym->forward_ref;
-         sym->forward_ref = forward_ref;
-       }
-      else
-       {
-         forward_ref->next = t->tag_ptr->forward_ref;
-         t->tag_ptr->forward_ref = forward_ref;
-       }
-
-      (void) add_aux_sym_rndx (ST_RFDESCAPE, indexNil);
-      forward_ref->index_ptr
-       = &vp->last->datum->aux[ vp->objects_last_page - 1];
-
-      (void) add_aux_sym_symint (file_index);
-      forward_ref->ifd_ptr
-       = &vp->last->datum->aux[ vp->objects_last_page - 1];
-    }
-
-  /* Add information about array bounds if they exist.  */
-  for (i = 0; i < t->num_dims; i++)
-    {
-      (void) add_aux_sym_rndx (ST_RFDESCAPE,
-                              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 (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 claims that the bitfield width goes here.
-     But it needs to be emitted earlier. */
-
-  return ret;
-}
-\f
-/* Add a tag to the tag table (unless it already exists).  */
-
-static tag_t *
-get_tag (tag, sym, basic_type)
-     const char *tag;                  /* tag name */
-     localsym_t *sym;                  /* tag start block */
-     bt_t basic_type;                  /* bt_Struct, bt_Union, or bt_Enum */
-{
-  shash_t *hash_ptr;
-  const char *err;
-  tag_t *tag_ptr;
-
-  if (cur_file_ptr == (efdr_t *) NULL)
-    as_fatal ("no current file pointer");
-
-  hash_ptr = (shash_t *) hash_find (tag_hash, tag);
-
-  if (hash_ptr != (shash_t *) NULL
-      && hash_ptr->tag_ptr != (tag_t *) NULL)
-  {
-    tag_ptr = hash_ptr->tag_ptr;
-    if (sym != (localsym_t *) NULL)
-      {
-       tag_ptr->basic_type = basic_type;
-       tag_ptr->ifd        = cur_file_ptr->file_index;
-       tag_ptr->sym        = sym;
-      }
-    return tag_ptr;
-  }
-
-  if (hash_ptr == (shash_t *) NULL)
-    {
-      char *perm;
-
-      perm = xmalloc ((unsigned long) (strlen (tag) + 1));
-      strcpy (perm, tag);
-      hash_ptr = allocate_shash ();
-      err = hash_insert (tag_hash, perm, (char *) hash_ptr);
-      if (err)
-       as_fatal ("Inserting \"%s\" into tag hash table: %s",
-                 tag, err);
-      hash_ptr->string = perm;
-    }
-
-  tag_ptr = allocate_tag ();
-  tag_ptr->forward_ref = (forward_t *) NULL;
-  tag_ptr->hash_ptr    = hash_ptr;
-  tag_ptr->same_name   = hash_ptr->tag_ptr;
-  tag_ptr->basic_type  = basic_type;
-  tag_ptr->sym         = sym;
-  tag_ptr->ifd         = ((sym == (localsym_t *) NULL)
-                          ? (symint_t) -1
-                          : cur_file_ptr->file_index);
-  tag_ptr->same_block  = cur_tag_head->first_tag;
-
-  cur_tag_head->first_tag = tag_ptr;
-  hash_ptr->tag_ptr      = tag_ptr;
-
-  return tag_ptr;
-}
-\f
-/* Add an unknown {struct, union, enum} tag.  */
-
-static void
-add_unknown_tag (ptag)
-     tag_t     *ptag;          /* pointer to tag information */
-{
-  shash_t *hash_ptr    = ptag->hash_ptr;
-  char *name           = hash_ptr->string;
-  localsym_t *sym;
-  forward_t **pf;
-
-#ifdef ECOFF_DEBUG
-  if (debug > 1)
-    {
-      char *agg_type   = "{unknown aggregate type}";
-      switch (ptag->basic_type)
-       {
-       case bt_Struct: agg_type = "struct";    break;
-       case bt_Union:  agg_type = "union";     break;
-       case bt_Enum:   agg_type = "enum";      break;
-       default:                                break;
-       }
-
-      fprintf (stderr, "unknown %s %.*s found\n", agg_type,
-              hash_ptr->len, name_start);
-    }
-#endif
-
-  sym = add_ecoff_symbol (name,
-                         st_Block,
-                         sc_Info,
-                         (symbolS *) NULL,
-                         (symint_t) 0,
-                         (symint_t) 0);
-
-  (void) add_ecoff_symbol (name,
-                          st_End,
-                          sc_Info,
-                          (symbolS *) NULL,
-                          (symint_t) 0,
-                          (symint_t) 0);
-
-  for (pf = &sym->forward_ref; *pf != (forward_t *) NULL; pf = &(*pf)->next)
-    ;
-  *pf = ptag->forward_ref;
-}
-\f
-/* Add a procedure to the current file's list of procedures, and record
-   this is the current procedure.  */
-
-static void
-add_procedure (func)
-     char *func;                       /* func name */
-{
-  register varray_t *vp;
-  register proc_t *new_proc_ptr;
-
-#ifdef ECOFF_DEBUG
-  if (debug)
-    fputc ('\n', stderr);
-#endif
-
-  if (cur_file_ptr == (efdr_t *) NULL)
-    as_fatal ("no current file pointer");
-
-  vp = &cur_file_ptr->procs;
-
-  if (vp->objects_last_page == vp->objects_per_page)
-    add_varray_page (vp);
-
-  cur_proc_ptr = new_proc_ptr = &vp->last->datum->proc[vp->objects_last_page++];
-
-  vp->num_allocated++;
-
-  new_proc_ptr->pdr.isym = -1;
-  new_proc_ptr->pdr.iline = -1;
-  new_proc_ptr->pdr.lnLow = -1;
-  new_proc_ptr->pdr.lnHigh = -1;
-
-  /* Push the start of the function.  */
-  new_proc_ptr->sym = add_ecoff_symbol ((const char *) NULL, st_Proc, sc_Text,
-                                       symbol_find_or_make (func),
-                                       (symint_t) 0, (symint_t) 0);
-
-  ++proc_cnt;
-
-  /* Fill in the linenos preceding the .ent, if any.  */
-  if (noproc_lineno != (lineno_list_t *) NULL)
-    {
-      lineno_list_t *l;
-
-      for (l = noproc_lineno; l != (lineno_list_t *) NULL; l = l->next)
-       l->proc = new_proc_ptr;
-      *last_lineno_ptr = noproc_lineno;
-      while (*last_lineno_ptr != NULL)
-       last_lineno_ptr = &(*last_lineno_ptr)->next;
-      noproc_lineno = (lineno_list_t *) NULL;
-    }
-}
-\f
-/* Add a new filename, and set up all of the file relative
-   virtual arrays (strings, symbols, aux syms, etc.).  Record
-   where the current file structure lives.  */
-
-static void
-add_file (file_name, indx)
-     const char *file_name;            /* file name */
-     int indx;
-{
-  register int first_ch;
-  register efdr_t *fil_ptr;
-
-#ifdef ECOFF_DEBUG
-  if (debug)
-    fprintf (stderr, "\tfile\t%.*s\n", len, file_start);
-#endif
-
-  /* If the file name is NULL, then no .file symbol appeared, and we
-     want to use the actual file name.  Unfortunately, we don't have a
-     clean way to access it.  */
-  if (file_name == (const char *) NULL)
-    {
-      extern char *logical_input_file;
-      extern char *physical_input_file;
-
-      if (first_file != (efdr_t *) NULL)
-       as_fatal ("fake .file after real one");
-      file_name = logical_input_file;
-      if (file_name == (const char *) NULL)
-       {
-         file_name = physical_input_file;
-         if (file_name == (const char *) NULL)
-           file_name = "UNKNOWN";
-       }
-    }
-
-#ifndef NO_LISTING
-  if (listing)
-    listing_source_file (file_name);
-#endif
-
-  /* If we're creating stabs, then we don't actually make a new FDR.
-     Instead, we just create a stabs symbol.  */
-  if (stabs_seen)
-    {
-      (void) add_ecoff_symbol (file_name, st_Nil, sc_Nil,
-                              symbol_new ("L0\001", now_seg,
-                                          (valueT) frag_now_fix (),
-                                          frag_now),
-                              0, ECOFF_MARK_STAB (N_SOL));
-      return;
-    }
-
-  first_ch = *file_name;
-
-  /* See if the file has already been created.  */
-  for (fil_ptr = first_file;
-       fil_ptr != (efdr_t *) NULL;
-       fil_ptr = fil_ptr->next_file)
-    {
-      if (first_ch == fil_ptr->name[0]
-         && strcmp (file_name, fil_ptr->name) == 0)
-       {
-         cur_file_ptr = fil_ptr;
-         break;
-       }
-    }
-
-  /* If this is a new file, create it. */
-  if (fil_ptr == (efdr_t *) NULL)
-    {
-      if (file_desc.objects_last_page == file_desc.objects_per_page)
-       add_varray_page (&file_desc);
-
-      fil_ptr = cur_file_ptr =
-       &file_desc.last->datum->file[file_desc.objects_last_page++];
-      *fil_ptr = init_file;
-
-      fil_ptr->file_index = indx;
-      ++file_desc.num_allocated;
-
-      /* Allocate the string hash table.  */
-      fil_ptr->str_hash = hash_new ();
-
-      /* Make sure 0 byte in string table is null  */
-      add_string (&fil_ptr->strings,
-                 fil_ptr->str_hash,
-                 "",
-                 (shash_t **)0);
-
-      if (strlen (file_name) > PAGE_USIZE - 2)
-       as_fatal ("Filename goes over one page boundary.");
-
-      /* Push the start of the filename. We assume that the filename
-         will be stored at string offset 1.  */
-      (void) add_ecoff_symbol (file_name, st_File, sc_Text,
-                              (symbolS *) NULL,
-                              (symint_t) 0, (symint_t) 0);
-      fil_ptr->fdr.rss = 1;
-      fil_ptr->name = &fil_ptr->strings.last->datum->byte[1];
-
-      /* Update the linked list of file descriptors.  */
-      *last_file_ptr = fil_ptr;
-      last_file_ptr = &fil_ptr->next_file;
-
-      /* Add void & int types to the file (void should be first to catch
-        errant 0's within the index fields).  */
-      fil_ptr->void_type = add_aux_sym_tir (&void_type_info,
-                                           hash_yes,
-                                           &cur_file_ptr->thash_head[0]);
-
-      fil_ptr->int_type = add_aux_sym_tir (&int_type_info,
-                                          hash_yes,
-                                          &cur_file_ptr->thash_head[0]);
-    }
-}
-\f
-#ifdef ECOFF_DEBUG
-
-/* Convert storage class to string.  */
-
-static char *
-sc_to_string(storage_class)
-     sc_t storage_class;
-{
-  switch(storage_class)
-    {
-    case sc_Nil:        return "Nil,";
-    case sc_Text:       return "Text,";
-    case sc_Data:       return "Data,";
-    case sc_Bss:        return "Bss,";
-    case sc_Register:   return "Register,";
-    case sc_Abs:        return "Abs,";
-    case sc_Undefined:  return "Undefined,";
-    case sc_CdbLocal:   return "CdbLocal,";
-    case sc_Bits:       return "Bits,";
-    case sc_CdbSystem:  return "CdbSystem,";
-    case sc_RegImage:   return "RegImage,";
-    case sc_Info:       return "Info,";
-    case sc_UserStruct:         return "UserStruct,";
-    case sc_SData:      return "SData,";
-    case sc_SBss:       return "SBss,";
-    case sc_RData:      return "RData,";
-    case sc_Var:        return "Var,";
-    case sc_Common:     return "Common,";
-    case sc_SCommon:    return "SCommon,";
-    case sc_VarRegister: return "VarRegister,";
-    case sc_Variant:    return "Variant,";
-    case sc_SUndefined:         return "SUndefined,";
-    case sc_Init:       return "Init,";
-    case sc_Max:        return "Max,";
-    }
-
-  return "???,";
-}
-
-#endif /* DEBUG */
-\f
-#ifdef ECOFF_DEBUG
-
-/* Convert symbol type to string.  */
-
-static char *
-st_to_string(symbol_type)
-     st_t symbol_type;
-{
-  switch(symbol_type)
-    {
-    case st_Nil:       return "Nil,";
-    case st_Global:    return "Global,";
-    case st_Static:    return "Static,";
-    case st_Param:     return "Param,";
-    case st_Local:     return "Local,";
-    case st_Label:     return "Label,";
-    case st_Proc:      return "Proc,";
-    case st_Block:     return "Block,";
-    case st_End:       return "End,";
-    case st_Member:    return "Member,";
-    case st_Typedef:   return "Typedef,";
-    case st_File:      return "File,";
-    case st_RegReloc:  return "RegReloc,";
-    case st_Forward:   return "Forward,";
-    case st_StaticProc:        return "StaticProc,";
-    case st_Constant:  return "Constant,";
-    case st_Str:       return "String,";
-    case st_Number:    return "Number,";
-    case st_Expr:      return "Expr,";
-    case st_Type:      return "Type,";
-    case st_Max:       return "Max,";
-    }
-
-  return "???,";
-}
-
-#endif /* DEBUG */
-\f
-/* Parse .begin directives which have a label as the first argument
-   which gives the location of the start of the block.  */
-
-static void
-obj_ecoff_begin (ignore)
-     int ignore;
-{
-  char *name;
-  char name_end;
-
-  if (cur_file_ptr == (efdr_t *) NULL)
-    {
-      as_warn (".begin directive without a preceding .file directive");
-      demand_empty_rest_of_line ();
-      return;
-    }
-
-  if (cur_proc_ptr == (proc_t *) NULL)
-    {
-      as_warn (".begin directive without a preceding .ent directive");
-      demand_empty_rest_of_line ();
-      return;
-    }
-  
-  name = input_line_pointer;
-  name_end = get_symbol_end ();
-
-  (void) add_ecoff_symbol ((const char *) NULL, st_Block, sc_Text,
-                          symbol_find_or_make (name),
-                          (symint_t) 0, (symint_t) 0);
-
-  *input_line_pointer = name_end;
-
-  /* The line number follows, but we don't use it.  */
-  (void) get_absolute_expression ();
-  demand_empty_rest_of_line ();
-}
-\f
-/* Parse .bend directives which have a label as the first argument
-   which gives the location of the end of the block.  */
-
-static void
-obj_ecoff_bend (ignore)
-     int ignore;
-{
-  char *name;
-  char name_end;
-  symbolS *endsym;
-
-  if (cur_file_ptr == (efdr_t *) NULL)
-    {
-      as_warn (".bend directive without a preceding .file directive");
-      demand_empty_rest_of_line ();
-      return;
-    }
-
-  if (cur_proc_ptr == (proc_t *) NULL)
-    {
-      as_warn (".bend directive without a preceding .ent directive");
-      demand_empty_rest_of_line ();
-      return;
-    }
-
-  name = input_line_pointer;
-  name_end = get_symbol_end ();
-
-  /* The value is the distance between the .bend directive and the
-     corresponding symbol.  We fill in the offset when we write out
-     the symbol.  */
-  endsym = symbol_find (name);
-  if (endsym == (symbolS *) NULL)
-    as_warn (".bend directive names unknown symbol");
-  else
-    (void) add_ecoff_symbol ((const char *) NULL, st_End, sc_Text, endsym,
-                            (symint_t) 0, (symint_t) 0);
-
-  *input_line_pointer = name_end;
-
-  /* The line number follows, but we don't use it.  */
-  (void) get_absolute_expression ();
-  demand_empty_rest_of_line ();
-}
-\f
-/* COFF debugging information is provided as a series of directives
-   (.def, .scl, etc.).  We build up information as we read the
-   directives in the following static variables, and file it away when
-   we reach the .endef directive.  */
-static char *coff_sym_name;
-static type_info_t coff_type;
-static sc_t coff_storage_class;
-static st_t coff_symbol_typ;
-static int coff_is_function;
-static char *coff_tag;
-static valueT coff_value;
-symbolS *coff_sym_value;
-static int coff_inside_enumeration;
-
-/* Handle a .def directive: start defining a symbol.  */
-
-static void
-obj_ecoff_def (ignore)
-     int ignore;
-{
-  char *name;
-  char name_end;
-
-  SKIP_WHITESPACES ();
-
-  name = input_line_pointer;
-  name_end = get_symbol_end ();
-
-  if (coff_sym_name != (char *) NULL)
-    as_warn (".def pseudo-op used inside of .def/.endef; ignored");
-  else if (*name == '\0')
-    as_warn ("Empty symbol name in .def; ignored");
-  else
-    {
-      if (coff_sym_name != (char *) NULL)
-       free (coff_sym_name);
-      if (coff_tag != (char *) NULL)
-       free (coff_tag);
-      coff_sym_name = (char *) xmalloc ((unsigned long) (strlen (name) + 1));
-      strcpy (coff_sym_name, name);
-      coff_type = type_info_init;
-      coff_storage_class = sc_Nil;
-      coff_symbol_typ = st_Nil;
-      coff_is_function = 0;
-      coff_tag = (char *) NULL;
-      coff_value = 0;
-      coff_sym_value = (symbolS *) NULL;
-    }
-
-  *input_line_pointer = name_end;
-
-  demand_empty_rest_of_line ();
-}
-
-/* Handle a .dim directive, used to give dimensions for an array.  The
-   arguments are comma separated numbers.  mips-tfile assumes that
-   there will not be more than 6 dimensions, and gdb won't read any
-   more than that anyhow, so I will also make that assumption.  */
-
-static void
-obj_ecoff_dim (ignore)
-     int ignore;
-{
-  int dimens[N_TQ];
-  int i;
-
-  if (coff_sym_name == (char *) NULL)
-    {
-      as_warn (".dim pseudo-op used outside of .def/.endef; ignored");
-      demand_empty_rest_of_line ();
-      return;
-    }
-
-  for (i = 0; i < N_TQ; i++)
-    {
-      SKIP_WHITESPACES ();
-      dimens[i] = get_absolute_expression ();
-      if (*input_line_pointer == ',')
-       ++input_line_pointer;
-      else
-       {
-         if (*input_line_pointer != '\n'
-             && *input_line_pointer != ';')
-           as_warn ("Badly formed .dim directive");
-         break;
-       }
-    }
-
-  if (i == N_TQ)
-    --i;
-
-  /* The dimensions are stored away in reverse order.  */
-  for (; i >= 0; i--)
-    {
-      if (coff_type.num_dims >= N_TQ)
-       {
-         as_warn ("Too many .dim entries");
-         break;
-       }
-      coff_type.dimensions[coff_type.num_dims] = dimens[i];
-      ++coff_type.num_dims;
-    }
-
-  demand_empty_rest_of_line ();
-}
-
-/* Handle a .scl directive, which sets the COFF storage class of the
-   symbol.  */
-
-static void
-obj_ecoff_scl (ignore)
-     int ignore;
-{
-  long val;
-
-  if (coff_sym_name == (char *) NULL)
-    {
-      as_warn (".scl pseudo-op used outside of .def/.endef; ignored");
-      demand_empty_rest_of_line ();
-      return;
-    }
-
-  val = get_absolute_expression ();
-
-  coff_symbol_typ = map_coff_sym_type[val];
-  coff_storage_class = map_coff_storage[val];
-
-  demand_empty_rest_of_line ();
-}
-
-/* Handle a .size directive.  For some reason mips-tfile.c thinks that
-   .size can have multiple arguments.  We humor it, although gcc will
-   never generate more than one argument.  */
-
-static void
-obj_ecoff_size (ignore)
-     int ignore;
-{
-  int sizes[N_TQ];
-  int i;
-
-  if (coff_sym_name == (char *) NULL)
-    {
-      as_warn (".size pseudo-op used outside of .def/.endef; ignored");
-      demand_empty_rest_of_line ();
-      return;
-    }
-
-  for (i = 0; i < N_TQ; i++)
-    {
-      SKIP_WHITESPACES ();
-      sizes[i] = get_absolute_expression ();
-      if (*input_line_pointer == ',')
-       ++input_line_pointer;
-      else
-       {
-         if (*input_line_pointer != '\n'
-             && *input_line_pointer != ';')
-           as_warn ("Badly formed .size directive");
-         break;
-       }
-    }
-
-  if (i == N_TQ)
-    --i;
-
-  /* The sizes are stored away in reverse order.  */
-  for (; i >= 0; i--)
-    {
-      if (coff_type.num_sizes >= N_TQ)
-       {
-         as_warn ("Too many .size entries");
-         break;
-       }
-      coff_type.sizes[coff_type.num_sizes] = sizes[i];
-      ++coff_type.num_sizes;
-    }
-
-  demand_empty_rest_of_line ();
-}
-
-/* Handle the .type directive, which gives the COFF type of the
-   symbol.  */
-
-static void
-obj_ecoff_type (ignore)
-     int ignore;
-{
-  long val;
-  tq_t *tq_ptr;
-  tq_t *tq_shft;
-
-  if (coff_sym_name == (char *) NULL)
-    {
-      as_warn (".type pseudo-op used outside of .def/.endef; ignored");
-      demand_empty_rest_of_line ();
-      return;
-    }
-
-  val = get_absolute_expression ();
-
-  coff_type.orig_type = BTYPE (val);
-  coff_type.basic_type = map_coff_types[coff_type.orig_type];
-
-  tq_ptr = &coff_type.type_qualifiers[N_TQ];
-  while (val &~ N_BTMASK)
-    {
-      if (tq_ptr == &coff_type.type_qualifiers[0])
-       {
-         as_warn ("Too derived values in .type argument");
-         break;
-       }
-      if (ISPTR (val))
-       *--tq_ptr = tq_Ptr;
-      else if (ISFCN (val))
-       *--tq_ptr = tq_Proc;
-      else if (ISARY (val))
-       *--tq_ptr = tq_Array;
-      else
-       as_fatal ("Unrecognized .type argument");
-
-      val = DECREF (val);
-    }
-
-  tq_shft = &coff_type.type_qualifiers[0];
-  while (tq_ptr != &coff_type.type_qualifiers[N_TQ])
-    *tq_shft++ = *tq_ptr++;
-
-  if (tq_shft != &coff_type.type_qualifiers[0] && tq_shft[-1] == tq_Proc)
-    {
-      /* 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
-        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.  */
-      coff_is_function = 1;
-      tq_shft[-1] = tq_Nil;
-    }
-
-  while (tq_shft != &coff_type.type_qualifiers[N_TQ])
-    *tq_shft++ = tq_Nil;
-
-  demand_empty_rest_of_line ();
-}
-
-/* Handle the .tag directive, which gives the name of a structure,
-   union or enum.  */
-
-static void
-obj_ecoff_tag (ignore)
-     int ignore;
-{
-  char *name;
-  char name_end;
-
-  if (coff_sym_name == (char *) NULL)
-    {
-      as_warn (".tag pseudo-op used outside of .def/.endef; ignored");
-      demand_empty_rest_of_line ();
-      return;
-    }
-
-  name = input_line_pointer;
-  name_end = get_symbol_end ();
-
-  coff_tag = (char *) xmalloc ((unsigned long) (strlen (name) + 1));
-  strcpy (coff_tag, name);
-
-  *input_line_pointer = name_end;
-
-  demand_empty_rest_of_line ();
-}
-
-/* Handle the .val directive, which gives the value of the symbol.  It
-   may be the name of a static or global symbol.  */
-
-static void
-obj_ecoff_val (ignore)
-     int ignore;
-{
-  if (coff_sym_name == (char *) NULL)
-    {
-      as_warn (".val pseudo-op used outside of .def/.endef; ignored");
-      demand_empty_rest_of_line ();
-      return;
-    }
-
-  if (! is_name_beginner ((unsigned char) *input_line_pointer))
-    coff_value = get_absolute_expression ();
-  else
-    {
-      char *name;
-      char name_end;
-
-      name = input_line_pointer;
-      name_end = get_symbol_end ();
-
-      if (strcmp (name, ".") == 0)
-       as_warn ("`.val .' not supported");
-      else
-       coff_sym_value = symbol_find_or_make (name);
-
-      *input_line_pointer = name_end;
-
-      /* FIXME: gcc can generate address expressions here in unusual
-        cases (search for "obscure" in sdbout.c), although this is
-        very unlikely for a MIPS chip.  */
-    }
-
-  demand_empty_rest_of_line ();
-}
-
-/* Handle the .endef directive, which terminates processing of COFF
-   debugging information for a symbol.  */
-
-static void
-obj_ecoff_endef (ignore)
-     int ignore;
-{
-  char *name;
-  symint_t indx;
-  localsym_t *sym;
-
-  demand_empty_rest_of_line ();
-
-  if (coff_sym_name == (char *) NULL)
-    {
-      as_warn (".endef pseudo-op used before .def; ignored");
-      return;
-    }
-
-  name = coff_sym_name;
-  coff_sym_name = (char *) NULL;
-
-  /* If the symbol is a static or external, we have already gotten the
-     appropriate type and class, so make sure we don't override those
-     values.  This is needed because there are some type and classes
-     that are not in COFF, such as short data, etc.  */
-  if (coff_sym_value != (symbolS *) NULL)
-    {
-      coff_symbol_typ = st_Nil;
-      coff_storage_class = sc_Nil;
-    }
-
-  coff_type.extra_sizes = coff_tag != (char *) NULL;
-  if (coff_type.num_dims > 0)
-    {
-      int diff = coff_type.num_dims - coff_type.num_sizes;
-      int i = coff_type.num_dims - 1;
-      int j;
-
-      if (coff_type.num_sizes != 1 || diff < 0)
-       {
-         as_warn ("Bad COFF debugging info");
-         return;
-       }
-
-      /* If this is an array, make sure the same number of dimensions
-        and sizes were passed, creating extra sizes for multiply
-        dimensioned arrays if not passed.  */
-      coff_type.extra_sizes = 0;
-      if (diff)
-       {
-         j = (sizeof (coff_type.sizes) / sizeof (coff_type.sizes[0])) - 1;
-         while (j >= 0)
-           {
-             coff_type.sizes[j] = (((j - diff) >= 0)
-                                   ? coff_type.sizes[j - diff]
-                                   : 0);
-             j--;
-           }
-
-         coff_type.num_sizes = i + 1;
-         for (i--; i >= 0; i--)
-           coff_type.sizes[i] = (coff_type.sizes[i + 1]
-                                 / coff_type.dimensions[i + 1]);
-       }
-    }
-  else if (coff_symbol_typ == st_Member
-          && coff_type.num_sizes - coff_type.extra_sizes == 1)
-    {
-      /* Is this a bitfield?  This is indicated by a structure memeber
-        having a size field that isn't an array.  */
-      coff_type.bitfield = 1;
-    }
-
-  /* Except for enumeration members & begin/ending of scopes, put the
-     type word in the aux. symbol table.  */
-  if (coff_symbol_typ == st_Block || coff_symbol_typ == st_End)
-    indx = 0;
-  else if (coff_inside_enumeration)
-    indx = cur_file_ptr->void_type;
-  else
-    {
-      if (coff_type.basic_type == bt_Struct
-         || coff_type.basic_type == bt_Union
-         || coff_type.basic_type == bt_Enum)
-       {
-         if (coff_tag == (char *) NULL)
-           {
-             as_warn ("No tag specified for %s", name);
-             return;
-           }
-
-         coff_type.tag_ptr = get_tag (coff_tag, (localsym_t *) NULL,
-                                      coff_type.basic_type);
-       }
-
-      if (coff_is_function)
-       {
-         last_func_type_info = coff_type;
-         last_func_sym_value = coff_sym_value;
-         return;
-       }
-
-      indx = add_aux_sym_tir (&coff_type,
-                             hash_yes,
-                             &cur_file_ptr->thash_head[0]);
-    }
-
-  /* Do any last minute adjustments that are necessary.  */
-  switch (coff_symbol_typ)
-    {
-    default:
-      break;
-
-      /* For the beginning of structs, unions, and enumerations, the
-        size info needs to be passed in the value field.  */
-    case st_Block:
-      if (coff_type.num_sizes - coff_type.num_dims - coff_type.extra_sizes
-         != 1)
-       {
-         as_warn ("Bad COFF debugging information");
-         return;
-       }
-      else
-       coff_value = coff_type.sizes[0];
-
-      coff_inside_enumeration = (coff_type.orig_type == T_ENUM);
-      break;
-
-      /* For the end of structs, unions, and enumerations, omit the
-        name which is always ".eos".  This needs to be done last, so
-        that any error reporting above gives the correct name.  */
-    case st_End:
-      free (name);
-      name = (char *) NULL;
-      coff_value = 0;
-      coff_inside_enumeration = 0;
-      break;
-
-      /* 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 distinguished by indx == indexNil.  For enumerations,
-        update the maximum enumeration value.  */
-    case st_Member:
-      if (! coff_type.bitfield && ! coff_inside_enumeration)
-       coff_value *= 8;
-
-      break;
-    }
-
-  /* Add the symbol.  */
-  sym = add_ecoff_symbol (name,
-                         coff_symbol_typ,
-                         coff_storage_class,
-                         coff_sym_value,
-                         (symint_t) coff_value,
-                         indx);
-
-  /* deal with struct, union, and enum tags.  */
-  if (coff_symbol_typ == st_Block)
-    {
-      /* Create or update the tag information.  */
-      tag_t *tag_ptr = get_tag (name,
-                               sym,
-                               coff_type.basic_type);
-      forward_t **pf;
-
-      /* Remember any forward references.  */
-      for (pf = &sym->forward_ref;
-          *pf != (forward_t *) NULL;
-          pf = &(*pf)->next)
-       ;
-      *pf = tag_ptr->forward_ref;
-      tag_ptr->forward_ref = (forward_t *) NULL;
-    }
-}
-\f
-/* Parse .end directives.  */
-
-static void
-obj_ecoff_end (ignore)
-     int ignore;
-{
-  char *name;
-  char name_end;
-  register int ch;
-  symbolS *ent;
-
-  if (cur_file_ptr == (efdr_t *) NULL)
-    {
-      as_warn (".end directive without a preceding .file directive");
-      demand_empty_rest_of_line ();
-      return;
-    }
-
-  if (cur_proc_ptr == (proc_t *) NULL)
-    {
-      as_warn (".end directive without a preceding .ent directive");
-      demand_empty_rest_of_line ();
-      return;
-    }
-
-  name = input_line_pointer;
-  name_end = get_symbol_end ();
-  
-  ch = *name;
-  if (! is_name_beginner (ch))
-    {
-      as_warn (".end directive has no name");
-      *input_line_pointer = name_end;
-      demand_empty_rest_of_line ();
-      return;
-    }
-
-  /* The value is the distance between the .end directive and the
-     corresponding symbol.  We create a fake symbol to hold the
-     current location, and put in the offset when we write out the
-     symbol.  */
-  ent = symbol_find (name);
-  if (ent == (symbolS *) NULL)
-    as_warn (".end directive names unknown symbol");
-  else
-    (void) add_ecoff_symbol ((const char *) NULL, st_End, sc_Text,
-                            symbol_new ("L0\001", now_seg,
-                                        (valueT) frag_now_fix (),
-                                        frag_now),
-                            (symint_t) 0, (symint_t) 0);
-
-  cur_proc_ptr = (proc_t *) NULL;
-
-  *input_line_pointer = name_end;
-  demand_empty_rest_of_line ();
-}
-\f
-/* Parse .ent directives.  */
-
-static void
-obj_ecoff_ent (ignore)
-     int ignore;
-{
-  char *name;
-  char name_end;
-  register int ch;
-
-  if (cur_file_ptr == (efdr_t *) NULL)
-    add_file ((const char *) NULL, 0);
-
-  if (cur_proc_ptr != (proc_t *) NULL)
-    {
-      as_warn ("second .ent directive found before .end directive");
-      demand_empty_rest_of_line ();
-      return;
-    }
-
-  name = input_line_pointer;
-  name_end = get_symbol_end ();
-
-  ch = *name;
-  if (! is_name_beginner (ch))
-    {
-      as_warn (".ent directive has no name");
-      *input_line_pointer = name_end;
-      demand_empty_rest_of_line ();
-      return;
-    }
-
-  add_procedure (name);
-
-  *input_line_pointer = name_end;
-  demand_empty_rest_of_line ();
-}
-\f
-/* Parse .file directives.  */
-
-static void
-obj_ecoff_file (ignore)
-     int ignore;
-{
-  int indx;
-  char *name;
-  int len;
-
-  if (cur_proc_ptr != (proc_t *) NULL)
-    {
-      as_warn ("No way to handle .file within .ent/.end section");
-      demand_empty_rest_of_line ();
-      return;
-    }
-
-  indx = (int) get_absolute_expression ();
-
-  /* FIXME: we don't have to save the name here.  */
-  name = demand_copy_C_string (&len);
-
-  add_file (name, indx - 1);
-
-  demand_empty_rest_of_line ();
-}
-\f
-/* Parse .fmask directives.  */
-
-static void
-obj_ecoff_fmask (ignore)
-     int ignore;
-{
-  long val;
-
-  if (cur_proc_ptr == (proc_t *) NULL)
-    {
-      as_warn (".fmask outside of .ent");
-      demand_empty_rest_of_line ();
-      return;
-    }
-
-  if (get_absolute_expression_and_terminator (&val) != ',')
-    {
-      as_warn ("Bad .fmask directive");
-      --input_line_pointer;
-      demand_empty_rest_of_line ();
-      return;
-    }
-
-  cur_proc_ptr->pdr.fregmask = val;
-  cur_proc_ptr->pdr.fregoffset = get_absolute_expression ();
-
-  demand_empty_rest_of_line ();
-}
-\f
-/* Parse .frame directives.  */
-
-static void
-obj_ecoff_frame (ignore)
-     int ignore;
-{
-  long val;
-
-  if (cur_proc_ptr == (proc_t *) NULL)
-    {
-      as_warn (".frame outside of .ent");
-      demand_empty_rest_of_line ();
-      return;
-    }
-
-  cur_proc_ptr->pdr.framereg = tc_get_register ();
-
-  SKIP_WHITESPACE ();
-  if (*input_line_pointer++ != ','
-      || get_absolute_expression_and_terminator (&val) != ',')
-    {
-      as_warn ("Bad .frame directive");
-      --input_line_pointer;
-      demand_empty_rest_of_line ();
-      return;
-    }
-
-  cur_proc_ptr->pdr.frameoffset = val;
-
-  cur_proc_ptr->pdr.pcreg = tc_get_register ();
-
-  demand_empty_rest_of_line ();
-}
-\f
-/* Parse .mask directives.  */
-
-static void
-obj_ecoff_mask (ignore)
-     int ignore;
-{
-  long val;
-
-  if (cur_proc_ptr == (proc_t *) NULL)
-    {
-      as_warn (".mask outside of .ent");
-      demand_empty_rest_of_line ();
-      return;
-    }
-
-  if (get_absolute_expression_and_terminator (&val) != ',')
-    {
-      as_warn ("Bad .mask directive");
-      --input_line_pointer;
-      demand_empty_rest_of_line ();
-      return;
-    }
-
-  cur_proc_ptr->pdr.regmask = val;
-  cur_proc_ptr->pdr.regoffset = get_absolute_expression ();
-
-  demand_empty_rest_of_line ();
-}
-\f
-/* Parse .loc directives.  */
-
-static void
-obj_ecoff_loc (ignore)
-     int ignore;
-{
-  lineno_list_t *list;
-  symint_t lineno;
-
-  if (cur_file_ptr == (efdr_t *) NULL)
-    {
-      as_warn (".loc before .file");
-      demand_empty_rest_of_line ();
-      return;
-    }
-
-  if (now_seg != text_section)
-    {
-      as_warn (".loc outside of .text");
-      demand_empty_rest_of_line ();
-      return;
-    }
-
-  /* Skip the file number.  */
-  SKIP_WHITESPACE ();
-  get_absolute_expression ();
-  SKIP_WHITESPACE ();
-
-  lineno = get_absolute_expression ();
-
-#ifndef NO_LISTING
-  if (listing)
-    listing_source_line (lineno);
-#endif
-
-  /* If we're building stabs, then output a special label rather than
-     ECOFF line number info.  */
-  if (stabs_seen)
-    {
-      (void) add_ecoff_symbol ((char *) NULL, st_Label, sc_Text,
-                              symbol_new ("L0\001", now_seg,
-                                          (valueT) frag_now_fix (),
-                                          frag_now),
-                              0, lineno);
-      return;
-    }
-
-  list = allocate_lineno_list ();
-
-  list->next = (lineno_list_t *) NULL;
-  list->file = cur_file_ptr;
-  list->proc = cur_proc_ptr;
-  list->frag = frag_now;
-  list->paddr = frag_now_fix ();
-  list->lineno = lineno;
-
-  /* A .loc directive will sometimes appear before a .ent directive,
-     which means that cur_proc_ptr will be NULL here.  Arrange to
-     patch this up.  */
-  if (cur_proc_ptr == (proc_t *) NULL)
-    {
-      lineno_list_t **pl;
-
-      pl = &noproc_lineno;
-      while (*pl != (lineno_list_t *) NULL)
-       pl = &(*pl)->next;
-      *pl = list;
-    }
-  else
-    {
-      *last_lineno_ptr = list;
-      last_lineno_ptr = &list->next;
-    }
-}
-\f
-/* Make sure the @stabs symbol is emitted.  */
-
-static void
-mark_stabs (ignore)
-     int ignore;
-{
-  if (! stabs_seen)
-    {
-      /* Add a dummy @stabs dymbol. */
-      stabs_seen = 1;
-      (void) add_ecoff_symbol (stabs_symbol, stNil, scInfo,
-                              (symbolS *) NULL,
-                              (symint_t) -1, ECOFF_MARK_STAB (0));
-    }
-}
-\f
-/* Handle .stabs directives.  The actual parsing routine is done by a
-   generic routine.  This routine is called via OBJ_PROCESS_STAB.
-   When this is called, input_line_pointer will be pointing at the
-   value field of the stab.
-
-   .stabs directives have five fields:
-       "string"        a string, encoding the type information.
-       code            a numeric code, defined in <stab.h>
-       0               a zero
-       desc            a zero or line number
-       value           a numeric value or an address.
-
-    If the value is relocatable, we transform this into:
-       iss             points as an index into string space
-       value           value from lookup of the name
-       st              st from lookup of the name
-       sc              sc from lookup of the name
-       index           code|CODE_MASK
-
-    If the value is not relocatable, we transform this into:
-       iss             points as an index into string space
-       value           value
-       st              st_Nil
-       sc              sc_Nil
-       index           code|CODE_MASK
-
-    .stabn directives have four fields (string is null):
-       code            a numeric code, defined in <stab.h>
-       0               a zero
-       desc            a zero or a line number
-       value           a numeric value or an address.  */
-
-void
-ecoff_stab (what, string, type, other, desc)
-     int what;
-     const char *string;
-     int type;
-     int other;
-     int desc;
-{
-  efdr_t *save_file_ptr = cur_file_ptr;
-  symbolS *sym;
-  symint_t value;
-  st_t st;
-  sc_t sc;
-  symint_t indx;
-
-  /* We don't handle .stabd.  */
-  if (what != 's' && what != 'n')
-    {
-      as_bad (".stab%c is not supported", what);
-      return;
-    }
-
-  /* A .stabn uses a null name, not an empty string.  */
-  if (what == 'n')
-    string = NULL;
-
-  /* We ignore the other field.  */
-  if (other != 0)
-    as_warn (".stab%c: ignoring non-zero other field", what);
-
-  /* Make sure we have a current file.  */
-  if (cur_file_ptr == (efdr_t *) NULL)
-    {
-      add_file ((const char *) NULL, 0);
-      save_file_ptr = cur_file_ptr;
-    }
-
-  /* For stabs in ECOFF, the first symbol must be @stabs.  This is a
-     signal to gdb.  */
-  if (stabs_seen == 0)
-    mark_stabs (0);
-
-  /* Line number stabs are handled differently, since they have two
-     values, the line number and the address of the label.  We use the
-     index field (aka desc) to hold the line number, and the value
-     field to hold the address.  The symbol type is st_Label, which
-     should be different from the other stabs, so that gdb can
-     recognize it.  */
-  if (type == N_SLINE)
-    {
-      SYMR dummy_symr;
-      char *name;
-      char name_end;
-
-#ifndef NO_LISTING
-      if (listing)
-       listing_source_line ((unsigned int) desc);
-#endif
-
-      dummy_symr.index = desc;
-      if (dummy_symr.index != desc)
-       {
-         as_warn ("Line number (%d) for .stab%c directive cannot fit in index field (20 bits)",
-                  desc, what);
-         return;
-       }
-
-      name = input_line_pointer;
-      name_end = get_symbol_end ();
-
-      sym = symbol_find_or_make (name);
-      *input_line_pointer = name_end;
-
-      value = 0;
-      st = st_Label;
-      sc = sc_Text;
-      indx = desc;
-    }
-  else
-    {
-#ifndef NO_LISTING
-      if (listing && (type == N_SO || type == N_SOL))
-       listing_source_file (string);
-#endif
-      
-      if (isdigit (*input_line_pointer)
-         || *input_line_pointer == '-'
-         || *input_line_pointer == '+')
-       {
-         st = st_Nil;
-         sc = sc_Nil;
-         sym = (symbolS *) NULL;
-         value = get_absolute_expression ();
-       }
-      else if (! is_name_beginner ((unsigned char) *input_line_pointer))
-       {
-         as_warn ("Illegal .stab%c directive, bad character", what);
-         return;
-       }
-      else
-       {
-         char *name;
-         char name_end;
-
-         name = input_line_pointer;
-         name_end = get_symbol_end ();
-
-         sym = symbol_find_or_make (name);
-
-         sc = sc_Nil;
-         st = st_Nil;
-         value = 0;
-
-         *input_line_pointer = name_end;
-         if (name_end == '+' || name_end == '-')
-           {
-             ++input_line_pointer;
-             value = get_absolute_expression ();
-             if (name_end == '-')
-               value = - value;
-           }
-       }
-
-      indx = ECOFF_MARK_STAB (type);
-    }
-
-  (void) add_ecoff_symbol (string, st, sc, sym, value, indx);
-
-  /* Restore normal file type.  */
-  cur_file_ptr = save_file_ptr;
-}
-\f
-/* Add bytes to the symbolic information buffer.  */
-
-static char *
-ecoff_add_bytes (buf, bufend, bufptr, need)
-     char **buf;
-     char **bufend;
-     char *bufptr;
-     unsigned long need;
-{
-  unsigned long at;
-  unsigned long want;
-
-  at = bufptr - *buf;
-  need -= *bufend - bufptr;
-  if (need < PAGE_SIZE)
-    need = PAGE_SIZE;
-  want = (*bufend - *buf) + need;
-  *buf = xrealloc (*buf, want);
-  *bufend = *buf + want;
-  return *buf + at;
-}
-
-/* Adjust the symbolic information buffer to the alignment required
-   for the ECOFF target debugging information.  */
-
-static unsigned long
-ecoff_padding_adjust (buf, bufend, offset, bufptrptr)
-     char **buf;
-     char **bufend;
-     unsigned long offset;
-     char **bufptrptr;
-{
-  bfd_size_type align;
-
-  align = ecoff_backend (stdoutput)->debug_align;
-  if ((offset & (align - 1)) != 0)
-    {
-      unsigned long add;
-
-      add = align - (offset & (align - 1));
-      if (*bufend - (*buf + offset) < add)
-       (void) ecoff_add_bytes (buf, bufend, *buf + offset, add);
-      memset (*buf + offset, 0, add);
-      offset += add;
-      if (bufptrptr != (char **) NULL)
-       *bufptrptr = *buf + offset;
-    }
-
-  return offset;
-}
-
-/* Build the line number information.  */
-
-static unsigned long
-ecoff_build_lineno (buf, bufend, offset, linecntptr)
-     char **buf;
-     char **bufend;
-     unsigned long offset;
-     long *linecntptr;
-{
-  char *bufptr;
-  register lineno_list_t *l;
-  lineno_list_t *last;
-  efdr_t *file;
-  proc_t *proc;
-  unsigned long c;
-  long iline;
-  long totcount;
-
-  if (linecntptr != (long *) NULL)
-    *linecntptr = 0;
-
-  bufptr = *buf + offset;
-
-  file = (efdr_t *) NULL;
-  proc = (proc_t *) NULL;
-  last = (lineno_list_t *) NULL;
-  c = offset;
-  iline = 0;
-  totcount = 0;
-  for (l = first_lineno; l != (lineno_list_t *) NULL; l = l->next)
-    {
-      long count;
-      long delta;
-
-      /* Get the offset to the memory address of the next line number
-        (in words).  Do this first, so that we can skip ahead to the
-        next useful line number entry.  */
-      if (l->next == (lineno_list_t *) NULL)
-       count = 0;
-      else
-       {
-         count = ((l->next->frag->fr_address + l->next->paddr
-                   - (l->frag->fr_address + l->paddr))
-                  >> 2);
-         if (count <= 0)
-           {
-             /* Don't change last, so we still get the right delta.  */
-             continue;
-           }
-       }
-
-      if (l->file != file || l->proc != proc)
-       {
-         if (l->proc != proc && proc != (proc_t *) NULL)
-           proc->pdr.lnHigh = last->lineno;
-         if (l->file != file && file != (efdr_t *) NULL)
-           {
-             file->fdr.cbLine = c - file->fdr.cbLineOffset;
-             /* The cline field is ill-documented.  This is a guess
-                at the right value.  */
-             file->fdr.cline = totcount + count;
-             if (linecntptr != (long *) NULL)
-               *linecntptr += totcount + count;
-             totcount = 0;
-           }
-
-         if (l->file != file)
-           {
-             file = l->file;
-             file->fdr.ilineBase = iline;
-             file->fdr.cbLineOffset = c;
-           }
-         if (l->proc != proc)
-           {
-             proc = l->proc;
-             if (proc != (proc_t *) NULL)
-               {
-                 proc->pdr.lnLow = l->lineno;
-                 proc->pdr.cbLineOffset = c - file->fdr.cbLineOffset;
-                 /* The iline field is ill-documented.  This is a
-                    guess at the right value.  */
-                 proc->pdr.iline = totcount;
-               }
-           }
-
-         last = (lineno_list_t *) NULL;
-       }      
-
-      totcount += count;
-
-      /* Get the offset to this line number.  */
-      if (last == (lineno_list_t *) NULL)
-       delta = 0;
-      else
-       delta = l->lineno - last->lineno;
-
-      /* Put in the offset to this line number.  */
-      while (delta != 0)
-       {
-         int setcount;
-
-         /* 1 is added to each count read.  */
-         --count;
-         /* We can only adjust the word count by up to 15 words at a
-            time.  */
-         if (count <= 0x0f)
-           {
-             setcount = count;
-             count = 0;
-           }
-         else
-           {
-             setcount = 0x0f;
-             count -= 0x0f;
-           }
-         if (delta >= -7 && delta <= 7)
-           {
-             if (bufptr >= *bufend)
-               bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 1);
-             *bufptr++ = setcount + (delta << 4);
-             delta = 0;
-             ++c;
-           }
-         else
-           {
-             int set;
-
-             if (*bufend - bufptr < 3)
-               bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 3);
-             *bufptr++ = setcount + (8 << 4);
-             if (delta < -0x8000)
-               {
-                 set = -0x8000;
-                 delta += 0x8000;
-               }
-             else if (delta > 0x7fff)
-               {
-                 set = 0x7fff;
-                 delta -= 0x7fff;
-               }
-             else
-               {
-                 set = delta;
-                 delta = 0;
-               }
-             *bufptr++ = set >> 8;
-             *bufptr++ = set & 0xffff;
-             c += 3;
-           }
-       }
-
-      /* Finish adjusting the count.  */
-      while (count > 0)
-       {
-         if (bufptr >= *bufend)
-           bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 1);
-         /* 1 is added to each count read.  */
-         --count;
-         if (count > 0x0f)
-           {
-             *bufptr++ = 0x0f;
-             count -= 0x0f;
-           }
-         else
-           {
-             *bufptr++ = count;
-             count = 0;
-           }
-         ++c;
-       }
-
-      ++iline;
-      last = l;
-    }
-
-  if (proc != (proc_t *) NULL)
-    proc->pdr.lnHigh = last->lineno;
-  if (file != (efdr_t *) NULL)
-    {
-      file->fdr.cbLine = c - file->fdr.cbLineOffset;
-      file->fdr.cline = totcount;
-    }
-
-  if (linecntptr != (long *) NULL)
-    *linecntptr += totcount;
-
-  c = ecoff_padding_adjust (buf, bufend, c, &bufptr);
-
-  return c;
-}
-
-/* Build and swap out the symbols.  */
-
-static unsigned long
-ecoff_build_symbols (buf,
-                    bufend,
-                    offset,
-                    extbuf,
-                    extbufend,
-                    extoffset,
-                    ext_strings,
-                    ext_str_hash)
-     char **buf;
-     char **bufend;
-     unsigned long offset;
-     char **extbuf;
-     char **extbufend;
-     unsigned long *extoffset;
-     varray_t *ext_strings;
-     struct hash_control *ext_str_hash;
-{
-  const bfd_size_type external_sym_size =
-    ecoff_backend (stdoutput)->external_sym_size;
-  const bfd_size_type external_ext_size =
-    ecoff_backend (stdoutput)->external_ext_size;
-  void (* const swap_sym_out) PARAMS ((bfd *, const SYMR *, PTR))
-    = ecoff_backend (stdoutput)->swap_sym_out;
-  void (* const swap_ext_out) PARAMS ((bfd *, const EXTR *, PTR))
-    = ecoff_backend (stdoutput)->swap_ext_out;
-  char *sym_out;
-  char *ext_out;
-  long isym;
-  long iext;
-  vlinks_t *file_link;
-
-  sym_out = *buf + offset;
-  ext_out = *extbuf + *extoffset;
-
-  isym = 0;
-  iext = 0;
-
-  /* The symbols are stored by file.  */
-  for (file_link = file_desc.first;
-       file_link != (vlinks_t *) NULL;
-       file_link = file_link->next)
-    {
-      int ifilesym;
-      int fil_cnt;
-      efdr_t *fil_ptr;
-      efdr_t *fil_end;
-
-      if (file_link->next == (vlinks_t *) NULL)
-       fil_cnt = file_desc.objects_last_page;
-      else
-       fil_cnt = file_desc.objects_per_page;
-      fil_ptr = file_link->datum->file;
-      fil_end = fil_ptr + fil_cnt;
-      for (; fil_ptr < fil_end; fil_ptr++)
-       {
-         vlinks_t *sym_link;
-
-         fil_ptr->fdr.isymBase = isym;
-         ifilesym = isym;
-         for (sym_link = fil_ptr->symbols.first;
-              sym_link != (vlinks_t *) NULL;
-              sym_link = sym_link->next)
-           {
-             int sym_cnt;
-             localsym_t *sym_ptr;
-             localsym_t *sym_end;
-
-             if (sym_link->next == (vlinks_t *) NULL)
-               sym_cnt = fil_ptr->symbols.objects_last_page;
-             else
-               sym_cnt = fil_ptr->symbols.objects_per_page;
-             sym_ptr = sym_link->datum->sym;
-             sym_end = sym_ptr + sym_cnt;
-             for (; sym_ptr < sym_end; sym_ptr++)
-               {
-                 int local;
-                 symbolS *as_sym;
-                 forward_t *f;
-
-                 know (sym_ptr->file_ptr == fil_ptr);
-
-                 /* If there is no associated gas symbol, then this
-                    is a pure debugging symbol.  We have already
-                    added the name (if any) to fil_ptr->strings.
-                    Otherwise we must decide whether this is an
-                    external or a local symbol (actually, it may be
-                    both if the local provides additional debugging
-                    information for the external).  */
-                 local = 1;
-                 as_sym = sym_ptr->as_sym;
-                 if (as_sym != (symbolS *) NULL)
-                   {
-                     symint_t indx;
-
-                     /* The value of a block start symbol is the
-                        offset from the start of the procedure.  For
-                        other symbols we just use the gas value (but
-                        we must offset it by the vma of the section,
-                        just as BFD does, because BFD will not see
-                        this value).  */
-                     if (sym_ptr->ecoff_sym.st == (int) st_Block
-                         && sym_ptr->ecoff_sym.sc == (int) sc_Text)
-                       {
-                         symbolS *begin_sym;
-
-                         know (sym_ptr->proc_ptr != (proc_t *) NULL);
-                         begin_sym = sym_ptr->proc_ptr->sym->as_sym;
-                         if (S_GET_SEGMENT (as_sym)
-                             != S_GET_SEGMENT (begin_sym))
-                           as_warn (".begin/.bend in different segments");
-                         sym_ptr->ecoff_sym.value =
-                           S_GET_VALUE (as_sym) - S_GET_VALUE (begin_sym);
-                       }
-                     else
-                       sym_ptr->ecoff_sym.value =
-                         (S_GET_VALUE (as_sym)
-                          + bfd_get_section_vma (stdoutput,
-                                                 S_GET_SEGMENT (as_sym)));
-
-                     /* Set st_Proc to st_StaticProc for local
-                        functions.  */
-                     if (sym_ptr->ecoff_sym.st == st_Proc
-                         && S_IS_DEFINED (as_sym)
-                         && ! S_IS_EXTERNAL (as_sym))
-                       sym_ptr->ecoff_sym.st = st_StaticProc;
-
-                     /* Get the type and storage class based on where
-                        the symbol actually wound up.  Traditionally,
-                        N_LBRAC and N_RBRAC are *not* relocated. */
-                     indx = sym_ptr->ecoff_sym.index;
-                     if (sym_ptr->ecoff_sym.st == st_Nil
-                         && sym_ptr->ecoff_sym.sc == sc_Nil
-                         && (! ECOFF_IS_STAB (&sym_ptr->ecoff_sym)
-                             || ((ECOFF_UNMARK_STAB (indx) != N_LBRAC)
-                                 && (ECOFF_UNMARK_STAB (indx) != N_RBRAC))))
-                       {
-                         segT seg;
-                         const char *segname;
-                         st_t st;
-                         sc_t sc;
-
-                         seg = S_GET_SEGMENT (as_sym);
-                         segname = segment_name (seg);
-
-                         if (S_IS_EXTERNAL (as_sym)
-                             || ! S_IS_DEFINED (as_sym))
-                           st = st_Global;
-                         else if (seg == text_section)
-                           st = st_Label;
-                         else
-                           st = st_Static;
-
-                         if (! S_IS_DEFINED (as_sym)
-                             || as_sym->ecoff_undefined)
-                           {
-                             if (S_GET_VALUE (as_sym) > 0
-                                 && (S_GET_VALUE (as_sym)
-                                     <= bfd_get_gp_size (stdoutput)))
-                               sc = sc_SUndefined;
-                             else
-                               sc = sc_Undefined;
-                           }
-                         else if (S_IS_COMMON (as_sym))
-                           {
-                             if (S_GET_VALUE (as_sym) > 0
-                                 && (S_GET_VALUE (as_sym)
-                                     <= bfd_get_gp_size (stdoutput)))
-                               sc = sc_SCommon;
-                             else
-                               sc = sc_Common;
-                           }
-                         else if (seg == text_section)
-                           sc = sc_Text;
-                         else if (seg == data_section)
-                           sc = sc_Data;
-                         else if (strcmp (segname, ".rdata") == 0)
-                           sc = sc_RData;
-                         else if (strcmp (segname, ".sdata") == 0)
-                           sc = sc_SData;
-                         else if (seg == bss_section)
-                           sc = sc_Bss;
-                         else if (strcmp (segname, ".sbss") == 0)
-                           sc = sc_SBss;
-                         else if (seg == &bfd_abs_section)
-                           sc = sc_Abs;
-                         else
-                           abort ();
-
-                         sym_ptr->ecoff_sym.st = (int) st;
-                         sym_ptr->ecoff_sym.sc = (int) sc;
-                       }
-
-                     /* This is just an external symbol if it is
-                        outside a procedure and it has a type.
-                        FIXME: g++ will generate symbols which have
-                        different names in the debugging information
-                        than the actual symbol.  Should we handle
-                        them here?  */
-                     if ((S_IS_EXTERNAL (as_sym)
-                          || ! S_IS_DEFINED (as_sym))
-                         && sym_ptr->proc_ptr == (proc_t *) NULL
-                         && sym_ptr->ecoff_sym.st != (int) st_Nil
-                         && ! ECOFF_IS_STAB (&sym_ptr->ecoff_sym))
-                       local = 0;
-
-                     /* If an st_end symbol has an associated gas
-                        symbol, then it is a local label created for
-                        a .bend or .end directive.  Stabs line
-                        numbers will have \001 in the names.  */
-                     if (local
-                         && sym_ptr->ecoff_sym.st != st_End
-                         && strchr (sym_ptr->name, '\001') == 0)
-                       sym_ptr->ecoff_sym.iss =
-                         add_string (&fil_ptr->strings,
-                                     fil_ptr->str_hash,
-                                     sym_ptr->name,
-                                     (shash_t **) NULL);
-                   }
-
-                 /* We now know the index of this symbol; fill in
-                    locations that have been waiting for that
-                    information.  */
-                 if (sym_ptr->begin_ptr != (localsym_t *) NULL)
-                   {
-                     localsym_t *begin_ptr;
-                     st_t begin_type;
-
-                     know (local);
-                     begin_ptr = sym_ptr->begin_ptr;
-                     know (begin_ptr->sym_index != -1);
-                     sym_ptr->ecoff_sym.index = begin_ptr->sym_index;
-                     if (sym_ptr->ecoff_sym.sc != (int) sc_Info)
-                       sym_ptr->ecoff_sym.iss = begin_ptr->ecoff_sym.iss;
-
-                     begin_type = begin_ptr->ecoff_sym.st;
-                     if (begin_type == st_File
-                         || begin_type == st_Block)
-                       {
-                         begin_ptr->ecoff_sym.index = isym - ifilesym + 1;
-                         (*swap_sym_out) (stdoutput,
-                                          &begin_ptr->ecoff_sym,
-                                          (*buf
-                                           + offset
-                                           + (begin_ptr->sym_index
-                                              * external_sym_size)));
-                       }
-                     else
-                       {
-                         know (begin_ptr->index_ptr != (aux_t *) NULL);
-                         begin_ptr->index_ptr->data.isym =
-                           isym - ifilesym + 1;
-                       }
-
-                     /* The value of the symbol marking the end of a
-                        procedure is the size of the procedure.  The
-                        value of the symbol marking the end of a
-                        block is the offset from the start of the
-                        procedure to the block.  */
-                     if (begin_type == st_Proc)
-                       {
-                         know (as_sym != (symbolS *) NULL);
-                         know (begin_ptr->as_sym != (symbolS *) NULL);
-                         if (S_GET_SEGMENT (as_sym)
-                             != S_GET_SEGMENT (begin_ptr->as_sym))
-                           as_warn (".begin/.bend in different segments");
-                         sym_ptr->ecoff_sym.value =
-                           (S_GET_VALUE (as_sym)
-                            - S_GET_VALUE (begin_ptr->as_sym));
-                       }
-                     else if (begin_type == st_Block
-                              && sym_ptr->ecoff_sym.sc != (int) sc_Info)
-                       {
-                         symbolS *begin_sym;
-
-                         know (as_sym != (symbolS *) NULL);
-                         know (sym_ptr->proc_ptr != (proc_t *) NULL);
-                         begin_sym = sym_ptr->proc_ptr->sym->as_sym;
-                         if (S_GET_SEGMENT (as_sym)
-                             != S_GET_SEGMENT (begin_sym))
-                           as_warn (".begin/.bend in different segments");
-                         sym_ptr->ecoff_sym.value =
-                           S_GET_VALUE (as_sym) - S_GET_VALUE (begin_sym);
-                       }
-                   }
-
-                 for (f = sym_ptr->forward_ref;
-                      f != (forward_t *) NULL;
-                      f = f->next)
-                   {
-                     know (local);
-                     f->ifd_ptr->data.isym = fil_ptr->file_index;
-                     f->index_ptr->data.rndx.index = isym - ifilesym;
-                   }
-
-                 if (local)
-                   {
-                     if (*bufend - sym_out < external_sym_size)
-                       sym_out = ecoff_add_bytes (buf, bufend,
-                                                  sym_out,
-                                                  external_sym_size);
-                     (*swap_sym_out) (stdoutput, &sym_ptr->ecoff_sym,
-                                      sym_out);
-                     sym_out += external_sym_size;
-
-                     sym_ptr->sym_index = isym;
-
-                     if (sym_ptr->proc_ptr != (proc_t *) NULL
-                         && sym_ptr->proc_ptr->sym == sym_ptr)
-                       sym_ptr->proc_ptr->pdr.isym = isym - ifilesym;
-
-                     ++isym;
-                   }
-
-                 /* If this is an external symbol, swap it out.  */
-                 if (as_sym != (symbolS *) NULL
-                     && (S_IS_EXTERNAL (as_sym)
-                         || ! S_IS_DEFINED (as_sym))
-                     && ! ECOFF_IS_STAB (&sym_ptr->ecoff_sym))
-                   {
-                     EXTR ext;
-
-                     memset (&ext, 0, sizeof ext);
-                     ext.asym = sym_ptr->ecoff_sym;
-                     if (sym_ptr->ecoff_sym.st == st_Proc
-                         || sym_ptr->ecoff_sym.st == st_StaticProc)
-                       {
-                         know (local);
-                         ext.asym.index = isym - ifilesym - 1;
-                       }
-                     ext.ifd = fil_ptr->file_index;
-                     ext.asym.iss = add_string (ext_strings,
-                                                ext_str_hash,
-                                                S_GET_NAME (as_sym),
-                                                (shash_t **) NULL);
-                     if (*extbufend - ext_out < external_ext_size)
-                       ext_out = ecoff_add_bytes (extbuf, extbufend,
-                                                  ext_out,
-                                                  external_ext_size);
-                     (*swap_ext_out) (stdoutput, &ext, ext_out);
-                     ecoff_set_sym_index (as_sym->bsym, iext);
-                     ext_out += external_ext_size;
-                     ++iext;
-                   }
-               }
-           }
-         fil_ptr->fdr.csym = isym - fil_ptr->fdr.isymBase;
-       }
-    }
-
-  *extoffset += iext * external_ext_size;
-  return offset + isym * external_sym_size;
-}
-
-/* Swap out the procedure information.  */
-
-static unsigned long
-ecoff_build_procs (buf, bufend, offset)
-     char **buf;
-     char **bufend;
-     unsigned long offset;
-{
-  const bfd_size_type external_pdr_size
-    = ecoff_backend (stdoutput)->external_pdr_size;
-  void (* const swap_pdr_out) PARAMS ((bfd *, const PDR *, PTR))
-    = ecoff_backend (stdoutput)->swap_pdr_out;
-  char *pdr_out;
-  int first_fil;
-  long iproc;
-  vlinks_t *file_link;
-
-  pdr_out = *buf + offset;
-  
-  first_fil = 1;
-  iproc = 0;
-
-  /* The procedures are stored by file.  */
-  for (file_link = file_desc.first;
-       file_link != (vlinks_t *) NULL;
-       file_link = file_link->next)
-    {
-      int fil_cnt;
-      efdr_t *fil_ptr;
-      efdr_t *fil_end;
-
-      if (file_link->next == (vlinks_t *) NULL)
-       fil_cnt = file_desc.objects_last_page;
-      else
-       fil_cnt = file_desc.objects_per_page;
-      fil_ptr = file_link->datum->file;
-      fil_end = fil_ptr + fil_cnt;
-      for (; fil_ptr < fil_end; fil_ptr++)
-       {
-         vlinks_t *proc_link;
-         int first;
-
-         fil_ptr->fdr.ipdFirst = iproc;
-         first = 1;
-         for (proc_link = fil_ptr->procs.first;
-              proc_link != (vlinks_t *) NULL;
-              proc_link = proc_link->next)
-           {
-             int prc_cnt;
-             proc_t *proc_ptr;
-             proc_t *proc_end;
-
-             if (proc_link->next == (vlinks_t *) NULL)
-               prc_cnt = fil_ptr->procs.objects_last_page;
-             else
-               prc_cnt = fil_ptr->procs.objects_per_page;
-             proc_ptr = proc_link->datum->proc;
-             proc_end = proc_ptr + prc_cnt;
-             for (; proc_ptr < proc_end; proc_ptr++)
-               {
-                 symbolS *adr_sym;
-                 unsigned long adr;
-
-                 adr_sym = proc_ptr->sym->as_sym;
-                 adr = (S_GET_VALUE (adr_sym)
-                        + bfd_get_section_vma (stdoutput,
-                                               S_GET_SEGMENT (adr_sym)));
-                 if (first)
-                   {
-                     if (first_fil)
-                       first_fil = 0;
-                     else
-                       fil_ptr->fdr.adr = adr;
-                     first = 0;
-                   }
-                 proc_ptr->pdr.adr = adr - fil_ptr->fdr.adr;
-                 if (*bufend - pdr_out < external_pdr_size)
-                   pdr_out = ecoff_add_bytes (buf, bufend,
-                                              pdr_out,
-                                              external_pdr_size);
-                 (*swap_pdr_out) (stdoutput, &proc_ptr->pdr, pdr_out);
-                 pdr_out += external_pdr_size;
-                 ++iproc;
-               }
-           }
-         fil_ptr->fdr.cpd = iproc - fil_ptr->fdr.ipdFirst;
-       }
-    }
-
-  return offset + iproc * external_pdr_size;
-}
-
-/* Swap out the aux information.  */
-
-static unsigned long
-ecoff_build_aux (buf, bufend, offset)
-     char **buf;
-     char **bufend;
-     unsigned long offset;
-{
-  int bigendian;
-  union aux_ext *aux_out;
-  long iaux;
-  vlinks_t *file_link;
-
-  bigendian = stdoutput->xvec->header_byteorder_big_p;
-
-  aux_out = (union aux_ext *) (*buf + offset);
-  
-  iaux = 0;
-
-  /* The aux entries are stored by file.  */
-  for (file_link = file_desc.first;
-       file_link != (vlinks_t *) NULL;
-       file_link = file_link->next)
-    {
-      int fil_cnt;
-      efdr_t *fil_ptr;
-      efdr_t *fil_end;
-
-      if (file_link->next == (vlinks_t *) NULL)
-       fil_cnt = file_desc.objects_last_page;
-      else
-       fil_cnt = file_desc.objects_per_page;
-      fil_ptr = file_link->datum->file;
-      fil_end = fil_ptr + fil_cnt;
-      for (; fil_ptr < fil_end; fil_ptr++)
-       {
-         vlinks_t *aux_link;
-
-         fil_ptr->fdr.fBigendian = bigendian;
-         fil_ptr->fdr.iauxBase = iaux;
-         for (aux_link = fil_ptr->aux_syms.first;
-              aux_link != (vlinks_t *) NULL;
-              aux_link = aux_link->next)
-           {
-             int aux_cnt;
-             aux_t *aux_ptr;
-             aux_t *aux_end;
-
-             if (aux_link->next == (vlinks_t *) NULL)
-               aux_cnt = fil_ptr->aux_syms.objects_last_page;
-             else
-               aux_cnt = fil_ptr->aux_syms.objects_per_page;
-             aux_ptr = aux_link->datum->aux;
-             aux_end = aux_ptr + aux_cnt;
-             for (; aux_ptr < aux_end; aux_ptr++)
-               {
-                 if (*bufend - (char *) aux_out < sizeof (union aux_ext))
-                   aux_out = ((union aux_ext *)
-                              ecoff_add_bytes (buf, bufend,
-                                               (char *) aux_out,
-                                               sizeof (union aux_ext)));
-                 switch (aux_ptr->type)
-                   {
-                   case aux_tir:
-                     ecoff_swap_tir_out (bigendian, &aux_ptr->data.ti,
-                                         &aux_out->a_ti);
-                     break;
-                   case aux_rndx:
-                     ecoff_swap_rndx_out (bigendian, &aux_ptr->data.rndx,
-                                          &aux_out->a_rndx);
-                     break;
-                   case aux_dnLow:
-                     AUX_PUT_DNLOW (bigendian, aux_ptr->data.dnLow,
-                                    aux_out);
-                     break;
-                   case aux_dnHigh:
-                     AUX_PUT_DNHIGH (bigendian, aux_ptr->data.dnHigh,
-                                     aux_out);
-                     break;
-                   case aux_isym:
-                     AUX_PUT_ISYM (bigendian, aux_ptr->data.isym,
-                                   aux_out);
-                     break;
-                   case aux_iss:
-                     AUX_PUT_ISS (bigendian, aux_ptr->data.iss,
-                                  aux_out);
-                     break;
-                   case aux_width:
-                     AUX_PUT_WIDTH (bigendian, aux_ptr->data.width,
-                                    aux_out);
-                     break;
-                   case aux_count:
-                     AUX_PUT_COUNT (bigendian, aux_ptr->data.count,
-                                    aux_out);
-                     break;
-                   }
-
-                 ++aux_out;
-                 ++iaux;
-               }
-           }
-         fil_ptr->fdr.caux = iaux - fil_ptr->fdr.iauxBase;
-       }
-    }
-
-  return offset + iaux * sizeof (union aux_ext);
-}
-
-/* Copy out the strings from a varray_t.  This returns the number of
-   bytes copied, rather than the new offset.  */
-
-static unsigned long
-ecoff_build_strings (buf, bufend, offset, vp)
-     char **buf;
-     char **bufend;
-     unsigned long offset;
-     varray_t *vp;
-{
-  unsigned long istr;
-  char *str_out;
-  vlinks_t *str_link;
-
-  str_out = *buf + offset;
-
-  istr = 0;
-
-  for (str_link = vp->first;
-       str_link != (vlinks_t *) NULL;
-       str_link = str_link->next)
-    {
-      unsigned long str_cnt;
-
-      if (str_link->next == (vlinks_t *) NULL)
-       str_cnt = vp->objects_last_page;
-      else
-       str_cnt = vp->objects_per_page;
-
-      if (*bufend - str_out < str_cnt)
-       str_out = ecoff_add_bytes (buf, bufend, str_out, str_cnt);
-
-      memcpy (str_out, str_link->datum->byte, str_cnt);
-      str_out += str_cnt;
-      istr += str_cnt;
-    }
-
-  return istr;
-}
-
-/* Dump out the local strings.  */
-
-static unsigned long
-ecoff_build_ss (buf, bufend, offset)
-     char **buf;
-     char **bufend;
-     unsigned long offset;
-{
-  long iss;
-  vlinks_t *file_link;
-
-  iss = 0;
-
-  for (file_link = file_desc.first;
-       file_link != (vlinks_t *) NULL;
-       file_link = file_link->next)
-    {
-      int fil_cnt;
-      efdr_t *fil_ptr;
-      efdr_t *fil_end;
-
-      if (file_link->next == (vlinks_t *) NULL)
-       fil_cnt = file_desc.objects_last_page;
-      else
-       fil_cnt = file_desc.objects_per_page;
-      fil_ptr = file_link->datum->file;
-      fil_end = fil_ptr + fil_cnt;
-      for (; fil_ptr < fil_end; fil_ptr++)
-       {
-         long ss_cnt;
+/* These are the pseudo-ops we support in this file.  Only those
+   relating to debugging information are supported here.
 
-         fil_ptr->fdr.issBase = iss;
-         ss_cnt = ecoff_build_strings (buf, bufend, offset + iss,
-                                       &fil_ptr->strings);
-         fil_ptr->fdr.cbSs = ss_cnt;
-         iss += ss_cnt;
-       }
-    }
+   The following pseudo-ops from the Kane and Heinrich MIPS book
+   should be defined here, but are currently unsupported: .aent,
+   .bgnb, .endb, .verstamp, .vreg.
 
-  return ecoff_padding_adjust (buf, bufend, offset + iss, (char **) NULL);
-}
+   The following pseudo-ops from the Kane and Heinrich MIPS book are
+   MIPS CPU specific, and should be defined by tc-mips.c: .alias,
+   .extern, .galive, .gjaldef, .gjrlive, .livereg, .noalias, .option,
+   .rdata, .sdata, .set.
 
-/* Swap out the file descriptors.  */
+   The following pseudo-ops from the Kane and Heinrich MIPS book are
+   not MIPS CPU specific, but are also not ECOFF specific.  I have
+   only listed the ones which are not already in read.c.  It's not
+   completely clear where these should be defined, but tc-mips.c is
+   probably the most reasonable place: .asciiz, .asm0, .endr, .err,
+   .half, .lab, .repeat, .struct, .weakext.  */
 
-static unsigned long
-ecoff_build_fdr (buf, bufend, offset)
-     char **buf;
-     char **bufend;
-     unsigned long offset;
+const pseudo_typeS obj_pseudo_table[] =
 {
-  const bfd_size_type external_fdr_size
-    = ecoff_backend (stdoutput)->external_fdr_size;
-  void (* const swap_fdr_out) PARAMS ((bfd *, const FDR *, PTR))
-    = ecoff_backend (stdoutput)->swap_fdr_out;
-  long ifile;
-  char *fdr_out;
-  vlinks_t *file_link;
-
-  ifile = 0;
-
-  fdr_out = *buf + offset;
-
-  for (file_link = file_desc.first;
-       file_link != (vlinks_t *) NULL;
-       file_link = file_link->next)
-    {
-      int fil_cnt;
-      efdr_t *fil_ptr;
-      efdr_t *fil_end;
+  /* COFF style debugging information. .ln is not used; .loc is used
+     instead.  */
+  { "def",     ecoff_directive_def,    0 },
+  { "dim",     ecoff_directive_dim,    0 },
+  { "endef",   ecoff_directive_endef,  0 },
+  { "file",    ecoff_directive_file,   0 },
+  { "scl",     ecoff_directive_scl,    0 },
+  { "size",    ecoff_directive_size,   0 },
+  { "tag",     ecoff_directive_tag,    0 },
+  { "type",    ecoff_directive_type,   0 },
+  { "val",     ecoff_directive_val,    0 },
 
-      if (file_link->next == (vlinks_t *) NULL)
-       fil_cnt = file_desc.objects_last_page;
-      else
-       fil_cnt = file_desc.objects_per_page;
-      fil_ptr = file_link->datum->file;
-      fil_end = fil_ptr + fil_cnt;
-      for (; fil_ptr < fil_end; fil_ptr++)
-       {
-         if (*bufend - fdr_out < external_fdr_size)
-           fdr_out = ecoff_add_bytes (buf, bufend, fdr_out,
-                                      external_fdr_size);
-         (*swap_fdr_out) (stdoutput, &fil_ptr->fdr, fdr_out);
-         fdr_out += external_fdr_size;
-         ++ifile;
-       }
-    }
+  /* ECOFF specific debugging information.  */
+  { "begin",   ecoff_directive_begin,  0 },
+  { "bend",    ecoff_directive_bend,   0 },
+  { "end",     ecoff_directive_end,    0 },
+  { "ent",     ecoff_directive_ent,    0 },
+  { "fmask",   ecoff_directive_fmask,  0 },
+  { "frame",   ecoff_directive_frame,  0 },
+  { "loc",     ecoff_directive_loc,    0 },
+  { "mask",    ecoff_directive_mask,   0 },
+
+  /* These are used on Irix.  I don't know how to implement them.  */
+  { "bgnb",    s_ignore,               0 },
+  { "endb",    s_ignore,               0 },
+  { "verstamp",        s_ignore,               0 },
 
-  return offset + ifile * external_fdr_size;
-}
+  /* Sentinel.  */
+  { NULL }
+};
 
 /* Swap out the symbols and debugging information for BFD.  */
 
 void
 ecoff_frob_file ()
 {
-  const struct ecoff_backend_data * const backend = ecoff_backend (stdoutput);
-  const bfd_size_type external_pdr_size = backend->external_pdr_size;
-  tag_t *ptag;
-  tag_t *ptag_next;
-  efdr_t *fil_ptr;
-  int end_warning;
-  efdr_t *hold_file_ptr;
-  proc_t * hold_proc_ptr;
+  const struct ecoff_debug_swap * const debug_swap
+    = &ecoff_backend (stdoutput)->debug_swap;
   bfd_vma addr;
   asection *sec;
-  symbolS *sym;
   HDRR *hdr;
   char *buf;
-  char *bufend;
-  unsigned long offset;
-  char *extbuf;
-  char *extbufend;
-  unsigned long extoffset;
-  varray_t ext_strings;
-  static varray_t init_ext_strings = INIT_VARRAY (char);
-  struct hash_control *ext_str_hash;
   char *set;
 
-  /* Make sure we have a file.  */
-  if (first_file == (efdr_t *) NULL)
-    add_file ((const char *) NULL, 0);
-
-  /* Handle any top level tags.  */
-  for (ptag = top_tag_head->first_tag;
-       ptag != (tag_t *) NULL;
-       ptag = ptag_next)
-    {
-      if (ptag->forward_ref != (forward_t *) NULL)
-       add_unknown_tag (ptag);
-
-      ptag_next = ptag->same_block;
-      ptag->hash_ptr->tag_ptr = ptag->same_name;
-      free_tag (ptag);
-    }
-
-  free_thead (top_tag_head);
-
-  /* Output an ending symbol for all the files.  We have to do this
-     here for the last file, so we may as well do it for all of the
-     files.  */
-  end_warning = 0;
-  for (fil_ptr = first_file;
-       fil_ptr != (efdr_t *) NULL;
-       fil_ptr = fil_ptr->next_file)
-    {
-      cur_file_ptr = fil_ptr;
-      while (cur_file_ptr->cur_scope->prev != (scope_t *) NULL)
-       {
-         cur_file_ptr->cur_scope = cur_file_ptr->cur_scope->prev;
-         if (! end_warning)
-           {
-             as_warn ("Missing .end or .bend at end of file");
-             end_warning = 1;
-           }
-       }
-      (void) add_ecoff_symbol ((const char *) NULL,
-                              st_End, sc_Text,
-                              (symbolS *) NULL,
-                              (symint_t) 0,
-                              (symint_t) 0);
-    }
-
   /* Set the section VMA values.  */
   addr = 0;
   for (sec = stdoutput->sections; sec != (asection *) NULL; sec = sec->next)
@@ -4482,126 +101,32 @@ ecoff_frob_file ()
       addr += bfd_section_size (stdoutput, sec);
     }
 
-  /* Look through the symbols.  Add debugging information for each
-     symbol that has not already received it.  */
-  hold_file_ptr = cur_file_ptr;
-  hold_proc_ptr = cur_proc_ptr;
-  cur_proc_ptr = (proc_t *) NULL;
-  for (sym = symbol_rootP; sym != (symbolS *) NULL; sym = symbol_next (sym))
-    {
-      if (sym->ecoff_symbol
-         || sym->ecoff_file == (efdr_t *) NULL
-         || (sym->bsym->flags & BSF_SECTION_SYM) != 0)
-       continue;
-
-      cur_file_ptr = sym->ecoff_file;
-      add_ecoff_symbol ((const char *) NULL, st_Nil, sc_Nil, sym,
-                       S_GET_VALUE (sym), indexNil);
-    }
-  cur_proc_ptr = hold_proc_ptr;
-  cur_file_ptr = hold_file_ptr;
-
-  /* Build the symbolic information.  */
-  hdr = &ecoff_data (stdoutput)->symbolic_header;
-  offset = 0;
-  buf = xmalloc (PAGE_SIZE);
-  bufend = buf + PAGE_SIZE;
-
-  /* Build the line number information.  */
-  hdr->cbLineOffset = offset;
-  offset = ecoff_build_lineno (&buf, &bufend, offset, &hdr->ilineMax);
-  hdr->cbLine = offset - hdr->cbLineOffset;
-
-  /* We don't use dense numbers at all.  */
-  hdr->idnMax = 0;
-  hdr->cbDnOffset = 0;
-
-  /* We can't build the PDR table until we have built the symbols,
-     because a PDR contains a symbol index.  However, we set aside
-     space at this point.  */
-  hdr->ipdMax = proc_cnt;
-  hdr->cbPdOffset = offset;
-  if (bufend - (buf + offset) < proc_cnt * external_pdr_size)
-    (void) ecoff_add_bytes (&buf, &bufend, buf + offset,
-                           proc_cnt * external_pdr_size);
-  offset += proc_cnt * external_pdr_size;
-
-  /* Build the symbols.  It's convenient to build both the local and
-     external symbols at the same time.  We can put the local symbols
-     directly into the buffer, but we have to hold the external
-     symbols apart until we know where they are going to go.  */
-  extbuf = xmalloc (PAGE_SIZE);
-  extbufend = extbuf + PAGE_SIZE;
-  extoffset = 0;
-  ext_strings = init_ext_strings;
-  ext_str_hash = hash_new ();
-  hdr->cbSymOffset = offset;
-  offset = ecoff_build_symbols (&buf, &bufend, offset,
-                               &extbuf, &extbufend, &extoffset,
-                               &ext_strings, ext_str_hash);
-  hdr->isymMax = (offset - hdr->cbSymOffset) / backend->external_sym_size;
-
-  /* Building the symbols initializes the symbol index in the PDR's.
-     Now we can swap out the PDR's.  */
-  (void) ecoff_build_procs (&buf, &bufend, hdr->cbPdOffset);
-
-  /* We don't use optimization symbols.  */
-  hdr->ioptMax = 0;
-  hdr->cbOptOffset = 0;
-
-  /* Swap out the auxiliary type information.  */
-  hdr->cbAuxOffset = offset;
-  offset = ecoff_build_aux (&buf, &bufend, offset);
-  hdr->iauxMax = (offset - hdr->cbAuxOffset) / sizeof (union aux_ext);
+  /* Build the ECOFF debugging information.  */
+  hdr = &ecoff_data (stdoutput)->debug_info.symbolic_header;
+  ecoff_build_debug (hdr, &buf, debug_swap);
 
-  /* Copy out the local strings.  */
-  hdr->cbSsOffset = offset;
-  offset = ecoff_build_ss (&buf, &bufend, offset);
-  hdr->issMax = offset - hdr->cbSsOffset;
-
-  /* Copy out the external strings.  */
-  hdr->cbSsExtOffset = offset;
-  offset += ecoff_build_strings (&buf, &bufend, offset, &ext_strings);
-  offset = ecoff_padding_adjust (&buf, &bufend, offset, (char **) NULL);
-  hdr->issExtMax = offset - hdr->cbSsExtOffset;
-
-  /* We don't use relative file descriptors.  */
-  hdr->crfd = 0;
-  hdr->cbRfdOffset = 0;
-
-  /* Swap out the file descriptors.  */
-  hdr->cbFdOffset = offset;
-  offset = ecoff_build_fdr (&buf, &bufend, offset);
-  hdr->ifdMax = (offset - hdr->cbFdOffset) / backend->external_fdr_size;
-
-  /* Copy out the external symbols.  */
-  hdr->cbExtOffset = offset;
-  if (bufend - (buf + offset) < extoffset)
-    (void) ecoff_add_bytes (&buf, &bufend, buf + offset, extoffset);
-  memcpy (buf + offset, extbuf, extoffset);
-  offset += extoffset;
-  hdr->iextMax = (offset - hdr->cbExtOffset) / backend->external_ext_size;
-
-  know ((offset & (backend->debug_align - 1)) == 0);
-
-  /* That completes the symbolic debugging information.  We must now
-     finish up the symbolic header and the ecoff_tdata structure.  */
+  /* Finish up the ecoff_tdata structure.  */
   set = buf;
 #define SET(ptr, count, type, size) \
-  ecoff_data (stdoutput)->ptr = (type) set; \
-  set += hdr->count * size
+  if (hdr->count == 0) \
+    ecoff_data (stdoutput)->debug_info.ptr = (type) NULL; \
+  else \
+    { \
+      ecoff_data (stdoutput)->debug_info.ptr = (type) set; \
+      set += hdr->count * size; \
+    }
 
   SET (line, cbLine, unsigned char *, sizeof (unsigned char));
-  SET (external_dnr, idnMax, PTR, backend->external_dnr_size);
-  SET (external_pdr, ipdMax, PTR, backend->external_pdr_size);
-  SET (external_sym, isymMax, PTR, backend->external_sym_size);
-  SET (external_opt, ioptMax, PTR, backend->external_opt_size);
+  SET (external_dnr, idnMax, PTR, debug_swap->external_dnr_size);
+  SET (external_pdr, ipdMax, PTR, debug_swap->external_pdr_size);
+  SET (external_sym, isymMax, PTR, debug_swap->external_sym_size);
+  SET (external_opt, ioptMax, PTR, debug_swap->external_opt_size);
   SET (external_aux, iauxMax, union aux_ext *, sizeof (union aux_ext));
   SET (ss, issMax, char *, sizeof (char));
   SET (ssext, issExtMax, char *, sizeof (char));
-  SET (external_rfd, crfd, PTR, backend->external_rfd_size);
-  SET (external_fdr, ifdMax, PTR, backend->external_fdr_size);
-  SET (external_ext, iextMax, PTR, backend->external_ext_size);
+  SET (external_rfd, crfd, PTR, debug_swap->external_rfd_size);
+  SET (external_fdr, ifdMax, PTR, debug_swap->external_fdr_size);
+  SET (external_ext, iextMax, PTR, debug_swap->external_ext_size);
 
 #undef SET
 
@@ -4632,401 +157,26 @@ ecoff_frob_file ()
       as_fatal ("Can't write REGINFO section");
   }
 
-  ecoff_data (stdoutput)->raw_size = offset;
-  ecoff_data (stdoutput)->raw_syments = buf;
-
-  hdr->magic = magicSym;
-  /* FIXME: what should hdr->vstamp be?  */
-
   bfd_set_symtab (stdoutput, bfd_get_outsymbols (stdoutput),
                  (unsigned int) (hdr->isymMax + hdr->iextMax));
 }
-\f
-/* Allocate a cluster of pages.  */
-
-#ifndef MALLOC_CHECK
-
-static page_t *
-allocate_cluster (npages)
-     unsigned long npages;
-{
-  register page_t *value = (page_t *) xmalloc (npages * PAGE_USIZE);
-
-#ifdef ECOFF_DEBUG
-  if (debug > 3)
-    fprintf (stderr, "\talloc\tnpages = %d, value = 0x%.8x\n", npages, value);
-#endif
-
-  memset (value, 0, npages * PAGE_USIZE);
-
-  return value;
-}
-
-
-static page_t *cluster_ptr = NULL;
-static unsigned long pages_left = 0;
-
-#endif /* MALLOC_CHECK */
-
-/* Allocate one page (which is initialized to 0).  */
-
-static page_t *
-allocate_page ()
-{
-#ifndef MALLOC_CHECK
-
-  if (pages_left == 0)
-    {
-      pages_left = MAX_CLUSTER_PAGES;
-      cluster_ptr = allocate_cluster (pages_left);
-    }
-
-  pages_left--;
-  return cluster_ptr++;
-
-#else  /* MALLOC_CHECK */
-
-  page_t *ptr;
-
-  ptr = xmalloc (PAGE_USIZE);
-  memset (ptr, 0, PAGE_USIZE);
-  return ptr;
-
-#endif /* MALLOC_CHECK */
-}
-\f
-/* Allocate scoping information.  */
-
-static scope_t *
-allocate_scope ()
-{
-  register scope_t *ptr;
-  static scope_t initial_scope;
-
-#ifndef MALLOC_CHECK
-
-  ptr = alloc_counts[(int)alloc_type_scope].free_list.f_scope;
-  if (ptr != (scope_t *) NULL)
-    alloc_counts[ (int)alloc_type_scope ].free_list.f_scope = ptr->free;
-  else
-    {
-      register int unallocated = alloc_counts[(int)alloc_type_scope].unallocated;
-      register page_t *cur_page        = alloc_counts[(int)alloc_type_scope].cur_page;
-
-      if (unallocated == 0)
-       {
-         unallocated = PAGE_SIZE / sizeof (scope_t);
-         alloc_counts[(int)alloc_type_scope].cur_page = cur_page = allocate_page ();
-         alloc_counts[(int)alloc_type_scope].total_pages++;
-       }
-
-      ptr = &cur_page->scope[--unallocated];
-      alloc_counts[(int)alloc_type_scope].unallocated = unallocated;
-    }
-
-#else
-
-  ptr = (scope_t *) xmalloc (sizeof (scope_t));
-
-#endif
-
-  alloc_counts[(int)alloc_type_scope].total_alloc++;
-  *ptr = initial_scope;
-  return ptr;
-}
-
-/* Free scoping information.  */
-
-static void
-free_scope (ptr)
-     scope_t *ptr;
-{
-  alloc_counts[(int)alloc_type_scope].total_free++;
-
-#ifndef MALLOC_CHECK
-  ptr->free = alloc_counts[(int)alloc_type_scope].free_list.f_scope;
-  alloc_counts[(int)alloc_type_scope].free_list.f_scope = ptr;
-#else
-  free ((PTR) ptr);
-#endif
-}
-\f
-/* Allocate links for pages in a virtual array.  */
-
-static vlinks_t *
-allocate_vlinks ()
-{
-  register vlinks_t *ptr;
-  static vlinks_t initial_vlinks;
-
-#ifndef MALLOC_CHECK
-
-  register int unallocated = alloc_counts[(int)alloc_type_vlinks].unallocated;
-  register page_t *cur_page = alloc_counts[(int)alloc_type_vlinks].cur_page;
-
-  if (unallocated == 0)
-    {
-      unallocated = PAGE_SIZE / sizeof (vlinks_t);
-      alloc_counts[(int)alloc_type_vlinks].cur_page = cur_page = allocate_page ();
-      alloc_counts[(int)alloc_type_vlinks].total_pages++;
-    }
-
-  ptr = &cur_page->vlinks[--unallocated];
-  alloc_counts[(int)alloc_type_vlinks].unallocated = unallocated;
-
-#else
-
-  ptr = (vlinks_t *) xmalloc (sizeof (vlinks_t));
-
-#endif
-
-  alloc_counts[(int)alloc_type_vlinks].total_alloc++;
-  *ptr = initial_vlinks;
-  return ptr;
-}
-\f
-/* Allocate string hash buckets.  */
-
-static shash_t *
-allocate_shash ()
-{
-  register shash_t *ptr;
-  static shash_t initial_shash;
-
-#ifndef MALLOC_CHECK
-
-  register int unallocated = alloc_counts[(int)alloc_type_shash].unallocated;
-  register page_t *cur_page = alloc_counts[(int)alloc_type_shash].cur_page;
-
-  if (unallocated == 0)
-    {
-      unallocated = PAGE_SIZE / sizeof (shash_t);
-      alloc_counts[(int)alloc_type_shash].cur_page = cur_page = allocate_page ();
-      alloc_counts[(int)alloc_type_shash].total_pages++;
-    }
-
-  ptr = &cur_page->shash[--unallocated];
-  alloc_counts[(int)alloc_type_shash].unallocated = unallocated;
-
-#else
-
-  ptr = (shash_t *) xmalloc (sizeof (shash_t));
-
-#endif
-
-  alloc_counts[(int)alloc_type_shash].total_alloc++;
-  *ptr = initial_shash;
-  return ptr;
-}
-\f
-/* Allocate type hash buckets.  */
-
-static thash_t *
-allocate_thash ()
-{
-  register thash_t *ptr;
-  static thash_t initial_thash;
-
-#ifndef MALLOC_CHECK
-
-  register int unallocated = alloc_counts[(int)alloc_type_thash].unallocated;
-  register page_t *cur_page = alloc_counts[(int)alloc_type_thash].cur_page;
-
-  if (unallocated == 0)
-    {
-      unallocated = PAGE_SIZE / sizeof (thash_t);
-      alloc_counts[(int)alloc_type_thash].cur_page = cur_page = allocate_page ();
-      alloc_counts[(int)alloc_type_thash].total_pages++;
-    }
-
-  ptr = &cur_page->thash[--unallocated];
-  alloc_counts[(int)alloc_type_thash].unallocated = unallocated;
-
-#else
-
-  ptr = (thash_t *) xmalloc (sizeof (thash_t));
-
-#endif
-
-  alloc_counts[(int)alloc_type_thash].total_alloc++;
-  *ptr = initial_thash;
-  return ptr;
-}
-\f
-/* Allocate structure, union, or enum tag information.  */
-
-static tag_t *
-allocate_tag ()
-{
-  register tag_t *ptr;
-  static tag_t initial_tag;
-
-#ifndef MALLOC_CHECK
-
-  ptr = alloc_counts[(int)alloc_type_tag].free_list.f_tag;
-  if (ptr != (tag_t *) NULL)
-    alloc_counts[(int)alloc_type_tag].free_list.f_tag = ptr->free;
-  else
-    {
-      register int unallocated = alloc_counts[(int)alloc_type_tag].unallocated;
-      register page_t *cur_page = alloc_counts[(int)alloc_type_tag].cur_page;
-
-      if (unallocated == 0)
-       {
-         unallocated = PAGE_SIZE / sizeof (tag_t);
-         alloc_counts[(int)alloc_type_tag].cur_page = cur_page = allocate_page ();
-         alloc_counts[(int)alloc_type_tag].total_pages++;
-       }
-
-      ptr = &cur_page->tag[--unallocated];
-      alloc_counts[(int)alloc_type_tag].unallocated = unallocated;
-    }
-
-#else
-
-  ptr = (tag_t *) xmalloc (sizeof (tag_t));
-
-#endif
-
-  alloc_counts[(int)alloc_type_tag].total_alloc++;
-  *ptr = initial_tag;
-  return ptr;
-}
-
-/* Free scoping information.  */
-
-static void
-free_tag (ptr)
-     tag_t *ptr;
-{
-  alloc_counts[(int)alloc_type_tag].total_free++;
-
-#ifndef MALLOC_CHECK
-  ptr->free = alloc_counts[(int)alloc_type_tag].free_list.f_tag;
-  alloc_counts[(int)alloc_type_tag].free_list.f_tag = ptr;
-#else
-  free ((PTR_T) ptr);
-#endif
-}
-\f
-/* Allocate forward reference to a yet unknown tag.  */
-
-static forward_t *
-allocate_forward ()
-{
-  register forward_t *ptr;
-  static forward_t initial_forward;
-
-#ifndef MALLOC_CHECK
-
-  register int unallocated = alloc_counts[(int)alloc_type_forward].unallocated;
-  register page_t *cur_page = alloc_counts[(int)alloc_type_forward].cur_page;
-
-  if (unallocated == 0)
-    {
-      unallocated = PAGE_SIZE / sizeof (forward_t);
-      alloc_counts[(int)alloc_type_forward].cur_page = cur_page = allocate_page ();
-      alloc_counts[(int)alloc_type_forward].total_pages++;
-    }
-
-  ptr = &cur_page->forward[--unallocated];
-  alloc_counts[(int)alloc_type_forward].unallocated = unallocated;
-
-#else
-
-  ptr = (forward_t *) xmalloc (sizeof (forward_t));
-
-#endif
-
-  alloc_counts[(int)alloc_type_forward].total_alloc++;
-  *ptr = initial_forward;
-  return ptr;
-}
-\f
-/* Allocate head of type hash list.  */
-
-static thead_t *
-allocate_thead ()
-{
-  register thead_t *ptr;
-  static thead_t initial_thead;
-
-#ifndef MALLOC_CHECK
-
-  ptr = alloc_counts[(int)alloc_type_thead].free_list.f_thead;
-  if (ptr != (thead_t *) NULL)
-    alloc_counts[ (int)alloc_type_thead ].free_list.f_thead = ptr->free;
-  else
-    {
-      register int unallocated = alloc_counts[(int)alloc_type_thead].unallocated;
-      register page_t *cur_page = alloc_counts[(int)alloc_type_thead].cur_page;
-
-      if (unallocated == 0)
-       {
-         unallocated = PAGE_SIZE / sizeof (thead_t);
-         alloc_counts[(int)alloc_type_thead].cur_page = cur_page = allocate_page ();
-         alloc_counts[(int)alloc_type_thead].total_pages++;
-       }
-
-      ptr = &cur_page->thead[--unallocated];
-      alloc_counts[(int)alloc_type_thead].unallocated = unallocated;
-    }
-
-#else
-
-  ptr = (thead_t *) xmalloc (sizeof (thead_t));
-
-#endif
-
-  alloc_counts[(int)alloc_type_thead].total_alloc++;
-  *ptr = initial_thead;
-  return ptr;
-}
-
-/* Free scoping information.  */
-
-static void
-free_thead (ptr)
-     thead_t *ptr;
-{
-  alloc_counts[(int)alloc_type_thead].total_free++;
-
-#ifndef MALLOC_CHECK
-  ptr->free = (thead_t *) alloc_counts[(int)alloc_type_thead].free_list.f_thead;
-  alloc_counts[(int)alloc_type_thead].free_list.f_thead = ptr;
-#else
-  free ((PTR_T) ptr);
-#endif
-}
-\f
-static lineno_list_t *
-allocate_lineno_list ()
-{
-  register lineno_list_t *ptr;
-  static lineno_list_t initial_lineno_list;
-
-#ifndef MALLOC_CHECK
-
-  register int unallocated = alloc_counts[(int)alloc_type_lineno].unallocated;
-  register page_t *cur_page = alloc_counts[(int)alloc_type_lineno].cur_page;
 
-  if (unallocated == 0)
-    {
-      unallocated = PAGE_SIZE / sizeof (lineno_list_t);
-      alloc_counts[(int)alloc_type_lineno].cur_page = cur_page = allocate_page ();
-      alloc_counts[(int)alloc_type_lineno].total_pages++;
-    }
-
-  ptr = &cur_page->lineno[--unallocated];
-  alloc_counts[(int)alloc_type_lineno].unallocated = unallocated;
-
-#else
+/* This is called by the ECOFF code to set the external information
+   for a symbol.  We just pass it on to BFD, which expects the swapped
+   information to be stored in the native field of the symbol.  */
 
-  ptr = (lineno_list_t *) xmalloc (sizeof (lineno_list_t));
-
-#endif
-
-  alloc_counts[(int)alloc_type_lineno].total_alloc++;
-  *ptr = initial_lineno_list;
-  return ptr;
+void
+obj_ecoff_set_ext (sym, ext)
+     symbolS *sym;
+     EXTR *ext;
+{
+  const struct ecoff_debug_swap * const debug_swap
+    = &ecoff_backend (stdoutput)->debug_swap;
+  ecoff_symbol_type *esym;
+
+  know (bfd_asymbol_flavour (sym->bsym) == bfd_target_ecoff_flavour);
+  esym = ecoffsymbol (sym->bsym);
+  esym->local = false;
+  esym->native = xmalloc (debug_swap->external_ext_size);
+  (*debug_swap->swap_ext_out) (stdoutput, ext, esym->native);
 }
index ab4676253ea2fb330b7c8e1a72e036babbe45163..a0cf0acfe33f78702e7f094930406f84c8c25a66 100644 (file)
 #include "subsegs.h"
 #include "obstack.h"
 
+#ifdef ECOFF_DEBUGGING
+#include "ecoff.h"
+#endif
+
 static int obj_elf_write_symbol_p PARAMS ((symbolS *sym));
 
+#ifdef ECOFF_DEBUGGING
+static boolean elf_get_extr PARAMS ((asymbol *, EXTR *));
+static void elf_set_index PARAMS ((asymbol *, bfd_size_type));
+#endif
+
 static void obj_elf_line PARAMS ((int));
 void obj_elf_version PARAMS ((int));
 static void obj_elf_size PARAMS ((int));
@@ -58,6 +67,43 @@ const pseudo_typeS obj_pseudo_table[] =
   {"data", obj_elf_data, 0},
   {"text", obj_elf_text, 0},
 
+#ifdef ECOFF_DEBUGGING
+  /* COFF style debugging information for ECOFF. .ln is not used; .loc
+     is used instead.  */
+  { "def",     ecoff_directive_def,    0 },
+  { "dim",     ecoff_directive_dim,    0 },
+  { "endef",   ecoff_directive_endef,  0 },
+  { "file",    ecoff_directive_file,   0 },
+  { "scl",     ecoff_directive_scl,    0 },
+  { "tag",     ecoff_directive_tag,    0 },
+  { "val",     ecoff_directive_val,    0 },
+
+  /* COFF debugging requires pseudo-ops .size and .type, but ELF
+     already has meanings for those.  We use .esize and .etype
+     instead.  These are only generated by gcc anyhow.  */
+  { "esize",   ecoff_directive_size,   0 },
+  { "etype",   ecoff_directive_type,   0 },
+
+  /* ECOFF specific debugging information.  */
+  { "begin",   ecoff_directive_begin,  0 },
+  { "bend",    ecoff_directive_bend,   0 },
+  { "end",     ecoff_directive_end,    0 },
+  { "ent",     ecoff_directive_ent,    0 },
+  { "fmask",   ecoff_directive_fmask,  0 },
+  { "frame",   ecoff_directive_frame,  0 },
+  { "loc",     ecoff_directive_loc,    0 },
+  { "mask",    ecoff_directive_mask,   0 },
+
+  /* These are used on Irix.  I don't know how to implement them.  */
+  { "alias",   s_ignore,               0 },
+  { "bgnb",    s_ignore,               0 },
+  { "endb",    s_ignore,               0 },
+  { "lab",     s_ignore,               0 },
+  { "noalias", s_ignore,               0 },
+  { "verstamp",        s_ignore,               0 },
+  { "vreg",    s_ignore,               0 },
+#endif /* ECOFF_DEBUGGING */
+
   {NULL}                       /* end sentinel */
 };
 
@@ -611,6 +657,9 @@ obj_elf_line (ignore)
 void 
 obj_read_begin_hook ()
 {
+#ifdef ECOFF_DEBUGGING
+  ecoff_read_begin_hook ();
+#endif
 }
 
 void 
@@ -627,6 +676,9 @@ obj_symbol_new_hook (symbolP)
   bzero ((char *) &esym->native_elf_sym, sizeof (esym->native_elf_sym));
   bzero ((char *) &esym->tc_data, sizeof (esym->tc_data));
 #endif
+#ifdef ECOFF_DEBUGGING
+  ecoff_symbol_new_hook (symbolP);
+#endif
 }
 
 void 
@@ -823,6 +875,7 @@ obj_elf_init_stab_section (seg)
 {
   char *file;
   char *p;
+  char *stabstr_name;
   unsigned int stroff;
 
   /* Force the section to align to a longword boundary.  Without this,
@@ -831,7 +884,10 @@ obj_elf_init_stab_section (seg)
 
   p = frag_more (12);
   as_where (&file, (unsigned int *) NULL);
-  stroff = get_stab_string_offset (file, segment_name (seg));
+  stabstr_name = (char *) alloca (strlen (segment_name (seg)) + 4);
+  strcpy (stabstr_name, segment_name (seg));
+  strcat (stabstr_name, "str");
+  stroff = get_stab_string_offset (file, stabstr_name);
   know (stroff == 1);
   md_number_to_chars (p, stroff, 4);
   seg_info (seg)->stabu.p = p;
@@ -872,6 +928,50 @@ adjust_stab_sections (abfd, sec, xxx)
   bfd_h_put_32 (abfd, (bfd_vma) strsz, (bfd_byte *) p + 8);
 }
 
+#ifdef ECOFF_DEBUGGING
+
+/* This function is called by the ECOFF code.  It is supposed to
+   record the external symbol information so that the backend can
+   write it out correctly.  The ELF backend doesn't actually handle
+   this at the moment, so we do it ourselves.  We save the information
+   in the symbol.  */
+
+void
+obj_ecoff_set_ext (sym, ext)
+     symbolS *sym;
+     EXTR *ext;
+{
+  sym->bsym->udata = (PTR) ext;
+}
+
+/* This function is called by bfd_ecoff_debug_externals.  It is
+   supposed to *EXT to the external symbol information, and return
+   whether the symbol should be used at all.  */
+
+static boolean
+elf_get_extr (sym, ext)
+     asymbol *sym;
+     EXTR *ext;
+{
+  if (sym->udata == NULL)
+    return false;
+  *ext = *(EXTR *) sym->udata;
+  return true;
+}
+
+/* This function is called by bfd_ecoff_debug_externals.  It has
+   nothing to do for ELF.  */
+
+/*ARGSUSED*/
+static void
+elf_set_index (sym, indx)
+     asymbol *sym;
+     bfd_size_type indx;
+{
+}
+
+#endif /* ECOFF_DEBUGGING */
+
 void 
 elf_frob_file ()
 {
@@ -896,4 +996,68 @@ elf_frob_file ()
 #ifdef elf_tc_make_sections
   elf_tc_make_sections (stdoutput);
 #endif
+
+#ifdef ECOFF_DEBUGGING
+  /* Generate the ECOFF debugging information.  */
+  {
+    const struct ecoff_debug_swap *debug_swap;
+    struct ecoff_debug_info debug;
+    char *buf;
+    asection *sec;
+
+    debug_swap
+      = get_elf_backend_data (stdoutput)->elf_backend_ecoff_debug_swap;
+    know (debug_swap != (const struct ecoff_debug_swap *) NULL);
+    ecoff_build_debug (&debug.symbolic_header, &buf, debug_swap);
+
+    /* Set up the pointers in debug.  */
+#define SET(ptr, offset, type) \
+    debug.ptr = (type) (buf + debug.symbolic_header.offset)
+
+    SET (line, cbLineOffset, unsigned char *);
+    SET (external_dnr, cbDnOffset, PTR);
+    SET (external_pdr, cbPdOffset, PTR);
+    SET (external_sym, cbSymOffset, PTR);
+    SET (external_opt, cbOptOffset, PTR);
+    SET (external_aux, cbAuxOffset, union aux_ext *);
+    SET (ss, cbSsOffset, char *);
+    SET (external_fdr, cbFdOffset, PTR);
+    SET (external_rfd, cbRfdOffset, PTR);
+    /* ssext and external_ext are set up just below.  */
+
+#undef SET    
+
+    /* Set up the external symbols.  */
+    debug.ssext = debug.ssext_end = NULL;
+    debug.external_ext = debug.external_ext_end = NULL;
+    if (! bfd_ecoff_debug_externals (stdoutput, &debug, debug_swap, true,
+                                    elf_get_extr, elf_set_index))
+      as_fatal ("Failed to set up debugging information: %s",
+               bfd_errmsg (bfd_error));
+
+    sec = bfd_get_section_by_name (stdoutput, ".mdebug");
+    assert (sec != NULL);
+
+    know (stdoutput->output_has_begun == false);
+
+    /* We set the size of the section, call bfd_set_section_contents
+       to force the ELF backend to allocate a file position, and then
+       write out the data.  FIXME: Is this really the best way to do
+       this?  */
+    sec->_raw_size = bfd_ecoff_debug_size (stdoutput, &debug, debug_swap);
+
+    if (! bfd_set_section_contents (stdoutput, sec, (PTR) NULL,
+                                   (file_ptr) 0, (bfd_size_type) 0))
+      as_fatal ("Can't start writing .mdebug section: %s",
+               bfd_errmsg (bfd_error));
+
+    know (stdoutput->output_has_begun == true);
+    know (sec->filepos != 0);
+
+    if (! bfd_ecoff_write_debug (stdoutput, &debug, debug_swap,
+                                sec->filepos))
+      as_fatal ("Could not write .mdebug section: %s",
+               bfd_errmsg (bfd_error));
+  }
+#endif /* ECOFF_DEBUGGING */
 }