OSDN Git Service

7258e92b16e9a91753da2457669112d9e0e8f8eb
[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 #ifndef NO_SYS_SIGLIST
1752 #ifndef DONT_DECLARE_SYS_SIGLIST
1753 extern char *sys_siglist[NSIG + 1];
1754 #endif
1755 #endif
1756
1757 #ifndef SEEK_SET        /* Symbolic constants for the "fseek" function: */
1758 #define SEEK_SET 0      /* Set file pointer to offset */
1759 #define SEEK_CUR 1      /* Set file pointer to its current value plus offset */
1760 #define SEEK_END 2      /* Set file pointer to the size of the file plus offset */
1761 #endif
1762
1763 \f
1764 /* List of assembler pseudo ops and beginning sequences that need
1765    special actions.  Someday, this should be a hash table, and such,
1766    but for now a linear list of names and calls to memcmp will
1767    do...... */
1768
1769 typedef struct _pseudo_ops {
1770   const char *name;                     /* pseudo-op in ascii */
1771   int len;                              /* length of name to compare */
1772   void (*func) __proto((const char *)); /* function to handle line */
1773 } pseudo_ops_t;
1774
1775 static pseudo_ops_t pseudo_ops[] = {
1776   { "#.def",    sizeof("#.def")-1,      parse_def },
1777   { "#.begin",  sizeof("#.begin")-1,    parse_begin },
1778   { "#.bend",   sizeof("#.bend")-1,     parse_bend },
1779   { ".end",     sizeof(".end")-1,       parse_end },
1780   { ".ent",     sizeof(".ent")-1,       parse_ent },
1781   { ".file",    sizeof(".file")-1,      parse_file },
1782   { "#.stabs",  sizeof("#.stabs")-1,    parse_stabs },
1783   { "#.stabn",  sizeof("#.stabn")-1,    parse_stabn },
1784   { ".stabs",   sizeof(".stabs")-1,     parse_stabs },
1785   { ".stabn",   sizeof(".stabn")-1,     parse_stabn },
1786   { "#@stabs",  sizeof("#@stabs")-1,    mark_stabs },
1787 };
1788
1789 \f
1790 /* Add a page to a varray object.  */
1791
1792 STATIC void
1793 add_varray_page (vp)
1794      varray_t *vp;                              /* varray to add page to */
1795 {
1796   vlinks_t *new_links = allocate_vlinks ();
1797
1798 #ifdef MALLOC_CHECK
1799   if (vp->object_size > 1)
1800     new_links->datum = (page_t *) xcalloc (1, vp->object_size);
1801   else
1802 #endif
1803     new_links->datum = allocate_page ();
1804
1805   alloc_counts[ (int)alloc_type_varray ].total_alloc++;
1806   alloc_counts[ (int)alloc_type_varray ].total_pages++;
1807
1808   new_links->start_index = vp->num_allocated;
1809   vp->objects_last_page = 0;
1810
1811   if (vp->first == (vlinks_t *)0)               /* first allocation? */
1812     vp->first = vp->last = new_links;
1813   else
1814     {                                           /* 2nd or greater allocation */
1815       new_links->prev = vp->last;
1816       vp->last->next = new_links;
1817       vp->last = new_links;
1818     }
1819 }
1820
1821 \f
1822 /* Compute hash code (from tree.c) */
1823
1824 #define HASHBITS 30
1825
1826 STATIC shash_t *
1827 hash_string (text, hash_len, hash_tbl, ret_hash_index)
1828      const char *text;                  /* ptr to text to hash */
1829      Ptrdiff_t hash_len;                /* length of the text */
1830      shash_t **hash_tbl;                /* hash table */
1831      symint_t *ret_hash_index;          /* ptr to store hash index */
1832 {
1833   register unsigned long hi;
1834   register Ptrdiff_t i;
1835   register shash_t *ptr;
1836   register int first_ch = *text;
1837
1838   hi = hash_len;
1839   for (i = 0; i < hash_len; i++)
1840     hi = ((hi & 0x003fffff) * 613) + (text[i] & 0xff);
1841
1842   hi &= (1 << HASHBITS) - 1;
1843   hi %= SHASH_SIZE;
1844
1845   if (ret_hash_index != (symint_t *)0)
1846     *ret_hash_index = hi;
1847
1848   for (ptr = hash_tbl[hi]; ptr != (shash_t *)0; ptr = ptr->next)
1849     if (hash_len == ptr->len
1850         && first_ch == ptr->string[0]
1851         && memcmp ((CPTR_T) text, (CPTR_T) ptr->string, hash_len) == 0)
1852       break;
1853
1854   return ptr;
1855 }
1856
1857 \f
1858 /* Add a string (and null pad) to one of the string tables.  A
1859    consequence of hashing strings, is that we don't let strings
1860    cross page boundaries.  The extra nulls will be ignored.  */
1861
1862 STATIC symint_t
1863 add_string (vp, hash_tbl, start, end_p1, ret_hash)
1864      varray_t *vp;                      /* string virtual array */
1865      shash_t **hash_tbl;                /* ptr to hash table */
1866      const char *start;                 /* 1st byte in string */
1867      const char *end_p1;                /* 1st byte after string */
1868      shash_t **ret_hash;                /* return hash pointer */
1869 {
1870   register Ptrdiff_t len = end_p1 - start;
1871   register shash_t *hash_ptr;
1872   symint_t hi;
1873
1874   if (len >= PAGE_USIZE)
1875     fatal ("String too big (%ld bytes)", (long) len);
1876
1877   hash_ptr = hash_string (start, len, hash_tbl, &hi);
1878   if (hash_ptr == (shash_t *)0)
1879     {
1880       register char *p;
1881
1882       if (vp->objects_last_page + len >= PAGE_USIZE)
1883         {
1884           vp->num_allocated =
1885             ((vp->num_allocated + PAGE_USIZE - 1) / PAGE_USIZE) * PAGE_USIZE;
1886           add_varray_page (vp);
1887         }
1888
1889       hash_ptr = allocate_shash ();
1890       hash_ptr->next = hash_tbl[hi];
1891       hash_tbl[hi] = hash_ptr;
1892
1893       hash_ptr->len = len;
1894       hash_ptr->indx = vp->num_allocated;
1895       hash_ptr->string = p = & vp->last->datum->byte[ vp->objects_last_page ];
1896
1897       vp->objects_last_page += len+1;
1898       vp->num_allocated += len+1;
1899
1900       while (len-- > 0)
1901         *p++ = *start++;
1902
1903       *p = '\0';
1904     }
1905
1906   if (ret_hash != (shash_t **)0)
1907     *ret_hash = hash_ptr;
1908
1909   return hash_ptr->indx;
1910 }
1911
1912 \f
1913 /* Add a local symbol.  */
1914
1915 STATIC symint_t
1916 add_local_symbol (str_start, str_end_p1, type, storage, value, indx)
1917      const char *str_start;             /* first byte in string */
1918      const char *str_end_p1;            /* first byte after string */
1919      st_t type;                         /* symbol type */
1920      sc_t storage;                      /* storage class */
1921      symint_t value;                    /* value of symbol */
1922      symint_t indx;                     /* index to local/aux. syms */
1923 {
1924   register symint_t ret;
1925   register SYMR *psym;
1926   register scope_t *pscope;
1927   register thead_t *ptag_head;
1928   register tag_t *ptag;
1929   register tag_t *ptag_next;
1930   register varray_t *vp = &cur_file_ptr->symbols;
1931   register int scope_delta = 0;
1932   shash_t *hash_ptr = (shash_t *)0;
1933
1934   if (vp->objects_last_page == vp->objects_per_page)
1935     add_varray_page (vp);
1936
1937   psym = &vp->last->datum->sym[ vp->objects_last_page++ ];
1938
1939   psym->value = value;
1940   psym->st = (unsigned) type;
1941   psym->sc = (unsigned) storage;
1942   psym->index = indx;
1943   psym->iss = (str_start == (const char *)0)
1944                 ? 0
1945                 : add_string (&cur_file_ptr->strings,
1946                               &cur_file_ptr->shash_head[0],
1947                               str_start,
1948                               str_end_p1,
1949                               &hash_ptr);
1950
1951   ret = vp->num_allocated++;
1952
1953   if (MIPS_IS_STAB(psym))
1954     return ret;
1955
1956   /* Save the symbol within the hash table if this is a static
1957      item, and it has a name.  */
1958   if (hash_ptr != (shash_t *)0
1959       && (type == st_Global || type == st_Static || type == st_Label
1960           || type == st_Proc || type == st_StaticProc))
1961     hash_ptr->sym_ptr = psym;
1962
1963   /* push or pop a scope if appropriate.  */
1964   switch (type)
1965     {
1966     default:
1967       break;
1968
1969     case st_File:                       /* beginning of file */
1970     case st_Proc:                       /* procedure */
1971     case st_StaticProc:                 /* static procedure */
1972     case st_Block:                      /* begin scope */
1973       pscope = allocate_scope ();
1974       pscope->prev = cur_file_ptr->cur_scope;
1975       pscope->lsym = psym;
1976       pscope->lnumber = ret;
1977       pscope->type = type;
1978       cur_file_ptr->cur_scope = pscope;
1979
1980       if (type != st_File)
1981         scope_delta = 1;
1982
1983       /* For every block type except file, struct, union, or
1984          enumeration blocks, push a level on the tag stack.  We omit
1985          file types, so that tags can span file boundaries.  */
1986       if (type != st_File && storage != sc_Info)
1987         {
1988           ptag_head = allocate_thead ();
1989           ptag_head->first_tag = 0;
1990           ptag_head->prev = cur_tag_head;
1991           cur_tag_head = ptag_head;
1992         }
1993       break;
1994
1995     case st_End:
1996       pscope = cur_file_ptr->cur_scope;
1997       if (pscope == (scope_t *)0)
1998         error ("internal error, too many st_End's");
1999
2000       else
2001         {
2002           st_t begin_type = (st_t) pscope->lsym->st;
2003
2004           if (begin_type != st_File)
2005             scope_delta = -1;
2006
2007           /* Except for file, structure, union, or enumeration end
2008              blocks remove all tags created within this scope.  */
2009           if (begin_type != st_File && storage != sc_Info)
2010             {
2011               ptag_head = cur_tag_head;
2012               cur_tag_head = ptag_head->prev;
2013
2014               for (ptag = ptag_head->first_tag;
2015                    ptag != (tag_t *)0;
2016                    ptag = ptag_next)
2017                 {
2018                   if (ptag->forward_ref != (forward_t *)0)
2019                     add_unknown_tag (ptag);
2020
2021                   ptag_next = ptag->same_block;
2022                   ptag->hash_ptr->tag_ptr = ptag->same_name;
2023                   free_tag (ptag);
2024                 }
2025
2026               free_thead (ptag_head);
2027             }
2028
2029           cur_file_ptr->cur_scope = pscope->prev;
2030           psym->index = pscope->lnumber;        /* blk end gets begin sym # */
2031
2032           if (storage != sc_Info)
2033             psym->iss = pscope->lsym->iss;      /* blk end gets same name */
2034
2035           if (begin_type == st_File || begin_type == st_Block)
2036             pscope->lsym->index = ret+1;        /* block begin gets next sym # */
2037
2038           /* Functions push two or more aux words as follows:
2039              1st word: index+1 of the end symbol
2040              2nd word: type of the function (plus any aux words needed).
2041              Also, tie the external pointer back to the function begin symbol.  */
2042           else
2043             {
2044               symint_t type;
2045               pscope->lsym->index = add_aux_sym_symint (ret+1);
2046               type = add_aux_sym_tir (&last_func_type_info,
2047                                       hash_no,
2048                                       &cur_file_ptr->thash_head[0]);
2049               if (last_func_eptr)
2050                 {
2051                   last_func_eptr->ifd = cur_file_ptr->file_index;
2052
2053                   /* The index for an external st_Proc symbol is the index
2054                      of the st_Proc symbol in the local symbol table.  */
2055                   last_func_eptr->asym.index = psym->index;
2056                 }
2057             }
2058
2059           free_scope (pscope);
2060         }
2061     }
2062
2063   cur_file_ptr->nested_scopes += scope_delta;
2064
2065   if (debug && type != st_File
2066       && (debug > 2 || type == st_Block || type == st_End
2067           || type == st_Proc || type == st_StaticProc))
2068     {
2069       char *sc_str = sc_to_string (storage);
2070       char *st_str = st_to_string (type);
2071       int depth = cur_file_ptr->nested_scopes + (scope_delta < 0);
2072
2073       fprintf (stderr,
2074                "\tlsym\tv= %10ld, depth= %2d, sc= %-12s",
2075                value, depth, sc_str);
2076
2077       if (str_start && str_end_p1 - str_start > 0)
2078         fprintf (stderr, " st= %-11s name= %.*s\n", st_str, str_end_p1 - str_start, str_start);
2079       else
2080         {
2081           Size_t len = strlen (st_str);
2082           fprintf (stderr, " st= %.*s\n", len-1, st_str);
2083         }
2084     }
2085
2086   return ret;
2087 }
2088
2089 \f
2090 /* Add an external symbol.  */
2091
2092 STATIC symint_t
2093 add_ext_symbol (str_start, str_end_p1, type, storage, value, indx, ifd)
2094      const char *str_start;             /* first byte in string */
2095      const char *str_end_p1;            /* first byte after string */
2096      st_t type;                         /* symbol type */
2097      sc_t storage;                      /* storage class */
2098      long value;                        /* value of symbol */
2099      symint_t indx;                     /* index to local/aux. syms */
2100      int ifd;                           /* file index */
2101 {
2102   register EXTR *psym;
2103   register varray_t *vp = &ext_symbols;
2104   shash_t *hash_ptr = (shash_t *)0;
2105
2106   if (debug > 1)
2107     {
2108       char *sc_str = sc_to_string (storage);
2109       char *st_str = st_to_string (type);
2110
2111       fprintf (stderr,
2112                "\tesym\tv= %10ld, ifd= %2d, sc= %-12s",
2113                value, ifd, sc_str);
2114
2115       if (str_start && str_end_p1 - str_start > 0)
2116         fprintf (stderr, " st= %-11s name= %.*s\n", st_str, str_end_p1 - str_start, str_start);
2117       else
2118         fprintf (stderr, " st= %s\n", st_str);
2119     }
2120
2121   if (vp->objects_last_page == vp->objects_per_page)
2122     add_varray_page (vp);
2123
2124   psym = &vp->last->datum->esym[ vp->objects_last_page++ ];
2125
2126   psym->ifd = ifd;
2127   psym->asym.value = value;
2128   psym->asym.st    = (unsigned) type;
2129   psym->asym.sc    = (unsigned) storage;
2130   psym->asym.index = indx;
2131   psym->asym.iss   = (str_start == (const char *)0)
2132                         ? 0
2133                         : add_string (&ext_strings,
2134                                       &ext_str_hash[0],
2135                                       str_start,
2136                                       str_end_p1,
2137                                       &hash_ptr);
2138
2139   hash_ptr->esym_ptr = psym;
2140   return vp->num_allocated++;
2141 }
2142
2143 \f
2144 /* Add an auxiliary symbol (passing a symint).  */
2145
2146 STATIC symint_t
2147 add_aux_sym_symint (aux_word)
2148      symint_t aux_word;         /* auxiliary information word */
2149 {
2150   register AUXU *aux_ptr;
2151   register efdr_t *file_ptr = cur_file_ptr;
2152   register varray_t *vp = &file_ptr->aux_syms;
2153
2154   if (vp->objects_last_page == vp->objects_per_page)
2155     add_varray_page (vp);
2156
2157   aux_ptr = &vp->last->datum->aux[ vp->objects_last_page++ ];
2158   aux_ptr->isym = aux_word;
2159
2160   return vp->num_allocated++;
2161 }
2162
2163
2164 /* Add an auxiliary symbol (passing a file/symbol index combo).  */
2165
2166 STATIC symint_t
2167 add_aux_sym_rndx (file_index, sym_index)
2168      int file_index;
2169      symint_t sym_index;
2170 {
2171   register AUXU *aux_ptr;
2172   register efdr_t *file_ptr = cur_file_ptr;
2173   register varray_t *vp = &file_ptr->aux_syms;
2174
2175   if (vp->objects_last_page == vp->objects_per_page)
2176     add_varray_page (vp);
2177
2178   aux_ptr = &vp->last->datum->aux[ vp->objects_last_page++ ];
2179   aux_ptr->rndx.rfd   = file_index;
2180   aux_ptr->rndx.index = sym_index;
2181
2182   return vp->num_allocated++;
2183 }
2184
2185 \f
2186 /* Add an auxiliary symbol (passing the basic type and possibly
2187    type qualifiers).  */
2188
2189 STATIC symint_t
2190 add_aux_sym_tir (t, state, hash_tbl)
2191      type_info_t *t;            /* current type information */
2192      hash_state_t state;        /* whether to hash type or not */
2193      thash_t **hash_tbl;        /* pointer to hash table to use */
2194 {
2195   register AUXU *aux_ptr;
2196   register efdr_t *file_ptr = cur_file_ptr;
2197   register varray_t *vp = &file_ptr->aux_syms;
2198   static AUXU init_aux;
2199   symint_t ret;
2200   int i;
2201   AUXU aux;
2202
2203   aux = init_aux;
2204   aux.ti.bt = (int) t->basic_type;
2205   aux.ti.continued = 0;
2206   aux.ti.fBitfield = t->bitfield;
2207
2208   aux.ti.tq0 = (int) t->type_qualifiers[0];
2209   aux.ti.tq1 = (int) t->type_qualifiers[1];
2210   aux.ti.tq2 = (int) t->type_qualifiers[2];
2211   aux.ti.tq3 = (int) t->type_qualifiers[3];
2212   aux.ti.tq4 = (int) t->type_qualifiers[4];
2213   aux.ti.tq5 = (int) t->type_qualifiers[5];
2214
2215
2216   /* For anything that adds additional information, we must not hash,
2217      so check here, and reset our state. */
2218
2219   if (state != hash_no
2220       && (t->type_qualifiers[0] == tq_Array
2221           || t->type_qualifiers[1] == tq_Array
2222           || t->type_qualifiers[2] == tq_Array
2223           || t->type_qualifiers[3] == tq_Array
2224           || t->type_qualifiers[4] == tq_Array
2225           || t->type_qualifiers[5] == tq_Array
2226           || t->basic_type == bt_Struct
2227           || t->basic_type == bt_Union
2228           || t->basic_type == bt_Enum
2229           || t->bitfield
2230           || t->num_dims > 0))
2231     state = hash_no;
2232
2233   /* See if we can hash this type, and save some space, but some types
2234      can't be hashed (because they contain arrays or continuations),
2235      and others can be put into the hash list, but cannot use existing
2236      types because other aux entries precede this one.  */
2237
2238   if (state != hash_no)
2239     {
2240       register thash_t *hash_ptr;
2241       register symint_t hi;
2242
2243       hi = aux.isym & ((1 << HASHBITS) - 1);
2244       hi %= THASH_SIZE;
2245
2246       for (hash_ptr = hash_tbl[hi];
2247            hash_ptr != (thash_t *)0;
2248            hash_ptr = hash_ptr->next)
2249         {
2250           if (aux.isym == hash_ptr->type.isym)
2251             break;
2252         }
2253
2254       if (hash_ptr != (thash_t *)0 && state == hash_yes)
2255         return hash_ptr->indx;
2256
2257       if (hash_ptr == (thash_t *)0)
2258         {
2259           hash_ptr = allocate_thash ();
2260           hash_ptr->next = hash_tbl[hi];
2261           hash_ptr->type = aux;
2262           hash_ptr->indx = vp->num_allocated;
2263           hash_tbl[hi] = hash_ptr;
2264         }
2265     }
2266
2267   /* Everything is set up, add the aux symbol. */
2268   if (vp->objects_last_page == vp->objects_per_page)
2269     add_varray_page (vp);
2270
2271   aux_ptr = &vp->last->datum->aux[ vp->objects_last_page++ ];
2272   *aux_ptr = aux;
2273
2274   ret = vp->num_allocated++;
2275
2276   /* Add bitfield length if it exists.
2277      
2278      NOTE:  Mips documentation claims bitfield goes at the end of the
2279      AUX record, but the DECstation compiler emits it here.
2280      (This would only make a difference for enum bitfields.)
2281
2282      Also note:  We use the last size given since gcc may emit 2
2283      for an enum bitfield.  */
2284
2285   if (t->bitfield)
2286     (void) add_aux_sym_symint ((symint_t)t->sizes[t->num_sizes-1]);
2287
2288
2289   /* Add tag information if needed.  Structure, union, and enum
2290      references add 2 aux symbols: a [file index, symbol index]
2291      pointer to the structure type, and the current file index.  */
2292
2293   if (t->basic_type == bt_Struct
2294       || t->basic_type == bt_Union
2295       || t->basic_type == bt_Enum)
2296     {
2297       register symint_t file_index = t->tag_ptr->ifd;
2298       register symint_t sym_index  = t->tag_ptr->indx;
2299
2300       if (t->unknown_tag)
2301         {
2302           (void) add_aux_sym_rndx (ST_RFDESCAPE, sym_index);
2303           (void) add_aux_sym_symint ((symint_t)-1);
2304         }
2305       else if (sym_index != indexNil)
2306         {
2307           (void) add_aux_sym_rndx (ST_RFDESCAPE, sym_index);
2308           (void) add_aux_sym_symint (file_index);
2309         }
2310       else
2311         {
2312           register forward_t *forward_ref = allocate_forward ();
2313
2314           forward_ref->type_ptr = aux_ptr;
2315           forward_ref->next = t->tag_ptr->forward_ref;
2316           t->tag_ptr->forward_ref = forward_ref;
2317
2318           (void) add_aux_sym_rndx (ST_RFDESCAPE, sym_index);
2319           forward_ref->index_ptr
2320             = &vp->last->datum->aux[ vp->objects_last_page - 1];
2321
2322           (void) add_aux_sym_symint (file_index);
2323           forward_ref->ifd_ptr
2324             = &vp->last->datum->aux[ vp->objects_last_page - 1];
2325         }
2326     }
2327
2328   /* Add information about array bounds if they exist.  */
2329   for (i = 0; i < t->num_dims; i++)
2330     {
2331       (void) add_aux_sym_rndx (ST_RFDESCAPE,
2332                                cur_file_ptr->int_type);
2333
2334       (void) add_aux_sym_symint (cur_file_ptr->file_index);     /* file index*/
2335       (void) add_aux_sym_symint ((symint_t)0);                  /* low bound */
2336       (void) add_aux_sym_symint (t->dimensions[i] - 1);         /* high bound*/
2337       (void) add_aux_sym_symint ((t->dimensions[i] == 0)        /* stride */
2338                               ? 0
2339                               : (t->sizes[i] * 8) / t->dimensions[i]);
2340     };
2341
2342   /* NOTE:  Mips documentation claism that the bitfield width goes here.
2343      But it needs to be emitted earlier. */
2344
2345   return ret;
2346 }
2347
2348 \f
2349 /* Add a tag to the tag table (unless it already exists).  */
2350
2351 STATIC tag_t *
2352 get_tag (tag_start, tag_end_p1, indx, basic_type)
2353      const char *tag_start;             /* 1st byte of tag name */
2354      const char *tag_end_p1;            /* 1st byte after tag name */
2355      symint_t indx;                     /* index of tag start block */
2356      bt_t basic_type;                   /* bt_Struct, bt_Union, or bt_Enum */
2357 {
2358   shash_t *hash_ptr;
2359   tag_t *tag_ptr;
2360   hash_ptr = hash_string (tag_start,
2361                           tag_end_p1 - tag_start,
2362                           &tag_hash[0],
2363                           (symint_t *)0);
2364
2365   if (hash_ptr != (shash_t *)0
2366       && hash_ptr->tag_ptr != (tag_t *)0)
2367   {
2368     tag_ptr = hash_ptr->tag_ptr;
2369     if (indx != indexNil)
2370       {
2371         tag_ptr->basic_type = basic_type;
2372         tag_ptr->ifd        = cur_file_ptr->file_index;
2373         tag_ptr->indx       = indx;
2374       }
2375     return tag_ptr;
2376   }
2377
2378   (void) add_string (&tag_strings,
2379                      &tag_hash[0],
2380                      tag_start,
2381                      tag_end_p1,
2382                      &hash_ptr);
2383
2384   tag_ptr = allocate_tag ();
2385   tag_ptr->forward_ref  = (forward_t *) 0;
2386   tag_ptr->hash_ptr     = hash_ptr;
2387   tag_ptr->same_name    = hash_ptr->tag_ptr;
2388   tag_ptr->basic_type   = basic_type;
2389   tag_ptr->indx         = indx;
2390   tag_ptr->ifd          = (indx == indexNil) ? -1 : cur_file_ptr->file_index;
2391   tag_ptr->same_block   = cur_tag_head->first_tag;
2392
2393   cur_tag_head->first_tag = tag_ptr;
2394   hash_ptr->tag_ptr       = tag_ptr;
2395
2396   return tag_ptr;
2397 }
2398
2399 \f
2400 /* Add an unknown {struct, union, enum} tag.  */
2401
2402 STATIC void
2403 add_unknown_tag (ptag)
2404      tag_t      *ptag;          /* pointer to tag information */
2405 {
2406   shash_t *hash_ptr     = ptag->hash_ptr;
2407   char *name_start      = hash_ptr->string;
2408   char *name_end_p1     = name_start + hash_ptr->len;
2409   forward_t *f_next     = ptag->forward_ref;
2410   forward_t *f_cur;
2411   int sym_index;
2412   int file_index        = cur_file_ptr->file_index;
2413
2414   if (debug > 1)
2415     {
2416       char *agg_type    = "{unknown aggregate type}";
2417       switch (ptag->basic_type)
2418         {
2419         case bt_Struct: agg_type = "struct";    break;
2420         case bt_Union:  agg_type = "union";     break;
2421         case bt_Enum:   agg_type = "enum";      break;
2422         default:                                break;
2423         }
2424
2425       fprintf (stderr, "unknown %s %.*s found\n", agg_type,
2426                hash_ptr->len, name_start);
2427     }
2428
2429   sym_index = add_local_symbol (name_start,
2430                                 name_end_p1,
2431                                 st_Block,
2432                                 sc_Info,
2433                                 (symint_t)0,
2434                                 (symint_t)0);
2435
2436   (void) add_local_symbol (name_start,
2437                            name_end_p1,
2438                            st_End,
2439                            sc_Info,
2440                            (symint_t)0,
2441                            (symint_t)0);
2442
2443   while (f_next != (forward_t *)0)
2444     {
2445       f_cur  = f_next;
2446       f_next = f_next->next;
2447
2448       f_cur->ifd_ptr->isym = file_index;
2449       f_cur->index_ptr->rndx.index = sym_index;
2450
2451       free_forward (f_cur);
2452     }
2453
2454   return;
2455 }
2456
2457 \f
2458 /* Add a procedure to the current file's list of procedures, and record
2459    this is the current procedure.  If the assembler created a PDR for
2460    this procedure, use that to initialize the current PDR.  */
2461
2462 STATIC void
2463 add_procedure (func_start, func_end_p1)
2464      const char *func_start;            /* 1st byte of func name */
2465      const char *func_end_p1;           /* 1st byte after func name */
2466 {
2467   register PDR *new_proc_ptr;
2468   register efdr_t *file_ptr = cur_file_ptr;
2469   register varray_t *vp = &file_ptr->procs;
2470   register symint_t value = 0;
2471   register st_t proc_type = st_Proc;
2472   register shash_t *shash_ptr = hash_string (func_start,
2473                                             func_end_p1 - func_start,
2474                                             &orig_str_hash[0],
2475                                             (symint_t *)0);
2476
2477   if (debug)
2478     fputc ('\n', stderr);
2479
2480   if (vp->objects_last_page == vp->objects_per_page)
2481     add_varray_page (vp);
2482
2483   cur_proc_ptr = new_proc_ptr = &vp->last->datum->proc[ vp->objects_last_page++ ];
2484
2485   vp->num_allocated++;
2486
2487
2488   /* Did the assembler create this procedure?  If so, get the PDR information.  */
2489   cur_oproc_ptr = (PDR *)0;
2490   if (shash_ptr != (shash_t *)0)
2491     {
2492       register PDR *old_proc_ptr = shash_ptr->proc_ptr;
2493       register SYMR *sym_ptr = shash_ptr->sym_ptr;
2494
2495       if (old_proc_ptr != (PDR *)0
2496           && sym_ptr != (SYMR *)0
2497           && ((st_t)sym_ptr->st == st_Proc || (st_t)sym_ptr->st == st_StaticProc))
2498         {
2499           cur_oproc_begin = sym_ptr;
2500           cur_oproc_end = shash_ptr->end_ptr;
2501           value = sym_ptr->value;
2502
2503           cur_oproc_ptr = old_proc_ptr;
2504           proc_type = (st_t)sym_ptr->st;
2505           *new_proc_ptr = *old_proc_ptr;        /* initialize */
2506         }
2507     }
2508
2509   if (cur_oproc_ptr == (PDR *)0)
2510     error ("Did not find a PDR block for %.*s", func_end_p1 - func_start, func_start);
2511
2512   /* Determine the start of symbols. */
2513   new_proc_ptr->isym = file_ptr->symbols.num_allocated;
2514
2515   /* Push the start of the function.  */
2516   (void) add_local_symbol (func_start, func_end_p1,
2517                            proc_type, sc_Text,
2518                            value,
2519                            (symint_t)0);
2520 }
2521
2522 \f
2523 /* Add a new filename, and set up all of the file relative
2524    virtual arrays (strings, symbols, aux syms, etc.).  Record
2525    where the current file structure lives.  */
2526
2527 STATIC void
2528 add_file (file_start, file_end_p1)
2529      const char *file_start;            /* first byte in string */
2530      const char *file_end_p1;           /* first byte after string */
2531 {
2532   static char zero_bytes[2] = { '\0', '\0' };
2533
2534   register Ptrdiff_t len = file_end_p1 - file_start;
2535   register int first_ch = *file_start;
2536   register efdr_t *file_ptr;
2537
2538   if (debug)
2539     fprintf (stderr, "\tfile\t%.*s\n", len, file_start);
2540
2541   /* See if the file has already been created.  */
2542   for (file_ptr = first_file;
2543        file_ptr != (efdr_t *)0;
2544        file_ptr = file_ptr->next_file)
2545     {
2546       if (first_ch == file_ptr->name[0]
2547           && file_ptr->name[len] == '\0'
2548           && memcmp ((CPTR_T) file_start, (CPTR_T) file_ptr->name, len) == 0)
2549         {
2550           cur_file_ptr = file_ptr;
2551           break;
2552         }
2553     }
2554
2555   /* If this is a new file, create it. */
2556   if (file_ptr == (efdr_t *)0)
2557     {
2558       if (file_desc.objects_last_page == file_desc.objects_per_page)
2559         add_varray_page (&file_desc);
2560
2561       file_ptr = cur_file_ptr =
2562         &file_desc.last->datum->file[ file_desc.objects_last_page++ ];
2563       *file_ptr = init_file;
2564
2565       file_ptr->file_index = file_desc.num_allocated++;
2566
2567       /* Allocate the string hash table.  */
2568       file_ptr->shash_head = (shash_t **) allocate_page ();
2569
2570       /* Make sure 0 byte in string table is null  */
2571       add_string (&file_ptr->strings,
2572                   &file_ptr->shash_head[0],
2573                   &zero_bytes[0],
2574                   &zero_bytes[0],
2575                   (shash_t **)0);
2576
2577       if (file_end_p1 - file_start > PAGE_USIZE-2)
2578         fatal ("Filename goes over one page boundary.");
2579
2580       /* Push the start of the filename. We assume that the filename
2581          will be stored at string offset 1.  */
2582       (void) add_local_symbol (file_start, file_end_p1, st_File, sc_Text,
2583                                (symint_t)0, (symint_t)0);
2584       file_ptr->fdr.rss = 1;
2585       file_ptr->name = &file_ptr->strings.last->datum->byte[1];
2586       file_ptr->name_len = file_end_p1 - file_start;
2587
2588       /* Update the linked list of file descriptors.  */
2589       *last_file_ptr = file_ptr;
2590       last_file_ptr = &file_ptr->next_file;
2591
2592       /* Add void & int types to the file (void should be first to catch
2593          errant 0's within the index fields).  */
2594       file_ptr->void_type = add_aux_sym_tir (&void_type_info,
2595                                              hash_yes,
2596                                              &cur_file_ptr->thash_head[0]);
2597
2598       file_ptr->int_type = add_aux_sym_tir (&int_type_info,
2599                                             hash_yes,
2600                                             &cur_file_ptr->thash_head[0]);
2601     }
2602 }
2603
2604 \f
2605 /* Add a stream of random bytes to a varray.  */
2606
2607 STATIC void
2608 add_bytes (vp, input_ptr, nitems)
2609      varray_t *vp;                      /* virtual array to add too */
2610      char *input_ptr;                   /* start of the bytes */
2611      Size_t nitems;                     /* # items to move */
2612 {
2613   register Size_t move_items;
2614   register Size_t move_bytes;
2615   register char *ptr;
2616
2617   while (nitems > 0)
2618     {
2619       if (vp->objects_last_page >= vp->objects_per_page)
2620         add_varray_page (vp);
2621
2622       ptr = &vp->last->datum->byte[ vp->objects_last_page * vp->object_size ];
2623       move_items = vp->objects_per_page - vp->objects_last_page;
2624       if (move_items > nitems)
2625         move_items = nitems;
2626
2627       move_bytes = move_items * vp->object_size;
2628       nitems -= move_items;
2629
2630       if (move_bytes >= 32)
2631         {
2632           (void) memcpy ((PTR_T) ptr, (CPTR_T) input_ptr, move_bytes);
2633           input_ptr += move_bytes;
2634         }
2635       else
2636         {
2637           while (move_bytes-- > 0)
2638             *ptr++ = *input_ptr++;
2639         }
2640     }
2641 }
2642
2643 \f
2644 /* Convert storage class to string.  */
2645
2646 STATIC char *
2647 sc_to_string(storage_class)
2648      sc_t storage_class;
2649 {
2650   switch(storage_class)
2651     {
2652     case sc_Nil:         return "Nil,";
2653     case sc_Text:        return "Text,";
2654     case sc_Data:        return "Data,";
2655     case sc_Bss:         return "Bss,";
2656     case sc_Register:    return "Register,";
2657     case sc_Abs:         return "Abs,";
2658     case sc_Undefined:   return "Undefined,";
2659     case sc_CdbLocal:    return "CdbLocal,";
2660     case sc_Bits:        return "Bits,";
2661     case sc_CdbSystem:   return "CdbSystem,";
2662     case sc_RegImage:    return "RegImage,";
2663     case sc_Info:        return "Info,";
2664     case sc_UserStruct:  return "UserStruct,";
2665     case sc_SData:       return "SData,";
2666     case sc_SBss:        return "SBss,";
2667     case sc_RData:       return "RData,";
2668     case sc_Var:         return "Var,";
2669     case sc_Common:      return "Common,";
2670     case sc_SCommon:     return "SCommon,";
2671     case sc_VarRegister: return "VarRegister,";
2672     case sc_Variant:     return "Variant,";
2673     case sc_SUndefined:  return "SUndefined,";
2674     case sc_Init:        return "Init,";
2675     case sc_Max:         return "Max,";
2676     }
2677
2678   return "???,";
2679 }
2680
2681 \f
2682 /* Convert symbol type to string.  */
2683
2684 STATIC char *
2685 st_to_string(symbol_type)
2686      st_t symbol_type;
2687 {
2688   switch(symbol_type)
2689     {
2690     case st_Nil:        return "Nil,";
2691     case st_Global:     return "Global,";
2692     case st_Static:     return "Static,";
2693     case st_Param:      return "Param,";
2694     case st_Local:      return "Local,";
2695     case st_Label:      return "Label,";
2696     case st_Proc:       return "Proc,";
2697     case st_Block:      return "Block,";
2698     case st_End:        return "End,";
2699     case st_Member:     return "Member,";
2700     case st_Typedef:    return "Typedef,";
2701     case st_File:       return "File,";
2702     case st_RegReloc:   return "RegReloc,";
2703     case st_Forward:    return "Forward,";
2704     case st_StaticProc: return "StaticProc,";
2705     case st_Constant:   return "Constant,";
2706     case st_Str:        return "String,";
2707     case st_Number:     return "Number,";
2708     case st_Expr:       return "Expr,";
2709     case st_Type:       return "Type,";
2710     case st_Max:        return "Max,";
2711     }
2712
2713   return "???,";
2714 }
2715
2716 \f
2717 /* Read a line from standard input, and return the start of the buffer
2718    (which is grows if the line is too big).  We split lines at the
2719    semi-colon, and return each logical line independently.  */
2720
2721 STATIC char *
2722 read_line __proto((void))
2723 {
2724   static   int line_split_p     = 0;
2725   register int string_p         = 0;
2726   register int comment_p        = 0;
2727   register int ch;
2728   register char *ptr;
2729
2730   if (cur_line_start == (char *)0)
2731     {                           /* allocate initial page */
2732       cur_line_start = (char *) allocate_page ();
2733       cur_line_alloc = PAGE_SIZE;
2734     }
2735
2736   if (!line_split_p)
2737     line_number++;
2738
2739   line_split_p = 0;
2740   cur_line_nbytes = 0;
2741
2742   for (ptr = cur_line_start; (ch = getchar ()) != EOF; *ptr++ = ch)
2743     {
2744       if (++cur_line_nbytes >= cur_line_alloc-1)
2745         {
2746           register int num_pages = cur_line_alloc / PAGE_SIZE;
2747           register char *old_buffer = cur_line_start;
2748
2749           cur_line_alloc += PAGE_SIZE;
2750           cur_line_start = (char *) allocate_multiple_pages (num_pages+1);
2751           memcpy (cur_line_start, old_buffer, num_pages * PAGE_SIZE);
2752
2753           ptr = cur_line_start + cur_line_nbytes - 1;
2754         }
2755
2756       if (ch == '\n')
2757         {
2758           *ptr++ = '\n';
2759           *ptr = '\0';
2760           cur_line_ptr = cur_line_start;
2761           return cur_line_ptr;
2762         }
2763
2764       else if (ch == '\0')
2765         error ("Null character found in input");
2766
2767       else if (!comment_p)
2768         {
2769           if (ch == '"')
2770             string_p = !string_p;
2771
2772           else if (ch == '#')
2773             comment_p++;
2774
2775           else if (ch == ';' && !string_p)
2776             {
2777               line_split_p = 1;
2778               *ptr++ = '\n';
2779               *ptr = '\0';
2780               cur_line_ptr = cur_line_start;
2781               return cur_line_ptr;
2782             }
2783         }
2784     }
2785
2786   if (ferror (stdin))
2787     pfatal_with_name (input_name);
2788
2789   cur_line_ptr = (char *)0;
2790   return (char *)0;
2791 }
2792
2793 \f
2794 /* Parse #.begin directives which have a label as the first argument
2795    which gives the location of the start of the block.  */
2796
2797 STATIC void
2798 parse_begin (start)
2799      const char *start;                 /* start of directive */
2800 {
2801   const char *end_p1;                   /* end of label */
2802   int ch;
2803   shash_t *hash_ptr;                    /* hash pointer to lookup label */
2804
2805   if (cur_file_ptr == (efdr_t *)0)
2806     {
2807       error ("#.begin directive without a preceding .file directive");
2808       return;
2809     }
2810
2811   if (cur_proc_ptr == (PDR *)0)
2812     {
2813       error ("#.begin directive without a preceding .ent directive");
2814       return;
2815     }
2816
2817   for (end_p1 = start; (ch = *end_p1) != '\0' && !isspace (ch); end_p1++)
2818     ;
2819
2820   hash_ptr = hash_string (start,
2821                           end_p1 - start,
2822                           &orig_str_hash[0],
2823                           (symint_t *)0);
2824
2825   if (hash_ptr == (shash_t *)0)
2826     {
2827       error ("Label %.*s not found for #.begin", end_p1 - start, start);
2828       return;
2829     }
2830
2831   if (cur_oproc_begin == (SYMR *)0)
2832     {
2833       error ("Procedure table %.*s not found for #.begin", end_p1 - start, start);
2834       return;
2835     }
2836
2837   (void) add_local_symbol ((const char *)0, (const char *)0,
2838                            st_Block, sc_Text,
2839                            (symint_t)hash_ptr->sym_ptr->value - cur_oproc_begin->value,
2840                            (symint_t)0);
2841 }
2842
2843 \f
2844 /* Parse #.bend directives which have a label as the first argument
2845    which gives the location of the end of the block.  */
2846
2847 STATIC void
2848 parse_bend (start)
2849      const char *start;                 /* start of directive */
2850 {
2851   const char *end_p1;                   /* end of label */
2852   int ch;
2853   shash_t *hash_ptr;                    /* hash pointer to lookup label */
2854
2855   if (cur_file_ptr == (efdr_t *)0)
2856     {
2857       error ("#.begin directive without a preceding .file directive");
2858       return;
2859     }
2860
2861   if (cur_proc_ptr == (PDR *)0)
2862     {
2863       error ("#.bend directive without a preceding .ent directive");
2864       return;
2865     }
2866
2867   for (end_p1 = start; (ch = *end_p1) != '\0' && !isspace (ch); end_p1++)
2868     ;
2869
2870   hash_ptr = hash_string (start,
2871                           end_p1 - start,
2872                           &orig_str_hash[0],
2873                           (symint_t *)0);
2874
2875   if (hash_ptr == (shash_t *)0)
2876     {
2877       error ("Label %.*s not found for #.bend", end_p1 - start, start);
2878       return;
2879     }
2880
2881   if (cur_oproc_begin == (SYMR *)0)
2882     {
2883       error ("Procedure table %.*s not found for #.bend", end_p1 - start, start);
2884       return;
2885     }
2886
2887   (void) add_local_symbol ((const char *)0, (const char *)0,
2888                            st_End, sc_Text,
2889                            (symint_t)hash_ptr->sym_ptr->value - cur_oproc_begin->value,
2890                            (symint_t)0);
2891 }
2892
2893 \f
2894 /* Parse #.def directives, which are contain standard COFF subdirectives
2895    to describe the debugging format.  These subdirectives include:
2896
2897         .scl    specify storage class
2898         .val    specify a value
2899         .endef  specify end of COFF directives
2900         .type   specify the type
2901         .size   specify the size of an array
2902         .dim    specify an array dimension
2903         .tag    specify a tag for a struct, union, or enum.  */
2904
2905 STATIC void
2906 parse_def (name_start)
2907      const char *name_start;                    /* start of directive */
2908 {
2909   const char *dir_start;                        /* start of current directive*/
2910   const char *dir_end_p1;                       /* end+1 of current directive*/
2911   const char *arg_start;                        /* start of current argument */
2912   const char *arg_end_p1;                       /* end+1 of current argument */
2913   const char *name_end_p1;                      /* end+1 of label */
2914   const char *tag_start   = (const char *)0;    /* start of tag name */
2915   const char *tag_end_p1  = (const char *)0;    /* end+1 of tag name */
2916   sc_t storage_class      = sc_Nil;
2917   st_t symbol_type        = st_Nil;
2918   type_info_t t;
2919   EXTR *eptr              = (EXTR *)0;          /* ext. sym equivalent to def*/
2920   int is_function         = 0;                  /* != 0 if function */
2921   symint_t value          = 0;
2922   symint_t indx           = cur_file_ptr->void_type;
2923   int error_line          = 0;
2924   symint_t arg_number;
2925   symint_t temp_array[ N_TQ ];
2926   int arg_was_number;
2927   int ch, i;
2928   Ptrdiff_t len;
2929
2930   static int inside_enumeration = 0;            /* is this an enumeration? */
2931
2932
2933   /* Initialize the type information.  */
2934   t = type_info_init;
2935
2936
2937   /* Search for the end of the name being defined.  */
2938   /* Allow spaces and such in names for G++ templates, which produce stabs
2939      that look like:
2940
2941      #.def   SMANIP<long unsigned int>; .scl 10; .type 0x8; .size 8; .endef */
2942
2943   for (name_end_p1 = name_start; (ch = *name_end_p1) != ';' && ch != '\0'; name_end_p1++)
2944     ;
2945
2946   if (ch == '\0')
2947     {
2948       error_line = __LINE__;
2949       saber_stop ();
2950       goto bomb_out;
2951     }
2952
2953   /* Parse the remaining subdirectives now.  */
2954   dir_start = name_end_p1+1;
2955   for (;;)
2956     {
2957       while ((ch = *dir_start) == ' ' || ch == '\t')
2958         ++dir_start;
2959
2960       if (ch != '.')
2961         {
2962           error_line = __LINE__;
2963           saber_stop ();
2964           goto bomb_out;
2965         }
2966
2967       /* Are we done? */
2968       if (dir_start[1] == 'e'
2969           && memcmp (dir_start, ".endef", sizeof (".endef")-1) == 0)
2970         break;
2971
2972       /* Pick up the subdirective now */
2973       for (dir_end_p1 = dir_start+1;
2974            (ch = *dir_end_p1) != ' ' && ch != '\t';
2975            dir_end_p1++)
2976         {
2977           if (ch == '\0' || isspace (ch))
2978             {
2979               error_line = __LINE__;
2980               saber_stop ();
2981               goto bomb_out;
2982             }
2983         }
2984
2985       /* Pick up the subdirective argument now.  */
2986       arg_was_number = arg_number = 0;
2987       arg_end_p1 = (const char *)0;
2988       arg_start = dir_end_p1+1;
2989       ch = *arg_start;
2990       while (ch == ' ' || ch == '\t')
2991         ch = *++arg_start;
2992
2993       if (isdigit (ch) || ch == '-' || ch == '+')
2994         {
2995           int ch2;
2996           arg_number = strtol (arg_start, (char **) &arg_end_p1, 0);
2997           if (arg_end_p1 != arg_start || (ch2 = *arg_end_p1 != ';') || ch2 != ',')
2998             arg_was_number++;
2999         }
3000
3001       else if (ch == '\0' || isspace (ch))
3002         {
3003           error_line = __LINE__;
3004           saber_stop ();
3005           goto bomb_out;
3006         }
3007
3008       if (!arg_was_number)
3009         {
3010           /* Allow spaces and such in names for G++ templates.  */
3011           for (arg_end_p1 = arg_start+1;
3012                (ch = *arg_end_p1) != ';' && ch != '\0';
3013                arg_end_p1++)
3014             ;
3015
3016           if (ch == '\0')
3017             {
3018               error_line = __LINE__;
3019               saber_stop ();
3020               goto bomb_out;
3021             }
3022         }
3023
3024       /* Classify the directives now.  */
3025       len = dir_end_p1 - dir_start;
3026       switch (dir_start[1])
3027         {
3028         default:
3029           error_line = __LINE__;
3030           saber_stop ();
3031           goto bomb_out;
3032
3033         case 'd':
3034           if (len == sizeof (".dim")-1
3035               && memcmp (dir_start, ".dim", sizeof (".dim")-1) == 0
3036               && arg_was_number)
3037             {
3038               symint_t *t_ptr = &temp_array[ N_TQ-1 ];
3039
3040               *t_ptr = arg_number;
3041               while (*arg_end_p1 == ',' && arg_was_number)
3042                 {
3043                   arg_start = arg_end_p1+1;
3044                   ch = *arg_start;
3045                   while (ch == ' ' || ch == '\t')
3046                     ch = *++arg_start;
3047
3048                   arg_was_number = 0;
3049                   if (isdigit (ch) || ch == '-' || ch == '+')
3050                     {
3051                       int ch2;
3052                       arg_number = strtol (arg_start, (char **) &arg_end_p1, 0);
3053                       if (arg_end_p1 != arg_start || (ch2 = *arg_end_p1 != ';') || ch2 != ',')
3054                         arg_was_number++;
3055
3056                       if (t_ptr == &temp_array[0])
3057                         {
3058                           error_line = __LINE__;
3059                           saber_stop ();
3060                           goto bomb_out;
3061                         }
3062
3063                       *--t_ptr = arg_number;
3064                     }
3065                 }
3066
3067               /* Reverse order of dimensions.  */
3068               while (t_ptr <= &temp_array[ N_TQ-1 ])
3069                 {
3070                   if (t.num_dims >= N_TQ-1)
3071                     {
3072                       error_line = __LINE__;
3073                       saber_stop ();
3074                       goto bomb_out;
3075                     }
3076
3077                   t.dimensions[ t.num_dims++ ] = *t_ptr++;
3078                 }
3079               break;
3080             }
3081           else
3082             {
3083               error_line = __LINE__;
3084               saber_stop ();
3085               goto bomb_out;
3086             }
3087
3088
3089         case 's':
3090           if (len == sizeof (".scl")-1
3091               && memcmp (dir_start, ".scl", sizeof (".scl")-1) == 0
3092               && arg_was_number
3093               && arg_number < ((symint_t) C_MAX))
3094             {
3095               /* If the symbol is a static or external, we have
3096                  already gotten the appropriate type and class, so
3097                  make sure we don't override those values.  This is
3098                  needed because there are some type and classes that
3099                  are not in COFF, such as short data, etc.  */
3100               if (symbol_type == st_Nil)
3101                 {
3102                   symbol_type   = map_coff_sym_type[arg_number];
3103                   storage_class = map_coff_storage [arg_number];
3104                 }
3105               break;
3106             }
3107
3108           else if (len == sizeof (".size")-1
3109                    && memcmp (dir_start, ".size", sizeof (".size")-1) == 0
3110                    && arg_was_number)
3111             {
3112               symint_t *t_ptr = &temp_array[ N_TQ-1 ];
3113
3114               *t_ptr = arg_number;
3115               while (*arg_end_p1 == ',' && arg_was_number)
3116                 {
3117                   arg_start = arg_end_p1+1;
3118                   ch = *arg_start;
3119                   while (ch == ' ' || ch == '\t')
3120                     ch = *++arg_start;
3121
3122                   arg_was_number = 0;
3123                   if (isdigit (ch) || ch == '-' || ch == '+')
3124                     {
3125                       int ch2;
3126                       arg_number = strtol (arg_start, (char **) &arg_end_p1, 0);
3127                       if (arg_end_p1 != arg_start || (ch2 = *arg_end_p1 != ';') || ch2 != ',')
3128                         arg_was_number++;
3129
3130                       if (t_ptr == &temp_array[0])
3131                         {
3132                           error_line = __LINE__;
3133                           saber_stop ();
3134                           goto bomb_out;
3135                         }
3136
3137                       *--t_ptr = arg_number;
3138                     }
3139                 }
3140
3141               /* Reverse order of sizes.  */
3142               while (t_ptr <= &temp_array[ N_TQ-1 ])
3143                 {
3144                   if (t.num_sizes >= N_TQ-1)
3145                     {
3146                       error_line = __LINE__;
3147                       saber_stop ();
3148                       goto bomb_out;
3149                     }
3150
3151                   t.sizes[ t.num_sizes++ ] = *t_ptr++;
3152                 }
3153               break;
3154             }
3155
3156           else
3157             {
3158               error_line = __LINE__;
3159               saber_stop ();
3160               goto bomb_out;
3161             }
3162
3163
3164         case 't':
3165           if (len == sizeof (".type")-1
3166               && memcmp (dir_start, ".type", sizeof (".type")-1) == 0
3167               && arg_was_number)
3168             {
3169               tq_t *tq_ptr = &t.type_qualifiers[0];
3170
3171               t.orig_type = (coff_type_t) (arg_number & N_BTMASK);
3172               t.basic_type = map_coff_types [(int)t.orig_type];
3173               for (i = N_TQ-1; i >= 0; i--)
3174                 {
3175                   int dt = (arg_number >> ((i * N_TQ_SHIFT) + N_BT_SHIFT)
3176                             & N_TMASK);
3177
3178                   if (dt != (int)DT_NON)
3179                     *tq_ptr++ = map_coff_derived_type [dt];
3180                 }
3181
3182               /* If this is a function, ignore it, so that we don't get
3183                  two entries (one from the .ent, and one for the .def
3184                  that precedes it).  Save the type information so that
3185                  the end block can properly add it after the begin block
3186                  index.  For MIPS knows what reason, we must strip off
3187                  the function type at this point.  */
3188               if (tq_ptr != &t.type_qualifiers[0] && tq_ptr[-1] == tq_Proc)
3189                 {
3190                   is_function = 1;
3191                   tq_ptr[-1] = tq_Nil;
3192                 }
3193
3194               break;
3195             }
3196
3197           else if (len == sizeof (".tag")-1
3198               && memcmp (dir_start, ".tag", sizeof (".tag")-1) == 0)
3199             {
3200               tag_start = arg_start;
3201               tag_end_p1 = arg_end_p1;
3202               break;
3203             }
3204
3205           else
3206             {
3207               error_line = __LINE__;
3208               saber_stop ();
3209               goto bomb_out;
3210             }
3211
3212
3213         case 'v':
3214           if (len == sizeof (".val")-1
3215               && memcmp (dir_start, ".val", sizeof (".val")-1) == 0)
3216             {
3217               if (arg_was_number)
3218                 value = arg_number;
3219
3220               /* If the value is not an integer value, it must be the
3221                  name of a static or global item.  Look up the name in
3222                  the original symbol table to pick up the storage
3223                  class, symbol type, etc.  */
3224               else
3225                 {
3226                   shash_t *orig_hash_ptr;       /* hash within orig sym table*/
3227                   shash_t *ext_hash_ptr;        /* hash within ext. sym table*/
3228
3229                   ext_hash_ptr = hash_string (arg_start,
3230                                               arg_end_p1 - arg_start,
3231                                               &ext_str_hash[0],
3232                                               (symint_t *)0);
3233
3234                   if (ext_hash_ptr != (shash_t *)0
3235                       && ext_hash_ptr->esym_ptr != (EXTR *)0)
3236                     eptr = ext_hash_ptr->esym_ptr;
3237
3238                   orig_hash_ptr = hash_string (arg_start,
3239                                                arg_end_p1 - arg_start,
3240                                                &orig_str_hash[0],
3241                                                (symint_t *)0);
3242
3243                   if ((orig_hash_ptr == (shash_t *)0
3244                        || orig_hash_ptr->sym_ptr == (SYMR *)0)
3245                       && eptr == (EXTR *)0)
3246                     {
3247                       fprintf (stderr, "warning, %.*s not found in original or external symbol tables, value defaults to 0\n",
3248                                arg_end_p1 - arg_start,
3249                                arg_start);
3250                       value = 0;
3251                     }
3252                   else
3253                     {
3254                       SYMR *ptr = (orig_hash_ptr != (shash_t *)0
3255                                    && orig_hash_ptr->sym_ptr != (SYMR *)0)
3256                                         ? orig_hash_ptr->sym_ptr
3257                                         : &eptr->asym;
3258
3259                       symbol_type = (st_t) ptr->st;
3260                       storage_class = (sc_t) ptr->sc;
3261                       value = ptr->value;
3262                     }
3263                 }
3264               break;
3265             }
3266           else
3267             {
3268               error_line = __LINE__;
3269               saber_stop ();
3270               goto bomb_out;
3271             }
3272         }
3273
3274       /* Set up to find next directive.  */
3275       dir_start = arg_end_p1 + 1;
3276     }
3277
3278
3279   t.extra_sizes = (tag_start != (char *)0);
3280   if (t.num_dims > 0)
3281     {
3282       int diff = t.num_dims - t.num_sizes;
3283       int i = t.num_dims - 1;
3284       int j;
3285
3286       if (t.num_sizes != 1 || diff < 0)
3287         {
3288           error_line = __LINE__;
3289           saber_stop ();
3290           goto bomb_out;
3291         }
3292
3293       /* If this is an array, make sure the same number of dimensions
3294          and sizes were passed, creating extra sizes for multiply
3295          dimensioned arrays if not passed.  */
3296
3297       t.extra_sizes = 0;
3298       if (diff)
3299         {
3300           for (j = (sizeof (t.sizes) / sizeof (t.sizes[0])) - 1; j >= 0; j--)
3301             t.sizes[ j ] = ((j-diff) >= 0) ? t.sizes[ j-diff ] : 0;
3302
3303           t.num_sizes = i + 1;
3304           for ( i--; i >= 0; i-- )
3305             {
3306               if (t.dimensions[ i+1 ])
3307                 t.sizes[ i ] = t.sizes[ i+1 ] / t.dimensions[ i+1 ];
3308               else
3309                 t.sizes[ i ] = t.sizes[ i+1 ];
3310             }
3311         }
3312     }
3313
3314   else if (symbol_type == st_Member && t.num_sizes - t.extra_sizes == 1)
3315     { /* Is this a bitfield?  This is indicated by a structure memeber
3316          having a size field that isn't an array.  */
3317
3318       t.bitfield = 1;
3319     }
3320
3321
3322   /* Except for enumeration members & begin/ending of scopes, put the
3323      type word in the aux. symbol table.  */
3324
3325   if (symbol_type == st_Block || symbol_type == st_End)
3326     indx = 0;
3327
3328   else if (inside_enumeration)
3329     indx = cur_file_ptr->void_type;
3330
3331   else
3332     {
3333       if (t.basic_type == bt_Struct
3334           || t.basic_type == bt_Union
3335           || t.basic_type == bt_Enum)
3336         {
3337           if (tag_start == (char *)0)
3338             {
3339               error ("No tag specified for %.*s",
3340                      name_end_p1 - name_start,
3341                      name_start);
3342               return;
3343             }
3344
3345           t.tag_ptr = get_tag (tag_start, tag_end_p1,  (symint_t)indexNil,
3346                                t.basic_type);
3347         }
3348
3349       if (is_function)
3350         {
3351           last_func_type_info = t;
3352           last_func_eptr = eptr;
3353           return;
3354         }
3355
3356       indx = add_aux_sym_tir (&t,
3357                               hash_yes,
3358                               &cur_file_ptr->thash_head[0]);
3359     }
3360
3361
3362   /* If this is an external or static symbol, update the appropriate
3363      external symbol.  */
3364
3365   if (eptr != (EXTR *)0
3366       && (eptr->asym.index == indexNil || cur_proc_ptr == (PDR *)0))
3367     {
3368       eptr->ifd = cur_file_ptr->file_index;
3369       eptr->asym.index = indx;
3370     }
3371
3372
3373   /* Do any last minute adjustments that are necessary.  */
3374   switch (symbol_type)
3375     {
3376     default:
3377       break;
3378
3379
3380       /* For the beginning of structs, unions, and enumerations, the
3381          size info needs to be passed in the value field.  */
3382
3383     case st_Block:
3384       if (t.num_sizes - t.num_dims - t.extra_sizes != 1)
3385         {
3386           error_line = __LINE__;
3387           saber_stop ();
3388           goto bomb_out;
3389         }
3390
3391       else
3392         value = t.sizes[0];
3393
3394       inside_enumeration = (t.orig_type == T_ENUM);
3395       break;
3396
3397
3398       /* For the end of structs, unions, and enumerations, omit the
3399          name which is always ".eos".  This needs to be done last, so
3400          that any error reporting above gives the correct name.  */
3401
3402     case st_End:
3403       name_start = name_end_p1 = (const char *)0;
3404       value = inside_enumeration = 0;
3405       break;
3406
3407
3408       /* Members of structures and unions that aren't bitfields, need
3409          to adjust the value from a byte offset to a bit offset.
3410          Members of enumerations do not have the value adjusted, and
3411          can be distinguished by indx == indexNil.  For enumerations,
3412          update the maximum enumeration value.  */
3413
3414     case st_Member:
3415       if (!t.bitfield && !inside_enumeration)
3416         value *= 8;
3417
3418       break;
3419     }
3420
3421
3422   /* Add the symbol, except for global symbols outside of functions,
3423      for which the external symbol table is fine enough.  */
3424
3425   if (eptr == (EXTR *)0
3426       || eptr->asym.st == (int)st_Nil
3427       || cur_proc_ptr != (PDR *)0)
3428     {
3429       symint_t isym = add_local_symbol (name_start, name_end_p1,
3430                                         symbol_type, storage_class,
3431                                         value,
3432                                         indx);
3433
3434       /* deal with struct, union, and enum tags.  */
3435       if (symbol_type == st_Block)
3436         {
3437           /* Create or update the tag information.  */
3438           tag_t *tag_ptr = get_tag (name_start,
3439                                     name_end_p1,
3440                                     isym,
3441                                     t.basic_type);
3442
3443           /* If there are any forward references, fill in the appropriate
3444              file and symbol indexes.  */
3445
3446           symint_t file_index  = cur_file_ptr->file_index;
3447           forward_t *f_next = tag_ptr->forward_ref;
3448           forward_t *f_cur;
3449
3450           while (f_next != (forward_t *)0)
3451             {
3452               f_cur  = f_next;
3453               f_next = f_next->next;
3454
3455               f_cur->ifd_ptr->isym = file_index;
3456               f_cur->index_ptr->rndx.index = isym;
3457
3458               free_forward (f_cur);
3459             }
3460
3461           tag_ptr->forward_ref = (forward_t *)0;
3462         }
3463     }
3464
3465   /* Normal return  */
3466   return;
3467
3468   /* Error return, issue message.  */
3469 bomb_out:
3470   if (error_line)
3471     error ("compiler error, badly formed #.def (internal line # = %d)", error_line);
3472   else
3473     error ("compiler error, badly formed #.def");
3474
3475   return;
3476 }
3477
3478 \f
3479 /* Parse .end directives.  */
3480
3481 STATIC void
3482 parse_end (start)
3483      const char *start;                 /* start of directive */
3484 {
3485   register const char *start_func, *end_func_p1;
3486   register int ch;
3487   register symint_t value;
3488   register FDR *orig_fdr;
3489
3490   if (cur_file_ptr == (efdr_t *)0)
3491     {
3492       error (".end directive without a preceding .file directive");
3493       return;
3494     }
3495
3496   if (cur_proc_ptr == (PDR *)0)
3497     {
3498       error (".end directive without a preceding .ent directive");
3499       return;
3500     }
3501
3502   /* Get the function name, skipping whitespace.  */
3503   for (start_func = start; isspace (*start_func); start_func++)
3504     ;
3505
3506   ch = *start_func;
3507   if (!IS_ASM_IDENT (ch))
3508     {
3509       error (".end directive has no name");
3510       return;
3511     }
3512
3513   for (end_func_p1 = start_func; IS_ASM_IDENT (ch); ch = *++end_func_p1)
3514     ;
3515
3516
3517   /* Get the value field for creating the end from the original object
3518      file (which we find by locating the procedure start, and using the
3519      pointer to the end+1 block and backing up.  The index points to a
3520      two word aux. symbol, whose first word is the index of the end
3521      symbol, and the second word is the type of the function return
3522      value.  */
3523
3524   orig_fdr = cur_file_ptr->orig_fdr;
3525   value = 0;
3526   if (orig_fdr != (FDR *)0 && cur_oproc_end != (SYMR *)0)
3527     value = cur_oproc_end->value;
3528
3529   else
3530     error ("Cannot find .end block for %.*s", end_func_p1 - start_func, start_func);
3531
3532   (void) add_local_symbol (start_func, end_func_p1,
3533                            st_End, sc_Text,
3534                            value,
3535                            (symint_t)0);
3536
3537   cur_proc_ptr = cur_oproc_ptr = (PDR *)0;
3538 }
3539
3540 \f
3541 /* Parse .ent directives.  */
3542
3543 STATIC void
3544 parse_ent (start)
3545      const char *start;                 /* start of directive */
3546 {
3547   register const char *start_func, *end_func_p1;
3548   register int ch;
3549
3550   if (cur_file_ptr == (efdr_t *)0)
3551     {
3552       error (".ent directive without a preceding .file directive");
3553       return;
3554     }
3555
3556   if (cur_proc_ptr != (PDR *)0)
3557     {
3558       error ("second .ent directive found before .end directive");
3559       return;
3560     }
3561
3562   for (start_func = start; isspace (*start_func); start_func++)
3563     ;
3564
3565   ch = *start_func;
3566   if (!IS_ASM_IDENT (ch))
3567     {
3568       error (".ent directive has no name");
3569       return;
3570     }
3571
3572   for (end_func_p1 = start_func; IS_ASM_IDENT (ch); ch = *++end_func_p1)
3573     ;
3574
3575   (void) add_procedure (start_func, end_func_p1);
3576 }
3577
3578 \f
3579 /* Parse .file directives.  */
3580
3581 STATIC void
3582 parse_file (start)
3583      const char *start;                 /* start of directive */
3584 {
3585   char *p;
3586   register char *start_name, *end_name_p1;
3587
3588   (void) strtol (start, &p, 0);
3589   if (start == p
3590       || (start_name = local_index (p, '"')) == (char *)0
3591       || (end_name_p1 = local_rindex (++start_name, '"')) == (char *)0)
3592     {
3593       error ("Invalid .file directive");
3594       return;
3595     }
3596
3597   if (cur_proc_ptr != (PDR *)0)
3598     {
3599       error ("No way to handle .file within .ent/.end section");
3600       return;
3601     }
3602
3603   add_file (start_name, end_name_p1);
3604 }
3605
3606 \f
3607 /* Make sure the @stabs symbol is emitted.  */
3608
3609 static void
3610 mark_stabs (start)
3611      const char *start;                 /* Start of directive (ignored) */
3612 {
3613   if (!stabs_seen)
3614     {
3615       /* Add a dummy @stabs dymbol. */
3616       stabs_seen = 1;
3617       (void) add_local_symbol (stabs_symbol,
3618                                stabs_symbol + sizeof (stabs_symbol),
3619                                stNil, scInfo, -1, MIPS_MARK_STAB(0));
3620
3621     }
3622 }
3623
3624 \f
3625 /* Parse .stabs directives.
3626
3627    .stabs directives have five fields:
3628         "string"        a string, encoding the type information.
3629         code            a numeric code, defined in <stab.h>
3630         0               a zero
3631         0               a zero or line number
3632         value           a numeric value or an address.
3633
3634     If the value is relocatable, we transform this into:
3635         iss             points as an index into string space
3636         value           value from lookup of the name
3637         st              st from lookup of the name
3638         sc              sc from lookup of the name
3639         index           code|CODE_MASK
3640
3641     If the value is not relocatable, we transform this into:
3642         iss             points as an index into string space
3643         value           value
3644         st              st_Nil
3645         sc              sc_Nil
3646         index           code|CODE_MASK
3647
3648     .stabn directives have four fields (string is null):
3649         code            a numeric code, defined in <stab.h>
3650         0               a zero
3651         0               a zero or a line number
3652         value           a numeric value or an address.  */
3653
3654 STATIC void
3655 parse_stabs_common (string_start, string_end, rest)
3656      const char *string_start;          /* start of string or NULL */
3657      const char *string_end;            /* end+1 of string or NULL */
3658      const char *rest;                  /* rest of the directive. */
3659 {
3660   efdr_t *save_file_ptr = cur_file_ptr;
3661   symint_t code;
3662   symint_t value;
3663   char *p;
3664   st_t st;
3665   sc_t sc;
3666   int ch;
3667
3668   if (stabs_seen == 0)
3669     mark_stabs ("");
3670
3671   /* Read code from stabs.  */
3672   if (!isdigit (*rest))
3673     {
3674       error ("Invalid .stabs/.stabn directive, code is non-numeric");
3675       return;
3676     }
3677
3678   code = strtol (rest, &p, 0);
3679
3680   /* Line number stabs are handled differently, since they have two values,
3681      the line number and the address of the label.  We use the index field
3682      (aka code) to hold the line number, and the value field to hold the
3683      address.  The symbol type is st_Label, which should be different from
3684      the other stabs, so that gdb can recognize it.  */
3685
3686   if (code == (int)N_SLINE)
3687     {
3688       SYMR *sym_ptr, dummy_symr;
3689       shash_t *shash_ptr;
3690
3691       /* Skip ,0, */
3692       if (p[0] != ',' || p[1] != '0' || p[2] != ',' || !isdigit (p[3]))
3693         {
3694           error ("Invalid line number .stabs/.stabn directive");
3695           return;
3696         }
3697
3698       code = strtol (p+3, &p, 0);
3699       ch = *++p;
3700       if (p[-1] != ',' || isdigit (ch) || !IS_ASM_IDENT (ch))
3701         {
3702           error ("Invalid line number .stabs/.stabn directive");
3703           return;
3704         }
3705
3706       dummy_symr.index = code;
3707       if (dummy_symr.index != code)
3708         {
3709           error ("Line number (%d) for .stabs/.stabn directive cannot fit in index field (20 bits)",
3710                  code);
3711
3712           return;
3713         }
3714
3715       shash_ptr = hash_string (p,
3716                                strlen (p) - 1,
3717                                &orig_str_hash[0],
3718                                (symint_t *)0);
3719
3720       if (shash_ptr == (shash_t *)0
3721           || (sym_ptr = shash_ptr->sym_ptr) == (SYMR *)0)
3722         {
3723           error ("Invalid .stabs/.stabn directive, value not found");
3724           return;
3725         }
3726
3727       if ((st_t) sym_ptr->st != st_Label)
3728         {
3729           error ("Invalid line number .stabs/.stabn directive");
3730           return;
3731         }
3732
3733       st = st_Label;
3734       sc = (sc_t) sym_ptr->sc;
3735       value = sym_ptr->value;
3736     }
3737   else
3738     {
3739       /* Skip ,<num>,<num>, */
3740       if (*p++ != ',')
3741         goto failure;
3742       for (; isdigit (*p); p++)
3743         ;
3744       if (*p++ != ',')
3745         goto failure;
3746       for (; isdigit (*p); p++)
3747         ;
3748       if (*p++ != ',')
3749         goto failure;
3750       ch = *p;
3751       if (!IS_ASM_IDENT (ch) && ch != '-')
3752         {
3753         failure:
3754           error ("Invalid .stabs/.stabn directive, bad character");
3755           return;
3756         }
3757
3758       if (isdigit (ch) || ch == '-')
3759         {
3760           st = st_Nil;
3761           sc = sc_Nil;
3762           value = strtol (p, &p, 0);
3763           if (*p != '\n')
3764             {
3765               error ("Invalid .stabs/.stabn directive, stuff after numeric value");
3766               return;
3767             }
3768         }
3769       else if (!IS_ASM_IDENT (ch))
3770         {
3771           error ("Invalid .stabs/.stabn directive, bad character");
3772           return;
3773         }
3774       else
3775         {
3776           SYMR *sym_ptr;
3777           shash_t *shash_ptr;
3778           const char *start, *end_p1;
3779
3780           start = p;
3781           if ((end_p1 = strchr (start, '+')) == (char *)0)
3782             {
3783               if ((end_p1 = strchr (start, '-')) == (char *)0)
3784                 end_p1 = start + strlen(start) - 1;
3785             }
3786
3787           shash_ptr = hash_string (start,
3788                                    end_p1 - start,
3789                                    &orig_str_hash[0],
3790                                    (symint_t *)0);
3791
3792           if (shash_ptr == (shash_t *)0
3793               || (sym_ptr = shash_ptr->sym_ptr) == (SYMR *)0)
3794             {
3795               shash_ptr = hash_string (start,
3796                                        end_p1 - start,
3797                                        &ext_str_hash[0],
3798                                        (symint_t *)0);
3799
3800               if (shash_ptr == (shash_t *)0
3801                   || shash_ptr->esym_ptr == (EXTR *)0)
3802                 {
3803                   error ("Invalid .stabs/.stabn directive, value not found");
3804                   return;
3805                 }
3806               else
3807                 sym_ptr = &(shash_ptr->esym_ptr->asym);
3808             }
3809
3810           /* Traditionally, N_LBRAC and N_RBRAC are *not* relocated. */
3811           if (code == (int)N_LBRAC || code == (int)N_RBRAC)
3812             {
3813               sc = scNil;
3814               st = stNil;
3815             }
3816           else
3817             {
3818               sc = (sc_t) sym_ptr->sc;
3819               st = (st_t) sym_ptr->st;
3820             }
3821           value = sym_ptr->value;
3822
3823           ch = *end_p1++;
3824           if (ch != '\n')
3825             {
3826               if (((!isdigit (*end_p1)) && (*end_p1 != '-'))
3827                   || ((ch != '+') && (ch != '-')))
3828                 {
3829                   error ("Invalid .stabs/.stabn directive, badly formed value");
3830                   return;
3831                 }
3832               if (ch == '+')
3833                 value += strtol (end_p1, &p, 0);
3834               else if (ch == '-')
3835                 value -= strtol (end_p1, &p, 0);
3836
3837               if (*p != '\n')
3838                 {
3839                   error ("Invalid .stabs/.stabn directive, stuff after numeric value");
3840                   return;
3841                 }
3842             }
3843         }
3844       code = MIPS_MARK_STAB(code);
3845     }
3846
3847   (void) add_local_symbol (string_start, string_end, st, sc, value, code);
3848   /* Restore normal file type.  */
3849   cur_file_ptr = save_file_ptr;
3850 }
3851
3852
3853 STATIC void
3854 parse_stabs (start)
3855      const char *start;                 /* start of directive */
3856 {
3857   const char *end = local_index (start+1, '"');
3858
3859   if (*start != '"' || end == (const char *)0 || end[1] != ',')
3860     {
3861       error ("Invalid .stabs directive, no string");
3862       return;
3863     }
3864
3865   parse_stabs_common (start+1, end, end+2);
3866 }
3867
3868
3869 STATIC void
3870 parse_stabn (start)
3871      const char *start;                 /* start of directive */
3872 {
3873   parse_stabs_common ((const char *)0, (const char *)0, start);
3874 }
3875
3876 \f
3877 /* Parse the input file, and write the lines to the output file
3878    if needed.  */
3879
3880 STATIC void
3881 parse_input __proto((void))
3882 {
3883   register char *p;
3884   register int i;
3885   register thead_t *ptag_head;
3886   register tag_t *ptag;
3887   register tag_t *ptag_next;
3888
3889   if (debug)
3890     fprintf (stderr, "\tinput\n");
3891
3892   /* Add a dummy scope block around the entire compilation unit for
3893      structures defined outside of blocks.  */
3894   ptag_head = allocate_thead ();
3895   ptag_head->first_tag = 0;
3896   ptag_head->prev = cur_tag_head;
3897   cur_tag_head = ptag_head;
3898
3899   while ((p = read_line ()) != (char *)0)
3900     {
3901       /* Skip leading blanks */
3902       while (isspace (*p))
3903         p++;
3904
3905       /* See if it's a directive we handle.  If so, dispatch handler.  */
3906       for (i = 0; i < sizeof (pseudo_ops) / sizeof (pseudo_ops[0]); i++)
3907         if (memcmp (p, pseudo_ops[i].name, pseudo_ops[i].len) == 0
3908             && isspace (p[pseudo_ops[i].len]))
3909           {
3910             p += pseudo_ops[i].len;     /* skip to first argument */
3911             while (isspace (*p))
3912               p++;
3913
3914             (*pseudo_ops[i].func)( p );
3915             break;
3916           }
3917     }
3918
3919   /* Process any tags at global level.  */
3920   ptag_head = cur_tag_head;
3921   cur_tag_head = ptag_head->prev;
3922
3923   for (ptag = ptag_head->first_tag;
3924        ptag != (tag_t *)0;
3925        ptag = ptag_next)
3926     {
3927       if (ptag->forward_ref != (forward_t *)0)
3928         add_unknown_tag (ptag);
3929
3930       ptag_next = ptag->same_block;
3931       ptag->hash_ptr->tag_ptr = ptag->same_name;
3932       free_tag (ptag);
3933     }
3934
3935   free_thead (ptag_head);
3936
3937 }
3938
3939 \f
3940 /* Update the global headers with the final offsets in preparation
3941    to write out the .T file.  */
3942
3943 STATIC void
3944 update_headers __proto((void))
3945 {
3946   register symint_t i;
3947   register efdr_t *file_ptr;
3948
3949   /* Set up the symbolic header.  */
3950   file_offset = sizeof (symbolic_header) + orig_file_header.f_symptr;
3951   symbolic_header.magic = orig_sym_hdr.magic;
3952   symbolic_header.vstamp = orig_sym_hdr.vstamp;
3953
3954   /* Set up global counts.  */
3955   symbolic_header.issExtMax = ext_strings.num_allocated;
3956   symbolic_header.idnMax    = dense_num.num_allocated;
3957   symbolic_header.ifdMax    = file_desc.num_allocated;
3958   symbolic_header.iextMax   = ext_symbols.num_allocated;
3959   symbolic_header.ilineMax  = orig_sym_hdr.ilineMax;
3960   symbolic_header.ioptMax   = orig_sym_hdr.ioptMax;
3961   symbolic_header.cbLine    = orig_sym_hdr.cbLine;
3962   symbolic_header.crfd      = orig_sym_hdr.crfd;
3963
3964
3965   /* Loop through each file, figuring out how many local syms,
3966      line numbers, etc. there are.  Also, put out end symbol
3967      for the filename.  */
3968
3969   for (file_ptr = first_file;
3970        file_ptr != (efdr_t *)0;
3971        file_ptr = file_ptr->next_file)
3972     {
3973       cur_file_ptr = file_ptr;
3974       (void) add_local_symbol ((const char *)0, (const char *)0,
3975                                st_End, sc_Text,
3976                                (symint_t)0,
3977                                (symint_t)0);
3978
3979       file_ptr->fdr.cpd = file_ptr->procs.num_allocated;
3980       file_ptr->fdr.ipdFirst = symbolic_header.ipdMax;
3981       symbolic_header.ipdMax += file_ptr->fdr.cpd;
3982
3983       file_ptr->fdr.csym = file_ptr->symbols.num_allocated;
3984       file_ptr->fdr.isymBase = symbolic_header.isymMax;
3985       symbolic_header.isymMax += file_ptr->fdr.csym;
3986
3987       file_ptr->fdr.caux = file_ptr->aux_syms.num_allocated;
3988       file_ptr->fdr.iauxBase = symbolic_header.iauxMax;
3989       symbolic_header.iauxMax += file_ptr->fdr.caux;
3990
3991       file_ptr->fdr.cbSs = file_ptr->strings.num_allocated;
3992       file_ptr->fdr.issBase = symbolic_header.issMax;
3993       symbolic_header.issMax += file_ptr->fdr.cbSs;
3994     }
3995
3996
3997   i = WORD_ALIGN (symbolic_header.cbLine);      /* line numbers */
3998   if (i > 0)
3999     {
4000       symbolic_header.cbLineOffset = file_offset;
4001       file_offset += i;
4002     }
4003
4004   i = symbolic_header.ioptMax;                  /* optimization symbols */
4005   if (((long) i) > 0)
4006     {
4007       symbolic_header.cbOptOffset = file_offset;
4008       file_offset += i * sizeof (OPTR);
4009     }
4010
4011   i = symbolic_header.idnMax;                   /* dense numbers */
4012   if (i > 0)
4013     {
4014       symbolic_header.cbDnOffset = file_offset;
4015       file_offset += i * sizeof (DNR);
4016     }
4017
4018   i = symbolic_header.ipdMax;                   /* procedure tables */
4019   if (i > 0)
4020     {
4021       symbolic_header.cbPdOffset = file_offset;
4022       file_offset += i * sizeof (PDR);
4023     }
4024
4025   i = symbolic_header.isymMax;                  /* local symbols */
4026   if (i > 0)
4027     {
4028       symbolic_header.cbSymOffset = file_offset;
4029       file_offset += i * sizeof (SYMR);
4030     }
4031
4032   i = symbolic_header.iauxMax;                  /* aux syms. */
4033   if (i > 0)
4034     {
4035       symbolic_header.cbAuxOffset = file_offset;
4036       file_offset += i * sizeof (TIR);
4037     }
4038
4039   i = WORD_ALIGN (symbolic_header.issMax);      /* local strings */
4040   if (i > 0)
4041     {
4042       symbolic_header.cbSsOffset = file_offset;
4043       file_offset += i;
4044     }
4045
4046   i = WORD_ALIGN (symbolic_header.issExtMax);   /* external strings */
4047   if (i > 0)
4048     {
4049       symbolic_header.cbSsExtOffset = file_offset;
4050       file_offset += i;
4051     }
4052
4053   i = symbolic_header.ifdMax;                   /* file tables */
4054   if (i > 0)
4055     {
4056       symbolic_header.cbFdOffset = file_offset;
4057       file_offset += i * sizeof (FDR);
4058     }
4059
4060   i = symbolic_header.crfd;                     /* relative file descriptors */
4061   if (i > 0)
4062     {
4063       symbolic_header.cbRfdOffset = file_offset;
4064       file_offset += i * sizeof (symint_t);
4065     }
4066
4067   i = symbolic_header.iextMax;                  /* external symbols */
4068   if (i > 0)
4069     {
4070       symbolic_header.cbExtOffset = file_offset;
4071       file_offset += i * sizeof (EXTR);
4072     }
4073 }
4074
4075 \f
4076 /* Write out a varray at a given location.  */
4077
4078 STATIC void
4079 write_varray (vp, offset, str)
4080      varray_t *vp;                      /* virtual array */
4081      off_t offset;                      /* offset to write varray to */
4082      const char *str;                   /* string to print out when tracing */
4083 {
4084   int num_write, sys_write;
4085   vlinks_t *ptr;
4086
4087   if (vp->num_allocated == 0)
4088     return;
4089
4090   if (debug)
4091     fprintf (stderr, "\twarray\tvp = 0x%.8x, offset = %7u, size = %7u, %s\n",
4092              vp, offset, vp->num_allocated * vp->object_size, str);
4093
4094   if (file_offset != offset
4095       && fseek (object_stream, (long)offset, SEEK_SET) < 0)
4096     pfatal_with_name (object_name);
4097
4098   for (ptr = vp->first; ptr != (vlinks_t *)0; ptr = ptr->next)
4099     {
4100       num_write = (ptr->next == (vlinks_t *)0)
4101         ? vp->objects_last_page * vp->object_size
4102         : vp->objects_per_page  * vp->object_size;
4103
4104       sys_write = fwrite ((PTR_T) ptr->datum, 1, num_write, object_stream);
4105       if (sys_write <= 0)
4106         pfatal_with_name (object_name);
4107
4108       else if (sys_write != num_write)
4109         fatal ("Wrote %d bytes to %s, system returned %d",
4110                num_write,
4111                object_name,
4112                sys_write);
4113
4114       file_offset += num_write;
4115     }
4116 }
4117
4118 \f
4119 /* Write out the symbol table in the object file.  */
4120
4121 STATIC void
4122 write_object __proto((void))
4123 {
4124   int sys_write;
4125   efdr_t *file_ptr;
4126   off_t offset;
4127
4128   if (debug)
4129     fprintf (stderr, "\n\twrite\tvp = 0x%.8x, offset = %7u, size = %7u, %s\n",
4130              (PTR_T *) &symbolic_header, 0, sizeof (symbolic_header),
4131              "symbolic header");
4132
4133   sys_write = fwrite ((PTR_T) &symbolic_header,
4134                       1,
4135                       sizeof (symbolic_header),
4136                       object_stream);
4137
4138   if (sys_write < 0)
4139     pfatal_with_name (object_name);
4140
4141   else if (sys_write != sizeof (symbolic_header))
4142     fatal ("Wrote %d bytes to %s, system returned %d",
4143            sizeof (symbolic_header),
4144            object_name,
4145            sys_write);
4146
4147
4148   file_offset = sizeof (symbolic_header) + orig_file_header.f_symptr;
4149
4150   if (symbolic_header.cbLine > 0)               /* line numbers */
4151     {
4152       long sys_write;
4153
4154       if (file_offset != symbolic_header.cbLineOffset
4155           && fseek (object_stream, symbolic_header.cbLineOffset, SEEK_SET) != 0)
4156         pfatal_with_name (object_name);
4157
4158       if (debug)
4159         fprintf (stderr, "\twrite\tvp = 0x%.8x, offset = %7u, size = %7u, %s\n",
4160                  (PTR_T *) &orig_linenum, symbolic_header.cbLineOffset,
4161                  symbolic_header.cbLine, "Line numbers");
4162
4163       sys_write = fwrite ((PTR_T) orig_linenum,
4164                           1,
4165                           symbolic_header.cbLine,
4166                           object_stream);
4167
4168       if (sys_write <= 0)
4169         pfatal_with_name (object_name);
4170
4171       else if (sys_write != symbolic_header.cbLine)
4172         fatal ("Wrote %d bytes to %s, system returned %d",
4173                symbolic_header.cbLine,
4174                object_name,
4175                sys_write);
4176
4177       file_offset = symbolic_header.cbLineOffset + symbolic_header.cbLine;
4178     }
4179
4180   if (symbolic_header.ioptMax > 0)              /* optimization symbols */
4181     {
4182       long sys_write;
4183       long num_write = symbolic_header.ioptMax * sizeof (OPTR);
4184
4185       if (file_offset != symbolic_header.cbOptOffset
4186           && fseek (object_stream, symbolic_header.cbOptOffset, SEEK_SET) != 0)
4187         pfatal_with_name (object_name);
4188
4189       if (debug)
4190         fprintf (stderr, "\twrite\tvp = 0x%.8x, offset = %7u, size = %7u, %s\n",
4191                  (PTR_T *) &orig_opt_syms, symbolic_header.cbOptOffset,
4192                  num_write, "Optimizer symbols");
4193
4194       sys_write = fwrite ((PTR_T) orig_opt_syms,
4195                           1,
4196                           num_write,
4197                           object_stream);
4198
4199       if (sys_write <= 0)
4200         pfatal_with_name (object_name);
4201
4202       else if (sys_write != num_write)
4203         fatal ("Wrote %d bytes to %s, system returned %d",
4204                num_write,
4205                object_name,
4206                sys_write);
4207
4208       file_offset = symbolic_header.cbOptOffset + num_write;
4209     }
4210
4211   if (symbolic_header.idnMax > 0)               /* dense numbers */
4212     write_varray (&dense_num, (off_t)symbolic_header.cbDnOffset, "Dense numbers");
4213
4214   if (symbolic_header.ipdMax > 0)               /* procedure tables */
4215     {
4216       offset = symbolic_header.cbPdOffset;
4217       for (file_ptr = first_file;
4218            file_ptr != (efdr_t *)0;
4219            file_ptr = file_ptr->next_file)
4220         {
4221           write_varray (&file_ptr->procs, offset, "Procedure tables");
4222           offset = file_offset;
4223         }
4224     }
4225
4226   if (symbolic_header.isymMax > 0)              /* local symbols */
4227     {
4228       offset = symbolic_header.cbSymOffset;
4229       for (file_ptr = first_file;
4230            file_ptr != (efdr_t *)0;
4231            file_ptr = file_ptr->next_file)
4232         {
4233           write_varray (&file_ptr->symbols, offset, "Local symbols");
4234           offset = file_offset;
4235         }
4236     }
4237
4238   if (symbolic_header.iauxMax > 0)              /* aux symbols */
4239     {
4240       offset = symbolic_header.cbAuxOffset;
4241       for (file_ptr = first_file;
4242            file_ptr != (efdr_t *)0;
4243            file_ptr = file_ptr->next_file)
4244         {
4245           write_varray (&file_ptr->aux_syms, offset, "Aux. symbols");
4246           offset = file_offset;
4247         }
4248     }
4249
4250   if (symbolic_header.issMax > 0)               /* local strings */
4251     {
4252       offset = symbolic_header.cbSsOffset;
4253       for (file_ptr = first_file;
4254            file_ptr != (efdr_t *)0;
4255            file_ptr = file_ptr->next_file)
4256         {
4257           write_varray (&file_ptr->strings, offset, "Local strings");
4258           offset = file_offset;
4259         }
4260     }
4261
4262   if (symbolic_header.issExtMax > 0)            /* external strings */
4263     write_varray (&ext_strings, symbolic_header.cbSsExtOffset, "External strings");
4264
4265   if (symbolic_header.ifdMax > 0)               /* file tables */
4266     {
4267       offset = symbolic_header.cbFdOffset;
4268       if (file_offset != offset
4269           && fseek (object_stream, (long)offset, SEEK_SET) < 0)
4270         pfatal_with_name (object_name);
4271
4272       file_offset = offset;
4273       for (file_ptr = first_file;
4274            file_ptr != (efdr_t *)0;
4275            file_ptr = file_ptr->next_file)
4276         {
4277           if (debug)
4278             fprintf (stderr, "\twrite\tvp = 0x%.8x, offset = %7u, size = %7u, %s\n",
4279                      (PTR_T *) &file_ptr->fdr, file_offset, sizeof (FDR), "File header");
4280
4281           sys_write = fwrite (&file_ptr->fdr,
4282                               1,
4283                               sizeof (FDR),
4284                               object_stream);
4285
4286           if (sys_write < 0)
4287             pfatal_with_name (object_name);
4288
4289           else if (sys_write != sizeof (FDR))
4290             fatal ("Wrote %d bytes to %s, system returned %d",
4291                    sizeof (FDR),
4292                    object_name,
4293                    sys_write);
4294
4295           file_offset = offset += sizeof (FDR);
4296         }
4297     }
4298
4299   if (symbolic_header.crfd > 0)                 /* relative file descriptors */
4300     {
4301       long sys_write;
4302       symint_t num_write = symbolic_header.crfd * sizeof (symint_t);
4303
4304       if (file_offset != symbolic_header.cbRfdOffset
4305           && fseek (object_stream, symbolic_header.cbRfdOffset, SEEK_SET) != 0)
4306         pfatal_with_name (object_name);
4307
4308       if (debug)
4309         fprintf (stderr, "\twrite\tvp = 0x%.8x, offset = %7u, size = %7u, %s\n",
4310                  (PTR_T *) &orig_rfds, symbolic_header.cbRfdOffset,
4311                  num_write, "Relative file descriptors");
4312
4313       sys_write = fwrite (orig_rfds,
4314                           1,
4315                           num_write,
4316                           object_stream);
4317
4318       if (sys_write <= 0)
4319         pfatal_with_name (object_name);
4320
4321       else if (sys_write != num_write)
4322         fatal ("Wrote %d bytes to %s, system returned %d",
4323                num_write,
4324                object_name,
4325                sys_write);
4326
4327       file_offset = symbolic_header.cbRfdOffset + num_write;
4328     }
4329
4330   if (symbolic_header.issExtMax > 0)            /* external symbols */
4331     write_varray (&ext_symbols, (off_t)symbolic_header.cbExtOffset, "External symbols");
4332
4333   if (fclose (object_stream) != 0)
4334     pfatal_with_name (object_name);
4335 }
4336
4337 \f
4338 /* Read some bytes at a specified location, and return a pointer.  */
4339
4340 STATIC page_t *
4341 read_seek (size, offset, str)
4342      Size_t size;               /* # bytes to read */
4343      off_t offset;              /* offset to read at */
4344      const char *str;           /* name for tracing */
4345 {
4346   page_t *ptr;
4347   long sys_read = 0;
4348
4349   if (size == 0)                /* nothing to read */
4350     return (page_t *)0;
4351
4352   if (debug)
4353     fprintf (stderr, "\trseek\tsize = %7u, offset = %7u, currently at %7u, %s\n",
4354              size, offset, file_offset, str);
4355
4356 #ifndef MALLOC_CHECK
4357   ptr = allocate_multiple_pages ((size + PAGE_USIZE - 1) / PAGE_USIZE);
4358 #else
4359   ptr = (page_t *) xcalloc (1, size);
4360 #endif
4361
4362   /* If we need to seek, and the distance is nearby, just do some reads,
4363      to speed things up.  */
4364   if (file_offset != offset)
4365     {
4366       symint_t difference = offset - file_offset;
4367
4368       if (difference < 8)
4369         {
4370           char small_buffer[8];
4371
4372           sys_read = fread (small_buffer, 1, difference, obj_in_stream);
4373           if (sys_read <= 0)
4374             pfatal_with_name (obj_in_name);
4375
4376           if (sys_read != difference)
4377             fatal ("Wanted to read %d bytes from %s, system returned %d",
4378                    size,
4379                    obj_in_name,
4380                    sys_read);
4381         }
4382       else if (fseek (obj_in_stream, offset, SEEK_SET) < 0)
4383         pfatal_with_name (obj_in_name);
4384     }
4385
4386   sys_read = fread ((PTR_T)ptr, 1, size, obj_in_stream);
4387   if (sys_read <= 0)
4388     pfatal_with_name (obj_in_name);
4389
4390   if (sys_read != size)
4391     fatal ("Wanted to read %d bytes from %s, system returned %d",
4392            size,
4393            obj_in_name,
4394            sys_read);
4395
4396   file_offset = offset + size;
4397
4398   if (file_offset > max_file_offset)
4399     max_file_offset = file_offset;
4400
4401   return ptr;
4402 }
4403
4404 \f
4405 /* Read the existing object file (and copy to the output object file
4406    if it is different from the input object file), and remove the old
4407    symbol table.  */
4408
4409 STATIC void
4410 copy_object __proto((void))
4411 {
4412   char buffer[ PAGE_SIZE ];
4413   register int sys_read;
4414   register int remaining;
4415   register int num_write;
4416   register int sys_write;
4417   register int fd, es;
4418   register int delete_ifd = 0;
4419   register int *remap_file_number;
4420   struct stat stat_buf;
4421
4422   if (debug)
4423     fprintf (stderr, "\tcopy\n");
4424
4425   if (fstat (fileno (obj_in_stream), &stat_buf) != 0
4426       || fseek (obj_in_stream, 0L, SEEK_SET) != 0)
4427     pfatal_with_name (obj_in_name);
4428
4429   sys_read = fread ((PTR_T) &orig_file_header,
4430                     1,
4431                     sizeof (struct filehdr),
4432                     obj_in_stream);
4433
4434   if (sys_read < 0)
4435     pfatal_with_name (obj_in_name);
4436
4437   else if (sys_read == 0 && feof (obj_in_stream))
4438     return;                     /* create a .T file sans file header */
4439
4440   else if (sys_read < sizeof (struct filehdr))
4441     fatal ("Wanted to read %d bytes from %s, system returned %d",
4442            sizeof (struct filehdr),
4443            obj_in_name,
4444            sys_read);
4445
4446
4447   if (orig_file_header.f_nsyms != sizeof (HDRR))
4448     fatal ("%s symbolic header wrong size (%d bytes, should be %d)",
4449            input_name, orig_file_header.f_nsyms, sizeof (HDRR));
4450
4451
4452   /* Read in the current symbolic header.  */
4453   if (fseek (obj_in_stream, (long) orig_file_header.f_symptr, SEEK_SET) != 0)
4454     pfatal_with_name (input_name);
4455
4456   sys_read = fread ((PTR_T) &orig_sym_hdr,
4457                     1,
4458                     sizeof (orig_sym_hdr),
4459                     obj_in_stream);
4460
4461   if (sys_read < 0)
4462     pfatal_with_name (object_name);
4463
4464   else if (sys_read < sizeof (struct filehdr))
4465     fatal ("Wanted to read %d bytes from %s, system returned %d",
4466            sizeof (struct filehdr),
4467            obj_in_name,
4468            sys_read);
4469
4470
4471   /* Read in each of the sections if they exist in the object file.
4472      We read things in in the order the mips assembler creates the
4473      sections, so in theory no extra seeks are done.
4474
4475      For simplicity sake, round each read up to a page boundary,
4476      we may want to revisit this later.... */
4477
4478   file_offset =  orig_file_header.f_symptr + sizeof (struct filehdr);
4479
4480   if (orig_sym_hdr.cbLine > 0)                  /* line numbers */
4481     orig_linenum = (char *) read_seek ((Size_t)orig_sym_hdr.cbLine,
4482                                        orig_sym_hdr.cbLineOffset,
4483                                        "Line numbers");
4484
4485   if (orig_sym_hdr.ipdMax > 0)                  /* procedure tables */
4486     orig_procs = (PDR *) read_seek ((Size_t)orig_sym_hdr.ipdMax * sizeof (PDR),
4487                                     orig_sym_hdr.cbPdOffset,
4488                                     "Procedure tables");
4489
4490   if (orig_sym_hdr.isymMax > 0)                 /* local symbols */
4491     orig_local_syms = (SYMR *) read_seek ((Size_t)orig_sym_hdr.isymMax * sizeof (SYMR),
4492                                           orig_sym_hdr.cbSymOffset,
4493                                           "Local symbols");
4494
4495   if (orig_sym_hdr.iauxMax > 0)                 /* aux symbols */
4496     orig_aux_syms = (AUXU *) read_seek ((Size_t)orig_sym_hdr.iauxMax * sizeof (AUXU),
4497                                         orig_sym_hdr.cbAuxOffset,
4498                                         "Aux. symbols");
4499
4500   if (orig_sym_hdr.issMax > 0)                  /* local strings */
4501     orig_local_strs = (char *) read_seek ((Size_t)orig_sym_hdr.issMax,
4502                                           orig_sym_hdr.cbSsOffset,
4503                                           "Local strings");
4504
4505   if (orig_sym_hdr.issExtMax > 0)               /* external strings */
4506     orig_ext_strs = (char *) read_seek ((Size_t)orig_sym_hdr.issExtMax,
4507                                         orig_sym_hdr.cbSsExtOffset,
4508                                         "External strings");
4509
4510   if (orig_sym_hdr.ifdMax > 0)                  /* file tables */
4511     orig_files = (FDR *) read_seek ((Size_t)orig_sym_hdr.ifdMax * sizeof (FDR),
4512                                     orig_sym_hdr.cbFdOffset,
4513                                     "File tables");
4514
4515   if (orig_sym_hdr.crfd > 0)                    /* relative file descriptors */
4516     orig_rfds = (symint_t *) read_seek ((Size_t)orig_sym_hdr.crfd * sizeof (symint_t),
4517                                         orig_sym_hdr.cbRfdOffset,
4518                                         "Relative file descriptors");
4519
4520   if (orig_sym_hdr.issExtMax > 0)               /* external symbols */
4521     orig_ext_syms = (EXTR *) read_seek ((Size_t)orig_sym_hdr.iextMax * sizeof (EXTR),
4522                                         orig_sym_hdr.cbExtOffset,
4523                                         "External symbols");
4524
4525   if (orig_sym_hdr.idnMax > 0)                  /* dense numbers */
4526     {
4527       orig_dense = (DNR *) read_seek ((Size_t)orig_sym_hdr.idnMax * sizeof (DNR),
4528                                       orig_sym_hdr.cbDnOffset,
4529                                       "Dense numbers");
4530
4531       add_bytes (&dense_num, (char *) orig_dense, (Size_t)orig_sym_hdr.idnMax);
4532     }
4533
4534   if (orig_sym_hdr.ioptMax > 0)                 /* opt symbols */
4535     orig_opt_syms = (OPTR *) read_seek ((Size_t)orig_sym_hdr.ioptMax * sizeof (OPTR),
4536                                         orig_sym_hdr.cbOptOffset,
4537                                         "Optimizer symbols");
4538
4539
4540
4541   /* Abort if the symbol table is not last.  */
4542   if (max_file_offset != stat_buf.st_size)
4543     fatal ("Symbol table is not last (symbol table ends at %ld, .o ends at %ld",
4544            max_file_offset,
4545            stat_buf.st_size);
4546
4547
4548   /* If the first original file descriptor is a dummy which the assembler
4549      put out, but there are no symbols in it, skip it now.  */
4550   if (orig_sym_hdr.ifdMax > 1
4551       && orig_files->csym == 2
4552       && orig_files->caux == 0)
4553     {
4554       char *filename = orig_local_strs + (orig_files->issBase + orig_files->rss);
4555       char *suffix = local_rindex (filename, '.');
4556
4557       if (suffix != (char *)0 && strcmp (suffix, ".s") == 0)
4558         delete_ifd = 1;
4559     }
4560
4561
4562   /* Create array to map original file numbers to the new file numbers
4563      (in case there are duplicate filenames, we collapse them into one
4564      file section, the MIPS assembler may or may not collapse them).  */
4565
4566   remap_file_number = (int *) alloca (sizeof (int) * orig_sym_hdr.ifdMax);
4567
4568   for (fd = delete_ifd; fd < orig_sym_hdr.ifdMax; fd++)
4569     {
4570       register FDR *fd_ptr = ORIG_FILES (fd);
4571       register char *filename = ORIG_LSTRS (fd_ptr->issBase + fd_ptr->rss);
4572
4573       /* file support itself.  */
4574       add_file (filename, filename + strlen (filename));
4575       remap_file_number[fd] = cur_file_ptr->file_index;
4576     }
4577
4578   if (delete_ifd > 0)           /* just in case */
4579     remap_file_number[0] = remap_file_number[1];
4580
4581
4582   /* Loop, adding each of the external symbols.  These must be in
4583      order or otherwise we would have to change the relocation
4584      entries.  We don't just call add_bytes, because we need to have
4585      the names put into the external hash table.  We set the type to
4586      'void' for now, and parse_def will fill in the correct type if it
4587      is in the symbol table.  We must add the external symbols before
4588      the locals, since the locals do lookups against the externals.  */
4589
4590   if (debug)
4591     fprintf (stderr, "\tehash\n");
4592
4593   for (es = 0; es < orig_sym_hdr.iextMax; es++)
4594     {
4595       register EXTR *eptr = orig_ext_syms + es;
4596       register char *ename = ORIG_ESTRS (eptr->asym.iss);
4597       register unsigned ifd = eptr->ifd;
4598
4599       (void) add_ext_symbol (ename,
4600                              ename + strlen (ename),
4601                              (st_t) eptr->asym.st,
4602                              (sc_t) eptr->asym.sc,
4603                              eptr->asym.value,
4604                              (symint_t)((eptr->asym.index == indexNil) ? indexNil : 0),
4605                              (ifd < orig_sym_hdr.ifdMax) ? remap_file_number[ ifd ] : ifd);
4606     }
4607
4608
4609   /* For each of the files in the object file, copy the symbols, and such
4610      into the varrays for the new object file.  */
4611
4612   for (fd = delete_ifd; fd < orig_sym_hdr.ifdMax; fd++)
4613     {
4614       register FDR *fd_ptr = ORIG_FILES (fd);
4615       register char *filename = ORIG_LSTRS (fd_ptr->issBase + fd_ptr->rss);
4616       register SYMR *sym_start;
4617       register SYMR *sym;
4618       register SYMR *sym_end_p1;
4619       register PDR *proc_start;
4620       register PDR *proc;
4621       register PDR *proc_end_p1;
4622
4623       /* file support itself.  */
4624       add_file (filename, filename + strlen (filename));
4625       cur_file_ptr->orig_fdr = fd_ptr;
4626
4627       /* Copy stuff that's just passed through (such as line #'s) */
4628       cur_file_ptr->fdr.adr          = fd_ptr->adr;
4629       cur_file_ptr->fdr.ilineBase    = fd_ptr->ilineBase;
4630       cur_file_ptr->fdr.cline        = fd_ptr->cline;
4631       cur_file_ptr->fdr.rfdBase      = fd_ptr->rfdBase;
4632       cur_file_ptr->fdr.crfd         = fd_ptr->crfd;
4633       cur_file_ptr->fdr.cbLineOffset = fd_ptr->cbLineOffset;
4634       cur_file_ptr->fdr.cbLine       = fd_ptr->cbLine;
4635       cur_file_ptr->fdr.fMerge       = fd_ptr->fMerge;
4636       cur_file_ptr->fdr.fReadin      = fd_ptr->fReadin;
4637       cur_file_ptr->fdr.glevel       = fd_ptr->glevel;
4638
4639       if (debug)
4640         fprintf (stderr, "\thash\tstart, filename %s\n", filename);
4641
4642       /* For each of the static and global symbols defined, add them
4643          to the hash table of original symbols, so we can look up
4644          their values.  */
4645
4646       sym_start = ORIG_LSYMS (fd_ptr->isymBase);
4647       sym_end_p1 = sym_start + fd_ptr->csym;
4648       for (sym = sym_start; sym < sym_end_p1; sym++)
4649         {
4650           switch ((st_t) sym->st)
4651             {
4652             default:
4653               break;
4654
4655             case st_Global:
4656             case st_Static:
4657             case st_Label:
4658             case st_Proc:
4659             case st_StaticProc:
4660               {
4661                 auto symint_t hash_index;
4662                 register char *str = ORIG_LSTRS (fd_ptr->issBase + sym->iss);
4663                 register Size_t len = strlen (str);
4664                 register shash_t *shash_ptr = hash_string (str,
4665                                                            (Ptrdiff_t)len,
4666                                                            &orig_str_hash[0],
4667                                                            &hash_index);
4668
4669                 if (shash_ptr != (shash_t *)0)
4670                   error ("internal error, %s is already in original symbol table", str);
4671
4672                 else
4673                   {
4674                     shash_ptr = allocate_shash ();
4675                     shash_ptr->next = orig_str_hash[hash_index];
4676                     orig_str_hash[hash_index] = shash_ptr;
4677
4678                     shash_ptr->len = len;
4679                     shash_ptr->indx = indexNil;
4680                     shash_ptr->string = str;
4681                     shash_ptr->sym_ptr = sym;
4682                   }
4683               }
4684               break;
4685
4686             case st_End:
4687               if ((sc_t) sym->sc == sc_Text)
4688                 {
4689                   register char *str = ORIG_LSTRS (fd_ptr->issBase + sym->iss);
4690
4691                   if (*str != '\0')
4692                     {
4693                       register Size_t len = strlen (str);
4694                       register shash_t *shash_ptr = hash_string (str,
4695                                                                  (Ptrdiff_t)len,
4696                                                                  &orig_str_hash[0],
4697                                                                  (symint_t *)0);
4698
4699                       if (shash_ptr != (shash_t *)0)
4700                         shash_ptr->end_ptr = sym;
4701                     }
4702                 }
4703               break;
4704
4705             }
4706         }
4707
4708       if (debug)
4709         {
4710           fprintf (stderr, "\thash\tdone,  filename %s\n", filename);
4711           fprintf (stderr, "\tproc\tstart, filename %s\n", filename);
4712         }
4713
4714       /* Go through each of the procedures in this file, and add the
4715          procedure pointer to the hash entry for the given name.  */
4716
4717       proc_start = ORIG_PROCS (fd_ptr->ipdFirst);
4718       proc_end_p1 = proc_start + fd_ptr->cpd;
4719       for (proc = proc_start; proc < proc_end_p1; proc++)
4720         {
4721           register SYMR *proc_sym = ORIG_LSYMS (fd_ptr->isymBase + proc->isym);
4722           register char *str = ORIG_LSTRS (fd_ptr->issBase + proc_sym->iss);
4723           register Size_t len = strlen (str);
4724           register shash_t *shash_ptr = hash_string (str,
4725                                                      (Ptrdiff_t)len,
4726                                                      &orig_str_hash[0],
4727                                                      (symint_t *)0);
4728
4729           if (shash_ptr == (shash_t *)0)
4730             error ("internal error, function %s is not in original symbol table", str);
4731
4732           else
4733             shash_ptr->proc_ptr = proc;
4734         }
4735
4736       if (debug)
4737         fprintf (stderr, "\tproc\tdone,  filename %s\n", filename);
4738
4739     }
4740   cur_file_ptr = first_file;
4741
4742
4743   /* Copy all of the object file up to the symbol table.  Originally
4744      we were going to use ftruncate, but that doesn't seem to work
4745      on Ultrix 3.1.... */
4746
4747   if (fseek (obj_in_stream, (long)0, SEEK_SET) != 0)
4748     pfatal_with_name (obj_in_name);
4749
4750   if (fseek (object_stream, (long)0, SEEK_SET) != 0)
4751     pfatal_with_name (object_name);
4752
4753   for (remaining = orig_file_header.f_symptr;
4754        remaining > 0;
4755        remaining -= num_write)
4756     {
4757       num_write = (remaining <= sizeof (buffer)) ? remaining : sizeof (buffer);
4758       sys_read = fread ((PTR_T) buffer, 1, num_write, obj_in_stream);
4759       if (sys_read <= 0)
4760         pfatal_with_name (obj_in_name);
4761
4762       else if (sys_read != num_write)
4763         fatal ("Wanted to read %d bytes from %s, system returned %d",
4764                num_write,
4765                obj_in_name,
4766                sys_read);
4767
4768       sys_write = fwrite (buffer, 1, num_write, object_stream);
4769       if (sys_write <= 0)
4770         pfatal_with_name (object_name);
4771
4772       else if (sys_write != num_write)
4773         fatal ("Wrote %d bytes to %s, system returned %d",
4774                num_write,
4775                object_name,
4776                sys_write);
4777     }
4778 }
4779
4780 \f
4781 /* Ye olde main program.  */
4782
4783 int
4784 main (argc, argv)
4785      int argc;
4786      char *argv[];
4787 {
4788   int iflag = 0;
4789   char *p = local_rindex (argv[0], '/');
4790   char *num_end;
4791   int option;
4792   int i;
4793
4794   progname = (p != 0) ? p+1 : argv[0];
4795
4796   (void) signal (SIGSEGV, catch_signal);
4797   (void) signal (SIGBUS,  catch_signal);
4798   (void) signal (SIGABRT, catch_signal);
4799
4800 #if !defined(__SABER__) && !defined(lint)
4801   if (sizeof (efdr_t) > PAGE_USIZE)
4802     fatal ("Efdr_t has a sizeof %d bytes, when it should be less than %d",
4803            sizeof (efdr_t),
4804            PAGE_USIZE);
4805
4806   if (sizeof (page_t) != PAGE_USIZE)
4807     fatal ("Page_t has a sizeof %d bytes, when it should be %d",
4808            sizeof (page_t),
4809            PAGE_USIZE);
4810
4811 #endif
4812
4813   alloc_counts[ alloc_type_none    ].alloc_name = "none";
4814   alloc_counts[ alloc_type_scope   ].alloc_name = "scope";
4815   alloc_counts[ alloc_type_vlinks  ].alloc_name = "vlinks";
4816   alloc_counts[ alloc_type_shash   ].alloc_name = "shash";
4817   alloc_counts[ alloc_type_thash   ].alloc_name = "thash";
4818   alloc_counts[ alloc_type_tag     ].alloc_name = "tag";
4819   alloc_counts[ alloc_type_forward ].alloc_name = "forward";
4820   alloc_counts[ alloc_type_thead   ].alloc_name = "thead";
4821   alloc_counts[ alloc_type_varray  ].alloc_name = "varray";
4822
4823   int_type_info  = type_info_init;
4824   int_type_info.basic_type = bt_Int;
4825
4826   void_type_info = type_info_init;
4827   void_type_info.basic_type = bt_Void;
4828
4829   while ((option = getopt (argc, argv, "d:i:I:o:v")) != EOF)
4830     switch (option)
4831       {
4832       default:
4833         had_errors++;
4834         break;
4835
4836       case 'd':
4837         debug = strtol (optarg, &num_end, 0);
4838         if ((unsigned)debug > 4 || num_end == optarg)
4839           had_errors++;
4840
4841         break;
4842
4843       case 'I':
4844         if (rename_output || obj_in_name != (char *)0)
4845           had_errors++;
4846         else
4847           rename_output = 1;
4848
4849         /* fall through to 'i' case.  */
4850
4851       case 'i':
4852         if (obj_in_name == (char *)0)
4853           {
4854             obj_in_name = optarg;
4855             iflag++;
4856           }
4857         else
4858           had_errors++;
4859         break;
4860
4861       case 'o':
4862         if (object_name == (char *)0)
4863           object_name = optarg;
4864         else
4865           had_errors++;
4866         break;
4867
4868       case 'v':
4869         version++;
4870         break;
4871       }
4872
4873   if (obj_in_name == (char *)0 && optind <= argc - 2)
4874     obj_in_name = argv[--argc];
4875
4876   if (object_name == (char *)0 && optind <= argc - 2)
4877     object_name = argv[--argc];
4878
4879   /* If there is an output name, but no input name use
4880      the same file for both, deleting the name between
4881      opening it for input and opening it for output.  */
4882   if (obj_in_name == (char *)0 && object_name != (char *)0)
4883     {
4884       obj_in_name = object_name;
4885       delete_input = 1;
4886     }
4887
4888   if (object_name == (char *)0 || had_errors || optind != argc - 1)
4889     {
4890       fprintf (stderr, "Calling Sequence:\n");
4891       fprintf (stderr, "\tmips-tfile [-d <num>] [-v] [-i <o-in-file>] -o <o-out-file> <s-file> (or)\n");
4892       fprintf (stderr, "\tmips-tfile [-d <num>] [-v] [-I <o-in-file>] -o <o-out-file> <s-file> (or)\n");
4893       fprintf (stderr, "\tmips-tfile [-d <num>] [-v] <s-file> <o-in-file> <o-out-file>\n");
4894       fprintf (stderr, "\n");
4895       fprintf (stderr, "Debug levels are:\n");
4896       fprintf (stderr, "    1\tGeneral debug + trace functions/blocks.\n");
4897       fprintf (stderr, "    2\tDebug level 1 + trace externals.\n");
4898       fprintf (stderr, "    3\tDebug level 2 + trace all symbols.\n");
4899       fprintf (stderr, "    4\tDebug level 3 + trace memory allocations.\n");
4900       return 1;
4901     }
4902
4903
4904   if (version)
4905     {
4906       fprintf (stderr, "mips-tfile version %s", version_string);
4907 #ifdef TARGET_VERSION
4908       TARGET_VERSION;
4909 #endif
4910       fputc ('\n', stderr);
4911     }
4912
4913   if (obj_in_name == (char *)0)
4914     obj_in_name = object_name;
4915
4916   if (rename_output && rename (object_name, obj_in_name) != 0)
4917     {
4918       char *buffer = (char *) allocate_multiple_pages (4);
4919       int len;
4920       int len2;
4921       int in_fd;
4922       int out_fd;
4923
4924       /* Rename failed, copy input file */
4925       in_fd = open (object_name, O_RDONLY, 0666);
4926       if (in_fd < 0)
4927         pfatal_with_name (object_name);
4928
4929       out_fd = open (obj_in_name, O_WRONLY | O_CREAT | O_TRUNC, 0666);
4930       if (out_fd < 0)
4931         pfatal_with_name (obj_in_name);
4932
4933       while ((len = read (in_fd, buffer, 4*PAGE_SIZE)) > 0)
4934         {
4935           len2 = write (out_fd, buffer, len);
4936           if (len2 < 0)
4937             pfatal_with_name (object_name);
4938
4939           if (len != len2)
4940             fatal ("wrote %d bytes to %s, expected to write %d", len2, obj_in_name, len);
4941         }
4942
4943       free_multiple_pages ((page_t *)buffer, 4);
4944
4945       if (len < 0)
4946         pfatal_with_name (object_name);
4947
4948       if (close (in_fd) < 0)
4949         pfatal_with_name (object_name);
4950
4951       if (close (out_fd) < 0)
4952         pfatal_with_name (obj_in_name);
4953     }
4954
4955   /* Must open input before output, since the output may be the same file, and
4956      we need to get the input handle before truncating it.  */
4957   obj_in_stream = fopen (obj_in_name, "r");
4958   if (obj_in_stream == (FILE *)0)
4959     pfatal_with_name (obj_in_name);
4960
4961   if (delete_input && unlink (obj_in_name) != 0)
4962     pfatal_with_name (obj_in_name);
4963
4964   object_stream = fopen (object_name, "w");
4965   if (object_stream == (FILE *)0)
4966     pfatal_with_name (object_name);
4967
4968   if (strcmp (argv[optind], "-") != 0)
4969     {
4970       input_name = argv[optind];
4971       if (freopen (argv[optind], "r", stdin) != stdin)
4972         pfatal_with_name (argv[optind]);
4973     }
4974
4975   copy_object ();                       /* scan & copy object file */
4976   parse_input ();                       /* scan all of input */
4977
4978   update_headers ();                    /* write out tfile */
4979   write_object ();
4980
4981   if (debug)
4982     {
4983       fprintf (stderr, "\n\tAllocation summary:\n\n");
4984       for (i = (int)alloc_type_none; i < (int)alloc_type_last; i++)
4985         if (alloc_counts[i].total_alloc)
4986           {
4987             fprintf (stderr,
4988                      "\t%s\t%5d allocation(s), %5d free(s), %2d page(s)\n",
4989                      alloc_counts[i].alloc_name,
4990                      alloc_counts[i].total_alloc,
4991                      alloc_counts[i].total_free,
4992                      alloc_counts[i].total_pages);
4993           }
4994     }
4995
4996   return (had_errors) ? 1 : 0;
4997 }
4998
4999 \f
5000 /* Catch a signal and exit without dumping core.  */
5001
5002 STATIC void
5003 catch_signal (signum)
5004      int signum;
5005 {
5006   (void) signal (signum, SIG_DFL);      /* just in case... */
5007 #ifdef NO_SYS_SIGLIST
5008   fatal ("caught signal");
5009 #else
5010   fatal (sys_siglist[signum]);
5011 #endif  
5012 }
5013
5014 /* Print a fatal error message.  NAME is the text.
5015    Also include a system error message based on `errno'.  */
5016
5017 void
5018 pfatal_with_name (msg)
5019      char *msg;
5020 {
5021   int save_errno = errno;               /* just in case.... */
5022   if (line_number > 0)
5023     fprintf (stderr, "%s, %s:%ld ", progname, input_name, line_number);
5024   else
5025     fprintf (stderr, "%s:", progname);
5026
5027   errno = save_errno;
5028   if (errno == 0)
5029     fprintf (stderr, "[errno = 0] %s\n", msg);
5030   else
5031     perror (msg);
5032
5033   exit (1);
5034 }
5035
5036 \f
5037 /* Procedure to abort with an out of bounds error message.  It has
5038    type int, so it can be used with an ?: expression within the
5039    ORIG_xxx macros, but the function never returns.  */
5040
5041 static int
5042 out_of_bounds (indx, max, str, prog_line)
5043      symint_t indx;             /* index that is out of bounds */
5044      symint_t max;              /* maximum index */
5045      const char *str;           /* string to print out */
5046      int prog_line;             /* line number within mips-tfile.c */
5047 {
5048   if (indx < max)               /* just in case */
5049     return 0;
5050
5051   fprintf (stderr, "%s, %s:%ld index %u is out of bounds for %s, max is %u, mips-tfile.c line# %d\n",
5052            progname, input_name, line_number, indx, str, max, prog_line);
5053
5054   exit (1);
5055   return 0;                     /* turn off warning messages */
5056 }
5057
5058 \f
5059 /* Allocate a cluster of pages.  USE_MALLOC says that malloc does not
5060    like sbrk's behind it's back (or sbrk isn't available).  If we use
5061    sbrk, we assume it gives us zeroed pages.  */
5062
5063 #ifndef MALLOC_CHECK
5064 #ifdef USE_MALLOC
5065
5066 STATIC page_t *
5067 allocate_cluster (npages)
5068      Size_t npages;
5069 {
5070   register page_t *value = (page_t *) calloc (npages, PAGE_USIZE);
5071
5072   if (value == 0)
5073     fatal ("Virtual memory exhausted.");
5074
5075   if (debug > 3)
5076     fprintf (stderr, "\talloc\tnpages = %d, value = 0x%.8x\n", npages, value);
5077
5078   return value;
5079 }
5080
5081 #else /* USE_MALLOC */
5082
5083 STATIC page_t *
5084 allocate_cluster (npages)
5085      Size_t npages;
5086 {
5087   register page_t *ptr = (page_t *) sbrk (0);   /* current sbreak */
5088   unsigned long offset = ((unsigned long) ptr) & (PAGE_SIZE - 1);
5089
5090   if (offset != 0)                      /* align to a page boundary */
5091     {
5092       if (sbrk (PAGE_USIZE - offset) == (char *)-1)
5093         pfatal_with_name ("allocate_cluster");
5094
5095       ptr = (page_t *) (((char *)ptr) + PAGE_SIZE - offset);
5096     }
5097
5098   if (sbrk (npages * PAGE_USIZE) == (char *)-1)
5099     pfatal_with_name ("allocate_cluster");
5100
5101   if (debug > 3)
5102     fprintf (stderr, "\talloc\tnpages = %d, value = 0x%.8x\n", npages, ptr);
5103
5104   return ptr;
5105 }
5106
5107 #endif /* USE_MALLOC */
5108
5109
5110 static page_t   *cluster_ptr    = NULL;
5111 static unsigned  pages_left     = 0;
5112
5113 #endif /* MALLOC_CHECK */
5114
5115
5116 /* Allocate some pages (which is initialized to 0).  */
5117
5118 STATIC page_t *
5119 allocate_multiple_pages (npages)
5120      Size_t npages;
5121 {
5122 #ifndef MALLOC_CHECK
5123   if (pages_left == 0 && npages < MAX_CLUSTER_PAGES)
5124     {
5125       pages_left = MAX_CLUSTER_PAGES;
5126       cluster_ptr = allocate_cluster (MAX_CLUSTER_PAGES);
5127     }
5128
5129   if (npages <= pages_left)
5130     {
5131       page_t *ptr = cluster_ptr;
5132       cluster_ptr += npages;
5133       pages_left -= npages;
5134       return ptr;
5135     }
5136
5137   return allocate_cluster (npages);
5138
5139 #else   /* MALLOC_CHECK */
5140   return (page_t *) xcalloc (npages, PAGE_SIZE);
5141
5142 #endif  /* MALLOC_CHECK */
5143 }
5144
5145
5146 /* Release some pages.  */
5147
5148 STATIC void
5149 free_multiple_pages (page_ptr, npages)
5150      page_t *page_ptr;
5151      Size_t npages;
5152 {
5153 #ifndef MALLOC_CHECK
5154   if (pages_left == 0)
5155     {
5156       cluster_ptr = page_ptr;
5157       pages_left = npages;
5158     }
5159
5160   else if ((page_ptr + npages) == cluster_ptr)
5161     {
5162       cluster_ptr -= npages;
5163       pages_left += npages;
5164     }
5165
5166   /* otherwise the page is not freed.  If more than call is
5167      done, we probably should worry about it, but at present,
5168      the free pages is done right after an allocate.  */
5169
5170 #else   /* MALLOC_CHECK */
5171   free ((char *) page_ptr);
5172
5173 #endif  /* MALLOC_CHECK */
5174 }
5175
5176
5177 /* Allocate one page (which is initialized to 0).  */
5178
5179 STATIC page_t *
5180 allocate_page __proto((void))
5181 {
5182 #ifndef MALLOC_CHECK
5183   if (pages_left == 0)
5184     {
5185       pages_left = MAX_CLUSTER_PAGES;
5186       cluster_ptr = allocate_cluster (MAX_CLUSTER_PAGES);
5187     }
5188
5189   pages_left--;
5190   return cluster_ptr++;
5191
5192 #else   /* MALLOC_CHECK */
5193   return (page_t *) xcalloc (1, PAGE_SIZE);
5194
5195 #endif  /* MALLOC_CHECK */
5196 }
5197
5198 \f
5199 /* Allocate scoping information.  */
5200
5201 STATIC scope_t *
5202 allocate_scope __proto((void))
5203 {
5204   register scope_t *ptr;
5205   static scope_t initial_scope;
5206
5207 #ifndef MALLOC_CHECK
5208   ptr = alloc_counts[ (int)alloc_type_scope ].free_list.f_scope;
5209   if (ptr != (scope_t *)0)
5210     alloc_counts[ (int)alloc_type_scope ].free_list.f_scope = ptr->free;
5211
5212   else
5213     {
5214       register int unallocated  = alloc_counts[ (int)alloc_type_scope ].unallocated;
5215       register page_t *cur_page = alloc_counts[ (int)alloc_type_scope ].cur_page;
5216
5217       if (unallocated == 0)
5218         {
5219           unallocated = PAGE_SIZE / sizeof (scope_t);
5220           alloc_counts[ (int)alloc_type_scope ].cur_page = cur_page = allocate_page ();
5221           alloc_counts[ (int)alloc_type_scope ].total_pages++;
5222         }
5223
5224       ptr = &cur_page->scope[ --unallocated ];
5225       alloc_counts[ (int)alloc_type_scope ].unallocated = unallocated;
5226     }
5227
5228 #else
5229   ptr = (scope_t *) xmalloc (sizeof (scope_t));
5230
5231 #endif
5232
5233   alloc_counts[ (int)alloc_type_scope ].total_alloc++;
5234   *ptr = initial_scope;
5235   return ptr;
5236 }
5237
5238 /* Free scoping information.  */
5239
5240 STATIC void
5241 free_scope (ptr)
5242      scope_t *ptr;
5243 {
5244   alloc_counts[ (int)alloc_type_scope ].total_free++;
5245
5246 #ifndef MALLOC_CHECK
5247   ptr->free = alloc_counts[ (int)alloc_type_scope ].free_list.f_scope;
5248   alloc_counts[ (int)alloc_type_scope ].free_list.f_scope = ptr;
5249
5250 #else
5251   xfree ((PTR_T) ptr);
5252 #endif
5253
5254 }
5255
5256 \f
5257 /* Allocate links for pages in a virtual array.  */
5258
5259 STATIC vlinks_t *
5260 allocate_vlinks __proto((void))
5261 {
5262   register vlinks_t *ptr;
5263   static vlinks_t initial_vlinks;
5264
5265 #ifndef MALLOC_CHECK
5266   register int unallocated      = alloc_counts[ (int)alloc_type_vlinks ].unallocated;
5267   register page_t *cur_page     = alloc_counts[ (int)alloc_type_vlinks ].cur_page;
5268
5269   if (unallocated == 0)
5270     {
5271       unallocated = PAGE_SIZE / sizeof (vlinks_t);
5272       alloc_counts[ (int)alloc_type_vlinks ].cur_page = cur_page = allocate_page ();
5273       alloc_counts[ (int)alloc_type_vlinks ].total_pages++;
5274     }
5275
5276   ptr = &cur_page->vlinks[ --unallocated ];
5277   alloc_counts[ (int)alloc_type_vlinks ].unallocated = unallocated;
5278
5279 #else
5280   ptr = (vlinks_t *) xmalloc (sizeof (vlinks_t));
5281
5282 #endif
5283
5284   alloc_counts[ (int)alloc_type_vlinks ].total_alloc++;
5285   *ptr = initial_vlinks;
5286   return ptr;
5287 }
5288
5289 \f
5290 /* Allocate string hash buckets.  */
5291
5292 STATIC shash_t *
5293 allocate_shash __proto((void))
5294 {
5295   register shash_t *ptr;
5296   static shash_t initial_shash;
5297
5298 #ifndef MALLOC_CHECK
5299   register int unallocated      = alloc_counts[ (int)alloc_type_shash ].unallocated;
5300   register page_t *cur_page     = alloc_counts[ (int)alloc_type_shash ].cur_page;
5301
5302   if (unallocated == 0)
5303     {
5304       unallocated = PAGE_SIZE / sizeof (shash_t);
5305       alloc_counts[ (int)alloc_type_shash ].cur_page = cur_page = allocate_page ();
5306       alloc_counts[ (int)alloc_type_shash ].total_pages++;
5307     }
5308
5309   ptr = &cur_page->shash[ --unallocated ];
5310   alloc_counts[ (int)alloc_type_shash ].unallocated = unallocated;
5311
5312 #else
5313   ptr = (shash_t *) xmalloc (sizeof (shash_t));
5314
5315 #endif
5316
5317   alloc_counts[ (int)alloc_type_shash ].total_alloc++;
5318   *ptr = initial_shash;
5319   return ptr;
5320 }
5321
5322 \f
5323 /* Allocate type hash buckets.  */
5324
5325 STATIC thash_t *
5326 allocate_thash __proto((void))
5327 {
5328   register thash_t *ptr;
5329   static thash_t initial_thash;
5330
5331 #ifndef MALLOC_CHECK
5332   register int unallocated      = alloc_counts[ (int)alloc_type_thash ].unallocated;
5333   register page_t *cur_page     = alloc_counts[ (int)alloc_type_thash ].cur_page;
5334
5335   if (unallocated == 0)
5336     {
5337       unallocated = PAGE_SIZE / sizeof (thash_t);
5338       alloc_counts[ (int)alloc_type_thash ].cur_page = cur_page = allocate_page ();
5339       alloc_counts[ (int)alloc_type_thash ].total_pages++;
5340     }
5341
5342   ptr = &cur_page->thash[ --unallocated ];
5343   alloc_counts[ (int)alloc_type_thash ].unallocated = unallocated;
5344
5345 #else
5346   ptr = (thash_t *) xmalloc (sizeof (thash_t));
5347
5348 #endif
5349
5350   alloc_counts[ (int)alloc_type_thash ].total_alloc++;
5351   *ptr = initial_thash;
5352   return ptr;
5353 }
5354
5355 \f
5356 /* Allocate structure, union, or enum tag information.  */
5357
5358 STATIC tag_t *
5359 allocate_tag __proto((void))
5360 {
5361   register tag_t *ptr;
5362   static tag_t initial_tag;
5363
5364 #ifndef MALLOC_CHECK
5365   ptr = alloc_counts[ (int)alloc_type_tag ].free_list.f_tag;
5366   if (ptr != (tag_t *)0)
5367     alloc_counts[ (int)alloc_type_tag ].free_list.f_tag = ptr->free;
5368
5369   else
5370     {
5371       register int unallocated  = alloc_counts[ (int)alloc_type_tag ].unallocated;
5372       register page_t *cur_page = alloc_counts[ (int)alloc_type_tag ].cur_page;
5373
5374       if (unallocated == 0)
5375         {
5376           unallocated = PAGE_SIZE / sizeof (tag_t);
5377           alloc_counts[ (int)alloc_type_tag ].cur_page = cur_page = allocate_page ();
5378           alloc_counts[ (int)alloc_type_tag ].total_pages++;
5379         }
5380
5381       ptr = &cur_page->tag[ --unallocated ];
5382       alloc_counts[ (int)alloc_type_tag ].unallocated = unallocated;
5383     }
5384
5385 #else
5386   ptr = (tag_t *) xmalloc (sizeof (tag_t));
5387
5388 #endif
5389
5390   alloc_counts[ (int)alloc_type_tag ].total_alloc++;
5391   *ptr = initial_tag;
5392   return ptr;
5393 }
5394
5395 /* Free scoping information.  */
5396
5397 STATIC void
5398 free_tag (ptr)
5399      tag_t *ptr;
5400 {
5401   alloc_counts[ (int)alloc_type_tag ].total_free++;
5402
5403 #ifndef MALLOC_CHECK
5404   ptr->free = alloc_counts[ (int)alloc_type_tag ].free_list.f_tag;
5405   alloc_counts[ (int)alloc_type_tag ].free_list.f_tag = ptr;
5406
5407 #else
5408   xfree ((PTR_T) ptr);
5409 #endif
5410
5411 }
5412
5413 \f
5414 /* Allocate forward reference to a yet unknown tag.  */
5415
5416 STATIC forward_t *
5417 allocate_forward __proto((void))
5418 {
5419   register forward_t *ptr;
5420   static forward_t initial_forward;
5421
5422 #ifndef MALLOC_CHECK
5423   ptr = alloc_counts[ (int)alloc_type_forward ].free_list.f_forward;
5424   if (ptr != (forward_t *)0)
5425     alloc_counts[ (int)alloc_type_forward ].free_list.f_forward = ptr->free;
5426
5427   else
5428     {
5429       register int unallocated  = alloc_counts[ (int)alloc_type_forward ].unallocated;
5430       register page_t *cur_page = alloc_counts[ (int)alloc_type_forward ].cur_page;
5431
5432       if (unallocated == 0)
5433         {
5434           unallocated = PAGE_SIZE / sizeof (forward_t);
5435           alloc_counts[ (int)alloc_type_forward ].cur_page = cur_page = allocate_page ();
5436           alloc_counts[ (int)alloc_type_forward ].total_pages++;
5437         }
5438
5439       ptr = &cur_page->forward[ --unallocated ];
5440       alloc_counts[ (int)alloc_type_forward ].unallocated = unallocated;
5441     }
5442
5443 #else
5444   ptr = (forward_t *) xmalloc (sizeof (forward_t));
5445
5446 #endif
5447
5448   alloc_counts[ (int)alloc_type_forward ].total_alloc++;
5449   *ptr = initial_forward;
5450   return ptr;
5451 }
5452
5453 /* Free scoping information.  */
5454
5455 STATIC void
5456 free_forward (ptr)
5457      forward_t *ptr;
5458 {
5459   alloc_counts[ (int)alloc_type_forward ].total_free++;
5460
5461 #ifndef MALLOC_CHECK
5462   ptr->free = alloc_counts[ (int)alloc_type_forward ].free_list.f_forward;
5463   alloc_counts[ (int)alloc_type_forward ].free_list.f_forward = ptr;
5464
5465 #else
5466   xfree ((PTR_T) ptr);
5467 #endif
5468
5469 }
5470
5471 \f
5472 /* Allocate head of type hash list.  */
5473
5474 STATIC thead_t *
5475 allocate_thead __proto((void))
5476 {
5477   register thead_t *ptr;
5478   static thead_t initial_thead;
5479
5480 #ifndef MALLOC_CHECK
5481   ptr = alloc_counts[ (int)alloc_type_thead ].free_list.f_thead;
5482   if (ptr != (thead_t *)0)
5483     alloc_counts[ (int)alloc_type_thead ].free_list.f_thead = ptr->free;
5484
5485   else
5486     {
5487       register int unallocated  = alloc_counts[ (int)alloc_type_thead ].unallocated;
5488       register page_t *cur_page = alloc_counts[ (int)alloc_type_thead ].cur_page;
5489
5490       if (unallocated == 0)
5491         {
5492           unallocated = PAGE_SIZE / sizeof (thead_t);
5493           alloc_counts[ (int)alloc_type_thead ].cur_page = cur_page = allocate_page ();
5494           alloc_counts[ (int)alloc_type_thead ].total_pages++;
5495         }
5496
5497       ptr = &cur_page->thead[ --unallocated ];
5498       alloc_counts[ (int)alloc_type_thead ].unallocated = unallocated;
5499     }
5500
5501 #else
5502   ptr = (thead_t *) xmalloc (sizeof (thead_t));
5503
5504 #endif
5505
5506   alloc_counts[ (int)alloc_type_thead ].total_alloc++;
5507   *ptr = initial_thead;
5508   return ptr;
5509 }
5510
5511 /* Free scoping information.  */
5512
5513 STATIC void
5514 free_thead (ptr)
5515      thead_t *ptr;
5516 {
5517   alloc_counts[ (int)alloc_type_thead ].total_free++;
5518
5519 #ifndef MALLOC_CHECK
5520   ptr->free = (thead_t *) alloc_counts[ (int)alloc_type_thead ].free_list.f_thead;
5521   alloc_counts[ (int)alloc_type_thead ].free_list.f_thead = ptr;
5522
5523 #else
5524   xfree ((PTR_T) ptr);
5525 #endif
5526
5527 }
5528
5529 #endif /* MIPS_DEBUGGING_INFO */
5530
5531 \f
5532 /* Output an error message and exit */
5533
5534 /*VARARGS*/
5535 void
5536 fatal (va_alist)
5537      va_dcl
5538 {
5539   va_list ap;
5540   char *format;
5541
5542   if (line_number > 0)
5543     fprintf (stderr, "%s, %s:%ld ", progname, input_name, line_number);
5544   else
5545     fprintf (stderr, "%s:", progname);
5546
5547   va_start(ap);
5548   format = va_arg (ap, char *);
5549   vfprintf (stderr, format, ap);
5550   va_end (ap);
5551   fprintf (stderr, "\n");
5552   if (line_number > 0)
5553     fprintf (stderr, "line:\t%s\n", cur_line_start);
5554
5555   saber_stop ();
5556   exit (1);
5557 }
5558
5559 /*VARARGS*/
5560 void
5561 error (va_alist) 
5562      va_dcl
5563 {
5564   va_list ap;
5565   char *format;
5566
5567   if (line_number > 0)
5568     fprintf (stderr, "%s, %s:%ld ", progname, input_name, line_number);
5569   else
5570     fprintf (stderr, "%s:", progname);
5571
5572   va_start(ap);
5573   format = va_arg (ap, char *);
5574   vfprintf (stderr, format, ap);
5575   fprintf (stderr, "\n");
5576   if (line_number > 0)
5577     fprintf (stderr, "line:\t%s\n", cur_line_start);
5578
5579   had_errors++;
5580   va_end (ap);
5581
5582   saber_stop ();
5583 }
5584
5585 /* More 'friendly' abort that prints the line and file.
5586    config.h can #define abort fancy_abort if you like that sort of thing.  */
5587
5588 void
5589 fancy_abort ()
5590 {
5591   fatal ("Internal abort.");
5592 }
5593 \f
5594
5595 /* When `malloc.c' is compiled with `rcheck' defined,
5596    it calls this function to report clobberage.  */
5597
5598 void
5599 botch (s)
5600      const char *s;
5601 {
5602   fatal (s);
5603 }
5604
5605 /* Same as `malloc' but report error if no memory available.  */
5606
5607 PTR_T
5608 xmalloc (size)
5609      Size_t size;
5610 {
5611   register PTR_T value = malloc (size);
5612   if (value == 0)
5613     fatal ("Virtual memory exhausted.");
5614
5615   if (debug > 3)
5616     fprintf (stderr, "\tmalloc\tptr = 0x%.8x, size = %10u\n", value, size);
5617
5618   return value;
5619 }
5620
5621 /* Same as `calloc' but report error if no memory available.  */
5622
5623 PTR_T
5624 xcalloc (size1, size2)
5625      Size_t size1, size2;
5626 {
5627   register PTR_T value = calloc (size1, size2);
5628   if (value == 0)
5629     fatal ("Virtual memory exhausted.");
5630
5631   if (debug > 3)
5632     fprintf (stderr, "\tcalloc\tptr = 0x%.8x, size1 = %10u, size2 = %10u [%u]\n",
5633              value, size1, size2, size1+size2);
5634
5635   return value;
5636 }
5637
5638 /* Same as `realloc' but report error if no memory available.  */
5639
5640 PTR_T
5641 xrealloc (ptr, size)
5642      PTR_T ptr;
5643      Size_t size;
5644 {
5645   register PTR_T result = realloc (ptr, size);
5646   if (!result)
5647     fatal ("Virtual memory exhausted.");
5648
5649   if (debug > 3)
5650     fprintf (stderr, "\trealloc\tptr = 0x%.8x, size = %10u, orig = 0x%.8x\n",
5651              result, size, ptr);
5652
5653   return result;
5654 }
5655
5656 void
5657 xfree (ptr)
5658      PTR_T ptr;
5659 {
5660   if (debug > 3)
5661     fprintf (stderr, "\tfree\tptr = 0x%.8x\n", ptr);
5662
5663   free (ptr);
5664 }
5665
5666 \f
5667 /* Define our own index/rindex, since the local and global symbol
5668    structures as defined by MIPS has an 'index' field.  */
5669
5670 STATIC char *
5671 local_index (str, sentinel)
5672      const char *str;
5673      int sentinel;
5674 {
5675   int ch;
5676
5677   for ( ; (ch = *str) != sentinel; str++)
5678     {
5679       if (ch == '\0')
5680         return (char *)0;
5681     }
5682
5683   return (char *)str;
5684 }
5685
5686 STATIC char *
5687 local_rindex (str, sentinel)
5688      const char *str;
5689      int sentinel;
5690 {
5691   int ch;
5692   const char *ret = (const char *)0;
5693
5694   for ( ; (ch = *str) != '\0'; str++)
5695     {
5696       if (ch == sentinel)
5697         ret = str;
5698     }
5699
5700   return (char *)ret;
5701 }