BSD 4_3_Net_2 release
[unix-history] / usr / src / usr.bin / pascal / src / stab.c
CommitLineData
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 35static 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
64int 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 70long checksum();
b721c131 71
f67e1704
KM
72/*
73 * Generate information about variables.
74 */
75
76stabgvar (p, length, line)
77struct nl *p;
78int 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
92stablvar (p, offset, length)
93struct nl *p;
94int 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 112oldstabgvar( 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 134oldstablvar( 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
154stabparam (p, offset, length)
155struct nl *p;
156int 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 175oldstabparam( 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 */
201stablbrac( 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 */
214stabrbrac( 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
224stabfunc (p, name, line, level)
225struct nl *p;
226char *name;
227int 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 */
264private 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 289oldstabfunc( 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 */
312stabline( 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 326stabsource(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 365stabinclude(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 */
406long
407checksum(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 447stabglabel( 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
459stabgconst( 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
472stabconst (c)
473struct 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
494stabgtype (name, type, line)
495char *name;
496struct nl *type;
497int 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
507stabltype (name, type)
508char *name;
509struct 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 521stabefunc( 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
547typedef struct TypeDesc *TypeDesc;
548
549struct 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
560private int tcount = 1;
561private TypeDesc typetable[TABLESIZE];
562
563private TypeDesc tdlookup (t)
564struct 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
575private int typelookup (t)
576struct 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
590private int entertype (type)
591struct 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
621private 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
639static genarray (t)
640struct 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
661static genrecord (t)
662struct 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
671static genrecfield (t, n)
672struct nl *t;
673int 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
686static genvarnt (t)
687struct nl *t;
688{
689 genrecord(t);
690}
691
692static genptr (t)
693struct 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
721fixfwdtype (t)
722struct 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
736static genenum (t)
737struct 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
757static genset (t)
758struct nl *t;
759{
760 putprintf("S", 1);
761 gentype(t->type);
762}
763
764static genrange (t)
765struct nl *t;
766{
767 putprintf("r", 1);
768 gentype(t->type);
769 putprintf(";%d;%d", 1, t->range[0], t->range[1]);
770}
771
772static genfparam (t)
773struct 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
796static genfile (t)
797struct nl *t;
798{
799 putprintf("d", 1);
800 gentype(t->type);
801}
802
803static gentype (t)
804struct 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
887static gencontinue ()
888{
889 putprintf("?\",0x%x,0,0,0", 0, N_LSYM);
890 putprintf("\t.stabs\t\"", 1);
891}
892
c6ae69c6 893#endif PC