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