xref: /csrg-svn/usr.bin/pascal/src/stab.c (revision 22191)
1*22191Sdist /*
2*22191Sdist  * Copyright (c) 1980 Regents of the University of California.
3*22191Sdist  * All rights reserved.  The Berkeley software License Agreement
4*22191Sdist  * specifies the terms and conditions for redistribution.
5*22191Sdist  */
6772Speter 
718355Smckusick #ifndef lint
8*22191Sdist static char sccsid[] = "@(#)stab.c	5.1 (Berkeley) 06/05/85";
9*22191Sdist #endif not lint
10826Speter 
11772Speter     /*
1218354Smckusick      *	Procedures to put out symbol table information
13826Speter      *	and stabs for separate compilation type checking.
1418354Smckusick      *	These use the .stabs, .stabn, and .stabd directives.
15772Speter      */
16772Speter 
17772Speter #include	"whoami.h"
18772Speter #ifdef	PC
19772Speter     /*	and the rest of the file */
20772Speter #   include	"0.h"
2110649Speter #   include	"objfmt.h"
2215952Smckusick #   include	"yy.h"
23772Speter #   include	<stab.h>
24772Speter 
25842Speter     /*
26842Speter      *  additional symbol definition for <stab.h>
27842Speter      *	that is used by the separate compilation facility --
28842Speter      *	eventually, <stab.h> should be updated to include this
29842Speter      */
30772Speter 
31842Speter #   include	"pstab.h"
32772Speter #   include	"pc.h"
33772Speter 
3418354Smckusick 
3518354Smckusick #define private static
3618354Smckusick 
3718354Smckusick int oldway = 0;
3818354Smckusick 
39772Speter     /*
40826Speter      *	absolute value: line numbers are negative if error recovery.
41826Speter      */
42826Speter #define	ABS( x )	( x < 0 ? -x : x )
4318355Smckusick long checksum();
44826Speter 
4518354Smckusick /*
4618354Smckusick  * Generate information about variables.
4718354Smckusick  */
4818354Smckusick 
4918354Smckusick stabgvar (p, length, line)
5018354Smckusick struct nl *p;
5118354Smckusick int length, line;
5218354Smckusick {
5318354Smckusick     putprintf("	.stabs	\"%s\",0x%x,0,0x%x,0x%x",
5418354Smckusick 	0, p->symbol, N_PC, N_PGVAR, ABS(line)
5518354Smckusick     );
5618354Smckusick     if (oldway != 0) {
5718354Smckusick 	oldstabgvar(p->symbol, p2type(p->type), 0, length, line);
5818354Smckusick     } else if (opt('g')) {
5918354Smckusick 	putprintf("\t.stabs\t\"%s:G", 1, p->symbol);
6018354Smckusick 	gentype(p->type);
6118354Smckusick 	putprintf("\",0x%x,0,0x%x,0", 0, N_GSYM, length);
6218354Smckusick     }
6318354Smckusick }
6418354Smckusick 
6518354Smckusick stablvar (p, offset, length)
6618354Smckusick struct nl *p;
6718354Smckusick int offset, length;
6818354Smckusick {
6918354Smckusick     int level;
7018354Smckusick 
7118354Smckusick     level = (p->nl_block & 037);
7218354Smckusick     if (oldway != 0) {
7318354Smckusick 	oldstablvar(p->symbol, p2type(p->type), level, offset, length);
7418354Smckusick     } else if (opt('g')) {
7518354Smckusick 	putprintf("\t.stabs\t\"%s:", 1, p->symbol);
7618354Smckusick 	gentype(p->type);
7718354Smckusick 	putprintf("\",0x%x,0,0x%x,0x%x", 0, N_LSYM, length, offset);
7818354Smckusick     }
7918354Smckusick }
8018354Smckusick 
81826Speter     /*
822164Speter      *	global variables
83772Speter      */
8418355Smckusick /*ARGSUSED*/
8518354Smckusick oldstabgvar( name , type , offset , length , line )
86772Speter     char	*name;
87772Speter     int		type;
88772Speter     int		offset;
89772Speter     int		length;
90826Speter     int		line;
91772Speter     {
92772Speter 	if ( ! opt('g') ) {
93772Speter 		return;
94772Speter 	}
95772Speter 	putprintf( "	.stabs	\"" , 1 );
9618355Smckusick 	putprintf( NAMEFORMAT , 1 , (int) name );
972164Speter 	putprintf( "\",0x%x,0,0x%x,0" , 0 , N_GSYM , type );
982164Speter 	putprintf( "	.stabs	\"" , 1 );
9918355Smckusick 	putprintf( NAMEFORMAT , 1 , (int) name );
1002164Speter 	putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length );
1012164Speter }
1022164Speter 
1032164Speter     /*
1042164Speter      *	local variables
1052164Speter      */
10618355Smckusick /*ARGSUSED*/
10718354Smckusick oldstablvar( name , type , level , offset , length )
1082164Speter     char	*name;
1092164Speter     int		type;
1102164Speter     int		level;
1112164Speter     int		offset;
1122164Speter     int		length;
1132164Speter     {
1142164Speter 
1152164Speter 	if ( ! opt('g') ) {
1162164Speter 		return;
117772Speter 	}
118772Speter 	putprintf( "	.stabs	\"" , 1 );
11918355Smckusick 	putprintf( NAMEFORMAT , 1 , (int) name );
1202164Speter 	putprintf( "\",0x%x,0,0x%x,0x%x" , 0 , N_LSYM , type , -offset );
1212164Speter 	putprintf( "	.stabs	\"" , 1 );
12218355Smckusick 	putprintf( NAMEFORMAT , 1 , (int) name );
123826Speter 	putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length );
124772Speter }
125772Speter 
126772Speter 
12718354Smckusick stabparam (p, offset, length)
12818354Smckusick struct nl *p;
12918354Smckusick int offset, length;
13018354Smckusick {
13118354Smckusick     if (oldway != 0) {
13218354Smckusick 	oldstabparam(p->symbol, p2type(p->type), offset, length);
13318354Smckusick     } else if (opt('g')) {
13418354Smckusick 	putprintf("\t.stabs\t\"%s:", 1, p->symbol);
13518354Smckusick 	if (p->class == REF) {
13618354Smckusick 	    putprintf("v", 1);
13718354Smckusick 	} else {
13818354Smckusick 	    putprintf("p", 1);
13918354Smckusick 	}
14018354Smckusick 	gentype((p->class == FPROC || p->class ==FFUNC) ? p : p->type);
14118354Smckusick 	putprintf("\",0x%x,0,0x%x,0x%x", 0, N_PSYM, length, offset);
14218354Smckusick     }
14318354Smckusick }
14418354Smckusick 
145772Speter     /*
146772Speter      *	parameters
147772Speter      */
14818354Smckusick oldstabparam( name , type , offset , length )
149772Speter     char	*name;
150772Speter     int		type;
151772Speter     int		offset;
152772Speter     int		length;
153772Speter     {
154772Speter 
155772Speter 	if ( ! opt('g') ) {
156772Speter 		return;
157772Speter 	}
158772Speter 	putprintf( "	.stabs	\"" , 1 );
15918355Smckusick 	putprintf( NAMEFORMAT , 1 , (int) name );
160826Speter 	putprintf( "\",0x%x,0,0x%x,0x%x" , 0 , N_PSYM , type , offset );
161772Speter 	putprintf( "	.stabs	\"" , 1 );
16218355Smckusick 	putprintf( NAMEFORMAT , 1 , (int) name );
163826Speter 	putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length );
164772Speter     }
165772Speter 
166772Speter     /*
167772Speter      *	fields
168772Speter      */
169772Speter 
170772Speter     /*
171772Speter      *	left brackets
17218354Smckusick      *  (dbx handles module-2 without these, so we won't use them either)
173772Speter      */
174772Speter stablbrac( level )
175772Speter     int	level;
176772Speter     {
177772Speter 
17818354Smckusick 	if ( ! opt('g') || oldway == 0 ) {
179772Speter 		return;
180772Speter 	}
181826Speter 	putprintf( "	.stabd	0x%x,0,0x%x" , 0 , N_LBRAC , level );
182772Speter     }
183772Speter 
184772Speter     /*
185772Speter      *	right brackets
186772Speter      */
187772Speter stabrbrac( level )
188772Speter     int	level;
189772Speter     {
190772Speter 
19118354Smckusick 	if ( ! opt('g') || oldway == 0 ) {
192772Speter 		return;
193772Speter 	}
194826Speter 	putprintf( "	.stabd	0x%x,0,0x%x" , 0 , N_RBRAC , level );
195772Speter     }
196772Speter 
19718354Smckusick stabfunc (p, name, line, level)
19818354Smckusick struct nl *p;
19918354Smckusick char *name;
20018354Smckusick int line, level;
20118354Smckusick {
20218354Smckusick     char extname[BUFSIZ],nestspec[BUFSIZ];
20318354Smckusick 
20418354Smckusick     if ( level == 1 ) {
20518354Smckusick 	if (p->class == FUNC) {
20618354Smckusick 	    putprintf("	.stabs	\"%s\",0x%x,0,0x%x,0x%x" ,
20718354Smckusick 		0 , name , N_PC , N_PGFUNC , ABS( line )
20818354Smckusick 	    );
20918354Smckusick 	} else if (p->class == PROC) {
21018354Smckusick 	    putprintf("	.stabs	\"%s\",0x%x,0,0x%x,0x%x" ,
21118354Smckusick 		0 , name , N_PC , N_PGPROC , ABS( line )
21218354Smckusick 	    );
21318354Smckusick 	}
21418354Smckusick     }
21518354Smckusick     if (oldway != 0) {
21618354Smckusick 	oldstabfunc(name, p->class, line, level);
21718354Smckusick     } else if (opt('g')) {
21818354Smckusick 	putprintf("\t.stabs\t\"%s:", 1, name);
21918354Smckusick 	if (p->class == FUNC) {
22018354Smckusick 	    putprintf("F", 1);
22118354Smckusick 	    gentype(p->type);
22218354Smckusick 	    putprintf(",", 1);
22318354Smckusick 	} else {
22418354Smckusick 	    putprintf("P,", 1);
22518354Smckusick 	}
22618354Smckusick 	sextname(extname, name, level);  /* set extname to entry label */
22718354Smckusick 	putprintf("%s,", 1, &(extname[1])); /* remove initial underbar */
22818354Smckusick 	snestspec(nestspec, level);
22918354Smckusick 	putprintf("%s\",0x%x,0,0,%s", 0, nestspec, N_FUN, extname);
23018354Smckusick     }
23118354Smckusick }
23218354Smckusick 
233772Speter     /*
23418354Smckusick      * construct the colon-separated static nesting string into a
23518354Smckusick      * caller-supplied buffer
23618354Smckusick      */
23718354Smckusick private snestspec(buffer, level)
23818354Smckusick     char buffer[];
23918354Smckusick     int level;
24018354Smckusick {
24118354Smckusick     char *starthere;
24218354Smckusick     int i;
24318354Smckusick 
24418354Smckusick     if (level <= 1) {
24518354Smckusick 	buffer[0] = '\0';
24618354Smckusick     } else {
24718354Smckusick 	starthere = &buffer[0];
24818354Smckusick 	for ( i = 1 ; i < level ; i++ ) {
24918354Smckusick 	    sprintf(starthere, "%s:", enclosing[i]);
25018354Smckusick 	    starthere += strlen(enclosing[i]) + 1;
25118354Smckusick 	}
25218354Smckusick 	*starthere-- = '\0'; /* remove last colon */
25318354Smckusick 	if (starthere >= &buffer[BUFSIZ-1]) {
25418354Smckusick 	    panic("snestspec");
25518354Smckusick 	}
25618354Smckusick     }
25718354Smckusick }
25818354Smckusick 
25918354Smckusick     /*
260772Speter      *	functions
261772Speter      */
26218354Smckusick oldstabfunc( name , typeclass , line , level )
263772Speter     char	*name;
2647925Smckusick     int		typeclass;
265772Speter     int		line;
266772Speter     long	level;
267772Speter     {
2683365Speter 	char	extname[ BUFSIZ ];
269772Speter 
270826Speter 	    /*
271826Speter 	     *	for sdb
272826Speter 	     */
273772Speter 	if ( ! opt('g') ) {
274772Speter 		return;
275772Speter 	}
276772Speter 	putprintf( "	.stabs	\"" , 1 );
27718355Smckusick 	putprintf( NAMEFORMAT , 1 , (int) name );
27818355Smckusick 	sextname( extname , name , (int) level );
27918355Smckusick 	putprintf( "\",0x%x,0,0x%x,%s" , 0 , N_FUN , line , (int) extname );
280772Speter     }
281772Speter 
282772Speter     /*
283772Speter      *	source line numbers
284772Speter      */
285772Speter stabline( line )
286772Speter     int	line;
287772Speter     {
288772Speter 	if ( ! opt('g') ) {
289772Speter 		return;
290772Speter 	}
291826Speter 	putprintf( "	.stabd	0x%x,0,0x%x" , 0 , N_SLINE , ABS( line ) );
292772Speter     }
293772Speter 
294772Speter     /*
29518354Smckusick      *	source files get none or more of these:
29618354Smckusick      *  one as they are entered,
29718354Smckusick      *  and one every time they are returned to from nested #includes
298772Speter      */
29918354Smckusick stabsource(filename, firsttime)
300772Speter     char	*filename;
30118354Smckusick     bool	firsttime;
30215952Smckusick {
30315952Smckusick     int		label;
30415952Smckusick 
30515952Smckusick 	/*
30615952Smckusick 	 *	for separate compilation
30715952Smckusick 	 */
30815952Smckusick     putprintf("	.stabs	\"%s\",0x%x,0,0x%x,0x%x", 0,
30918355Smckusick 	    (int) filename, N_PC, N_PSO, N_FLAGCHECKSUM);
31015952Smckusick 	/*
31118354Smckusick 	 *	for debugger
31215952Smckusick 	 */
31315952Smckusick     if ( ! opt('g') ) {
31415952Smckusick 	    return;
315772Speter     }
31618354Smckusick     if (oldway != 0) {
31718355Smckusick 	label = (int) getlab();
31818354Smckusick 	putprintf( "	.stabs	\"" , 1 );
31918354Smckusick 	putprintf( NAMEFORMAT , 1 , filename );
32018354Smckusick 	putprintf( "\",0x%x,0,0," , 1 , N_SO );
32118354Smckusick 	putprintf( PREFIXFORMAT , 0 , LLABELPREFIX , label );
32218354Smckusick 	putprintf( PREFIXFORMAT , 1 , LLABELPREFIX , label );
32318354Smckusick 	putprintf( ":" , 0 );
32418354Smckusick     } else {
32518354Smckusick 	if (firsttime) {
32618354Smckusick 	    putprintf( "	.stabs	\"" , 1 );
32718354Smckusick 	    putprintf( NAMEFORMAT , 1 , filename );
32818354Smckusick 	    putprintf( "\",0x%x,0,0,0" , 0 , N_SO );
32918354Smckusick 	}
33018354Smckusick     }
33115952Smckusick }
332772Speter 
333772Speter     /*
334772Speter      *	included files get one or more of these:
335772Speter      *	one as they are entered by a #include,
33615952Smckusick      *	and one every time they are returned to from nested #includes.
337772Speter      */
33815952Smckusick stabinclude(filename, firsttime)
339772Speter     char	*filename;
34015952Smckusick     bool	firsttime;
34115952Smckusick {
34218355Smckusick     int		label;
34315952Smckusick     long	check;
34415952Smckusick 
34515952Smckusick 	/*
34615952Smckusick 	 *	for separate compilation
34715952Smckusick 	 */
34815952Smckusick     if (firsttime) {
34915952Smckusick 	check = checksum(filename);
35015952Smckusick     } else {
35115952Smckusick 	check = N_FLAGCHECKSUM;
35215952Smckusick     }
35315952Smckusick     putprintf("	.stabs	\"%s\",0x%x,0,0x%x,0x%x", 0,
35418355Smckusick 	    (int) filename, N_PC, N_PSOL, check);
35515952Smckusick 	/*
35615952Smckusick 	 *	for sdb
35715952Smckusick 	 */
35815952Smckusick     if ( ! opt('g') ) {
35915952Smckusick 	    return;
36015952Smckusick     }
36118354Smckusick     if (oldway != 0) {
36218355Smckusick 	label = (int) getlab();
36318354Smckusick 	putprintf( "	.stabs	\"" , 1 );
36418354Smckusick 	putprintf( NAMEFORMAT , 1 , filename );
36518354Smckusick 	putprintf( "\",0x%x,0,0," , 1 , N_SOL );
36618354Smckusick 	putprintf( PREFIXFORMAT , 0 , LLABELPREFIX , label );
36718354Smckusick 	putprintf( PREFIXFORMAT , 1 , LLABELPREFIX , label );
36818354Smckusick 	putprintf( ":" , 0 );
36918354Smckusick     }
37015952Smckusick }
37115952Smckusick 
37215952Smckusick     /*
37315952Smckusick      *	anyone know a good checksum for ascii files?
37415952Smckusick      *	this does a rotate-left and then exclusive-or's in the character.
37515952Smckusick      *	also, it avoids returning checksums of 0.
37615952Smckusick      *	The rotate is implemented by shifting and adding back the
37715952Smckusick      *	sign bit when negative.
37815952Smckusick      */
37915952Smckusick long
38015952Smckusick checksum(filename)
38115952Smckusick     char	*filename;
38215952Smckusick {
38315952Smckusick     FILE		*filep;
38415952Smckusick     register int	input;
38515952Smckusick     register long	check;
38615952Smckusick 
38715952Smckusick     filep = fopen(filename, "r");
38815952Smckusick     if (filep == NULL) {
38915952Smckusick 	perror(filename);
39015952Smckusick 	pexit(DIED);
39115952Smckusick     }
39215952Smckusick     check = 0;
39315952Smckusick     while ((input = getc(filep)) != EOF) {
39415952Smckusick 	if (check < 0) {
39515952Smckusick 	    check <<= 1;
39615952Smckusick 	    check += 1;
39715952Smckusick 	} else {
39815952Smckusick 	    check <<= 1;
39915942Smckusick 	}
40015952Smckusick 	check ^= input;
40114128Speter     }
40218355Smckusick     (void) fclose(filep);
40315952Smckusick     if ((unsigned) check <= N_FLAGCHECKSUM) {
40415952Smckusick 	return N_FLAGCHECKSUM + 1;
40515952Smckusick     } else {
40615952Smckusick 	return check;
40715952Smckusick     }
40815952Smckusick }
40914128Speter 
410772Speter /*
411772Speter  * global Pascal symbols :
412772Speter  *   labels, types, constants, and external procedure and function names:
413772Speter  *   These are used by the separate compilation facility
414772Speter  *   to be able to check for disjoint header files.
415772Speter  */
416772Speter 
417826Speter     /*
418826Speter      *	global labels
419826Speter      */
420842Speter stabglabel( label , line )
421826Speter     char	*label;
422826Speter     int		line;
423772Speter     {
424772Speter 
425842Speter 	putprintf( "	.stabs	\"%s\",0x%x,0,0x%x,0x%x" , 0
42618355Smckusick 		    , (int) label , N_PC , N_PGLABEL , ABS( line ) );
427772Speter     }
428772Speter 
429826Speter     /*
430826Speter      *	global constants
431826Speter      */
432842Speter stabgconst( const , line )
433842Speter     char	*const;
434826Speter     int		line;
435772Speter     {
436772Speter 
437842Speter 	    putprintf( "	.stabs	\"%s\",0x%x,0,0x%x,0x%x" , 0
43818355Smckusick 			, (int) const , N_PC , N_PGCONST , ABS( line ) );
439772Speter     }
440772Speter 
44118354Smckusick /*
44218354Smckusick  * Generate symbolic information about a constant.
44318354Smckusick  */
444772Speter 
44518354Smckusick stabconst (c)
44618354Smckusick struct nl *c;
44718354Smckusick {
44818354Smckusick     if (opt('g') && oldway == 0) {
44918354Smckusick 	putprintf("\t.stabs\t\"%s:c=", 1, c->symbol);
45018354Smckusick 	if (c->type == nl + TSTR) {
45118354Smckusick 	    putprintf("s'%s'", 1, c->ptr[0]);
45218354Smckusick 	} else if (c->type == nl + T1CHAR) {
45318354Smckusick 	    putprintf("c%d", 1, c->range[0]);
45418354Smckusick 	} else if (isa(c->type, "i")) {
45518354Smckusick 	    putprintf("i%d", 1, c->range[0]);
45618354Smckusick 	} else if (isa(c->type, "d")) {
45718354Smckusick 	    putprintf("r%g", 1, c->real);
45818354Smckusick 	} else {
45918354Smckusick 	    putprintf("e", 1);
46018354Smckusick 	    gentype(c->type);
46118354Smckusick 	    putprintf(",%d", 1, c->range[0]);
46218354Smckusick 	}
46318354Smckusick 	putprintf("\",0x%x,0,0x%x,0x%x", 0, N_LSYM, 0, 0);
464772Speter     }
46518354Smckusick }
466772Speter 
46718354Smckusick stabgtype (name, type, line)
46818354Smckusick char *name;
46918354Smckusick struct nl *type;
47018354Smckusick int line;
47118354Smckusick {
47218354Smckusick     putprintf("	.stabs	\"%s\",0x%x,0,0x%x,0x%x" ,
47318354Smckusick 	0, name, N_PC , N_PGTYPE, ABS(line)
47418354Smckusick     );
47518354Smckusick     if (oldway == 0) {
47618354Smckusick 	stabltype(name, type);
47718354Smckusick     }
47818354Smckusick }
479772Speter 
48018354Smckusick stabltype (name, type)
48118354Smckusick char *name;
48218354Smckusick struct nl *type;
48318354Smckusick {
48418354Smckusick     if (opt('g')) {
48518354Smckusick 	putprintf("\t.stabs\t\"%s:t", 1, name);
48618354Smckusick 	gentype(type);
48718354Smckusick 	putprintf("\",0x%x,0,0,0", 0, N_LSYM);
48818354Smckusick     }
48918354Smckusick }
49018354Smckusick 
491826Speter     /*
492826Speter      *	external functions and procedures
493826Speter      */
4947925Smckusick stabefunc( name , typeclass , line )
495826Speter     char	*name;
4967925Smckusick     int		typeclass;
497826Speter     int		line;
498772Speter     {
499826Speter 	int	type;
500772Speter 
5017925Smckusick 	if ( typeclass == FUNC ) {
502842Speter 	    type = N_PEFUNC;
5037925Smckusick 	} else if ( typeclass == PROC ) {
504842Speter 	    type = N_PEPROC;
505826Speter 	} else {
506826Speter 	    return;
507772Speter 	}
508842Speter 	putprintf( "	.stabs	\"%s\",0x%x,0,0x%x,0x%x" , 0
50918355Smckusick 		    , (int) name , N_PC , type , ABS( line ) );
510772Speter     }
511772Speter 
51218354Smckusick /*
51318354Smckusick  * Generate type information encoded as a string for dbx.
51418354Smckusick  * The fwdptrnum field is used only when the type is a pointer
51518354Smckusick  * to a type that isn't known when it was entered.  When the
51618354Smckusick  * type field is filled for some such tptr, fixfwdtype should
51718354Smckusick  * be called to output an equivalencing type definition.
51818354Smckusick  */
51918354Smckusick 
52018354Smckusick typedef struct TypeDesc *TypeDesc;
52118354Smckusick 
52218354Smckusick struct TypeDesc {
52318354Smckusick     struct nl *tptr;
52418354Smckusick     int tnum;
52518354Smckusick     int fwdptrnum;
52618354Smckusick     TypeDesc chain;
52718354Smckusick };
52818354Smckusick 
52918354Smckusick #define TABLESIZE 2003
53018354Smckusick 
53118354Smckusick #define typehash(t) ( ( ((int) t) >> 2 ) % TABLESIZE )
53218354Smckusick 
53318354Smckusick private int tcount = 1;
53418354Smckusick private TypeDesc typetable[TABLESIZE];
53518354Smckusick 
53618354Smckusick private TypeDesc tdlookup (t)
53718354Smckusick struct nl *t;
53818354Smckusick {
53918354Smckusick     register TypeDesc td;
54018354Smckusick 
54118354Smckusick     td = typetable[typehash(t)];
54218354Smckusick     while (td != NIL && td->tptr != t) {
54318354Smckusick 	td = td->chain;
54418354Smckusick     }
54518354Smckusick     return td;
54618354Smckusick }
54718354Smckusick 
54818354Smckusick private int typelookup (t)
54918354Smckusick struct nl *t;
55018354Smckusick {
55118354Smckusick     register TypeDesc td;
55218354Smckusick     int r;
55318354Smckusick 
55418354Smckusick     td = tdlookup(t);
55518354Smckusick     if (td == NIL) {
55618354Smckusick 	r = 0;
55718354Smckusick     } else {
55818354Smckusick 	r = td->tnum;
55918354Smckusick     }
56018354Smckusick     return r;
56118354Smckusick }
56218354Smckusick 
56318354Smckusick private int entertype (type)
56418354Smckusick struct nl *type;
56518354Smckusick {
56618354Smckusick     register TypeDesc td;
56718354Smckusick     register int i;
56818354Smckusick 
56918354Smckusick     td = (TypeDesc) malloc(sizeof(struct TypeDesc));
57018354Smckusick     td->tptr = type;
57118354Smckusick     td->tnum = tcount;
57218354Smckusick     td->fwdptrnum = 0;
57318354Smckusick     ++tcount;
57418354Smckusick     i = typehash(type);
57518354Smckusick     td->chain = typetable[i];
57618354Smckusick     typetable[i] = td;
57718354Smckusick     return td->tnum;
57818354Smckusick }
57918354Smckusick 
58018354Smckusick /*
58118354Smckusick  * The in_types table currently contains "boolean", "char", "integer",
58218354Smckusick  * "real" and "_nil".  (See nl.c for definition.)
58318354Smckusick  * The lookup call below will give the TYPE class nl entry for these
58418354Smckusick  * types.  In each case except _nil, the type field of that entry is a RANGE
58518354Smckusick  * class nl entry for the type.  Sometimes other symbol table entries
58618354Smckusick  * point to the TYPE entry (e.g., when there is a range over the base type),
58718354Smckusick  * and other entries point to the RANGE entry (e.g., for a variable of the
58818354Smckusick  * given type).  We don't really want to distinguish between these uses
58918354Smckusick  * in dbx, and since it appears that the RANGE entries are not reused if
59018354Smckusick  * a range happens to coincide, we will give the two the same identifying
59118354Smckusick  * dbx type number.
59218354Smckusick  */
59318354Smckusick 
59418354Smckusick private inittypes()
59518354Smckusick {
59618354Smckusick     int i;
59718354Smckusick     extern char *in_types[];
59818354Smckusick     struct nl *p;
59918354Smckusick 
60018354Smckusick     for (i = 0; in_types[i] != NIL; i++) {
60118354Smckusick 	p = lookup(in_types[i]);
60218354Smckusick 	if (p != NIL) {
60318354Smckusick 	    entertype(p);
60418354Smckusick 	    if (p->type != NIL) {
60518354Smckusick 		--tcount; /* see comment above */
60618354Smckusick 		entertype(p->type);
60718354Smckusick 	    }
60818354Smckusick 	}
60918354Smckusick     }
61018354Smckusick }
61118354Smckusick 
61218354Smckusick static genarray (t)
61318354Smckusick struct nl *t;
61418354Smckusick {
61518354Smckusick     register struct nl *p;
61618354Smckusick 
61718354Smckusick     putprintf("a", 1);
61818354Smckusick     for (p = t->chain; p != NIL; p = p->chain) {
61918354Smckusick 	gentype(p);
62018354Smckusick 	putprintf(";", 1);
62118354Smckusick     }
62218354Smckusick     gentype(t->type);
62318354Smckusick }
62418354Smckusick 
62518354Smckusick /*
62618354Smckusick  * Really we should walk through ptr[NL_FIELDLIST] for the fields,
62718354Smckusick  * and then do the variant tag and fields separately, but dbx
62818354Smckusick  * doesn't support this yet.
62918354Smckusick  * So, since all the fields of all the variants are on the chain,
63018354Smckusick  * we walk through that.  Except that this gives the fields in the
63118354Smckusick  * reverse order, so we want to print in reverse order.
63218354Smckusick  */
63318354Smckusick 
63418354Smckusick static genrecord (t)
63518354Smckusick struct nl *t;
63618354Smckusick {
63718354Smckusick     putprintf("s%d", 1, t->value[NL_OFFS]);
63818354Smckusick     if (t->chain != NIL) {
63918354Smckusick 	genrecfield(t->chain, 1);
64018354Smckusick     }
64118354Smckusick     putprintf(";", 1);
64218354Smckusick }
64318354Smckusick 
64418354Smckusick static genrecfield (t, n)
64518354Smckusick struct nl *t;
64618354Smckusick int n;
64718354Smckusick {
64818354Smckusick     if (t->chain != NULL) {
64918354Smckusick 	genrecfield(t->chain, n + 1);
65018354Smckusick 	if (n % 2 == 0) {
65118354Smckusick 	    gencontinue();
65218354Smckusick 	}
65318354Smckusick     }
65418354Smckusick     putprintf("%s:", 1, t->symbol);
65518354Smckusick     gentype(t->type);
65618354Smckusick     putprintf(",%d,%d;", 1, 8*t->value[NL_OFFS], 8*lwidth(t->type));
65718354Smckusick }
65818354Smckusick 
65918354Smckusick static genvarnt (t)
66018354Smckusick struct nl *t;
66118354Smckusick {
66218354Smckusick     genrecord(t);
66318354Smckusick }
66418354Smckusick 
66518354Smckusick static genptr (t)
66618354Smckusick struct nl *t;
66718354Smckusick {
66818354Smckusick     register TypeDesc td;
66918354Smckusick 
67018354Smckusick     putprintf("*", 1);
67118354Smckusick     if (t->type != NIL) {
67218354Smckusick 	gentype(t->type);
67318354Smckusick     } else {
67418354Smckusick 	/*
67518354Smckusick 	 * unresolved forward pointer: use tcount to represent what is
67618354Smckusick          * begin pointed to, to be defined later
67718354Smckusick 	 */
67818354Smckusick 	td = tdlookup(t);
67918354Smckusick 	if (td == NIL) {
68018354Smckusick 	    panic("nil ptr in stab.genptr");
68118354Smckusick 	}
68218354Smckusick 	td->fwdptrnum = tcount;
68318354Smckusick 	putprintf("%d", 1, tcount);
68418354Smckusick 	++tcount;
68518354Smckusick     }
68618354Smckusick }
68718354Smckusick 
68818354Smckusick /*
68918354Smckusick  * The type t is a pointer which has just had its type field filled.
69018354Smckusick  * We need to generate a type stab saying that the number saved
69118354Smckusick  * in t's fwdptrnum is the same as the t->type's number
69218354Smckusick  */
69318354Smckusick 
69418354Smckusick fixfwdtype (t)
69518354Smckusick struct nl *t;
69618354Smckusick {
69718354Smckusick     register TypeDesc td;
69818354Smckusick 
69918354Smckusick     if (opt('g') && oldway == 0) {
70018354Smckusick 	td = tdlookup(t);
70118354Smckusick 	if (td != NIL) {
70218354Smckusick 	    putprintf("\t.stabs\t\":t%d=", 1, td->fwdptrnum);
70318354Smckusick 	    gentype(t->type);
70418354Smckusick 	    putprintf("\",0x%x,0,0,0", 0, N_LSYM);
70518354Smckusick 	}
70618354Smckusick     }
70718354Smckusick }
70818354Smckusick 
70918354Smckusick static genenum (t)
71018354Smckusick struct nl *t;
71118354Smckusick {
71218354Smckusick     register struct nl *e;
71318354Smckusick     register int i;
71418354Smckusick 
71518354Smckusick     putprintf("e", 1);
71618354Smckusick     i = 1;
71718354Smckusick     e = t->chain;
71818354Smckusick     while (e != NULL) {
71918354Smckusick 	if (i > 2) {
72018354Smckusick 	    gencontinue();
72118354Smckusick 	    i = 0;
72218354Smckusick 	}
72318354Smckusick 	putprintf("%s:%d,", 1, e->symbol, e->range[0]);
72418354Smckusick 	e = e->chain;
72518354Smckusick 	++i;
72618354Smckusick     }
72718354Smckusick     putprintf(";", 1);
72818354Smckusick }
72918354Smckusick 
73018354Smckusick static genset (t)
73118354Smckusick struct nl *t;
73218354Smckusick {
73318354Smckusick     putprintf("S", 1);
73418354Smckusick     gentype(t->type);
73518354Smckusick }
73618354Smckusick 
73718354Smckusick static genrange (t)
73818354Smckusick struct nl *t;
73918354Smckusick {
74018354Smckusick     putprintf("r", 1);
74118354Smckusick     gentype(t->type);
74218354Smckusick     putprintf(";%d;%d", 1, t->range[0], t->range[1]);
74318354Smckusick }
74418354Smckusick 
74518354Smckusick static genfparam (t)
74618354Smckusick struct nl *t;
74718354Smckusick {
74818354Smckusick     struct nl *p;
74918354Smckusick     int count;
75018354Smckusick 
75118354Smckusick     if (t->type != NULL) {
75218354Smckusick 	putprintf("f", 1);
75318354Smckusick 	gentype(t->type);
75418354Smckusick 	putprintf(",", 1);
75518354Smckusick     } else {
75618354Smckusick 	putprintf("p", 1);
75718354Smckusick     }
75818354Smckusick     count = 0;
75918354Smckusick     for (p = t->ptr[NL_FCHAIN]; p != NULL; p = p->chain) {
76018354Smckusick 	++count;
76118354Smckusick     }
76218354Smckusick     putprintf("%d;", 1, count);
76318354Smckusick     for (p = t->ptr[NL_FCHAIN]; p != NULL; p = p->chain) {
76418354Smckusick 	gentype(p->type);
76518354Smckusick 	putprintf(",%d;", 1, p->class);
76618354Smckusick     }
76718354Smckusick }
76818354Smckusick 
76918354Smckusick static genfile (t)
77018354Smckusick struct nl *t;
77118354Smckusick {
77218354Smckusick     putprintf("d", 1);
77318354Smckusick     gentype(t->type);
77418354Smckusick }
77518354Smckusick 
77618354Smckusick static gentype (t)
77718354Smckusick struct nl *t;
77818354Smckusick {
77918354Smckusick     int id;
78018354Smckusick 
78118354Smckusick     if (tcount == 1) {
78218354Smckusick 	inittypes();
78318354Smckusick     }
78418354Smckusick     id = typelookup(t);
78518354Smckusick     if (id != 0) {
78618354Smckusick 	putprintf("%d", 1, id);
78718354Smckusick     } else if (t->class == SCAL && t->chain == NULL) {
78818354Smckusick 	id = typelookup(t->type);
78918354Smckusick 	if (id != 0) {
79018354Smckusick 	    putprintf("%d", 1, id);
79118354Smckusick 	} else {
79218354Smckusick 	    genenum(t->type);
79318354Smckusick 	}
79418354Smckusick     } else {
79518354Smckusick 	id = entertype(t);
79618354Smckusick 	putprintf("%d=", 1, id);
79718354Smckusick 	switch (t->class) {
79818354Smckusick 	    case TYPE:
79918354Smckusick 		gentype(t->type);
80018354Smckusick 		break;
80118354Smckusick 
80218354Smckusick 	    case ARRAY:
80318354Smckusick 		genarray(t);
80418354Smckusick 		break;
80518354Smckusick 
80618354Smckusick 	    case RECORD:
80718354Smckusick 		genrecord(t);
80818354Smckusick 		break;
80918354Smckusick 
81018354Smckusick 	    case VARNT:
81118354Smckusick 		genvarnt(t);
81218354Smckusick 		break;
81318354Smckusick 
81418354Smckusick 	    case REF:
81518354Smckusick 		gentype(t->type);
81618354Smckusick 		break;
81718354Smckusick 
81818354Smckusick 	    case PTR:
81918354Smckusick 		genptr(t);
82018354Smckusick 		break;
82118354Smckusick 
82218354Smckusick 	    case SET:
82318354Smckusick 		genset(t);
82418354Smckusick 		break;
82518354Smckusick 
82618354Smckusick 	    case RANGE:
82718354Smckusick 		genrange(t);
82818354Smckusick 		break;
82918354Smckusick 
83018354Smckusick 	    case SCAL:
83118354Smckusick 		genenum(t);
83218354Smckusick 		break;
83318354Smckusick 
83418354Smckusick 	    case FPROC:
83518354Smckusick 	    case FFUNC:
83618354Smckusick 		genfparam(t);
83718354Smckusick 		break;
83818354Smckusick 
83918354Smckusick 	    case FILET:
84018354Smckusick 	    case PTRFILE:
84118354Smckusick 		genfile(t);
84218354Smckusick 		break;
84318354Smckusick 
84418354Smckusick 	    default:
84518354Smckusick 		/* This shouldn't happen */
84618354Smckusick 		/* Rather than bomb outright, let debugging go on */
84718354Smckusick 		warning();
84818354Smckusick 		error("Bad type class found in stab");
84918354Smckusick 		putprintf("1", 1, t->class);
85018354Smckusick 		break;
85118354Smckusick 	}
85218354Smckusick     }
85318354Smckusick }
85418354Smckusick 
85518354Smckusick /*
85618354Smckusick  * Continue stab information in a namelist new entry.  This is necessary
85718354Smckusick  * to avoid overflowing putprintf's buffer.
85818354Smckusick  */
85918354Smckusick 
86018354Smckusick static gencontinue ()
86118354Smckusick {
86218354Smckusick     putprintf("?\",0x%x,0,0,0", 0, N_LSYM);
86318354Smckusick     putprintf("\t.stabs\t\"", 1);
86418354Smckusick }
86518354Smckusick 
866772Speter #endif PC
867