xref: /csrg-svn/usr.bin/pascal/src/stab.c (revision 62215)
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