OSDN Git Service

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