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