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