OSDN Git Service

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