PR rtl-optimization/49095
[official-gcc.git] / gcc / mips-tfile.c
blob3af6266b45c1da5c8140722f054b083a57fb2fb2
1 /* Update the symbol table (the .T file) in a ECOFF 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 Copyright (C) 1991, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
6 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
7 Free Software Foundation, Inc.
8 Contributed by Michael Meissner (meissner@cygnus.com).
10 This file is part of GCC.
12 GCC is free software; you can redistribute it and/or modify it under
13 the terms of the GNU General Public License as published by the Free
14 Software Foundation; either version 3, or (at your option) any later
15 version.
17 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
18 WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 for more details.
22 You should have received a copy of the GNU General Public License
23 along with GCC; see the file COPYING3. If not see
24 <http://www.gnu.org/licenses/>. */
27 /* Here is a brief description of the MIPS ECOFF symbol table. The
28 MIPS symbol table has the following pieces:
30 Symbolic Header
32 +-- Auxiliary Symbols
34 +-- Dense number table
36 +-- Optimizer Symbols
38 +-- External Strings
40 +-- External Symbols
42 +-- Relative file descriptors
44 +-- File table
46 +-- Procedure table
48 +-- Line number table
50 +-- Local Strings
52 +-- Local Symbols
54 The symbolic header points to each of the other tables, and also
55 contains the number of entries. It also contains a magic number
56 and MIPS compiler version number, such as 2.0.
58 The auxiliary table is a series of 32 bit integers, that are
59 referenced as needed from the local symbol table. Unlike standard
60 COFF, the aux. information does not follow the symbol that uses
61 it, but rather is a separate table. In theory, this would allow
62 the MIPS compilers to collapse duplicate aux. entries, but I've not
63 noticed this happening with the 1.31 compiler suite. The different
64 types of aux. entries are:
66 1) dnLow: Low bound on array dimension.
68 2) dnHigh: High bound on array dimension.
70 3) isym: Index to the local symbol which is the start of the
71 function for the end of function first aux. entry.
73 4) width: Width of structures and bitfields.
75 5) count: Count of ranges for variant part.
77 6) rndx: A relative index into the symbol table. The relative
78 index field has two parts: rfd which is a pointer into the
79 relative file index table or ST_RFDESCAPE which says the next
80 aux. entry is the file number, and index: which is the pointer
81 into the local symbol within a given file table. This is for
82 things like references to types defined in another file.
84 7) Type information: This is like the COFF type bits, except it
85 is 32 bits instead of 16; they still have room to add new
86 basic types; and they can handle more than 6 levels of array,
87 pointer, function, etc. Each type information field contains
88 the following structure members:
90 a) fBitfield: a bit that says this is a bitfield, and the
91 size in bits follows as the next aux. entry.
93 b) continued: a bit that says the next aux. entry is a
94 continuation of the current type information (in case
95 there are more than 6 levels of array/ptr/function).
97 c) bt: an integer containing the base type before adding
98 array, pointer, function, etc. qualifiers. The
99 current base types that I have documentation for are:
101 btNil -- undefined
102 btAdr -- address - integer same size as ptr
103 btChar -- character
104 btUChar -- unsigned character
105 btShort -- short
106 btUShort -- unsigned short
107 btInt -- int
108 btUInt -- unsigned int
109 btLong -- long
110 btULong -- unsigned long
111 btFloat -- float (real)
112 btDouble -- Double (real)
113 btStruct -- Structure (Record)
114 btUnion -- Union (variant)
115 btEnum -- Enumerated
116 btTypedef -- defined via a typedef isymRef
117 btRange -- subrange of int
118 btSet -- pascal sets
119 btComplex -- fortran complex
120 btDComplex -- fortran double complex
121 btIndirect -- forward or unnamed typedef
122 btFixedDec -- Fixed Decimal
123 btFloatDec -- Float Decimal
124 btString -- Varying Length Character String
125 btBit -- Aligned Bit String
126 btPicture -- Picture
127 btVoid -- Void (MIPS cc revision >= 2.00)
129 d) tq0 - tq5: type qualifier fields as needed. The
130 current type qualifier fields I have documentation for
131 are:
133 tqNil -- no more qualifiers
134 tqPtr -- pointer
135 tqProc -- procedure
136 tqArray -- array
137 tqFar -- 8086 far pointers
138 tqVol -- volatile
141 The dense number table is used in the front ends, and disappears by
142 the time the .o is created.
144 With the 1.31 compiler suite, the optimization symbols don't seem
145 to be used as far as I can tell.
147 The linker is the first entity that creates the relative file
148 descriptor table, and I believe it is used so that the individual
149 file table pointers don't have to be rewritten when the objects are
150 merged together into the program file.
152 Unlike COFF, the basic symbol & string tables are split into
153 external and local symbols/strings. The relocation information
154 only goes off of the external symbol table, and the debug
155 information only goes off of the internal symbol table. The
156 external symbols can have links to an appropriate file index and
157 symbol within the file to give it the appropriate type information.
158 Because of this, the external symbols are actually larger than the
159 internal symbols (to contain the link information), and contain the
160 local symbol structure as a member, though this member is not the
161 first member of the external symbol structure (!). I suspect this
162 split is to make strip easier to deal with.
164 Each file table has offsets for where the line numbers, local
165 strings, local symbols, and procedure table starts from within the
166 global tables, and the indices are reset to 0 for each of those
167 tables for the file.
169 The procedure table contains the binary equivalents of the .ent
170 (start of the function address), .frame (what register is the
171 virtual frame pointer, constant offset from the register to obtain
172 the VFP, and what register holds the return address), .mask/.fmask
173 (bitmask of saved registers, and where the first register is stored
174 relative to the VFP) assembler directives. It also contains the
175 low and high bounds of the line numbers if debugging is turned on.
177 The line number table is a compressed form of the normal COFF line
178 table. Each line number entry is either 1 or 3 bytes long, and
179 contains a signed delta from the previous line, and an unsigned
180 count of the number of instructions this statement takes.
182 The local symbol table contains the following fields:
184 1) iss: index to the local string table giving the name of the
185 symbol.
187 2) value: value of the symbol (address, register number, etc.).
189 3) st: symbol type. The current symbol types are:
191 stNil -- Nuthin' special
192 stGlobal -- external symbol
193 stStatic -- static
194 stParam -- procedure argument
195 stLocal -- local variable
196 stLabel -- label
197 stProc -- External Procedure
198 stBlock -- beginning of block
199 stEnd -- end (of anything)
200 stMember -- member (of anything)
201 stTypedef -- type definition
202 stFile -- file name
203 stRegReloc -- register relocation
204 stForward -- forwarding address
205 stStaticProc -- Static procedure
206 stConstant -- const
208 4) sc: storage class. The current storage classes are:
210 scText -- text symbol
211 scData -- initialized data symbol
212 scBss -- un-initialized data symbol
213 scRegister -- value of symbol is register number
214 scAbs -- value of symbol is absolute
215 scUndefined -- who knows?
216 scCdbLocal -- variable's value is IN se->va.??
217 scBits -- this is a bit field
218 scCdbSystem -- value is IN debugger's address space
219 scRegImage -- register value saved on stack
220 scInfo -- symbol contains debugger information
221 scUserStruct -- addr in struct user for current process
222 scSData -- load time only small data
223 scSBss -- load time only small common
224 scRData -- load time only read only data
225 scVar -- Var parameter (fortranpascal)
226 scCommon -- common variable
227 scSCommon -- small common
228 scVarRegister -- Var parameter in a register
229 scVariant -- Variant record
230 scSUndefined -- small undefined(external) data
231 scInit -- .init section symbol
233 5) index: pointer to a local symbol or aux. entry.
237 For the following program:
239 #include <stdio.h>
241 main(){
242 printf("Hello World!\n");
243 return 0;
246 Mips-tdump produces the following information:
248 Global file header:
249 magic number 0x162
250 # sections 2
251 timestamp 645311799, Wed Jun 13 17:16:39 1990
252 symbolic header offset 284
253 symbolic header size 96
254 optional header 56
255 flags 0x0
257 Symbolic header, magic number = 0x7009, vstamp = 1.31:
259 Info Offset Number Bytes
260 ==== ====== ====== =====
262 Line numbers 380 4 4 [13]
263 Dense numbers 0 0 0
264 Procedures Tables 384 1 52
265 Local Symbols 436 16 192
266 Optimization Symbols 0 0 0
267 Auxiliary Symbols 628 39 156
268 Local Strings 784 80 80
269 External Strings 864 144 144
270 File Tables 1008 2 144
271 Relative Files 0 0 0
272 External Symbols 1152 20 320
274 File #0, "hello2.c"
276 Name index = 1 Readin = No
277 Merge = No Endian = LITTLE
278 Debug level = G2 Language = C
279 Adr = 0x00000000
281 Info Start Number Size Offset
282 ==== ===== ====== ==== ======
283 Local strings 0 15 15 784
284 Local symbols 0 6 72 436
285 Line numbers 0 13 13 380
286 Optimization symbols 0 0 0 0
287 Procedures 0 1 52 384
288 Auxiliary symbols 0 14 56 628
289 Relative Files 0 0 0 0
291 There are 6 local symbols, starting at 436
293 Symbol# 0: "hello2.c"
294 End+1 symbol = 6
295 String index = 1
296 Storage class = Text Index = 6
297 Symbol type = File Value = 0
299 Symbol# 1: "main"
300 End+1 symbol = 5
301 Type = int
302 String index = 10
303 Storage class = Text Index = 12
304 Symbol type = Proc Value = 0
306 Symbol# 2: ""
307 End+1 symbol = 4
308 String index = 0
309 Storage class = Text Index = 4
310 Symbol type = Block Value = 8
312 Symbol# 3: ""
313 First symbol = 2
314 String index = 0
315 Storage class = Text Index = 2
316 Symbol type = End Value = 28
318 Symbol# 4: "main"
319 First symbol = 1
320 String index = 10
321 Storage class = Text Index = 1
322 Symbol type = End Value = 52
324 Symbol# 5: "hello2.c"
325 First symbol = 0
326 String index = 1
327 Storage class = Text Index = 0
328 Symbol type = End Value = 0
330 There are 14 auxiliary table entries, starting at 628.
332 * #0 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
333 * #1 24, [ 24/ 0], [ 6 0:0 0:0:0:0:0:0]
334 * #2 8, [ 8/ 0], [ 2 0:0 0:0:0:0:0:0]
335 * #3 16, [ 16/ 0], [ 4 0:0 0:0:0:0:0:0]
336 * #4 24, [ 24/ 0], [ 6 0:0 0:0:0:0:0:0]
337 * #5 32, [ 32/ 0], [ 8 0:0 0:0:0:0:0:0]
338 * #6 40, [ 40/ 0], [10 0:0 0:0:0:0:0:0]
339 * #7 44, [ 44/ 0], [11 0:0 0:0:0:0:0:0]
340 * #8 12, [ 12/ 0], [ 3 0:0 0:0:0:0:0:0]
341 * #9 20, [ 20/ 0], [ 5 0:0 0:0:0:0:0:0]
342 * #10 28, [ 28/ 0], [ 7 0:0 0:0:0:0:0:0]
343 * #11 36, [ 36/ 0], [ 9 0:0 0:0:0:0:0:0]
344 #12 5, [ 5/ 0], [ 1 1:0 0:0:0:0:0:0]
345 #13 24, [ 24/ 0], [ 6 0:0 0:0:0:0:0:0]
347 There are 1 procedure descriptor entries, starting at 0.
349 Procedure descriptor 0:
350 Name index = 10 Name = "main"
351 .mask 0x80000000,-4 .fmask 0x00000000,0
352 .frame $29,24,$31
353 Opt. start = -1 Symbols start = 1
354 First line # = 3 Last line # = 6
355 Line Offset = 0 Address = 0x00000000
357 There are 4 bytes holding line numbers, starting at 380.
358 Line 3, delta 0, count 2
359 Line 4, delta 1, count 3
360 Line 5, delta 1, count 2
361 Line 6, delta 1, count 6
363 File #1, "/usr/include/stdio.h"
365 Name index = 1 Readin = No
366 Merge = Yes Endian = LITTLE
367 Debug level = G2 Language = C
368 Adr = 0x00000000
370 Info Start Number Size Offset
371 ==== ===== ====== ==== ======
372 Local strings 15 65 65 799
373 Local symbols 6 10 120 508
374 Line numbers 0 0 0 380
375 Optimization symbols 0 0 0 0
376 Procedures 1 0 0 436
377 Auxiliary symbols 14 25 100 684
378 Relative Files 0 0 0 0
380 There are 10 local symbols, starting at 442
382 Symbol# 0: "/usr/include/stdio.h"
383 End+1 symbol = 10
384 String index = 1
385 Storage class = Text Index = 10
386 Symbol type = File Value = 0
388 Symbol# 1: "_iobuf"
389 End+1 symbol = 9
390 String index = 22
391 Storage class = Info Index = 9
392 Symbol type = Block Value = 20
394 Symbol# 2: "_cnt"
395 Type = int
396 String index = 29
397 Storage class = Info Index = 4
398 Symbol type = Member Value = 0
400 Symbol# 3: "_ptr"
401 Type = ptr to char
402 String index = 34
403 Storage class = Info Index = 15
404 Symbol type = Member Value = 32
406 Symbol# 4: "_base"
407 Type = ptr to char
408 String index = 39
409 Storage class = Info Index = 16
410 Symbol type = Member Value = 64
412 Symbol# 5: "_bufsiz"
413 Type = int
414 String index = 45
415 Storage class = Info Index = 4
416 Symbol type = Member Value = 96
418 Symbol# 6: "_flag"
419 Type = short
420 String index = 53
421 Storage class = Info Index = 3
422 Symbol type = Member Value = 128
424 Symbol# 7: "_file"
425 Type = char
426 String index = 59
427 Storage class = Info Index = 2
428 Symbol type = Member Value = 144
430 Symbol# 8: ""
431 First symbol = 1
432 String index = 0
433 Storage class = Info Index = 1
434 Symbol type = End Value = 0
436 Symbol# 9: "/usr/include/stdio.h"
437 First symbol = 0
438 String index = 1
439 Storage class = Text Index = 0
440 Symbol type = End Value = 0
442 There are 25 auxiliary table entries, starting at 642.
444 * #14 -1, [4095/1048575], [63 1:1 f:f:f:f:f:f]
445 #15 65544, [ 8/ 16], [ 2 0:0 1:0:0:0:0:0]
446 #16 65544, [ 8/ 16], [ 2 0:0 1:0:0:0:0:0]
447 * #17 196656, [ 48/ 48], [12 0:0 3:0:0:0:0:0]
448 * #18 8191, [4095/ 1], [63 1:1 0:0:0:0:f:1]
449 * #19 1, [ 1/ 0], [ 0 1:0 0:0:0:0:0:0]
450 * #20 20479, [4095/ 4], [63 1:1 0:0:0:0:f:4]
451 * #21 1, [ 1/ 0], [ 0 1:0 0:0:0:0:0:0]
452 * #22 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
453 * #23 2, [ 2/ 0], [ 0 0:1 0:0:0:0:0:0]
454 * #24 160, [ 160/ 0], [40 0:0 0:0:0:0:0:0]
455 * #25 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
456 * #26 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
457 * #27 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
458 * #28 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
459 * #29 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
460 * #30 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
461 * #31 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
462 * #32 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
463 * #33 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
464 * #34 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
465 * #35 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
466 * #36 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
467 * #37 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
468 * #38 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
470 There are 0 procedure descriptor entries, starting at 1.
472 There are 20 external symbols, starting at 1152
474 Symbol# 0: "_iob"
475 Type = array [3 {160}] of struct _iobuf { ifd = 1, index = 1 }
476 String index = 0 Ifd = 1
477 Storage class = Nil Index = 17
478 Symbol type = Global Value = 60
480 Symbol# 1: "fopen"
481 String index = 5 Ifd = 1
482 Storage class = Nil Index = 1048575
483 Symbol type = Proc Value = 0
485 Symbol# 2: "fdopen"
486 String index = 11 Ifd = 1
487 Storage class = Nil Index = 1048575
488 Symbol type = Proc Value = 0
490 Symbol# 3: "freopen"
491 String index = 18 Ifd = 1
492 Storage class = Nil Index = 1048575
493 Symbol type = Proc Value = 0
495 Symbol# 4: "popen"
496 String index = 26 Ifd = 1
497 Storage class = Nil Index = 1048575
498 Symbol type = Proc Value = 0
500 Symbol# 5: "tmpfile"
501 String index = 32 Ifd = 1
502 Storage class = Nil Index = 1048575
503 Symbol type = Proc Value = 0
505 Symbol# 6: "ftell"
506 String index = 40 Ifd = 1
507 Storage class = Nil Index = 1048575
508 Symbol type = Proc Value = 0
510 Symbol# 7: "rewind"
511 String index = 46 Ifd = 1
512 Storage class = Nil Index = 1048575
513 Symbol type = Proc Value = 0
515 Symbol# 8: "setbuf"
516 String index = 53 Ifd = 1
517 Storage class = Nil Index = 1048575
518 Symbol type = Proc Value = 0
520 Symbol# 9: "setbuffer"
521 String index = 60 Ifd = 1
522 Storage class = Nil Index = 1048575
523 Symbol type = Proc Value = 0
525 Symbol# 10: "setlinebuf"
526 String index = 70 Ifd = 1
527 Storage class = Nil Index = 1048575
528 Symbol type = Proc Value = 0
530 Symbol# 11: "fgets"
531 String index = 81 Ifd = 1
532 Storage class = Nil Index = 1048575
533 Symbol type = Proc Value = 0
535 Symbol# 12: "gets"
536 String index = 87 Ifd = 1
537 Storage class = Nil Index = 1048575
538 Symbol type = Proc Value = 0
540 Symbol# 13: "ctermid"
541 String index = 92 Ifd = 1
542 Storage class = Nil Index = 1048575
543 Symbol type = Proc Value = 0
545 Symbol# 14: "cuserid"
546 String index = 100 Ifd = 1
547 Storage class = Nil Index = 1048575
548 Symbol type = Proc Value = 0
550 Symbol# 15: "tempnam"
551 String index = 108 Ifd = 1
552 Storage class = Nil Index = 1048575
553 Symbol type = Proc Value = 0
555 Symbol# 16: "tmpnam"
556 String index = 116 Ifd = 1
557 Storage class = Nil Index = 1048575
558 Symbol type = Proc Value = 0
560 Symbol# 17: "sprintf"
561 String index = 123 Ifd = 1
562 Storage class = Nil Index = 1048575
563 Symbol type = Proc Value = 0
565 Symbol# 18: "main"
566 Type = int
567 String index = 131 Ifd = 0
568 Storage class = Text Index = 1
569 Symbol type = Proc Value = 0
571 Symbol# 19: "printf"
572 String index = 136 Ifd = 0
573 Storage class = Undefined Index = 1048575
574 Symbol type = Proc Value = 0
576 The following auxiliary table entries were unused:
578 #0 0 0x00000000 void
579 #2 8 0x00000008 char
580 #3 16 0x00000010 short
581 #4 24 0x00000018 int
582 #5 32 0x00000020 long
583 #6 40 0x00000028 float
584 #7 44 0x0000002c double
585 #8 12 0x0000000c unsigned char
586 #9 20 0x00000014 unsigned short
587 #10 28 0x0000001c unsigned int
588 #11 36 0x00000024 unsigned long
589 #14 0 0x00000000 void
590 #15 24 0x00000018 int
591 #19 32 0x00000020 long
592 #20 40 0x00000028 float
593 #21 44 0x0000002c double
594 #22 12 0x0000000c unsigned char
595 #23 20 0x00000014 unsigned short
596 #24 28 0x0000001c unsigned int
597 #25 36 0x00000024 unsigned long
598 #26 48 0x00000030 struct no name { ifd = -1, index = 1048575 }
603 #include "config.h"
604 #include "system.h"
605 #include "version.h"
606 #include "intl.h"
608 /* Include getopt.h for the sake of getopt_long. */
609 #include "getopt.h"
611 /* Macros for mips-tfile.c to encapsulate stabs in ECOFF, and for
612 mips-tdump.c to print them out.
614 These must match the corresponding definitions in gdb/mipsread.c.
615 Unfortunately, gcc and gdb do not currently share any directories. */
617 #define CODE_MASK 0x8F300
618 #define MIPS_IS_STAB(sym) (((sym)->index & 0xFFF00) == CODE_MASK)
619 #define MIPS_MARK_STAB(code) ((code)+CODE_MASK)
620 #define MIPS_UNMARK_STAB(code) ((code)-CODE_MASK)
622 /* The following might be called from obstack or malloc,
623 so they can't be static. */
625 extern void pfatal_with_name (const char *) ATTRIBUTE_NORETURN;
626 extern void botch (const char *) ATTRIBUTE_NORETURN;
628 extern void fatal (const char *format, ...) ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
629 extern void error (const char *format, ...) ATTRIBUTE_PRINTF_1;
631 /* The local and global symbols have a field index, so undo any defines
632 of index -> strchr. */
634 #undef index
636 #include <a.out.h>
637 #include "gstab.h"
639 #define IS_ASM_IDENT(ch) \
640 (ISIDNUM (ch) || (ch) == '.' || (ch) == '$')
643 /* Redefinition of storage classes as an enumeration for better
644 debugging. */
646 typedef enum sc {
647 sc_Nil = scNil, /* no storage class */
648 sc_Text = scText, /* text symbol */
649 sc_Data = scData, /* initialized data symbol */
650 sc_Bss = scBss, /* un-initialized data symbol */
651 sc_Register = scRegister, /* value of symbol is register number */
652 sc_Abs = scAbs, /* value of symbol is absolute */
653 sc_Undefined = scUndefined, /* who knows? */
654 sc_CdbLocal = scCdbLocal, /* variable's value is IN se->va.?? */
655 sc_Bits = scBits, /* this is a bit field */
656 sc_CdbSystem = scCdbSystem, /* value is IN CDB's address space */
657 sc_RegImage = scRegImage, /* register value saved on stack */
658 sc_Info = scInfo, /* symbol contains debugger information */
659 sc_UserStruct = scUserStruct, /* addr in struct user for current process */
660 sc_SData = scSData, /* load time only small data */
661 sc_SBss = scSBss, /* load time only small common */
662 sc_RData = scRData, /* load time only read only data */
663 sc_Var = scVar, /* Var parameter (fortran,pascal) */
664 sc_Common = scCommon, /* common variable */
665 sc_SCommon = scSCommon, /* small common */
666 sc_VarRegister = scVarRegister, /* Var parameter in a register */
667 sc_Variant = scVariant, /* Variant record */
668 sc_SUndefined = scSUndefined, /* small undefined(external) data */
669 sc_Init = scInit, /* .init section symbol */
670 sc_Max = scMax /* Max storage class+1 */
671 } sc_t;
673 /* Redefinition of symbol type. */
675 typedef enum st {
676 st_Nil = stNil, /* Nuthin' special */
677 st_Global = stGlobal, /* external symbol */
678 st_Static = stStatic, /* static */
679 st_Param = stParam, /* procedure argument */
680 st_Local = stLocal, /* local variable */
681 st_Label = stLabel, /* label */
682 st_Proc = stProc, /* " " Procedure */
683 st_Block = stBlock, /* beginning of block */
684 st_End = stEnd, /* end (of anything) */
685 st_Member = stMember, /* member (of anything - struct/union/enum */
686 st_Typedef = stTypedef, /* type definition */
687 st_File = stFile, /* file name */
688 st_RegReloc = stRegReloc, /* register relocation */
689 st_Forward = stForward, /* forwarding address */
690 st_StaticProc = stStaticProc, /* load time only static procs */
691 st_Constant = stConstant, /* const */
692 st_Str = stStr, /* string */
693 st_Number = stNumber, /* pure number (i.e. 4 NOR 2+2) */
694 st_Expr = stExpr, /* 2+2 vs. 4 */
695 st_Type = stType, /* post-coercion SER */
696 st_Max = stMax /* max type+1 */
697 } st_t;
699 /* Redefinition of type qualifiers. */
701 typedef enum tq {
702 tq_Nil = tqNil, /* bt is what you see */
703 tq_Ptr = tqPtr, /* pointer */
704 tq_Proc = tqProc, /* procedure */
705 tq_Array = tqArray, /* duh */
706 tq_Far = tqFar, /* longer addressing - 8086/8 land */
707 tq_Vol = tqVol, /* volatile */
708 tq_Max = tqMax /* Max type qualifier+1 */
709 } tq_t;
711 /* Redefinition of basic types. */
713 typedef enum bt {
714 bt_Nil = btNil, /* undefined */
715 bt_Adr = btAdr, /* address - integer same size as pointer */
716 bt_Char = btChar, /* character */
717 bt_UChar = btUChar, /* unsigned character */
718 bt_Short = btShort, /* short */
719 bt_UShort = btUShort, /* unsigned short */
720 bt_Int = btInt, /* int */
721 bt_UInt = btUInt, /* unsigned int */
722 bt_Long = btLong, /* long */
723 bt_ULong = btULong, /* unsigned long */
724 bt_Float = btFloat, /* float (real) */
725 bt_Double = btDouble, /* Double (real) */
726 bt_Struct = btStruct, /* Structure (Record) */
727 bt_Union = btUnion, /* Union (variant) */
728 bt_Enum = btEnum, /* Enumerated */
729 bt_Typedef = btTypedef, /* defined via a typedef, isymRef points */
730 bt_Range = btRange, /* subrange of int */
731 bt_Set = btSet, /* pascal sets */
732 bt_Complex = btComplex, /* fortran complex */
733 bt_DComplex = btDComplex, /* fortran double complex */
734 bt_Indirect = btIndirect, /* forward or unnamed typedef */
735 bt_FixedDec = btFixedDec, /* Fixed Decimal */
736 bt_FloatDec = btFloatDec, /* Float Decimal */
737 bt_String = btString, /* Varying Length Character String */
738 bt_Bit = btBit, /* Aligned Bit String */
739 bt_Picture = btPicture, /* Picture */
741 #ifdef btVoid
742 bt_Void = btVoid, /* Void */
743 #else
744 #define bt_Void bt_Nil
745 #endif
747 bt_Max = btMax /* Max basic type+1 */
748 } bt_t;
752 /* Basic COFF storage classes. */
753 enum coff_storage {
754 C_EFCN = -1,
755 C_NULL = 0,
756 C_AUTO = 1,
757 C_EXT = 2,
758 C_STAT = 3,
759 C_REG = 4,
760 C_EXTDEF = 5,
761 C_LABEL = 6,
762 C_ULABEL = 7,
763 C_MOS = 8,
764 C_ARG = 9,
765 C_STRTAG = 10,
766 C_MOU = 11,
767 C_UNTAG = 12,
768 C_TPDEF = 13,
769 C_USTATIC = 14,
770 C_ENTAG = 15,
771 C_MOE = 16,
772 C_REGPARM = 17,
773 C_FIELD = 18,
774 C_BLOCK = 100,
775 C_FCN = 101,
776 C_EOS = 102,
777 C_FILE = 103,
778 C_LINE = 104,
779 C_ALIAS = 105,
780 C_HIDDEN = 106,
781 C_MAX = 107
782 } coff_storage_t;
784 /* Regular COFF fundamental type. */
785 typedef enum coff_type {
786 T_NULL = 0,
787 T_ARG = 1,
788 T_CHAR = 2,
789 T_SHORT = 3,
790 T_INT = 4,
791 T_LONG = 5,
792 T_FLOAT = 6,
793 T_DOUBLE = 7,
794 T_STRUCT = 8,
795 T_UNION = 9,
796 T_ENUM = 10,
797 T_MOE = 11,
798 T_UCHAR = 12,
799 T_USHORT = 13,
800 T_UINT = 14,
801 T_ULONG = 15,
802 T_MAX = 16
803 } coff_type_t;
805 /* Regular COFF derived types. */
806 typedef enum coff_dt {
807 DT_NON = 0,
808 DT_PTR = 1,
809 DT_FCN = 2,
810 DT_ARY = 3,
811 DT_MAX = 4
812 } coff_dt_t;
814 #define N_BTMASK 017 /* bitmask to isolate basic type */
815 #define N_TMASK 003 /* bitmask to isolate derived type */
816 #define N_BT_SHIFT 4 /* # bits to shift past basic type */
817 #define N_TQ_SHIFT 2 /* # bits to shift derived types */
818 #define N_TQ 6 /* # of type qualifiers */
820 /* States for whether to hash type or not. */
821 typedef enum hash_state {
822 hash_no = 0, /* don't hash type */
823 hash_yes = 1, /* ok to hash type, or use previous hash */
824 hash_record = 2 /* ok to record hash, but don't use prev. */
825 } hash_state_t;
828 /* Types of different sized allocation requests. */
829 enum alloc_type {
830 alloc_type_none, /* dummy value */
831 alloc_type_scope, /* nested scopes linked list */
832 alloc_type_vlinks, /* glue linking pages in varray */
833 alloc_type_shash, /* string hash element */
834 alloc_type_thash, /* type hash element */
835 alloc_type_tag, /* struct/union/tag element */
836 alloc_type_forward, /* element to hold unknown tag */
837 alloc_type_thead, /* head of type hash list */
838 alloc_type_varray, /* general varray allocation */
839 alloc_type_last /* last+1 element for array bounds */
843 #define WORD_ALIGN(x) (((x) + (sizeof (long) - 1)) & ~ (sizeof (long) - 1))
844 #define DWORD_ALIGN(x) (((x) + 7) & ~7)
847 /* Structures to provide n-number of virtual arrays, each of which can
848 grow linearly, and which are written in the object file as sequential
849 pages. On systems with a BSD malloc that define USE_MALLOC, the
850 MAX_CLUSTER_PAGES should be 1 less than a power of two, since malloc
851 adds its overhead, and rounds up to the next power of 2. Pages are
852 linked together via a linked list. */
854 #ifndef PAGE_SIZE
855 #define PAGE_SIZE 32768 /* size of varray pages */
856 #endif
858 #define PAGE_USIZE ((size_t) PAGE_SIZE)
861 #ifndef MAX_CLUSTER_PAGES /* # pages to get from system */
862 #ifndef USE_MALLOC /* in one memory request */
863 #define MAX_CLUSTER_PAGES 64
864 #else
865 #define MAX_CLUSTER_PAGES 63
866 #endif
867 #endif
870 /* Linked list connecting separate page allocations. */
871 typedef struct vlinks {
872 struct vlinks *prev; /* previous set of pages */
873 struct vlinks *next; /* next set of pages */
874 union page *datum; /* start of page */
875 unsigned long start_index; /* starting index # of page */
876 } vlinks_t;
879 /* Virtual array header. */
880 typedef struct varray {
881 vlinks_t *first; /* first page link */
882 vlinks_t *last; /* last page link */
883 unsigned long num_allocated; /* # objects allocated */
884 unsigned short object_size; /* size in bytes of each object */
885 unsigned short objects_per_page; /* # objects that can fit on a page */
886 unsigned short objects_last_page; /* # objects allocated on last page */
887 } varray_t;
889 #ifndef MALLOC_CHECK
890 #define OBJECTS_PER_PAGE(type) (PAGE_SIZE / sizeof (type))
891 #else
892 #define OBJECTS_PER_PAGE(type) ((sizeof (type) > 1) ? 1 : PAGE_SIZE)
893 #endif
895 #define INIT_VARRAY(type) { /* macro to initialize a varray */ \
896 (vlinks_t *) 0, /* first */ \
897 (vlinks_t *) 0, /* last */ \
898 0, /* num_allocated */ \
899 sizeof (type), /* object_size */ \
900 OBJECTS_PER_PAGE (type), /* objects_per_page */ \
901 OBJECTS_PER_PAGE (type), /* objects_last_page */ \
904 #define INITIALIZE_VARRAY(x,type) \
905 do { \
906 (x)->object_size = sizeof (type); \
907 (x)->objects_per_page = OBJECTS_PER_PAGE (type); \
908 (x)->objects_last_page = OBJECTS_PER_PAGE (type); \
909 } while (0)
911 /* Master type for indexes within the symbol table. */
912 typedef unsigned long symint_t;
915 /* Linked list support for nested scopes (file, block, structure, etc.). */
916 typedef struct scope {
917 struct scope *prev; /* previous scope level */
918 struct scope *free; /* free list pointer */
919 SYMR *lsym; /* pointer to local symbol node */
920 symint_t lnumber; /* lsym index */
921 st_t type; /* type of the node */
922 } scope_t;
925 /* Forward reference list for tags referenced, but not yet defined. */
926 typedef struct forward {
927 struct forward *next; /* next forward reference */
928 struct forward *free; /* free list pointer */
929 AUXU *ifd_ptr; /* pointer to store file index */
930 AUXU *index_ptr; /* pointer to store symbol index */
931 AUXU *type_ptr; /* pointer to munge type info */
932 } forward_t;
935 /* Linked list support for tags. The first tag in the list is always
936 the current tag for that block. */
937 typedef struct tag {
938 struct tag *free; /* free list pointer */
939 struct shash *hash_ptr; /* pointer to the hash table head */
940 struct tag *same_name; /* tag with same name in outer scope */
941 struct tag *same_block; /* next tag defined in the same block. */
942 struct forward *forward_ref; /* list of forward references */
943 bt_t basic_type; /* bt_Struct, bt_Union, or bt_Enum */
944 symint_t ifd; /* file # tag defined in */
945 symint_t indx; /* index within file's local symbols */
946 } tag_t;
949 /* Head of a block's linked list of tags. */
950 typedef struct thead {
951 struct thead *prev; /* previous block */
952 struct thead *free; /* free list pointer */
953 struct tag *first_tag; /* first tag in block defined */
954 } thead_t;
957 /* Union containing pointers to each the small structures which are freed up. */
958 typedef union small_free {
959 scope_t *f_scope; /* scope structure */
960 thead_t *f_thead; /* tag head structure */
961 tag_t *f_tag; /* tag element structure */
962 forward_t *f_forward; /* forward tag reference */
963 } small_free_t;
966 /* String hash table support. The size of the hash table must fit
967 within a page. */
969 #define SHASH_SIZE 511
971 #define HASH_LEN_MAX ((1 << 12) - 1) /* Max length we can store */
973 typedef struct shash {
974 struct shash *next; /* next hash value */
975 char *string; /* string we are hashing */
976 symint_t len; /* string length */
977 symint_t indx; /* index within string table */
978 EXTR *esym_ptr; /* global symbol pointer */
979 SYMR *sym_ptr; /* local symbol pointer */
980 SYMR *end_ptr; /* symbol pointer to end block */
981 tag_t *tag_ptr; /* tag pointer */
982 PDR *proc_ptr; /* procedure descriptor pointer */
983 } shash_t;
986 /* Type hash table support. The size of the hash table must fit
987 within a page with the other extended file descriptor information.
988 Because unique types which are hashed are fewer in number than
989 strings, we use a smaller hash value. */
991 #define THASH_SIZE 55
993 typedef struct thash {
994 struct thash *next; /* next hash value */
995 AUXU type; /* type we are hashing */
996 symint_t indx; /* index within string table */
997 } thash_t;
1000 /* Extended file descriptor that contains all of the support necessary
1001 to add things to each file separately. */
1002 typedef struct efdr {
1003 FDR fdr; /* File header to be written out */
1004 FDR *orig_fdr; /* original file header */
1005 char *name; /* filename */
1006 int name_len; /* length of the filename */
1007 symint_t void_type; /* aux. pointer to 'void' type */
1008 symint_t int_type; /* aux. pointer to 'int' type */
1009 scope_t *cur_scope; /* current nested scopes */
1010 symint_t file_index; /* current file number */
1011 int nested_scopes; /* # nested scopes */
1012 varray_t strings; /* local strings */
1013 varray_t symbols; /* local symbols */
1014 varray_t procs; /* procedures */
1015 varray_t aux_syms; /* auxiliary symbols */
1016 struct efdr *next_file; /* next file descriptor */
1017 /* string/type hash tables */
1018 shash_t **shash_head; /* string hash table */
1019 thash_t *thash_head[THASH_SIZE];
1020 } efdr_t;
1022 /* Pre-initialized extended file structure. */
1023 static int init_file_initialized = 0;
1024 static efdr_t init_file;
1026 static efdr_t *first_file; /* first file descriptor */
1027 static efdr_t **last_file_ptr = &first_file; /* file descriptor tail */
1030 /* Union of various things that are held in pages. */
1031 typedef union page {
1032 char byte [ PAGE_SIZE ];
1033 unsigned char ubyte [ PAGE_SIZE ];
1034 efdr_t file [ PAGE_SIZE / sizeof (efdr_t) ];
1035 FDR ofile [ PAGE_SIZE / sizeof (FDR) ];
1036 PDR proc [ PAGE_SIZE / sizeof (PDR) ];
1037 SYMR sym [ PAGE_SIZE / sizeof (SYMR) ];
1038 EXTR esym [ PAGE_SIZE / sizeof (EXTR) ];
1039 AUXU aux [ PAGE_SIZE / sizeof (AUXU) ];
1040 DNR dense [ PAGE_SIZE / sizeof (DNR) ];
1041 scope_t scope [ PAGE_SIZE / sizeof (scope_t) ];
1042 vlinks_t vlinks [ PAGE_SIZE / sizeof (vlinks_t) ];
1043 shash_t shash [ PAGE_SIZE / sizeof (shash_t) ];
1044 thash_t thash [ PAGE_SIZE / sizeof (thash_t) ];
1045 tag_t tag [ PAGE_SIZE / sizeof (tag_t) ];
1046 forward_t forward [ PAGE_SIZE / sizeof (forward_t) ];
1047 thead_t thead [ PAGE_SIZE / sizeof (thead_t) ];
1048 } page_t;
1051 /* Structure holding allocation information for small sized structures. */
1052 typedef struct alloc_info {
1053 const char *alloc_name; /* name of this allocation type (must be first) */
1054 page_t *cur_page; /* current page being allocated from */
1055 small_free_t free_list; /* current free list if any */
1056 int unallocated; /* number of elements unallocated on page */
1057 int total_alloc; /* total number of allocations */
1058 int total_free; /* total number of frees */
1059 int total_pages; /* total number of pages allocated */
1060 } alloc_info_t;
1062 /* Type information collected together. */
1063 typedef struct type_info {
1064 bt_t basic_type; /* basic type */
1065 coff_type_t orig_type; /* original COFF-based type */
1066 int num_tq; /* # type qualifiers */
1067 int num_dims; /* # dimensions */
1068 int num_sizes; /* # sizes */
1069 int extra_sizes; /* # extra sizes not tied with dims */
1070 tag_t * tag_ptr; /* tag pointer */
1071 int bitfield; /* symbol is a bitfield */
1072 int unknown_tag; /* this is an unknown tag */
1073 tq_t type_qualifiers[N_TQ]; /* type qualifiers (ptr, func, array)*/
1074 symint_t dimensions [N_TQ]; /* dimensions for each array */
1075 symint_t sizes [N_TQ+2]; /* sizes of each array slice + size of
1076 struct/union/enum + bitfield size */
1077 } type_info_t;
1079 /* Pre-initialized type_info struct. */
1080 static type_info_t type_info_init = {
1081 bt_Nil, /* basic type */
1082 T_NULL, /* original COFF-based type */
1083 0, /* # type qualifiers */
1084 0, /* # dimensions */
1085 0, /* # sizes */
1086 0, /* sizes not tied with dims */
1087 NULL, /* ptr to tag */
1088 0, /* bitfield */
1089 0, /* unknown tag */
1090 { /* type qualifiers */
1091 tq_Nil,
1092 tq_Nil,
1093 tq_Nil,
1094 tq_Nil,
1095 tq_Nil,
1096 tq_Nil,
1098 { /* dimensions */
1106 { /* sizes */
1119 /* Global virtual arrays & hash table for external strings as well as
1120 for the tags table and global tables for file descriptors, and
1121 dense numbers. */
1123 static varray_t file_desc = INIT_VARRAY (efdr_t);
1124 static varray_t dense_num = INIT_VARRAY (DNR);
1125 static varray_t tag_strings = INIT_VARRAY (char);
1126 static varray_t ext_strings = INIT_VARRAY (char);
1127 static varray_t ext_symbols = INIT_VARRAY (EXTR);
1129 static shash_t *orig_str_hash[SHASH_SIZE];
1130 static shash_t *ext_str_hash [SHASH_SIZE];
1131 static shash_t *tag_hash [SHASH_SIZE];
1133 /* Static types for int and void. Also, remember the last function's
1134 type (which is set up when we encounter the declaration for the
1135 function, and used when the end block for the function is emitted. */
1137 static type_info_t int_type_info;
1138 static type_info_t void_type_info;
1139 static type_info_t last_func_type_info;
1140 static EXTR *last_func_eptr;
1143 /* Convert COFF basic type to ECOFF basic type. The T_NULL type
1144 really should use bt_Void, but this causes the current ecoff GDB to
1145 issue unsupported type messages, and the Ultrix 4.00 dbx (aka MIPS
1146 2.0) doesn't understand it, even though the compiler generates it.
1147 Maybe this will be fixed in 2.10 or 2.20 of the MIPS compiler
1148 suite, but for now go with what works. */
1150 static const bt_t map_coff_types[ (int) T_MAX ] = {
1151 bt_Nil, /* T_NULL */
1152 bt_Nil, /* T_ARG */
1153 bt_Char, /* T_CHAR */
1154 bt_Short, /* T_SHORT */
1155 bt_Int, /* T_INT */
1156 bt_Long, /* T_LONG */
1157 bt_Float, /* T_FLOAT */
1158 bt_Double, /* T_DOUBLE */
1159 bt_Struct, /* T_STRUCT */
1160 bt_Union, /* T_UNION */
1161 bt_Enum, /* T_ENUM */
1162 bt_Enum, /* T_MOE */
1163 bt_UChar, /* T_UCHAR */
1164 bt_UShort, /* T_USHORT */
1165 bt_UInt, /* T_UINT */
1166 bt_ULong /* T_ULONG */
1169 /* Convert COFF storage class to ECOFF storage class. */
1170 static const sc_t map_coff_storage[ (int) C_MAX ] = {
1171 sc_Nil, /* 0: C_NULL */
1172 sc_Abs, /* 1: C_AUTO auto var */
1173 sc_Undefined, /* 2: C_EXT external */
1174 sc_Data, /* 3: C_STAT static */
1175 sc_Register, /* 4: C_REG register */
1176 sc_Undefined, /* 5: C_EXTDEF ??? */
1177 sc_Text, /* 6: C_LABEL label */
1178 sc_Text, /* 7: C_ULABEL user label */
1179 sc_Info, /* 8: C_MOS member of struct */
1180 sc_Abs, /* 9: C_ARG argument */
1181 sc_Info, /* 10: C_STRTAG struct tag */
1182 sc_Info, /* 11: C_MOU member of union */
1183 sc_Info, /* 12: C_UNTAG union tag */
1184 sc_Info, /* 13: C_TPDEF typedef */
1185 sc_Data, /* 14: C_USTATIC ??? */
1186 sc_Info, /* 15: C_ENTAG enum tag */
1187 sc_Info, /* 16: C_MOE member of enum */
1188 sc_Register, /* 17: C_REGPARM register parameter */
1189 sc_Bits, /* 18; C_FIELD bitfield */
1190 sc_Nil, /* 19 */
1191 sc_Nil, /* 20 */
1192 sc_Nil, /* 21 */
1193 sc_Nil, /* 22 */
1194 sc_Nil, /* 23 */
1195 sc_Nil, /* 24 */
1196 sc_Nil, /* 25 */
1197 sc_Nil, /* 26 */
1198 sc_Nil, /* 27 */
1199 sc_Nil, /* 28 */
1200 sc_Nil, /* 29 */
1201 sc_Nil, /* 30 */
1202 sc_Nil, /* 31 */
1203 sc_Nil, /* 32 */
1204 sc_Nil, /* 33 */
1205 sc_Nil, /* 34 */
1206 sc_Nil, /* 35 */
1207 sc_Nil, /* 36 */
1208 sc_Nil, /* 37 */
1209 sc_Nil, /* 38 */
1210 sc_Nil, /* 39 */
1211 sc_Nil, /* 40 */
1212 sc_Nil, /* 41 */
1213 sc_Nil, /* 42 */
1214 sc_Nil, /* 43 */
1215 sc_Nil, /* 44 */
1216 sc_Nil, /* 45 */
1217 sc_Nil, /* 46 */
1218 sc_Nil, /* 47 */
1219 sc_Nil, /* 48 */
1220 sc_Nil, /* 49 */
1221 sc_Nil, /* 50 */
1222 sc_Nil, /* 51 */
1223 sc_Nil, /* 52 */
1224 sc_Nil, /* 53 */
1225 sc_Nil, /* 54 */
1226 sc_Nil, /* 55 */
1227 sc_Nil, /* 56 */
1228 sc_Nil, /* 57 */
1229 sc_Nil, /* 58 */
1230 sc_Nil, /* 59 */
1231 sc_Nil, /* 60 */
1232 sc_Nil, /* 61 */
1233 sc_Nil, /* 62 */
1234 sc_Nil, /* 63 */
1235 sc_Nil, /* 64 */
1236 sc_Nil, /* 65 */
1237 sc_Nil, /* 66 */
1238 sc_Nil, /* 67 */
1239 sc_Nil, /* 68 */
1240 sc_Nil, /* 69 */
1241 sc_Nil, /* 70 */
1242 sc_Nil, /* 71 */
1243 sc_Nil, /* 72 */
1244 sc_Nil, /* 73 */
1245 sc_Nil, /* 74 */
1246 sc_Nil, /* 75 */
1247 sc_Nil, /* 76 */
1248 sc_Nil, /* 77 */
1249 sc_Nil, /* 78 */
1250 sc_Nil, /* 79 */
1251 sc_Nil, /* 80 */
1252 sc_Nil, /* 81 */
1253 sc_Nil, /* 82 */
1254 sc_Nil, /* 83 */
1255 sc_Nil, /* 84 */
1256 sc_Nil, /* 85 */
1257 sc_Nil, /* 86 */
1258 sc_Nil, /* 87 */
1259 sc_Nil, /* 88 */
1260 sc_Nil, /* 89 */
1261 sc_Nil, /* 90 */
1262 sc_Nil, /* 91 */
1263 sc_Nil, /* 92 */
1264 sc_Nil, /* 93 */
1265 sc_Nil, /* 94 */
1266 sc_Nil, /* 95 */
1267 sc_Nil, /* 96 */
1268 sc_Nil, /* 97 */
1269 sc_Nil, /* 98 */
1270 sc_Nil, /* 99 */
1271 sc_Text, /* 100: C_BLOCK block start/end */
1272 sc_Text, /* 101: C_FCN function start/end */
1273 sc_Info, /* 102: C_EOS end of struct/union/enum */
1274 sc_Nil, /* 103: C_FILE file start */
1275 sc_Nil, /* 104: C_LINE line number */
1276 sc_Nil, /* 105: C_ALIAS combined type info */
1277 sc_Nil, /* 106: C_HIDDEN ??? */
1280 /* Convert COFF storage class to ECOFF symbol type. */
1281 static const st_t map_coff_sym_type[ (int) C_MAX ] = {
1282 st_Nil, /* 0: C_NULL */
1283 st_Local, /* 1: C_AUTO auto var */
1284 st_Global, /* 2: C_EXT external */
1285 st_Static, /* 3: C_STAT static */
1286 st_Local, /* 4: C_REG register */
1287 st_Global, /* 5: C_EXTDEF ??? */
1288 st_Label, /* 6: C_LABEL label */
1289 st_Label, /* 7: C_ULABEL user label */
1290 st_Member, /* 8: C_MOS member of struct */
1291 st_Param, /* 9: C_ARG argument */
1292 st_Block, /* 10: C_STRTAG struct tag */
1293 st_Member, /* 11: C_MOU member of union */
1294 st_Block, /* 12: C_UNTAG union tag */
1295 st_Typedef, /* 13: C_TPDEF typedef */
1296 st_Static, /* 14: C_USTATIC ??? */
1297 st_Block, /* 15: C_ENTAG enum tag */
1298 st_Member, /* 16: C_MOE member of enum */
1299 st_Param, /* 17: C_REGPARM register parameter */
1300 st_Member, /* 18; C_FIELD bitfield */
1301 st_Nil, /* 19 */
1302 st_Nil, /* 20 */
1303 st_Nil, /* 21 */
1304 st_Nil, /* 22 */
1305 st_Nil, /* 23 */
1306 st_Nil, /* 24 */
1307 st_Nil, /* 25 */
1308 st_Nil, /* 26 */
1309 st_Nil, /* 27 */
1310 st_Nil, /* 28 */
1311 st_Nil, /* 29 */
1312 st_Nil, /* 30 */
1313 st_Nil, /* 31 */
1314 st_Nil, /* 32 */
1315 st_Nil, /* 33 */
1316 st_Nil, /* 34 */
1317 st_Nil, /* 35 */
1318 st_Nil, /* 36 */
1319 st_Nil, /* 37 */
1320 st_Nil, /* 38 */
1321 st_Nil, /* 39 */
1322 st_Nil, /* 40 */
1323 st_Nil, /* 41 */
1324 st_Nil, /* 42 */
1325 st_Nil, /* 43 */
1326 st_Nil, /* 44 */
1327 st_Nil, /* 45 */
1328 st_Nil, /* 46 */
1329 st_Nil, /* 47 */
1330 st_Nil, /* 48 */
1331 st_Nil, /* 49 */
1332 st_Nil, /* 50 */
1333 st_Nil, /* 51 */
1334 st_Nil, /* 52 */
1335 st_Nil, /* 53 */
1336 st_Nil, /* 54 */
1337 st_Nil, /* 55 */
1338 st_Nil, /* 56 */
1339 st_Nil, /* 57 */
1340 st_Nil, /* 58 */
1341 st_Nil, /* 59 */
1342 st_Nil, /* 60 */
1343 st_Nil, /* 61 */
1344 st_Nil, /* 62 */
1345 st_Nil, /* 63 */
1346 st_Nil, /* 64 */
1347 st_Nil, /* 65 */
1348 st_Nil, /* 66 */
1349 st_Nil, /* 67 */
1350 st_Nil, /* 68 */
1351 st_Nil, /* 69 */
1352 st_Nil, /* 70 */
1353 st_Nil, /* 71 */
1354 st_Nil, /* 72 */
1355 st_Nil, /* 73 */
1356 st_Nil, /* 74 */
1357 st_Nil, /* 75 */
1358 st_Nil, /* 76 */
1359 st_Nil, /* 77 */
1360 st_Nil, /* 78 */
1361 st_Nil, /* 79 */
1362 st_Nil, /* 80 */
1363 st_Nil, /* 81 */
1364 st_Nil, /* 82 */
1365 st_Nil, /* 83 */
1366 st_Nil, /* 84 */
1367 st_Nil, /* 85 */
1368 st_Nil, /* 86 */
1369 st_Nil, /* 87 */
1370 st_Nil, /* 88 */
1371 st_Nil, /* 89 */
1372 st_Nil, /* 90 */
1373 st_Nil, /* 91 */
1374 st_Nil, /* 92 */
1375 st_Nil, /* 93 */
1376 st_Nil, /* 94 */
1377 st_Nil, /* 95 */
1378 st_Nil, /* 96 */
1379 st_Nil, /* 97 */
1380 st_Nil, /* 98 */
1381 st_Nil, /* 99 */
1382 st_Block, /* 100: C_BLOCK block start/end */
1383 st_Proc, /* 101: C_FCN function start/end */
1384 st_End, /* 102: C_EOS end of struct/union/enum */
1385 st_File, /* 103: C_FILE file start */
1386 st_Nil, /* 104: C_LINE line number */
1387 st_Nil, /* 105: C_ALIAS combined type info */
1388 st_Nil, /* 106: C_HIDDEN ??? */
1391 /* Map COFF derived types to ECOFF type qualifiers. */
1392 static const tq_t map_coff_derived_type[ (int) DT_MAX ] = {
1393 tq_Nil, /* 0: DT_NON no more qualifiers */
1394 tq_Ptr, /* 1: DT_PTR pointer */
1395 tq_Proc, /* 2: DT_FCN function */
1396 tq_Array, /* 3: DT_ARY array */
1400 /* Keep track of different sized allocation requests. */
1401 static alloc_info_t alloc_counts[ (int) alloc_type_last ];
1404 /* Pointers and such to the original symbol table that is read in. */
1405 static struct filehdr orig_file_header; /* global object file header */
1407 static HDRR orig_sym_hdr; /* symbolic header on input */
1408 static char *orig_linenum; /* line numbers */
1409 static DNR *orig_dense; /* dense numbers */
1410 static PDR *orig_procs; /* procedures */
1411 static SYMR *orig_local_syms; /* local symbols */
1412 static OPTR *orig_opt_syms; /* optimization symbols */
1413 static AUXU *orig_aux_syms; /* auxiliary symbols */
1414 static char *orig_local_strs; /* local strings */
1415 static char *orig_ext_strs; /* external strings */
1416 static FDR *orig_files; /* file descriptors */
1417 static symint_t *orig_rfds; /* relative file desc's */
1418 static EXTR *orig_ext_syms; /* external symbols */
1420 /* Macros to convert an index into a given object within the original
1421 symbol table. */
1422 #define CHECK(num,max,str) \
1423 (((unsigned long) num > (unsigned long) max) ? out_of_bounds (num, max, str, __LINE__) : 0)
1425 #define ORIG_LINENUM(indx) (CHECK ((indx), orig_sym_hdr.cbLine, "line#"), (indx) + orig_linenum)
1426 #define ORIG_DENSE(indx) (CHECK ((indx), orig_sym_hdr.idnMax, "dense"), (indx) + orig_dense)
1427 #define ORIG_PROCS(indx) (CHECK ((indx), orig_sym_hdr.ipdMax, "procs"), (indx) + orig_procs)
1428 #define ORIG_FILES(indx) (CHECK ((indx), orig_sym_hdr.ifdMax, "funcs"), (indx) + orig_files)
1429 #define ORIG_LSYMS(indx) (CHECK ((indx), orig_sym_hdr.isymMax, "lsyms"), (indx) + orig_local_syms)
1430 #define ORIG_LSTRS(indx) (CHECK ((indx), orig_sym_hdr.issMax, "lstrs"), (indx) + orig_local_strs)
1431 #define ORIG_ESYMS(indx) (CHECK ((indx), orig_sym_hdr.iextMax, "esyms"), (indx) + orig_ext_syms)
1432 #define ORIG_ESTRS(indx) (CHECK ((indx), orig_sym_hdr.issExtMax, "estrs"), (indx) + orig_ext_strs)
1433 #define ORIG_OPT(indx) (CHECK ((indx), orig_sym_hdr.ioptMax, "opt"), (indx) + orig_opt_syms)
1434 #define ORIG_AUX(indx) (CHECK ((indx), orig_sym_hdr.iauxMax, "aux"), (indx) + orig_aux_syms)
1435 #define ORIG_RFDS(indx) (CHECK ((indx), orig_sym_hdr.crfd, "rfds"), (indx) + orig_rfds)
1437 /* Various other statics. */
1438 static HDRR symbolic_header; /* symbolic header */
1439 static efdr_t *cur_file_ptr = (efdr_t *) 0; /* current file desc. header */
1440 static PDR *cur_proc_ptr = (PDR *) 0; /* current procedure header */
1441 static SYMR *cur_oproc_begin = (SYMR *) 0; /* original proc. sym begin info */
1442 static SYMR *cur_oproc_end = (SYMR *) 0; /* original proc. sym end info */
1443 static PDR *cur_oproc_ptr = (PDR *) 0; /* current original procedure*/
1444 static thead_t *cur_tag_head = (thead_t *) 0;/* current tag head */
1445 static unsigned long file_offset = 0; /* current file offset */
1446 static unsigned long max_file_offset = 0; /* maximum file offset */
1447 static FILE *object_stream = (FILE *) 0; /* file desc. to output .o */
1448 static FILE *obj_in_stream = (FILE *) 0; /* file desc. to input .o */
1449 static const char *progname = (const char *) 0;/* program name for errors */
1450 static const char *input_name = "stdin"; /* name of input file */
1451 static char *object_name = (char *) 0; /* tmp. name of object file */
1452 static char *obj_in_name = (char *) 0; /* name of input object file */
1453 static char *cur_line_start = (char *) 0; /* current line read in */
1454 static char *cur_line_ptr = (char *) 0; /* ptr within current line */
1455 static unsigned cur_line_nbytes = 0; /* # bytes for current line */
1456 static unsigned cur_line_alloc = 0; /* # bytes total in buffer */
1457 static long line_number = 0; /* current input line number */
1458 static int debug = 0; /* trace functions */
1459 static int version = 0; /* print version # */
1460 static int verbose = 0;
1461 static int had_errors = 0; /* != 0 if errors were found */
1462 static int rename_output = 0; /* != 0 if rename output file*/
1463 static int delete_input = 0; /* != 0 if delete input after done */
1464 static int stabs_seen = 0; /* != 0 if stabs have been seen */
1467 /* Pseudo symbol to use when putting stabs into the symbol table. */
1468 #ifndef STABS_SYMBOL
1469 #define STABS_SYMBOL "@stabs"
1470 #endif
1472 static const char stabs_symbol[] = STABS_SYMBOL;
1475 /* Forward reference for functions. See the definition for more details. */
1477 static int out_of_bounds (symint_t, symint_t, const char *, int);
1478 static shash_t *hash_string (const char *, ptrdiff_t, shash_t **, symint_t *);
1479 static symint_t add_string (varray_t *, shash_t **, const char *, const char *,
1480 shash_t **);
1481 static symint_t add_local_symbol (const char *, const char *, st_t, sc_t,
1482 symint_t, symint_t);
1483 static symint_t add_ext_symbol (EXTR *, int);
1484 static symint_t add_aux_sym_symint (symint_t);
1485 static symint_t add_aux_sym_rndx (int, symint_t);
1486 static symint_t add_aux_sym_tir (type_info_t *, hash_state_t, thash_t **);
1487 static tag_t * get_tag (const char *, const char *, symint_t, bt_t);
1488 static void add_unknown_tag (tag_t *);
1489 static void add_procedure (const char *, const char *);
1490 static void initialize_init_file (void);
1491 static void add_file (const char *, const char *);
1492 static void add_bytes (varray_t *, char *, size_t);
1493 static void add_varray_page (varray_t *);
1494 static void update_headers (void);
1495 static void write_varray (varray_t *, off_t, const char *);
1496 static void write_object (void);
1497 static const char *st_to_string (st_t);
1498 static const char *sc_to_string (sc_t);
1499 static char *read_line (void);
1500 static void parse_input (void);
1501 static void mark_stabs (const char *);
1502 static void parse_begin (const char *);
1503 static void parse_bend (const char *);
1504 static void parse_def (const char *);
1505 static void parse_end (const char *);
1506 static void parse_ent (const char *);
1507 static void parse_file (const char *);
1508 static void parse_stabs_common (const char *, const char *, const char *);
1509 static void parse_stabs (const char *);
1510 static void parse_stabn (const char *);
1511 static page_t *read_seek (size_t, off_t, const char *);
1512 static void copy_object (void);
1514 static void catch_signal (int) ATTRIBUTE_NORETURN;
1515 static page_t *allocate_page (void);
1516 static page_t *allocate_multiple_pages (size_t);
1517 static void free_multiple_pages (page_t *, size_t);
1519 #ifndef MALLOC_CHECK
1520 static page_t *allocate_cluster (size_t);
1521 #endif
1523 static forward_t *allocate_forward (void);
1524 static scope_t *allocate_scope (void);
1525 static shash_t *allocate_shash (void);
1526 static tag_t *allocate_tag (void);
1527 static thash_t *allocate_thash (void);
1528 static thead_t *allocate_thead (void);
1529 static vlinks_t *allocate_vlinks (void);
1531 static void free_forward (forward_t *);
1532 static void free_scope (scope_t *);
1533 static void free_tag (tag_t *);
1534 static void free_thead (thead_t *);
1536 extern char *optarg;
1537 extern int optind;
1538 extern int opterr;
1540 /* List of assembler pseudo ops and beginning sequences that need
1541 special actions. Someday, this should be a hash table, and such,
1542 but for now a linear list of names and calls to memcmp will
1543 do...... */
1545 typedef struct _pseudo_ops {
1546 const char *const name; /* pseudo-op in ascii */
1547 const int len; /* length of name to compare */
1548 void (*const func) (const char *); /* function to handle line */
1549 } pseudo_ops_t;
1551 static const pseudo_ops_t pseudo_ops[] = {
1552 { "#.def", sizeof("#.def")-1, parse_def },
1553 { "#.begin", sizeof("#.begin")-1, parse_begin },
1554 { "#.bend", sizeof("#.bend")-1, parse_bend },
1555 { ".end", sizeof(".end")-1, parse_end },
1556 { ".ent", sizeof(".ent")-1, parse_ent },
1557 { ".file", sizeof(".file")-1, parse_file },
1558 { "#.stabs", sizeof("#.stabs")-1, parse_stabs },
1559 { "#.stabn", sizeof("#.stabn")-1, parse_stabn },
1560 { ".stabs", sizeof(".stabs")-1, parse_stabs },
1561 { ".stabn", sizeof(".stabn")-1, parse_stabn },
1562 { "#@stabs", sizeof("#@stabs")-1, mark_stabs },
1566 /* Command line options for getopt_long. */
1568 static const struct option options[] =
1570 { "version", 0, 0, 'V' },
1571 { "verbose", 0, 0, 'v' },
1572 { 0, 0, 0, 0 }
1575 /* Add a page to a varray object. */
1577 static void
1578 add_varray_page (varray_t *vp)
1580 vlinks_t *new_links = allocate_vlinks ();
1582 #ifdef MALLOC_CHECK
1583 if (vp->object_size > 1)
1584 new_links->datum = xcalloc (1, vp->object_size);
1585 else
1586 #endif
1587 new_links->datum = allocate_page ();
1589 alloc_counts[ (int) alloc_type_varray ].total_alloc++;
1590 alloc_counts[ (int) alloc_type_varray ].total_pages++;
1592 new_links->start_index = vp->num_allocated;
1593 vp->objects_last_page = 0;
1595 if (vp->first == (vlinks_t *) 0) /* first allocation? */
1596 vp->first = vp->last = new_links;
1597 else
1598 { /* 2nd or greater allocation */
1599 new_links->prev = vp->last;
1600 vp->last->next = new_links;
1601 vp->last = new_links;
1606 /* Compute hash code (from tree.c) */
1608 #define HASHBITS 30
1610 static shash_t *
1611 hash_string (const char *text, ptrdiff_t hash_len, shash_t **hash_tbl,
1612 symint_t *ret_hash_index)
1614 unsigned long hi;
1615 ptrdiff_t i;
1616 shash_t *ptr;
1617 int first_ch = *text;
1619 hi = hash_len;
1620 for (i = 0; i < hash_len; i++)
1621 hi = ((hi & 0x003fffff) * 613) + (text[i] & 0xff);
1623 hi &= (1 << HASHBITS) - 1;
1624 hi %= SHASH_SIZE;
1626 if (ret_hash_index != (symint_t *) 0)
1627 *ret_hash_index = hi;
1629 for (ptr = hash_tbl[hi]; ptr != (shash_t *) 0; ptr = ptr->next)
1630 if ((symint_t) hash_len == ptr->len
1631 && first_ch == ptr->string[0]
1632 && memcmp (text, ptr->string, hash_len) == 0)
1633 break;
1635 return ptr;
1639 /* Add a string (and null pad) to one of the string tables. A
1640 consequence of hashing strings, is that we don't let strings cross
1641 page boundaries. The extra nulls will be ignored. VP is a string
1642 virtual array, HASH_TBL a pointer to the hash table, the string
1643 starts at START and the position one byte after the string is given
1644 with END_P1, the resulting hash pointer is returned in RET_HASH. */
1646 static symint_t
1647 add_string (varray_t *vp, shash_t **hash_tbl, const char *start,
1648 const char *end_p1, shash_t **ret_hash)
1650 ptrdiff_t len = end_p1 - start;
1651 shash_t *hash_ptr;
1652 symint_t hi;
1654 if (len >= (ptrdiff_t) PAGE_USIZE)
1655 fatal ("string too big (%ld bytes)", (long) len);
1657 hash_ptr = hash_string (start, len, hash_tbl, &hi);
1658 if (hash_ptr == (shash_t *) 0)
1660 char *p;
1662 if (vp->objects_last_page + len >= (long) PAGE_USIZE)
1664 vp->num_allocated
1665 = ((vp->num_allocated + PAGE_USIZE - 1) / PAGE_USIZE) * PAGE_USIZE;
1666 add_varray_page (vp);
1669 hash_ptr = allocate_shash ();
1670 hash_ptr->next = hash_tbl[hi];
1671 hash_tbl[hi] = hash_ptr;
1673 hash_ptr->len = len;
1674 hash_ptr->indx = vp->num_allocated;
1675 hash_ptr->string = p = & vp->last->datum->byte[ vp->objects_last_page ];
1677 vp->objects_last_page += len+1;
1678 vp->num_allocated += len+1;
1680 while (len-- > 0)
1681 *p++ = *start++;
1683 *p = '\0';
1686 if (ret_hash != (shash_t **) 0)
1687 *ret_hash = hash_ptr;
1689 return hash_ptr->indx;
1693 /* Add a local symbol. The symbol string starts at STR_START and the
1694 first byte after it is marked by STR_END_P1. The symbol has type
1695 TYPE and storage class STORAGE and value VALUE. INDX is an index
1696 to local/aux. symbols. */
1698 static symint_t
1699 add_local_symbol (const char *str_start, const char *str_end_p1, st_t type,
1700 sc_t storage, symint_t value, symint_t indx)
1702 symint_t ret;
1703 SYMR *psym;
1704 scope_t *pscope;
1705 thead_t *ptag_head;
1706 tag_t *ptag;
1707 tag_t *ptag_next;
1708 varray_t *vp = &cur_file_ptr->symbols;
1709 int scope_delta = 0;
1710 shash_t *hash_ptr = (shash_t *) 0;
1712 if (vp->objects_last_page == vp->objects_per_page)
1713 add_varray_page (vp);
1715 psym = &vp->last->datum->sym[ vp->objects_last_page++ ];
1717 psym->value = value;
1718 psym->st = (unsigned) type;
1719 psym->sc = (unsigned) storage;
1720 psym->index = indx;
1721 psym->iss = (str_start == (const char *) 0)
1723 : add_string (&cur_file_ptr->strings,
1724 &cur_file_ptr->shash_head[0],
1725 str_start,
1726 str_end_p1,
1727 &hash_ptr);
1729 ret = vp->num_allocated++;
1731 if (MIPS_IS_STAB (psym))
1732 return ret;
1734 /* Save the symbol within the hash table if this is a static
1735 item, and it has a name. */
1736 if (hash_ptr != (shash_t *) 0
1737 && (type == st_Global || type == st_Static || type == st_Label
1738 || type == st_Proc || type == st_StaticProc))
1739 hash_ptr->sym_ptr = psym;
1741 /* push or pop a scope if appropriate. */
1742 switch (type)
1744 default:
1745 break;
1747 case st_File: /* beginning of file */
1748 case st_Proc: /* procedure */
1749 case st_StaticProc: /* static procedure */
1750 case st_Block: /* begin scope */
1751 pscope = allocate_scope ();
1752 pscope->prev = cur_file_ptr->cur_scope;
1753 pscope->lsym = psym;
1754 pscope->lnumber = ret;
1755 pscope->type = type;
1756 cur_file_ptr->cur_scope = pscope;
1758 if (type != st_File)
1759 scope_delta = 1;
1761 /* For every block type except file, struct, union, or
1762 enumeration blocks, push a level on the tag stack. We omit
1763 file types, so that tags can span file boundaries. */
1764 if (type != st_File && storage != sc_Info)
1766 ptag_head = allocate_thead ();
1767 ptag_head->first_tag = 0;
1768 ptag_head->prev = cur_tag_head;
1769 cur_tag_head = ptag_head;
1771 break;
1773 case st_End:
1774 pscope = cur_file_ptr->cur_scope;
1775 if (pscope == (scope_t *) 0)
1776 error ("internal error, too many st_End's");
1778 else
1780 st_t begin_type = (st_t) pscope->lsym->st;
1782 if (begin_type != st_File)
1783 scope_delta = -1;
1785 /* Except for file, structure, union, or enumeration end
1786 blocks remove all tags created within this scope. */
1787 if (begin_type != st_File && storage != sc_Info)
1789 ptag_head = cur_tag_head;
1790 cur_tag_head = ptag_head->prev;
1792 for (ptag = ptag_head->first_tag;
1793 ptag != (tag_t *) 0;
1794 ptag = ptag_next)
1796 if (ptag->forward_ref != (forward_t *) 0)
1797 add_unknown_tag (ptag);
1799 ptag_next = ptag->same_block;
1800 ptag->hash_ptr->tag_ptr = ptag->same_name;
1801 free_tag (ptag);
1804 free_thead (ptag_head);
1807 cur_file_ptr->cur_scope = pscope->prev;
1808 psym->index = pscope->lnumber; /* blk end gets begin sym # */
1810 if (storage != sc_Info)
1811 psym->iss = pscope->lsym->iss; /* blk end gets same name */
1813 if (begin_type == st_File || begin_type == st_Block)
1814 pscope->lsym->index = ret+1; /* block begin gets next sym # */
1816 /* Functions push two or more aux words as follows:
1817 1st word: index+1 of the end symbol
1818 2nd word: type of the function (plus any aux words needed).
1819 Also, tie the external pointer back to the function begin symbol. */
1820 else
1822 symint_t type;
1823 pscope->lsym->index = add_aux_sym_symint (ret+1);
1824 type = add_aux_sym_tir (&last_func_type_info,
1825 hash_no,
1826 &cur_file_ptr->thash_head[0]);
1827 if (last_func_eptr)
1829 last_func_eptr->ifd = cur_file_ptr->file_index;
1831 /* The index for an external st_Proc symbol is the index
1832 of the st_Proc symbol in the local symbol table. */
1833 last_func_eptr->asym.index = psym->index;
1837 free_scope (pscope);
1841 cur_file_ptr->nested_scopes += scope_delta;
1843 if (debug && type != st_File
1844 && (debug > 2 || type == st_Block || type == st_End
1845 || type == st_Proc || type == st_StaticProc))
1847 const char *sc_str = sc_to_string (storage);
1848 const char *st_str = st_to_string (type);
1849 int depth = cur_file_ptr->nested_scopes + (scope_delta < 0);
1851 fprintf (stderr,
1852 "\tlsym\tv= %10ld, depth= %2d, sc= %-12s",
1853 value, depth, sc_str);
1855 if (str_start && str_end_p1 - str_start > 0)
1856 fprintf (stderr, " st= %-11s name= %.*s\n",
1857 st_str, (int) (str_end_p1 - str_start), str_start);
1858 else
1860 size_t len = strlen (st_str);
1861 fprintf (stderr, " st= %.*s\n", (int) (len-1), st_str);
1865 return ret;
1869 /* Add an external symbol with symbol pointer ESYM and file index
1870 IFD. */
1872 static symint_t
1873 add_ext_symbol (EXTR *esym, int ifd)
1875 const char *str_start; /* first byte in string */
1876 const char *str_end_p1; /* first byte after string */
1877 EXTR *psym;
1878 varray_t *vp = &ext_symbols;
1879 shash_t *hash_ptr = (shash_t *) 0;
1881 str_start = ORIG_ESTRS (esym->asym.iss);
1882 str_end_p1 = str_start + strlen (str_start);
1884 if (debug > 1)
1886 long value = esym->asym.value;
1887 const char *sc_str = sc_to_string ((sc_t) esym->asym.sc);
1888 const char *st_str = st_to_string ((st_t) esym->asym.st);
1890 fprintf (stderr,
1891 "\tesym\tv= %10ld, ifd= %2d, sc= %-12s",
1892 value, ifd, sc_str);
1894 if (str_start && str_end_p1 - str_start > 0)
1895 fprintf (stderr, " st= %-11s name= %.*s\n",
1896 st_str, (int) (str_end_p1 - str_start), str_start);
1897 else
1898 fprintf (stderr, " st= %s\n", st_str);
1901 if (vp->objects_last_page == vp->objects_per_page)
1902 add_varray_page (vp);
1904 psym = &vp->last->datum->esym[ vp->objects_last_page++ ];
1906 *psym = *esym;
1907 psym->ifd = ifd;
1908 psym->asym.index = indexNil;
1909 psym->asym.iss = (str_start == (const char *) 0)
1911 : add_string (&ext_strings,
1912 &ext_str_hash[0],
1913 str_start,
1914 str_end_p1,
1915 &hash_ptr);
1917 hash_ptr->esym_ptr = psym;
1918 return vp->num_allocated++;
1922 /* Add an auxiliary symbol (passing a symint). */
1924 static symint_t
1925 add_aux_sym_symint (symint_t aux_word)
1927 AUXU *aux_ptr;
1928 efdr_t *file_ptr = cur_file_ptr;
1929 varray_t *vp = &file_ptr->aux_syms;
1931 if (vp->objects_last_page == vp->objects_per_page)
1932 add_varray_page (vp);
1934 aux_ptr = &vp->last->datum->aux[ vp->objects_last_page++ ];
1935 aux_ptr->isym = aux_word;
1937 return vp->num_allocated++;
1941 /* Add an auxiliary symbol (passing a file/symbol index combo). */
1943 static symint_t
1944 add_aux_sym_rndx (int file_index, symint_t sym_index)
1946 AUXU *aux_ptr;
1947 efdr_t *file_ptr = cur_file_ptr;
1948 varray_t *vp = &file_ptr->aux_syms;
1950 if (vp->objects_last_page == vp->objects_per_page)
1951 add_varray_page (vp);
1953 aux_ptr = &vp->last->datum->aux[ vp->objects_last_page++ ];
1954 aux_ptr->rndx.rfd = file_index;
1955 aux_ptr->rndx.index = sym_index;
1957 return vp->num_allocated++;
1961 /* Add an auxiliary symbol (passing the basic type and possibly
1962 type qualifiers). */
1964 static symint_t
1965 add_aux_sym_tir (type_info_t *t, hash_state_t state, thash_t **hash_tbl)
1967 AUXU *aux_ptr;
1968 efdr_t *file_ptr = cur_file_ptr;
1969 varray_t *vp = &file_ptr->aux_syms;
1970 static AUXU init_aux;
1971 symint_t ret;
1972 int i;
1973 AUXU aux;
1975 aux = init_aux;
1976 aux.ti.bt = (int) t->basic_type;
1977 aux.ti.continued = 0;
1978 aux.ti.fBitfield = t->bitfield;
1980 aux.ti.tq0 = (int) t->type_qualifiers[0];
1981 aux.ti.tq1 = (int) t->type_qualifiers[1];
1982 aux.ti.tq2 = (int) t->type_qualifiers[2];
1983 aux.ti.tq3 = (int) t->type_qualifiers[3];
1984 aux.ti.tq4 = (int) t->type_qualifiers[4];
1985 aux.ti.tq5 = (int) t->type_qualifiers[5];
1988 /* For anything that adds additional information, we must not hash,
1989 so check here, and reset our state. */
1991 if (state != hash_no
1992 && (t->type_qualifiers[0] == tq_Array
1993 || t->type_qualifiers[1] == tq_Array
1994 || t->type_qualifiers[2] == tq_Array
1995 || t->type_qualifiers[3] == tq_Array
1996 || t->type_qualifiers[4] == tq_Array
1997 || t->type_qualifiers[5] == tq_Array
1998 || t->basic_type == bt_Struct
1999 || t->basic_type == bt_Union
2000 || t->basic_type == bt_Enum
2001 || t->bitfield
2002 || t->num_dims > 0))
2003 state = hash_no;
2005 /* See if we can hash this type, and save some space, but some types
2006 can't be hashed (because they contain arrays or continuations),
2007 and others can be put into the hash list, but cannot use existing
2008 types because other aux entries precede this one. */
2010 if (state != hash_no)
2012 thash_t *hash_ptr;
2013 symint_t hi;
2015 hi = aux.isym & ((1 << HASHBITS) - 1);
2016 hi %= THASH_SIZE;
2018 for (hash_ptr = hash_tbl[hi];
2019 hash_ptr != (thash_t *) 0;
2020 hash_ptr = hash_ptr->next)
2022 if (aux.isym == hash_ptr->type.isym)
2023 break;
2026 if (hash_ptr != (thash_t *) 0 && state == hash_yes)
2027 return hash_ptr->indx;
2029 if (hash_ptr == (thash_t *) 0)
2031 hash_ptr = allocate_thash ();
2032 hash_ptr->next = hash_tbl[hi];
2033 hash_ptr->type = aux;
2034 hash_ptr->indx = vp->num_allocated;
2035 hash_tbl[hi] = hash_ptr;
2039 /* Everything is set up, add the aux symbol. */
2040 if (vp->objects_last_page == vp->objects_per_page)
2041 add_varray_page (vp);
2043 aux_ptr = &vp->last->datum->aux[ vp->objects_last_page++ ];
2044 *aux_ptr = aux;
2046 ret = vp->num_allocated++;
2048 /* Add bitfield length if it exists.
2050 NOTE: Mips documentation claims bitfield goes at the end of the
2051 AUX record, but the DECstation compiler emits it here.
2052 (This would only make a difference for enum bitfields.)
2054 Also note: We use the last size given since gcc may emit 2
2055 for an enum bitfield. */
2057 if (t->bitfield)
2058 (void) add_aux_sym_symint ((symint_t) t->sizes[t->num_sizes-1]);
2061 /* Add tag information if needed. Structure, union, and enum
2062 references add 2 aux symbols: a [file index, symbol index]
2063 pointer to the structure type, and the current file index. */
2065 if (t->basic_type == bt_Struct
2066 || t->basic_type == bt_Union
2067 || t->basic_type == bt_Enum)
2069 symint_t file_index = t->tag_ptr->ifd;
2070 symint_t sym_index = t->tag_ptr->indx;
2072 if (t->unknown_tag)
2074 (void) add_aux_sym_rndx (ST_RFDESCAPE, sym_index);
2075 (void) add_aux_sym_symint ((symint_t)-1);
2077 else if (sym_index != indexNil)
2079 (void) add_aux_sym_rndx (ST_RFDESCAPE, sym_index);
2080 (void) add_aux_sym_symint (file_index);
2082 else
2084 forward_t *forward_ref = allocate_forward ();
2086 forward_ref->type_ptr = aux_ptr;
2087 forward_ref->next = t->tag_ptr->forward_ref;
2088 t->tag_ptr->forward_ref = forward_ref;
2090 (void) add_aux_sym_rndx (ST_RFDESCAPE, sym_index);
2091 forward_ref->index_ptr
2092 = &vp->last->datum->aux[ vp->objects_last_page - 1];
2094 (void) add_aux_sym_symint (file_index);
2095 forward_ref->ifd_ptr
2096 = &vp->last->datum->aux[ vp->objects_last_page - 1];
2100 /* Add information about array bounds if they exist. */
2101 for (i = 0; i < t->num_dims; i++)
2103 (void) add_aux_sym_rndx (ST_RFDESCAPE,
2104 cur_file_ptr->int_type);
2106 (void) add_aux_sym_symint (cur_file_ptr->file_index); /* file index*/
2107 (void) add_aux_sym_symint ((symint_t) 0); /* low bound */
2108 (void) add_aux_sym_symint (t->dimensions[i] - 1); /* high bound*/
2109 (void) add_aux_sym_symint ((t->dimensions[i] == 0) /* stride */
2111 : (t->sizes[i] * 8) / t->dimensions[i]);
2114 /* NOTE: Mips documentation claims that the bitfield width goes here.
2115 But it needs to be emitted earlier. */
2117 return ret;
2121 /* Add a tag to the tag table (unless it already exists). */
2123 static tag_t *
2124 get_tag (const char *tag_start, /* 1st byte of tag name */
2125 const char *tag_end_p1, /* 1st byte after tag name */
2126 symint_t indx, /* index of tag start block */
2127 bt_t basic_type) /* bt_Struct, bt_Union, or bt_Enum */
2130 shash_t *hash_ptr;
2131 tag_t *tag_ptr;
2132 hash_ptr = hash_string (tag_start,
2133 tag_end_p1 - tag_start,
2134 &tag_hash[0],
2135 (symint_t *) 0);
2137 if (hash_ptr != (shash_t *) 0
2138 && hash_ptr->tag_ptr != (tag_t *) 0)
2140 tag_ptr = hash_ptr->tag_ptr;
2141 if (indx != indexNil)
2143 tag_ptr->basic_type = basic_type;
2144 tag_ptr->ifd = cur_file_ptr->file_index;
2145 tag_ptr->indx = indx;
2147 return tag_ptr;
2150 (void) add_string (&tag_strings,
2151 &tag_hash[0],
2152 tag_start,
2153 tag_end_p1,
2154 &hash_ptr);
2156 tag_ptr = allocate_tag ();
2157 tag_ptr->forward_ref = (forward_t *) 0;
2158 tag_ptr->hash_ptr = hash_ptr;
2159 tag_ptr->same_name = hash_ptr->tag_ptr;
2160 tag_ptr->basic_type = basic_type;
2161 tag_ptr->indx = indx;
2162 tag_ptr->ifd = (indx == indexNil
2163 ? (symint_t) -1 : cur_file_ptr->file_index);
2164 tag_ptr->same_block = cur_tag_head->first_tag;
2166 cur_tag_head->first_tag = tag_ptr;
2167 hash_ptr->tag_ptr = tag_ptr;
2169 return tag_ptr;
2173 /* Add an unknown {struct, union, enum} tag. */
2175 static void
2176 add_unknown_tag (tag_t *ptag)
2178 shash_t *hash_ptr = ptag->hash_ptr;
2179 char *name_start = hash_ptr->string;
2180 char *name_end_p1 = name_start + hash_ptr->len;
2181 forward_t *f_next = ptag->forward_ref;
2182 forward_t *f_cur;
2183 int sym_index;
2184 int file_index = cur_file_ptr->file_index;
2186 if (debug > 1)
2188 const char *agg_type = "{unknown aggregate type}";
2189 switch (ptag->basic_type)
2191 case bt_Struct: agg_type = "struct"; break;
2192 case bt_Union: agg_type = "union"; break;
2193 case bt_Enum: agg_type = "enum"; break;
2194 default: break;
2197 fprintf (stderr, "unknown %s %.*s found\n",
2198 agg_type, (int) hash_ptr->len, name_start);
2201 sym_index = add_local_symbol (name_start,
2202 name_end_p1,
2203 st_Block,
2204 sc_Info,
2205 (symint_t) 0,
2206 (symint_t) 0);
2208 (void) add_local_symbol (name_start,
2209 name_end_p1,
2210 st_End,
2211 sc_Info,
2212 (symint_t) 0,
2213 (symint_t) 0);
2215 while (f_next != (forward_t *) 0)
2217 f_cur = f_next;
2218 f_next = f_next->next;
2220 f_cur->ifd_ptr->isym = file_index;
2221 f_cur->index_ptr->rndx.index = sym_index;
2223 free_forward (f_cur);
2226 return;
2230 /* Add a procedure to the current file's list of procedures, and record
2231 this is the current procedure. If the assembler created a PDR for
2232 this procedure, use that to initialize the current PDR. */
2234 static void
2235 add_procedure (const char *func_start, /* 1st byte of func name */
2236 const char *func_end_p1) /* 1st byte after func name */
2238 PDR *new_proc_ptr;
2239 efdr_t *file_ptr = cur_file_ptr;
2240 varray_t *vp = &file_ptr->procs;
2241 symint_t value = 0;
2242 st_t proc_type = st_Proc;
2243 shash_t *shash_ptr = hash_string (func_start,
2244 func_end_p1 - func_start,
2245 &orig_str_hash[0],
2246 (symint_t *) 0);
2248 if (debug)
2249 fputc ('\n', stderr);
2251 if (vp->objects_last_page == vp->objects_per_page)
2252 add_varray_page (vp);
2254 cur_proc_ptr = new_proc_ptr = &vp->last->datum->proc[ vp->objects_last_page++ ];
2256 vp->num_allocated++;
2259 /* Did the assembler create this procedure? If so, get the PDR information. */
2260 cur_oproc_ptr = (PDR *) 0;
2261 if (shash_ptr != (shash_t *) 0)
2263 PDR *old_proc_ptr = shash_ptr->proc_ptr;
2264 SYMR *sym_ptr = shash_ptr->sym_ptr;
2266 if (old_proc_ptr != (PDR *) 0
2267 && sym_ptr != (SYMR *) 0
2268 && ((st_t) sym_ptr->st == st_Proc || (st_t) sym_ptr->st == st_StaticProc))
2270 cur_oproc_begin = sym_ptr;
2271 cur_oproc_end = shash_ptr->end_ptr;
2272 value = sym_ptr->value;
2274 cur_oproc_ptr = old_proc_ptr;
2275 proc_type = (st_t) sym_ptr->st;
2276 *new_proc_ptr = *old_proc_ptr; /* initialize */
2280 if (cur_oproc_ptr == (PDR *) 0)
2281 error ("did not find a PDR block for %.*s",
2282 (int) (func_end_p1 - func_start), func_start);
2284 /* Determine the start of symbols. */
2285 new_proc_ptr->isym = file_ptr->symbols.num_allocated;
2287 /* Push the start of the function. */
2288 (void) add_local_symbol (func_start, func_end_p1,
2289 proc_type, sc_Text,
2290 value,
2291 (symint_t) 0);
2295 /* Initialize the init_file structure. */
2297 static void
2298 initialize_init_file (void)
2300 union {
2301 unsigned char c[4];
2302 int i;
2303 } endian_test;
2305 memset (&init_file, 0, sizeof (init_file));
2307 init_file.fdr.lang = langC;
2308 init_file.fdr.fMerge = 1;
2309 init_file.fdr.glevel = GLEVEL_2;
2311 /* mips-tfile doesn't attempt to perform byte swapping and always writes
2312 out integers in its native ordering. For cross-compilers, this need
2313 not be the same as either the host or the target. The simplest thing
2314 to do is skip the configury and perform an introspective test. */
2315 /* ??? Despite the name, mips-tfile is currently only used on alpha/Tru64
2316 and would/may require significant work to be used in cross-compiler
2317 configurations, so we could simply admit defeat and hard code this as
2318 little-endian, i.e. init_file.fdr.fBigendian = 0. */
2319 endian_test.i = 1;
2320 if (endian_test.c[3])
2321 init_file.fdr.fBigendian = 1;
2323 INITIALIZE_VARRAY (&init_file.strings, char);
2324 INITIALIZE_VARRAY (&init_file.symbols, SYMR);
2325 INITIALIZE_VARRAY (&init_file.procs, PDR);
2326 INITIALIZE_VARRAY (&init_file.aux_syms, AUXU);
2328 init_file_initialized = 1;
2331 /* Add a new filename, and set up all of the file relative
2332 virtual arrays (strings, symbols, aux syms, etc.). Record
2333 where the current file structure lives. */
2335 static void
2336 add_file (const char *file_start, /* first byte in string */
2337 const char *file_end_p1) /* first byte after string */
2339 static char zero_bytes[2] = { '\0', '\0' };
2341 ptrdiff_t len = file_end_p1 - file_start;
2342 int first_ch = *file_start;
2343 efdr_t *file_ptr;
2345 if (debug)
2346 fprintf (stderr, "\tfile\t%.*s\n", (int) len, file_start);
2348 /* See if the file has already been created. */
2349 for (file_ptr = first_file;
2350 file_ptr != (efdr_t *) 0;
2351 file_ptr = file_ptr->next_file)
2353 if (first_ch == file_ptr->name[0]
2354 && file_ptr->name[len] == '\0'
2355 && memcmp (file_start, file_ptr->name, len) == 0)
2357 cur_file_ptr = file_ptr;
2358 break;
2362 /* If this is a new file, create it. */
2363 if (file_ptr == (efdr_t *) 0)
2365 if (file_desc.objects_last_page == file_desc.objects_per_page)
2366 add_varray_page (&file_desc);
2368 if (! init_file_initialized)
2369 initialize_init_file ();
2371 file_ptr = cur_file_ptr
2372 = &file_desc.last->datum->file[ file_desc.objects_last_page++ ];
2373 *file_ptr = init_file;
2375 file_ptr->file_index = file_desc.num_allocated++;
2377 /* Allocate the string hash table. */
2378 file_ptr->shash_head = (shash_t **) allocate_page ();
2380 /* Make sure 0 byte in string table is null */
2381 add_string (&file_ptr->strings,
2382 &file_ptr->shash_head[0],
2383 &zero_bytes[0],
2384 &zero_bytes[0],
2385 (shash_t **) 0);
2387 if (file_end_p1 - file_start > (long) PAGE_USIZE-2)
2388 fatal ("filename goes over one page boundary");
2390 /* Push the start of the filename. We assume that the filename
2391 will be stored at string offset 1. */
2392 (void) add_local_symbol (file_start, file_end_p1, st_File, sc_Text,
2393 (symint_t) 0, (symint_t) 0);
2394 file_ptr->fdr.rss = 1;
2395 file_ptr->name = &file_ptr->strings.last->datum->byte[1];
2396 file_ptr->name_len = file_end_p1 - file_start;
2398 /* Update the linked list of file descriptors. */
2399 *last_file_ptr = file_ptr;
2400 last_file_ptr = &file_ptr->next_file;
2402 /* Add void & int types to the file (void should be first to catch
2403 errant 0's within the index fields). */
2404 file_ptr->void_type = add_aux_sym_tir (&void_type_info,
2405 hash_yes,
2406 &cur_file_ptr->thash_head[0]);
2408 file_ptr->int_type = add_aux_sym_tir (&int_type_info,
2409 hash_yes,
2410 &cur_file_ptr->thash_head[0]);
2415 /* Add a stream of random bytes to a varray. */
2417 static void
2418 add_bytes (varray_t *vp, /* virtual array to add too */
2419 char *input_ptr, /* start of the bytes */
2420 size_t nitems) /* # items to move */
2422 size_t move_items;
2423 size_t move_bytes;
2424 char *ptr;
2426 while (nitems > 0)
2428 if (vp->objects_last_page >= vp->objects_per_page)
2429 add_varray_page (vp);
2431 ptr = &vp->last->datum->byte[ vp->objects_last_page * vp->object_size ];
2432 move_items = vp->objects_per_page - vp->objects_last_page;
2433 if (move_items > nitems)
2434 move_items = nitems;
2436 move_bytes = move_items * vp->object_size;
2437 nitems -= move_items;
2439 if (move_bytes >= 32)
2441 (void) memcpy (ptr, input_ptr, move_bytes);
2442 input_ptr += move_bytes;
2444 else
2446 while (move_bytes-- > 0)
2447 *ptr++ = *input_ptr++;
2453 /* Convert storage class to string. */
2455 static const char *
2456 sc_to_string (sc_t storage_class)
2458 switch (storage_class)
2460 case sc_Nil: return "Nil,";
2461 case sc_Text: return "Text,";
2462 case sc_Data: return "Data,";
2463 case sc_Bss: return "Bss,";
2464 case sc_Register: return "Register,";
2465 case sc_Abs: return "Abs,";
2466 case sc_Undefined: return "Undefined,";
2467 case sc_CdbLocal: return "CdbLocal,";
2468 case sc_Bits: return "Bits,";
2469 case sc_CdbSystem: return "CdbSystem,";
2470 case sc_RegImage: return "RegImage,";
2471 case sc_Info: return "Info,";
2472 case sc_UserStruct: return "UserStruct,";
2473 case sc_SData: return "SData,";
2474 case sc_SBss: return "SBss,";
2475 case sc_RData: return "RData,";
2476 case sc_Var: return "Var,";
2477 case sc_Common: return "Common,";
2478 case sc_SCommon: return "SCommon,";
2479 case sc_VarRegister: return "VarRegister,";
2480 case sc_Variant: return "Variant,";
2481 case sc_SUndefined: return "SUndefined,";
2482 case sc_Init: return "Init,";
2483 case sc_Max: return "Max,";
2486 return "???,";
2490 /* Convert symbol type to string. */
2492 static const char *
2493 st_to_string (st_t symbol_type)
2495 switch (symbol_type)
2497 case st_Nil: return "Nil,";
2498 case st_Global: return "Global,";
2499 case st_Static: return "Static,";
2500 case st_Param: return "Param,";
2501 case st_Local: return "Local,";
2502 case st_Label: return "Label,";
2503 case st_Proc: return "Proc,";
2504 case st_Block: return "Block,";
2505 case st_End: return "End,";
2506 case st_Member: return "Member,";
2507 case st_Typedef: return "Typedef,";
2508 case st_File: return "File,";
2509 case st_RegReloc: return "RegReloc,";
2510 case st_Forward: return "Forward,";
2511 case st_StaticProc: return "StaticProc,";
2512 case st_Constant: return "Constant,";
2513 case st_Str: return "String,";
2514 case st_Number: return "Number,";
2515 case st_Expr: return "Expr,";
2516 case st_Type: return "Type,";
2517 case st_Max: return "Max,";
2520 return "???,";
2524 /* Read a line from standard input, and return the start of the buffer
2525 (which is grows if the line is too big). We split lines at the
2526 semi-colon, and return each logical line independently. */
2528 static char *
2529 read_line (void)
2531 static int line_split_p = 0;
2532 int string_p = 0;
2533 int comment_p = 0;
2534 int ch;
2535 char *ptr;
2537 if (cur_line_start == (char *) 0)
2538 { /* allocate initial page */
2539 cur_line_start = (char *) allocate_page ();
2540 cur_line_alloc = PAGE_SIZE;
2543 if (!line_split_p)
2544 line_number++;
2546 line_split_p = 0;
2547 cur_line_nbytes = 0;
2549 for (ptr = cur_line_start; (ch = getchar ()) != EOF; *ptr++ = ch)
2551 if (++cur_line_nbytes >= cur_line_alloc-1)
2553 int num_pages = cur_line_alloc / PAGE_SIZE;
2554 char *old_buffer = cur_line_start;
2556 cur_line_alloc += PAGE_SIZE;
2557 cur_line_start = (char *) allocate_multiple_pages (num_pages+1);
2558 memcpy (cur_line_start, old_buffer, num_pages * PAGE_SIZE);
2560 ptr = cur_line_start + cur_line_nbytes - 1;
2563 if (ch == '\n')
2565 *ptr++ = '\n';
2566 *ptr = '\0';
2567 cur_line_ptr = cur_line_start;
2568 return cur_line_ptr;
2571 else if (ch == '\0')
2572 error ("null character found in input");
2574 else if (!comment_p)
2576 if (ch == '"')
2577 string_p = !string_p;
2579 else if (ch == '#')
2580 comment_p++;
2582 else if (ch == ';' && !string_p)
2584 line_split_p = 1;
2585 *ptr++ = '\n';
2586 *ptr = '\0';
2587 cur_line_ptr = cur_line_start;
2588 return cur_line_ptr;
2593 if (ferror (stdin))
2594 pfatal_with_name (input_name);
2596 cur_line_ptr = (char *) 0;
2597 return (char *) 0;
2601 /* Parse #.begin directives which have a label as the first argument
2602 which gives the location of the start of the block. */
2604 static void
2605 parse_begin (const char *start)
2607 const char *end_p1; /* end of label */
2608 int ch;
2609 shash_t *hash_ptr; /* hash pointer to lookup label */
2611 if (cur_file_ptr == (efdr_t *) 0)
2613 error ("#.begin directive without a preceding .file directive");
2614 return;
2617 if (cur_proc_ptr == (PDR *) 0)
2619 error ("#.begin directive without a preceding .ent directive");
2620 return;
2623 for (end_p1 = start; (ch = *end_p1) != '\0' && !ISSPACE (ch); end_p1++)
2626 hash_ptr = hash_string (start,
2627 end_p1 - start,
2628 &orig_str_hash[0],
2629 (symint_t *) 0);
2631 if (hash_ptr == (shash_t *) 0)
2633 error ("label %.*s not found for #.begin",
2634 (int) (end_p1 - start), start);
2635 return;
2638 if (cur_oproc_begin == (SYMR *) 0)
2640 error ("procedure table %.*s not found for #.begin",
2641 (int) (end_p1 - start), start);
2642 return;
2645 (void) add_local_symbol ((const char *) 0, (const char *) 0,
2646 st_Block, sc_Text,
2647 (symint_t) hash_ptr->sym_ptr->value - cur_oproc_begin->value,
2648 (symint_t) 0);
2652 /* Parse #.bend directives which have a label as the first argument
2653 which gives the location of the end of the block. */
2655 static void
2656 parse_bend (const char *start)
2658 const char *end_p1; /* end of label */
2659 int ch;
2660 shash_t *hash_ptr; /* hash pointer to lookup label */
2662 if (cur_file_ptr == (efdr_t *) 0)
2664 error ("#.begin directive without a preceding .file directive");
2665 return;
2668 if (cur_proc_ptr == (PDR *) 0)
2670 error ("#.bend directive without a preceding .ent directive");
2671 return;
2674 for (end_p1 = start; (ch = *end_p1) != '\0' && !ISSPACE (ch); end_p1++)
2677 hash_ptr = hash_string (start,
2678 end_p1 - start,
2679 &orig_str_hash[0],
2680 (symint_t *) 0);
2682 if (hash_ptr == (shash_t *) 0)
2684 error ("label %.*s not found for #.bend", (int) (end_p1 - start), start);
2685 return;
2688 if (cur_oproc_begin == (SYMR *) 0)
2690 error ("procedure table %.*s not found for #.bend",
2691 (int) (end_p1 - start), start);
2692 return;
2695 (void) add_local_symbol ((const char *) 0, (const char *) 0,
2696 st_End, sc_Text,
2697 (symint_t) hash_ptr->sym_ptr->value - cur_oproc_begin->value,
2698 (symint_t) 0);
2702 /* Parse #.def directives, which are contain standard COFF subdirectives
2703 to describe the debugging format. These subdirectives include:
2705 .scl specify storage class
2706 .val specify a value
2707 .endef specify end of COFF directives
2708 .type specify the type
2709 .size specify the size of an array
2710 .dim specify an array dimension
2711 .tag specify a tag for a struct, union, or enum. */
2713 static void
2714 parse_def (const char *name_start)
2716 const char *dir_start; /* start of current directive*/
2717 const char *dir_end_p1; /* end+1 of current directive*/
2718 const char *arg_start; /* start of current argument */
2719 const char *arg_end_p1; /* end+1 of current argument */
2720 const char *name_end_p1; /* end+1 of label */
2721 const char *tag_start = 0; /* start of tag name */
2722 const char *tag_end_p1 = 0; /* end+1 of tag name */
2723 sc_t storage_class = sc_Nil;
2724 st_t symbol_type = st_Nil;
2725 type_info_t t;
2726 EXTR *eptr = (EXTR *) 0; /* ext. sym equivalent to def*/
2727 int is_function = 0; /* != 0 if function */
2728 symint_t value = 0;
2729 symint_t indx = cur_file_ptr->void_type;
2730 int error_line = 0;
2731 symint_t arg_number;
2732 symint_t temp_array[ N_TQ ];
2733 int arg_was_number;
2734 int ch, i;
2735 ptrdiff_t len;
2737 static int inside_enumeration = 0; /* is this an enumeration? */
2740 /* Initialize the type information. */
2741 t = type_info_init;
2744 /* Search for the end of the name being defined. */
2745 /* Allow spaces and such in names for G++ templates, which produce stabs
2746 that look like:
2748 #.def SMANIP<long unsigned int>; .scl 10; .type 0x8; .size 8; .endef */
2750 for (name_end_p1 = name_start; (ch = *name_end_p1) != ';' && ch != '\0'; name_end_p1++)
2753 if (ch == '\0')
2755 error_line = __LINE__;
2756 goto bomb_out;
2759 /* Parse the remaining subdirectives now. */
2760 dir_start = name_end_p1+1;
2761 for (;;)
2763 while ((ch = *dir_start) == ' ' || ch == '\t')
2764 ++dir_start;
2766 if (ch != '.')
2768 error_line = __LINE__;
2769 goto bomb_out;
2772 /* Are we done? */
2773 if (dir_start[1] == 'e'
2774 && memcmp (dir_start, ".endef", sizeof (".endef")-1) == 0)
2775 break;
2777 /* Pick up the subdirective now. */
2778 for (dir_end_p1 = dir_start+1;
2779 (ch = *dir_end_p1) != ' ' && ch != '\t';
2780 dir_end_p1++)
2782 if (ch == '\0' || ISSPACE (ch))
2784 error_line = __LINE__;
2785 goto bomb_out;
2789 /* Pick up the subdirective argument now. */
2790 arg_was_number = arg_number = 0;
2791 arg_end_p1 = 0;
2792 arg_start = dir_end_p1+1;
2793 ch = *arg_start;
2794 while (ch == ' ' || ch == '\t')
2795 ch = *++arg_start;
2797 if (ISDIGIT (ch) || ch == '-' || ch == '+')
2799 int ch2;
2800 arg_number = strtol (arg_start, (char **) &arg_end_p1, 0);
2801 /* It's only a number if followed by ';' or ','. */
2802 if (arg_end_p1 != arg_start && (((ch2 = *arg_end_p1) == ';') || ch2 == ','))
2803 arg_was_number++;
2806 else if (ch == '\0' || ISSPACE (ch))
2808 error_line = __LINE__;
2809 goto bomb_out;
2812 if (!arg_was_number)
2814 /* Allow spaces and such in names for G++ templates. */
2815 for (arg_end_p1 = arg_start+1;
2816 (ch = *arg_end_p1) != ';' && ch != '\0';
2817 arg_end_p1++)
2820 if (ch == '\0')
2822 error_line = __LINE__;
2823 goto bomb_out;
2827 /* Classify the directives now. */
2828 len = dir_end_p1 - dir_start;
2829 switch (dir_start[1])
2831 default:
2832 error_line = __LINE__;
2833 goto bomb_out;
2835 case 'd':
2836 if (len == sizeof (".dim")-1
2837 && memcmp (dir_start, ".dim", sizeof (".dim")-1) == 0
2838 && arg_was_number)
2840 symint_t *t_ptr = &temp_array[ N_TQ-1 ];
2842 *t_ptr = arg_number;
2843 while (*arg_end_p1 == ',' && arg_was_number)
2845 arg_start = arg_end_p1+1;
2846 ch = *arg_start;
2847 while (ch == ' ' || ch == '\t')
2848 ch = *++arg_start;
2850 arg_was_number = 0;
2851 if (ISDIGIT (ch) || ch == '-' || ch == '+')
2853 int ch2;
2854 arg_number = strtol (arg_start, (char **) &arg_end_p1, 0);
2855 if (arg_end_p1 != arg_start && (((ch2 = *arg_end_p1) == ';') || ch2 == ','))
2856 arg_was_number++;
2858 if (t_ptr == &temp_array[0])
2860 error_line = __LINE__;
2861 goto bomb_out;
2864 *--t_ptr = arg_number;
2868 /* Reverse order of dimensions. */
2869 while (t_ptr <= &temp_array[ N_TQ-1 ])
2871 if (t.num_dims >= N_TQ-1)
2873 error_line = __LINE__;
2874 goto bomb_out;
2877 t.dimensions[ t.num_dims++ ] = *t_ptr++;
2879 break;
2881 else
2883 error_line = __LINE__;
2884 goto bomb_out;
2888 case 's':
2889 if (len == sizeof (".scl")-1
2890 && memcmp (dir_start, ".scl", sizeof (".scl")-1) == 0
2891 && arg_was_number
2892 && arg_number < ((symint_t) C_MAX))
2894 /* If the symbol is a static or external, we have
2895 already gotten the appropriate type and class, so
2896 make sure we don't override those values. This is
2897 needed because there are some type and classes that
2898 are not in COFF, such as short data, etc. */
2899 if (symbol_type == st_Nil)
2901 symbol_type = map_coff_sym_type[arg_number];
2902 storage_class = map_coff_storage [arg_number];
2904 break;
2907 else if (len == sizeof (".size")-1
2908 && memcmp (dir_start, ".size", sizeof (".size")-1) == 0
2909 && arg_was_number)
2911 symint_t *t_ptr = &temp_array[ N_TQ-1 ];
2913 *t_ptr = arg_number;
2914 while (*arg_end_p1 == ',' && arg_was_number)
2916 arg_start = arg_end_p1+1;
2917 ch = *arg_start;
2918 while (ch == ' ' || ch == '\t')
2919 ch = *++arg_start;
2921 arg_was_number = 0;
2922 if (ISDIGIT (ch) || ch == '-' || ch == '+')
2924 int ch2;
2925 arg_number = strtol (arg_start, (char **) &arg_end_p1, 0);
2926 if (arg_end_p1 != arg_start && (((ch2 = *arg_end_p1) == ';') || ch2 == ','))
2927 arg_was_number++;
2929 if (t_ptr == &temp_array[0])
2931 error_line = __LINE__;
2932 goto bomb_out;
2935 *--t_ptr = arg_number;
2939 /* Reverse order of sizes. */
2940 while (t_ptr <= &temp_array[ N_TQ-1 ])
2942 if (t.num_sizes >= N_TQ-1)
2944 error_line = __LINE__;
2945 goto bomb_out;
2948 t.sizes[ t.num_sizes++ ] = *t_ptr++;
2950 break;
2953 else
2955 error_line = __LINE__;
2956 goto bomb_out;
2960 case 't':
2961 if (len == sizeof (".type")-1
2962 && memcmp (dir_start, ".type", sizeof (".type")-1) == 0
2963 && arg_was_number)
2965 tq_t *tq_ptr = &t.type_qualifiers[0];
2967 t.orig_type = (coff_type_t) (arg_number & N_BTMASK);
2968 t.basic_type = map_coff_types [(int) t.orig_type];
2969 for (i = N_TQ-1; i >= 0; i--)
2971 int dt = (arg_number >> ((i * N_TQ_SHIFT) + N_BT_SHIFT)
2972 & N_TMASK);
2974 if (dt != (int) DT_NON)
2975 *tq_ptr++ = map_coff_derived_type [dt];
2978 /* If this is a function, ignore it, so that we don't get
2979 two entries (one from the .ent, and one for the .def
2980 that precedes it). Save the type information so that
2981 the end block can properly add it after the begin block
2982 index. For MIPS knows what reason, we must strip off
2983 the function type at this point. */
2984 if (tq_ptr != &t.type_qualifiers[0] && tq_ptr[-1] == tq_Proc)
2986 is_function = 1;
2987 tq_ptr[-1] = tq_Nil;
2990 break;
2993 else if (len == sizeof (".tag")-1
2994 && memcmp (dir_start, ".tag", sizeof (".tag")-1) == 0)
2996 tag_start = arg_start;
2997 tag_end_p1 = arg_end_p1;
2998 break;
3001 else
3003 error_line = __LINE__;
3004 goto bomb_out;
3008 case 'v':
3009 if (len == sizeof (".val")-1
3010 && memcmp (dir_start, ".val", sizeof (".val")-1) == 0)
3012 if (arg_was_number)
3013 value = arg_number;
3015 /* If the value is not an integer value, it must be the
3016 name of a static or global item. Look up the name in
3017 the original symbol table to pick up the storage
3018 class, symbol type, etc. */
3019 else
3021 shash_t *orig_hash_ptr; /* hash within orig sym table*/
3022 shash_t *ext_hash_ptr; /* hash within ext. sym table*/
3024 ext_hash_ptr = hash_string (arg_start,
3025 arg_end_p1 - arg_start,
3026 &ext_str_hash[0],
3027 (symint_t *) 0);
3029 if (ext_hash_ptr != (shash_t *) 0
3030 && ext_hash_ptr->esym_ptr != (EXTR *) 0)
3031 eptr = ext_hash_ptr->esym_ptr;
3033 orig_hash_ptr = hash_string (arg_start,
3034 arg_end_p1 - arg_start,
3035 &orig_str_hash[0],
3036 (symint_t *) 0);
3038 if ((orig_hash_ptr == (shash_t *) 0
3039 || orig_hash_ptr->sym_ptr == (SYMR *) 0)
3040 && eptr == (EXTR *) 0)
3042 fprintf (stderr, "warning, %.*s not found in original or external symbol tables, value defaults to 0\n",
3043 (int) (arg_end_p1 - arg_start),
3044 arg_start);
3045 value = 0;
3047 else
3049 SYMR *ptr = (orig_hash_ptr != (shash_t *) 0
3050 && orig_hash_ptr->sym_ptr != (SYMR *) 0)
3051 ? orig_hash_ptr->sym_ptr
3052 : &eptr->asym;
3054 symbol_type = (st_t) ptr->st;
3055 storage_class = (sc_t) ptr->sc;
3056 value = ptr->value;
3059 break;
3061 else
3063 error_line = __LINE__;
3064 goto bomb_out;
3068 /* Set up to find next directive. */
3069 dir_start = arg_end_p1 + 1;
3073 if (storage_class == sc_Bits)
3075 t.bitfield = 1;
3076 t.extra_sizes = 1;
3078 else
3079 t.extra_sizes = 0;
3081 if (t.num_dims > 0)
3083 int num_real_sizes = t.num_sizes - t.extra_sizes;
3084 int diff = t.num_dims - num_real_sizes;
3085 int i = t.num_dims - 1;
3086 int j;
3088 if (num_real_sizes != 1 || diff < 0)
3090 error_line = __LINE__;
3091 goto bomb_out;
3094 /* If this is an array, make sure the same number of dimensions
3095 and sizes were passed, creating extra sizes for multiply
3096 dimensioned arrays if not passed. */
3098 if (diff)
3100 for (j = ARRAY_SIZE (t.sizes) - 1; j >= 0; j--)
3101 t.sizes[ j ] = ((j-diff) >= 0) ? t.sizes[ j-diff ] : 0;
3103 t.num_sizes = i + 1;
3104 for ( i--; i >= 0; i-- )
3106 if (t.dimensions[ i+1 ])
3107 t.sizes[ i ] = t.sizes[ i+1 ] / t.dimensions[ i+1 ];
3108 else
3109 t.sizes[ i ] = t.sizes[ i+1 ];
3114 /* Except for enumeration members & begin/ending of scopes, put the
3115 type word in the aux. symbol table. */
3117 if (symbol_type == st_Block || symbol_type == st_End)
3118 indx = 0;
3120 else if (inside_enumeration)
3121 indx = cur_file_ptr->void_type;
3123 else
3125 if (t.basic_type == bt_Struct
3126 || t.basic_type == bt_Union
3127 || t.basic_type == bt_Enum)
3129 if (tag_start == (char *) 0)
3131 error ("no tag specified for %.*s",
3132 (int) (name_end_p1 - name_start),
3133 name_start);
3134 return;
3137 t.tag_ptr = get_tag (tag_start, tag_end_p1, (symint_t) indexNil,
3138 t.basic_type);
3141 if (is_function)
3143 last_func_type_info = t;
3144 last_func_eptr = eptr;
3145 return;
3148 indx = add_aux_sym_tir (&t,
3149 hash_yes,
3150 &cur_file_ptr->thash_head[0]);
3154 /* If this is an external or static symbol, update the appropriate
3155 external symbol. */
3157 if (eptr != (EXTR *) 0
3158 && (eptr->asym.index == indexNil || cur_proc_ptr == (PDR *) 0))
3160 eptr->ifd = cur_file_ptr->file_index;
3161 eptr->asym.index = indx;
3165 /* Do any last minute adjustments that are necessary. */
3166 switch (symbol_type)
3168 default:
3169 break;
3172 /* For the beginning of structs, unions, and enumerations, the
3173 size info needs to be passed in the value field. */
3175 case st_Block:
3176 if (t.num_sizes - t.num_dims - t.extra_sizes != 1)
3178 error_line = __LINE__;
3179 goto bomb_out;
3182 else
3183 value = t.sizes[0];
3185 inside_enumeration = (t.orig_type == T_ENUM);
3186 break;
3189 /* For the end of structs, unions, and enumerations, omit the
3190 name which is always ".eos". This needs to be done last, so
3191 that any error reporting above gives the correct name. */
3193 case st_End:
3194 name_start = name_end_p1 = 0;
3195 value = inside_enumeration = 0;
3196 break;
3199 /* Members of structures and unions that aren't bitfields, need
3200 to adjust the value from a byte offset to a bit offset.
3201 Members of enumerations do not have the value adjusted, and
3202 can be distinguished by indx == indexNil. For enumerations,
3203 update the maximum enumeration value. */
3205 case st_Member:
3206 if (!t.bitfield && !inside_enumeration)
3207 value *= 8;
3209 break;
3213 /* Add the symbol, except for global symbols outside of functions,
3214 for which the external symbol table is fine enough. */
3216 if (eptr == (EXTR *) 0
3217 || eptr->asym.st == (int) st_Nil
3218 || cur_proc_ptr != (PDR *) 0)
3220 symint_t isym = add_local_symbol (name_start, name_end_p1,
3221 symbol_type, storage_class,
3222 value,
3223 indx);
3225 /* Deal with struct, union, and enum tags. */
3226 if (symbol_type == st_Block)
3228 /* Create or update the tag information. */
3229 tag_t *tag_ptr = get_tag (name_start,
3230 name_end_p1,
3231 isym,
3232 t.basic_type);
3234 /* If there are any forward references, fill in the appropriate
3235 file and symbol indexes. */
3237 symint_t file_index = cur_file_ptr->file_index;
3238 forward_t *f_next = tag_ptr->forward_ref;
3239 forward_t *f_cur;
3241 while (f_next != (forward_t *) 0)
3243 f_cur = f_next;
3244 f_next = f_next->next;
3246 f_cur->ifd_ptr->isym = file_index;
3247 f_cur->index_ptr->rndx.index = isym;
3249 free_forward (f_cur);
3252 tag_ptr->forward_ref = (forward_t *) 0;
3256 /* Normal return */
3257 return;
3259 /* Error return, issue message. */
3260 bomb_out:
3261 if (error_line)
3262 error ("compiler error, badly formed #.def (internal line # = %d)", error_line);
3263 else
3264 error ("compiler error, badly formed #.def");
3266 return;
3270 /* Parse .end directives. */
3272 static void
3273 parse_end (const char *start)
3275 const char *start_func, *end_func_p1;
3276 int ch;
3277 symint_t value;
3278 FDR *orig_fdr;
3280 if (cur_file_ptr == (efdr_t *) 0)
3282 error (".end directive without a preceding .file directive");
3283 return;
3286 if (cur_proc_ptr == (PDR *) 0)
3288 error (".end directive without a preceding .ent directive");
3289 return;
3292 /* Get the function name, skipping whitespace. */
3293 for (start_func = start; ISSPACE ((unsigned char)*start_func); start_func++)
3296 ch = *start_func;
3297 if (!IS_ASM_IDENT (ch))
3299 error (".end directive has no name");
3300 return;
3303 for (end_func_p1 = start_func; IS_ASM_IDENT (ch); ch = *++end_func_p1)
3307 /* Get the value field for creating the end from the original object
3308 file (which we find by locating the procedure start, and using the
3309 pointer to the end+1 block and backing up. The index points to a
3310 two word aux. symbol, whose first word is the index of the end
3311 symbol, and the second word is the type of the function return
3312 value. */
3314 orig_fdr = cur_file_ptr->orig_fdr;
3315 value = 0;
3316 if (orig_fdr != (FDR *) 0 && cur_oproc_end != (SYMR *) 0)
3317 value = cur_oproc_end->value;
3319 else
3320 error ("cannot find .end block for %.*s",
3321 (int) (end_func_p1 - start_func), start_func);
3323 (void) add_local_symbol (start_func, end_func_p1,
3324 st_End, sc_Text,
3325 value,
3326 (symint_t) 0);
3328 cur_proc_ptr = cur_oproc_ptr = (PDR *) 0;
3332 /* Parse .ent directives. */
3334 static void
3335 parse_ent (const char *start)
3337 const char *start_func, *end_func_p1;
3338 int ch;
3340 if (cur_file_ptr == (efdr_t *) 0)
3342 error (".ent directive without a preceding .file directive");
3343 return;
3346 if (cur_proc_ptr != (PDR *) 0)
3348 error ("second .ent directive found before .end directive");
3349 return;
3352 for (start_func = start; ISSPACE ((unsigned char)*start_func); start_func++)
3355 ch = *start_func;
3356 if (!IS_ASM_IDENT (ch))
3358 error (".ent directive has no name");
3359 return;
3362 for (end_func_p1 = start_func; IS_ASM_IDENT (ch); ch = *++end_func_p1)
3365 (void) add_procedure (start_func, end_func_p1);
3369 /* Parse .file directives. */
3371 static void
3372 parse_file (const char *start)
3374 char *p;
3375 char *start_name, *end_name_p1;
3377 (void) strtol (start, &p, 0);
3378 if (start == p
3379 || (start_name = strchr (p, '"')) == (char *) 0
3380 || (end_name_p1 = strrchr (++start_name, '"')) == (char *) 0)
3382 error ("invalid .file directive");
3383 return;
3386 if (cur_proc_ptr != (PDR *) 0)
3388 error ("no way to handle .file within .ent/.end section");
3389 return;
3392 add_file (start_name, end_name_p1);
3396 /* Make sure the @stabs symbol is emitted. */
3398 static void
3399 mark_stabs (const char *start ATTRIBUTE_UNUSED)
3401 if (!stabs_seen)
3403 /* Add a dummy @stabs symbol. */
3404 stabs_seen = 1;
3405 (void) add_local_symbol (stabs_symbol,
3406 stabs_symbol + sizeof (stabs_symbol),
3407 (st_t) stNil, (sc_t) scInfo, -1,
3408 MIPS_MARK_STAB (0));
3414 /* Parse .stabs directives.
3416 .stabs directives have five fields:
3417 "string" a string, encoding the type information.
3418 code a numeric code, defined in <stab.h>
3419 0 a zero
3420 0 a zero or line number
3421 value a numeric value or an address.
3423 If the value is relocatable, we transform this into:
3424 iss points as an index into string space
3425 value value from lookup of the name
3426 st st from lookup of the name
3427 sc sc from lookup of the name
3428 index code|CODE_MASK
3430 If the value is not relocatable, we transform this into:
3431 iss points as an index into string space
3432 value value
3433 st st_Nil
3434 sc sc_Nil
3435 index code|CODE_MASK
3437 .stabn directives have four fields (string is null):
3438 code a numeric code, defined in <stab.h>
3439 0 a zero
3440 0 a zero or a line number
3441 value a numeric value or an address. */
3443 static void
3444 parse_stabs_common (const char *string_start, /* start of string or NULL */
3445 const char *string_end, /* end+1 of string or NULL */
3446 const char *rest) /* rest of the directive. */
3448 efdr_t *save_file_ptr = cur_file_ptr;
3449 symint_t code;
3450 symint_t value;
3451 char *p;
3452 st_t st;
3453 sc_t sc;
3454 int ch;
3456 if (stabs_seen == 0)
3457 mark_stabs ("");
3459 /* Read code from stabs. */
3460 if (!ISDIGIT (*rest))
3462 error ("invalid .stabs/.stabn directive, code is non-numeric");
3463 return;
3466 code = strtol (rest, &p, 0);
3468 /* Line number stabs are handled differently, since they have two values,
3469 the line number and the address of the label. We use the index field
3470 (aka code) to hold the line number, and the value field to hold the
3471 address. The symbol type is st_Label, which should be different from
3472 the other stabs, so that gdb can recognize it. */
3474 if (code == (int) N_SLINE)
3476 SYMR *sym_ptr, dummy_symr;
3477 shash_t *shash_ptr;
3479 /* Skip ,0, */
3480 if (p[0] != ',' || p[1] != '0' || p[2] != ',' || !ISDIGIT (p[3]))
3482 error ("invalid line number .stabs/.stabn directive");
3483 return;
3486 code = strtol (p+3, &p, 0);
3487 ch = *++p;
3488 if (p[-1] != ',' || ISDIGIT (ch) || !IS_ASM_IDENT (ch))
3490 error ("invalid line number .stabs/.stabn directive");
3491 return;
3494 dummy_symr.index = code;
3495 if (dummy_symr.index != code)
3497 error ("line number (%lu) for .stabs/.stabn directive cannot fit in index field (20 bits)",
3498 code);
3500 return;
3503 shash_ptr = hash_string (p,
3504 strlen (p) - 1,
3505 &orig_str_hash[0],
3506 (symint_t *) 0);
3508 if (shash_ptr == (shash_t *) 0
3509 || (sym_ptr = shash_ptr->sym_ptr) == (SYMR *) 0)
3511 error ("invalid .stabs/.stabn directive, value not found");
3512 return;
3515 if ((st_t) sym_ptr->st != st_Label)
3517 error ("invalid line number .stabs/.stabn directive");
3518 return;
3521 st = st_Label;
3522 sc = (sc_t) sym_ptr->sc;
3523 value = sym_ptr->value;
3525 else
3527 /* Skip ,<num>,<num>, */
3528 if (*p++ != ',')
3529 goto failure;
3530 for (; ISDIGIT (*p); p++)
3532 if (*p++ != ',')
3533 goto failure;
3534 for (; ISDIGIT (*p); p++)
3536 if (*p++ != ',')
3537 goto failure;
3538 ch = *p;
3539 if (!IS_ASM_IDENT (ch) && ch != '-')
3541 failure:
3542 error ("invalid .stabs/.stabn directive, bad character");
3543 return;
3546 if (ISDIGIT (ch) || ch == '-')
3548 st = st_Nil;
3549 sc = sc_Nil;
3550 value = strtol (p, &p, 0);
3551 if (*p != '\n')
3553 error ("invalid .stabs/.stabn directive, stuff after numeric value");
3554 return;
3557 else if (!IS_ASM_IDENT (ch))
3559 error ("invalid .stabs/.stabn directive, bad character");
3560 return;
3562 else
3564 SYMR *sym_ptr;
3565 shash_t *shash_ptr;
3566 const char *start, *end_p1;
3568 start = p;
3569 if ((end_p1 = strchr (start, '+')) == (char *) 0)
3571 if ((end_p1 = strchr (start, '-')) == (char *) 0)
3572 end_p1 = start + strlen (start) - 1;
3575 shash_ptr = hash_string (start,
3576 end_p1 - start,
3577 &orig_str_hash[0],
3578 (symint_t *) 0);
3580 if (shash_ptr == (shash_t *) 0
3581 || (sym_ptr = shash_ptr->sym_ptr) == (SYMR *) 0)
3583 shash_ptr = hash_string (start,
3584 end_p1 - start,
3585 &ext_str_hash[0],
3586 (symint_t *) 0);
3588 if (shash_ptr == (shash_t *) 0
3589 || shash_ptr->esym_ptr == (EXTR *) 0)
3591 error ("invalid .stabs/.stabn directive, value not found");
3592 return;
3594 else
3595 sym_ptr = &(shash_ptr->esym_ptr->asym);
3598 /* Traditionally, N_LBRAC and N_RBRAC are *not* relocated. */
3599 if (code == (int) N_LBRAC || code == (int) N_RBRAC)
3601 sc = (sc_t) scNil;
3602 st = (st_t) stNil;
3604 else
3606 sc = (sc_t) sym_ptr->sc;
3607 st = (st_t) sym_ptr->st;
3609 value = sym_ptr->value;
3611 ch = *end_p1++;
3612 if (ch != '\n')
3614 if (((!ISDIGIT (*end_p1)) && (*end_p1 != '-'))
3615 || ((ch != '+') && (ch != '-')))
3617 error ("invalid .stabs/.stabn directive, badly formed value");
3618 return;
3620 if (ch == '+')
3621 value += strtol (end_p1, &p, 0);
3622 else if (ch == '-')
3623 value -= strtol (end_p1, &p, 0);
3625 if (*p != '\n')
3627 error ("invalid .stabs/.stabn directive, stuff after numeric value");
3628 return;
3632 code = MIPS_MARK_STAB (code);
3635 (void) add_local_symbol (string_start, string_end, st, sc, value, code);
3636 /* Restore normal file type. */
3637 cur_file_ptr = save_file_ptr;
3641 static void
3642 parse_stabs (const char *start)
3644 const char *end = strchr (start+1, '"');
3646 if (*start != '"' || end == (const char *) 0 || end[1] != ',')
3648 error ("invalid .stabs directive, no string");
3649 return;
3652 parse_stabs_common (start+1, end, end+2);
3656 static void
3657 parse_stabn (const char *start)
3659 parse_stabs_common ((const char *) 0, (const char *) 0, start);
3663 /* Parse the input file, and write the lines to the output file
3664 if needed. */
3666 static void
3667 parse_input (void)
3669 char *p;
3670 size_t i;
3671 thead_t *ptag_head;
3672 tag_t *ptag;
3673 tag_t *ptag_next;
3675 if (debug)
3676 fprintf (stderr, "\tinput\n");
3678 /* Add a dummy scope block around the entire compilation unit for
3679 structures defined outside of blocks. */
3680 ptag_head = allocate_thead ();
3681 ptag_head->first_tag = 0;
3682 ptag_head->prev = cur_tag_head;
3683 cur_tag_head = ptag_head;
3685 while ((p = read_line ()) != (char *) 0)
3687 /* Skip leading blanks. */
3688 while (ISSPACE ((unsigned char)*p))
3689 p++;
3691 /* See if it's a directive we handle. If so, dispatch handler. */
3692 for (i = 0; i < ARRAY_SIZE (pseudo_ops); i++)
3693 if (memcmp (p, pseudo_ops[i].name, pseudo_ops[i].len) == 0
3694 && ISSPACE ((unsigned char)(p[pseudo_ops[i].len])))
3696 p += pseudo_ops[i].len; /* skip to first argument */
3697 while (ISSPACE ((unsigned char)*p))
3698 p++;
3700 (*pseudo_ops[i].func)( p );
3701 break;
3705 /* Process any tags at global level. */
3706 ptag_head = cur_tag_head;
3707 cur_tag_head = ptag_head->prev;
3709 for (ptag = ptag_head->first_tag;
3710 ptag != (tag_t *) 0;
3711 ptag = ptag_next)
3713 if (ptag->forward_ref != (forward_t *) 0)
3714 add_unknown_tag (ptag);
3716 ptag_next = ptag->same_block;
3717 ptag->hash_ptr->tag_ptr = ptag->same_name;
3718 free_tag (ptag);
3721 free_thead (ptag_head);
3726 /* Update the global headers with the final offsets in preparation
3727 to write out the .T file. */
3729 static void
3730 update_headers (void)
3732 symint_t i;
3733 efdr_t *file_ptr;
3735 /* Set up the symbolic header. */
3736 file_offset = sizeof (symbolic_header) + orig_file_header.f_symptr;
3737 symbolic_header.magic = orig_sym_hdr.magic;
3738 symbolic_header.vstamp = orig_sym_hdr.vstamp;
3740 /* Set up global counts. */
3741 symbolic_header.issExtMax = ext_strings.num_allocated;
3742 symbolic_header.idnMax = dense_num.num_allocated;
3743 symbolic_header.ifdMax = file_desc.num_allocated;
3744 symbolic_header.iextMax = ext_symbols.num_allocated;
3745 symbolic_header.ilineMax = orig_sym_hdr.ilineMax;
3746 symbolic_header.ioptMax = orig_sym_hdr.ioptMax;
3747 symbolic_header.cbLine = orig_sym_hdr.cbLine;
3748 symbolic_header.crfd = orig_sym_hdr.crfd;
3751 /* Loop through each file, figuring out how many local syms,
3752 line numbers, etc. there are. Also, put out end symbol
3753 for the filename. */
3755 for (file_ptr = first_file;
3756 file_ptr != (efdr_t *) 0;
3757 file_ptr = file_ptr->next_file)
3759 SYMR *sym_start;
3760 SYMR *sym;
3761 SYMR *sym_end_p1;
3762 FDR *fd_ptr = file_ptr->orig_fdr;
3764 cur_file_ptr = file_ptr;
3766 /* Copy st_Static symbols from the original local symbol table if
3767 they did not get added to the new local symbol table.
3768 This happens with stabs-in-ecoff or if the source file is
3769 compiled without debugging. */
3770 sym_start = ORIG_LSYMS (fd_ptr->isymBase);
3771 sym_end_p1 = sym_start + fd_ptr->csym;
3772 for (sym = sym_start; sym < sym_end_p1; sym++)
3774 if ((st_t) sym->st == st_Static)
3776 char *str = ORIG_LSTRS (fd_ptr->issBase + sym->iss);
3777 size_t len = strlen (str);
3778 shash_t *hash_ptr;
3780 /* Ignore internal labels. */
3781 if (str[0] == '$' && str[1] == 'L')
3782 continue;
3783 hash_ptr = hash_string (str,
3784 (ptrdiff_t) len,
3785 &file_ptr->shash_head[0],
3786 (symint_t *) 0);
3787 if (hash_ptr == (shash_t *) 0)
3789 (void) add_local_symbol (str, str + len,
3790 (st_t) sym->st, (sc_t) sym->sc,
3791 (symint_t) sym->value,
3792 (symint_t) indexNil);
3796 (void) add_local_symbol ((const char *) 0, (const char *) 0,
3797 st_End, sc_Text,
3798 (symint_t) 0,
3799 (symint_t) 0);
3801 file_ptr->fdr.cpd = file_ptr->procs.num_allocated;
3802 file_ptr->fdr.ipdFirst = symbolic_header.ipdMax;
3803 symbolic_header.ipdMax += file_ptr->fdr.cpd;
3805 file_ptr->fdr.csym = file_ptr->symbols.num_allocated;
3806 file_ptr->fdr.isymBase = symbolic_header.isymMax;
3807 symbolic_header.isymMax += file_ptr->fdr.csym;
3809 file_ptr->fdr.caux = file_ptr->aux_syms.num_allocated;
3810 file_ptr->fdr.iauxBase = symbolic_header.iauxMax;
3811 symbolic_header.iauxMax += file_ptr->fdr.caux;
3813 file_ptr->fdr.cbSs = file_ptr->strings.num_allocated;
3814 file_ptr->fdr.issBase = symbolic_header.issMax;
3815 symbolic_header.issMax += file_ptr->fdr.cbSs;
3818 /* Align ecoff symbol tables to avoid OSF1/1.3 nm complaints. */
3819 #define ALIGN_SYMTABLE_OFFSET(OFFSET) (((OFFSET) + 7) & ~7)
3821 file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
3822 i = WORD_ALIGN (symbolic_header.cbLine); /* line numbers */
3823 if (i > 0)
3825 symbolic_header.cbLineOffset = file_offset;
3826 file_offset += i;
3827 file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
3830 i = symbolic_header.ioptMax; /* optimization symbols */
3831 if (((long) i) > 0)
3833 symbolic_header.cbOptOffset = file_offset;
3834 file_offset += i * sizeof (OPTR);
3835 file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
3838 i = symbolic_header.idnMax; /* dense numbers */
3839 if (i > 0)
3841 symbolic_header.cbDnOffset = file_offset;
3842 file_offset += i * sizeof (DNR);
3843 file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
3846 i = symbolic_header.ipdMax; /* procedure tables */
3847 if (i > 0)
3849 symbolic_header.cbPdOffset = file_offset;
3850 file_offset += i * sizeof (PDR);
3851 file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
3854 i = symbolic_header.isymMax; /* local symbols */
3855 if (i > 0)
3857 symbolic_header.cbSymOffset = file_offset;
3858 file_offset += i * sizeof (SYMR);
3859 file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
3862 i = symbolic_header.iauxMax; /* aux syms. */
3863 if (i > 0)
3865 symbolic_header.cbAuxOffset = file_offset;
3866 file_offset += i * sizeof (TIR);
3867 file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
3870 i = WORD_ALIGN (symbolic_header.issMax); /* local strings */
3871 if (i > 0)
3873 symbolic_header.cbSsOffset = file_offset;
3874 file_offset += i;
3875 file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
3878 i = WORD_ALIGN (symbolic_header.issExtMax); /* external strings */
3879 if (i > 0)
3881 symbolic_header.cbSsExtOffset = file_offset;
3882 file_offset += i;
3883 file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
3886 i = symbolic_header.ifdMax; /* file tables */
3887 if (i > 0)
3889 symbolic_header.cbFdOffset = file_offset;
3890 file_offset += i * sizeof (FDR);
3891 file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
3894 i = symbolic_header.crfd; /* relative file descriptors */
3895 if (i > 0)
3897 symbolic_header.cbRfdOffset = file_offset;
3898 file_offset += i * sizeof (symint_t);
3899 file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
3902 i = symbolic_header.iextMax; /* external symbols */
3903 if (i > 0)
3905 symbolic_header.cbExtOffset = file_offset;
3906 file_offset += i * sizeof (EXTR);
3907 file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
3912 /* Write out a varray at a given location. */
3914 static void
3915 write_varray (varray_t *vp, /* virtual array */
3916 off_t offset, /* offset to write varray to */
3917 const char *str) /* string to print out when tracing */
3919 int num_write, sys_write;
3920 vlinks_t *ptr;
3922 if (vp->num_allocated == 0)
3923 return;
3925 if (debug)
3926 fprintf (stderr, "\twarray\tvp = " HOST_PTR_PRINTF
3927 ", offset = %7lu, size = %7lu, %s\n",
3928 (void *) vp, (unsigned long) offset,
3929 vp->num_allocated * vp->object_size, str);
3931 if (file_offset != (unsigned long) offset
3932 && fseek (object_stream, (long) offset, SEEK_SET) < 0)
3933 pfatal_with_name (object_name);
3935 for (ptr = vp->first; ptr != (vlinks_t *) 0; ptr = ptr->next)
3937 num_write = (ptr->next == (vlinks_t *) 0)
3938 ? vp->objects_last_page * vp->object_size
3939 : vp->objects_per_page * vp->object_size;
3941 sys_write = fwrite (ptr->datum, 1, num_write, object_stream);
3942 if (sys_write <= 0)
3943 pfatal_with_name (object_name);
3945 else if (sys_write != num_write)
3946 fatal ("wrote %d bytes to %s, system returned %d",
3947 num_write,
3948 object_name,
3949 sys_write);
3951 file_offset += num_write;
3956 /* Write out the symbol table in the object file. */
3958 static void
3959 write_object (void)
3961 int sys_write;
3962 efdr_t *file_ptr;
3963 off_t offset;
3965 if (debug)
3966 fprintf (stderr, "\n\twrite\tvp = " HOST_PTR_PRINTF
3967 ", offset = %7u, size = %7lu, %s\n",
3968 (void *) &symbolic_header, 0,
3969 (unsigned long) sizeof (symbolic_header), "symbolic header");
3971 sys_write = fwrite (&symbolic_header,
3973 sizeof (symbolic_header),
3974 object_stream);
3976 if (sys_write < 0)
3977 pfatal_with_name (object_name);
3979 else if (sys_write != sizeof (symbolic_header))
3980 fatal ("wrote %d bytes to %s, system returned %d",
3981 (int) sizeof (symbolic_header),
3982 object_name,
3983 sys_write);
3986 file_offset = sizeof (symbolic_header) + orig_file_header.f_symptr;
3988 if (symbolic_header.cbLine > 0) /* line numbers */
3990 long sys_write;
3992 if (file_offset != (unsigned long) symbolic_header.cbLineOffset
3993 && fseek (object_stream, symbolic_header.cbLineOffset, SEEK_SET) != 0)
3994 pfatal_with_name (object_name);
3996 if (debug)
3997 fprintf (stderr, "\twrite\tvp = " HOST_PTR_PRINTF
3998 ", offset = %7lu, size = %7lu, %s\n",
3999 (void *) &orig_linenum, (long) symbolic_header.cbLineOffset,
4000 (long) symbolic_header.cbLine, "Line numbers");
4002 sys_write = fwrite (orig_linenum,
4004 symbolic_header.cbLine,
4005 object_stream);
4007 if (sys_write <= 0)
4008 pfatal_with_name (object_name);
4010 else if (sys_write != symbolic_header.cbLine)
4011 fatal ("wrote %ld bytes to %s, system returned %ld",
4012 (long) symbolic_header.cbLine,
4013 object_name,
4014 sys_write);
4016 file_offset = symbolic_header.cbLineOffset + symbolic_header.cbLine;
4019 if (symbolic_header.ioptMax > 0) /* optimization symbols */
4021 long sys_write;
4022 long num_write = symbolic_header.ioptMax * sizeof (OPTR);
4024 if (file_offset != (unsigned long) symbolic_header.cbOptOffset
4025 && fseek (object_stream, symbolic_header.cbOptOffset, SEEK_SET) != 0)
4026 pfatal_with_name (object_name);
4028 if (debug)
4029 fprintf (stderr, "\twrite\tvp = " HOST_PTR_PRINTF
4030 ", offset = %7lu, size = %7lu, %s\n",
4031 (void *) &orig_opt_syms, (long) symbolic_header.cbOptOffset,
4032 num_write, "Optimizer symbols");
4034 sys_write = fwrite (orig_opt_syms,
4036 num_write,
4037 object_stream);
4039 if (sys_write <= 0)
4040 pfatal_with_name (object_name);
4042 else if (sys_write != num_write)
4043 fatal ("wrote %ld bytes to %s, system returned %ld",
4044 num_write,
4045 object_name,
4046 sys_write);
4048 file_offset = symbolic_header.cbOptOffset + num_write;
4051 if (symbolic_header.idnMax > 0) /* dense numbers */
4052 write_varray (&dense_num, (off_t) symbolic_header.cbDnOffset, "Dense numbers");
4054 if (symbolic_header.ipdMax > 0) /* procedure tables */
4056 offset = symbolic_header.cbPdOffset;
4057 for (file_ptr = first_file;
4058 file_ptr != (efdr_t *) 0;
4059 file_ptr = file_ptr->next_file)
4061 write_varray (&file_ptr->procs, offset, "Procedure tables");
4062 offset = file_offset;
4066 if (symbolic_header.isymMax > 0) /* local symbols */
4068 offset = symbolic_header.cbSymOffset;
4069 for (file_ptr = first_file;
4070 file_ptr != (efdr_t *) 0;
4071 file_ptr = file_ptr->next_file)
4073 write_varray (&file_ptr->symbols, offset, "Local symbols");
4074 offset = file_offset;
4078 if (symbolic_header.iauxMax > 0) /* aux symbols */
4080 offset = symbolic_header.cbAuxOffset;
4081 for (file_ptr = first_file;
4082 file_ptr != (efdr_t *) 0;
4083 file_ptr = file_ptr->next_file)
4085 write_varray (&file_ptr->aux_syms, offset, "Aux. symbols");
4086 offset = file_offset;
4090 if (symbolic_header.issMax > 0) /* local strings */
4092 offset = symbolic_header.cbSsOffset;
4093 for (file_ptr = first_file;
4094 file_ptr != (efdr_t *) 0;
4095 file_ptr = file_ptr->next_file)
4097 write_varray (&file_ptr->strings, offset, "Local strings");
4098 offset = file_offset;
4102 if (symbolic_header.issExtMax > 0) /* external strings */
4103 write_varray (&ext_strings, symbolic_header.cbSsExtOffset, "External strings");
4105 if (symbolic_header.ifdMax > 0) /* file tables */
4107 offset = symbolic_header.cbFdOffset;
4108 if (file_offset != (unsigned long) offset
4109 && fseek (object_stream, (long) offset, SEEK_SET) < 0)
4110 pfatal_with_name (object_name);
4112 file_offset = offset;
4113 for (file_ptr = first_file;
4114 file_ptr != (efdr_t *) 0;
4115 file_ptr = file_ptr->next_file)
4117 if (debug)
4118 fprintf (stderr, "\twrite\tvp = " HOST_PTR_PRINTF
4119 ", offset = %7lu, size = %7lu, %s\n",
4120 (void *) &file_ptr->fdr, file_offset,
4121 (unsigned long) sizeof (FDR), "File header");
4123 sys_write = fwrite (&file_ptr->fdr,
4125 sizeof (FDR),
4126 object_stream);
4128 if (sys_write < 0)
4129 pfatal_with_name (object_name);
4131 else if (sys_write != sizeof (FDR))
4132 fatal ("wrote %d bytes to %s, system returned %d",
4133 (int) sizeof (FDR),
4134 object_name,
4135 sys_write);
4137 file_offset = offset += sizeof (FDR);
4141 if (symbolic_header.crfd > 0) /* relative file descriptors */
4143 long sys_write;
4144 symint_t num_write = symbolic_header.crfd * sizeof (symint_t);
4146 if (file_offset != (unsigned long) symbolic_header.cbRfdOffset
4147 && fseek (object_stream, symbolic_header.cbRfdOffset, SEEK_SET) != 0)
4148 pfatal_with_name (object_name);
4150 if (debug)
4151 fprintf (stderr, "\twrite\tvp = " HOST_PTR_PRINTF
4152 ", offset = %7lu, size = %7lu, %s\n",
4153 (void *) &orig_rfds, (long) symbolic_header.cbRfdOffset,
4154 num_write, "Relative file descriptors");
4156 sys_write = fwrite (orig_rfds,
4158 num_write,
4159 object_stream);
4161 if (sys_write <= 0)
4162 pfatal_with_name (object_name);
4164 else if (sys_write != (long) num_write)
4165 fatal ("wrote %lu bytes to %s, system returned %ld",
4166 num_write,
4167 object_name,
4168 sys_write);
4170 file_offset = symbolic_header.cbRfdOffset + num_write;
4173 if (symbolic_header.issExtMax > 0) /* external symbols */
4174 write_varray (&ext_symbols, (off_t) symbolic_header.cbExtOffset, "External symbols");
4176 if (fclose (object_stream) != 0)
4177 pfatal_with_name (object_name);
4181 /* Read some bytes at a specified location, and return a pointer. */
4183 static page_t *
4184 read_seek (size_t size, /* # bytes to read */
4185 off_t offset, /* offset to read at */
4186 const char *str) /* name for tracing */
4188 page_t *ptr;
4189 long sys_read = 0;
4191 if (size == 0) /* nothing to read */
4192 return (page_t *) 0;
4194 if (debug)
4195 fprintf (stderr,
4196 "\trseek\tsize = %7lu, offset = %7lu, currently at %7lu, %s\n",
4197 (unsigned long) size, (unsigned long) offset, file_offset, str);
4199 #ifndef MALLOC_CHECK
4200 ptr = allocate_multiple_pages ((size + PAGE_USIZE - 1) / PAGE_USIZE);
4201 #else
4202 ptr = xcalloc (1, size);
4203 #endif
4205 /* If we need to seek, and the distance is nearby, just do some reads,
4206 to speed things up. */
4207 if (file_offset != (unsigned long) offset)
4209 symint_t difference = offset - file_offset;
4211 if (difference < 8)
4213 char small_buffer[8];
4215 sys_read = fread (small_buffer, 1, difference, obj_in_stream);
4216 if (sys_read <= 0)
4217 pfatal_with_name (obj_in_name);
4219 if ((symint_t) sys_read != difference)
4220 fatal ("wanted to read %lu bytes from %s, system returned %ld",
4221 (unsigned long) size,
4222 obj_in_name,
4223 sys_read);
4225 else if (fseek (obj_in_stream, offset, SEEK_SET) < 0)
4226 pfatal_with_name (obj_in_name);
4229 sys_read = fread (ptr, 1, size, obj_in_stream);
4230 if (sys_read <= 0)
4231 pfatal_with_name (obj_in_name);
4233 if (sys_read != (long) size)
4234 fatal ("wanted to read %lu bytes from %s, system returned %ld",
4235 (unsigned long) size,
4236 obj_in_name,
4237 sys_read);
4239 file_offset = offset + size;
4241 if (file_offset > max_file_offset)
4242 max_file_offset = file_offset;
4244 return ptr;
4248 /* Read the existing object file (and copy to the output object file
4249 if it is different from the input object file), and remove the old
4250 symbol table. */
4252 static void
4253 copy_object (void)
4255 char buffer[ PAGE_SIZE ];
4256 int sys_read;
4257 int remaining;
4258 int num_write;
4259 int sys_write;
4260 int fd, es;
4261 int delete_ifd = 0;
4262 int *remap_file_number;
4263 struct stat stat_buf;
4265 if (debug)
4266 fprintf (stderr, "\tcopy\n");
4268 if (fstat (fileno (obj_in_stream), &stat_buf) != 0
4269 || fseek (obj_in_stream, 0L, SEEK_SET) != 0)
4270 pfatal_with_name (obj_in_name);
4272 sys_read = fread (&orig_file_header,
4274 sizeof (struct filehdr),
4275 obj_in_stream);
4277 if (sys_read < 0)
4278 pfatal_with_name (obj_in_name);
4280 else if (sys_read == 0 && feof (obj_in_stream))
4281 return; /* create a .T file sans file header */
4283 else if (sys_read < (int) sizeof (struct filehdr))
4284 fatal ("wanted to read %d bytes from %s, system returned %d",
4285 (int) sizeof (struct filehdr),
4286 obj_in_name,
4287 sys_read);
4290 if (orig_file_header.f_nsyms != sizeof (HDRR))
4291 fatal ("%s symbolic header wrong size (%ld bytes, should be %ld)",
4292 input_name, (long) orig_file_header.f_nsyms, (long) sizeof (HDRR));
4295 /* Read in the current symbolic header. */
4296 if (fseek (obj_in_stream, (long) orig_file_header.f_symptr, SEEK_SET) != 0)
4297 pfatal_with_name (input_name);
4299 sys_read = fread (&orig_sym_hdr,
4301 sizeof (orig_sym_hdr),
4302 obj_in_stream);
4304 if (sys_read < 0)
4305 pfatal_with_name (object_name);
4307 else if (sys_read < (int) sizeof (struct filehdr))
4308 fatal ("wanted to read %d bytes from %s, system returned %d",
4309 (int) sizeof (struct filehdr),
4310 obj_in_name,
4311 sys_read);
4314 /* Read in each of the sections if they exist in the object file.
4315 We read things in the order the mips assembler creates the
4316 sections, so in theory no extra seeks are done.
4318 For simplicity sake, round each read up to a page boundary,
4319 we may want to revisit this later.... */
4321 file_offset = orig_file_header.f_symptr + sizeof (struct filehdr);
4323 if (orig_sym_hdr.cbLine > 0) /* line numbers */
4324 orig_linenum = (char *) read_seek (orig_sym_hdr.cbLine,
4325 orig_sym_hdr.cbLineOffset,
4326 "Line numbers");
4328 if (orig_sym_hdr.ipdMax > 0) /* procedure tables */
4329 orig_procs = (PDR *) read_seek (orig_sym_hdr.ipdMax * sizeof (PDR),
4330 orig_sym_hdr.cbPdOffset,
4331 "Procedure tables");
4333 if (orig_sym_hdr.isymMax > 0) /* local symbols */
4334 orig_local_syms = (SYMR *) read_seek (orig_sym_hdr.isymMax * sizeof (SYMR),
4335 orig_sym_hdr.cbSymOffset,
4336 "Local symbols");
4338 if (orig_sym_hdr.iauxMax > 0) /* aux symbols */
4339 orig_aux_syms = (AUXU *) read_seek (orig_sym_hdr.iauxMax * sizeof (AUXU),
4340 orig_sym_hdr.cbAuxOffset,
4341 "Aux. symbols");
4343 if (orig_sym_hdr.issMax > 0) /* local strings */
4344 orig_local_strs = (char *) read_seek (orig_sym_hdr.issMax,
4345 orig_sym_hdr.cbSsOffset,
4346 "Local strings");
4348 if (orig_sym_hdr.issExtMax > 0) /* external strings */
4349 orig_ext_strs = (char *) read_seek (orig_sym_hdr.issExtMax,
4350 orig_sym_hdr.cbSsExtOffset,
4351 "External strings");
4353 if (orig_sym_hdr.ifdMax > 0) /* file tables */
4354 orig_files = (FDR *) read_seek (orig_sym_hdr.ifdMax * sizeof (FDR),
4355 orig_sym_hdr.cbFdOffset,
4356 "File tables");
4358 if (orig_sym_hdr.crfd > 0) /* relative file descriptors */
4359 orig_rfds = (symint_t *) read_seek (orig_sym_hdr.crfd * sizeof (symint_t),
4360 orig_sym_hdr.cbRfdOffset,
4361 "Relative file descriptors");
4363 if (orig_sym_hdr.issExtMax > 0) /* external symbols */
4364 orig_ext_syms = (EXTR *) read_seek (orig_sym_hdr.iextMax * sizeof (EXTR),
4365 orig_sym_hdr.cbExtOffset,
4366 "External symbols");
4368 if (orig_sym_hdr.idnMax > 0) /* dense numbers */
4370 orig_dense = (DNR *) read_seek (orig_sym_hdr.idnMax * sizeof (DNR),
4371 orig_sym_hdr.cbDnOffset,
4372 "Dense numbers");
4374 add_bytes (&dense_num, (char *) orig_dense, orig_sym_hdr.idnMax);
4377 if (orig_sym_hdr.ioptMax > 0) /* opt symbols */
4378 orig_opt_syms = (OPTR *) read_seek (orig_sym_hdr.ioptMax * sizeof (OPTR),
4379 orig_sym_hdr.cbOptOffset,
4380 "Optimizer symbols");
4384 /* The symbol table should be last. */
4385 if (max_file_offset != (unsigned long) stat_buf.st_size)
4386 fatal ("symbol table is not last (symbol table ends at %ld, .o ends at %ld",
4387 max_file_offset,
4388 (long) stat_buf.st_size);
4391 /* If the first original file descriptor is a dummy which the assembler
4392 put out, but there are no symbols in it, skip it now. */
4393 if (orig_sym_hdr.ifdMax > 1
4394 && orig_files->csym == 2
4395 && orig_files->caux == 0)
4397 char *filename = orig_local_strs + (orig_files->issBase + orig_files->rss);
4398 char *suffix = strrchr (filename, '.');
4400 if (suffix != (char *) 0 && strcmp (suffix, ".s") == 0)
4401 delete_ifd = 1;
4405 /* Create array to map original file numbers to the new file numbers
4406 (in case there are duplicate filenames, we collapse them into one
4407 file section, the MIPS assembler may or may not collapse them). */
4409 remap_file_number = (int *) alloca (sizeof (int) * orig_sym_hdr.ifdMax);
4411 for (fd = delete_ifd; fd < orig_sym_hdr.ifdMax; fd++)
4413 FDR *fd_ptr = ORIG_FILES (fd);
4414 char *filename = ORIG_LSTRS (fd_ptr->issBase + fd_ptr->rss);
4416 /* file support itself. */
4417 add_file (filename, filename + strlen (filename));
4418 remap_file_number[fd] = cur_file_ptr->file_index;
4421 if (delete_ifd > 0) /* just in case */
4422 remap_file_number[0] = remap_file_number[1];
4425 /* Loop, adding each of the external symbols. These must be in
4426 order or otherwise we would have to change the relocation
4427 entries. We don't just call add_bytes, because we need to have
4428 the names put into the external hash table. We set the type to
4429 'void' for now, and parse_def will fill in the correct type if it
4430 is in the symbol table. We must add the external symbols before
4431 the locals, since the locals do lookups against the externals. */
4433 if (debug)
4434 fprintf (stderr, "\tehash\n");
4436 for (es = 0; es < orig_sym_hdr.iextMax; es++)
4438 EXTR *eptr = orig_ext_syms + es;
4439 int ifd = eptr->ifd;
4441 (void) add_ext_symbol (eptr, ((long) ifd < orig_sym_hdr.ifdMax)
4442 ? remap_file_number[ ifd ] : ifd );
4446 /* For each of the files in the object file, copy the symbols, and such
4447 into the varrays for the new object file. */
4449 for (fd = delete_ifd; fd < orig_sym_hdr.ifdMax; fd++)
4451 FDR *fd_ptr = ORIG_FILES (fd);
4452 char *filename = ORIG_LSTRS (fd_ptr->issBase + fd_ptr->rss);
4453 SYMR *sym_start;
4454 SYMR *sym;
4455 SYMR *sym_end_p1;
4456 PDR *proc_start;
4457 PDR *proc;
4458 PDR *proc_end_p1;
4460 /* file support itself. */
4461 add_file (filename, filename + strlen (filename));
4462 cur_file_ptr->orig_fdr = fd_ptr;
4464 /* Copy stuff that's just passed through (such as line #'s) */
4465 cur_file_ptr->fdr.adr = fd_ptr->adr;
4466 cur_file_ptr->fdr.ilineBase = fd_ptr->ilineBase;
4467 cur_file_ptr->fdr.cline = fd_ptr->cline;
4468 cur_file_ptr->fdr.rfdBase = fd_ptr->rfdBase;
4469 cur_file_ptr->fdr.crfd = fd_ptr->crfd;
4470 cur_file_ptr->fdr.cbLineOffset = fd_ptr->cbLineOffset;
4471 cur_file_ptr->fdr.cbLine = fd_ptr->cbLine;
4472 cur_file_ptr->fdr.fMerge = fd_ptr->fMerge;
4473 cur_file_ptr->fdr.fReadin = fd_ptr->fReadin;
4474 cur_file_ptr->fdr.glevel = fd_ptr->glevel;
4476 if (debug)
4477 fprintf (stderr, "\thash\tstart, filename %s\n", filename);
4479 /* For each of the static and global symbols defined, add them
4480 to the hash table of original symbols, so we can look up
4481 their values. */
4483 sym_start = ORIG_LSYMS (fd_ptr->isymBase);
4484 sym_end_p1 = sym_start + fd_ptr->csym;
4485 for (sym = sym_start; sym < sym_end_p1; sym++)
4487 switch ((st_t) sym->st)
4489 default:
4490 break;
4492 case st_Global:
4493 case st_Static:
4494 case st_Label:
4495 case st_Proc:
4496 case st_StaticProc:
4498 auto symint_t hash_index;
4499 char *str = ORIG_LSTRS (fd_ptr->issBase + sym->iss);
4500 size_t len = strlen (str);
4501 shash_t *shash_ptr = hash_string (str,
4502 (ptrdiff_t) len,
4503 &orig_str_hash[0],
4504 &hash_index);
4506 if (shash_ptr != (shash_t *) 0)
4507 error ("internal error, %s is already in original symbol table", str);
4509 else
4511 shash_ptr = allocate_shash ();
4512 shash_ptr->next = orig_str_hash[hash_index];
4513 orig_str_hash[hash_index] = shash_ptr;
4515 shash_ptr->len = len;
4516 shash_ptr->indx = indexNil;
4517 shash_ptr->string = str;
4518 shash_ptr->sym_ptr = sym;
4521 break;
4523 case st_End:
4524 if ((sc_t) sym->sc == sc_Text)
4526 char *str = ORIG_LSTRS (fd_ptr->issBase + sym->iss);
4528 if (*str != '\0')
4530 size_t len = strlen (str);
4531 shash_t *shash_ptr = hash_string (str,
4532 (ptrdiff_t) len,
4533 &orig_str_hash[0],
4534 (symint_t *) 0);
4536 if (shash_ptr != (shash_t *) 0)
4537 shash_ptr->end_ptr = sym;
4540 break;
4545 if (debug)
4547 fprintf (stderr, "\thash\tdone, filename %s\n", filename);
4548 fprintf (stderr, "\tproc\tstart, filename %s\n", filename);
4551 /* Go through each of the procedures in this file, and add the
4552 procedure pointer to the hash entry for the given name. */
4554 proc_start = ORIG_PROCS (fd_ptr->ipdFirst);
4555 proc_end_p1 = proc_start + fd_ptr->cpd;
4556 for (proc = proc_start; proc < proc_end_p1; proc++)
4558 SYMR *proc_sym = ORIG_LSYMS (fd_ptr->isymBase + proc->isym);
4559 char *str = ORIG_LSTRS (fd_ptr->issBase + proc_sym->iss);
4560 size_t len = strlen (str);
4561 shash_t *shash_ptr = hash_string (str,
4562 (ptrdiff_t) len,
4563 &orig_str_hash[0],
4564 (symint_t *) 0);
4566 if (shash_ptr == (shash_t *) 0)
4567 error ("internal error, function %s is not in original symbol table", str);
4569 else
4570 shash_ptr->proc_ptr = proc;
4573 if (debug)
4574 fprintf (stderr, "\tproc\tdone, filename %s\n", filename);
4577 cur_file_ptr = first_file;
4580 /* Copy all of the object file up to the symbol table. Originally
4581 we were going to use ftruncate, but that doesn't seem to work
4582 on Ultrix 3.1.... */
4584 if (fseek (obj_in_stream, (long) 0, SEEK_SET) != 0)
4585 pfatal_with_name (obj_in_name);
4587 if (fseek (object_stream, (long) 0, SEEK_SET) != 0)
4588 pfatal_with_name (object_name);
4590 for (remaining = orig_file_header.f_symptr;
4591 remaining > 0;
4592 remaining -= num_write)
4594 num_write
4595 = (remaining <= (int) sizeof (buffer))
4596 ? remaining : (int) sizeof (buffer);
4597 sys_read = fread (buffer, 1, num_write, obj_in_stream);
4598 if (sys_read <= 0)
4599 pfatal_with_name (obj_in_name);
4601 else if (sys_read != num_write)
4602 fatal ("wanted to read %d bytes from %s, system returned %d",
4603 num_write,
4604 obj_in_name,
4605 sys_read);
4607 sys_write = fwrite (buffer, 1, num_write, object_stream);
4608 if (sys_write <= 0)
4609 pfatal_with_name (object_name);
4611 else if (sys_write != num_write)
4612 fatal ("wrote %d bytes to %s, system returned %d",
4613 num_write,
4614 object_name,
4615 sys_write);
4620 /* Ye olde main program. */
4622 extern int main (int, char **);
4625 main (int argc, char **argv)
4627 int iflag = 0;
4628 char *num_end;
4629 int option;
4630 int i;
4632 progname = lbasename (argv[0]);
4634 (void) signal (SIGSEGV, catch_signal);
4635 (void) signal (SIGBUS, catch_signal);
4636 (void) signal (SIGABRT, catch_signal);
4638 #ifndef lint
4639 if (sizeof (efdr_t) > PAGE_USIZE)
4640 fatal ("efdr_t has a sizeof %d bytes, when it should be less than %d",
4641 (int) sizeof (efdr_t),
4642 (int) PAGE_USIZE);
4644 if (sizeof (page_t) != PAGE_USIZE)
4645 fatal ("page_t has a sizeof %d bytes, when it should be %d",
4646 (int) sizeof (page_t),
4647 (int) PAGE_USIZE);
4649 #endif
4651 alloc_counts[ alloc_type_none ].alloc_name = "none";
4652 alloc_counts[ alloc_type_scope ].alloc_name = "scope";
4653 alloc_counts[ alloc_type_vlinks ].alloc_name = "vlinks";
4654 alloc_counts[ alloc_type_shash ].alloc_name = "shash";
4655 alloc_counts[ alloc_type_thash ].alloc_name = "thash";
4656 alloc_counts[ alloc_type_tag ].alloc_name = "tag";
4657 alloc_counts[ alloc_type_forward ].alloc_name = "forward";
4658 alloc_counts[ alloc_type_thead ].alloc_name = "thead";
4659 alloc_counts[ alloc_type_varray ].alloc_name = "varray";
4661 int_type_info = type_info_init;
4662 int_type_info.basic_type = bt_Int;
4664 void_type_info = type_info_init;
4665 void_type_info.basic_type = bt_Void;
4667 while ((option = getopt_long (argc, argv, "d:i:I:o:v", options, NULL)) != -1)
4668 switch (option)
4670 default:
4671 had_errors++;
4672 break;
4674 case 'd':
4675 debug = strtol (optarg, &num_end, 0);
4676 if ((unsigned) debug > 4 || num_end == optarg)
4677 had_errors++;
4679 break;
4681 case 'I':
4682 if (rename_output || obj_in_name != (char *) 0)
4683 had_errors++;
4684 else
4685 rename_output = 1;
4687 /* Fall through to 'i' case. */
4689 case 'i':
4690 if (obj_in_name == (char *) 0)
4692 obj_in_name = optarg;
4693 iflag++;
4695 else
4696 had_errors++;
4697 break;
4699 case 'o':
4700 if (object_name == (char *) 0)
4701 object_name = optarg;
4702 else
4703 had_errors++;
4704 break;
4706 case 'v':
4707 verbose++;
4708 break;
4710 case 'V':
4711 version++;
4712 break;
4715 if (version)
4717 printf (_("mips-tfile %s%s\n"), pkgversion_string, version_string);
4718 fputs ("Copyright (C) 2011 Free Software Foundation, Inc.\n", stdout);
4719 fputs (_("This is free software; see the source for copying conditions. There is NO\n\
4720 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"),
4721 stdout);
4722 exit (0);
4725 if (obj_in_name == (char *) 0 && optind <= argc - 2)
4726 obj_in_name = argv[--argc];
4728 if (object_name == (char *) 0 && optind <= argc - 2)
4729 object_name = argv[--argc];
4731 /* If there is an output name, but no input name use
4732 the same file for both, deleting the name between
4733 opening it for input and opening it for output. */
4734 if (obj_in_name == (char *) 0 && object_name != (char *) 0)
4736 obj_in_name = object_name;
4737 delete_input = 1;
4740 if (optind != argc - 1)
4741 had_errors++;
4743 if (verbose || had_errors)
4744 fprintf (stderr, _("mips-tfile (GCC) %s\n"), version_string);
4746 if (object_name == (char *) 0 || had_errors)
4748 fprintf (stderr, _("Calling Sequence:\n"));
4749 fprintf (stderr, _("\tmips-tfile [-d <num>] [-v] [-i <o-in-file>] -o <o-out-file> <s-file> (or)\n"));
4750 fprintf (stderr, _("\tmips-tfile [-d <num>] [-v] [-I <o-in-file>] -o <o-out-file> <s-file> (or)\n"));
4751 fprintf (stderr, _("\tmips-tfile [-d <num>] [-v] <s-file> <o-in-file> <o-out-file>\n"));
4752 fprintf (stderr, "\n");
4753 fprintf (stderr, _("Debug levels are:\n"));
4754 fprintf (stderr, _(" 1\tGeneral debug + trace functions/blocks.\n"));
4755 fprintf (stderr, _(" 2\tDebug level 1 + trace externals.\n"));
4756 fprintf (stderr, _(" 3\tDebug level 2 + trace all symbols.\n"));
4757 fprintf (stderr, _(" 4\tDebug level 3 + trace memory allocations.\n"));
4758 return 1;
4761 if (obj_in_name == (char *) 0)
4762 obj_in_name = object_name;
4764 if (rename_output && rename (object_name, obj_in_name) != 0)
4766 char *buffer = (char *) allocate_multiple_pages (4);
4767 int len;
4768 int len2;
4769 int in_fd;
4770 int out_fd;
4772 /* Rename failed, copy input file */
4773 in_fd = open (object_name, O_RDONLY, 0666);
4774 if (in_fd < 0)
4775 pfatal_with_name (object_name);
4777 out_fd = open (obj_in_name, O_WRONLY | O_CREAT | O_TRUNC, 0666);
4778 if (out_fd < 0)
4779 pfatal_with_name (obj_in_name);
4781 while ((len = read (in_fd, buffer, 4*PAGE_SIZE)) > 0)
4783 len2 = write (out_fd, buffer, len);
4784 if (len2 < 0)
4785 pfatal_with_name (object_name);
4787 if (len != len2)
4788 fatal ("wrote %d bytes to %s, expected to write %d", len2, obj_in_name, len);
4791 free_multiple_pages ((page_t *) buffer, 4);
4793 if (len < 0)
4794 pfatal_with_name (object_name);
4796 if (close (in_fd) < 0)
4797 pfatal_with_name (object_name);
4799 if (close (out_fd) < 0)
4800 pfatal_with_name (obj_in_name);
4803 /* Must open input before output, since the output may be the same file, and
4804 we need to get the input handle before truncating it. */
4805 obj_in_stream = fopen (obj_in_name, "r");
4806 if (obj_in_stream == (FILE *) 0)
4807 pfatal_with_name (obj_in_name);
4809 if (delete_input && unlink (obj_in_name) != 0)
4810 pfatal_with_name (obj_in_name);
4812 object_stream = fopen (object_name, "w");
4813 if (object_stream == (FILE *) 0)
4814 pfatal_with_name (object_name);
4816 if (strcmp (argv[optind], "-") != 0)
4818 input_name = argv[optind];
4819 if (freopen (argv[optind], "r", stdin) != stdin)
4820 pfatal_with_name (argv[optind]);
4823 copy_object (); /* scan & copy object file */
4824 parse_input (); /* scan all of input */
4826 update_headers (); /* write out tfile */
4827 write_object ();
4829 if (debug)
4831 fprintf (stderr, "\n\tAllocation summary:\n\n");
4832 for (i = (int) alloc_type_none; i < (int) alloc_type_last; i++)
4833 if (alloc_counts[i].total_alloc)
4835 fprintf (stderr,
4836 "\t%s\t%5d allocation(s), %5d free(s), %2d page(s)\n",
4837 alloc_counts[i].alloc_name,
4838 alloc_counts[i].total_alloc,
4839 alloc_counts[i].total_free,
4840 alloc_counts[i].total_pages);
4844 return (had_errors) ? 1 : 0;
4848 /* Catch a signal and exit without dumping core. */
4850 static void
4851 catch_signal (int signum)
4853 (void) signal (signum, SIG_DFL); /* just in case... */
4854 fatal ("%s", strsignal (signum));
4857 /* Print a fatal error message. NAME is the text.
4858 Also include a system error message based on `errno'. */
4860 void
4861 pfatal_with_name (const char *msg)
4863 int save_errno = errno; /* just in case.... */
4864 if (line_number > 0)
4865 fprintf (stderr, "%s, %s:%ld ", progname, input_name, line_number);
4866 else
4867 fprintf (stderr, "%s:", progname);
4869 errno = save_errno;
4870 if (errno == 0)
4871 fprintf (stderr, "[errno = 0] %s\n", msg);
4872 else
4873 perror (msg);
4875 exit (1);
4879 /* Procedure to die with an out of bounds error message. It has
4880 type int, so it can be used with an ?: expression within the
4881 ORIG_xxx macros, but the function never returns. */
4883 static int
4884 out_of_bounds (symint_t indx, /* index that is out of bounds */
4885 symint_t max, /* maximum index */
4886 const char *str, /* string to print out */
4887 int prog_line) /* line number within mips-tfile.c */
4889 if (indx < max) /* just in case */
4890 return 0;
4892 fprintf (stderr, "%s, %s:%ld index %lu is out of bounds for %s, max is %lu, mips-tfile.c line# %d\n",
4893 progname, input_name, line_number, indx, str, max, prog_line);
4895 exit (1);
4896 return 0; /* turn off warning messages */
4900 /* Allocate a cluster of pages. USE_MALLOC says that malloc does not
4901 like sbrk's behind its back (or sbrk isn't available). If we use
4902 sbrk, we assume it gives us zeroed pages. */
4904 #ifndef MALLOC_CHECK
4905 #ifdef USE_MALLOC
4907 static page_t *
4908 allocate_cluster (size_t npages)
4910 page_t *value = xcalloc (npages, PAGE_USIZE);
4912 if (debug > 3)
4913 fprintf (stderr, "\talloc\tnpages = %d, value = 0x%.8x\n", npages, value);
4915 return value;
4918 #else /* USE_MALLOC */
4920 static page_t *
4921 allocate_cluster (size_t npages)
4923 page_t *ptr = (page_t *) sbrk (0); /* current sbreak */
4924 unsigned long offset = ((unsigned long) ptr) & (PAGE_SIZE - 1);
4926 if (offset != 0) /* align to a page boundary */
4928 if (sbrk (PAGE_USIZE - offset) == (char *)-1)
4929 pfatal_with_name ("allocate_cluster");
4931 ptr = (page_t *) (((char *) ptr) + PAGE_SIZE - offset);
4934 if (sbrk (npages * PAGE_USIZE) == (char *) -1)
4935 pfatal_with_name ("allocate_cluster");
4937 if (debug > 3)
4938 fprintf (stderr, "\talloc\tnpages = %lu, value = " HOST_PTR_PRINTF "\n",
4939 (unsigned long) npages, (void *) ptr);
4941 return ptr;
4944 #endif /* USE_MALLOC */
4947 static page_t *cluster_ptr = NULL;
4948 static unsigned pages_left = 0;
4950 #endif /* MALLOC_CHECK */
4953 /* Allocate some pages (which is initialized to 0). */
4955 static page_t *
4956 allocate_multiple_pages (size_t npages)
4958 #ifndef MALLOC_CHECK
4959 if (pages_left == 0 && npages < MAX_CLUSTER_PAGES)
4961 pages_left = MAX_CLUSTER_PAGES;
4962 cluster_ptr = allocate_cluster (MAX_CLUSTER_PAGES);
4965 if (npages <= pages_left)
4967 page_t *ptr = cluster_ptr;
4968 cluster_ptr += npages;
4969 pages_left -= npages;
4970 return ptr;
4973 return allocate_cluster (npages);
4975 #else /* MALLOC_CHECK */
4976 return xcalloc (npages, PAGE_SIZE);
4978 #endif /* MALLOC_CHECK */
4982 /* Release some pages. */
4984 static void
4985 free_multiple_pages (page_t *page_ptr, size_t npages)
4987 #ifndef MALLOC_CHECK
4988 if (pages_left == 0)
4990 cluster_ptr = page_ptr;
4991 pages_left = npages;
4994 else if ((page_ptr + npages) == cluster_ptr)
4996 cluster_ptr -= npages;
4997 pages_left += npages;
5000 /* otherwise the page is not freed. If more than call is
5001 done, we probably should worry about it, but at present,
5002 the free pages is done right after an allocate. */
5004 #else /* MALLOC_CHECK */
5005 free (page_ptr);
5007 #endif /* MALLOC_CHECK */
5011 /* Allocate one page (which is initialized to 0). */
5013 static page_t *
5014 allocate_page (void)
5016 #ifndef MALLOC_CHECK
5017 if (pages_left == 0)
5019 pages_left = MAX_CLUSTER_PAGES;
5020 cluster_ptr = allocate_cluster (MAX_CLUSTER_PAGES);
5023 pages_left--;
5024 return cluster_ptr++;
5026 #else /* MALLOC_CHECK */
5027 return xcalloc (1, PAGE_SIZE);
5029 #endif /* MALLOC_CHECK */
5033 /* Allocate scoping information. */
5035 static scope_t *
5036 allocate_scope (void)
5038 scope_t *ptr;
5039 static scope_t initial_scope;
5041 #ifndef MALLOC_CHECK
5042 ptr = alloc_counts[ (int) alloc_type_scope ].free_list.f_scope;
5043 if (ptr != (scope_t *) 0)
5044 alloc_counts[ (int) alloc_type_scope ].free_list.f_scope = ptr->free;
5046 else
5048 int unallocated = alloc_counts[ (int) alloc_type_scope ].unallocated;
5049 page_t *cur_page = alloc_counts[ (int) alloc_type_scope ].cur_page;
5051 if (unallocated == 0)
5053 unallocated = PAGE_SIZE / sizeof (scope_t);
5054 alloc_counts[ (int) alloc_type_scope ].cur_page = cur_page = allocate_page ();
5055 alloc_counts[ (int) alloc_type_scope ].total_pages++;
5058 ptr = &cur_page->scope[ --unallocated ];
5059 alloc_counts[ (int) alloc_type_scope ].unallocated = unallocated;
5062 #else
5063 ptr = xmalloc (sizeof (scope_t));
5065 #endif
5067 alloc_counts[ (int) alloc_type_scope ].total_alloc++;
5068 *ptr = initial_scope;
5069 return ptr;
5072 /* Free scoping information. */
5074 static void
5075 free_scope (scope_t *ptr)
5077 alloc_counts[ (int) alloc_type_scope ].total_free++;
5079 #ifndef MALLOC_CHECK
5080 ptr->free = alloc_counts[ (int) alloc_type_scope ].free_list.f_scope;
5081 alloc_counts[ (int) alloc_type_scope ].free_list.f_scope = ptr;
5083 #else
5084 free (ptr);
5085 #endif
5090 /* Allocate links for pages in a virtual array. */
5092 static vlinks_t *
5093 allocate_vlinks (void)
5095 vlinks_t *ptr;
5096 static vlinks_t initial_vlinks;
5098 #ifndef MALLOC_CHECK
5099 int unallocated = alloc_counts[ (int) alloc_type_vlinks ].unallocated;
5100 page_t *cur_page = alloc_counts[ (int) alloc_type_vlinks ].cur_page;
5102 if (unallocated == 0)
5104 unallocated = PAGE_SIZE / sizeof (vlinks_t);
5105 alloc_counts[ (int) alloc_type_vlinks ].cur_page = cur_page = allocate_page ();
5106 alloc_counts[ (int) alloc_type_vlinks ].total_pages++;
5109 ptr = &cur_page->vlinks[ --unallocated ];
5110 alloc_counts[ (int) alloc_type_vlinks ].unallocated = unallocated;
5112 #else
5113 ptr = xmalloc (sizeof (vlinks_t));
5115 #endif
5117 alloc_counts[ (int) alloc_type_vlinks ].total_alloc++;
5118 *ptr = initial_vlinks;
5119 return ptr;
5123 /* Allocate string hash buckets. */
5125 static shash_t *
5126 allocate_shash (void)
5128 shash_t *ptr;
5129 static shash_t initial_shash;
5131 #ifndef MALLOC_CHECK
5132 int unallocated = alloc_counts[ (int) alloc_type_shash ].unallocated;
5133 page_t *cur_page = alloc_counts[ (int) alloc_type_shash ].cur_page;
5135 if (unallocated == 0)
5137 unallocated = PAGE_SIZE / sizeof (shash_t);
5138 alloc_counts[ (int) alloc_type_shash ].cur_page = cur_page = allocate_page ();
5139 alloc_counts[ (int) alloc_type_shash ].total_pages++;
5142 ptr = &cur_page->shash[ --unallocated ];
5143 alloc_counts[ (int) alloc_type_shash ].unallocated = unallocated;
5145 #else
5146 ptr = xmalloc (sizeof (shash_t));
5148 #endif
5150 alloc_counts[ (int) alloc_type_shash ].total_alloc++;
5151 *ptr = initial_shash;
5152 return ptr;
5156 /* Allocate type hash buckets. */
5158 static thash_t *
5159 allocate_thash (void)
5161 thash_t *ptr;
5162 static thash_t initial_thash;
5164 #ifndef MALLOC_CHECK
5165 int unallocated = alloc_counts[ (int) alloc_type_thash ].unallocated;
5166 page_t *cur_page = alloc_counts[ (int) alloc_type_thash ].cur_page;
5168 if (unallocated == 0)
5170 unallocated = PAGE_SIZE / sizeof (thash_t);
5171 alloc_counts[ (int) alloc_type_thash ].cur_page = cur_page = allocate_page ();
5172 alloc_counts[ (int) alloc_type_thash ].total_pages++;
5175 ptr = &cur_page->thash[ --unallocated ];
5176 alloc_counts[ (int) alloc_type_thash ].unallocated = unallocated;
5178 #else
5179 ptr = xmalloc (sizeof (thash_t));
5181 #endif
5183 alloc_counts[ (int) alloc_type_thash ].total_alloc++;
5184 *ptr = initial_thash;
5185 return ptr;
5189 /* Allocate structure, union, or enum tag information. */
5191 static tag_t *
5192 allocate_tag (void)
5194 tag_t *ptr;
5195 static tag_t initial_tag;
5197 #ifndef MALLOC_CHECK
5198 ptr = alloc_counts[ (int) alloc_type_tag ].free_list.f_tag;
5199 if (ptr != (tag_t *) 0)
5200 alloc_counts[ (int) alloc_type_tag ].free_list.f_tag = ptr->free;
5202 else
5204 int unallocated = alloc_counts[ (int) alloc_type_tag ].unallocated;
5205 page_t *cur_page = alloc_counts[ (int) alloc_type_tag ].cur_page;
5207 if (unallocated == 0)
5209 unallocated = PAGE_SIZE / sizeof (tag_t);
5210 alloc_counts[ (int) alloc_type_tag ].cur_page = cur_page = allocate_page ();
5211 alloc_counts[ (int) alloc_type_tag ].total_pages++;
5214 ptr = &cur_page->tag[ --unallocated ];
5215 alloc_counts[ (int) alloc_type_tag ].unallocated = unallocated;
5218 #else
5219 ptr = xmalloc (sizeof (tag_t));
5221 #endif
5223 alloc_counts[ (int) alloc_type_tag ].total_alloc++;
5224 *ptr = initial_tag;
5225 return ptr;
5228 /* Free scoping information. */
5230 static void
5231 free_tag (tag_t *ptr)
5233 alloc_counts[ (int) alloc_type_tag ].total_free++;
5235 #ifndef MALLOC_CHECK
5236 ptr->free = alloc_counts[ (int) alloc_type_tag ].free_list.f_tag;
5237 alloc_counts[ (int) alloc_type_tag ].free_list.f_tag = ptr;
5239 #else
5240 free (ptr);
5241 #endif
5246 /* Allocate forward reference to a yet unknown tag. */
5248 static forward_t *
5249 allocate_forward (void)
5251 forward_t *ptr;
5252 static forward_t initial_forward;
5254 #ifndef MALLOC_CHECK
5255 ptr = alloc_counts[ (int) alloc_type_forward ].free_list.f_forward;
5256 if (ptr != (forward_t *) 0)
5257 alloc_counts[ (int) alloc_type_forward ].free_list.f_forward = ptr->free;
5259 else
5261 int unallocated = alloc_counts[ (int) alloc_type_forward ].unallocated;
5262 page_t *cur_page = alloc_counts[ (int) alloc_type_forward ].cur_page;
5264 if (unallocated == 0)
5266 unallocated = PAGE_SIZE / sizeof (forward_t);
5267 alloc_counts[ (int) alloc_type_forward ].cur_page = cur_page = allocate_page ();
5268 alloc_counts[ (int) alloc_type_forward ].total_pages++;
5271 ptr = &cur_page->forward[ --unallocated ];
5272 alloc_counts[ (int) alloc_type_forward ].unallocated = unallocated;
5275 #else
5276 ptr = xmalloc (sizeof (forward_t));
5278 #endif
5280 alloc_counts[ (int) alloc_type_forward ].total_alloc++;
5281 *ptr = initial_forward;
5282 return ptr;
5285 /* Free scoping information. */
5287 static void
5288 free_forward (forward_t *ptr)
5290 alloc_counts[ (int) alloc_type_forward ].total_free++;
5292 #ifndef MALLOC_CHECK
5293 ptr->free = alloc_counts[ (int) alloc_type_forward ].free_list.f_forward;
5294 alloc_counts[ (int) alloc_type_forward ].free_list.f_forward = ptr;
5296 #else
5297 free (ptr);
5298 #endif
5303 /* Allocate head of type hash list. */
5305 static thead_t *
5306 allocate_thead (void)
5308 thead_t *ptr;
5309 static thead_t initial_thead;
5311 #ifndef MALLOC_CHECK
5312 ptr = alloc_counts[ (int) alloc_type_thead ].free_list.f_thead;
5313 if (ptr != (thead_t *) 0)
5314 alloc_counts[ (int) alloc_type_thead ].free_list.f_thead = ptr->free;
5316 else
5318 int unallocated = alloc_counts[ (int) alloc_type_thead ].unallocated;
5319 page_t *cur_page = alloc_counts[ (int) alloc_type_thead ].cur_page;
5321 if (unallocated == 0)
5323 unallocated = PAGE_SIZE / sizeof (thead_t);
5324 alloc_counts[ (int) alloc_type_thead ].cur_page = cur_page = allocate_page ();
5325 alloc_counts[ (int) alloc_type_thead ].total_pages++;
5328 ptr = &cur_page->thead[ --unallocated ];
5329 alloc_counts[ (int) alloc_type_thead ].unallocated = unallocated;
5332 #else
5333 ptr = xmalloc (sizeof (thead_t));
5335 #endif
5337 alloc_counts[ (int) alloc_type_thead ].total_alloc++;
5338 *ptr = initial_thead;
5339 return ptr;
5342 /* Free scoping information. */
5344 static void
5345 free_thead (thead_t *ptr)
5347 alloc_counts[ (int) alloc_type_thead ].total_free++;
5349 #ifndef MALLOC_CHECK
5350 ptr->free = (thead_t *) alloc_counts[ (int) alloc_type_thead ].free_list.f_thead;
5351 alloc_counts[ (int) alloc_type_thead ].free_list.f_thead = ptr;
5353 #else
5354 free (ptr);
5355 #endif
5359 /* Output an error message and exit. */
5361 void
5362 fatal (const char *format, ...)
5364 va_list ap;
5366 va_start (ap, format);
5368 if (line_number > 0)
5369 fprintf (stderr, "%s, %s:%ld ", progname, input_name, line_number);
5370 else
5371 fprintf (stderr, "%s:", progname);
5373 vfprintf (stderr, format, ap);
5374 va_end (ap);
5375 fprintf (stderr, "\n");
5376 if (line_number > 0)
5377 fprintf (stderr, "line:\t%s\n", cur_line_start);
5379 exit (1);
5382 void
5383 error (const char *format, ...)
5385 va_list ap;
5387 va_start (ap, format);
5389 if (line_number > 0)
5390 fprintf (stderr, "%s, %s:%ld ", progname, input_name, line_number);
5391 else
5392 fprintf (stderr, "%s:", progname);
5394 vfprintf (stderr, format, ap);
5395 fprintf (stderr, "\n");
5396 if (line_number > 0)
5397 fprintf (stderr, "line:\t%s\n", cur_line_start);
5399 had_errors++;
5400 va_end (ap);
5403 /* More 'friendly' abort that prints the line and file. */
5405 void
5406 fancy_abort (const char *file, int line, const char *func)
5408 fatal ("abort in %s, at %s:%d", func, file, line);
5412 /* When `malloc.c' is compiled with `rcheck' defined,
5413 it calls this function to report clobberage. */
5415 void
5416 botch (const char *s)
5418 fatal ("%s", s);