OSDN Git Service

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