148116Sbostic /*-
2*62215Sbostic * Copyright (c) 1980, 1993
3*62215Sbostic * The Regents of the University of California. All rights reserved.
448116Sbostic *
548116Sbostic * %sccs.include.redist.c%
622191Sdist */
7772Speter
818355Smckusick #ifndef lint
9*62215Sbostic static char sccsid[] = "@(#)stab.c 8.1 (Berkeley) 06/06/93";
1048116Sbostic #endif /* not lint */
11826Speter
12772Speter /*
1318354Smckusick * Procedures to put out symbol table information
14826Speter * and stabs for separate compilation type checking.
1518354Smckusick * These use the .stabs, .stabn, and .stabd directives.
16772Speter */
17772Speter
18772Speter #include "whoami.h"
19772Speter #ifdef PC
20772Speter /* and the rest of the file */
21772Speter # include "0.h"
2210649Speter # include "objfmt.h"
2315952Smckusick # include "yy.h"
24772Speter # include <stab.h>
25772Speter
26842Speter /*
27842Speter * additional symbol definition for <stab.h>
28842Speter * that is used by the separate compilation facility --
29842Speter * eventually, <stab.h> should be updated to include this
30842Speter */
31772Speter
32842Speter # include "pstab.h"
33772Speter # include "pc.h"
34772Speter
3518354Smckusick
3618354Smckusick #define private static
3718354Smckusick
3818354Smckusick int oldway = 0;
3918354Smckusick
40772Speter /*
41826Speter * absolute value: line numbers are negative if error recovery.
42826Speter */
43826Speter #define ABS( x ) ( x < 0 ? -x : x )
4418355Smckusick long checksum();
45826Speter
4618354Smckusick /*
4718354Smckusick * Generate information about variables.
4818354Smckusick */
4918354Smckusick
5018354Smckusick stabgvar (p, length, line)
5118354Smckusick struct nl *p;
5218354Smckusick int length, line;
5318354Smckusick {
5418354Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x",
5518354Smckusick 0, p->symbol, N_PC, N_PGVAR, ABS(line)
5618354Smckusick );
5718354Smckusick if (oldway != 0) {
5818354Smckusick oldstabgvar(p->symbol, p2type(p->type), 0, length, line);
5918354Smckusick } else if (opt('g')) {
6018354Smckusick putprintf("\t.stabs\t\"%s:G", 1, p->symbol);
6118354Smckusick gentype(p->type);
6218354Smckusick putprintf("\",0x%x,0,0x%x,0", 0, N_GSYM, length);
6318354Smckusick }
6418354Smckusick }
6518354Smckusick
6618354Smckusick stablvar (p, offset, length)
6718354Smckusick struct nl *p;
6818354Smckusick int offset, length;
6918354Smckusick {
7018354Smckusick int level;
7118354Smckusick
7218354Smckusick level = (p->nl_block & 037);
7318354Smckusick if (oldway != 0) {
7418354Smckusick oldstablvar(p->symbol, p2type(p->type), level, offset, length);
7518354Smckusick } else if (opt('g')) {
7618354Smckusick putprintf("\t.stabs\t\"%s:", 1, p->symbol);
7718354Smckusick gentype(p->type);
7818354Smckusick putprintf("\",0x%x,0,0x%x,0x%x", 0, N_LSYM, length, offset);
7918354Smckusick }
8018354Smckusick }
8118354Smckusick
82826Speter /*
832164Speter * global variables
84772Speter */
8518355Smckusick /*ARGSUSED*/
oldstabgvar(name,type,offset,length,line)8618354Smckusick oldstabgvar( name , type , offset , length , line )
87772Speter char *name;
88772Speter int type;
89772Speter int offset;
90772Speter int length;
91826Speter int line;
92772Speter {
93772Speter if ( ! opt('g') ) {
94772Speter return;
95772Speter }
96772Speter putprintf( " .stabs \"" , 1 );
9718355Smckusick putprintf( NAMEFORMAT , 1 , (int) name );
982164Speter putprintf( "\",0x%x,0,0x%x,0" , 0 , N_GSYM , type );
992164Speter putprintf( " .stabs \"" , 1 );
10018355Smckusick putprintf( NAMEFORMAT , 1 , (int) name );
1012164Speter putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length );
1022164Speter }
1032164Speter
1042164Speter /*
1052164Speter * local variables
1062164Speter */
10718355Smckusick /*ARGSUSED*/
oldstablvar(name,type,level,offset,length)10818354Smckusick oldstablvar( name , type , level , offset , length )
1092164Speter char *name;
1102164Speter int type;
1112164Speter int level;
1122164Speter int offset;
1132164Speter int length;
1142164Speter {
1152164Speter
1162164Speter if ( ! opt('g') ) {
1172164Speter return;
118772Speter }
119772Speter putprintf( " .stabs \"" , 1 );
12018355Smckusick putprintf( NAMEFORMAT , 1 , (int) name );
1212164Speter putprintf( "\",0x%x,0,0x%x,0x%x" , 0 , N_LSYM , type , -offset );
1222164Speter putprintf( " .stabs \"" , 1 );
12318355Smckusick putprintf( NAMEFORMAT , 1 , (int) name );
124826Speter putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length );
125772Speter }
126772Speter
127772Speter
12818354Smckusick stabparam (p, offset, length)
12918354Smckusick struct nl *p;
13018354Smckusick int offset, length;
13118354Smckusick {
13218354Smckusick if (oldway != 0) {
13318354Smckusick oldstabparam(p->symbol, p2type(p->type), offset, length);
13418354Smckusick } else if (opt('g')) {
13518354Smckusick putprintf("\t.stabs\t\"%s:", 1, p->symbol);
13618354Smckusick if (p->class == REF) {
13718354Smckusick putprintf("v", 1);
13818354Smckusick } else {
13918354Smckusick putprintf("p", 1);
14018354Smckusick }
14118354Smckusick gentype((p->class == FPROC || p->class ==FFUNC) ? p : p->type);
14218354Smckusick putprintf("\",0x%x,0,0x%x,0x%x", 0, N_PSYM, length, offset);
14318354Smckusick }
14418354Smckusick }
14518354Smckusick
146772Speter /*
147772Speter * parameters
148772Speter */
oldstabparam(name,type,offset,length)14918354Smckusick oldstabparam( name , type , offset , length )
150772Speter char *name;
151772Speter int type;
152772Speter int offset;
153772Speter int length;
154772Speter {
155772Speter
156772Speter if ( ! opt('g') ) {
157772Speter return;
158772Speter }
159772Speter putprintf( " .stabs \"" , 1 );
16018355Smckusick putprintf( NAMEFORMAT , 1 , (int) name );
161826Speter putprintf( "\",0x%x,0,0x%x,0x%x" , 0 , N_PSYM , type , offset );
162772Speter putprintf( " .stabs \"" , 1 );
16318355Smckusick putprintf( NAMEFORMAT , 1 , (int) name );
164826Speter putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length );
165772Speter }
166772Speter
167772Speter /*
168772Speter * fields
169772Speter */
170772Speter
171772Speter /*
172772Speter * left brackets
17318354Smckusick * (dbx handles module-2 without these, so we won't use them either)
174772Speter */
stablbrac(level)175772Speter stablbrac( level )
176772Speter int level;
177772Speter {
178772Speter
17918354Smckusick if ( ! opt('g') || oldway == 0 ) {
180772Speter return;
181772Speter }
182826Speter putprintf( " .stabd 0x%x,0,0x%x" , 0 , N_LBRAC , level );
183772Speter }
184772Speter
185772Speter /*
186772Speter * right brackets
187772Speter */
stabrbrac(level)188772Speter stabrbrac( level )
189772Speter int level;
190772Speter {
191772Speter
19218354Smckusick if ( ! opt('g') || oldway == 0 ) {
193772Speter return;
194772Speter }
195826Speter putprintf( " .stabd 0x%x,0,0x%x" , 0 , N_RBRAC , level );
196772Speter }
197772Speter
19818354Smckusick stabfunc (p, name, line, level)
19918354Smckusick struct nl *p;
20018354Smckusick char *name;
20118354Smckusick int line, level;
20218354Smckusick {
20318354Smckusick char extname[BUFSIZ],nestspec[BUFSIZ];
20418354Smckusick
20518354Smckusick if ( level == 1 ) {
20618354Smckusick if (p->class == FUNC) {
20718354Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x" ,
20818354Smckusick 0 , name , N_PC , N_PGFUNC , ABS( line )
20918354Smckusick );
21018354Smckusick } else if (p->class == PROC) {
21118354Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x" ,
21218354Smckusick 0 , name , N_PC , N_PGPROC , ABS( line )
21318354Smckusick );
21418354Smckusick }
21518354Smckusick }
21618354Smckusick if (oldway != 0) {
21718354Smckusick oldstabfunc(name, p->class, line, level);
21818354Smckusick } else if (opt('g')) {
21918354Smckusick putprintf("\t.stabs\t\"%s:", 1, name);
22018354Smckusick if (p->class == FUNC) {
22118354Smckusick putprintf("F", 1);
22218354Smckusick gentype(p->type);
22318354Smckusick putprintf(",", 1);
22418354Smckusick } else {
22518354Smckusick putprintf("P,", 1);
22618354Smckusick }
22718354Smckusick sextname(extname, name, level); /* set extname to entry label */
22818354Smckusick putprintf("%s,", 1, &(extname[1])); /* remove initial underbar */
22918354Smckusick snestspec(nestspec, level);
23018354Smckusick putprintf("%s\",0x%x,0,0,%s", 0, nestspec, N_FUN, extname);
23118354Smckusick }
23218354Smckusick }
23318354Smckusick
234772Speter /*
23518354Smckusick * construct the colon-separated static nesting string into a
23618354Smckusick * caller-supplied buffer
23718354Smckusick */
snestspec(buffer,level)23818354Smckusick private snestspec(buffer, level)
23918354Smckusick char buffer[];
24018354Smckusick int level;
24118354Smckusick {
24218354Smckusick char *starthere;
24318354Smckusick int i;
24418354Smckusick
24518354Smckusick if (level <= 1) {
24618354Smckusick buffer[0] = '\0';
24718354Smckusick } else {
24818354Smckusick starthere = &buffer[0];
24918354Smckusick for ( i = 1 ; i < level ; i++ ) {
25018354Smckusick sprintf(starthere, "%s:", enclosing[i]);
25118354Smckusick starthere += strlen(enclosing[i]) + 1;
25218354Smckusick }
25325263Smckusick *--starthere = '\0'; /* remove last colon */
25418354Smckusick if (starthere >= &buffer[BUFSIZ-1]) {
25518354Smckusick panic("snestspec");
25618354Smckusick }
25718354Smckusick }
25818354Smckusick }
25918354Smckusick
26018354Smckusick /*
261772Speter * functions
262772Speter */
oldstabfunc(name,typeclass,line,level)26318354Smckusick oldstabfunc( name , typeclass , line , level )
264772Speter char *name;
2657925Smckusick int typeclass;
266772Speter int line;
267772Speter long level;
268772Speter {
2693365Speter char extname[ BUFSIZ ];
270772Speter
271826Speter /*
272826Speter * for sdb
273826Speter */
274772Speter if ( ! opt('g') ) {
275772Speter return;
276772Speter }
277772Speter putprintf( " .stabs \"" , 1 );
27818355Smckusick putprintf( NAMEFORMAT , 1 , (int) name );
27918355Smckusick sextname( extname , name , (int) level );
28018355Smckusick putprintf( "\",0x%x,0,0x%x,%s" , 0 , N_FUN , line , (int) extname );
281772Speter }
282772Speter
283772Speter /*
284772Speter * source line numbers
285772Speter */
stabline(line)286772Speter stabline( line )
287772Speter int line;
288772Speter {
289772Speter if ( ! opt('g') ) {
290772Speter return;
291772Speter }
292826Speter putprintf( " .stabd 0x%x,0,0x%x" , 0 , N_SLINE , ABS( line ) );
293772Speter }
294772Speter
295772Speter /*
29618354Smckusick * source files get none or more of these:
29718354Smckusick * one as they are entered,
29818354Smckusick * and one every time they are returned to from nested #includes
299772Speter */
stabsource(filename,firsttime)30018354Smckusick stabsource(filename, firsttime)
301772Speter char *filename;
30218354Smckusick bool firsttime;
30315952Smckusick {
30415952Smckusick int label;
30515952Smckusick
30615952Smckusick /*
30715952Smckusick * for separate compilation
30815952Smckusick */
30915952Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x", 0,
31018355Smckusick (int) filename, N_PC, N_PSO, N_FLAGCHECKSUM);
31115952Smckusick /*
31218354Smckusick * for debugger
31315952Smckusick */
31415952Smckusick if ( ! opt('g') ) {
31515952Smckusick return;
316772Speter }
31718354Smckusick if (oldway != 0) {
31818355Smckusick label = (int) getlab();
31918354Smckusick putprintf( " .stabs \"" , 1 );
32018354Smckusick putprintf( NAMEFORMAT , 1 , filename );
32118354Smckusick putprintf( "\",0x%x,0,0," , 1 , N_SO );
32218354Smckusick putprintf( PREFIXFORMAT , 0 , LLABELPREFIX , label );
32318354Smckusick putprintf( PREFIXFORMAT , 1 , LLABELPREFIX , label );
32418354Smckusick putprintf( ":" , 0 );
32518354Smckusick } else {
32618354Smckusick if (firsttime) {
32718354Smckusick putprintf( " .stabs \"" , 1 );
32818354Smckusick putprintf( NAMEFORMAT , 1 , filename );
32918354Smckusick putprintf( "\",0x%x,0,0,0" , 0 , N_SO );
33018354Smckusick }
33118354Smckusick }
33215952Smckusick }
333772Speter
334772Speter /*
335772Speter * included files get one or more of these:
336772Speter * one as they are entered by a #include,
33715952Smckusick * and one every time they are returned to from nested #includes.
338772Speter */
stabinclude(filename,firsttime)33915952Smckusick stabinclude(filename, firsttime)
340772Speter char *filename;
34115952Smckusick bool firsttime;
34215952Smckusick {
34318355Smckusick int label;
34415952Smckusick long check;
34515952Smckusick
34615952Smckusick /*
34715952Smckusick * for separate compilation
34815952Smckusick */
34915952Smckusick if (firsttime) {
35015952Smckusick check = checksum(filename);
35115952Smckusick } else {
35215952Smckusick check = N_FLAGCHECKSUM;
35315952Smckusick }
35415952Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x", 0,
35518355Smckusick (int) filename, N_PC, N_PSOL, check);
35615952Smckusick /*
35715952Smckusick * for sdb
35815952Smckusick */
35915952Smckusick if ( ! opt('g') ) {
36015952Smckusick return;
36115952Smckusick }
36218354Smckusick if (oldway != 0) {
36318355Smckusick label = (int) getlab();
36418354Smckusick putprintf( " .stabs \"" , 1 );
36518354Smckusick putprintf( NAMEFORMAT , 1 , filename );
36618354Smckusick putprintf( "\",0x%x,0,0," , 1 , N_SOL );
36718354Smckusick putprintf( PREFIXFORMAT , 0 , LLABELPREFIX , label );
36818354Smckusick putprintf( PREFIXFORMAT , 1 , LLABELPREFIX , label );
36918354Smckusick putprintf( ":" , 0 );
37018354Smckusick }
37115952Smckusick }
37215952Smckusick
37315952Smckusick /*
37415952Smckusick * anyone know a good checksum for ascii files?
37515952Smckusick * this does a rotate-left and then exclusive-or's in the character.
37615952Smckusick * also, it avoids returning checksums of 0.
37715952Smckusick * The rotate is implemented by shifting and adding back the
37815952Smckusick * sign bit when negative.
37915952Smckusick */
38015952Smckusick long
checksum(filename)38115952Smckusick checksum(filename)
38215952Smckusick char *filename;
38315952Smckusick {
38415952Smckusick FILE *filep;
38515952Smckusick register int input;
38615952Smckusick register long check;
38715952Smckusick
38815952Smckusick filep = fopen(filename, "r");
38915952Smckusick if (filep == NULL) {
39015952Smckusick perror(filename);
39115952Smckusick pexit(DIED);
39215952Smckusick }
39315952Smckusick check = 0;
39415952Smckusick while ((input = getc(filep)) != EOF) {
39515952Smckusick if (check < 0) {
39615952Smckusick check <<= 1;
39715952Smckusick check += 1;
39815952Smckusick } else {
39915952Smckusick check <<= 1;
40015942Smckusick }
40115952Smckusick check ^= input;
40214128Speter }
40318355Smckusick (void) fclose(filep);
40415952Smckusick if ((unsigned) check <= N_FLAGCHECKSUM) {
40515952Smckusick return N_FLAGCHECKSUM + 1;
40615952Smckusick } else {
40715952Smckusick return check;
40815952Smckusick }
40915952Smckusick }
41014128Speter
411772Speter /*
412772Speter * global Pascal symbols :
413772Speter * labels, types, constants, and external procedure and function names:
414772Speter * These are used by the separate compilation facility
415772Speter * to be able to check for disjoint header files.
416772Speter */
417772Speter
418826Speter /*
419826Speter * global labels
420826Speter */
stabglabel(label,line)421842Speter stabglabel( label , line )
422826Speter char *label;
423826Speter int line;
424772Speter {
425772Speter
426842Speter putprintf( " .stabs \"%s\",0x%x,0,0x%x,0x%x" , 0
42718355Smckusick , (int) label , N_PC , N_PGLABEL , ABS( line ) );
428772Speter }
429772Speter
430826Speter /*
431826Speter * global constants
432826Speter */
stabgconst(constant,line)43333236Sbostic stabgconst( constant , line )
43433236Sbostic char *constant;
435826Speter int line;
436772Speter {
437772Speter
438842Speter putprintf( " .stabs \"%s\",0x%x,0,0x%x,0x%x" , 0
43933236Sbostic , (int) constant , N_PC , N_PGCONST , ABS( line ) );
440772Speter }
441772Speter
44218354Smckusick /*
44318354Smckusick * Generate symbolic information about a constant.
44418354Smckusick */
445772Speter
44618354Smckusick stabconst (c)
44718354Smckusick struct nl *c;
44818354Smckusick {
44918354Smckusick if (opt('g') && oldway == 0) {
45018354Smckusick putprintf("\t.stabs\t\"%s:c=", 1, c->symbol);
45118354Smckusick if (c->type == nl + TSTR) {
45218354Smckusick putprintf("s'%s'", 1, c->ptr[0]);
45318354Smckusick } else if (c->type == nl + T1CHAR) {
45418354Smckusick putprintf("c%d", 1, c->range[0]);
45518354Smckusick } else if (isa(c->type, "i")) {
45618354Smckusick putprintf("i%d", 1, c->range[0]);
45718354Smckusick } else if (isa(c->type, "d")) {
45818354Smckusick putprintf("r%g", 1, c->real);
45918354Smckusick } else {
46018354Smckusick putprintf("e", 1);
46118354Smckusick gentype(c->type);
46218354Smckusick putprintf(",%d", 1, c->range[0]);
46318354Smckusick }
46418354Smckusick putprintf("\",0x%x,0,0x%x,0x%x", 0, N_LSYM, 0, 0);
465772Speter }
46618354Smckusick }
467772Speter
stabgtype(name,type,line)46818354Smckusick stabgtype (name, type, line)
46918354Smckusick char *name;
47018354Smckusick struct nl *type;
47118354Smckusick int line;
47218354Smckusick {
47318354Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x" ,
47418354Smckusick 0, name, N_PC , N_PGTYPE, ABS(line)
47518354Smckusick );
47618354Smckusick if (oldway == 0) {
47718354Smckusick stabltype(name, type);
47818354Smckusick }
47918354Smckusick }
480772Speter
stabltype(name,type)48118354Smckusick stabltype (name, type)
48218354Smckusick char *name;
48318354Smckusick struct nl *type;
48418354Smckusick {
48518354Smckusick if (opt('g')) {
48618354Smckusick putprintf("\t.stabs\t\"%s:t", 1, name);
48718354Smckusick gentype(type);
48818354Smckusick putprintf("\",0x%x,0,0,0", 0, N_LSYM);
48918354Smckusick }
49018354Smckusick }
49118354Smckusick
492826Speter /*
493826Speter * external functions and procedures
494826Speter */
stabefunc(name,typeclass,line)4957925Smckusick stabefunc( name , typeclass , line )
496826Speter char *name;
4977925Smckusick int typeclass;
498826Speter int line;
499772Speter {
500826Speter int type;
501772Speter
5027925Smckusick if ( typeclass == FUNC ) {
503842Speter type = N_PEFUNC;
5047925Smckusick } else if ( typeclass == PROC ) {
505842Speter type = N_PEPROC;
506826Speter } else {
507826Speter return;
508772Speter }
509842Speter putprintf( " .stabs \"%s\",0x%x,0,0x%x,0x%x" , 0
51018355Smckusick , (int) name , N_PC , type , ABS( line ) );
511772Speter }
512772Speter
51318354Smckusick /*
51418354Smckusick * Generate type information encoded as a string for dbx.
51518354Smckusick * The fwdptrnum field is used only when the type is a pointer
51618354Smckusick * to a type that isn't known when it was entered. When the
51718354Smckusick * type field is filled for some such tptr, fixfwdtype should
51818354Smckusick * be called to output an equivalencing type definition.
51918354Smckusick */
52018354Smckusick
52118354Smckusick typedef struct TypeDesc *TypeDesc;
52218354Smckusick
52318354Smckusick struct TypeDesc {
52418354Smckusick struct nl *tptr;
52518354Smckusick int tnum;
52618354Smckusick int fwdptrnum;
52718354Smckusick TypeDesc chain;
52818354Smckusick };
52918354Smckusick
53018354Smckusick #define TABLESIZE 2003
53118354Smckusick
53218354Smckusick #define typehash(t) ( ( ((int) t) >> 2 ) % TABLESIZE )
53318354Smckusick
53418354Smckusick private int tcount = 1;
53518354Smckusick private TypeDesc typetable[TABLESIZE];
53618354Smckusick
tdlookup(t)53718354Smckusick private TypeDesc tdlookup (t)
53818354Smckusick struct nl *t;
53918354Smckusick {
54018354Smckusick register TypeDesc td;
54118354Smckusick
54218354Smckusick td = typetable[typehash(t)];
54318354Smckusick while (td != NIL && td->tptr != t) {
54418354Smckusick td = td->chain;
54518354Smckusick }
54618354Smckusick return td;
54718354Smckusick }
54818354Smckusick
typelookup(t)54918354Smckusick private int typelookup (t)
55018354Smckusick struct nl *t;
55118354Smckusick {
55218354Smckusick register TypeDesc td;
55318354Smckusick int r;
55418354Smckusick
55518354Smckusick td = tdlookup(t);
55618354Smckusick if (td == NIL) {
55718354Smckusick r = 0;
55818354Smckusick } else {
55918354Smckusick r = td->tnum;
56018354Smckusick }
56118354Smckusick return r;
56218354Smckusick }
56318354Smckusick
entertype(type)56418354Smckusick private int entertype (type)
56518354Smckusick struct nl *type;
56618354Smckusick {
56718354Smckusick register TypeDesc td;
56818354Smckusick register int i;
56918354Smckusick
57018354Smckusick td = (TypeDesc) malloc(sizeof(struct TypeDesc));
57118354Smckusick td->tptr = type;
57218354Smckusick td->tnum = tcount;
57318354Smckusick td->fwdptrnum = 0;
57418354Smckusick ++tcount;
57518354Smckusick i = typehash(type);
57618354Smckusick td->chain = typetable[i];
57718354Smckusick typetable[i] = td;
57818354Smckusick return td->tnum;
57918354Smckusick }
58018354Smckusick
58118354Smckusick /*
58218354Smckusick * The in_types table currently contains "boolean", "char", "integer",
58318354Smckusick * "real" and "_nil". (See nl.c for definition.)
58418354Smckusick * The lookup call below will give the TYPE class nl entry for these
58518354Smckusick * types. In each case except _nil, the type field of that entry is a RANGE
58618354Smckusick * class nl entry for the type. Sometimes other symbol table entries
58718354Smckusick * point to the TYPE entry (e.g., when there is a range over the base type),
58818354Smckusick * and other entries point to the RANGE entry (e.g., for a variable of the
58918354Smckusick * given type). We don't really want to distinguish between these uses
59018354Smckusick * in dbx, and since it appears that the RANGE entries are not reused if
59118354Smckusick * a range happens to coincide, we will give the two the same identifying
59218354Smckusick * dbx type number.
59318354Smckusick */
59418354Smckusick
inittypes()59518354Smckusick private inittypes()
59618354Smckusick {
59718354Smckusick int i;
59818354Smckusick extern char *in_types[];
59918354Smckusick struct nl *p;
60018354Smckusick
60118354Smckusick for (i = 0; in_types[i] != NIL; i++) {
60218354Smckusick p = lookup(in_types[i]);
60318354Smckusick if (p != NIL) {
60418354Smckusick entertype(p);
60518354Smckusick if (p->type != NIL) {
60618354Smckusick --tcount; /* see comment above */
60718354Smckusick entertype(p->type);
60818354Smckusick }
60918354Smckusick }
61018354Smckusick }
61118354Smckusick }
61218354Smckusick
61318354Smckusick static genarray (t)
61418354Smckusick struct nl *t;
61518354Smckusick {
61618354Smckusick register struct nl *p;
61718354Smckusick
61818354Smckusick for (p = t->chain; p != NIL; p = p->chain) {
61925263Smckusick putprintf("a", 1);
62018354Smckusick gentype(p);
62118354Smckusick putprintf(";", 1);
62218354Smckusick }
62318354Smckusick gentype(t->type);
62418354Smckusick }
62518354Smckusick
62618354Smckusick /*
62718354Smckusick * Really we should walk through ptr[NL_FIELDLIST] for the fields,
62818354Smckusick * and then do the variant tag and fields separately, but dbx
62918354Smckusick * doesn't support this yet.
63018354Smckusick * So, since all the fields of all the variants are on the chain,
63118354Smckusick * we walk through that. Except that this gives the fields in the
63218354Smckusick * reverse order, so we want to print in reverse order.
63318354Smckusick */
63418354Smckusick
63518354Smckusick static genrecord (t)
63618354Smckusick struct nl *t;
63718354Smckusick {
63818354Smckusick putprintf("s%d", 1, t->value[NL_OFFS]);
63918354Smckusick if (t->chain != NIL) {
64018354Smckusick genrecfield(t->chain, 1);
64118354Smckusick }
64218354Smckusick putprintf(";", 1);
64318354Smckusick }
64418354Smckusick
64518354Smckusick static genrecfield (t, n)
64618354Smckusick struct nl *t;
64718354Smckusick int n;
64818354Smckusick {
64918354Smckusick if (t->chain != NULL) {
65018354Smckusick genrecfield(t->chain, n + 1);
65118354Smckusick if (n % 2 == 0) {
65218354Smckusick gencontinue();
65318354Smckusick }
65418354Smckusick }
65518354Smckusick putprintf("%s:", 1, t->symbol);
65618354Smckusick gentype(t->type);
65718354Smckusick putprintf(",%d,%d;", 1, 8*t->value[NL_OFFS], 8*lwidth(t->type));
65818354Smckusick }
65918354Smckusick
66018354Smckusick static genvarnt (t)
66118354Smckusick struct nl *t;
66218354Smckusick {
66318354Smckusick genrecord(t);
66418354Smckusick }
66518354Smckusick
66618354Smckusick static genptr (t)
66718354Smckusick struct nl *t;
66818354Smckusick {
66918354Smckusick register TypeDesc td;
67018354Smckusick
67118354Smckusick putprintf("*", 1);
67218354Smckusick if (t->type != NIL) {
67318354Smckusick gentype(t->type);
67418354Smckusick } else {
67518354Smckusick /*
67618354Smckusick * unresolved forward pointer: use tcount to represent what is
67718354Smckusick * begin pointed to, to be defined later
67818354Smckusick */
67918354Smckusick td = tdlookup(t);
68018354Smckusick if (td == NIL) {
68118354Smckusick panic("nil ptr in stab.genptr");
68218354Smckusick }
68318354Smckusick td->fwdptrnum = tcount;
68418354Smckusick putprintf("%d", 1, tcount);
68518354Smckusick ++tcount;
68618354Smckusick }
68718354Smckusick }
68818354Smckusick
68918354Smckusick /*
69018354Smckusick * The type t is a pointer which has just had its type field filled.
69118354Smckusick * We need to generate a type stab saying that the number saved
69218354Smckusick * in t's fwdptrnum is the same as the t->type's number
69318354Smckusick */
69418354Smckusick
69518354Smckusick fixfwdtype (t)
69618354Smckusick struct nl *t;
69718354Smckusick {
69818354Smckusick register TypeDesc td;
69918354Smckusick
70018354Smckusick if (opt('g') && oldway == 0) {
70118354Smckusick td = tdlookup(t);
70218354Smckusick if (td != NIL) {
70318354Smckusick putprintf("\t.stabs\t\":t%d=", 1, td->fwdptrnum);
70418354Smckusick gentype(t->type);
70518354Smckusick putprintf("\",0x%x,0,0,0", 0, N_LSYM);
70618354Smckusick }
70718354Smckusick }
70818354Smckusick }
70918354Smckusick
71018354Smckusick static genenum (t)
71118354Smckusick struct nl *t;
71218354Smckusick {
71318354Smckusick register struct nl *e;
71418354Smckusick register int i;
71518354Smckusick
71618354Smckusick putprintf("e", 1);
71718354Smckusick i = 1;
71818354Smckusick e = t->chain;
71918354Smckusick while (e != NULL) {
72018354Smckusick if (i > 2) {
72118354Smckusick gencontinue();
72218354Smckusick i = 0;
72318354Smckusick }
72418354Smckusick putprintf("%s:%d,", 1, e->symbol, e->range[0]);
72518354Smckusick e = e->chain;
72618354Smckusick ++i;
72718354Smckusick }
72818354Smckusick putprintf(";", 1);
72918354Smckusick }
73018354Smckusick
73118354Smckusick static genset (t)
73218354Smckusick struct nl *t;
73318354Smckusick {
73418354Smckusick putprintf("S", 1);
73518354Smckusick gentype(t->type);
73618354Smckusick }
73718354Smckusick
73818354Smckusick static genrange (t)
73918354Smckusick struct nl *t;
74018354Smckusick {
74118354Smckusick putprintf("r", 1);
74218354Smckusick gentype(t->type);
74318354Smckusick putprintf(";%d;%d", 1, t->range[0], t->range[1]);
74418354Smckusick }
74518354Smckusick
74618354Smckusick static genfparam (t)
74718354Smckusick struct nl *t;
74818354Smckusick {
74918354Smckusick struct nl *p;
75018354Smckusick int count;
75118354Smckusick
75218354Smckusick if (t->type != NULL) {
75318354Smckusick putprintf("f", 1);
75418354Smckusick gentype(t->type);
75518354Smckusick putprintf(",", 1);
75618354Smckusick } else {
75718354Smckusick putprintf("p", 1);
75818354Smckusick }
75918354Smckusick count = 0;
76018354Smckusick for (p = t->ptr[NL_FCHAIN]; p != NULL; p = p->chain) {
76118354Smckusick ++count;
76218354Smckusick }
76318354Smckusick putprintf("%d;", 1, count);
76418354Smckusick for (p = t->ptr[NL_FCHAIN]; p != NULL; p = p->chain) {
76518354Smckusick gentype(p->type);
76618354Smckusick putprintf(",%d;", 1, p->class);
76718354Smckusick }
76818354Smckusick }
76918354Smckusick
77018354Smckusick static genfile (t)
77118354Smckusick struct nl *t;
77218354Smckusick {
77318354Smckusick putprintf("d", 1);
77418354Smckusick gentype(t->type);
77518354Smckusick }
77618354Smckusick
77718354Smckusick static gentype (t)
77818354Smckusick struct nl *t;
77918354Smckusick {
78018354Smckusick int id;
78118354Smckusick
78218354Smckusick if (tcount == 1) {
78318354Smckusick inittypes();
78418354Smckusick }
78518354Smckusick id = typelookup(t);
78618354Smckusick if (id != 0) {
78718354Smckusick putprintf("%d", 1, id);
78818354Smckusick } else if (t->class == SCAL && t->chain == NULL) {
78918354Smckusick id = typelookup(t->type);
79018354Smckusick if (id != 0) {
79118354Smckusick putprintf("%d", 1, id);
79218354Smckusick } else {
79318354Smckusick genenum(t->type);
79418354Smckusick }
79518354Smckusick } else {
79618354Smckusick id = entertype(t);
79718354Smckusick putprintf("%d=", 1, id);
79818354Smckusick switch (t->class) {
79918354Smckusick case TYPE:
80018354Smckusick gentype(t->type);
80118354Smckusick break;
80218354Smckusick
80318354Smckusick case ARRAY:
80418354Smckusick genarray(t);
80518354Smckusick break;
80618354Smckusick
80718354Smckusick case RECORD:
80818354Smckusick genrecord(t);
80918354Smckusick break;
81018354Smckusick
81118354Smckusick case VARNT:
81218354Smckusick genvarnt(t);
81318354Smckusick break;
81418354Smckusick
81518354Smckusick case REF:
81618354Smckusick gentype(t->type);
81718354Smckusick break;
81818354Smckusick
81918354Smckusick case PTR:
82018354Smckusick genptr(t);
82118354Smckusick break;
82218354Smckusick
82318354Smckusick case SET:
82418354Smckusick genset(t);
82518354Smckusick break;
82618354Smckusick
82718354Smckusick case RANGE:
82818354Smckusick genrange(t);
82918354Smckusick break;
83018354Smckusick
83118354Smckusick case SCAL:
83218354Smckusick genenum(t);
83318354Smckusick break;
83418354Smckusick
83518354Smckusick case FPROC:
83618354Smckusick case FFUNC:
83718354Smckusick genfparam(t);
83818354Smckusick break;
83918354Smckusick
84018354Smckusick case FILET:
84118354Smckusick case PTRFILE:
84218354Smckusick genfile(t);
84318354Smckusick break;
84418354Smckusick
84518354Smckusick default:
84618354Smckusick /* This shouldn't happen */
84718354Smckusick /* Rather than bomb outright, let debugging go on */
84818354Smckusick warning();
84918354Smckusick error("Bad type class found in stab");
85018354Smckusick putprintf("1", 1, t->class);
85118354Smckusick break;
85218354Smckusick }
85318354Smckusick }
85418354Smckusick }
85518354Smckusick
85618354Smckusick /*
85718354Smckusick * Continue stab information in a namelist new entry. This is necessary
85818354Smckusick * to avoid overflowing putprintf's buffer.
85918354Smckusick */
86018354Smckusick
gencontinue()86118354Smckusick static gencontinue ()
86218354Smckusick {
86318354Smckusick putprintf("?\",0x%x,0,0,0", 0, N_LSYM);
86418354Smckusick putprintf("\t.stabs\t\"", 1);
86518354Smckusick }
86618354Smckusick
867772Speter #endif PC
868