Commit | Line | Data |
---|---|---|
0fc6e47b KB |
1 | /*- |
2 | * Copyright (c) 1980 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
af359dea C |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions | |
7 | * are met: | |
8 | * 1. Redistributions of source code must retain the above copyright | |
9 | * notice, this list of conditions and the following disclaimer. | |
10 | * 2. Redistributions in binary form must reproduce the above copyright | |
11 | * notice, this list of conditions and the following disclaimer in the | |
12 | * documentation and/or other materials provided with the distribution. | |
13 | * 3. All advertising materials mentioning features or use of this software | |
14 | * must display the following acknowledgement: | |
15 | * This product includes software developed by the University of | |
16 | * California, Berkeley and its contributors. | |
17 | * 4. Neither the name of the University nor the names of its contributors | |
18 | * may be used to endorse or promote products derived from this software | |
19 | * without specific prior written permission. | |
20 | * | |
21 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
31 | * SUCH DAMAGE. | |
252367af | 32 | */ |
b721c131 | 33 | |
b1148f06 | 34 | #ifndef lint |
af359dea | 35 | static char sccsid[] = "@(#)stab.c 5.4 (Berkeley) 4/16/91"; |
0fc6e47b | 36 | #endif /* not lint */ |
c6ae69c6 PK |
37 | |
38 | /* | |
f67e1704 | 39 | * Procedures to put out symbol table information |
b721c131 | 40 | * and stabs for separate compilation type checking. |
f67e1704 | 41 | * These use the .stabs, .stabn, and .stabd directives. |
c6ae69c6 PK |
42 | */ |
43 | ||
c6ae69c6 PK |
44 | #include "whoami.h" |
45 | #ifdef PC | |
46 | /* and the rest of the file */ | |
47 | # include "0.h" | |
1ba5ecf2 | 48 | # include "objfmt.h" |
73eeab33 | 49 | # include "yy.h" |
c6ae69c6 PK |
50 | # include <stab.h> |
51 | ||
99f6998f PK |
52 | /* |
53 | * additional symbol definition for <stab.h> | |
54 | * that is used by the separate compilation facility -- | |
55 | * eventually, <stab.h> should be updated to include this | |
56 | */ | |
c6ae69c6 | 57 | |
99f6998f | 58 | # include "pstab.h" |
c6ae69c6 PK |
59 | # include "pc.h" |
60 | ||
f67e1704 KM |
61 | |
62 | #define private static | |
63 | ||
64 | int oldway = 0; | |
65 | ||
b721c131 PK |
66 | /* |
67 | * absolute value: line numbers are negative if error recovery. | |
68 | */ | |
69 | #define ABS( x ) ( x < 0 ? -x : x ) | |
3b091403 | 70 | long checksum(); |
b721c131 | 71 | |
f67e1704 KM |
72 | /* |
73 | * Generate information about variables. | |
74 | */ | |
75 | ||
76 | stabgvar (p, length, line) | |
77 | struct nl *p; | |
78 | int length, line; | |
79 | { | |
80 | putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x", | |
81 | 0, p->symbol, N_PC, N_PGVAR, ABS(line) | |
82 | ); | |
83 | if (oldway != 0) { | |
84 | oldstabgvar(p->symbol, p2type(p->type), 0, length, line); | |
85 | } else if (opt('g')) { | |
86 | putprintf("\t.stabs\t\"%s:G", 1, p->symbol); | |
87 | gentype(p->type); | |
88 | putprintf("\",0x%x,0,0x%x,0", 0, N_GSYM, length); | |
89 | } | |
90 | } | |
91 | ||
92 | stablvar (p, offset, length) | |
93 | struct nl *p; | |
94 | int offset, length; | |
95 | { | |
96 | int level; | |
97 | ||
98 | level = (p->nl_block & 037); | |
99 | if (oldway != 0) { | |
100 | oldstablvar(p->symbol, p2type(p->type), level, offset, length); | |
101 | } else if (opt('g')) { | |
102 | putprintf("\t.stabs\t\"%s:", 1, p->symbol); | |
103 | gentype(p->type); | |
104 | putprintf("\",0x%x,0,0x%x,0x%x", 0, N_LSYM, length, offset); | |
105 | } | |
106 | } | |
107 | ||
c6ae69c6 | 108 | /* |
c5e061f2 | 109 | * global variables |
c6ae69c6 | 110 | */ |
b1148f06 | 111 | /*ARGSUSED*/ |
f67e1704 | 112 | oldstabgvar( name , type , offset , length , line ) |
c6ae69c6 PK |
113 | char *name; |
114 | int type; | |
c6ae69c6 PK |
115 | int offset; |
116 | int length; | |
b721c131 | 117 | int line; |
c6ae69c6 | 118 | { |
c6ae69c6 PK |
119 | if ( ! opt('g') ) { |
120 | return; | |
121 | } | |
122 | putprintf( " .stabs \"" , 1 ); | |
b1148f06 | 123 | putprintf( NAMEFORMAT , 1 , (int) name ); |
c5e061f2 | 124 | putprintf( "\",0x%x,0,0x%x,0" , 0 , N_GSYM , type ); |
c6ae69c6 | 125 | putprintf( " .stabs \"" , 1 ); |
b1148f06 | 126 | putprintf( NAMEFORMAT , 1 , (int) name ); |
b721c131 | 127 | putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length ); |
c5e061f2 PK |
128 | } |
129 | ||
130 | /* | |
131 | * local variables | |
132 | */ | |
b1148f06 | 133 | /*ARGSUSED*/ |
f67e1704 | 134 | oldstablvar( name , type , level , offset , length ) |
c5e061f2 PK |
135 | char *name; |
136 | int type; | |
137 | int level; | |
138 | int offset; | |
139 | int length; | |
140 | { | |
c6ae69c6 | 141 | |
c5e061f2 PK |
142 | if ( ! opt('g') ) { |
143 | return; | |
144 | } | |
145 | putprintf( " .stabs \"" , 1 ); | |
b1148f06 | 146 | putprintf( NAMEFORMAT , 1 , (int) name ); |
c5e061f2 PK |
147 | putprintf( "\",0x%x,0,0x%x,0x%x" , 0 , N_LSYM , type , -offset ); |
148 | putprintf( " .stabs \"" , 1 ); | |
b1148f06 | 149 | putprintf( NAMEFORMAT , 1 , (int) name ); |
c5e061f2 | 150 | putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length ); |
c6ae69c6 PK |
151 | } |
152 | ||
153 | ||
f67e1704 KM |
154 | stabparam (p, offset, length) |
155 | struct nl *p; | |
156 | int offset, length; | |
157 | { | |
158 | if (oldway != 0) { | |
159 | oldstabparam(p->symbol, p2type(p->type), offset, length); | |
160 | } else if (opt('g')) { | |
161 | putprintf("\t.stabs\t\"%s:", 1, p->symbol); | |
162 | if (p->class == REF) { | |
163 | putprintf("v", 1); | |
164 | } else { | |
165 | putprintf("p", 1); | |
166 | } | |
167 | gentype((p->class == FPROC || p->class ==FFUNC) ? p : p->type); | |
168 | putprintf("\",0x%x,0,0x%x,0x%x", 0, N_PSYM, length, offset); | |
169 | } | |
170 | } | |
171 | ||
c6ae69c6 PK |
172 | /* |
173 | * parameters | |
174 | */ | |
f67e1704 | 175 | oldstabparam( name , type , offset , length ) |
c6ae69c6 PK |
176 | char *name; |
177 | int type; | |
178 | int offset; | |
179 | int length; | |
180 | { | |
181 | ||
182 | if ( ! opt('g') ) { | |
183 | return; | |
184 | } | |
185 | putprintf( " .stabs \"" , 1 ); | |
b1148f06 | 186 | putprintf( NAMEFORMAT , 1 , (int) name ); |
b721c131 | 187 | putprintf( "\",0x%x,0,0x%x,0x%x" , 0 , N_PSYM , type , offset ); |
c6ae69c6 | 188 | putprintf( " .stabs \"" , 1 ); |
b1148f06 | 189 | putprintf( NAMEFORMAT , 1 , (int) name ); |
b721c131 | 190 | putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length ); |
c6ae69c6 PK |
191 | } |
192 | ||
193 | /* | |
194 | * fields | |
195 | */ | |
c6ae69c6 PK |
196 | |
197 | /* | |
198 | * left brackets | |
f67e1704 | 199 | * (dbx handles module-2 without these, so we won't use them either) |
c6ae69c6 PK |
200 | */ |
201 | stablbrac( level ) | |
202 | int level; | |
203 | { | |
204 | ||
f67e1704 | 205 | if ( ! opt('g') || oldway == 0 ) { |
c6ae69c6 PK |
206 | return; |
207 | } | |
b721c131 | 208 | putprintf( " .stabd 0x%x,0,0x%x" , 0 , N_LBRAC , level ); |
c6ae69c6 PK |
209 | } |
210 | ||
211 | /* | |
212 | * right brackets | |
213 | */ | |
214 | stabrbrac( level ) | |
215 | int level; | |
216 | { | |
217 | ||
f67e1704 | 218 | if ( ! opt('g') || oldway == 0 ) { |
c6ae69c6 PK |
219 | return; |
220 | } | |
b721c131 | 221 | putprintf( " .stabd 0x%x,0,0x%x" , 0 , N_RBRAC , level ); |
c6ae69c6 PK |
222 | } |
223 | ||
f67e1704 KM |
224 | stabfunc (p, name, line, level) |
225 | struct nl *p; | |
226 | char *name; | |
227 | int line, level; | |
228 | { | |
229 | char extname[BUFSIZ],nestspec[BUFSIZ]; | |
230 | ||
231 | if ( level == 1 ) { | |
232 | if (p->class == FUNC) { | |
233 | putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x" , | |
234 | 0 , name , N_PC , N_PGFUNC , ABS( line ) | |
235 | ); | |
236 | } else if (p->class == PROC) { | |
237 | putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x" , | |
238 | 0 , name , N_PC , N_PGPROC , ABS( line ) | |
239 | ); | |
240 | } | |
241 | } | |
242 | if (oldway != 0) { | |
243 | oldstabfunc(name, p->class, line, level); | |
244 | } else if (opt('g')) { | |
245 | putprintf("\t.stabs\t\"%s:", 1, name); | |
246 | if (p->class == FUNC) { | |
247 | putprintf("F", 1); | |
248 | gentype(p->type); | |
249 | putprintf(",", 1); | |
250 | } else { | |
251 | putprintf("P,", 1); | |
252 | } | |
253 | sextname(extname, name, level); /* set extname to entry label */ | |
254 | putprintf("%s,", 1, &(extname[1])); /* remove initial underbar */ | |
255 | snestspec(nestspec, level); | |
256 | putprintf("%s\",0x%x,0,0,%s", 0, nestspec, N_FUN, extname); | |
257 | } | |
258 | } | |
259 | ||
260 | /* | |
261 | * construct the colon-separated static nesting string into a | |
262 | * caller-supplied buffer | |
263 | */ | |
264 | private snestspec(buffer, level) | |
265 | char buffer[]; | |
266 | int level; | |
267 | { | |
268 | char *starthere; | |
269 | int i; | |
270 | ||
271 | if (level <= 1) { | |
272 | buffer[0] = '\0'; | |
273 | } else { | |
274 | starthere = &buffer[0]; | |
275 | for ( i = 1 ; i < level ; i++ ) { | |
276 | sprintf(starthere, "%s:", enclosing[i]); | |
277 | starthere += strlen(enclosing[i]) + 1; | |
278 | } | |
a7081ede | 279 | *--starthere = '\0'; /* remove last colon */ |
f67e1704 KM |
280 | if (starthere >= &buffer[BUFSIZ-1]) { |
281 | panic("snestspec"); | |
282 | } | |
283 | } | |
284 | } | |
285 | ||
c6ae69c6 PK |
286 | /* |
287 | * functions | |
288 | */ | |
f67e1704 | 289 | oldstabfunc( name , typeclass , line , level ) |
c6ae69c6 | 290 | char *name; |
270467f1 | 291 | int typeclass; |
c6ae69c6 PK |
292 | int line; |
293 | long level; | |
294 | { | |
078a6e08 | 295 | char extname[ BUFSIZ ]; |
c6ae69c6 | 296 | |
b721c131 PK |
297 | /* |
298 | * for sdb | |
299 | */ | |
c6ae69c6 PK |
300 | if ( ! opt('g') ) { |
301 | return; | |
302 | } | |
303 | putprintf( " .stabs \"" , 1 ); | |
b1148f06 KM |
304 | putprintf( NAMEFORMAT , 1 , (int) name ); |
305 | sextname( extname , name , (int) level ); | |
306 | putprintf( "\",0x%x,0,0x%x,%s" , 0 , N_FUN , line , (int) extname ); | |
c6ae69c6 PK |
307 | } |
308 | ||
309 | /* | |
310 | * source line numbers | |
311 | */ | |
312 | stabline( line ) | |
313 | int line; | |
314 | { | |
315 | if ( ! opt('g') ) { | |
316 | return; | |
317 | } | |
b721c131 | 318 | putprintf( " .stabd 0x%x,0,0x%x" , 0 , N_SLINE , ABS( line ) ); |
c6ae69c6 PK |
319 | } |
320 | ||
321 | /* | |
f67e1704 KM |
322 | * source files get none or more of these: |
323 | * one as they are entered, | |
324 | * and one every time they are returned to from nested #includes | |
c6ae69c6 | 325 | */ |
f67e1704 | 326 | stabsource(filename, firsttime) |
c6ae69c6 | 327 | char *filename; |
f67e1704 | 328 | bool firsttime; |
73eeab33 PK |
329 | { |
330 | int label; | |
331 | ||
332 | /* | |
333 | * for separate compilation | |
334 | */ | |
335 | putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x", 0, | |
24cec487 | 336 | (int) filename, N_PC, N_PSO, N_FLAGCHECKSUM); |
73eeab33 | 337 | /* |
f67e1704 | 338 | * for debugger |
73eeab33 PK |
339 | */ |
340 | if ( ! opt('g') ) { | |
341 | return; | |
c6ae69c6 | 342 | } |
f67e1704 | 343 | if (oldway != 0) { |
d71f4c92 | 344 | label = (int) getlab(); |
f67e1704 KM |
345 | putprintf( " .stabs \"" , 1 ); |
346 | putprintf( NAMEFORMAT , 1 , filename ); | |
347 | putprintf( "\",0x%x,0,0," , 1 , N_SO ); | |
348 | putprintf( PREFIXFORMAT , 0 , LLABELPREFIX , label ); | |
349 | putprintf( PREFIXFORMAT , 1 , LLABELPREFIX , label ); | |
350 | putprintf( ":" , 0 ); | |
351 | } else { | |
352 | if (firsttime) { | |
353 | putprintf( " .stabs \"" , 1 ); | |
354 | putprintf( NAMEFORMAT , 1 , filename ); | |
355 | putprintf( "\",0x%x,0,0,0" , 0 , N_SO ); | |
356 | } | |
357 | } | |
73eeab33 | 358 | } |
c6ae69c6 PK |
359 | |
360 | /* | |
361 | * included files get one or more of these: | |
362 | * one as they are entered by a #include, | |
73eeab33 | 363 | * and one every time they are returned to from nested #includes. |
c6ae69c6 | 364 | */ |
73eeab33 | 365 | stabinclude(filename, firsttime) |
c6ae69c6 | 366 | char *filename; |
73eeab33 PK |
367 | bool firsttime; |
368 | { | |
24cec487 | 369 | int label; |
73eeab33 PK |
370 | long check; |
371 | ||
372 | /* | |
373 | * for separate compilation | |
374 | */ | |
375 | if (firsttime) { | |
376 | check = checksum(filename); | |
377 | } else { | |
378 | check = N_FLAGCHECKSUM; | |
c6ae69c6 | 379 | } |
73eeab33 | 380 | putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x", 0, |
24cec487 | 381 | (int) filename, N_PC, N_PSOL, check); |
73eeab33 PK |
382 | /* |
383 | * for sdb | |
384 | */ | |
385 | if ( ! opt('g') ) { | |
386 | return; | |
387 | } | |
f67e1704 | 388 | if (oldway != 0) { |
d71f4c92 | 389 | label = (int) getlab(); |
f67e1704 KM |
390 | putprintf( " .stabs \"" , 1 ); |
391 | putprintf( NAMEFORMAT , 1 , filename ); | |
392 | putprintf( "\",0x%x,0,0," , 1 , N_SOL ); | |
393 | putprintf( PREFIXFORMAT , 0 , LLABELPREFIX , label ); | |
394 | putprintf( PREFIXFORMAT , 1 , LLABELPREFIX , label ); | |
395 | putprintf( ":" , 0 ); | |
396 | } | |
73eeab33 | 397 | } |
c6ae69c6 | 398 | |
73eeab33 PK |
399 | /* |
400 | * anyone know a good checksum for ascii files? | |
401 | * this does a rotate-left and then exclusive-or's in the character. | |
402 | * also, it avoids returning checksums of 0. | |
403 | * The rotate is implemented by shifting and adding back the | |
404 | * sign bit when negative. | |
405 | */ | |
406 | long | |
407 | checksum(filename) | |
408 | char *filename; | |
409 | { | |
410 | FILE *filep; | |
411 | register int input; | |
412 | register long check; | |
413 | ||
414 | filep = fopen(filename, "r"); | |
415 | if (filep == NULL) { | |
416 | perror(filename); | |
417 | pexit(DIED); | |
418 | } | |
419 | check = 0; | |
420 | while ((input = getc(filep)) != EOF) { | |
421 | if (check < 0) { | |
422 | check <<= 1; | |
423 | check += 1; | |
424 | } else { | |
425 | check <<= 1; | |
426 | } | |
427 | check ^= input; | |
428 | } | |
3b091403 | 429 | (void) fclose(filep); |
73eeab33 PK |
430 | if ((unsigned) check <= N_FLAGCHECKSUM) { |
431 | return N_FLAGCHECKSUM + 1; | |
432 | } else { | |
433 | return check; | |
434 | } | |
435 | } | |
c6ae69c6 PK |
436 | |
437 | /* | |
438 | * global Pascal symbols : | |
439 | * labels, types, constants, and external procedure and function names: | |
440 | * These are used by the separate compilation facility | |
441 | * to be able to check for disjoint header files. | |
c6ae69c6 PK |
442 | */ |
443 | ||
b721c131 PK |
444 | /* |
445 | * global labels | |
446 | */ | |
99f6998f | 447 | stabglabel( label , line ) |
b721c131 PK |
448 | char *label; |
449 | int line; | |
c6ae69c6 | 450 | { |
c6ae69c6 | 451 | |
99f6998f | 452 | putprintf( " .stabs \"%s\",0x%x,0,0x%x,0x%x" , 0 |
b1148f06 | 453 | , (int) label , N_PC , N_PGLABEL , ABS( line ) ); |
c6ae69c6 PK |
454 | } |
455 | ||
b721c131 PK |
456 | /* |
457 | * global constants | |
458 | */ | |
28424b27 KB |
459 | stabgconst( constant , line ) |
460 | char *constant; | |
b721c131 | 461 | int line; |
c6ae69c6 | 462 | { |
c6ae69c6 | 463 | |
99f6998f | 464 | putprintf( " .stabs \"%s\",0x%x,0,0x%x,0x%x" , 0 |
28424b27 | 465 | , (int) constant , N_PC , N_PGCONST , ABS( line ) ); |
c6ae69c6 PK |
466 | } |
467 | ||
f67e1704 KM |
468 | /* |
469 | * Generate symbolic information about a constant. | |
470 | */ | |
c6ae69c6 | 471 | |
95f51977 C |
472 | stabconst (c) |
473 | struct nl *c; | |
474 | { | |
475 | if (opt('g') && oldway == 0) { | |
476 | putprintf("\t.stabs\t\"%s:c=", 1, c->symbol); | |
477 | if (c->type == nl + TSTR) { | |
478 | putprintf("s'%s'", 1, c->ptr[0]); | |
479 | } else if (c->type == nl + T1CHAR) { | |
480 | putprintf("c%d", 1, c->range[0]); | |
481 | } else if (isa(c->type, "i")) { | |
482 | putprintf("i%d", 1, c->range[0]); | |
483 | } else if (isa(c->type, "d")) { | |
484 | putprintf("r%g", 1, c->real); | |
485 | } else { | |
486 | putprintf("e", 1); | |
487 | gentype(c->type); | |
488 | putprintf(",%d", 1, c->range[0]); | |
489 | } | |
490 | putprintf("\",0x%x,0,0x%x,0x%x", 0, N_LSYM, 0, 0); | |
c6ae69c6 | 491 | } |
f67e1704 | 492 | } |
c6ae69c6 | 493 | |
f67e1704 KM |
494 | stabgtype (name, type, line) |
495 | char *name; | |
496 | struct nl *type; | |
497 | int line; | |
498 | { | |
499 | putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x" , | |
500 | 0, name, N_PC , N_PGTYPE, ABS(line) | |
501 | ); | |
502 | if (oldway == 0) { | |
503 | stabltype(name, type); | |
504 | } | |
505 | } | |
506 | ||
507 | stabltype (name, type) | |
508 | char *name; | |
509 | struct nl *type; | |
510 | { | |
511 | if (opt('g')) { | |
512 | putprintf("\t.stabs\t\"%s:t", 1, name); | |
513 | gentype(type); | |
514 | putprintf("\",0x%x,0,0,0", 0, N_LSYM); | |
515 | } | |
516 | } | |
c6ae69c6 | 517 | |
b721c131 PK |
518 | /* |
519 | * external functions and procedures | |
520 | */ | |
270467f1 | 521 | stabefunc( name , typeclass , line ) |
b721c131 | 522 | char *name; |
270467f1 | 523 | int typeclass; |
b721c131 | 524 | int line; |
c6ae69c6 | 525 | { |
b721c131 | 526 | int type; |
c6ae69c6 | 527 | |
270467f1 | 528 | if ( typeclass == FUNC ) { |
99f6998f | 529 | type = N_PEFUNC; |
270467f1 | 530 | } else if ( typeclass == PROC ) { |
99f6998f | 531 | type = N_PEPROC; |
b721c131 PK |
532 | } else { |
533 | return; | |
c6ae69c6 | 534 | } |
99f6998f | 535 | putprintf( " .stabs \"%s\",0x%x,0,0x%x,0x%x" , 0 |
b1148f06 | 536 | , (int) name , N_PC , type , ABS( line ) ); |
c6ae69c6 PK |
537 | } |
538 | ||
f67e1704 KM |
539 | /* |
540 | * Generate type information encoded as a string for dbx. | |
541 | * The fwdptrnum field is used only when the type is a pointer | |
542 | * to a type that isn't known when it was entered. When the | |
543 | * type field is filled for some such tptr, fixfwdtype should | |
544 | * be called to output an equivalencing type definition. | |
545 | */ | |
546 | ||
547 | typedef struct TypeDesc *TypeDesc; | |
548 | ||
549 | struct TypeDesc { | |
550 | struct nl *tptr; | |
551 | int tnum; | |
552 | int fwdptrnum; | |
553 | TypeDesc chain; | |
554 | }; | |
555 | ||
556 | #define TABLESIZE 2003 | |
557 | ||
558 | #define typehash(t) ( ( ((int) t) >> 2 ) % TABLESIZE ) | |
559 | ||
560 | private int tcount = 1; | |
561 | private TypeDesc typetable[TABLESIZE]; | |
562 | ||
563 | private TypeDesc tdlookup (t) | |
564 | struct nl *t; | |
565 | { | |
566 | register TypeDesc td; | |
567 | ||
568 | td = typetable[typehash(t)]; | |
569 | while (td != NIL && td->tptr != t) { | |
570 | td = td->chain; | |
571 | } | |
572 | return td; | |
573 | } | |
574 | ||
575 | private int typelookup (t) | |
576 | struct nl *t; | |
577 | { | |
578 | register TypeDesc td; | |
579 | int r; | |
580 | ||
581 | td = tdlookup(t); | |
582 | if (td == NIL) { | |
583 | r = 0; | |
584 | } else { | |
585 | r = td->tnum; | |
586 | } | |
587 | return r; | |
588 | } | |
589 | ||
590 | private int entertype (type) | |
591 | struct nl *type; | |
592 | { | |
593 | register TypeDesc td; | |
594 | register int i; | |
595 | ||
596 | td = (TypeDesc) malloc(sizeof(struct TypeDesc)); | |
597 | td->tptr = type; | |
598 | td->tnum = tcount; | |
599 | td->fwdptrnum = 0; | |
600 | ++tcount; | |
601 | i = typehash(type); | |
602 | td->chain = typetable[i]; | |
603 | typetable[i] = td; | |
604 | return td->tnum; | |
605 | } | |
606 | ||
607 | /* | |
608 | * The in_types table currently contains "boolean", "char", "integer", | |
609 | * "real" and "_nil". (See nl.c for definition.) | |
610 | * The lookup call below will give the TYPE class nl entry for these | |
611 | * types. In each case except _nil, the type field of that entry is a RANGE | |
612 | * class nl entry for the type. Sometimes other symbol table entries | |
613 | * point to the TYPE entry (e.g., when there is a range over the base type), | |
614 | * and other entries point to the RANGE entry (e.g., for a variable of the | |
615 | * given type). We don't really want to distinguish between these uses | |
616 | * in dbx, and since it appears that the RANGE entries are not reused if | |
617 | * a range happens to coincide, we will give the two the same identifying | |
618 | * dbx type number. | |
619 | */ | |
620 | ||
621 | private inittypes() | |
622 | { | |
623 | int i; | |
624 | extern char *in_types[]; | |
625 | struct nl *p; | |
626 | ||
627 | for (i = 0; in_types[i] != NIL; i++) { | |
628 | p = lookup(in_types[i]); | |
629 | if (p != NIL) { | |
630 | entertype(p); | |
631 | if (p->type != NIL) { | |
632 | --tcount; /* see comment above */ | |
633 | entertype(p->type); | |
634 | } | |
635 | } | |
636 | } | |
637 | } | |
638 | ||
639 | static genarray (t) | |
640 | struct nl *t; | |
641 | { | |
642 | register struct nl *p; | |
643 | ||
f67e1704 | 644 | for (p = t->chain; p != NIL; p = p->chain) { |
a7081ede | 645 | putprintf("a", 1); |
f67e1704 KM |
646 | gentype(p); |
647 | putprintf(";", 1); | |
648 | } | |
649 | gentype(t->type); | |
650 | } | |
651 | ||
652 | /* | |
653 | * Really we should walk through ptr[NL_FIELDLIST] for the fields, | |
654 | * and then do the variant tag and fields separately, but dbx | |
655 | * doesn't support this yet. | |
656 | * So, since all the fields of all the variants are on the chain, | |
657 | * we walk through that. Except that this gives the fields in the | |
658 | * reverse order, so we want to print in reverse order. | |
659 | */ | |
660 | ||
661 | static genrecord (t) | |
662 | struct nl *t; | |
663 | { | |
664 | putprintf("s%d", 1, t->value[NL_OFFS]); | |
665 | if (t->chain != NIL) { | |
666 | genrecfield(t->chain, 1); | |
667 | } | |
668 | putprintf(";", 1); | |
669 | } | |
670 | ||
671 | static genrecfield (t, n) | |
672 | struct nl *t; | |
673 | int n; | |
674 | { | |
675 | if (t->chain != NULL) { | |
676 | genrecfield(t->chain, n + 1); | |
677 | if (n % 2 == 0) { | |
678 | gencontinue(); | |
679 | } | |
680 | } | |
681 | putprintf("%s:", 1, t->symbol); | |
682 | gentype(t->type); | |
683 | putprintf(",%d,%d;", 1, 8*t->value[NL_OFFS], 8*lwidth(t->type)); | |
684 | } | |
685 | ||
686 | static genvarnt (t) | |
687 | struct nl *t; | |
688 | { | |
689 | genrecord(t); | |
690 | } | |
691 | ||
692 | static genptr (t) | |
693 | struct nl *t; | |
694 | { | |
695 | register TypeDesc td; | |
696 | ||
697 | putprintf("*", 1); | |
698 | if (t->type != NIL) { | |
699 | gentype(t->type); | |
700 | } else { | |
701 | /* | |
702 | * unresolved forward pointer: use tcount to represent what is | |
703 | * begin pointed to, to be defined later | |
704 | */ | |
705 | td = tdlookup(t); | |
706 | if (td == NIL) { | |
707 | panic("nil ptr in stab.genptr"); | |
708 | } | |
709 | td->fwdptrnum = tcount; | |
710 | putprintf("%d", 1, tcount); | |
711 | ++tcount; | |
712 | } | |
713 | } | |
714 | ||
715 | /* | |
716 | * The type t is a pointer which has just had its type field filled. | |
717 | * We need to generate a type stab saying that the number saved | |
718 | * in t's fwdptrnum is the same as the t->type's number | |
719 | */ | |
720 | ||
721 | fixfwdtype (t) | |
722 | struct nl *t; | |
723 | { | |
724 | register TypeDesc td; | |
725 | ||
726 | if (opt('g') && oldway == 0) { | |
727 | td = tdlookup(t); | |
728 | if (td != NIL) { | |
729 | putprintf("\t.stabs\t\":t%d=", 1, td->fwdptrnum); | |
730 | gentype(t->type); | |
731 | putprintf("\",0x%x,0,0,0", 0, N_LSYM); | |
732 | } | |
733 | } | |
734 | } | |
735 | ||
736 | static genenum (t) | |
737 | struct nl *t; | |
738 | { | |
739 | register struct nl *e; | |
740 | register int i; | |
741 | ||
742 | putprintf("e", 1); | |
743 | i = 1; | |
744 | e = t->chain; | |
745 | while (e != NULL) { | |
746 | if (i > 2) { | |
747 | gencontinue(); | |
748 | i = 0; | |
749 | } | |
750 | putprintf("%s:%d,", 1, e->symbol, e->range[0]); | |
751 | e = e->chain; | |
752 | ++i; | |
753 | } | |
754 | putprintf(";", 1); | |
755 | } | |
756 | ||
757 | static genset (t) | |
758 | struct nl *t; | |
759 | { | |
760 | putprintf("S", 1); | |
761 | gentype(t->type); | |
762 | } | |
763 | ||
764 | static genrange (t) | |
765 | struct nl *t; | |
766 | { | |
767 | putprintf("r", 1); | |
768 | gentype(t->type); | |
769 | putprintf(";%d;%d", 1, t->range[0], t->range[1]); | |
770 | } | |
771 | ||
772 | static genfparam (t) | |
773 | struct nl *t; | |
774 | { | |
775 | struct nl *p; | |
776 | int count; | |
777 | ||
778 | if (t->type != NULL) { | |
779 | putprintf("f", 1); | |
780 | gentype(t->type); | |
781 | putprintf(",", 1); | |
782 | } else { | |
783 | putprintf("p", 1); | |
784 | } | |
785 | count = 0; | |
786 | for (p = t->ptr[NL_FCHAIN]; p != NULL; p = p->chain) { | |
787 | ++count; | |
788 | } | |
789 | putprintf("%d;", 1, count); | |
790 | for (p = t->ptr[NL_FCHAIN]; p != NULL; p = p->chain) { | |
791 | gentype(p->type); | |
792 | putprintf(",%d;", 1, p->class); | |
793 | } | |
794 | } | |
795 | ||
796 | static genfile (t) | |
797 | struct nl *t; | |
798 | { | |
799 | putprintf("d", 1); | |
800 | gentype(t->type); | |
801 | } | |
802 | ||
803 | static gentype (t) | |
804 | struct nl *t; | |
805 | { | |
806 | int id; | |
807 | ||
808 | if (tcount == 1) { | |
809 | inittypes(); | |
810 | } | |
811 | id = typelookup(t); | |
812 | if (id != 0) { | |
813 | putprintf("%d", 1, id); | |
814 | } else if (t->class == SCAL && t->chain == NULL) { | |
815 | id = typelookup(t->type); | |
816 | if (id != 0) { | |
817 | putprintf("%d", 1, id); | |
818 | } else { | |
819 | genenum(t->type); | |
820 | } | |
821 | } else { | |
822 | id = entertype(t); | |
823 | putprintf("%d=", 1, id); | |
824 | switch (t->class) { | |
825 | case TYPE: | |
826 | gentype(t->type); | |
827 | break; | |
828 | ||
829 | case ARRAY: | |
830 | genarray(t); | |
831 | break; | |
832 | ||
833 | case RECORD: | |
834 | genrecord(t); | |
835 | break; | |
836 | ||
837 | case VARNT: | |
838 | genvarnt(t); | |
839 | break; | |
840 | ||
841 | case REF: | |
842 | gentype(t->type); | |
843 | break; | |
844 | ||
845 | case PTR: | |
846 | genptr(t); | |
847 | break; | |
848 | ||
849 | case SET: | |
850 | genset(t); | |
851 | break; | |
852 | ||
853 | case RANGE: | |
854 | genrange(t); | |
855 | break; | |
856 | ||
857 | case SCAL: | |
858 | genenum(t); | |
859 | break; | |
860 | ||
861 | case FPROC: | |
862 | case FFUNC: | |
863 | genfparam(t); | |
864 | break; | |
865 | ||
866 | case FILET: | |
867 | case PTRFILE: | |
868 | genfile(t); | |
869 | break; | |
870 | ||
871 | default: | |
872 | /* This shouldn't happen */ | |
873 | /* Rather than bomb outright, let debugging go on */ | |
874 | warning(); | |
875 | error("Bad type class found in stab"); | |
876 | putprintf("1", 1, t->class); | |
877 | break; | |
878 | } | |
879 | } | |
880 | } | |
881 | ||
882 | /* | |
883 | * Continue stab information in a namelist new entry. This is necessary | |
884 | * to avoid overflowing putprintf's buffer. | |
885 | */ | |
886 | ||
887 | static gencontinue () | |
888 | { | |
889 | putprintf("?\",0x%x,0,0,0", 0, N_LSYM); | |
890 | putprintf("\t.stabs\t\"", 1); | |
891 | } | |
892 | ||
c6ae69c6 | 893 | #endif PC |