OSDN Git Service

* gcc.c (trad_capable_cpp, default_compilers): Don't handle
[pf3gnuchains/gcc-fork.git] / gcc / mips-tfile.c
1 /* Update the symbol table (the .T file) in a MIPS object to
2    contain debugging information specified by the GNU compiler
3    in the form of comments (the mips assembler does not support
4    assembly access to debug information).
5    Copyright (C) 1991, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
6    2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
7    Free Software Foundation, Inc.
8    Contributed by Michael Meissner (meissner@cygnus.com).
9
10 This file is part of GCC.
11
12 GCC is free software; you can redistribute it and/or modify it under
13 the terms of the GNU General Public License as published by the Free
14 Software Foundation; either version 3, or (at your option) any later
15 version.
16
17 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
18 WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with GCC; see the file COPYING3.  If not see
24 <http://www.gnu.org/licenses/>.  */
25
26 \f
27 /* Here is a brief description of the MIPS ECOFF symbol table.  The
28    MIPS symbol table has the following pieces:
29
30         Symbolic Header
31             |
32             +-- Auxiliary Symbols
33             |
34             +-- Dense number table
35             |
36             +-- Optimizer Symbols
37             |
38             +-- External Strings
39             |
40             +-- External Symbols
41             |
42             +-- Relative file descriptors
43             |
44             +-- File table
45                     |
46                     +-- Procedure table
47                     |
48                     +-- Line number table
49                     |
50                     +-- Local Strings
51                     |
52                     +-- Local Symbols
53
54    The symbolic header points to each of the other tables, and also
55    contains the number of entries.  It also contains a magic number
56    and MIPS compiler version number, such as 2.0.
57
58    The auxiliary table is a series of 32 bit integers, that are
59    referenced as needed from the local symbol table.  Unlike standard
60    COFF, the aux. information does not follow the symbol that uses
61    it, but rather is a separate table.  In theory, this would allow
62    the MIPS compilers to collapse duplicate aux. entries, but I've not
63    noticed this happening with the 1.31 compiler suite.  The different
64    types of aux. entries are:
65
66     1)  dnLow: Low bound on array dimension.
67
68     2)  dnHigh: High bound on array dimension.
69
70     3)  isym: Index to the local symbol which is the start of the
71         function for the end of function first aux. entry.
72
73     4)  width: Width of structures and bitfields.
74
75     5)  count: Count of ranges for variant part.
76
77     6)  rndx: A relative index into the symbol table.  The relative
78         index field has two parts: rfd which is a pointer into the
79         relative file index table or ST_RFDESCAPE which says the next
80         aux. entry is the file number, and index: which is the pointer
81         into the local symbol within a given file table.  This is for
82         things like references to types defined in another file.
83
84     7)  Type information: This is like the COFF type bits, except it
85         is 32 bits instead of 16; they still have room to add new
86         basic types; and they can handle more than 6 levels of array,
87         pointer, function, etc.  Each type information field contains
88         the following structure members:
89
90             a)  fBitfield: a bit that says this is a bitfield, and the
91                 size in bits follows as the next aux. entry.
92
93             b)  continued: a bit that says the next aux. entry is a
94                 continuation of the current type information (in case
95                 there are more than 6 levels of array/ptr/function).
96
97             c)  bt: an integer containing the base type before adding
98                 array, pointer, function, etc. qualifiers.  The
99                 current base types that I have documentation for are:
100
101                         btNil           -- undefined
102                         btAdr           -- address - integer same size as ptr
103                         btChar          -- character
104                         btUChar         -- unsigned character
105                         btShort         -- short
106                         btUShort        -- unsigned short
107                         btInt           -- int
108                         btUInt          -- unsigned int
109                         btLong          -- long
110                         btULong         -- unsigned long
111                         btFloat         -- float (real)
112                         btDouble        -- Double (real)
113                         btStruct        -- Structure (Record)
114                         btUnion         -- Union (variant)
115                         btEnum          -- Enumerated
116                         btTypedef       -- defined via a typedef isymRef
117                         btRange         -- subrange of int
118                         btSet           -- pascal sets
119                         btComplex       -- fortran complex
120                         btDComplex      -- fortran double complex
121                         btIndirect      -- forward or unnamed typedef
122                         btFixedDec      -- Fixed Decimal
123                         btFloatDec      -- Float Decimal
124                         btString        -- Varying Length Character String
125                         btBit           -- Aligned Bit String
126                         btPicture       -- Picture
127                         btVoid          -- Void (MIPS cc revision >= 2.00)
128
129             d)  tq0 - tq5: type qualifier fields as needed.  The
130                 current type qualifier fields I have documentation for
131                 are:
132
133                         tqNil           -- no more qualifiers
134                         tqPtr           -- pointer
135                         tqProc          -- procedure
136                         tqArray         -- array
137                         tqFar           -- 8086 far pointers
138                         tqVol           -- volatile
139
140
141    The dense number table is used in the front ends, and disappears by
142    the time the .o is created.
143
144    With the 1.31 compiler suite, the optimization symbols don't seem
145    to be used as far as I can tell.
146
147    The linker is the first entity that creates the relative file
148    descriptor table, and I believe it is used so that the individual
149    file table pointers don't have to be rewritten when the objects are
150    merged together into the program file.
151
152    Unlike COFF, the basic symbol & string tables are split into
153    external and local symbols/strings.  The relocation information
154    only goes off of the external symbol table, and the debug
155    information only goes off of the internal symbol table.  The
156    external symbols can have links to an appropriate file index and
157    symbol within the file to give it the appropriate type information.
158    Because of this, the external symbols are actually larger than the
159    internal symbols (to contain the link information), and contain the
160    local symbol structure as a member, though this member is not the
161    first member of the external symbol structure (!).  I suspect this
162    split is to make strip easier to deal with.
163
164    Each file table has offsets for where the line numbers, local
165    strings, local symbols, and procedure table starts from within the
166    global tables, and the indices are reset to 0 for each of those
167    tables for the file.
168
169    The procedure table contains the binary equivalents of the .ent
170    (start of the function address), .frame (what register is the
171    virtual frame pointer, constant offset from the register to obtain
172    the VFP, and what register holds the return address), .mask/.fmask
173    (bitmask of saved registers, and where the first register is stored
174    relative to the VFP) assembler directives.  It also contains the
175    low and high bounds of the line numbers if debugging is turned on.
176
177    The line number table is a compressed form of the normal COFF line
178    table.  Each line number entry is either 1 or 3 bytes long, and
179    contains a signed delta from the previous line, and an unsigned
180    count of the number of instructions this statement takes.
181
182    The local symbol table contains the following fields:
183
184     1)  iss: index to the local string table giving the name of the
185         symbol.
186
187     2)  value: value of the symbol (address, register number, etc.).
188
189     3)  st: symbol type.  The current symbol types are:
190
191             stNil         -- Nuthin' special
192             stGlobal      -- external symbol
193             stStatic      -- static
194             stParam       -- procedure argument
195             stLocal       -- local variable
196             stLabel       -- label
197             stProc        -- External Procedure
198             stBlock       -- beginning of block
199             stEnd         -- end (of anything)
200             stMember      -- member (of anything)
201             stTypedef     -- type definition
202             stFile        -- file name
203             stRegReloc    -- register relocation
204             stForward     -- forwarding address
205             stStaticProc  -- Static procedure
206             stConstant    -- const
207
208     4)  sc: storage class.  The current storage classes are:
209
210             scText        -- text symbol
211             scData        -- initialized data symbol
212             scBss         -- un-initialized data symbol
213             scRegister    -- value of symbol is register number
214             scAbs         -- value of symbol is absolute
215             scUndefined   -- who knows?
216             scCdbLocal    -- variable's value is IN se->va.??
217             scBits        -- this is a bit field
218             scCdbSystem   -- value is IN debugger's address space
219             scRegImage    -- register value saved on stack
220             scInfo        -- symbol contains debugger information
221             scUserStruct  -- addr in struct user for current process
222             scSData       -- load time only small data
223             scSBss        -- load time only small common
224             scRData       -- load time only read only data
225             scVar         -- Var parameter (fortranpascal)
226             scCommon      -- common variable
227             scSCommon     -- small common
228             scVarRegister -- Var parameter in a register
229             scVariant     -- Variant record
230             scSUndefined  -- small undefined(external) data
231             scInit        -- .init section symbol
232
233     5)  index: pointer to a local symbol or aux. entry.
234
235
236
237    For the following program:
238
239         #include <stdio.h>
240
241         main(){
242                 printf("Hello World!\n");
243                 return 0;
244         }
245
246    Mips-tdump produces the following information:
247
248    Global file header:
249        magic number             0x162
250        # sections               2
251        timestamp                645311799, Wed Jun 13 17:16:39 1990
252        symbolic header offset   284
253        symbolic header size     96
254        optional header          56
255        flags                    0x0
256
257    Symbolic header, magic number = 0x7009, vstamp = 1.31:
258
259        Info                      Offset      Number       Bytes
260        ====                      ======      ======      =====
261
262        Line numbers                 380           4           4 [13]
263        Dense numbers                  0           0           0
264        Procedures Tables            384           1          52
265        Local Symbols                436          16         192
266        Optimization Symbols           0           0           0
267        Auxiliary Symbols            628          39         156
268        Local Strings                784          80          80
269        External Strings             864         144         144
270        File Tables                 1008           2         144
271        Relative Files                 0           0           0
272        External Symbols            1152          20         320
273
274    File #0, "hello2.c"
275
276        Name index  = 1          Readin      = No
277        Merge       = No         Endian      = LITTLE
278        Debug level = G2         Language    = C
279        Adr         = 0x00000000
280
281        Info                       Start      Number        Size      Offset
282        ====                       =====      ======        ====      ======
283        Local strings                  0          15          15         784
284        Local symbols                  0           6          72         436
285        Line numbers                   0          13          13         380
286        Optimization symbols           0           0           0           0
287        Procedures                     0           1          52         384
288        Auxiliary symbols              0          14          56         628
289        Relative Files                 0           0           0           0
290
291     There are 6 local symbols, starting at 436
292
293         Symbol# 0: "hello2.c"
294             End+1 symbol  = 6
295             String index  = 1
296             Storage class = Text        Index  = 6
297             Symbol type   = File        Value  = 0
298
299         Symbol# 1: "main"
300             End+1 symbol  = 5
301             Type          = int
302             String index  = 10
303             Storage class = Text        Index  = 12
304             Symbol type   = Proc        Value  = 0
305
306         Symbol# 2: ""
307             End+1 symbol  = 4
308             String index  = 0
309             Storage class = Text        Index  = 4
310             Symbol type   = Block       Value  = 8
311
312         Symbol# 3: ""
313             First symbol  = 2
314             String index  = 0
315             Storage class = Text        Index  = 2
316             Symbol type   = End         Value  = 28
317
318         Symbol# 4: "main"
319             First symbol  = 1
320             String index  = 10
321             Storage class = Text        Index  = 1
322             Symbol type   = End         Value  = 52
323
324         Symbol# 5: "hello2.c"
325             First symbol  = 0
326             String index  = 1
327             Storage class = Text        Index  = 0
328             Symbol type   = End         Value  = 0
329
330     There are 14 auxiliary table entries, starting at 628.
331
332         * #0               0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
333         * #1              24, [  24/      0], [ 6 0:0 0:0:0:0:0:0]
334         * #2               8, [   8/      0], [ 2 0:0 0:0:0:0:0:0]
335         * #3              16, [  16/      0], [ 4 0:0 0:0:0:0:0:0]
336         * #4              24, [  24/      0], [ 6 0:0 0:0:0:0:0:0]
337         * #5              32, [  32/      0], [ 8 0:0 0:0:0:0:0:0]
338         * #6              40, [  40/      0], [10 0:0 0:0:0:0:0:0]
339         * #7              44, [  44/      0], [11 0:0 0:0:0:0:0:0]
340         * #8              12, [  12/      0], [ 3 0:0 0:0:0:0:0:0]
341         * #9              20, [  20/      0], [ 5 0:0 0:0:0:0:0:0]
342         * #10             28, [  28/      0], [ 7 0:0 0:0:0:0:0:0]
343         * #11             36, [  36/      0], [ 9 0:0 0:0:0:0:0:0]
344           #12              5, [   5/      0], [ 1 1:0 0:0:0:0:0:0]
345           #13             24, [  24/      0], [ 6 0:0 0:0:0:0:0:0]
346
347     There are 1 procedure descriptor entries, starting at 0.
348
349         Procedure descriptor 0:
350             Name index   = 10          Name          = "main"
351             .mask 0x80000000,-4        .fmask 0x00000000,0
352             .frame $29,24,$31
353             Opt. start   = -1          Symbols start = 1
354             First line # = 3           Last line #   = 6
355             Line Offset  = 0           Address       = 0x00000000
356
357         There are 4 bytes holding line numbers, starting at 380.
358             Line           3,   delta     0,   count  2
359             Line           4,   delta     1,   count  3
360             Line           5,   delta     1,   count  2
361             Line           6,   delta     1,   count  6
362
363    File #1, "/usr/include/stdio.h"
364
365     Name index  = 1          Readin      = No
366     Merge       = Yes        Endian      = LITTLE
367     Debug level = G2         Language    = C
368     Adr         = 0x00000000
369
370     Info                       Start      Number        Size      Offset
371     ====                       =====      ======        ====      ======
372     Local strings                 15          65          65         799
373     Local symbols                  6          10         120         508
374     Line numbers                   0           0           0         380
375     Optimization symbols           0           0           0           0
376     Procedures                     1           0           0         436
377     Auxiliary symbols             14          25         100         684
378     Relative Files                 0           0           0           0
379
380     There are 10 local symbols, starting at 442
381
382         Symbol# 0: "/usr/include/stdio.h"
383             End+1 symbol  = 10
384             String index  = 1
385             Storage class = Text        Index  = 10
386             Symbol type   = File        Value  = 0
387
388         Symbol# 1: "_iobuf"
389             End+1 symbol  = 9
390             String index  = 22
391             Storage class = Info        Index  = 9
392             Symbol type   = Block       Value  = 20
393
394         Symbol# 2: "_cnt"
395             Type          = int
396             String index  = 29
397             Storage class = Info        Index  = 4
398             Symbol type   = Member      Value  = 0
399
400         Symbol# 3: "_ptr"
401             Type          = ptr to char
402             String index  = 34
403             Storage class = Info        Index  = 15
404             Symbol type   = Member      Value  = 32
405
406         Symbol# 4: "_base"
407             Type          = ptr to char
408             String index  = 39
409             Storage class = Info        Index  = 16
410             Symbol type   = Member      Value  = 64
411
412         Symbol# 5: "_bufsiz"
413             Type          = int
414             String index  = 45
415             Storage class = Info        Index  = 4
416             Symbol type   = Member      Value  = 96
417
418         Symbol# 6: "_flag"
419             Type          = short
420             String index  = 53
421             Storage class = Info        Index  = 3
422             Symbol type   = Member      Value  = 128
423
424         Symbol# 7: "_file"
425             Type          = char
426             String index  = 59
427             Storage class = Info        Index  = 2
428             Symbol type   = Member      Value  = 144
429
430         Symbol# 8: ""
431             First symbol  = 1
432             String index  = 0
433             Storage class = Info        Index  = 1
434             Symbol type   = End         Value  = 0
435
436         Symbol# 9: "/usr/include/stdio.h"
437             First symbol  = 0
438             String index  = 1
439             Storage class = Text        Index  = 0
440             Symbol type   = End         Value  = 0
441
442     There are 25 auxiliary table entries, starting at 642.
443
444         * #14             -1, [4095/1048575], [63 1:1 f:f:f:f:f:f]
445           #15          65544, [   8/     16], [ 2 0:0 1:0:0:0:0:0]
446           #16          65544, [   8/     16], [ 2 0:0 1:0:0:0:0:0]
447         * #17         196656, [  48/     48], [12 0:0 3:0:0:0:0:0]
448         * #18           8191, [4095/      1], [63 1:1 0:0:0:0:f:1]
449         * #19              1, [   1/      0], [ 0 1:0 0:0:0:0:0:0]
450         * #20          20479, [4095/      4], [63 1:1 0:0:0:0:f:4]
451         * #21              1, [   1/      0], [ 0 1:0 0:0:0:0:0:0]
452         * #22              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
453         * #23              2, [   2/      0], [ 0 0:1 0:0:0:0:0:0]
454         * #24            160, [ 160/      0], [40 0:0 0:0:0:0:0:0]
455         * #25              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
456         * #26              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
457         * #27              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
458         * #28              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
459         * #29              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
460         * #30              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
461         * #31              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
462         * #32              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
463         * #33              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
464         * #34              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
465         * #35              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
466         * #36              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
467         * #37              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
468         * #38              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
469
470     There are 0 procedure descriptor entries, starting at 1.
471
472    There are 20 external symbols, starting at 1152
473
474         Symbol# 0: "_iob"
475             Type          = array [3 {160}] of struct _iobuf { ifd = 1, index = 1 }
476             String index  = 0           Ifd    = 1
477             Storage class = Nil         Index  = 17
478             Symbol type   = Global      Value  = 60
479
480         Symbol# 1: "fopen"
481             String index  = 5           Ifd    = 1
482             Storage class = Nil         Index  = 1048575
483             Symbol type   = Proc        Value  = 0
484
485         Symbol# 2: "fdopen"
486             String index  = 11          Ifd    = 1
487             Storage class = Nil         Index  = 1048575
488             Symbol type   = Proc        Value  = 0
489
490         Symbol# 3: "freopen"
491             String index  = 18          Ifd    = 1
492             Storage class = Nil         Index  = 1048575
493             Symbol type   = Proc        Value  = 0
494
495         Symbol# 4: "popen"
496             String index  = 26          Ifd    = 1
497             Storage class = Nil         Index  = 1048575
498             Symbol type   = Proc        Value  = 0
499
500         Symbol# 5: "tmpfile"
501             String index  = 32          Ifd    = 1
502             Storage class = Nil         Index  = 1048575
503             Symbol type   = Proc        Value  = 0
504
505         Symbol# 6: "ftell"
506             String index  = 40          Ifd    = 1
507             Storage class = Nil         Index  = 1048575
508             Symbol type   = Proc        Value  = 0
509
510         Symbol# 7: "rewind"
511             String index  = 46          Ifd    = 1
512             Storage class = Nil         Index  = 1048575
513             Symbol type   = Proc        Value  = 0
514
515         Symbol# 8: "setbuf"
516             String index  = 53          Ifd    = 1
517             Storage class = Nil         Index  = 1048575
518             Symbol type   = Proc        Value  = 0
519
520         Symbol# 9: "setbuffer"
521             String index  = 60          Ifd    = 1
522             Storage class = Nil         Index  = 1048575
523             Symbol type   = Proc        Value  = 0
524
525         Symbol# 10: "setlinebuf"
526             String index  = 70          Ifd    = 1
527             Storage class = Nil         Index  = 1048575
528             Symbol type   = Proc        Value  = 0
529
530         Symbol# 11: "fgets"
531             String index  = 81          Ifd    = 1
532             Storage class = Nil         Index  = 1048575
533             Symbol type   = Proc        Value  = 0
534
535         Symbol# 12: "gets"
536             String index  = 87          Ifd    = 1
537             Storage class = Nil         Index  = 1048575
538             Symbol type   = Proc        Value  = 0
539
540         Symbol# 13: "ctermid"
541             String index  = 92          Ifd    = 1
542             Storage class = Nil         Index  = 1048575
543             Symbol type   = Proc        Value  = 0
544
545         Symbol# 14: "cuserid"
546             String index  = 100         Ifd    = 1
547             Storage class = Nil         Index  = 1048575
548             Symbol type   = Proc        Value  = 0
549
550         Symbol# 15: "tempnam"
551             String index  = 108         Ifd    = 1
552             Storage class = Nil         Index  = 1048575
553             Symbol type   = Proc        Value  = 0
554
555         Symbol# 16: "tmpnam"
556             String index  = 116         Ifd    = 1
557             Storage class = Nil         Index  = 1048575
558             Symbol type   = Proc        Value  = 0
559
560         Symbol# 17: "sprintf"
561             String index  = 123         Ifd    = 1
562             Storage class = Nil         Index  = 1048575
563             Symbol type   = Proc        Value  = 0
564
565         Symbol# 18: "main"
566             Type          = int
567             String index  = 131         Ifd    = 0
568             Storage class = Text        Index  = 1
569             Symbol type   = Proc        Value  = 0
570
571         Symbol# 19: "printf"
572             String index  = 136         Ifd    = 0
573             Storage class = Undefined   Index  = 1048575
574             Symbol type   = Proc        Value  = 0
575
576    The following auxiliary table entries were unused:
577
578     #0               0  0x00000000  void
579     #2               8  0x00000008  char
580     #3              16  0x00000010  short
581     #4              24  0x00000018  int
582     #5              32  0x00000020  long
583     #6              40  0x00000028  float
584     #7              44  0x0000002c  double
585     #8              12  0x0000000c  unsigned char
586     #9              20  0x00000014  unsigned short
587     #10             28  0x0000001c  unsigned int
588     #11             36  0x00000024  unsigned long
589     #14              0  0x00000000  void
590     #15             24  0x00000018  int
591     #19             32  0x00000020  long
592     #20             40  0x00000028  float
593     #21             44  0x0000002c  double
594     #22             12  0x0000000c  unsigned char
595     #23             20  0x00000014  unsigned short
596     #24             28  0x0000001c  unsigned int
597     #25             36  0x00000024  unsigned long
598     #26             48  0x00000030  struct no name { ifd = -1, index = 1048575 }
599
600 */
601 \f
602
603 #include "config.h"
604 #include "system.h"
605 #include "coretypes.h"
606 #include "tm.h"
607 #include "version.h"
608 #include "intl.h"
609
610 #ifndef __SABER__
611 #define saber_stop()
612 #endif
613
614 /* Include getopt.h for the sake of getopt_long.  */
615 #include "getopt.h"
616
617 #ifndef __LINE__
618 #define __LINE__ 0
619 #endif
620
621 /* Due to size_t being defined in sys/types.h and different
622    in stddef.h, we have to do this by hand.....  Note, these
623    types are correct for MIPS based systems, and may not be
624    correct for other systems.  Ultrix 4.0 and Silicon Graphics
625    have this fixed, but since the following is correct, and
626    the fact that including stddef.h gets you GCC's version
627    instead of the standard one it's not worth it to fix it.  */
628
629 #if defined(__OSF1__) || defined(__OSF__) || defined(__osf__)
630 #define Size_t          long unsigned int
631 #else
632 #define Size_t          unsigned int
633 #endif
634 #define Ptrdiff_t       long
635
636 /* The following might be called from obstack or malloc,
637    so they can't be static.  */
638
639 extern void pfatal_with_name (const char *) ATTRIBUTE_NORETURN;
640 extern void botch (const char *) ATTRIBUTE_NORETURN;
641
642 extern void fatal (const char *format, ...) ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
643 extern void error (const char *format, ...) ATTRIBUTE_PRINTF_1;
644 \f
645 #ifndef MIPS_DEBUGGING_INFO
646
647 static int       line_number;
648 static int       cur_line_start;
649 static int       debug;
650 static int       had_errors;
651 static const char *progname;
652 static const char *input_name;
653
654 int
655 main (void)
656 {
657   fprintf (stderr, "Mips-tfile should only be run on a MIPS computer!\n");
658   exit (1);
659 }
660
661 #else                           /* MIPS_DEBUGGING defined */
662 \f
663 /* The local and global symbols have a field index, so undo any defines
664    of index -> strchr.  */
665
666 #undef index
667
668 #ifndef CROSS_DIRECTORY_STRUCTURE
669 #include <a.out.h>
670 #else
671 #include "mips/a.out.h"
672 #endif /* CROSS_DIRECTORY_STRUCTURE */
673
674 #include "gstab.h"
675
676 #ifndef MALLOC_CHECK
677 #ifdef  __SABER__
678 #define MALLOC_CHECK
679 #endif
680 #endif
681
682 #define IS_ASM_IDENT(ch) \
683   (ISIDNUM (ch) || (ch) == '.' || (ch) == '$')
684
685 \f
686 /* Redefinition of storage classes as an enumeration for better
687    debugging.  */
688
689 typedef enum sc {
690   sc_Nil         = scNil,         /* no storage class */
691   sc_Text        = scText,        /* text symbol */
692   sc_Data        = scData,        /* initialized data symbol */
693   sc_Bss         = scBss,         /* un-initialized data symbol */
694   sc_Register    = scRegister,    /* value of symbol is register number */
695   sc_Abs         = scAbs,         /* value of symbol is absolute */
696   sc_Undefined   = scUndefined,   /* who knows? */
697   sc_CdbLocal    = scCdbLocal,    /* variable's value is IN se->va.?? */
698   sc_Bits        = scBits,        /* this is a bit field */
699   sc_CdbSystem   = scCdbSystem,   /* value is IN CDB's address space */
700   sc_RegImage    = scRegImage,    /* register value saved on stack */
701   sc_Info        = scInfo,        /* symbol contains debugger information */
702   sc_UserStruct  = scUserStruct,  /* addr in struct user for current process */
703   sc_SData       = scSData,       /* load time only small data */
704   sc_SBss        = scSBss,        /* load time only small common */
705   sc_RData       = scRData,       /* load time only read only data */
706   sc_Var         = scVar,         /* Var parameter (fortran,pascal) */
707   sc_Common      = scCommon,      /* common variable */
708   sc_SCommon     = scSCommon,     /* small common */
709   sc_VarRegister = scVarRegister, /* Var parameter in a register */
710   sc_Variant     = scVariant,     /* Variant record */
711   sc_SUndefined  = scSUndefined,  /* small undefined(external) data */
712   sc_Init        = scInit,        /* .init section symbol */
713   sc_Max         = scMax          /* Max storage class+1 */
714 } sc_t;
715
716 /* Redefinition of symbol type.  */
717
718 typedef enum st {
719   st_Nil        = stNil,        /* Nuthin' special */
720   st_Global     = stGlobal,     /* external symbol */
721   st_Static     = stStatic,     /* static */
722   st_Param      = stParam,      /* procedure argument */
723   st_Local      = stLocal,      /* local variable */
724   st_Label      = stLabel,      /* label */
725   st_Proc       = stProc,       /*     "      "  Procedure */
726   st_Block      = stBlock,      /* beginning of block */
727   st_End        = stEnd,        /* end (of anything) */
728   st_Member     = stMember,     /* member (of anything  - struct/union/enum */
729   st_Typedef    = stTypedef,    /* type definition */
730   st_File       = stFile,       /* file name */
731   st_RegReloc   = stRegReloc,   /* register relocation */
732   st_Forward    = stForward,    /* forwarding address */
733   st_StaticProc = stStaticProc, /* load time only static procs */
734   st_Constant   = stConstant,   /* const */
735   st_Str        = stStr,        /* string */
736   st_Number     = stNumber,     /* pure number (i.e. 4 NOR 2+2) */
737   st_Expr       = stExpr,       /* 2+2 vs. 4 */
738   st_Type       = stType,       /* post-coercion SER */
739   st_Max        = stMax         /* max type+1 */
740 } st_t;
741
742 /* Redefinition of type qualifiers.  */
743
744 typedef enum tq {
745   tq_Nil        = tqNil,        /* bt is what you see */
746   tq_Ptr        = tqPtr,        /* pointer */
747   tq_Proc       = tqProc,       /* procedure */
748   tq_Array      = tqArray,      /* duh */
749   tq_Far        = tqFar,        /* longer addressing - 8086/8 land */
750   tq_Vol        = tqVol,        /* volatile */
751   tq_Max        = tqMax         /* Max type qualifier+1 */
752 } tq_t;
753
754 /* Redefinition of basic types.  */
755
756 typedef enum bt {
757   bt_Nil        = btNil,        /* undefined */
758   bt_Adr        = btAdr,        /* address - integer same size as pointer */
759   bt_Char       = btChar,       /* character */
760   bt_UChar      = btUChar,      /* unsigned character */
761   bt_Short      = btShort,      /* short */
762   bt_UShort     = btUShort,     /* unsigned short */
763   bt_Int        = btInt,        /* int */
764   bt_UInt       = btUInt,       /* unsigned int */
765   bt_Long       = btLong,       /* long */
766   bt_ULong      = btULong,      /* unsigned long */
767   bt_Float      = btFloat,      /* float (real) */
768   bt_Double     = btDouble,     /* Double (real) */
769   bt_Struct     = btStruct,     /* Structure (Record) */
770   bt_Union      = btUnion,      /* Union (variant) */
771   bt_Enum       = btEnum,       /* Enumerated */
772   bt_Typedef    = btTypedef,    /* defined via a typedef, isymRef points */
773   bt_Range      = btRange,      /* subrange of int */
774   bt_Set        = btSet,        /* pascal sets */
775   bt_Complex    = btComplex,    /* fortran complex */
776   bt_DComplex   = btDComplex,   /* fortran double complex */
777   bt_Indirect   = btIndirect,   /* forward or unnamed typedef */
778   bt_FixedDec   = btFixedDec,   /* Fixed Decimal */
779   bt_FloatDec   = btFloatDec,   /* Float Decimal */
780   bt_String     = btString,     /* Varying Length Character String */
781   bt_Bit        = btBit,        /* Aligned Bit String */
782   bt_Picture    = btPicture,    /* Picture */
783
784 #ifdef btVoid
785   bt_Void       = btVoid,       /* Void */
786 #else
787 #define bt_Void bt_Nil
788 #endif
789
790   bt_Max        = btMax         /* Max basic type+1 */
791 } bt_t;
792
793 \f
794
795 /* Basic COFF storage classes.  */
796 enum coff_storage {
797   C_EFCN        = -1,
798   C_NULL        = 0,
799   C_AUTO        = 1,
800   C_EXT         = 2,
801   C_STAT        = 3,
802   C_REG         = 4,
803   C_EXTDEF      = 5,
804   C_LABEL       = 6,
805   C_ULABEL      = 7,
806   C_MOS         = 8,
807   C_ARG         = 9,
808   C_STRTAG      = 10,
809   C_MOU         = 11,
810   C_UNTAG       = 12,
811   C_TPDEF       = 13,
812   C_USTATIC     = 14,
813   C_ENTAG       = 15,
814   C_MOE         = 16,
815   C_REGPARM     = 17,
816   C_FIELD       = 18,
817   C_BLOCK       = 100,
818   C_FCN         = 101,
819   C_EOS         = 102,
820   C_FILE        = 103,
821   C_LINE        = 104,
822   C_ALIAS       = 105,
823   C_HIDDEN      = 106,
824   C_MAX         = 107
825 } coff_storage_t;
826
827 /* Regular COFF fundamental type.  */
828 typedef enum coff_type {
829   T_NULL        = 0,
830   T_ARG         = 1,
831   T_CHAR        = 2,
832   T_SHORT       = 3,
833   T_INT         = 4,
834   T_LONG        = 5,
835   T_FLOAT       = 6,
836   T_DOUBLE      = 7,
837   T_STRUCT      = 8,
838   T_UNION       = 9,
839   T_ENUM        = 10,
840   T_MOE         = 11,
841   T_UCHAR       = 12,
842   T_USHORT      = 13,
843   T_UINT        = 14,
844   T_ULONG       = 15,
845   T_MAX         = 16
846 } coff_type_t;
847
848 /* Regular COFF derived types.  */
849 typedef enum coff_dt {
850   DT_NON        = 0,
851   DT_PTR        = 1,
852   DT_FCN        = 2,
853   DT_ARY        = 3,
854   DT_MAX        = 4
855 } coff_dt_t;
856
857 #define N_BTMASK        017     /* bitmask to isolate basic type */
858 #define N_TMASK         003     /* bitmask to isolate derived type */
859 #define N_BT_SHIFT      4       /* # bits to shift past basic type */
860 #define N_TQ_SHIFT      2       /* # bits to shift derived types */
861 #define N_TQ            6       /* # of type qualifiers */
862
863 /* States for whether to hash type or not.  */
864 typedef enum hash_state {
865   hash_no       = 0,            /* don't hash type */
866   hash_yes      = 1,            /* ok to hash type, or use previous hash */
867   hash_record   = 2             /* ok to record hash, but don't use prev.  */
868 } hash_state_t;
869
870
871 /* Types of different sized allocation requests.  */
872 enum alloc_type {
873   alloc_type_none,              /* dummy value */
874   alloc_type_scope,             /* nested scopes linked list */
875   alloc_type_vlinks,            /* glue linking pages in varray */
876   alloc_type_shash,             /* string hash element */
877   alloc_type_thash,             /* type hash element */
878   alloc_type_tag,               /* struct/union/tag element */
879   alloc_type_forward,           /* element to hold unknown tag */
880   alloc_type_thead,             /* head of type hash list */
881   alloc_type_varray,            /* general varray allocation */
882   alloc_type_last               /* last+1 element for array bounds */
883 };
884
885 \f
886 #define WORD_ALIGN(x)  (((x) + (sizeof (long) - 1)) & ~ (sizeof (long) - 1))
887 #define DWORD_ALIGN(x) (((x) + 7) & ~7)
888
889
890 /* Structures to provide n-number of virtual arrays, each of which can
891    grow linearly, and which are written in the object file as sequential
892    pages.  On systems with a BSD malloc that define USE_MALLOC, the
893    MAX_CLUSTER_PAGES should be 1 less than a power of two, since malloc
894    adds its overhead, and rounds up to the next power of 2.  Pages are
895    linked together via a linked list.  */
896
897 #ifndef PAGE_SIZE
898 #define PAGE_SIZE 32768         /* size of varray pages */
899 #endif
900
901 #define PAGE_USIZE ((Size_t) PAGE_SIZE)
902
903
904 #ifndef MAX_CLUSTER_PAGES       /* # pages to get from system */
905 #ifndef USE_MALLOC              /* in one memory request */
906 #define MAX_CLUSTER_PAGES 64
907 #else
908 #define MAX_CLUSTER_PAGES 63
909 #endif
910 #endif
911
912
913 /* Linked list connecting separate page allocations.  */
914 typedef struct vlinks {
915   struct vlinks *prev;          /* previous set of pages */
916   struct vlinks *next;          /* next set of pages */
917   union  page   *datum;         /* start of page */
918   unsigned long  start_index;   /* starting index # of page */
919 } vlinks_t;
920
921
922 /* Virtual array header.  */
923 typedef struct varray {
924   vlinks_t      *first;                 /* first page link */
925   vlinks_t      *last;                  /* last page link */
926   unsigned long  num_allocated;         /* # objects allocated */
927   unsigned short object_size;           /* size in bytes of each object */
928   unsigned short objects_per_page;      /* # objects that can fit on a page */
929   unsigned short objects_last_page;     /* # objects allocated on last page */
930 } varray_t;
931
932 #ifndef MALLOC_CHECK
933 #define OBJECTS_PER_PAGE(type) (PAGE_SIZE / sizeof (type))
934 #else
935 #define OBJECTS_PER_PAGE(type) ((sizeof (type) > 1) ? 1 : PAGE_SIZE)
936 #endif
937
938 #define INIT_VARRAY(type) {     /* macro to initialize a varray */      \
939   (vlinks_t *) 0,               /* first */                             \
940   (vlinks_t *) 0,               /* last */                              \
941   0,                            /* num_allocated */                     \
942   sizeof (type),                /* object_size */                       \
943   OBJECTS_PER_PAGE (type),      /* objects_per_page */                  \
944   OBJECTS_PER_PAGE (type),      /* objects_last_page */                 \
945 }
946
947 #define INITIALIZE_VARRAY(x,type)                       \
948 do {                                                    \
949   (x)->object_size = sizeof (type);                     \
950   (x)->objects_per_page = OBJECTS_PER_PAGE (type);      \
951   (x)->objects_last_page = OBJECTS_PER_PAGE (type);     \
952 } while (0)
953
954 /* Master type for indexes within the symbol table.  */
955 typedef unsigned long symint_t;
956
957
958 /* Linked list support for nested scopes (file, block, structure, etc.).  */
959 typedef struct scope {
960   struct scope  *prev;          /* previous scope level */
961   struct scope  *free;          /* free list pointer */
962   SYMR          *lsym;          /* pointer to local symbol node */
963   symint_t       lnumber;       /* lsym index */
964   st_t           type;          /* type of the node */
965 } scope_t;
966
967
968 /* Forward reference list for tags referenced, but not yet defined.  */
969 typedef struct forward {
970   struct forward *next;         /* next forward reference */
971   struct forward *free;         /* free list pointer */
972   AUXU           *ifd_ptr;      /* pointer to store file index */
973   AUXU           *index_ptr;    /* pointer to store symbol index */
974   AUXU           *type_ptr;     /* pointer to munge type info */
975 } forward_t;
976
977
978 /* Linked list support for tags.  The first tag in the list is always
979    the current tag for that block.  */
980 typedef struct tag {
981   struct tag     *free;         /* free list pointer */
982   struct shash   *hash_ptr;     /* pointer to the hash table head */
983   struct tag     *same_name;    /* tag with same name in outer scope */
984   struct tag     *same_block;   /* next tag defined in the same block.  */
985   struct forward *forward_ref;  /* list of forward references */
986   bt_t            basic_type;   /* bt_Struct, bt_Union, or bt_Enum */
987   symint_t        ifd;          /* file # tag defined in */
988   symint_t        indx;         /* index within file's local symbols */
989 } tag_t;
990
991
992 /* Head of a block's linked list of tags.  */
993 typedef struct thead {
994   struct thead  *prev;          /* previous block */
995   struct thead  *free;          /* free list pointer */
996   struct tag    *first_tag;     /* first tag in block defined */
997 } thead_t;
998
999
1000 /* Union containing pointers to each the small structures which are freed up.  */
1001 typedef union small_free {
1002   scope_t       *f_scope;       /* scope structure */
1003   thead_t       *f_thead;       /* tag head structure */
1004   tag_t         *f_tag;         /* tag element structure */
1005   forward_t     *f_forward;     /* forward tag reference */
1006 } small_free_t;
1007
1008
1009 /* String hash table support.  The size of the hash table must fit
1010    within a page.  */
1011
1012 #ifndef SHASH_SIZE
1013 #define SHASH_SIZE 1009
1014 #endif
1015
1016 #define HASH_LEN_MAX ((1 << 12) - 1)    /* Max length we can store */
1017
1018 typedef struct shash {
1019   struct shash  *next;          /* next hash value */
1020   char          *string;        /* string we are hashing */
1021   symint_t       len;           /* string length */
1022   symint_t       indx;          /* index within string table */
1023   EXTR          *esym_ptr;      /* global symbol pointer */
1024   SYMR          *sym_ptr;       /* local symbol pointer */
1025   SYMR          *end_ptr;       /* symbol pointer to end block */
1026   tag_t         *tag_ptr;       /* tag pointer */
1027   PDR           *proc_ptr;      /* procedure descriptor pointer */
1028 } shash_t;
1029
1030
1031 /* Type hash table support.  The size of the hash table must fit
1032    within a page with the other extended file descriptor information.
1033    Because unique types which are hashed are fewer in number than
1034    strings, we use a smaller hash value.  */
1035
1036 #ifndef THASH_SIZE
1037 #define THASH_SIZE 113
1038 #endif
1039
1040 typedef struct thash {
1041   struct thash  *next;          /* next hash value */
1042   AUXU           type;          /* type we are hashing */
1043   symint_t       indx;          /* index within string table */
1044 } thash_t;
1045
1046
1047 /* Extended file descriptor that contains all of the support necessary
1048    to add things to each file separately.  */
1049 typedef struct efdr {
1050   FDR            fdr;           /* File header to be written out */
1051   FDR           *orig_fdr;      /* original file header */
1052   char          *name;          /* filename */
1053   int            name_len;      /* length of the filename */
1054   symint_t       void_type;     /* aux. pointer to 'void' type */
1055   symint_t       int_type;      /* aux. pointer to 'int' type */
1056   scope_t       *cur_scope;     /* current nested scopes */
1057   symint_t       file_index;    /* current file number */
1058   int            nested_scopes; /* # nested scopes */
1059   varray_t       strings;       /* local strings */
1060   varray_t       symbols;       /* local symbols */
1061   varray_t       procs;         /* procedures */
1062   varray_t       aux_syms;      /* auxiliary symbols */
1063   struct efdr   *next_file;     /* next file descriptor */
1064                                 /* string/type hash tables */
1065   shash_t      **shash_head;    /* string hash table */
1066   thash_t       *thash_head[THASH_SIZE];
1067 } efdr_t;
1068
1069 /* Pre-initialized extended file structure.  */
1070 static int init_file_initialized = 0;
1071 static efdr_t init_file;
1072
1073 static efdr_t *first_file;                      /* first file descriptor */
1074 static efdr_t **last_file_ptr = &first_file;    /* file descriptor tail */
1075
1076
1077 /* Union of various things that are held in pages.  */
1078 typedef union page {
1079   char          byte    [ PAGE_SIZE ];
1080   unsigned char ubyte   [ PAGE_SIZE ];
1081   efdr_t        file    [ PAGE_SIZE / sizeof (efdr_t)    ];
1082   FDR           ofile   [ PAGE_SIZE / sizeof (FDR)       ];
1083   PDR           proc    [ PAGE_SIZE / sizeof (PDR)       ];
1084   SYMR          sym     [ PAGE_SIZE / sizeof (SYMR)      ];
1085   EXTR          esym    [ PAGE_SIZE / sizeof (EXTR)      ];
1086   AUXU          aux     [ PAGE_SIZE / sizeof (AUXU)      ];
1087   DNR           dense   [ PAGE_SIZE / sizeof (DNR)       ];
1088   scope_t       scope   [ PAGE_SIZE / sizeof (scope_t)   ];
1089   vlinks_t      vlinks  [ PAGE_SIZE / sizeof (vlinks_t)  ];
1090   shash_t       shash   [ PAGE_SIZE / sizeof (shash_t)   ];
1091   thash_t       thash   [ PAGE_SIZE / sizeof (thash_t)   ];
1092   tag_t         tag     [ PAGE_SIZE / sizeof (tag_t)     ];
1093   forward_t     forward [ PAGE_SIZE / sizeof (forward_t) ];
1094   thead_t       thead   [ PAGE_SIZE / sizeof (thead_t)   ];
1095 } page_t;
1096
1097
1098 /* Structure holding allocation information for small sized structures.  */
1099 typedef struct alloc_info {
1100   const char    *alloc_name;    /* name of this allocation type (must be first) */
1101   page_t        *cur_page;      /* current page being allocated from */
1102   small_free_t   free_list;     /* current free list if any */
1103   int            unallocated;   /* number of elements unallocated on page */
1104   int            total_alloc;   /* total number of allocations */
1105   int            total_free;    /* total number of frees */
1106   int            total_pages;   /* total number of pages allocated */
1107 } alloc_info_t;
1108
1109 /* Type information collected together.  */
1110 typedef struct type_info {
1111   bt_t        basic_type;               /* basic type */
1112   coff_type_t orig_type;                /* original COFF-based type */
1113   int         num_tq;                   /* # type qualifiers */
1114   int         num_dims;                 /* # dimensions */
1115   int         num_sizes;                /* # sizes */
1116   int         extra_sizes;              /* # extra sizes not tied with dims */
1117   tag_t *     tag_ptr;                  /* tag pointer */
1118   int         bitfield;                 /* symbol is a bitfield */
1119   int         unknown_tag;              /* this is an unknown tag */
1120   tq_t        type_qualifiers[N_TQ];    /* type qualifiers (ptr, func, array)*/
1121   symint_t    dimensions     [N_TQ];    /* dimensions for each array */
1122   symint_t    sizes          [N_TQ+2];  /* sizes of each array slice + size of
1123                                            struct/union/enum + bitfield size */
1124 } type_info_t;
1125
1126 /* Pre-initialized type_info struct.  */
1127 static type_info_t type_info_init = {
1128   bt_Nil,                               /* basic type */
1129   T_NULL,                               /* original COFF-based type */
1130   0,                                    /* # type qualifiers */
1131   0,                                    /* # dimensions */
1132   0,                                    /* # sizes */
1133   0,                                    /* sizes not tied with dims */
1134   NULL,                                 /* ptr to tag */
1135   0,                                    /* bitfield */
1136   0,                                    /* unknown tag */
1137   {                                     /* type qualifiers */
1138     tq_Nil,
1139     tq_Nil,
1140     tq_Nil,
1141     tq_Nil,
1142     tq_Nil,
1143     tq_Nil,
1144   },
1145   {                                     /* dimensions */
1146     0,
1147     0,
1148     0,
1149     0,
1150     0,
1151     0
1152   },
1153   {                                     /* sizes */
1154     0,
1155     0,
1156     0,
1157     0,
1158     0,
1159     0,
1160     0,
1161     0,
1162   },
1163 };
1164
1165
1166 /* Global virtual arrays & hash table for external strings as well as
1167    for the tags table and global tables for file descriptors, and
1168    dense numbers.  */
1169
1170 static varray_t file_desc       = INIT_VARRAY (efdr_t);
1171 static varray_t dense_num       = INIT_VARRAY (DNR);
1172 static varray_t tag_strings     = INIT_VARRAY (char);
1173 static varray_t ext_strings     = INIT_VARRAY (char);
1174 static varray_t ext_symbols     = INIT_VARRAY (EXTR);
1175
1176 static shash_t  *orig_str_hash[SHASH_SIZE];
1177 static shash_t  *ext_str_hash [SHASH_SIZE];
1178 static shash_t  *tag_hash     [SHASH_SIZE];
1179
1180 /* Static types for int and void.  Also, remember the last function's
1181    type (which is set up when we encounter the declaration for the
1182    function, and used when the end block for the function is emitted.  */
1183
1184 static type_info_t int_type_info;
1185 static type_info_t void_type_info;
1186 static type_info_t last_func_type_info;
1187 static EXTR       *last_func_eptr;
1188
1189
1190 /* Convert COFF basic type to ECOFF basic type.  The T_NULL type
1191    really should use bt_Void, but this causes the current ecoff GDB to
1192    issue unsupported type messages, and the Ultrix 4.00 dbx (aka MIPS
1193    2.0) doesn't understand it, even though the compiler generates it.
1194    Maybe this will be fixed in 2.10 or 2.20 of the MIPS compiler
1195    suite, but for now go with what works.  */
1196
1197 static const bt_t map_coff_types[ (int) T_MAX ] = {
1198   bt_Nil,                       /* T_NULL */
1199   bt_Nil,                       /* T_ARG */
1200   bt_Char,                      /* T_CHAR */
1201   bt_Short,                     /* T_SHORT */
1202   bt_Int,                       /* T_INT */
1203   bt_Long,                      /* T_LONG */
1204   bt_Float,                     /* T_FLOAT */
1205   bt_Double,                    /* T_DOUBLE */
1206   bt_Struct,                    /* T_STRUCT */
1207   bt_Union,                     /* T_UNION */
1208   bt_Enum,                      /* T_ENUM */
1209   bt_Enum,                      /* T_MOE */
1210   bt_UChar,                     /* T_UCHAR */
1211   bt_UShort,                    /* T_USHORT */
1212   bt_UInt,                      /* T_UINT */
1213   bt_ULong                      /* T_ULONG */
1214 };
1215
1216 /* Convert COFF storage class to ECOFF storage class.  */
1217 static const sc_t map_coff_storage[ (int) C_MAX ] = {
1218   sc_Nil,                       /*   0: C_NULL */
1219   sc_Abs,                       /*   1: C_AUTO    auto var */
1220   sc_Undefined,                 /*   2: C_EXT     external */
1221   sc_Data,                      /*   3: C_STAT    static */
1222   sc_Register,                  /*   4: C_REG     register */
1223   sc_Undefined,                 /*   5: C_EXTDEF  ??? */
1224   sc_Text,                      /*   6: C_LABEL   label */
1225   sc_Text,                      /*   7: C_ULABEL  user label */
1226   sc_Info,                      /*   8: C_MOS     member of struct */
1227   sc_Abs,                       /*   9: C_ARG     argument */
1228   sc_Info,                      /*  10: C_STRTAG  struct tag */
1229   sc_Info,                      /*  11: C_MOU     member of union */
1230   sc_Info,                      /*  12: C_UNTAG   union tag */
1231   sc_Info,                      /*  13: C_TPDEF   typedef */
1232   sc_Data,                      /*  14: C_USTATIC ??? */
1233   sc_Info,                      /*  15: C_ENTAG   enum tag */
1234   sc_Info,                      /*  16: C_MOE     member of enum */
1235   sc_Register,                  /*  17: C_REGPARM register parameter */
1236   sc_Bits,                      /*  18; C_FIELD   bitfield */
1237   sc_Nil,                       /*  19 */
1238   sc_Nil,                       /*  20 */
1239   sc_Nil,                       /*  21 */
1240   sc_Nil,                       /*  22 */
1241   sc_Nil,                       /*  23 */
1242   sc_Nil,                       /*  24 */
1243   sc_Nil,                       /*  25 */
1244   sc_Nil,                       /*  26 */
1245   sc_Nil,                       /*  27 */
1246   sc_Nil,                       /*  28 */
1247   sc_Nil,                       /*  29 */
1248   sc_Nil,                       /*  30 */
1249   sc_Nil,                       /*  31 */
1250   sc_Nil,                       /*  32 */
1251   sc_Nil,                       /*  33 */
1252   sc_Nil,                       /*  34 */
1253   sc_Nil,                       /*  35 */
1254   sc_Nil,                       /*  36 */
1255   sc_Nil,                       /*  37 */
1256   sc_Nil,                       /*  38 */
1257   sc_Nil,                       /*  39 */
1258   sc_Nil,                       /*  40 */
1259   sc_Nil,                       /*  41 */
1260   sc_Nil,                       /*  42 */
1261   sc_Nil,                       /*  43 */
1262   sc_Nil,                       /*  44 */
1263   sc_Nil,                       /*  45 */
1264   sc_Nil,                       /*  46 */
1265   sc_Nil,                       /*  47 */
1266   sc_Nil,                       /*  48 */
1267   sc_Nil,                       /*  49 */
1268   sc_Nil,                       /*  50 */
1269   sc_Nil,                       /*  51 */
1270   sc_Nil,                       /*  52 */
1271   sc_Nil,                       /*  53 */
1272   sc_Nil,                       /*  54 */
1273   sc_Nil,                       /*  55 */
1274   sc_Nil,                       /*  56 */
1275   sc_Nil,                       /*  57 */
1276   sc_Nil,                       /*  58 */
1277   sc_Nil,                       /*  59 */
1278   sc_Nil,                       /*  60 */
1279   sc_Nil,                       /*  61 */
1280   sc_Nil,                       /*  62 */
1281   sc_Nil,                       /*  63 */
1282   sc_Nil,                       /*  64 */
1283   sc_Nil,                       /*  65 */
1284   sc_Nil,                       /*  66 */
1285   sc_Nil,                       /*  67 */
1286   sc_Nil,                       /*  68 */
1287   sc_Nil,                       /*  69 */
1288   sc_Nil,                       /*  70 */
1289   sc_Nil,                       /*  71 */
1290   sc_Nil,                       /*  72 */
1291   sc_Nil,                       /*  73 */
1292   sc_Nil,                       /*  74 */
1293   sc_Nil,                       /*  75 */
1294   sc_Nil,                       /*  76 */
1295   sc_Nil,                       /*  77 */
1296   sc_Nil,                       /*  78 */
1297   sc_Nil,                       /*  79 */
1298   sc_Nil,                       /*  80 */
1299   sc_Nil,                       /*  81 */
1300   sc_Nil,                       /*  82 */
1301   sc_Nil,                       /*  83 */
1302   sc_Nil,                       /*  84 */
1303   sc_Nil,                       /*  85 */
1304   sc_Nil,                       /*  86 */
1305   sc_Nil,                       /*  87 */
1306   sc_Nil,                       /*  88 */
1307   sc_Nil,                       /*  89 */
1308   sc_Nil,                       /*  90 */
1309   sc_Nil,                       /*  91 */
1310   sc_Nil,                       /*  92 */
1311   sc_Nil,                       /*  93 */
1312   sc_Nil,                       /*  94 */
1313   sc_Nil,                       /*  95 */
1314   sc_Nil,                       /*  96 */
1315   sc_Nil,                       /*  97 */
1316   sc_Nil,                       /*  98 */
1317   sc_Nil,                       /*  99 */
1318   sc_Text,                      /* 100: C_BLOCK  block start/end */
1319   sc_Text,                      /* 101: C_FCN    function start/end */
1320   sc_Info,                      /* 102: C_EOS    end of struct/union/enum */
1321   sc_Nil,                       /* 103: C_FILE   file start */
1322   sc_Nil,                       /* 104: C_LINE   line number */
1323   sc_Nil,                       /* 105: C_ALIAS  combined type info */
1324   sc_Nil,                       /* 106: C_HIDDEN ??? */
1325 };
1326
1327 /* Convert COFF storage class to ECOFF symbol type.  */
1328 static const st_t map_coff_sym_type[ (int) C_MAX ] = {
1329   st_Nil,                       /*   0: C_NULL */
1330   st_Local,                     /*   1: C_AUTO    auto var */
1331   st_Global,                    /*   2: C_EXT     external */
1332   st_Static,                    /*   3: C_STAT    static */
1333   st_Local,                     /*   4: C_REG     register */
1334   st_Global,                    /*   5: C_EXTDEF  ??? */
1335   st_Label,                     /*   6: C_LABEL   label */
1336   st_Label,                     /*   7: C_ULABEL  user label */
1337   st_Member,                    /*   8: C_MOS     member of struct */
1338   st_Param,                     /*   9: C_ARG     argument */
1339   st_Block,                     /*  10: C_STRTAG  struct tag */
1340   st_Member,                    /*  11: C_MOU     member of union */
1341   st_Block,                     /*  12: C_UNTAG   union tag */
1342   st_Typedef,                   /*  13: C_TPDEF   typedef */
1343   st_Static,                    /*  14: C_USTATIC ??? */
1344   st_Block,                     /*  15: C_ENTAG   enum tag */
1345   st_Member,                    /*  16: C_MOE     member of enum */
1346   st_Param,                     /*  17: C_REGPARM register parameter */
1347   st_Member,                    /*  18; C_FIELD   bitfield */
1348   st_Nil,                       /*  19 */
1349   st_Nil,                       /*  20 */
1350   st_Nil,                       /*  21 */
1351   st_Nil,                       /*  22 */
1352   st_Nil,                       /*  23 */
1353   st_Nil,                       /*  24 */
1354   st_Nil,                       /*  25 */
1355   st_Nil,                       /*  26 */
1356   st_Nil,                       /*  27 */
1357   st_Nil,                       /*  28 */
1358   st_Nil,                       /*  29 */
1359   st_Nil,                       /*  30 */
1360   st_Nil,                       /*  31 */
1361   st_Nil,                       /*  32 */
1362   st_Nil,                       /*  33 */
1363   st_Nil,                       /*  34 */
1364   st_Nil,                       /*  35 */
1365   st_Nil,                       /*  36 */
1366   st_Nil,                       /*  37 */
1367   st_Nil,                       /*  38 */
1368   st_Nil,                       /*  39 */
1369   st_Nil,                       /*  40 */
1370   st_Nil,                       /*  41 */
1371   st_Nil,                       /*  42 */
1372   st_Nil,                       /*  43 */
1373   st_Nil,                       /*  44 */
1374   st_Nil,                       /*  45 */
1375   st_Nil,                       /*  46 */
1376   st_Nil,                       /*  47 */
1377   st_Nil,                       /*  48 */
1378   st_Nil,                       /*  49 */
1379   st_Nil,                       /*  50 */
1380   st_Nil,                       /*  51 */
1381   st_Nil,                       /*  52 */
1382   st_Nil,                       /*  53 */
1383   st_Nil,                       /*  54 */
1384   st_Nil,                       /*  55 */
1385   st_Nil,                       /*  56 */
1386   st_Nil,                       /*  57 */
1387   st_Nil,                       /*  58 */
1388   st_Nil,                       /*  59 */
1389   st_Nil,                       /*  60 */
1390   st_Nil,                       /*  61 */
1391   st_Nil,                       /*  62 */
1392   st_Nil,                       /*  63 */
1393   st_Nil,                       /*  64 */
1394   st_Nil,                       /*  65 */
1395   st_Nil,                       /*  66 */
1396   st_Nil,                       /*  67 */
1397   st_Nil,                       /*  68 */
1398   st_Nil,                       /*  69 */
1399   st_Nil,                       /*  70 */
1400   st_Nil,                       /*  71 */
1401   st_Nil,                       /*  72 */
1402   st_Nil,                       /*  73 */
1403   st_Nil,                       /*  74 */
1404   st_Nil,                       /*  75 */
1405   st_Nil,                       /*  76 */
1406   st_Nil,                       /*  77 */
1407   st_Nil,                       /*  78 */
1408   st_Nil,                       /*  79 */
1409   st_Nil,                       /*  80 */
1410   st_Nil,                       /*  81 */
1411   st_Nil,                       /*  82 */
1412   st_Nil,                       /*  83 */
1413   st_Nil,                       /*  84 */
1414   st_Nil,                       /*  85 */
1415   st_Nil,                       /*  86 */
1416   st_Nil,                       /*  87 */
1417   st_Nil,                       /*  88 */
1418   st_Nil,                       /*  89 */
1419   st_Nil,                       /*  90 */
1420   st_Nil,                       /*  91 */
1421   st_Nil,                       /*  92 */
1422   st_Nil,                       /*  93 */
1423   st_Nil,                       /*  94 */
1424   st_Nil,                       /*  95 */
1425   st_Nil,                       /*  96 */
1426   st_Nil,                       /*  97 */
1427   st_Nil,                       /*  98 */
1428   st_Nil,                       /*  99 */
1429   st_Block,                     /* 100: C_BLOCK  block start/end */
1430   st_Proc,                      /* 101: C_FCN    function start/end */
1431   st_End,                       /* 102: C_EOS    end of struct/union/enum */
1432   st_File,                      /* 103: C_FILE   file start */
1433   st_Nil,                       /* 104: C_LINE   line number */
1434   st_Nil,                       /* 105: C_ALIAS  combined type info */
1435   st_Nil,                       /* 106: C_HIDDEN ??? */
1436 };
1437
1438 /* Map COFF derived types to ECOFF type qualifiers.  */
1439 static const tq_t map_coff_derived_type[ (int) DT_MAX ] = {
1440   tq_Nil,                       /* 0: DT_NON    no more qualifiers */
1441   tq_Ptr,                       /* 1: DT_PTR    pointer */
1442   tq_Proc,                      /* 2: DT_FCN    function */
1443   tq_Array,                     /* 3: DT_ARY    array */
1444 };
1445
1446
1447 /* Keep track of different sized allocation requests.  */
1448 static alloc_info_t alloc_counts[ (int) alloc_type_last ];
1449
1450 \f
1451 /* Pointers and such to the original symbol table that is read in.  */
1452 static struct filehdr orig_file_header;         /* global object file header */
1453
1454 static HDRR      orig_sym_hdr;                  /* symbolic header on input */
1455 static char     *orig_linenum;                  /* line numbers */
1456 static DNR      *orig_dense;                    /* dense numbers */
1457 static PDR      *orig_procs;                    /* procedures */
1458 static SYMR     *orig_local_syms;               /* local symbols */
1459 static OPTR     *orig_opt_syms;                 /* optimization symbols */
1460 static AUXU     *orig_aux_syms;                 /* auxiliary symbols */
1461 static char     *orig_local_strs;               /* local strings */
1462 static char     *orig_ext_strs;                 /* external strings */
1463 static FDR      *orig_files;                    /* file descriptors */
1464 static symint_t *orig_rfds;                     /* relative file desc's */
1465 static EXTR     *orig_ext_syms;                 /* external symbols */
1466
1467 /* Macros to convert an index into a given object within the original
1468    symbol table.  */
1469 #define CHECK(num,max,str) \
1470   (((unsigned long) num > (unsigned long) max) ? out_of_bounds (num, max, str, __LINE__) : 0)
1471
1472 #define ORIG_LINENUM(indx)      (CHECK ((indx), orig_sym_hdr.cbLine,    "line#"), (indx) + orig_linenum)
1473 #define ORIG_DENSE(indx)        (CHECK ((indx), orig_sym_hdr.idnMax,    "dense"), (indx) + orig_dense)
1474 #define ORIG_PROCS(indx)        (CHECK ((indx), orig_sym_hdr.ipdMax,    "procs"), (indx) + orig_procs)
1475 #define ORIG_FILES(indx)        (CHECK ((indx), orig_sym_hdr.ifdMax,    "funcs"), (indx) + orig_files)
1476 #define ORIG_LSYMS(indx)        (CHECK ((indx), orig_sym_hdr.isymMax,   "lsyms"), (indx) + orig_local_syms)
1477 #define ORIG_LSTRS(indx)        (CHECK ((indx), orig_sym_hdr.issMax,    "lstrs"), (indx) + orig_local_strs)
1478 #define ORIG_ESYMS(indx)        (CHECK ((indx), orig_sym_hdr.iextMax,   "esyms"), (indx) + orig_ext_syms)
1479 #define ORIG_ESTRS(indx)        (CHECK ((indx), orig_sym_hdr.issExtMax, "estrs"), (indx) + orig_ext_strs)
1480 #define ORIG_OPT(indx)          (CHECK ((indx), orig_sym_hdr.ioptMax,   "opt"),   (indx) + orig_opt_syms)
1481 #define ORIG_AUX(indx)          (CHECK ((indx), orig_sym_hdr.iauxMax,   "aux"),   (indx) + orig_aux_syms)
1482 #define ORIG_RFDS(indx)         (CHECK ((indx), orig_sym_hdr.crfd,      "rfds"),  (indx) + orig_rfds)
1483
1484 /* Various other statics.  */
1485 static HDRR     symbolic_header;                /* symbolic header */
1486 static efdr_t  *cur_file_ptr    = (efdr_t *) 0; /* current file desc. header */
1487 static PDR     *cur_proc_ptr    = (PDR *) 0;    /* current procedure header */
1488 static SYMR    *cur_oproc_begin = (SYMR *) 0;   /* original proc. sym begin info */
1489 static SYMR    *cur_oproc_end   = (SYMR *) 0;   /* original proc. sym end info */
1490 static PDR     *cur_oproc_ptr   = (PDR *) 0;    /* current original procedure*/
1491 static thead_t *cur_tag_head    = (thead_t *) 0;/* current tag head */
1492 static unsigned long file_offset        = 0;    /* current file offset */
1493 static unsigned long max_file_offset    = 0;    /* maximum file offset */
1494 static FILE    *object_stream   = (FILE *) 0;   /* file desc. to output .o */
1495 static FILE    *obj_in_stream   = (FILE *) 0;   /* file desc. to input .o */
1496 static char    *progname        = (char *) 0;   /* program name for errors */
1497 static const char *input_name   = "stdin";      /* name of input file */
1498 static char    *object_name     = (char *) 0;   /* tmp. name of object file */
1499 static char    *obj_in_name     = (char *) 0;   /* name of input object file */
1500 static char    *cur_line_start  = (char *) 0;   /* current line read in */
1501 static char    *cur_line_ptr    = (char *) 0;   /* ptr within current line */
1502 static unsigned cur_line_nbytes = 0;            /* # bytes for current line */
1503 static unsigned cur_line_alloc  = 0;            /* # bytes total in buffer */
1504 static long     line_number     = 0;            /* current input line number */
1505 static int      debug           = 0;            /* trace functions */
1506 static int      version         = 0;            /* print version # */
1507 static int      verbose         = 0;
1508 static int      had_errors      = 0;            /* != 0 if errors were found */
1509 static int      rename_output   = 0;            /* != 0 if rename output file*/
1510 static int      delete_input    = 0;            /* != 0 if delete input after done */
1511 static int      stabs_seen      = 0;            /* != 0 if stabs have been seen */
1512
1513
1514 /* Pseudo symbol to use when putting stabs into the symbol table.  */
1515 #ifndef STABS_SYMBOL
1516 #define STABS_SYMBOL "@stabs"
1517 #endif
1518
1519 static const char stabs_symbol[] = STABS_SYMBOL;
1520
1521 \f
1522 /* Forward reference for functions.  See the definition for more details.  */
1523
1524 #ifndef STATIC
1525 #define STATIC static
1526 #endif
1527
1528 STATIC int out_of_bounds (symint_t, symint_t, const char *, int);
1529 STATIC shash_t *hash_string (const char *, Ptrdiff_t, shash_t **, symint_t *);
1530 STATIC symint_t add_string (varray_t *, shash_t **, const char *, const char *,
1531                             shash_t **);
1532 STATIC symint_t add_local_symbol (const char *, const char *, st_t, sc_t,
1533                                   symint_t, symint_t);
1534 STATIC symint_t add_ext_symbol (EXTR *, int);
1535 STATIC symint_t add_aux_sym_symint (symint_t);
1536 STATIC symint_t add_aux_sym_rndx (int, symint_t);
1537 STATIC symint_t add_aux_sym_tir (type_info_t *, hash_state_t, thash_t **);
1538 STATIC tag_t *  get_tag (const char *, const char *, symint_t, bt_t);
1539 STATIC void add_unknown_tag (tag_t *);
1540 STATIC void add_procedure (const char *, const char *);
1541 STATIC void initialize_init_file (void);
1542 STATIC void add_file (const char *, const char *);
1543 STATIC void add_bytes (varray_t *, char *, Size_t);
1544 STATIC void add_varray_page (varray_t *);
1545 STATIC void update_headers (void);
1546 STATIC void write_varray (varray_t *, off_t, const char *);
1547 STATIC void write_object (void);
1548 STATIC const char *st_to_string (st_t);
1549 STATIC const char *sc_to_string (sc_t);
1550 STATIC char *read_line (void);
1551 STATIC void parse_input (void);
1552 STATIC void mark_stabs (const char *);
1553 STATIC void parse_begin (const char *);
1554 STATIC void parse_bend (const char *);
1555 STATIC void parse_def (const char *);
1556 STATIC void parse_end (const char *);
1557 STATIC void parse_ent (const char *);
1558 STATIC void parse_file (const char *);
1559 STATIC void parse_stabs_common (const char *, const char *, const char *);
1560 STATIC void parse_stabs (const char *);
1561 STATIC void parse_stabn (const char *);
1562 STATIC page_t  *read_seek (Size_t, off_t, const char *);
1563 STATIC void copy_object (void);
1564
1565 STATIC void catch_signal (int) ATTRIBUTE_NORETURN;
1566 STATIC page_t *allocate_page (void);
1567 STATIC page_t *allocate_multiple_pages (Size_t);
1568 STATIC void     free_multiple_pages (page_t *, Size_t);
1569
1570 #ifndef MALLOC_CHECK
1571 STATIC page_t  *allocate_cluster (Size_t);
1572 #endif
1573
1574 STATIC forward_t *allocate_forward (void);
1575 STATIC scope_t *allocate_scope (void);
1576 STATIC shash_t *allocate_shash (void);
1577 STATIC tag_t  *allocate_tag (void);
1578 STATIC thash_t *allocate_thash (void);
1579 STATIC thead_t *allocate_thead (void);
1580 STATIC vlinks_t *allocate_vlinks (void);
1581
1582 STATIC void free_forward (forward_t *);
1583 STATIC void free_scope (scope_t *);
1584 STATIC void free_tag (tag_t *);
1585 STATIC void free_thead (thead_t *);
1586
1587 extern char *optarg;
1588 extern int   optind;
1589 extern int   opterr;
1590 \f
1591 /* List of assembler pseudo ops and beginning sequences that need
1592    special actions.  Someday, this should be a hash table, and such,
1593    but for now a linear list of names and calls to memcmp will
1594    do......  */
1595
1596 typedef struct _pseudo_ops {
1597   const char *const name;                       /* pseudo-op in ascii */
1598   const int len;                                /* length of name to compare */
1599   void (*const func) (const char *);    /* function to handle line */
1600 } pseudo_ops_t;
1601
1602 static const pseudo_ops_t pseudo_ops[] = {
1603   { "#.def",    sizeof("#.def")-1,      parse_def },
1604   { "#.begin",  sizeof("#.begin")-1,    parse_begin },
1605   { "#.bend",   sizeof("#.bend")-1,     parse_bend },
1606   { ".end",     sizeof(".end")-1,       parse_end },
1607   { ".ent",     sizeof(".ent")-1,       parse_ent },
1608   { ".file",    sizeof(".file")-1,      parse_file },
1609   { "#.stabs",  sizeof("#.stabs")-1,    parse_stabs },
1610   { "#.stabn",  sizeof("#.stabn")-1,    parse_stabn },
1611   { ".stabs",   sizeof(".stabs")-1,     parse_stabs },
1612   { ".stabn",   sizeof(".stabn")-1,     parse_stabn },
1613   { "#@stabs",  sizeof("#@stabs")-1,    mark_stabs },
1614 };
1615
1616 \f
1617 /* Command line options for getopt_long.  */
1618
1619 static const struct option options[] =
1620 {
1621   { "version", 0, 0, 'V' },
1622   { "verbose", 0, 0, 'v' },
1623   { 0, 0, 0, 0 }
1624 };
1625 \f
1626 /* Add a page to a varray object.  */
1627
1628 STATIC void
1629 add_varray_page (varray_t *vp)
1630 {
1631   vlinks_t *new_links = allocate_vlinks ();
1632
1633 #ifdef MALLOC_CHECK
1634   if (vp->object_size > 1)
1635     new_links->datum = xcalloc (1, vp->object_size);
1636   else
1637 #endif
1638     new_links->datum = allocate_page ();
1639
1640   alloc_counts[ (int) alloc_type_varray ].total_alloc++;
1641   alloc_counts[ (int) alloc_type_varray ].total_pages++;
1642
1643   new_links->start_index = vp->num_allocated;
1644   vp->objects_last_page = 0;
1645
1646   if (vp->first == (vlinks_t *) 0)              /* first allocation? */
1647     vp->first = vp->last = new_links;
1648   else
1649     {                                           /* 2nd or greater allocation */
1650       new_links->prev = vp->last;
1651       vp->last->next = new_links;
1652       vp->last = new_links;
1653     }
1654 }
1655
1656 \f
1657 /* Compute hash code (from tree.c) */
1658
1659 #define HASHBITS 30
1660
1661 STATIC shash_t *
1662 hash_string (const char *text, Ptrdiff_t hash_len, shash_t **hash_tbl,
1663              symint_t *ret_hash_index)
1664 {
1665   unsigned long hi;
1666   Ptrdiff_t i;
1667   shash_t *ptr;
1668   int first_ch = *text;
1669
1670   hi = hash_len;
1671   for (i = 0; i < hash_len; i++)
1672     hi = ((hi & 0x003fffff) * 613) + (text[i] & 0xff);
1673
1674   hi &= (1 << HASHBITS) - 1;
1675   hi %= SHASH_SIZE;
1676
1677   if (ret_hash_index != (symint_t *) 0)
1678     *ret_hash_index = hi;
1679
1680   for (ptr = hash_tbl[hi]; ptr != (shash_t *) 0; ptr = ptr->next)
1681     if ((symint_t) hash_len == ptr->len
1682         && first_ch == ptr->string[0]
1683         && memcmp (text, ptr->string, hash_len) == 0)
1684       break;
1685
1686   return ptr;
1687 }
1688
1689 \f
1690 /* Add a string (and null pad) to one of the string tables.  A
1691    consequence of hashing strings, is that we don't let strings cross
1692    page boundaries.  The extra nulls will be ignored.  VP is a string
1693    virtual array, HASH_TBL a pointer to the hash table, the string
1694    starts at START and the position one byte after the string is given
1695    with END_P1, the resulting hash pointer is returned in RET_HASH.  */
1696
1697 STATIC symint_t
1698 add_string (varray_t *vp, shash_t **hash_tbl, const char *start,
1699             const char *end_p1, shash_t **ret_hash)
1700 {
1701   Ptrdiff_t len = end_p1 - start;
1702   shash_t *hash_ptr;
1703   symint_t hi;
1704
1705   if (len >= (Ptrdiff_t) PAGE_USIZE)
1706     fatal ("string too big (%ld bytes)", (long) len);
1707
1708   hash_ptr = hash_string (start, len, hash_tbl, &hi);
1709   if (hash_ptr == (shash_t *) 0)
1710     {
1711       char *p;
1712
1713       if (vp->objects_last_page + len >= (long) PAGE_USIZE)
1714         {
1715           vp->num_allocated
1716             = ((vp->num_allocated + PAGE_USIZE - 1) / PAGE_USIZE) * PAGE_USIZE;
1717           add_varray_page (vp);
1718         }
1719
1720       hash_ptr = allocate_shash ();
1721       hash_ptr->next = hash_tbl[hi];
1722       hash_tbl[hi] = hash_ptr;
1723
1724       hash_ptr->len = len;
1725       hash_ptr->indx = vp->num_allocated;
1726       hash_ptr->string = p = & vp->last->datum->byte[ vp->objects_last_page ];
1727
1728       vp->objects_last_page += len+1;
1729       vp->num_allocated += len+1;
1730
1731       while (len-- > 0)
1732         *p++ = *start++;
1733
1734       *p = '\0';
1735     }
1736
1737   if (ret_hash != (shash_t **) 0)
1738     *ret_hash = hash_ptr;
1739
1740   return hash_ptr->indx;
1741 }
1742
1743 \f
1744 /* Add a local symbol.  The symbol string starts at STR_START and the
1745    first byte after it is marked by STR_END_P1.  The symbol has type
1746    TYPE and storage class STORAGE and value VALUE.  INDX is an index
1747    to local/aux. symbols.  */
1748
1749 STATIC symint_t
1750 add_local_symbol (const char *str_start, const char *str_end_p1, st_t type,
1751                   sc_t storage,  symint_t value, symint_t indx)
1752 {
1753   symint_t ret;
1754   SYMR *psym;
1755   scope_t *pscope;
1756   thead_t *ptag_head;
1757   tag_t *ptag;
1758   tag_t *ptag_next;
1759   varray_t *vp = &cur_file_ptr->symbols;
1760   int scope_delta = 0;
1761   shash_t *hash_ptr = (shash_t *) 0;
1762
1763   if (vp->objects_last_page == vp->objects_per_page)
1764     add_varray_page (vp);
1765
1766   psym = &vp->last->datum->sym[ vp->objects_last_page++ ];
1767
1768   psym->value = value;
1769   psym->st = (unsigned) type;
1770   psym->sc = (unsigned) storage;
1771   psym->index = indx;
1772   psym->iss = (str_start == (const char *) 0)
1773                 ? 0
1774                 : add_string (&cur_file_ptr->strings,
1775                               &cur_file_ptr->shash_head[0],
1776                               str_start,
1777                               str_end_p1,
1778                               &hash_ptr);
1779
1780   ret = vp->num_allocated++;
1781
1782   if (MIPS_IS_STAB (psym))
1783     return ret;
1784
1785   /* Save the symbol within the hash table if this is a static
1786      item, and it has a name.  */
1787   if (hash_ptr != (shash_t *) 0
1788       && (type == st_Global || type == st_Static || type == st_Label
1789           || type == st_Proc || type == st_StaticProc))
1790     hash_ptr->sym_ptr = psym;
1791
1792   /* push or pop a scope if appropriate.  */
1793   switch (type)
1794     {
1795     default:
1796       break;
1797
1798     case st_File:                       /* beginning of file */
1799     case st_Proc:                       /* procedure */
1800     case st_StaticProc:                 /* static procedure */
1801     case st_Block:                      /* begin scope */
1802       pscope = allocate_scope ();
1803       pscope->prev = cur_file_ptr->cur_scope;
1804       pscope->lsym = psym;
1805       pscope->lnumber = ret;
1806       pscope->type = type;
1807       cur_file_ptr->cur_scope = pscope;
1808
1809       if (type != st_File)
1810         scope_delta = 1;
1811
1812       /* For every block type except file, struct, union, or
1813          enumeration blocks, push a level on the tag stack.  We omit
1814          file types, so that tags can span file boundaries.  */
1815       if (type != st_File && storage != sc_Info)
1816         {
1817           ptag_head = allocate_thead ();
1818           ptag_head->first_tag = 0;
1819           ptag_head->prev = cur_tag_head;
1820           cur_tag_head = ptag_head;
1821         }
1822       break;
1823
1824     case st_End:
1825       pscope = cur_file_ptr->cur_scope;
1826       if (pscope == (scope_t *) 0)
1827         error ("internal error, too many st_End's");
1828
1829       else
1830         {
1831           st_t begin_type = (st_t) pscope->lsym->st;
1832
1833           if (begin_type != st_File)
1834             scope_delta = -1;
1835
1836           /* Except for file, structure, union, or enumeration end
1837              blocks remove all tags created within this scope.  */
1838           if (begin_type != st_File && storage != sc_Info)
1839             {
1840               ptag_head = cur_tag_head;
1841               cur_tag_head = ptag_head->prev;
1842
1843               for (ptag = ptag_head->first_tag;
1844                    ptag != (tag_t *) 0;
1845                    ptag = ptag_next)
1846                 {
1847                   if (ptag->forward_ref != (forward_t *) 0)
1848                     add_unknown_tag (ptag);
1849
1850                   ptag_next = ptag->same_block;
1851                   ptag->hash_ptr->tag_ptr = ptag->same_name;
1852                   free_tag (ptag);
1853                 }
1854
1855               free_thead (ptag_head);
1856             }
1857
1858           cur_file_ptr->cur_scope = pscope->prev;
1859           psym->index = pscope->lnumber;        /* blk end gets begin sym # */
1860
1861           if (storage != sc_Info)
1862             psym->iss = pscope->lsym->iss;      /* blk end gets same name */
1863
1864           if (begin_type == st_File || begin_type == st_Block)
1865             pscope->lsym->index = ret+1;        /* block begin gets next sym # */
1866
1867           /* Functions push two or more aux words as follows:
1868              1st word: index+1 of the end symbol
1869              2nd word: type of the function (plus any aux words needed).
1870              Also, tie the external pointer back to the function begin symbol.  */
1871           else
1872             {
1873               symint_t type;
1874               pscope->lsym->index = add_aux_sym_symint (ret+1);
1875               type = add_aux_sym_tir (&last_func_type_info,
1876                                       hash_no,
1877                                       &cur_file_ptr->thash_head[0]);
1878               if (last_func_eptr)
1879                 {
1880                   last_func_eptr->ifd = cur_file_ptr->file_index;
1881
1882                   /* The index for an external st_Proc symbol is the index
1883                      of the st_Proc symbol in the local symbol table.  */
1884                   last_func_eptr->asym.index = psym->index;
1885                 }
1886             }
1887
1888           free_scope (pscope);
1889         }
1890     }
1891
1892   cur_file_ptr->nested_scopes += scope_delta;
1893
1894   if (debug && type != st_File
1895       && (debug > 2 || type == st_Block || type == st_End
1896           || type == st_Proc || type == st_StaticProc))
1897     {
1898       const char *sc_str = sc_to_string (storage);
1899       const char *st_str = st_to_string (type);
1900       int depth = cur_file_ptr->nested_scopes + (scope_delta < 0);
1901
1902       fprintf (stderr,
1903                "\tlsym\tv= %10ld, depth= %2d, sc= %-12s",
1904                value, depth, sc_str);
1905
1906       if (str_start && str_end_p1 - str_start > 0)
1907         fprintf (stderr, " st= %-11s name= %.*s\n",
1908                  st_str, (int) (str_end_p1 - str_start), str_start);
1909       else
1910         {
1911           Size_t len = strlen (st_str);
1912           fprintf (stderr, " st= %.*s\n", (int) (len-1), st_str);
1913         }
1914     }
1915
1916   return ret;
1917 }
1918
1919 \f
1920 /* Add an external symbol with symbol pointer ESYM and file index
1921    IFD.  */
1922
1923 STATIC symint_t
1924 add_ext_symbol (EXTR *esym, int ifd)
1925 {
1926   const char *str_start;                /* first byte in string */
1927   const char *str_end_p1;               /* first byte after string */
1928   EXTR *psym;
1929   varray_t *vp = &ext_symbols;
1930   shash_t *hash_ptr = (shash_t *) 0;
1931
1932   str_start = ORIG_ESTRS (esym->asym.iss);
1933   str_end_p1 = str_start + strlen (str_start);
1934
1935   if (debug > 1)
1936     {
1937       long value = esym->asym.value;
1938       const char *sc_str = sc_to_string ((sc_t) esym->asym.sc);
1939       const char *st_str = st_to_string ((st_t) esym->asym.st);
1940
1941       fprintf (stderr,
1942                "\tesym\tv= %10ld, ifd= %2d, sc= %-12s",
1943                value, ifd, sc_str);
1944
1945       if (str_start && str_end_p1 - str_start > 0)
1946         fprintf (stderr, " st= %-11s name= %.*s\n",
1947                  st_str, (int) (str_end_p1 - str_start), str_start);
1948       else
1949         fprintf (stderr, " st= %s\n", st_str);
1950     }
1951
1952   if (vp->objects_last_page == vp->objects_per_page)
1953     add_varray_page (vp);
1954
1955   psym = &vp->last->datum->esym[ vp->objects_last_page++ ];
1956
1957   *psym = *esym;
1958   psym->ifd = ifd;
1959   psym->asym.index = indexNil;
1960   psym->asym.iss   = (str_start == (const char *) 0)
1961                         ? 0
1962                         : add_string (&ext_strings,
1963                                       &ext_str_hash[0],
1964                                       str_start,
1965                                       str_end_p1,
1966                                       &hash_ptr);
1967
1968   hash_ptr->esym_ptr = psym;
1969   return vp->num_allocated++;
1970 }
1971
1972 \f
1973 /* Add an auxiliary symbol (passing a symint).  */
1974
1975 STATIC symint_t
1976 add_aux_sym_symint (symint_t aux_word)
1977 {
1978   AUXU *aux_ptr;
1979   efdr_t *file_ptr = cur_file_ptr;
1980   varray_t *vp = &file_ptr->aux_syms;
1981
1982   if (vp->objects_last_page == vp->objects_per_page)
1983     add_varray_page (vp);
1984
1985   aux_ptr = &vp->last->datum->aux[ vp->objects_last_page++ ];
1986   aux_ptr->isym = aux_word;
1987
1988   return vp->num_allocated++;
1989 }
1990
1991
1992 /* Add an auxiliary symbol (passing a file/symbol index combo).  */
1993
1994 STATIC symint_t
1995 add_aux_sym_rndx (int file_index, symint_t sym_index)
1996 {
1997   AUXU *aux_ptr;
1998   efdr_t *file_ptr = cur_file_ptr;
1999   varray_t *vp = &file_ptr->aux_syms;
2000
2001   if (vp->objects_last_page == vp->objects_per_page)
2002     add_varray_page (vp);
2003
2004   aux_ptr = &vp->last->datum->aux[ vp->objects_last_page++ ];
2005   aux_ptr->rndx.rfd   = file_index;
2006   aux_ptr->rndx.index = sym_index;
2007
2008   return vp->num_allocated++;
2009 }
2010
2011 \f
2012 /* Add an auxiliary symbol (passing the basic type and possibly
2013    type qualifiers).  */
2014
2015 STATIC symint_t
2016 add_aux_sym_tir (type_info_t *t, hash_state_t state, thash_t **hash_tbl)
2017 {
2018   AUXU *aux_ptr;
2019   efdr_t *file_ptr = cur_file_ptr;
2020   varray_t *vp = &file_ptr->aux_syms;
2021   static AUXU init_aux;
2022   symint_t ret;
2023   int i;
2024   AUXU aux;
2025
2026   aux = init_aux;
2027   aux.ti.bt = (int) t->basic_type;
2028   aux.ti.continued = 0;
2029   aux.ti.fBitfield = t->bitfield;
2030
2031   aux.ti.tq0 = (int) t->type_qualifiers[0];
2032   aux.ti.tq1 = (int) t->type_qualifiers[1];
2033   aux.ti.tq2 = (int) t->type_qualifiers[2];
2034   aux.ti.tq3 = (int) t->type_qualifiers[3];
2035   aux.ti.tq4 = (int) t->type_qualifiers[4];
2036   aux.ti.tq5 = (int) t->type_qualifiers[5];
2037
2038
2039   /* For anything that adds additional information, we must not hash,
2040      so check here, and reset our state.  */
2041
2042   if (state != hash_no
2043       && (t->type_qualifiers[0] == tq_Array
2044           || t->type_qualifiers[1] == tq_Array
2045           || t->type_qualifiers[2] == tq_Array
2046           || t->type_qualifiers[3] == tq_Array
2047           || t->type_qualifiers[4] == tq_Array
2048           || t->type_qualifiers[5] == tq_Array
2049           || t->basic_type == bt_Struct
2050           || t->basic_type == bt_Union
2051           || t->basic_type == bt_Enum
2052           || t->bitfield
2053           || t->num_dims > 0))
2054     state = hash_no;
2055
2056   /* See if we can hash this type, and save some space, but some types
2057      can't be hashed (because they contain arrays or continuations),
2058      and others can be put into the hash list, but cannot use existing
2059      types because other aux entries precede this one.  */
2060
2061   if (state != hash_no)
2062     {
2063       thash_t *hash_ptr;
2064       symint_t hi;
2065
2066       hi = aux.isym & ((1 << HASHBITS) - 1);
2067       hi %= THASH_SIZE;
2068
2069       for (hash_ptr = hash_tbl[hi];
2070            hash_ptr != (thash_t *) 0;
2071            hash_ptr = hash_ptr->next)
2072         {
2073           if (aux.isym == hash_ptr->type.isym)
2074             break;
2075         }
2076
2077       if (hash_ptr != (thash_t *) 0 && state == hash_yes)
2078         return hash_ptr->indx;
2079
2080       if (hash_ptr == (thash_t *) 0)
2081         {
2082           hash_ptr = allocate_thash ();
2083           hash_ptr->next = hash_tbl[hi];
2084           hash_ptr->type = aux;
2085           hash_ptr->indx = vp->num_allocated;
2086           hash_tbl[hi] = hash_ptr;
2087         }
2088     }
2089
2090   /* Everything is set up, add the aux symbol.  */
2091   if (vp->objects_last_page == vp->objects_per_page)
2092     add_varray_page (vp);
2093
2094   aux_ptr = &vp->last->datum->aux[ vp->objects_last_page++ ];
2095   *aux_ptr = aux;
2096
2097   ret = vp->num_allocated++;
2098
2099   /* Add bitfield length if it exists.
2100
2101      NOTE:  Mips documentation claims bitfield goes at the end of the
2102      AUX record, but the DECstation compiler emits it here.
2103      (This would only make a difference for enum bitfields.)
2104
2105      Also note:  We use the last size given since gcc may emit 2
2106      for an enum bitfield.  */
2107
2108   if (t->bitfield)
2109     (void) add_aux_sym_symint ((symint_t) t->sizes[t->num_sizes-1]);
2110
2111
2112   /* Add tag information if needed.  Structure, union, and enum
2113      references add 2 aux symbols: a [file index, symbol index]
2114      pointer to the structure type, and the current file index.  */
2115
2116   if (t->basic_type == bt_Struct
2117       || t->basic_type == bt_Union
2118       || t->basic_type == bt_Enum)
2119     {
2120       symint_t file_index = t->tag_ptr->ifd;
2121       symint_t sym_index  = t->tag_ptr->indx;
2122
2123       if (t->unknown_tag)
2124         {
2125           (void) add_aux_sym_rndx (ST_RFDESCAPE, sym_index);
2126           (void) add_aux_sym_symint ((symint_t)-1);
2127         }
2128       else if (sym_index != indexNil)
2129         {
2130           (void) add_aux_sym_rndx (ST_RFDESCAPE, sym_index);
2131           (void) add_aux_sym_symint (file_index);
2132         }
2133       else
2134         {
2135           forward_t *forward_ref = allocate_forward ();
2136
2137           forward_ref->type_ptr = aux_ptr;
2138           forward_ref->next = t->tag_ptr->forward_ref;
2139           t->tag_ptr->forward_ref = forward_ref;
2140
2141           (void) add_aux_sym_rndx (ST_RFDESCAPE, sym_index);
2142           forward_ref->index_ptr
2143             = &vp->last->datum->aux[ vp->objects_last_page - 1];
2144
2145           (void) add_aux_sym_symint (file_index);
2146           forward_ref->ifd_ptr
2147             = &vp->last->datum->aux[ vp->objects_last_page - 1];
2148         }
2149     }
2150
2151   /* Add information about array bounds if they exist.  */
2152   for (i = 0; i < t->num_dims; i++)
2153     {
2154       (void) add_aux_sym_rndx (ST_RFDESCAPE,
2155                                cur_file_ptr->int_type);
2156
2157       (void) add_aux_sym_symint (cur_file_ptr->file_index);     /* file index*/
2158       (void) add_aux_sym_symint ((symint_t) 0);                 /* low bound */
2159       (void) add_aux_sym_symint (t->dimensions[i] - 1);         /* high bound*/
2160       (void) add_aux_sym_symint ((t->dimensions[i] == 0)        /* stride */
2161                               ? 0
2162                               : (t->sizes[i] * 8) / t->dimensions[i]);
2163     };
2164
2165   /* NOTE:  Mips documentation claims that the bitfield width goes here.
2166      But it needs to be emitted earlier.  */
2167
2168   return ret;
2169 }
2170
2171 \f
2172 /* Add a tag to the tag table (unless it already exists).  */
2173
2174 STATIC tag_t *
2175 get_tag (const char *tag_start,         /* 1st byte of tag name */
2176          const char *tag_end_p1,        /* 1st byte after tag name */
2177          symint_t indx,         /* index of tag start block */
2178          bt_t basic_type)               /* bt_Struct, bt_Union, or bt_Enum */
2179
2180 {
2181   shash_t *hash_ptr;
2182   tag_t *tag_ptr;
2183   hash_ptr = hash_string (tag_start,
2184                           tag_end_p1 - tag_start,
2185                           &tag_hash[0],
2186                           (symint_t *) 0);
2187
2188   if (hash_ptr != (shash_t *) 0
2189       && hash_ptr->tag_ptr != (tag_t *) 0)
2190   {
2191     tag_ptr = hash_ptr->tag_ptr;
2192     if (indx != indexNil)
2193       {
2194         tag_ptr->basic_type = basic_type;
2195         tag_ptr->ifd        = cur_file_ptr->file_index;
2196         tag_ptr->indx       = indx;
2197       }
2198     return tag_ptr;
2199   }
2200
2201   (void) add_string (&tag_strings,
2202                      &tag_hash[0],
2203                      tag_start,
2204                      tag_end_p1,
2205                      &hash_ptr);
2206
2207   tag_ptr = allocate_tag ();
2208   tag_ptr->forward_ref  = (forward_t *) 0;
2209   tag_ptr->hash_ptr     = hash_ptr;
2210   tag_ptr->same_name    = hash_ptr->tag_ptr;
2211   tag_ptr->basic_type   = basic_type;
2212   tag_ptr->indx         = indx;
2213   tag_ptr->ifd          = (indx == indexNil
2214                            ? (symint_t) -1 : cur_file_ptr->file_index);
2215   tag_ptr->same_block   = cur_tag_head->first_tag;
2216
2217   cur_tag_head->first_tag = tag_ptr;
2218   hash_ptr->tag_ptr       = tag_ptr;
2219
2220   return tag_ptr;
2221 }
2222
2223 \f
2224 /* Add an unknown {struct, union, enum} tag.  */
2225
2226 STATIC void
2227 add_unknown_tag (tag_t *ptag)
2228 {
2229   shash_t *hash_ptr     = ptag->hash_ptr;
2230   char *name_start      = hash_ptr->string;
2231   char *name_end_p1     = name_start + hash_ptr->len;
2232   forward_t *f_next     = ptag->forward_ref;
2233   forward_t *f_cur;
2234   int sym_index;
2235   int file_index        = cur_file_ptr->file_index;
2236
2237   if (debug > 1)
2238     {
2239       const char *agg_type = "{unknown aggregate type}";
2240       switch (ptag->basic_type)
2241         {
2242         case bt_Struct: agg_type = "struct";    break;
2243         case bt_Union:  agg_type = "union";     break;
2244         case bt_Enum:   agg_type = "enum";      break;
2245         default:                                break;
2246         }
2247
2248       fprintf (stderr, "unknown %s %.*s found\n",
2249                agg_type, (int) hash_ptr->len, name_start);
2250     }
2251
2252   sym_index = add_local_symbol (name_start,
2253                                 name_end_p1,
2254                                 st_Block,
2255                                 sc_Info,
2256                                 (symint_t) 0,
2257                                 (symint_t) 0);
2258
2259   (void) add_local_symbol (name_start,
2260                            name_end_p1,
2261                            st_End,
2262                            sc_Info,
2263                            (symint_t) 0,
2264                            (symint_t) 0);
2265
2266   while (f_next != (forward_t *) 0)
2267     {
2268       f_cur  = f_next;
2269       f_next = f_next->next;
2270
2271       f_cur->ifd_ptr->isym = file_index;
2272       f_cur->index_ptr->rndx.index = sym_index;
2273
2274       free_forward (f_cur);
2275     }
2276
2277   return;
2278 }
2279
2280 \f
2281 /* Add a procedure to the current file's list of procedures, and record
2282    this is the current procedure.  If the assembler created a PDR for
2283    this procedure, use that to initialize the current PDR.  */
2284
2285 STATIC void
2286 add_procedure (const char *func_start,  /* 1st byte of func name */
2287                const char *func_end_p1) /* 1st byte after func name */
2288 {
2289   PDR *new_proc_ptr;
2290   efdr_t *file_ptr = cur_file_ptr;
2291   varray_t *vp = &file_ptr->procs;
2292   symint_t value = 0;
2293   st_t proc_type = st_Proc;
2294   shash_t *shash_ptr = hash_string (func_start,
2295                                     func_end_p1 - func_start,
2296                                     &orig_str_hash[0],
2297                                     (symint_t *) 0);
2298
2299   if (debug)
2300     fputc ('\n', stderr);
2301
2302   if (vp->objects_last_page == vp->objects_per_page)
2303     add_varray_page (vp);
2304
2305   cur_proc_ptr = new_proc_ptr = &vp->last->datum->proc[ vp->objects_last_page++ ];
2306
2307   vp->num_allocated++;
2308
2309
2310   /* Did the assembler create this procedure?  If so, get the PDR information.  */
2311   cur_oproc_ptr = (PDR *) 0;
2312   if (shash_ptr != (shash_t *) 0)
2313     {
2314       PDR *old_proc_ptr = shash_ptr->proc_ptr;
2315       SYMR *sym_ptr = shash_ptr->sym_ptr;
2316
2317       if (old_proc_ptr != (PDR *) 0
2318           && sym_ptr != (SYMR *) 0
2319           && ((st_t) sym_ptr->st == st_Proc || (st_t) sym_ptr->st == st_StaticProc))
2320         {
2321           cur_oproc_begin = sym_ptr;
2322           cur_oproc_end = shash_ptr->end_ptr;
2323           value = sym_ptr->value;
2324
2325           cur_oproc_ptr = old_proc_ptr;
2326           proc_type = (st_t) sym_ptr->st;
2327           *new_proc_ptr = *old_proc_ptr;        /* initialize */
2328         }
2329     }
2330
2331   if (cur_oproc_ptr == (PDR *) 0)
2332     error ("did not find a PDR block for %.*s",
2333            (int) (func_end_p1 - func_start), func_start);
2334
2335   /* Determine the start of symbols.  */
2336   new_proc_ptr->isym = file_ptr->symbols.num_allocated;
2337
2338   /* Push the start of the function.  */
2339   (void) add_local_symbol (func_start, func_end_p1,
2340                            proc_type, sc_Text,
2341                            value,
2342                            (symint_t) 0);
2343 }
2344
2345 \f
2346 /* Initialize the init_file structure.  */
2347
2348 STATIC void
2349 initialize_init_file (void)
2350 {
2351   union {
2352     unsigned char c[4];
2353     int i;
2354   } endian_test;
2355
2356   memset (&init_file, 0, sizeof (init_file));
2357
2358   init_file.fdr.lang = langC;
2359   init_file.fdr.fMerge = 1;
2360   init_file.fdr.glevel = GLEVEL_2;
2361
2362   /* mips-tfile doesn't attempt to perform byte swapping and always writes
2363      out integers in its native ordering.  For cross-compilers, this need
2364      not be the same as either the host or the target.  The simplest thing
2365      to do is skip the configury and perform an introspective test.  */
2366   /* ??? Despite the name, mips-tfile is currently only used on alpha/Tru64
2367      and would/may require significant work to be used in cross-compiler
2368      configurations, so we could simply admit defeat and hard code this as
2369      little-endian, i.e. init_file.fdr.fBigendian = 0.  */
2370   endian_test.i = 1;
2371   if (endian_test.c[3])
2372     init_file.fdr.fBigendian = 1;
2373
2374   INITIALIZE_VARRAY (&init_file.strings, char);
2375   INITIALIZE_VARRAY (&init_file.symbols, SYMR);
2376   INITIALIZE_VARRAY (&init_file.procs, PDR);
2377   INITIALIZE_VARRAY (&init_file.aux_syms, AUXU);
2378
2379   init_file_initialized = 1;
2380 }
2381
2382 /* Add a new filename, and set up all of the file relative
2383    virtual arrays (strings, symbols, aux syms, etc.).  Record
2384    where the current file structure lives.  */
2385
2386 STATIC void
2387 add_file (const char *file_start,  /* first byte in string */
2388           const char *file_end_p1) /* first byte after string */
2389 {
2390   static char zero_bytes[2] = { '\0', '\0' };
2391
2392   Ptrdiff_t len = file_end_p1 - file_start;
2393   int first_ch = *file_start;
2394   efdr_t *file_ptr;
2395
2396   if (debug)
2397     fprintf (stderr, "\tfile\t%.*s\n", (int) len, file_start);
2398
2399   /* See if the file has already been created.  */
2400   for (file_ptr = first_file;
2401        file_ptr != (efdr_t *) 0;
2402        file_ptr = file_ptr->next_file)
2403     {
2404       if (first_ch == file_ptr->name[0]
2405           && file_ptr->name[len] == '\0'
2406           && memcmp (file_start, file_ptr->name, len) == 0)
2407         {
2408           cur_file_ptr = file_ptr;
2409           break;
2410         }
2411     }
2412
2413   /* If this is a new file, create it.  */
2414   if (file_ptr == (efdr_t *) 0)
2415     {
2416       if (file_desc.objects_last_page == file_desc.objects_per_page)
2417         add_varray_page (&file_desc);
2418
2419       if (! init_file_initialized)
2420         initialize_init_file ();
2421
2422       file_ptr = cur_file_ptr
2423         = &file_desc.last->datum->file[ file_desc.objects_last_page++ ];
2424       *file_ptr = init_file;
2425
2426       file_ptr->file_index = file_desc.num_allocated++;
2427
2428       /* Allocate the string hash table.  */
2429       file_ptr->shash_head = (shash_t **) allocate_page ();
2430
2431       /* Make sure 0 byte in string table is null  */
2432       add_string (&file_ptr->strings,
2433                   &file_ptr->shash_head[0],
2434                   &zero_bytes[0],
2435                   &zero_bytes[0],
2436                   (shash_t **) 0);
2437
2438       if (file_end_p1 - file_start > (long) PAGE_USIZE-2)
2439         fatal ("filename goes over one page boundary");
2440
2441       /* Push the start of the filename. We assume that the filename
2442          will be stored at string offset 1.  */
2443       (void) add_local_symbol (file_start, file_end_p1, st_File, sc_Text,
2444                                (symint_t) 0, (symint_t) 0);
2445       file_ptr->fdr.rss = 1;
2446       file_ptr->name = &file_ptr->strings.last->datum->byte[1];
2447       file_ptr->name_len = file_end_p1 - file_start;
2448
2449       /* Update the linked list of file descriptors.  */
2450       *last_file_ptr = file_ptr;
2451       last_file_ptr = &file_ptr->next_file;
2452
2453       /* Add void & int types to the file (void should be first to catch
2454          errant 0's within the index fields).  */
2455       file_ptr->void_type = add_aux_sym_tir (&void_type_info,
2456                                              hash_yes,
2457                                              &cur_file_ptr->thash_head[0]);
2458
2459       file_ptr->int_type = add_aux_sym_tir (&int_type_info,
2460                                             hash_yes,
2461                                             &cur_file_ptr->thash_head[0]);
2462     }
2463 }
2464
2465 \f
2466 /* Add a stream of random bytes to a varray.  */
2467
2468 STATIC void
2469 add_bytes (varray_t *vp,        /* virtual array to add too */
2470            char *input_ptr,     /* start of the bytes */
2471            Size_t nitems)       /* # items to move */
2472 {
2473   Size_t move_items;
2474   Size_t move_bytes;
2475   char *ptr;
2476
2477   while (nitems > 0)
2478     {
2479       if (vp->objects_last_page >= vp->objects_per_page)
2480         add_varray_page (vp);
2481
2482       ptr = &vp->last->datum->byte[ vp->objects_last_page * vp->object_size ];
2483       move_items = vp->objects_per_page - vp->objects_last_page;
2484       if (move_items > nitems)
2485         move_items = nitems;
2486
2487       move_bytes = move_items * vp->object_size;
2488       nitems -= move_items;
2489
2490       if (move_bytes >= 32)
2491         {
2492           (void) memcpy (ptr, input_ptr, move_bytes);
2493           input_ptr += move_bytes;
2494         }
2495       else
2496         {
2497           while (move_bytes-- > 0)
2498             *ptr++ = *input_ptr++;
2499         }
2500     }
2501 }
2502
2503 \f
2504 /* Convert storage class to string.  */
2505
2506 STATIC const char *
2507 sc_to_string (sc_t storage_class)
2508 {
2509   switch (storage_class)
2510     {
2511     case sc_Nil:         return "Nil,";
2512     case sc_Text:        return "Text,";
2513     case sc_Data:        return "Data,";
2514     case sc_Bss:         return "Bss,";
2515     case sc_Register:    return "Register,";
2516     case sc_Abs:         return "Abs,";
2517     case sc_Undefined:   return "Undefined,";
2518     case sc_CdbLocal:    return "CdbLocal,";
2519     case sc_Bits:        return "Bits,";
2520     case sc_CdbSystem:   return "CdbSystem,";
2521     case sc_RegImage:    return "RegImage,";
2522     case sc_Info:        return "Info,";
2523     case sc_UserStruct:  return "UserStruct,";
2524     case sc_SData:       return "SData,";
2525     case sc_SBss:        return "SBss,";
2526     case sc_RData:       return "RData,";
2527     case sc_Var:         return "Var,";
2528     case sc_Common:      return "Common,";
2529     case sc_SCommon:     return "SCommon,";
2530     case sc_VarRegister: return "VarRegister,";
2531     case sc_Variant:     return "Variant,";
2532     case sc_SUndefined:  return "SUndefined,";
2533     case sc_Init:        return "Init,";
2534     case sc_Max:         return "Max,";
2535     }
2536
2537   return "???,";
2538 }
2539
2540 \f
2541 /* Convert symbol type to string.  */
2542
2543 STATIC const char *
2544 st_to_string (st_t symbol_type)
2545 {
2546   switch (symbol_type)
2547     {
2548     case st_Nil:        return "Nil,";
2549     case st_Global:     return "Global,";
2550     case st_Static:     return "Static,";
2551     case st_Param:      return "Param,";
2552     case st_Local:      return "Local,";
2553     case st_Label:      return "Label,";
2554     case st_Proc:       return "Proc,";
2555     case st_Block:      return "Block,";
2556     case st_End:        return "End,";
2557     case st_Member:     return "Member,";
2558     case st_Typedef:    return "Typedef,";
2559     case st_File:       return "File,";
2560     case st_RegReloc:   return "RegReloc,";
2561     case st_Forward:    return "Forward,";
2562     case st_StaticProc: return "StaticProc,";
2563     case st_Constant:   return "Constant,";
2564     case st_Str:        return "String,";
2565     case st_Number:     return "Number,";
2566     case st_Expr:       return "Expr,";
2567     case st_Type:       return "Type,";
2568     case st_Max:        return "Max,";
2569     }
2570
2571   return "???,";
2572 }
2573
2574 \f
2575 /* Read a line from standard input, and return the start of the buffer
2576    (which is grows if the line is too big).  We split lines at the
2577    semi-colon, and return each logical line independently.  */
2578
2579 STATIC char *
2580 read_line (void)
2581 {
2582   static   int line_split_p     = 0;
2583   int string_p          = 0;
2584   int comment_p = 0;
2585   int ch;
2586   char *ptr;
2587
2588   if (cur_line_start == (char *) 0)
2589     {                           /* allocate initial page */
2590       cur_line_start = (char *) allocate_page ();
2591       cur_line_alloc = PAGE_SIZE;
2592     }
2593
2594   if (!line_split_p)
2595     line_number++;
2596
2597   line_split_p = 0;
2598   cur_line_nbytes = 0;
2599
2600   for (ptr = cur_line_start; (ch = getchar ()) != EOF; *ptr++ = ch)
2601     {
2602       if (++cur_line_nbytes >= cur_line_alloc-1)
2603         {
2604           int num_pages = cur_line_alloc / PAGE_SIZE;
2605           char *old_buffer = cur_line_start;
2606
2607           cur_line_alloc += PAGE_SIZE;
2608           cur_line_start = (char *) allocate_multiple_pages (num_pages+1);
2609           memcpy (cur_line_start, old_buffer, num_pages * PAGE_SIZE);
2610
2611           ptr = cur_line_start + cur_line_nbytes - 1;
2612         }
2613
2614       if (ch == '\n')
2615         {
2616           *ptr++ = '\n';
2617           *ptr = '\0';
2618           cur_line_ptr = cur_line_start;
2619           return cur_line_ptr;
2620         }
2621
2622       else if (ch == '\0')
2623         error ("null character found in input");
2624
2625       else if (!comment_p)
2626         {
2627           if (ch == '"')
2628             string_p = !string_p;
2629
2630           else if (ch == '#')
2631             comment_p++;
2632
2633           else if (ch == ';' && !string_p)
2634             {
2635               line_split_p = 1;
2636               *ptr++ = '\n';
2637               *ptr = '\0';
2638               cur_line_ptr = cur_line_start;
2639               return cur_line_ptr;
2640             }
2641         }
2642     }
2643
2644   if (ferror (stdin))
2645     pfatal_with_name (input_name);
2646
2647   cur_line_ptr = (char *) 0;
2648   return (char *) 0;
2649 }
2650
2651 \f
2652 /* Parse #.begin directives which have a label as the first argument
2653    which gives the location of the start of the block.  */
2654
2655 STATIC void
2656 parse_begin (const char *start)
2657 {
2658   const char *end_p1;                   /* end of label */
2659   int ch;
2660   shash_t *hash_ptr;                    /* hash pointer to lookup label */
2661
2662   if (cur_file_ptr == (efdr_t *) 0)
2663     {
2664       error ("#.begin directive without a preceding .file directive");
2665       return;
2666     }
2667
2668   if (cur_proc_ptr == (PDR *) 0)
2669     {
2670       error ("#.begin directive without a preceding .ent directive");
2671       return;
2672     }
2673
2674   for (end_p1 = start; (ch = *end_p1) != '\0' && !ISSPACE (ch); end_p1++)
2675     ;
2676
2677   hash_ptr = hash_string (start,
2678                           end_p1 - start,
2679                           &orig_str_hash[0],
2680                           (symint_t *) 0);
2681
2682   if (hash_ptr == (shash_t *) 0)
2683     {
2684       error ("label %.*s not found for #.begin",
2685              (int) (end_p1 - start), start);
2686       return;
2687     }
2688
2689   if (cur_oproc_begin == (SYMR *) 0)
2690     {
2691       error ("procedure table %.*s not found for #.begin",
2692              (int) (end_p1 - start), start);
2693       return;
2694     }
2695
2696   (void) add_local_symbol ((const char *) 0, (const char *) 0,
2697                            st_Block, sc_Text,
2698                            (symint_t) hash_ptr->sym_ptr->value - cur_oproc_begin->value,
2699                            (symint_t) 0);
2700 }
2701
2702 \f
2703 /* Parse #.bend directives which have a label as the first argument
2704    which gives the location of the end of the block.  */
2705
2706 STATIC void
2707 parse_bend (const char *start)
2708 {
2709   const char *end_p1;                   /* end of label */
2710   int ch;
2711   shash_t *hash_ptr;                    /* hash pointer to lookup label */
2712
2713   if (cur_file_ptr == (efdr_t *) 0)
2714     {
2715       error ("#.begin directive without a preceding .file directive");
2716       return;
2717     }
2718
2719   if (cur_proc_ptr == (PDR *) 0)
2720     {
2721       error ("#.bend directive without a preceding .ent directive");
2722       return;
2723     }
2724
2725   for (end_p1 = start; (ch = *end_p1) != '\0' && !ISSPACE (ch); end_p1++)
2726     ;
2727
2728   hash_ptr = hash_string (start,
2729                           end_p1 - start,
2730                           &orig_str_hash[0],
2731                           (symint_t *) 0);
2732
2733   if (hash_ptr == (shash_t *) 0)
2734     {
2735       error ("label %.*s not found for #.bend", (int) (end_p1 - start), start);
2736       return;
2737     }
2738
2739   if (cur_oproc_begin == (SYMR *) 0)
2740     {
2741       error ("procedure table %.*s not found for #.bend",
2742              (int) (end_p1 - start), start);
2743       return;
2744     }
2745
2746   (void) add_local_symbol ((const char *) 0, (const char *) 0,
2747                            st_End, sc_Text,
2748                            (symint_t) hash_ptr->sym_ptr->value - cur_oproc_begin->value,
2749                            (symint_t) 0);
2750 }
2751
2752 \f
2753 /* Parse #.def directives, which are contain standard COFF subdirectives
2754    to describe the debugging format.  These subdirectives include:
2755
2756         .scl    specify storage class
2757         .val    specify a value
2758         .endef  specify end of COFF directives
2759         .type   specify the type
2760         .size   specify the size of an array
2761         .dim    specify an array dimension
2762         .tag    specify a tag for a struct, union, or enum.  */
2763
2764 STATIC void
2765 parse_def (const char *name_start)
2766 {
2767   const char *dir_start;                        /* start of current directive*/
2768   const char *dir_end_p1;                       /* end+1 of current directive*/
2769   const char *arg_start;                        /* start of current argument */
2770   const char *arg_end_p1;                       /* end+1 of current argument */
2771   const char *name_end_p1;                      /* end+1 of label */
2772   const char *tag_start   = 0;                  /* start of tag name */
2773   const char *tag_end_p1  = 0;                  /* end+1 of tag name */
2774   sc_t storage_class      = sc_Nil;
2775   st_t symbol_type        = st_Nil;
2776   type_info_t t;
2777   EXTR *eptr              = (EXTR *) 0;         /* ext. sym equivalent to def*/
2778   int is_function         = 0;                  /* != 0 if function */
2779   symint_t value          = 0;
2780   symint_t indx           = cur_file_ptr->void_type;
2781   int error_line          = 0;
2782   symint_t arg_number;
2783   symint_t temp_array[ N_TQ ];
2784   int arg_was_number;
2785   int ch, i;
2786   Ptrdiff_t len;
2787
2788   static int inside_enumeration = 0;            /* is this an enumeration? */
2789
2790
2791   /* Initialize the type information.  */
2792   t = type_info_init;
2793
2794
2795   /* Search for the end of the name being defined.  */
2796   /* Allow spaces and such in names for G++ templates, which produce stabs
2797      that look like:
2798
2799      #.def   SMANIP<long unsigned int>; .scl 10; .type 0x8; .size 8; .endef */
2800
2801   for (name_end_p1 = name_start; (ch = *name_end_p1) != ';' && ch != '\0'; name_end_p1++)
2802     ;
2803
2804   if (ch == '\0')
2805     {
2806       error_line = __LINE__;
2807       saber_stop ();
2808       goto bomb_out;
2809     }
2810
2811   /* Parse the remaining subdirectives now.  */
2812   dir_start = name_end_p1+1;
2813   for (;;)
2814     {
2815       while ((ch = *dir_start) == ' ' || ch == '\t')
2816         ++dir_start;
2817
2818       if (ch != '.')
2819         {
2820           error_line = __LINE__;
2821           saber_stop ();
2822           goto bomb_out;
2823         }
2824
2825       /* Are we done? */
2826       if (dir_start[1] == 'e'
2827           && memcmp (dir_start, ".endef", sizeof (".endef")-1) == 0)
2828         break;
2829
2830       /* Pick up the subdirective now.  */
2831       for (dir_end_p1 = dir_start+1;
2832            (ch = *dir_end_p1) != ' ' && ch != '\t';
2833            dir_end_p1++)
2834         {
2835           if (ch == '\0' || ISSPACE (ch))
2836             {
2837               error_line = __LINE__;
2838               saber_stop ();
2839               goto bomb_out;
2840             }
2841         }
2842
2843       /* Pick up the subdirective argument now.  */
2844       arg_was_number = arg_number = 0;
2845       arg_end_p1 = 0;
2846       arg_start = dir_end_p1+1;
2847       ch = *arg_start;
2848       while (ch == ' ' || ch == '\t')
2849         ch = *++arg_start;
2850
2851       if (ISDIGIT (ch) || ch == '-' || ch == '+')
2852         {
2853           int ch2;
2854           arg_number = strtol (arg_start, (char **) &arg_end_p1, 0);
2855           /* It's only a number if followed by ';' or ','. */
2856           if (arg_end_p1 != arg_start && (((ch2 = *arg_end_p1) == ';') || ch2 == ','))
2857             arg_was_number++;
2858         }
2859
2860       else if (ch == '\0' || ISSPACE (ch))
2861         {
2862           error_line = __LINE__;
2863           saber_stop ();
2864           goto bomb_out;
2865         }
2866
2867       if (!arg_was_number)
2868         {
2869           /* Allow spaces and such in names for G++ templates.  */
2870           for (arg_end_p1 = arg_start+1;
2871                (ch = *arg_end_p1) != ';' && ch != '\0';
2872                arg_end_p1++)
2873             ;
2874
2875           if (ch == '\0')
2876             {
2877               error_line = __LINE__;
2878               saber_stop ();
2879               goto bomb_out;
2880             }
2881         }
2882
2883       /* Classify the directives now.  */
2884       len = dir_end_p1 - dir_start;
2885       switch (dir_start[1])
2886         {
2887         default:
2888           error_line = __LINE__;
2889           saber_stop ();
2890           goto bomb_out;
2891
2892         case 'd':
2893           if (len == sizeof (".dim")-1
2894               && memcmp (dir_start, ".dim", sizeof (".dim")-1) == 0
2895               && arg_was_number)
2896             {
2897               symint_t *t_ptr = &temp_array[ N_TQ-1 ];
2898
2899               *t_ptr = arg_number;
2900               while (*arg_end_p1 == ',' && arg_was_number)
2901                 {
2902                   arg_start = arg_end_p1+1;
2903                   ch = *arg_start;
2904                   while (ch == ' ' || ch == '\t')
2905                     ch = *++arg_start;
2906
2907                   arg_was_number = 0;
2908                   if (ISDIGIT (ch) || ch == '-' || ch == '+')
2909                     {
2910                       int ch2;
2911                       arg_number = strtol (arg_start, (char **) &arg_end_p1, 0);
2912                       if (arg_end_p1 != arg_start && (((ch2 = *arg_end_p1) == ';') || ch2 == ','))
2913                         arg_was_number++;
2914
2915                       if (t_ptr == &temp_array[0])
2916                         {
2917                           error_line = __LINE__;
2918                           saber_stop ();
2919                           goto bomb_out;
2920                         }
2921
2922                       *--t_ptr = arg_number;
2923                     }
2924                 }
2925
2926               /* Reverse order of dimensions.  */
2927               while (t_ptr <= &temp_array[ N_TQ-1 ])
2928                 {
2929                   if (t.num_dims >= N_TQ-1)
2930                     {
2931                       error_line = __LINE__;
2932                       saber_stop ();
2933                       goto bomb_out;
2934                     }
2935
2936                   t.dimensions[ t.num_dims++ ] = *t_ptr++;
2937                 }
2938               break;
2939             }
2940           else
2941             {
2942               error_line = __LINE__;
2943               saber_stop ();
2944               goto bomb_out;
2945             }
2946
2947
2948         case 's':
2949           if (len == sizeof (".scl")-1
2950               && memcmp (dir_start, ".scl", sizeof (".scl")-1) == 0
2951               && arg_was_number
2952               && arg_number < ((symint_t) C_MAX))
2953             {
2954               /* If the symbol is a static or external, we have
2955                  already gotten the appropriate type and class, so
2956                  make sure we don't override those values.  This is
2957                  needed because there are some type and classes that
2958                  are not in COFF, such as short data, etc.  */
2959               if (symbol_type == st_Nil)
2960                 {
2961                   symbol_type   = map_coff_sym_type[arg_number];
2962                   storage_class = map_coff_storage [arg_number];
2963                 }
2964               break;
2965             }
2966
2967           else if (len == sizeof (".size")-1
2968                    && memcmp (dir_start, ".size", sizeof (".size")-1) == 0
2969                    && arg_was_number)
2970             {
2971               symint_t *t_ptr = &temp_array[ N_TQ-1 ];
2972
2973               *t_ptr = arg_number;
2974               while (*arg_end_p1 == ',' && arg_was_number)
2975                 {
2976                   arg_start = arg_end_p1+1;
2977                   ch = *arg_start;
2978                   while (ch == ' ' || ch == '\t')
2979                     ch = *++arg_start;
2980
2981                   arg_was_number = 0;
2982                   if (ISDIGIT (ch) || ch == '-' || ch == '+')
2983                     {
2984                       int ch2;
2985                       arg_number = strtol (arg_start, (char **) &arg_end_p1, 0);
2986                       if (arg_end_p1 != arg_start && (((ch2 = *arg_end_p1) == ';') || ch2 == ','))
2987                         arg_was_number++;
2988
2989                       if (t_ptr == &temp_array[0])
2990                         {
2991                           error_line = __LINE__;
2992                           saber_stop ();
2993                           goto bomb_out;
2994                         }
2995
2996                       *--t_ptr = arg_number;
2997                     }
2998                 }
2999
3000               /* Reverse order of sizes.  */
3001               while (t_ptr <= &temp_array[ N_TQ-1 ])
3002                 {
3003                   if (t.num_sizes >= N_TQ-1)
3004                     {
3005                       error_line = __LINE__;
3006                       saber_stop ();
3007                       goto bomb_out;
3008                     }
3009
3010                   t.sizes[ t.num_sizes++ ] = *t_ptr++;
3011                 }
3012               break;
3013             }
3014
3015           else
3016             {
3017               error_line = __LINE__;
3018               saber_stop ();
3019               goto bomb_out;
3020             }
3021
3022
3023         case 't':
3024           if (len == sizeof (".type")-1
3025               && memcmp (dir_start, ".type", sizeof (".type")-1) == 0
3026               && arg_was_number)
3027             {
3028               tq_t *tq_ptr = &t.type_qualifiers[0];
3029
3030               t.orig_type = (coff_type_t) (arg_number & N_BTMASK);
3031               t.basic_type = map_coff_types [(int) t.orig_type];
3032               for (i = N_TQ-1; i >= 0; i--)
3033                 {
3034                   int dt = (arg_number >> ((i * N_TQ_SHIFT) + N_BT_SHIFT)
3035                             & N_TMASK);
3036
3037                   if (dt != (int) DT_NON)
3038                     *tq_ptr++ = map_coff_derived_type [dt];
3039                 }
3040
3041               /* If this is a function, ignore it, so that we don't get
3042                  two entries (one from the .ent, and one for the .def
3043                  that precedes it).  Save the type information so that
3044                  the end block can properly add it after the begin block
3045                  index.  For MIPS knows what reason, we must strip off
3046                  the function type at this point.  */
3047               if (tq_ptr != &t.type_qualifiers[0] && tq_ptr[-1] == tq_Proc)
3048                 {
3049                   is_function = 1;
3050                   tq_ptr[-1] = tq_Nil;
3051                 }
3052
3053               break;
3054             }
3055
3056           else if (len == sizeof (".tag")-1
3057               && memcmp (dir_start, ".tag", sizeof (".tag")-1) == 0)
3058             {
3059               tag_start = arg_start;
3060               tag_end_p1 = arg_end_p1;
3061               break;
3062             }
3063
3064           else
3065             {
3066               error_line = __LINE__;
3067               saber_stop ();
3068               goto bomb_out;
3069             }
3070
3071
3072         case 'v':
3073           if (len == sizeof (".val")-1
3074               && memcmp (dir_start, ".val", sizeof (".val")-1) == 0)
3075             {
3076               if (arg_was_number)
3077                 value = arg_number;
3078
3079               /* If the value is not an integer value, it must be the
3080                  name of a static or global item.  Look up the name in
3081                  the original symbol table to pick up the storage
3082                  class, symbol type, etc.  */
3083               else
3084                 {
3085                   shash_t *orig_hash_ptr;       /* hash within orig sym table*/
3086                   shash_t *ext_hash_ptr;        /* hash within ext. sym table*/
3087
3088                   ext_hash_ptr = hash_string (arg_start,
3089                                               arg_end_p1 - arg_start,
3090                                               &ext_str_hash[0],
3091                                               (symint_t *) 0);
3092
3093                   if (ext_hash_ptr != (shash_t *) 0
3094                       && ext_hash_ptr->esym_ptr != (EXTR *) 0)
3095                     eptr = ext_hash_ptr->esym_ptr;
3096
3097                   orig_hash_ptr = hash_string (arg_start,
3098                                                arg_end_p1 - arg_start,
3099                                                &orig_str_hash[0],
3100                                                (symint_t *) 0);
3101
3102                   if ((orig_hash_ptr == (shash_t *) 0
3103                        || orig_hash_ptr->sym_ptr == (SYMR *) 0)
3104                       && eptr == (EXTR *) 0)
3105                     {
3106                       fprintf (stderr, "warning, %.*s not found in original or external symbol tables, value defaults to 0\n",
3107                                (int) (arg_end_p1 - arg_start),
3108                                arg_start);
3109                       value = 0;
3110                     }
3111                   else
3112                     {
3113                       SYMR *ptr = (orig_hash_ptr != (shash_t *) 0
3114                                    && orig_hash_ptr->sym_ptr != (SYMR *) 0)
3115                                         ? orig_hash_ptr->sym_ptr
3116                                         : &eptr->asym;
3117
3118                       symbol_type = (st_t) ptr->st;
3119                       storage_class = (sc_t) ptr->sc;
3120                       value = ptr->value;
3121                     }
3122                 }
3123               break;
3124             }
3125           else
3126             {
3127               error_line = __LINE__;
3128               saber_stop ();
3129               goto bomb_out;
3130             }
3131         }
3132
3133       /* Set up to find next directive.  */
3134       dir_start = arg_end_p1 + 1;
3135     }
3136
3137
3138   if (storage_class == sc_Bits)
3139     {
3140       t.bitfield = 1;
3141       t.extra_sizes = 1;
3142     }
3143   else
3144     t.extra_sizes = 0;
3145
3146   if (t.num_dims > 0)
3147     {
3148       int num_real_sizes = t.num_sizes - t.extra_sizes;
3149       int diff = t.num_dims - num_real_sizes;
3150       int i = t.num_dims - 1;
3151       int j;
3152
3153       if (num_real_sizes != 1 || diff < 0)
3154         {
3155           error_line = __LINE__;
3156           saber_stop ();
3157           goto bomb_out;
3158         }
3159
3160       /* If this is an array, make sure the same number of dimensions
3161          and sizes were passed, creating extra sizes for multiply
3162          dimensioned arrays if not passed.  */
3163
3164       if (diff)
3165         {
3166           for (j = ARRAY_SIZE (t.sizes) - 1; j >= 0; j--)
3167             t.sizes[ j ] = ((j-diff) >= 0) ? t.sizes[ j-diff ] : 0;
3168
3169           t.num_sizes = i + 1;
3170           for ( i--; i >= 0; i-- )
3171             {
3172               if (t.dimensions[ i+1 ])
3173                 t.sizes[ i ] = t.sizes[ i+1 ] / t.dimensions[ i+1 ];
3174               else
3175                 t.sizes[ i ] = t.sizes[ i+1 ];
3176             }
3177         }
3178     }
3179
3180   /* Except for enumeration members & begin/ending of scopes, put the
3181      type word in the aux. symbol table.  */
3182
3183   if (symbol_type == st_Block || symbol_type == st_End)
3184     indx = 0;
3185
3186   else if (inside_enumeration)
3187     indx = cur_file_ptr->void_type;
3188
3189   else
3190     {
3191       if (t.basic_type == bt_Struct
3192           || t.basic_type == bt_Union
3193           || t.basic_type == bt_Enum)
3194         {
3195           if (tag_start == (char *) 0)
3196             {
3197               error ("no tag specified for %.*s",
3198                      (int) (name_end_p1 - name_start),
3199                      name_start);
3200               return;
3201             }
3202
3203           t.tag_ptr = get_tag (tag_start, tag_end_p1,  (symint_t) indexNil,
3204                                t.basic_type);
3205         }
3206
3207       if (is_function)
3208         {
3209           last_func_type_info = t;
3210           last_func_eptr = eptr;
3211           return;
3212         }
3213
3214       indx = add_aux_sym_tir (&t,
3215                               hash_yes,
3216                               &cur_file_ptr->thash_head[0]);
3217     }
3218
3219
3220   /* If this is an external or static symbol, update the appropriate
3221      external symbol.  */
3222
3223   if (eptr != (EXTR *) 0
3224       && (eptr->asym.index == indexNil || cur_proc_ptr == (PDR *) 0))
3225     {
3226       eptr->ifd = cur_file_ptr->file_index;
3227       eptr->asym.index = indx;
3228     }
3229
3230
3231   /* Do any last minute adjustments that are necessary.  */
3232   switch (symbol_type)
3233     {
3234     default:
3235       break;
3236
3237
3238       /* For the beginning of structs, unions, and enumerations, the
3239          size info needs to be passed in the value field.  */
3240
3241     case st_Block:
3242       if (t.num_sizes - t.num_dims - t.extra_sizes != 1)
3243         {
3244           error_line = __LINE__;
3245           saber_stop ();
3246           goto bomb_out;
3247         }
3248
3249       else
3250         value = t.sizes[0];
3251
3252       inside_enumeration = (t.orig_type == T_ENUM);
3253       break;
3254
3255
3256       /* For the end of structs, unions, and enumerations, omit the
3257          name which is always ".eos".  This needs to be done last, so
3258          that any error reporting above gives the correct name.  */
3259
3260     case st_End:
3261       name_start = name_end_p1 = 0;
3262       value = inside_enumeration = 0;
3263       break;
3264
3265
3266       /* Members of structures and unions that aren't bitfields, need
3267          to adjust the value from a byte offset to a bit offset.
3268          Members of enumerations do not have the value adjusted, and
3269          can be distinguished by indx == indexNil.  For enumerations,
3270          update the maximum enumeration value.  */
3271
3272     case st_Member:
3273       if (!t.bitfield && !inside_enumeration)
3274         value *= 8;
3275
3276       break;
3277     }
3278
3279
3280   /* Add the symbol, except for global symbols outside of functions,
3281      for which the external symbol table is fine enough.  */
3282
3283   if (eptr == (EXTR *) 0
3284       || eptr->asym.st == (int) st_Nil
3285       || cur_proc_ptr != (PDR *) 0)
3286     {
3287       symint_t isym = add_local_symbol (name_start, name_end_p1,
3288                                         symbol_type, storage_class,
3289                                         value,
3290                                         indx);
3291
3292       /* Deal with struct, union, and enum tags.  */
3293       if (symbol_type == st_Block)
3294         {
3295           /* Create or update the tag information.  */
3296           tag_t *tag_ptr = get_tag (name_start,
3297                                     name_end_p1,
3298                                     isym,
3299                                     t.basic_type);
3300
3301           /* If there are any forward references, fill in the appropriate
3302              file and symbol indexes.  */
3303
3304           symint_t file_index  = cur_file_ptr->file_index;
3305           forward_t *f_next = tag_ptr->forward_ref;
3306           forward_t *f_cur;
3307
3308           while (f_next != (forward_t *) 0)
3309             {
3310               f_cur  = f_next;
3311               f_next = f_next->next;
3312
3313               f_cur->ifd_ptr->isym = file_index;
3314               f_cur->index_ptr->rndx.index = isym;
3315
3316               free_forward (f_cur);
3317             }
3318
3319           tag_ptr->forward_ref = (forward_t *) 0;
3320         }
3321     }
3322
3323   /* Normal return  */
3324   return;
3325
3326   /* Error return, issue message.  */
3327 bomb_out:
3328   if (error_line)
3329     error ("compiler error, badly formed #.def (internal line # = %d)", error_line);
3330   else
3331     error ("compiler error, badly formed #.def");
3332
3333   return;
3334 }
3335
3336 \f
3337 /* Parse .end directives.  */
3338
3339 STATIC void
3340 parse_end (const char *start)
3341 {
3342   const char *start_func, *end_func_p1;
3343   int ch;
3344   symint_t value;
3345   FDR *orig_fdr;
3346
3347   if (cur_file_ptr == (efdr_t *) 0)
3348     {
3349       error (".end directive without a preceding .file directive");
3350       return;
3351     }
3352
3353   if (cur_proc_ptr == (PDR *) 0)
3354     {
3355       error (".end directive without a preceding .ent directive");
3356       return;
3357     }
3358
3359   /* Get the function name, skipping whitespace.  */
3360   for (start_func = start; ISSPACE ((unsigned char)*start_func); start_func++)
3361     ;
3362
3363   ch = *start_func;
3364   if (!IS_ASM_IDENT (ch))
3365     {
3366       error (".end directive has no name");
3367       return;
3368     }
3369
3370   for (end_func_p1 = start_func; IS_ASM_IDENT (ch); ch = *++end_func_p1)
3371     ;
3372
3373
3374   /* Get the value field for creating the end from the original object
3375      file (which we find by locating the procedure start, and using the
3376      pointer to the end+1 block and backing up.  The index points to a
3377      two word aux. symbol, whose first word is the index of the end
3378      symbol, and the second word is the type of the function return
3379      value.  */
3380
3381   orig_fdr = cur_file_ptr->orig_fdr;
3382   value = 0;
3383   if (orig_fdr != (FDR *) 0 && cur_oproc_end != (SYMR *) 0)
3384     value = cur_oproc_end->value;
3385
3386   else
3387     error ("cannot find .end block for %.*s",
3388            (int) (end_func_p1 - start_func), start_func);
3389
3390   (void) add_local_symbol (start_func, end_func_p1,
3391                            st_End, sc_Text,
3392                            value,
3393                            (symint_t) 0);
3394
3395   cur_proc_ptr = cur_oproc_ptr = (PDR *) 0;
3396 }
3397
3398 \f
3399 /* Parse .ent directives.  */
3400
3401 STATIC void
3402 parse_ent (const char *start)
3403 {
3404   const char *start_func, *end_func_p1;
3405   int ch;
3406
3407   if (cur_file_ptr == (efdr_t *) 0)
3408     {
3409       error (".ent directive without a preceding .file directive");
3410       return;
3411     }
3412
3413   if (cur_proc_ptr != (PDR *) 0)
3414     {
3415       error ("second .ent directive found before .end directive");
3416       return;
3417     }
3418
3419   for (start_func = start; ISSPACE ((unsigned char)*start_func); start_func++)
3420     ;
3421
3422   ch = *start_func;
3423   if (!IS_ASM_IDENT (ch))
3424     {
3425       error (".ent directive has no name");
3426       return;
3427     }
3428
3429   for (end_func_p1 = start_func; IS_ASM_IDENT (ch); ch = *++end_func_p1)
3430     ;
3431
3432   (void) add_procedure (start_func, end_func_p1);
3433 }
3434
3435 \f
3436 /* Parse .file directives.  */
3437
3438 STATIC void
3439 parse_file (const char *start)
3440 {
3441   char *p;
3442   char *start_name, *end_name_p1;
3443
3444   (void) strtol (start, &p, 0);
3445   if (start == p
3446       || (start_name = strchr (p, '"')) == (char *) 0
3447       || (end_name_p1 = strrchr (++start_name, '"')) == (char *) 0)
3448     {
3449       error ("invalid .file directive");
3450       return;
3451     }
3452
3453   if (cur_proc_ptr != (PDR *) 0)
3454     {
3455       error ("no way to handle .file within .ent/.end section");
3456       return;
3457     }
3458
3459   add_file (start_name, end_name_p1);
3460 }
3461
3462 \f
3463 /* Make sure the @stabs symbol is emitted.  */
3464
3465 static void
3466 mark_stabs (const char *start ATTRIBUTE_UNUSED)
3467 {
3468   if (!stabs_seen)
3469     {
3470       /* Add a dummy @stabs symbol.  */
3471       stabs_seen = 1;
3472       (void) add_local_symbol (stabs_symbol,
3473                                stabs_symbol + sizeof (stabs_symbol),
3474                                (st_t) stNil, (sc_t) scInfo, -1,
3475                                MIPS_MARK_STAB (0));
3476
3477     }
3478 }
3479
3480 \f
3481 /* Parse .stabs directives.
3482
3483    .stabs directives have five fields:
3484         "string"        a string, encoding the type information.
3485         code            a numeric code, defined in <stab.h>
3486         0               a zero
3487         0               a zero or line number
3488         value           a numeric value or an address.
3489
3490     If the value is relocatable, we transform this into:
3491         iss             points as an index into string space
3492         value           value from lookup of the name
3493         st              st from lookup of the name
3494         sc              sc from lookup of the name
3495         index           code|CODE_MASK
3496
3497     If the value is not relocatable, we transform this into:
3498         iss             points as an index into string space
3499         value           value
3500         st              st_Nil
3501         sc              sc_Nil
3502         index           code|CODE_MASK
3503
3504     .stabn directives have four fields (string is null):
3505         code            a numeric code, defined in <stab.h>
3506         0               a zero
3507         0               a zero or a line number
3508         value           a numeric value or an address.  */
3509
3510 STATIC void
3511 parse_stabs_common (const char *string_start,   /* start of string or NULL */
3512                     const char *string_end,     /* end+1 of string or NULL */
3513                     const char *rest)           /* rest of the directive.  */
3514 {
3515   efdr_t *save_file_ptr = cur_file_ptr;
3516   symint_t code;
3517   symint_t value;
3518   char *p;
3519   st_t st;
3520   sc_t sc;
3521   int ch;
3522
3523   if (stabs_seen == 0)
3524     mark_stabs ("");
3525
3526   /* Read code from stabs.  */
3527   if (!ISDIGIT (*rest))
3528     {
3529       error ("invalid .stabs/.stabn directive, code is non-numeric");
3530       return;
3531     }
3532
3533   code = strtol (rest, &p, 0);
3534
3535   /* Line number stabs are handled differently, since they have two values,
3536      the line number and the address of the label.  We use the index field
3537      (aka code) to hold the line number, and the value field to hold the
3538      address.  The symbol type is st_Label, which should be different from
3539      the other stabs, so that gdb can recognize it.  */
3540
3541   if (code == (int) N_SLINE)
3542     {
3543       SYMR *sym_ptr, dummy_symr;
3544       shash_t *shash_ptr;
3545
3546       /* Skip ,0, */
3547       if (p[0] != ',' || p[1] != '0' || p[2] != ',' || !ISDIGIT (p[3]))
3548         {
3549           error ("invalid line number .stabs/.stabn directive");
3550           return;
3551         }
3552
3553       code = strtol (p+3, &p, 0);
3554       ch = *++p;
3555       if (p[-1] != ',' || ISDIGIT (ch) || !IS_ASM_IDENT (ch))
3556         {
3557           error ("invalid line number .stabs/.stabn directive");
3558           return;
3559         }
3560
3561       dummy_symr.index = code;
3562       if (dummy_symr.index != code)
3563         {
3564           error ("line number (%lu) for .stabs/.stabn directive cannot fit in index field (20 bits)",
3565                  code);
3566
3567           return;
3568         }
3569
3570       shash_ptr = hash_string (p,
3571                                strlen (p) - 1,
3572                                &orig_str_hash[0],
3573                                (symint_t *) 0);
3574
3575       if (shash_ptr == (shash_t *) 0
3576           || (sym_ptr = shash_ptr->sym_ptr) == (SYMR *) 0)
3577         {
3578           error ("invalid .stabs/.stabn directive, value not found");
3579           return;
3580         }
3581
3582       if ((st_t) sym_ptr->st != st_Label)
3583         {
3584           error ("invalid line number .stabs/.stabn directive");
3585           return;
3586         }
3587
3588       st = st_Label;
3589       sc = (sc_t) sym_ptr->sc;
3590       value = sym_ptr->value;
3591     }
3592   else
3593     {
3594       /* Skip ,<num>,<num>, */
3595       if (*p++ != ',')
3596         goto failure;
3597       for (; ISDIGIT (*p); p++)
3598         ;
3599       if (*p++ != ',')
3600         goto failure;
3601       for (; ISDIGIT (*p); p++)
3602         ;
3603       if (*p++ != ',')
3604         goto failure;
3605       ch = *p;
3606       if (!IS_ASM_IDENT (ch) && ch != '-')
3607         {
3608         failure:
3609           error ("invalid .stabs/.stabn directive, bad character");
3610           return;
3611         }
3612
3613       if (ISDIGIT (ch) || ch == '-')
3614         {
3615           st = st_Nil;
3616           sc = sc_Nil;
3617           value = strtol (p, &p, 0);
3618           if (*p != '\n')
3619             {
3620               error ("invalid .stabs/.stabn directive, stuff after numeric value");
3621               return;
3622             }
3623         }
3624       else if (!IS_ASM_IDENT (ch))
3625         {
3626           error ("invalid .stabs/.stabn directive, bad character");
3627           return;
3628         }
3629       else
3630         {
3631           SYMR *sym_ptr;
3632           shash_t *shash_ptr;
3633           const char *start, *end_p1;
3634
3635           start = p;
3636           if ((end_p1 = strchr (start, '+')) == (char *) 0)
3637             {
3638               if ((end_p1 = strchr (start, '-')) == (char *) 0)
3639                 end_p1 = start + strlen (start) - 1;
3640             }
3641
3642           shash_ptr = hash_string (start,
3643                                    end_p1 - start,
3644                                    &orig_str_hash[0],
3645                                    (symint_t *) 0);
3646
3647           if (shash_ptr == (shash_t *) 0
3648               || (sym_ptr = shash_ptr->sym_ptr) == (SYMR *) 0)
3649             {
3650               shash_ptr = hash_string (start,
3651                                        end_p1 - start,
3652                                        &ext_str_hash[0],
3653                                        (symint_t *) 0);
3654
3655               if (shash_ptr == (shash_t *) 0
3656                   || shash_ptr->esym_ptr == (EXTR *) 0)
3657                 {
3658                   error ("invalid .stabs/.stabn directive, value not found");
3659                   return;
3660                 }
3661               else
3662                 sym_ptr = &(shash_ptr->esym_ptr->asym);
3663             }
3664
3665           /* Traditionally, N_LBRAC and N_RBRAC are *not* relocated.  */
3666           if (code == (int) N_LBRAC || code == (int) N_RBRAC)
3667             {
3668               sc = (sc_t) scNil;
3669               st = (st_t) stNil;
3670             }
3671           else
3672             {
3673               sc = (sc_t) sym_ptr->sc;
3674               st = (st_t) sym_ptr->st;
3675             }
3676           value = sym_ptr->value;
3677
3678           ch = *end_p1++;
3679           if (ch != '\n')
3680             {
3681               if (((!ISDIGIT (*end_p1)) && (*end_p1 != '-'))
3682                   || ((ch != '+') && (ch != '-')))
3683                 {
3684                   error ("invalid .stabs/.stabn directive, badly formed value");
3685                   return;
3686                 }
3687               if (ch == '+')
3688                 value += strtol (end_p1, &p, 0);
3689               else if (ch == '-')
3690                 value -= strtol (end_p1, &p, 0);
3691
3692               if (*p != '\n')
3693                 {
3694                   error ("invalid .stabs/.stabn directive, stuff after numeric value");
3695                   return;
3696                 }
3697             }
3698         }
3699       code = MIPS_MARK_STAB (code);
3700     }
3701
3702   (void) add_local_symbol (string_start, string_end, st, sc, value, code);
3703   /* Restore normal file type.  */
3704   cur_file_ptr = save_file_ptr;
3705 }
3706
3707
3708 STATIC void
3709 parse_stabs (const char *start)
3710 {
3711   const char *end = strchr (start+1, '"');
3712
3713   if (*start != '"' || end == (const char *) 0 || end[1] != ',')
3714     {
3715       error ("invalid .stabs directive, no string");
3716       return;
3717     }
3718
3719   parse_stabs_common (start+1, end, end+2);
3720 }
3721
3722
3723 STATIC void
3724 parse_stabn (const char *start)
3725 {
3726   parse_stabs_common ((const char *) 0, (const char *) 0, start);
3727 }
3728
3729 \f
3730 /* Parse the input file, and write the lines to the output file
3731    if needed.  */
3732
3733 STATIC void
3734 parse_input (void)
3735 {
3736   char *p;
3737   Size_t i;
3738   thead_t *ptag_head;
3739   tag_t *ptag;
3740   tag_t *ptag_next;
3741
3742   if (debug)
3743     fprintf (stderr, "\tinput\n");
3744
3745   /* Add a dummy scope block around the entire compilation unit for
3746      structures defined outside of blocks.  */
3747   ptag_head = allocate_thead ();
3748   ptag_head->first_tag = 0;
3749   ptag_head->prev = cur_tag_head;
3750   cur_tag_head = ptag_head;
3751
3752   while ((p = read_line ()) != (char *) 0)
3753     {
3754       /* Skip leading blanks.  */
3755       while (ISSPACE ((unsigned char)*p))
3756         p++;
3757
3758       /* See if it's a directive we handle.  If so, dispatch handler.  */
3759       for (i = 0; i < ARRAY_SIZE (pseudo_ops); i++)
3760         if (memcmp (p, pseudo_ops[i].name, pseudo_ops[i].len) == 0
3761             && ISSPACE ((unsigned char)(p[pseudo_ops[i].len])))
3762           {
3763             p += pseudo_ops[i].len;     /* skip to first argument */
3764             while (ISSPACE ((unsigned char)*p))
3765               p++;
3766
3767             (*pseudo_ops[i].func)( p );
3768             break;
3769           }
3770     }
3771
3772   /* Process any tags at global level.  */
3773   ptag_head = cur_tag_head;
3774   cur_tag_head = ptag_head->prev;
3775
3776   for (ptag = ptag_head->first_tag;
3777        ptag != (tag_t *) 0;
3778        ptag = ptag_next)
3779     {
3780       if (ptag->forward_ref != (forward_t *) 0)
3781         add_unknown_tag (ptag);
3782
3783       ptag_next = ptag->same_block;
3784       ptag->hash_ptr->tag_ptr = ptag->same_name;
3785       free_tag (ptag);
3786     }
3787
3788   free_thead (ptag_head);
3789
3790 }
3791
3792 \f
3793 /* Update the global headers with the final offsets in preparation
3794    to write out the .T file.  */
3795
3796 STATIC void
3797 update_headers (void)
3798 {
3799   symint_t i;
3800   efdr_t *file_ptr;
3801
3802   /* Set up the symbolic header.  */
3803   file_offset = sizeof (symbolic_header) + orig_file_header.f_symptr;
3804   symbolic_header.magic = orig_sym_hdr.magic;
3805   symbolic_header.vstamp = orig_sym_hdr.vstamp;
3806
3807   /* Set up global counts.  */
3808   symbolic_header.issExtMax = ext_strings.num_allocated;
3809   symbolic_header.idnMax    = dense_num.num_allocated;
3810   symbolic_header.ifdMax    = file_desc.num_allocated;
3811   symbolic_header.iextMax   = ext_symbols.num_allocated;
3812   symbolic_header.ilineMax  = orig_sym_hdr.ilineMax;
3813   symbolic_header.ioptMax   = orig_sym_hdr.ioptMax;
3814   symbolic_header.cbLine    = orig_sym_hdr.cbLine;
3815   symbolic_header.crfd      = orig_sym_hdr.crfd;
3816
3817
3818   /* Loop through each file, figuring out how many local syms,
3819      line numbers, etc. there are.  Also, put out end symbol
3820      for the filename.  */
3821
3822   for (file_ptr = first_file;
3823        file_ptr != (efdr_t *) 0;
3824        file_ptr = file_ptr->next_file)
3825     {
3826       SYMR *sym_start;
3827       SYMR *sym;
3828       SYMR *sym_end_p1;
3829       FDR *fd_ptr = file_ptr->orig_fdr;
3830
3831       cur_file_ptr = file_ptr;
3832
3833       /* Copy st_Static symbols from the original local symbol table if
3834          they did not get added to the new local symbol table.
3835          This happens with stabs-in-ecoff or if the source file is
3836          compiled without debugging.  */
3837       sym_start = ORIG_LSYMS (fd_ptr->isymBase);
3838       sym_end_p1 = sym_start + fd_ptr->csym;
3839       for (sym = sym_start; sym < sym_end_p1; sym++)
3840         {
3841           if ((st_t) sym->st == st_Static)
3842             {
3843               char *str = ORIG_LSTRS (fd_ptr->issBase + sym->iss);
3844               Size_t len = strlen (str);
3845               shash_t *hash_ptr;
3846
3847               /* Ignore internal labels.  */
3848               if (str[0] == '$' && str[1] == 'L')
3849                 continue;
3850               hash_ptr = hash_string (str,
3851                                       (Ptrdiff_t) len,
3852                                       &file_ptr->shash_head[0],
3853                                       (symint_t *) 0);
3854               if (hash_ptr == (shash_t *) 0)
3855                 {
3856                   (void) add_local_symbol (str, str + len,
3857                                            (st_t) sym->st, (sc_t) sym->sc,
3858                                            (symint_t) sym->value,
3859                                            (symint_t) indexNil);
3860                 }
3861             }
3862         }
3863       (void) add_local_symbol ((const char *) 0, (const char *) 0,
3864                                st_End, sc_Text,
3865                                (symint_t) 0,
3866                                (symint_t) 0);
3867
3868       file_ptr->fdr.cpd = file_ptr->procs.num_allocated;
3869       file_ptr->fdr.ipdFirst = symbolic_header.ipdMax;
3870       symbolic_header.ipdMax += file_ptr->fdr.cpd;
3871
3872       file_ptr->fdr.csym = file_ptr->symbols.num_allocated;
3873       file_ptr->fdr.isymBase = symbolic_header.isymMax;
3874       symbolic_header.isymMax += file_ptr->fdr.csym;
3875
3876       file_ptr->fdr.caux = file_ptr->aux_syms.num_allocated;
3877       file_ptr->fdr.iauxBase = symbolic_header.iauxMax;
3878       symbolic_header.iauxMax += file_ptr->fdr.caux;
3879
3880       file_ptr->fdr.cbSs = file_ptr->strings.num_allocated;
3881       file_ptr->fdr.issBase = symbolic_header.issMax;
3882       symbolic_header.issMax += file_ptr->fdr.cbSs;
3883     }
3884
3885 #ifndef ALIGN_SYMTABLE_OFFSET
3886 #define ALIGN_SYMTABLE_OFFSET(OFFSET) (OFFSET)
3887 #endif
3888
3889   file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
3890   i = WORD_ALIGN (symbolic_header.cbLine);      /* line numbers */
3891   if (i > 0)
3892     {
3893       symbolic_header.cbLineOffset = file_offset;
3894       file_offset += i;
3895       file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
3896     }
3897
3898   i = symbolic_header.ioptMax;                  /* optimization symbols */
3899   if (((long) i) > 0)
3900     {
3901       symbolic_header.cbOptOffset = file_offset;
3902       file_offset += i * sizeof (OPTR);
3903       file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
3904     }
3905
3906   i = symbolic_header.idnMax;                   /* dense numbers */
3907   if (i > 0)
3908     {
3909       symbolic_header.cbDnOffset = file_offset;
3910       file_offset += i * sizeof (DNR);
3911       file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
3912     }
3913
3914   i = symbolic_header.ipdMax;                   /* procedure tables */
3915   if (i > 0)
3916     {
3917       symbolic_header.cbPdOffset = file_offset;
3918       file_offset += i * sizeof (PDR);
3919       file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
3920     }
3921
3922   i = symbolic_header.isymMax;                  /* local symbols */
3923   if (i > 0)
3924     {
3925       symbolic_header.cbSymOffset = file_offset;
3926       file_offset += i * sizeof (SYMR);
3927       file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
3928     }
3929
3930   i = symbolic_header.iauxMax;                  /* aux syms.  */
3931   if (i > 0)
3932     {
3933       symbolic_header.cbAuxOffset = file_offset;
3934       file_offset += i * sizeof (TIR);
3935       file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
3936     }
3937
3938   i = WORD_ALIGN (symbolic_header.issMax);      /* local strings */
3939   if (i > 0)
3940     {
3941       symbolic_header.cbSsOffset = file_offset;
3942       file_offset += i;
3943       file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
3944     }
3945
3946   i = WORD_ALIGN (symbolic_header.issExtMax);   /* external strings */
3947   if (i > 0)
3948     {
3949       symbolic_header.cbSsExtOffset = file_offset;
3950       file_offset += i;
3951       file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
3952     }
3953
3954   i = symbolic_header.ifdMax;                   /* file tables */
3955   if (i > 0)
3956     {
3957       symbolic_header.cbFdOffset = file_offset;
3958       file_offset += i * sizeof (FDR);
3959       file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
3960     }
3961
3962   i = symbolic_header.crfd;                     /* relative file descriptors */
3963   if (i > 0)
3964     {
3965       symbolic_header.cbRfdOffset = file_offset;
3966       file_offset += i * sizeof (symint_t);
3967       file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
3968     }
3969
3970   i = symbolic_header.iextMax;                  /* external symbols */
3971   if (i > 0)
3972     {
3973       symbolic_header.cbExtOffset = file_offset;
3974       file_offset += i * sizeof (EXTR);
3975       file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
3976     }
3977 }
3978
3979 \f
3980 /* Write out a varray at a given location.  */
3981
3982 STATIC void
3983 write_varray (varray_t *vp,    /* virtual array */
3984               off_t offset,    /* offset to write varray to */
3985               const char *str) /* string to print out when tracing */
3986 {
3987   int num_write, sys_write;
3988   vlinks_t *ptr;
3989
3990   if (vp->num_allocated == 0)
3991     return;
3992
3993   if (debug)
3994     fprintf (stderr, "\twarray\tvp = " HOST_PTR_PRINTF
3995             ", offset = %7lu, size = %7lu, %s\n",
3996              (void *) vp, (unsigned long) offset,
3997              vp->num_allocated * vp->object_size, str);
3998
3999   if (file_offset != (unsigned long) offset
4000       && fseek (object_stream, (long) offset, SEEK_SET) < 0)
4001     pfatal_with_name (object_name);
4002
4003   for (ptr = vp->first; ptr != (vlinks_t *) 0; ptr = ptr->next)
4004     {
4005       num_write = (ptr->next == (vlinks_t *) 0)
4006         ? vp->objects_last_page * vp->object_size
4007         : vp->objects_per_page  * vp->object_size;
4008
4009       sys_write = fwrite (ptr->datum, 1, num_write, object_stream);
4010       if (sys_write <= 0)
4011         pfatal_with_name (object_name);
4012
4013       else if (sys_write != num_write)
4014         fatal ("wrote %d bytes to %s, system returned %d",
4015                num_write,
4016                object_name,
4017                sys_write);
4018
4019       file_offset += num_write;
4020     }
4021 }
4022
4023 \f
4024 /* Write out the symbol table in the object file.  */
4025
4026 STATIC void
4027 write_object (void)
4028 {
4029   int sys_write;
4030   efdr_t *file_ptr;
4031   off_t offset;
4032
4033   if (debug)
4034     fprintf (stderr, "\n\twrite\tvp = " HOST_PTR_PRINTF
4035             ", offset = %7u, size = %7lu, %s\n",
4036              (void *) &symbolic_header, 0,
4037              (unsigned long) sizeof (symbolic_header), "symbolic header");
4038
4039   sys_write = fwrite (&symbolic_header,
4040                       1,
4041                       sizeof (symbolic_header),
4042                       object_stream);
4043
4044   if (sys_write < 0)
4045     pfatal_with_name (object_name);
4046
4047   else if (sys_write != sizeof (symbolic_header))
4048     fatal ("wrote %d bytes to %s, system returned %d",
4049            (int) sizeof (symbolic_header),
4050            object_name,
4051            sys_write);
4052
4053
4054   file_offset = sizeof (symbolic_header) + orig_file_header.f_symptr;
4055
4056   if (symbolic_header.cbLine > 0)               /* line numbers */
4057     {
4058       long sys_write;
4059
4060       if (file_offset != (unsigned long) symbolic_header.cbLineOffset
4061           && fseek (object_stream, symbolic_header.cbLineOffset, SEEK_SET) != 0)
4062         pfatal_with_name (object_name);
4063
4064       if (debug)
4065         fprintf (stderr, "\twrite\tvp = " HOST_PTR_PRINTF
4066                 ", offset = %7lu, size = %7lu, %s\n",
4067                  (void *) &orig_linenum, (long) symbolic_header.cbLineOffset,
4068                  (long) symbolic_header.cbLine, "Line numbers");
4069
4070       sys_write = fwrite (orig_linenum,
4071                           1,
4072                           symbolic_header.cbLine,
4073                           object_stream);
4074
4075       if (sys_write <= 0)
4076         pfatal_with_name (object_name);
4077
4078       else if (sys_write != symbolic_header.cbLine)
4079         fatal ("wrote %ld bytes to %s, system returned %ld",
4080                (long) symbolic_header.cbLine,
4081                object_name,
4082                sys_write);
4083
4084       file_offset = symbolic_header.cbLineOffset + symbolic_header.cbLine;
4085     }
4086
4087   if (symbolic_header.ioptMax > 0)              /* optimization symbols */
4088     {
4089       long sys_write;
4090       long num_write = symbolic_header.ioptMax * sizeof (OPTR);
4091
4092       if (file_offset != (unsigned long) symbolic_header.cbOptOffset
4093           && fseek (object_stream, symbolic_header.cbOptOffset, SEEK_SET) != 0)
4094         pfatal_with_name (object_name);
4095
4096       if (debug)
4097         fprintf (stderr, "\twrite\tvp = " HOST_PTR_PRINTF
4098                 ", offset = %7lu, size = %7lu, %s\n",
4099                  (void *) &orig_opt_syms, (long) symbolic_header.cbOptOffset,
4100                  num_write, "Optimizer symbols");
4101
4102       sys_write = fwrite (orig_opt_syms,
4103                           1,
4104                           num_write,
4105                           object_stream);
4106
4107       if (sys_write <= 0)
4108         pfatal_with_name (object_name);
4109
4110       else if (sys_write != num_write)
4111         fatal ("wrote %ld bytes to %s, system returned %ld",
4112                num_write,
4113                object_name,
4114                sys_write);
4115
4116       file_offset = symbolic_header.cbOptOffset + num_write;
4117     }
4118
4119   if (symbolic_header.idnMax > 0)               /* dense numbers */
4120     write_varray (&dense_num, (off_t) symbolic_header.cbDnOffset, "Dense numbers");
4121
4122   if (symbolic_header.ipdMax > 0)               /* procedure tables */
4123     {
4124       offset = symbolic_header.cbPdOffset;
4125       for (file_ptr = first_file;
4126            file_ptr != (efdr_t *) 0;
4127            file_ptr = file_ptr->next_file)
4128         {
4129           write_varray (&file_ptr->procs, offset, "Procedure tables");
4130           offset = file_offset;
4131         }
4132     }
4133
4134   if (symbolic_header.isymMax > 0)              /* local symbols */
4135     {
4136       offset = symbolic_header.cbSymOffset;
4137       for (file_ptr = first_file;
4138            file_ptr != (efdr_t *) 0;
4139            file_ptr = file_ptr->next_file)
4140         {
4141           write_varray (&file_ptr->symbols, offset, "Local symbols");
4142           offset = file_offset;
4143         }
4144     }
4145
4146   if (symbolic_header.iauxMax > 0)              /* aux symbols */
4147     {
4148       offset = symbolic_header.cbAuxOffset;
4149       for (file_ptr = first_file;
4150            file_ptr != (efdr_t *) 0;
4151            file_ptr = file_ptr->next_file)
4152         {
4153           write_varray (&file_ptr->aux_syms, offset, "Aux. symbols");
4154           offset = file_offset;
4155         }
4156     }
4157
4158   if (symbolic_header.issMax > 0)               /* local strings */
4159     {
4160       offset = symbolic_header.cbSsOffset;
4161       for (file_ptr = first_file;
4162            file_ptr != (efdr_t *) 0;
4163            file_ptr = file_ptr->next_file)
4164         {
4165           write_varray (&file_ptr->strings, offset, "Local strings");
4166           offset = file_offset;
4167         }
4168     }
4169
4170   if (symbolic_header.issExtMax > 0)            /* external strings */
4171     write_varray (&ext_strings, symbolic_header.cbSsExtOffset, "External strings");
4172
4173   if (symbolic_header.ifdMax > 0)               /* file tables */
4174     {
4175       offset = symbolic_header.cbFdOffset;
4176       if (file_offset != (unsigned long) offset
4177           && fseek (object_stream, (long) offset, SEEK_SET) < 0)
4178         pfatal_with_name (object_name);
4179
4180       file_offset = offset;
4181       for (file_ptr = first_file;
4182            file_ptr != (efdr_t *) 0;
4183            file_ptr = file_ptr->next_file)
4184         {
4185           if (debug)
4186             fprintf (stderr, "\twrite\tvp = " HOST_PTR_PRINTF
4187                     ", offset = %7lu, size = %7lu, %s\n",
4188                      (void *) &file_ptr->fdr, file_offset,
4189                      (unsigned long) sizeof (FDR), "File header");
4190
4191           sys_write = fwrite (&file_ptr->fdr,
4192                               1,
4193                               sizeof (FDR),
4194                               object_stream);
4195
4196           if (sys_write < 0)
4197             pfatal_with_name (object_name);
4198
4199           else if (sys_write != sizeof (FDR))
4200             fatal ("wrote %d bytes to %s, system returned %d",
4201                    (int) sizeof (FDR),
4202                    object_name,
4203                    sys_write);
4204
4205           file_offset = offset += sizeof (FDR);
4206         }
4207     }
4208
4209   if (symbolic_header.crfd > 0)                 /* relative file descriptors */
4210     {
4211       long sys_write;
4212       symint_t num_write = symbolic_header.crfd * sizeof (symint_t);
4213
4214       if (file_offset != (unsigned long) symbolic_header.cbRfdOffset
4215           && fseek (object_stream, symbolic_header.cbRfdOffset, SEEK_SET) != 0)
4216         pfatal_with_name (object_name);
4217
4218       if (debug)
4219         fprintf (stderr, "\twrite\tvp = " HOST_PTR_PRINTF
4220                 ", offset = %7lu, size = %7lu, %s\n",
4221                  (void *) &orig_rfds, (long) symbolic_header.cbRfdOffset,
4222                  num_write, "Relative file descriptors");
4223
4224       sys_write = fwrite (orig_rfds,
4225                           1,
4226                           num_write,
4227                           object_stream);
4228
4229       if (sys_write <= 0)
4230         pfatal_with_name (object_name);
4231
4232       else if (sys_write != (long) num_write)
4233         fatal ("wrote %lu bytes to %s, system returned %ld",
4234                num_write,
4235                object_name,
4236                sys_write);
4237
4238       file_offset = symbolic_header.cbRfdOffset + num_write;
4239     }
4240
4241   if (symbolic_header.issExtMax > 0)            /* external symbols */
4242     write_varray (&ext_symbols, (off_t) symbolic_header.cbExtOffset, "External symbols");
4243
4244   if (fclose (object_stream) != 0)
4245     pfatal_with_name (object_name);
4246 }
4247
4248 \f
4249 /* Read some bytes at a specified location, and return a pointer.  */
4250
4251 STATIC page_t *
4252 read_seek (Size_t size,         /* # bytes to read */
4253            off_t offset,        /* offset to read at */
4254            const char *str)     /* name for tracing */
4255 {
4256   page_t *ptr;
4257   long sys_read = 0;
4258
4259   if (size == 0)                /* nothing to read */
4260     return (page_t *) 0;
4261
4262   if (debug)
4263     fprintf (stderr,
4264              "\trseek\tsize = %7lu, offset = %7lu, currently at %7lu, %s\n",
4265              (unsigned long) size, (unsigned long) offset, file_offset, str);
4266
4267 #ifndef MALLOC_CHECK
4268   ptr = allocate_multiple_pages ((size + PAGE_USIZE - 1) / PAGE_USIZE);
4269 #else
4270   ptr = xcalloc (1, size);
4271 #endif
4272
4273   /* If we need to seek, and the distance is nearby, just do some reads,
4274      to speed things up.  */
4275   if (file_offset != (unsigned long) offset)
4276     {
4277       symint_t difference = offset - file_offset;
4278
4279       if (difference < 8)
4280         {
4281           char small_buffer[8];
4282
4283           sys_read = fread (small_buffer, 1, difference, obj_in_stream);
4284           if (sys_read <= 0)
4285             pfatal_with_name (obj_in_name);
4286
4287           if ((symint_t) sys_read != difference)
4288             fatal ("wanted to read %lu bytes from %s, system returned %ld",
4289                    (unsigned long) size,
4290                    obj_in_name,
4291                    sys_read);
4292         }
4293       else if (fseek (obj_in_stream, offset, SEEK_SET) < 0)
4294         pfatal_with_name (obj_in_name);
4295     }
4296
4297   sys_read = fread (ptr, 1, size, obj_in_stream);
4298   if (sys_read <= 0)
4299     pfatal_with_name (obj_in_name);
4300
4301   if (sys_read != (long) size)
4302     fatal ("wanted to read %lu bytes from %s, system returned %ld",
4303            (unsigned long) size,
4304            obj_in_name,
4305            sys_read);
4306
4307   file_offset = offset + size;
4308
4309   if (file_offset > max_file_offset)
4310     max_file_offset = file_offset;
4311
4312   return ptr;
4313 }
4314
4315 \f
4316 /* Read the existing object file (and copy to the output object file
4317    if it is different from the input object file), and remove the old
4318    symbol table.  */
4319
4320 STATIC void
4321 copy_object (void)
4322 {
4323   char buffer[ PAGE_SIZE ];
4324   int sys_read;
4325   int remaining;
4326   int num_write;
4327   int sys_write;
4328   int fd, es;
4329   int delete_ifd = 0;
4330   int *remap_file_number;
4331   struct stat stat_buf;
4332
4333   if (debug)
4334     fprintf (stderr, "\tcopy\n");
4335
4336   if (fstat (fileno (obj_in_stream), &stat_buf) != 0
4337       || fseek (obj_in_stream, 0L, SEEK_SET) != 0)
4338     pfatal_with_name (obj_in_name);
4339
4340   sys_read = fread (&orig_file_header,
4341                     1,
4342                     sizeof (struct filehdr),
4343                     obj_in_stream);
4344
4345   if (sys_read < 0)
4346     pfatal_with_name (obj_in_name);
4347
4348   else if (sys_read == 0 && feof (obj_in_stream))
4349     return;                     /* create a .T file sans file header */
4350
4351   else if (sys_read < (int) sizeof (struct filehdr))
4352     fatal ("wanted to read %d bytes from %s, system returned %d",
4353            (int) sizeof (struct filehdr),
4354            obj_in_name,
4355            sys_read);
4356
4357
4358   if (orig_file_header.f_nsyms != sizeof (HDRR))
4359     fatal ("%s symbolic header wrong size (%ld bytes, should be %ld)",
4360            input_name, (long) orig_file_header.f_nsyms, (long) sizeof (HDRR));
4361
4362
4363   /* Read in the current symbolic header.  */
4364   if (fseek (obj_in_stream, (long) orig_file_header.f_symptr, SEEK_SET) != 0)
4365     pfatal_with_name (input_name);
4366
4367   sys_read = fread (&orig_sym_hdr,
4368                     1,
4369                     sizeof (orig_sym_hdr),
4370                     obj_in_stream);
4371
4372   if (sys_read < 0)
4373     pfatal_with_name (object_name);
4374
4375   else if (sys_read < (int) sizeof (struct filehdr))
4376     fatal ("wanted to read %d bytes from %s, system returned %d",
4377            (int) sizeof (struct filehdr),
4378            obj_in_name,
4379            sys_read);
4380
4381
4382   /* Read in each of the sections if they exist in the object file.
4383      We read things in the order the mips assembler creates the
4384      sections, so in theory no extra seeks are done.
4385
4386      For simplicity sake, round each read up to a page boundary,
4387      we may want to revisit this later....  */
4388
4389   file_offset =  orig_file_header.f_symptr + sizeof (struct filehdr);
4390
4391   if (orig_sym_hdr.cbLine > 0)                  /* line numbers */
4392     orig_linenum = (char *) read_seek (orig_sym_hdr.cbLine,
4393                                        orig_sym_hdr.cbLineOffset,
4394                                        "Line numbers");
4395
4396   if (orig_sym_hdr.ipdMax > 0)                  /* procedure tables */
4397     orig_procs = (PDR *) read_seek (orig_sym_hdr.ipdMax * sizeof (PDR),
4398                                     orig_sym_hdr.cbPdOffset,
4399                                     "Procedure tables");
4400
4401   if (orig_sym_hdr.isymMax > 0)                 /* local symbols */
4402     orig_local_syms = (SYMR *) read_seek (orig_sym_hdr.isymMax * sizeof (SYMR),
4403                                           orig_sym_hdr.cbSymOffset,
4404                                           "Local symbols");
4405
4406   if (orig_sym_hdr.iauxMax > 0)                 /* aux symbols */
4407     orig_aux_syms = (AUXU *) read_seek (orig_sym_hdr.iauxMax * sizeof (AUXU),
4408                                         orig_sym_hdr.cbAuxOffset,
4409                                         "Aux. symbols");
4410
4411   if (orig_sym_hdr.issMax > 0)                  /* local strings */
4412     orig_local_strs = (char *) read_seek (orig_sym_hdr.issMax,
4413                                           orig_sym_hdr.cbSsOffset,
4414                                           "Local strings");
4415
4416   if (orig_sym_hdr.issExtMax > 0)               /* external strings */
4417     orig_ext_strs = (char *) read_seek (orig_sym_hdr.issExtMax,
4418                                         orig_sym_hdr.cbSsExtOffset,
4419                                         "External strings");
4420
4421   if (orig_sym_hdr.ifdMax > 0)                  /* file tables */
4422     orig_files = (FDR *) read_seek (orig_sym_hdr.ifdMax * sizeof (FDR),
4423                                     orig_sym_hdr.cbFdOffset,
4424                                     "File tables");
4425
4426   if (orig_sym_hdr.crfd > 0)                    /* relative file descriptors */
4427     orig_rfds = (symint_t *) read_seek (orig_sym_hdr.crfd * sizeof (symint_t),
4428                                         orig_sym_hdr.cbRfdOffset,
4429                                         "Relative file descriptors");
4430
4431   if (orig_sym_hdr.issExtMax > 0)               /* external symbols */
4432     orig_ext_syms = (EXTR *) read_seek (orig_sym_hdr.iextMax * sizeof (EXTR),
4433                                         orig_sym_hdr.cbExtOffset,
4434                                         "External symbols");
4435
4436   if (orig_sym_hdr.idnMax > 0)                  /* dense numbers */
4437     {
4438       orig_dense = (DNR *) read_seek (orig_sym_hdr.idnMax * sizeof (DNR),
4439                                       orig_sym_hdr.cbDnOffset,
4440                                       "Dense numbers");
4441
4442       add_bytes (&dense_num, (char *) orig_dense, orig_sym_hdr.idnMax);
4443     }
4444
4445   if (orig_sym_hdr.ioptMax > 0)                 /* opt symbols */
4446     orig_opt_syms = (OPTR *) read_seek (orig_sym_hdr.ioptMax * sizeof (OPTR),
4447                                         orig_sym_hdr.cbOptOffset,
4448                                         "Optimizer symbols");
4449
4450
4451
4452   /* The symbol table should be last.  */
4453   if (max_file_offset != (unsigned long) stat_buf.st_size)
4454     fatal ("symbol table is not last (symbol table ends at %ld, .o ends at %ld",
4455            max_file_offset,
4456            (long) stat_buf.st_size);
4457
4458
4459   /* If the first original file descriptor is a dummy which the assembler
4460      put out, but there are no symbols in it, skip it now.  */
4461   if (orig_sym_hdr.ifdMax > 1
4462       && orig_files->csym == 2
4463       && orig_files->caux == 0)
4464     {
4465       char *filename = orig_local_strs + (orig_files->issBase + orig_files->rss);
4466       char *suffix = strrchr (filename, '.');
4467
4468       if (suffix != (char *) 0 && strcmp (suffix, ".s") == 0)
4469         delete_ifd = 1;
4470     }
4471
4472
4473   /* Create array to map original file numbers to the new file numbers
4474      (in case there are duplicate filenames, we collapse them into one
4475      file section, the MIPS assembler may or may not collapse them).  */
4476
4477   remap_file_number = (int *) alloca (sizeof (int) * orig_sym_hdr.ifdMax);
4478
4479   for (fd = delete_ifd; fd < orig_sym_hdr.ifdMax; fd++)
4480     {
4481       FDR *fd_ptr = ORIG_FILES (fd);
4482       char *filename = ORIG_LSTRS (fd_ptr->issBase + fd_ptr->rss);
4483
4484       /* file support itself.  */
4485       add_file (filename, filename + strlen (filename));
4486       remap_file_number[fd] = cur_file_ptr->file_index;
4487     }
4488
4489   if (delete_ifd > 0)           /* just in case */
4490     remap_file_number[0] = remap_file_number[1];
4491
4492
4493   /* Loop, adding each of the external symbols.  These must be in
4494      order or otherwise we would have to change the relocation
4495      entries.  We don't just call add_bytes, because we need to have
4496      the names put into the external hash table.  We set the type to
4497      'void' for now, and parse_def will fill in the correct type if it
4498      is in the symbol table.  We must add the external symbols before
4499      the locals, since the locals do lookups against the externals.  */
4500
4501   if (debug)
4502     fprintf (stderr, "\tehash\n");
4503
4504   for (es = 0; es < orig_sym_hdr.iextMax; es++)
4505     {
4506       EXTR *eptr = orig_ext_syms + es;
4507       int ifd = eptr->ifd;
4508
4509       (void) add_ext_symbol (eptr, ((long) ifd < orig_sym_hdr.ifdMax)
4510                              ? remap_file_number[ ifd ] : ifd );
4511     }
4512
4513
4514   /* For each of the files in the object file, copy the symbols, and such
4515      into the varrays for the new object file.  */
4516
4517   for (fd = delete_ifd; fd < orig_sym_hdr.ifdMax; fd++)
4518     {
4519       FDR *fd_ptr = ORIG_FILES (fd);
4520       char *filename = ORIG_LSTRS (fd_ptr->issBase + fd_ptr->rss);
4521       SYMR *sym_start;
4522       SYMR *sym;
4523       SYMR *sym_end_p1;
4524       PDR *proc_start;
4525       PDR *proc;
4526       PDR *proc_end_p1;
4527
4528       /* file support itself.  */
4529       add_file (filename, filename + strlen (filename));
4530       cur_file_ptr->orig_fdr = fd_ptr;
4531
4532       /* Copy stuff that's just passed through (such as line #'s) */
4533       cur_file_ptr->fdr.adr          = fd_ptr->adr;
4534       cur_file_ptr->fdr.ilineBase    = fd_ptr->ilineBase;
4535       cur_file_ptr->fdr.cline        = fd_ptr->cline;
4536       cur_file_ptr->fdr.rfdBase      = fd_ptr->rfdBase;
4537       cur_file_ptr->fdr.crfd         = fd_ptr->crfd;
4538       cur_file_ptr->fdr.cbLineOffset = fd_ptr->cbLineOffset;
4539       cur_file_ptr->fdr.cbLine       = fd_ptr->cbLine;
4540       cur_file_ptr->fdr.fMerge       = fd_ptr->fMerge;
4541       cur_file_ptr->fdr.fReadin      = fd_ptr->fReadin;
4542       cur_file_ptr->fdr.glevel       = fd_ptr->glevel;
4543
4544       if (debug)
4545         fprintf (stderr, "\thash\tstart, filename %s\n", filename);
4546
4547       /* For each of the static and global symbols defined, add them
4548          to the hash table of original symbols, so we can look up
4549          their values.  */
4550
4551       sym_start = ORIG_LSYMS (fd_ptr->isymBase);
4552       sym_end_p1 = sym_start + fd_ptr->csym;
4553       for (sym = sym_start; sym < sym_end_p1; sym++)
4554         {
4555           switch ((st_t) sym->st)
4556             {
4557             default:
4558               break;
4559
4560             case st_Global:
4561             case st_Static:
4562             case st_Label:
4563             case st_Proc:
4564             case st_StaticProc:
4565               {
4566                 auto symint_t hash_index;
4567                 char *str = ORIG_LSTRS (fd_ptr->issBase + sym->iss);
4568                 Size_t len = strlen (str);
4569                 shash_t *shash_ptr = hash_string (str,
4570                                                   (Ptrdiff_t) len,
4571                                                   &orig_str_hash[0],
4572                                                   &hash_index);
4573
4574                 if (shash_ptr != (shash_t *) 0)
4575                   error ("internal error, %s is already in original symbol table", str);
4576
4577                 else
4578                   {
4579                     shash_ptr = allocate_shash ();
4580                     shash_ptr->next = orig_str_hash[hash_index];
4581                     orig_str_hash[hash_index] = shash_ptr;
4582
4583                     shash_ptr->len = len;
4584                     shash_ptr->indx = indexNil;
4585                     shash_ptr->string = str;
4586                     shash_ptr->sym_ptr = sym;
4587                   }
4588               }
4589               break;
4590
4591             case st_End:
4592               if ((sc_t) sym->sc == sc_Text)
4593                 {
4594                   char *str = ORIG_LSTRS (fd_ptr->issBase + sym->iss);
4595
4596                   if (*str != '\0')
4597                     {
4598                       Size_t len = strlen (str);
4599                       shash_t *shash_ptr = hash_string (str,
4600                                                         (Ptrdiff_t) len,
4601                                                         &orig_str_hash[0],
4602                                                         (symint_t *) 0);
4603
4604                       if (shash_ptr != (shash_t *) 0)
4605                         shash_ptr->end_ptr = sym;
4606                     }
4607                 }
4608               break;
4609
4610             }
4611         }
4612
4613       if (debug)
4614         {
4615           fprintf (stderr, "\thash\tdone,  filename %s\n", filename);
4616           fprintf (stderr, "\tproc\tstart, filename %s\n", filename);
4617         }
4618
4619       /* Go through each of the procedures in this file, and add the
4620          procedure pointer to the hash entry for the given name.  */
4621
4622       proc_start = ORIG_PROCS (fd_ptr->ipdFirst);
4623       proc_end_p1 = proc_start + fd_ptr->cpd;
4624       for (proc = proc_start; proc < proc_end_p1; proc++)
4625         {
4626           SYMR *proc_sym = ORIG_LSYMS (fd_ptr->isymBase + proc->isym);
4627           char *str = ORIG_LSTRS (fd_ptr->issBase + proc_sym->iss);
4628           Size_t len = strlen (str);
4629           shash_t *shash_ptr = hash_string (str,
4630                                             (Ptrdiff_t) len,
4631                                             &orig_str_hash[0],
4632                                             (symint_t *) 0);
4633
4634           if (shash_ptr == (shash_t *) 0)
4635             error ("internal error, function %s is not in original symbol table", str);
4636
4637           else
4638             shash_ptr->proc_ptr = proc;
4639         }
4640
4641       if (debug)
4642         fprintf (stderr, "\tproc\tdone,  filename %s\n", filename);
4643
4644     }
4645   cur_file_ptr = first_file;
4646
4647
4648   /* Copy all of the object file up to the symbol table.  Originally
4649      we were going to use ftruncate, but that doesn't seem to work
4650      on Ultrix 3.1....  */
4651
4652   if (fseek (obj_in_stream, (long) 0, SEEK_SET) != 0)
4653     pfatal_with_name (obj_in_name);
4654
4655   if (fseek (object_stream, (long) 0, SEEK_SET) != 0)
4656     pfatal_with_name (object_name);
4657
4658   for (remaining = orig_file_header.f_symptr;
4659        remaining > 0;
4660        remaining -= num_write)
4661     {
4662       num_write
4663         = (remaining <= (int) sizeof (buffer))
4664           ? remaining : (int) sizeof (buffer);
4665       sys_read = fread (buffer, 1, num_write, obj_in_stream);
4666       if (sys_read <= 0)
4667         pfatal_with_name (obj_in_name);
4668
4669       else if (sys_read != num_write)
4670         fatal ("wanted to read %d bytes from %s, system returned %d",
4671                num_write,
4672                obj_in_name,
4673                sys_read);
4674
4675       sys_write = fwrite (buffer, 1, num_write, object_stream);
4676       if (sys_write <= 0)
4677         pfatal_with_name (object_name);
4678
4679       else if (sys_write != num_write)
4680         fatal ("wrote %d bytes to %s, system returned %d",
4681                num_write,
4682                object_name,
4683                sys_write);
4684     }
4685 }
4686
4687 \f
4688 /* Ye olde main program.  */
4689
4690 extern int main (int, char **);
4691
4692 int
4693 main (int argc, char **argv)
4694 {
4695   int iflag = 0;
4696   char *p = strrchr (argv[0], '/');
4697   char *num_end;
4698   int option;
4699   int i;
4700
4701   progname = (p != 0) ? p+1 : argv[0];
4702
4703   (void) signal (SIGSEGV, catch_signal);
4704   (void) signal (SIGBUS,  catch_signal);
4705   (void) signal (SIGABRT, catch_signal);
4706
4707 #if !defined(__SABER__) && !defined(lint)
4708   if (sizeof (efdr_t) > PAGE_USIZE)
4709     fatal ("efdr_t has a sizeof %d bytes, when it should be less than %d",
4710            (int) sizeof (efdr_t),
4711            (int) PAGE_USIZE);
4712
4713   if (sizeof (page_t) != PAGE_USIZE)
4714     fatal ("page_t has a sizeof %d bytes, when it should be %d",
4715            (int) sizeof (page_t),
4716            (int) PAGE_USIZE);
4717
4718 #endif
4719
4720   alloc_counts[ alloc_type_none    ].alloc_name = "none";
4721   alloc_counts[ alloc_type_scope   ].alloc_name = "scope";
4722   alloc_counts[ alloc_type_vlinks  ].alloc_name = "vlinks";
4723   alloc_counts[ alloc_type_shash   ].alloc_name = "shash";
4724   alloc_counts[ alloc_type_thash   ].alloc_name = "thash";
4725   alloc_counts[ alloc_type_tag     ].alloc_name = "tag";
4726   alloc_counts[ alloc_type_forward ].alloc_name = "forward";
4727   alloc_counts[ alloc_type_thead   ].alloc_name = "thead";
4728   alloc_counts[ alloc_type_varray  ].alloc_name = "varray";
4729
4730   int_type_info  = type_info_init;
4731   int_type_info.basic_type = bt_Int;
4732
4733   void_type_info = type_info_init;
4734   void_type_info.basic_type = bt_Void;
4735
4736   while ((option = getopt_long (argc, argv, "d:i:I:o:v", options, NULL)) != -1)
4737     switch (option)
4738       {
4739       default:
4740         had_errors++;
4741         break;
4742
4743       case 'd':
4744         debug = strtol (optarg, &num_end, 0);
4745         if ((unsigned) debug > 4 || num_end == optarg)
4746           had_errors++;
4747
4748         break;
4749
4750       case 'I':
4751         if (rename_output || obj_in_name != (char *) 0)
4752           had_errors++;
4753         else
4754           rename_output = 1;
4755
4756         /* Fall through to 'i' case.  */
4757
4758       case 'i':
4759         if (obj_in_name == (char *) 0)
4760           {
4761             obj_in_name = optarg;
4762             iflag++;
4763           }
4764         else
4765           had_errors++;
4766         break;
4767
4768       case 'o':
4769         if (object_name == (char *) 0)
4770           object_name = optarg;
4771         else
4772           had_errors++;
4773         break;
4774
4775       case 'v':
4776         verbose++;
4777         break;
4778
4779       case 'V':
4780         version++;
4781         break;
4782       }
4783
4784   if (version)
4785     {
4786       printf (_("mips-tfile %s%s\n"), pkgversion_string, version_string);
4787       fputs ("Copyright (C) 2010 Free Software Foundation, Inc.\n", stdout);
4788       fputs (_("This is free software; see the source for copying conditions.  There is NO\n\
4789 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"),
4790              stdout);
4791       exit (0);
4792     }
4793
4794   if (obj_in_name == (char *) 0 && optind <= argc - 2)
4795     obj_in_name = argv[--argc];
4796
4797   if (object_name == (char *) 0 && optind <= argc - 2)
4798     object_name = argv[--argc];
4799
4800   /* If there is an output name, but no input name use
4801      the same file for both, deleting the name between
4802      opening it for input and opening it for output.  */
4803   if (obj_in_name == (char *) 0 && object_name != (char *) 0)
4804     {
4805       obj_in_name = object_name;
4806       delete_input = 1;
4807     }
4808
4809   if (optind != argc - 1)
4810     had_errors++;
4811
4812   if (verbose || had_errors)
4813     {
4814       fprintf (stderr, _("mips-tfile (GCC) %s"), version_string);
4815 #ifdef TARGET_VERSION
4816       TARGET_VERSION;
4817 #endif
4818       fputc ('\n', stderr);
4819     }
4820
4821   if (object_name == (char *) 0 || had_errors)
4822     {
4823       fprintf (stderr, _("Calling Sequence:\n"));
4824       fprintf (stderr, _("\tmips-tfile [-d <num>] [-v] [-i <o-in-file>] -o <o-out-file> <s-file> (or)\n"));
4825       fprintf (stderr, _("\tmips-tfile [-d <num>] [-v] [-I <o-in-file>] -o <o-out-file> <s-file> (or)\n"));
4826       fprintf (stderr, _("\tmips-tfile [-d <num>] [-v] <s-file> <o-in-file> <o-out-file>\n"));
4827       fprintf (stderr, "\n");
4828       fprintf (stderr, _("Debug levels are:\n"));
4829       fprintf (stderr, _("    1\tGeneral debug + trace functions/blocks.\n"));
4830       fprintf (stderr, _("    2\tDebug level 1 + trace externals.\n"));
4831       fprintf (stderr, _("    3\tDebug level 2 + trace all symbols.\n"));
4832       fprintf (stderr, _("    4\tDebug level 3 + trace memory allocations.\n"));
4833       return 1;
4834     }
4835
4836   if (obj_in_name == (char *) 0)
4837     obj_in_name = object_name;
4838
4839   if (rename_output && rename (object_name, obj_in_name) != 0)
4840     {
4841       char *buffer = (char *) allocate_multiple_pages (4);
4842       int len;
4843       int len2;
4844       int in_fd;
4845       int out_fd;
4846
4847       /* Rename failed, copy input file */
4848       in_fd = open (object_name, O_RDONLY, 0666);
4849       if (in_fd < 0)
4850         pfatal_with_name (object_name);
4851
4852       out_fd = open (obj_in_name, O_WRONLY | O_CREAT | O_TRUNC, 0666);
4853       if (out_fd < 0)
4854         pfatal_with_name (obj_in_name);
4855
4856       while ((len = read (in_fd, buffer, 4*PAGE_SIZE)) > 0)
4857         {
4858           len2 = write (out_fd, buffer, len);
4859           if (len2 < 0)
4860             pfatal_with_name (object_name);
4861
4862           if (len != len2)
4863             fatal ("wrote %d bytes to %s, expected to write %d", len2, obj_in_name, len);
4864         }
4865
4866       free_multiple_pages ((page_t *) buffer, 4);
4867
4868       if (len < 0)
4869         pfatal_with_name (object_name);
4870
4871       if (close (in_fd) < 0)
4872         pfatal_with_name (object_name);
4873
4874       if (close (out_fd) < 0)
4875         pfatal_with_name (obj_in_name);
4876     }
4877
4878   /* Must open input before output, since the output may be the same file, and
4879      we need to get the input handle before truncating it.  */
4880   obj_in_stream = fopen (obj_in_name, "r");
4881   if (obj_in_stream == (FILE *) 0)
4882     pfatal_with_name (obj_in_name);
4883
4884   if (delete_input && unlink (obj_in_name) != 0)
4885     pfatal_with_name (obj_in_name);
4886
4887   object_stream = fopen (object_name, "w");
4888   if (object_stream == (FILE *) 0)
4889     pfatal_with_name (object_name);
4890
4891   if (strcmp (argv[optind], "-") != 0)
4892     {
4893       input_name = argv[optind];
4894       if (freopen (argv[optind], "r", stdin) != stdin)
4895         pfatal_with_name (argv[optind]);
4896     }
4897
4898   copy_object ();                       /* scan & copy object file */
4899   parse_input ();                       /* scan all of input */
4900
4901   update_headers ();                    /* write out tfile */
4902   write_object ();
4903
4904   if (debug)
4905     {
4906       fprintf (stderr, "\n\tAllocation summary:\n\n");
4907       for (i = (int) alloc_type_none; i < (int) alloc_type_last; i++)
4908         if (alloc_counts[i].total_alloc)
4909           {
4910             fprintf (stderr,
4911                      "\t%s\t%5d allocation(s), %5d free(s), %2d page(s)\n",
4912                      alloc_counts[i].alloc_name,
4913                      alloc_counts[i].total_alloc,
4914                      alloc_counts[i].total_free,
4915                      alloc_counts[i].total_pages);
4916           }
4917     }
4918
4919   return (had_errors) ? 1 : 0;
4920 }
4921
4922 \f
4923 /* Catch a signal and exit without dumping core.  */
4924
4925 STATIC void
4926 catch_signal (int signum)
4927 {
4928   (void) signal (signum, SIG_DFL);      /* just in case...  */
4929   fatal ("%s", strsignal (signum));
4930 }
4931
4932 /* Print a fatal error message.  NAME is the text.
4933    Also include a system error message based on `errno'.  */
4934
4935 void
4936 pfatal_with_name (const char *msg)
4937 {
4938   int save_errno = errno;               /* just in case....  */
4939   if (line_number > 0)
4940     fprintf (stderr, "%s, %s:%ld ", progname, input_name, line_number);
4941   else
4942     fprintf (stderr, "%s:", progname);
4943
4944   errno = save_errno;
4945   if (errno == 0)
4946     fprintf (stderr, "[errno = 0] %s\n", msg);
4947   else
4948     perror (msg);
4949
4950   exit (1);
4951 }
4952
4953 \f
4954 /* Procedure to die with an out of bounds error message.  It has
4955    type int, so it can be used with an ?: expression within the
4956    ORIG_xxx macros, but the function never returns.  */
4957
4958 static int
4959 out_of_bounds (symint_t indx,   /* index that is out of bounds */
4960                symint_t max,    /* maximum index */
4961                const char *str, /* string to print out */
4962                int prog_line)   /* line number within mips-tfile.c */
4963 {
4964   if (indx < max)               /* just in case */
4965     return 0;
4966
4967   fprintf (stderr, "%s, %s:%ld index %lu is out of bounds for %s, max is %lu, mips-tfile.c line# %d\n",
4968            progname, input_name, line_number, indx, str, max, prog_line);
4969
4970   exit (1);
4971   return 0;                     /* turn off warning messages */
4972 }
4973
4974 \f
4975 /* Allocate a cluster of pages.  USE_MALLOC says that malloc does not
4976    like sbrk's behind its back (or sbrk isn't available).  If we use
4977    sbrk, we assume it gives us zeroed pages.  */
4978
4979 #ifndef MALLOC_CHECK
4980 #ifdef USE_MALLOC
4981
4982 STATIC page_t *
4983 allocate_cluster (Size_t npages)
4984 {
4985   page_t *value = xcalloc (npages, PAGE_USIZE);
4986
4987   if (debug > 3)
4988     fprintf (stderr, "\talloc\tnpages = %d, value = 0x%.8x\n", npages, value);
4989
4990   return value;
4991 }
4992
4993 #else /* USE_MALLOC */
4994
4995 STATIC page_t *
4996 allocate_cluster (Size_t npages)
4997 {
4998   page_t *ptr = (page_t *) sbrk (0);    /* current sbreak */
4999   unsigned long offset = ((unsigned long) ptr) & (PAGE_SIZE - 1);
5000
5001   if (offset != 0)                      /* align to a page boundary */
5002     {
5003       if (sbrk (PAGE_USIZE - offset) == (char *)-1)
5004         pfatal_with_name ("allocate_cluster");
5005
5006       ptr = (page_t *) (((char *) ptr) + PAGE_SIZE - offset);
5007     }
5008
5009   if (sbrk (npages * PAGE_USIZE) == (char *) -1)
5010     pfatal_with_name ("allocate_cluster");
5011
5012   if (debug > 3)
5013     fprintf (stderr, "\talloc\tnpages = %lu, value = " HOST_PTR_PRINTF "\n",
5014              (unsigned long) npages, (void *) ptr);
5015
5016   return ptr;
5017 }
5018
5019 #endif /* USE_MALLOC */
5020
5021
5022 static page_t   *cluster_ptr    = NULL;
5023 static unsigned  pages_left     = 0;
5024
5025 #endif /* MALLOC_CHECK */
5026
5027
5028 /* Allocate some pages (which is initialized to 0).  */
5029
5030 STATIC page_t *
5031 allocate_multiple_pages (Size_t npages)
5032 {
5033 #ifndef MALLOC_CHECK
5034   if (pages_left == 0 && npages < MAX_CLUSTER_PAGES)
5035     {
5036       pages_left = MAX_CLUSTER_PAGES;
5037       cluster_ptr = allocate_cluster (MAX_CLUSTER_PAGES);
5038     }
5039
5040   if (npages <= pages_left)
5041     {
5042       page_t *ptr = cluster_ptr;
5043       cluster_ptr += npages;
5044       pages_left -= npages;
5045       return ptr;
5046     }
5047
5048   return allocate_cluster (npages);
5049
5050 #else   /* MALLOC_CHECK */
5051   return xcalloc (npages, PAGE_SIZE);
5052
5053 #endif  /* MALLOC_CHECK */
5054 }
5055
5056
5057 /* Release some pages.  */
5058
5059 STATIC void
5060 free_multiple_pages (page_t *page_ptr, Size_t npages)
5061 {
5062 #ifndef MALLOC_CHECK
5063   if (pages_left == 0)
5064     {
5065       cluster_ptr = page_ptr;
5066       pages_left = npages;
5067     }
5068
5069   else if ((page_ptr + npages) == cluster_ptr)
5070     {
5071       cluster_ptr -= npages;
5072       pages_left += npages;
5073     }
5074
5075   /* otherwise the page is not freed.  If more than call is
5076      done, we probably should worry about it, but at present,
5077      the free pages is done right after an allocate.  */
5078
5079 #else   /* MALLOC_CHECK */
5080   free (page_ptr);
5081
5082 #endif  /* MALLOC_CHECK */
5083 }
5084
5085
5086 /* Allocate one page (which is initialized to 0).  */
5087
5088 STATIC page_t *
5089 allocate_page (void)
5090 {
5091 #ifndef MALLOC_CHECK
5092   if (pages_left == 0)
5093     {
5094       pages_left = MAX_CLUSTER_PAGES;
5095       cluster_ptr = allocate_cluster (MAX_CLUSTER_PAGES);
5096     }
5097
5098   pages_left--;
5099   return cluster_ptr++;
5100
5101 #else   /* MALLOC_CHECK */
5102   return xcalloc (1, PAGE_SIZE);
5103
5104 #endif  /* MALLOC_CHECK */
5105 }
5106
5107 \f
5108 /* Allocate scoping information.  */
5109
5110 STATIC scope_t *
5111 allocate_scope (void)
5112 {
5113   scope_t *ptr;
5114   static scope_t initial_scope;
5115
5116 #ifndef MALLOC_CHECK
5117   ptr = alloc_counts[ (int) alloc_type_scope ].free_list.f_scope;
5118   if (ptr != (scope_t *) 0)
5119     alloc_counts[ (int) alloc_type_scope ].free_list.f_scope = ptr->free;
5120
5121   else
5122     {
5123       int unallocated   = alloc_counts[ (int) alloc_type_scope ].unallocated;
5124       page_t *cur_page  = alloc_counts[ (int) alloc_type_scope ].cur_page;
5125
5126       if (unallocated == 0)
5127         {
5128           unallocated = PAGE_SIZE / sizeof (scope_t);
5129           alloc_counts[ (int) alloc_type_scope ].cur_page = cur_page = allocate_page ();
5130           alloc_counts[ (int) alloc_type_scope ].total_pages++;
5131         }
5132
5133       ptr = &cur_page->scope[ --unallocated ];
5134       alloc_counts[ (int) alloc_type_scope ].unallocated = unallocated;
5135     }
5136
5137 #else
5138   ptr = xmalloc (sizeof (scope_t));
5139
5140 #endif
5141
5142   alloc_counts[ (int) alloc_type_scope ].total_alloc++;
5143   *ptr = initial_scope;
5144   return ptr;
5145 }
5146
5147 /* Free scoping information.  */
5148
5149 STATIC void
5150 free_scope (scope_t *ptr)
5151 {
5152   alloc_counts[ (int) alloc_type_scope ].total_free++;
5153
5154 #ifndef MALLOC_CHECK
5155   ptr->free = alloc_counts[ (int) alloc_type_scope ].free_list.f_scope;
5156   alloc_counts[ (int) alloc_type_scope ].free_list.f_scope = ptr;
5157
5158 #else
5159   free (ptr);
5160 #endif
5161
5162 }
5163
5164 \f
5165 /* Allocate links for pages in a virtual array.  */
5166
5167 STATIC vlinks_t *
5168 allocate_vlinks (void)
5169 {
5170   vlinks_t *ptr;
5171   static vlinks_t initial_vlinks;
5172
5173 #ifndef MALLOC_CHECK
5174   int unallocated       = alloc_counts[ (int) alloc_type_vlinks ].unallocated;
5175   page_t *cur_page      = alloc_counts[ (int) alloc_type_vlinks ].cur_page;
5176
5177   if (unallocated == 0)
5178     {
5179       unallocated = PAGE_SIZE / sizeof (vlinks_t);
5180       alloc_counts[ (int) alloc_type_vlinks ].cur_page = cur_page = allocate_page ();
5181       alloc_counts[ (int) alloc_type_vlinks ].total_pages++;
5182     }
5183
5184   ptr = &cur_page->vlinks[ --unallocated ];
5185   alloc_counts[ (int) alloc_type_vlinks ].unallocated = unallocated;
5186
5187 #else
5188   ptr = xmalloc (sizeof (vlinks_t));
5189
5190 #endif
5191
5192   alloc_counts[ (int) alloc_type_vlinks ].total_alloc++;
5193   *ptr = initial_vlinks;
5194   return ptr;
5195 }
5196
5197 \f
5198 /* Allocate string hash buckets.  */
5199
5200 STATIC shash_t *
5201 allocate_shash (void)
5202 {
5203   shash_t *ptr;
5204   static shash_t initial_shash;
5205
5206 #ifndef MALLOC_CHECK
5207   int unallocated       = alloc_counts[ (int) alloc_type_shash ].unallocated;
5208   page_t *cur_page      = alloc_counts[ (int) alloc_type_shash ].cur_page;
5209
5210   if (unallocated == 0)
5211     {
5212       unallocated = PAGE_SIZE / sizeof (shash_t);
5213       alloc_counts[ (int) alloc_type_shash ].cur_page = cur_page = allocate_page ();
5214       alloc_counts[ (int) alloc_type_shash ].total_pages++;
5215     }
5216
5217   ptr = &cur_page->shash[ --unallocated ];
5218   alloc_counts[ (int) alloc_type_shash ].unallocated = unallocated;
5219
5220 #else
5221   ptr = xmalloc (sizeof (shash_t));
5222
5223 #endif
5224
5225   alloc_counts[ (int) alloc_type_shash ].total_alloc++;
5226   *ptr = initial_shash;
5227   return ptr;
5228 }
5229
5230 \f
5231 /* Allocate type hash buckets.  */
5232
5233 STATIC thash_t *
5234 allocate_thash (void)
5235 {
5236   thash_t *ptr;
5237   static thash_t initial_thash;
5238
5239 #ifndef MALLOC_CHECK
5240   int unallocated       = alloc_counts[ (int) alloc_type_thash ].unallocated;
5241   page_t *cur_page      = alloc_counts[ (int) alloc_type_thash ].cur_page;
5242
5243   if (unallocated == 0)
5244     {
5245       unallocated = PAGE_SIZE / sizeof (thash_t);
5246       alloc_counts[ (int) alloc_type_thash ].cur_page = cur_page = allocate_page ();
5247       alloc_counts[ (int) alloc_type_thash ].total_pages++;
5248     }
5249
5250   ptr = &cur_page->thash[ --unallocated ];
5251   alloc_counts[ (int) alloc_type_thash ].unallocated = unallocated;
5252
5253 #else
5254   ptr = xmalloc (sizeof (thash_t));
5255
5256 #endif
5257
5258   alloc_counts[ (int) alloc_type_thash ].total_alloc++;
5259   *ptr = initial_thash;
5260   return ptr;
5261 }
5262
5263 \f
5264 /* Allocate structure, union, or enum tag information.  */
5265
5266 STATIC tag_t *
5267 allocate_tag (void)
5268 {
5269   tag_t *ptr;
5270   static tag_t initial_tag;
5271
5272 #ifndef MALLOC_CHECK
5273   ptr = alloc_counts[ (int) alloc_type_tag ].free_list.f_tag;
5274   if (ptr != (tag_t *) 0)
5275     alloc_counts[ (int) alloc_type_tag ].free_list.f_tag = ptr->free;
5276
5277   else
5278     {
5279       int unallocated   = alloc_counts[ (int) alloc_type_tag ].unallocated;
5280       page_t *cur_page  = alloc_counts[ (int) alloc_type_tag ].cur_page;
5281
5282       if (unallocated == 0)
5283         {
5284           unallocated = PAGE_SIZE / sizeof (tag_t);
5285           alloc_counts[ (int) alloc_type_tag ].cur_page = cur_page = allocate_page ();
5286           alloc_counts[ (int) alloc_type_tag ].total_pages++;
5287         }
5288
5289       ptr = &cur_page->tag[ --unallocated ];
5290       alloc_counts[ (int) alloc_type_tag ].unallocated = unallocated;
5291     }
5292
5293 #else
5294   ptr = xmalloc (sizeof (tag_t));
5295
5296 #endif
5297
5298   alloc_counts[ (int) alloc_type_tag ].total_alloc++;
5299   *ptr = initial_tag;
5300   return ptr;
5301 }
5302
5303 /* Free scoping information.  */
5304
5305 STATIC void
5306 free_tag (tag_t *ptr)
5307 {
5308   alloc_counts[ (int) alloc_type_tag ].total_free++;
5309
5310 #ifndef MALLOC_CHECK
5311   ptr->free = alloc_counts[ (int) alloc_type_tag ].free_list.f_tag;
5312   alloc_counts[ (int) alloc_type_tag ].free_list.f_tag = ptr;
5313
5314 #else
5315   free (ptr);
5316 #endif
5317
5318 }
5319
5320 \f
5321 /* Allocate forward reference to a yet unknown tag.  */
5322
5323 STATIC forward_t *
5324 allocate_forward (void)
5325 {
5326   forward_t *ptr;
5327   static forward_t initial_forward;
5328
5329 #ifndef MALLOC_CHECK
5330   ptr = alloc_counts[ (int) alloc_type_forward ].free_list.f_forward;
5331   if (ptr != (forward_t *) 0)
5332     alloc_counts[ (int) alloc_type_forward ].free_list.f_forward = ptr->free;
5333
5334   else
5335     {
5336       int unallocated   = alloc_counts[ (int) alloc_type_forward ].unallocated;
5337       page_t *cur_page  = alloc_counts[ (int) alloc_type_forward ].cur_page;
5338
5339       if (unallocated == 0)
5340         {
5341           unallocated = PAGE_SIZE / sizeof (forward_t);
5342           alloc_counts[ (int) alloc_type_forward ].cur_page = cur_page = allocate_page ();
5343           alloc_counts[ (int) alloc_type_forward ].total_pages++;
5344         }
5345
5346       ptr = &cur_page->forward[ --unallocated ];
5347       alloc_counts[ (int) alloc_type_forward ].unallocated = unallocated;
5348     }
5349
5350 #else
5351   ptr = xmalloc (sizeof (forward_t));
5352
5353 #endif
5354
5355   alloc_counts[ (int) alloc_type_forward ].total_alloc++;
5356   *ptr = initial_forward;
5357   return ptr;
5358 }
5359
5360 /* Free scoping information.  */
5361
5362 STATIC void
5363 free_forward (forward_t *ptr)
5364 {
5365   alloc_counts[ (int) alloc_type_forward ].total_free++;
5366
5367 #ifndef MALLOC_CHECK
5368   ptr->free = alloc_counts[ (int) alloc_type_forward ].free_list.f_forward;
5369   alloc_counts[ (int) alloc_type_forward ].free_list.f_forward = ptr;
5370
5371 #else
5372   free (ptr);
5373 #endif
5374
5375 }
5376
5377 \f
5378 /* Allocate head of type hash list.  */
5379
5380 STATIC thead_t *
5381 allocate_thead (void)
5382 {
5383   thead_t *ptr;
5384   static thead_t initial_thead;
5385
5386 #ifndef MALLOC_CHECK
5387   ptr = alloc_counts[ (int) alloc_type_thead ].free_list.f_thead;
5388   if (ptr != (thead_t *) 0)
5389     alloc_counts[ (int) alloc_type_thead ].free_list.f_thead = ptr->free;
5390
5391   else
5392     {
5393       int unallocated   = alloc_counts[ (int) alloc_type_thead ].unallocated;
5394       page_t *cur_page  = alloc_counts[ (int) alloc_type_thead ].cur_page;
5395
5396       if (unallocated == 0)
5397         {
5398           unallocated = PAGE_SIZE / sizeof (thead_t);
5399           alloc_counts[ (int) alloc_type_thead ].cur_page = cur_page = allocate_page ();
5400           alloc_counts[ (int) alloc_type_thead ].total_pages++;
5401         }
5402
5403       ptr = &cur_page->thead[ --unallocated ];
5404       alloc_counts[ (int) alloc_type_thead ].unallocated = unallocated;
5405     }
5406
5407 #else
5408   ptr = xmalloc (sizeof (thead_t));
5409
5410 #endif
5411
5412   alloc_counts[ (int) alloc_type_thead ].total_alloc++;
5413   *ptr = initial_thead;
5414   return ptr;
5415 }
5416
5417 /* Free scoping information.  */
5418
5419 STATIC void
5420 free_thead (thead_t *ptr)
5421 {
5422   alloc_counts[ (int) alloc_type_thead ].total_free++;
5423
5424 #ifndef MALLOC_CHECK
5425   ptr->free = (thead_t *) alloc_counts[ (int) alloc_type_thead ].free_list.f_thead;
5426   alloc_counts[ (int) alloc_type_thead ].free_list.f_thead = ptr;
5427
5428 #else
5429   free (ptr);
5430 #endif
5431
5432 }
5433
5434 #endif /* MIPS_DEBUGGING_INFO */
5435
5436 \f
5437 /* Output an error message and exit.  */
5438
5439 void
5440 fatal (const char *format, ...)
5441 {
5442   va_list ap;
5443
5444   va_start (ap, format);
5445
5446   if (line_number > 0)
5447     fprintf (stderr, "%s, %s:%ld ", progname, input_name, line_number);
5448   else
5449     fprintf (stderr, "%s:", progname);
5450
5451   vfprintf (stderr, format, ap);
5452   va_end (ap);
5453   fprintf (stderr, "\n");
5454   if (line_number > 0)
5455     fprintf (stderr, "line:\t%s\n", cur_line_start);
5456
5457   saber_stop ();
5458   exit (1);
5459 }
5460
5461 void
5462 error (const char *format, ...)
5463 {
5464   va_list ap;
5465
5466   va_start (ap, format);
5467
5468   if (line_number > 0)
5469     fprintf (stderr, "%s, %s:%ld ", progname, input_name, line_number);
5470   else
5471     fprintf (stderr, "%s:", progname);
5472
5473   vfprintf (stderr, format, ap);
5474   fprintf (stderr, "\n");
5475   if (line_number > 0)
5476     fprintf (stderr, "line:\t%s\n", cur_line_start);
5477
5478   had_errors++;
5479   va_end (ap);
5480
5481   saber_stop ();
5482 }
5483
5484 /* More 'friendly' abort that prints the line and file.  */
5485
5486 void
5487 fancy_abort (const char *file, int line, const char *func)
5488 {
5489   fatal ("abort in %s, at %s:%d", func, file, line);
5490 }
5491 \f
5492
5493 /* When `malloc.c' is compiled with `rcheck' defined,
5494    it calls this function to report clobberage.  */
5495
5496 void
5497 botch (const char *s)
5498 {
5499   fatal ("%s", s);
5500 }