xref: /csrg-svn/usr.bin/pascal/src/stab.c (revision 18355)
1826Speter /* Copyright (c) 1980 Regents of the University of California */
2772Speter 
3*18355Smckusick #ifndef lint
4*18355Smckusick static	char sccsid[] = "@(#)stab.c 2.3 03/15/85";
5*18355Smckusick #endif
6826Speter 
7772Speter     /*
818354Smckusick      *	Procedures to put out symbol table information
9826Speter      *	and stabs for separate compilation type checking.
1018354Smckusick      *	These use the .stabs, .stabn, and .stabd directives.
11772Speter      */
12772Speter 
13772Speter #include	"whoami.h"
14772Speter #ifdef	PC
15772Speter     /*	and the rest of the file */
16772Speter #   include	"0.h"
1710649Speter #   include	"objfmt.h"
1815952Smckusick #   include	"yy.h"
19772Speter #   include	<stab.h>
20772Speter 
21842Speter     /*
22842Speter      *  additional symbol definition for <stab.h>
23842Speter      *	that is used by the separate compilation facility --
24842Speter      *	eventually, <stab.h> should be updated to include this
25842Speter      */
26772Speter 
27842Speter #   include	"pstab.h"
28772Speter #   include	"pc.h"
29772Speter 
3018354Smckusick 
3118354Smckusick #define private static
3218354Smckusick 
3318354Smckusick int oldway = 0;
3418354Smckusick 
35772Speter     /*
36826Speter      *	absolute value: line numbers are negative if error recovery.
37826Speter      */
38826Speter #define	ABS( x )	( x < 0 ? -x : x )
39*18355Smckusick long checksum();
40826Speter 
4118354Smckusick /*
4218354Smckusick  * Generate information about variables.
4318354Smckusick  */
4418354Smckusick 
4518354Smckusick stabgvar (p, length, line)
4618354Smckusick struct nl *p;
4718354Smckusick int length, line;
4818354Smckusick {
4918354Smckusick     putprintf("	.stabs	\"%s\",0x%x,0,0x%x,0x%x",
5018354Smckusick 	0, p->symbol, N_PC, N_PGVAR, ABS(line)
5118354Smckusick     );
5218354Smckusick     if (oldway != 0) {
5318354Smckusick 	oldstabgvar(p->symbol, p2type(p->type), 0, length, line);
5418354Smckusick     } else if (opt('g')) {
5518354Smckusick 	putprintf("\t.stabs\t\"%s:G", 1, p->symbol);
5618354Smckusick 	gentype(p->type);
5718354Smckusick 	putprintf("\",0x%x,0,0x%x,0", 0, N_GSYM, length);
5818354Smckusick     }
5918354Smckusick }
6018354Smckusick 
6118354Smckusick stablvar (p, offset, length)
6218354Smckusick struct nl *p;
6318354Smckusick int offset, length;
6418354Smckusick {
6518354Smckusick     int level;
6618354Smckusick 
6718354Smckusick     level = (p->nl_block & 037);
6818354Smckusick     if (oldway != 0) {
6918354Smckusick 	oldstablvar(p->symbol, p2type(p->type), level, offset, length);
7018354Smckusick     } else if (opt('g')) {
7118354Smckusick 	putprintf("\t.stabs\t\"%s:", 1, p->symbol);
7218354Smckusick 	gentype(p->type);
7318354Smckusick 	putprintf("\",0x%x,0,0x%x,0x%x", 0, N_LSYM, length, offset);
7418354Smckusick     }
7518354Smckusick }
7618354Smckusick 
77826Speter     /*
782164Speter      *	global variables
79772Speter      */
80*18355Smckusick /*ARGSUSED*/
8118354Smckusick oldstabgvar( name , type , offset , length , line )
82772Speter     char	*name;
83772Speter     int		type;
84772Speter     int		offset;
85772Speter     int		length;
86826Speter     int		line;
87772Speter     {
88772Speter 	if ( ! opt('g') ) {
89772Speter 		return;
90772Speter 	}
91772Speter 	putprintf( "	.stabs	\"" , 1 );
92*18355Smckusick 	putprintf( NAMEFORMAT , 1 , (int) name );
932164Speter 	putprintf( "\",0x%x,0,0x%x,0" , 0 , N_GSYM , type );
942164Speter 	putprintf( "	.stabs	\"" , 1 );
95*18355Smckusick 	putprintf( NAMEFORMAT , 1 , (int) name );
962164Speter 	putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length );
972164Speter }
982164Speter 
992164Speter     /*
1002164Speter      *	local variables
1012164Speter      */
102*18355Smckusick /*ARGSUSED*/
10318354Smckusick oldstablvar( name , type , level , offset , length )
1042164Speter     char	*name;
1052164Speter     int		type;
1062164Speter     int		level;
1072164Speter     int		offset;
1082164Speter     int		length;
1092164Speter     {
1102164Speter 
1112164Speter 	if ( ! opt('g') ) {
1122164Speter 		return;
113772Speter 	}
114772Speter 	putprintf( "	.stabs	\"" , 1 );
115*18355Smckusick 	putprintf( NAMEFORMAT , 1 , (int) name );
1162164Speter 	putprintf( "\",0x%x,0,0x%x,0x%x" , 0 , N_LSYM , type , -offset );
1172164Speter 	putprintf( "	.stabs	\"" , 1 );
118*18355Smckusick 	putprintf( NAMEFORMAT , 1 , (int) name );
119826Speter 	putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length );
120772Speter }
121772Speter 
122772Speter 
12318354Smckusick stabparam (p, offset, length)
12418354Smckusick struct nl *p;
12518354Smckusick int offset, length;
12618354Smckusick {
12718354Smckusick     if (oldway != 0) {
12818354Smckusick 	oldstabparam(p->symbol, p2type(p->type), offset, length);
12918354Smckusick     } else if (opt('g')) {
13018354Smckusick 	putprintf("\t.stabs\t\"%s:", 1, p->symbol);
13118354Smckusick 	if (p->class == REF) {
13218354Smckusick 	    putprintf("v", 1);
13318354Smckusick 	} else {
13418354Smckusick 	    putprintf("p", 1);
13518354Smckusick 	}
13618354Smckusick 	gentype((p->class == FPROC || p->class ==FFUNC) ? p : p->type);
13718354Smckusick 	putprintf("\",0x%x,0,0x%x,0x%x", 0, N_PSYM, length, offset);
13818354Smckusick     }
13918354Smckusick }
14018354Smckusick 
141772Speter     /*
142772Speter      *	parameters
143772Speter      */
14418354Smckusick oldstabparam( name , type , offset , length )
145772Speter     char	*name;
146772Speter     int		type;
147772Speter     int		offset;
148772Speter     int		length;
149772Speter     {
150772Speter 
151772Speter 	if ( ! opt('g') ) {
152772Speter 		return;
153772Speter 	}
154772Speter 	putprintf( "	.stabs	\"" , 1 );
155*18355Smckusick 	putprintf( NAMEFORMAT , 1 , (int) name );
156826Speter 	putprintf( "\",0x%x,0,0x%x,0x%x" , 0 , N_PSYM , type , offset );
157772Speter 	putprintf( "	.stabs	\"" , 1 );
158*18355Smckusick 	putprintf( NAMEFORMAT , 1 , (int) name );
159826Speter 	putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length );
160772Speter     }
161772Speter 
162772Speter     /*
163772Speter      *	fields
164772Speter      */
165772Speter 
166772Speter     /*
167772Speter      *	left brackets
16818354Smckusick      *  (dbx handles module-2 without these, so we won't use them either)
169772Speter      */
170772Speter stablbrac( level )
171772Speter     int	level;
172772Speter     {
173772Speter 
17418354Smckusick 	if ( ! opt('g') || oldway == 0 ) {
175772Speter 		return;
176772Speter 	}
177826Speter 	putprintf( "	.stabd	0x%x,0,0x%x" , 0 , N_LBRAC , level );
178772Speter     }
179772Speter 
180772Speter     /*
181772Speter      *	right brackets
182772Speter      */
183772Speter stabrbrac( level )
184772Speter     int	level;
185772Speter     {
186772Speter 
18718354Smckusick 	if ( ! opt('g') || oldway == 0 ) {
188772Speter 		return;
189772Speter 	}
190826Speter 	putprintf( "	.stabd	0x%x,0,0x%x" , 0 , N_RBRAC , level );
191772Speter     }
192772Speter 
19318354Smckusick stabfunc (p, name, line, level)
19418354Smckusick struct nl *p;
19518354Smckusick char *name;
19618354Smckusick int line, level;
19718354Smckusick {
19818354Smckusick     char extname[BUFSIZ],nestspec[BUFSIZ];
19918354Smckusick 
20018354Smckusick     if ( level == 1 ) {
20118354Smckusick 	if (p->class == FUNC) {
20218354Smckusick 	    putprintf("	.stabs	\"%s\",0x%x,0,0x%x,0x%x" ,
20318354Smckusick 		0 , name , N_PC , N_PGFUNC , ABS( line )
20418354Smckusick 	    );
20518354Smckusick 	} else if (p->class == PROC) {
20618354Smckusick 	    putprintf("	.stabs	\"%s\",0x%x,0,0x%x,0x%x" ,
20718354Smckusick 		0 , name , N_PC , N_PGPROC , ABS( line )
20818354Smckusick 	    );
20918354Smckusick 	}
21018354Smckusick     }
21118354Smckusick     if (oldway != 0) {
21218354Smckusick 	oldstabfunc(name, p->class, line, level);
21318354Smckusick     } else if (opt('g')) {
21418354Smckusick 	putprintf("\t.stabs\t\"%s:", 1, name);
21518354Smckusick 	if (p->class == FUNC) {
21618354Smckusick 	    putprintf("F", 1);
21718354Smckusick 	    gentype(p->type);
21818354Smckusick 	    putprintf(",", 1);
21918354Smckusick 	} else {
22018354Smckusick 	    putprintf("P,", 1);
22118354Smckusick 	}
22218354Smckusick 	sextname(extname, name, level);  /* set extname to entry label */
22318354Smckusick 	putprintf("%s,", 1, &(extname[1])); /* remove initial underbar */
22418354Smckusick 	snestspec(nestspec, level);
22518354Smckusick 	putprintf("%s\",0x%x,0,0,%s", 0, nestspec, N_FUN, extname);
22618354Smckusick     }
22718354Smckusick }
22818354Smckusick 
229772Speter     /*
23018354Smckusick      * construct the colon-separated static nesting string into a
23118354Smckusick      * caller-supplied buffer
23218354Smckusick      */
23318354Smckusick private snestspec(buffer, level)
23418354Smckusick     char buffer[];
23518354Smckusick     int level;
23618354Smckusick {
23718354Smckusick     char *starthere;
23818354Smckusick     int i;
23918354Smckusick 
24018354Smckusick     if (level <= 1) {
24118354Smckusick 	buffer[0] = '\0';
24218354Smckusick     } else {
24318354Smckusick 	starthere = &buffer[0];
24418354Smckusick 	for ( i = 1 ; i < level ; i++ ) {
24518354Smckusick 	    sprintf(starthere, "%s:", enclosing[i]);
24618354Smckusick 	    starthere += strlen(enclosing[i]) + 1;
24718354Smckusick 	}
24818354Smckusick 	*starthere-- = '\0'; /* remove last colon */
24918354Smckusick 	if (starthere >= &buffer[BUFSIZ-1]) {
25018354Smckusick 	    panic("snestspec");
25118354Smckusick 	}
25218354Smckusick     }
25318354Smckusick }
25418354Smckusick 
25518354Smckusick     /*
256772Speter      *	functions
257772Speter      */
25818354Smckusick oldstabfunc( name , typeclass , line , level )
259772Speter     char	*name;
2607925Smckusick     int		typeclass;
261772Speter     int		line;
262772Speter     long	level;
263772Speter     {
2643365Speter 	char	extname[ BUFSIZ ];
265772Speter 
266826Speter 	    /*
267826Speter 	     *	for sdb
268826Speter 	     */
269772Speter 	if ( ! opt('g') ) {
270772Speter 		return;
271772Speter 	}
272772Speter 	putprintf( "	.stabs	\"" , 1 );
273*18355Smckusick 	putprintf( NAMEFORMAT , 1 , (int) name );
274*18355Smckusick 	sextname( extname , name , (int) level );
275*18355Smckusick 	putprintf( "\",0x%x,0,0x%x,%s" , 0 , N_FUN , line , (int) extname );
276772Speter     }
277772Speter 
278772Speter     /*
279772Speter      *	source line numbers
280772Speter      */
281772Speter stabline( line )
282772Speter     int	line;
283772Speter     {
284772Speter 	if ( ! opt('g') ) {
285772Speter 		return;
286772Speter 	}
287826Speter 	putprintf( "	.stabd	0x%x,0,0x%x" , 0 , N_SLINE , ABS( line ) );
288772Speter     }
289772Speter 
290772Speter     /*
29118354Smckusick      *	source files get none or more of these:
29218354Smckusick      *  one as they are entered,
29318354Smckusick      *  and one every time they are returned to from nested #includes
294772Speter      */
29518354Smckusick stabsource(filename, firsttime)
296772Speter     char	*filename;
29718354Smckusick     bool	firsttime;
29815952Smckusick {
29915952Smckusick     int		label;
30015952Smckusick 
30115952Smckusick 	/*
30215952Smckusick 	 *	for separate compilation
30315952Smckusick 	 */
30415952Smckusick     putprintf("	.stabs	\"%s\",0x%x,0,0x%x,0x%x", 0,
305*18355Smckusick 	    (int) filename, N_PC, N_PSO, N_FLAGCHECKSUM);
30615952Smckusick 	/*
30718354Smckusick 	 *	for debugger
30815952Smckusick 	 */
30915952Smckusick     if ( ! opt('g') ) {
31015952Smckusick 	    return;
311772Speter     }
31218354Smckusick     if (oldway != 0) {
313*18355Smckusick 	label = (int) getlab();
31418354Smckusick 	putprintf( "	.stabs	\"" , 1 );
31518354Smckusick 	putprintf( NAMEFORMAT , 1 , filename );
31618354Smckusick 	putprintf( "\",0x%x,0,0," , 1 , N_SO );
31718354Smckusick 	putprintf( PREFIXFORMAT , 0 , LLABELPREFIX , label );
31818354Smckusick 	putprintf( PREFIXFORMAT , 1 , LLABELPREFIX , label );
31918354Smckusick 	putprintf( ":" , 0 );
32018354Smckusick     } else {
32118354Smckusick 	if (firsttime) {
32218354Smckusick 	    putprintf( "	.stabs	\"" , 1 );
32318354Smckusick 	    putprintf( NAMEFORMAT , 1 , filename );
32418354Smckusick 	    putprintf( "\",0x%x,0,0,0" , 0 , N_SO );
32518354Smckusick 	}
32618354Smckusick     }
32715952Smckusick }
328772Speter 
329772Speter     /*
330772Speter      *	included files get one or more of these:
331772Speter      *	one as they are entered by a #include,
33215952Smckusick      *	and one every time they are returned to from nested #includes.
333772Speter      */
33415952Smckusick stabinclude(filename, firsttime)
335772Speter     char	*filename;
33615952Smckusick     bool	firsttime;
33715952Smckusick {
338*18355Smckusick     int		label;
33915952Smckusick     long	check;
34015952Smckusick 
34115952Smckusick 	/*
34215952Smckusick 	 *	for separate compilation
34315952Smckusick 	 */
34415952Smckusick     if (firsttime) {
34515952Smckusick 	check = checksum(filename);
34615952Smckusick     } else {
34715952Smckusick 	check = N_FLAGCHECKSUM;
34815952Smckusick     }
34915952Smckusick     putprintf("	.stabs	\"%s\",0x%x,0,0x%x,0x%x", 0,
350*18355Smckusick 	    (int) filename, N_PC, N_PSOL, check);
35115952Smckusick 	/*
35215952Smckusick 	 *	for sdb
35315952Smckusick 	 */
35415952Smckusick     if ( ! opt('g') ) {
35515952Smckusick 	    return;
35615952Smckusick     }
35718354Smckusick     if (oldway != 0) {
358*18355Smckusick 	label = (int) getlab();
35918354Smckusick 	putprintf( "	.stabs	\"" , 1 );
36018354Smckusick 	putprintf( NAMEFORMAT , 1 , filename );
36118354Smckusick 	putprintf( "\",0x%x,0,0," , 1 , N_SOL );
36218354Smckusick 	putprintf( PREFIXFORMAT , 0 , LLABELPREFIX , label );
36318354Smckusick 	putprintf( PREFIXFORMAT , 1 , LLABELPREFIX , label );
36418354Smckusick 	putprintf( ":" , 0 );
36518354Smckusick     }
36615952Smckusick }
36715952Smckusick 
36815952Smckusick     /*
36915952Smckusick      *	anyone know a good checksum for ascii files?
37015952Smckusick      *	this does a rotate-left and then exclusive-or's in the character.
37115952Smckusick      *	also, it avoids returning checksums of 0.
37215952Smckusick      *	The rotate is implemented by shifting and adding back the
37315952Smckusick      *	sign bit when negative.
37415952Smckusick      */
37515952Smckusick long
37615952Smckusick checksum(filename)
37715952Smckusick     char	*filename;
37815952Smckusick {
37915952Smckusick     FILE		*filep;
38015952Smckusick     register int	input;
38115952Smckusick     register long	check;
38215952Smckusick 
38315952Smckusick     filep = fopen(filename, "r");
38415952Smckusick     if (filep == NULL) {
38515952Smckusick 	perror(filename);
38615952Smckusick 	pexit(DIED);
38715952Smckusick     }
38815952Smckusick     check = 0;
38915952Smckusick     while ((input = getc(filep)) != EOF) {
39015952Smckusick 	if (check < 0) {
39115952Smckusick 	    check <<= 1;
39215952Smckusick 	    check += 1;
39315952Smckusick 	} else {
39415952Smckusick 	    check <<= 1;
39515942Smckusick 	}
39615952Smckusick 	check ^= input;
39714128Speter     }
398*18355Smckusick     (void) fclose(filep);
39915952Smckusick     if ((unsigned) check <= N_FLAGCHECKSUM) {
40015952Smckusick 	return N_FLAGCHECKSUM + 1;
40115952Smckusick     } else {
40215952Smckusick 	return check;
40315952Smckusick     }
40415952Smckusick }
40514128Speter 
406772Speter /*
407772Speter  * global Pascal symbols :
408772Speter  *   labels, types, constants, and external procedure and function names:
409772Speter  *   These are used by the separate compilation facility
410772Speter  *   to be able to check for disjoint header files.
411772Speter  */
412772Speter 
413826Speter     /*
414826Speter      *	global labels
415826Speter      */
416842Speter stabglabel( label , line )
417826Speter     char	*label;
418826Speter     int		line;
419772Speter     {
420772Speter 
421842Speter 	putprintf( "	.stabs	\"%s\",0x%x,0,0x%x,0x%x" , 0
422*18355Smckusick 		    , (int) label , N_PC , N_PGLABEL , ABS( line ) );
423772Speter     }
424772Speter 
425826Speter     /*
426826Speter      *	global constants
427826Speter      */
428842Speter stabgconst( const , line )
429842Speter     char	*const;
430826Speter     int		line;
431772Speter     {
432772Speter 
433842Speter 	    putprintf( "	.stabs	\"%s\",0x%x,0,0x%x,0x%x" , 0
434*18355Smckusick 			, (int) const , N_PC , N_PGCONST , ABS( line ) );
435772Speter     }
436772Speter 
43718354Smckusick /*
43818354Smckusick  * Generate symbolic information about a constant.
43918354Smckusick  */
440772Speter 
44118354Smckusick stabconst (c)
44218354Smckusick struct nl *c;
44318354Smckusick {
44418354Smckusick     if (opt('g') && oldway == 0) {
44518354Smckusick 	putprintf("\t.stabs\t\"%s:c=", 1, c->symbol);
44618354Smckusick 	if (c->type == nl + TSTR) {
44718354Smckusick 	    putprintf("s'%s'", 1, c->ptr[0]);
44818354Smckusick 	} else if (c->type == nl + T1CHAR) {
44918354Smckusick 	    putprintf("c%d", 1, c->range[0]);
45018354Smckusick 	} else if (isa(c->type, "i")) {
45118354Smckusick 	    putprintf("i%d", 1, c->range[0]);
45218354Smckusick 	} else if (isa(c->type, "d")) {
45318354Smckusick 	    putprintf("r%g", 1, c->real);
45418354Smckusick 	} else {
45518354Smckusick 	    putprintf("e", 1);
45618354Smckusick 	    gentype(c->type);
45718354Smckusick 	    putprintf(",%d", 1, c->range[0]);
45818354Smckusick 	}
45918354Smckusick 	putprintf("\",0x%x,0,0x%x,0x%x", 0, N_LSYM, 0, 0);
460772Speter     }
46118354Smckusick }
462772Speter 
46318354Smckusick stabgtype (name, type, line)
46418354Smckusick char *name;
46518354Smckusick struct nl *type;
46618354Smckusick int line;
46718354Smckusick {
46818354Smckusick     putprintf("	.stabs	\"%s\",0x%x,0,0x%x,0x%x" ,
46918354Smckusick 	0, name, N_PC , N_PGTYPE, ABS(line)
47018354Smckusick     );
47118354Smckusick     if (oldway == 0) {
47218354Smckusick 	stabltype(name, type);
47318354Smckusick     }
47418354Smckusick }
475772Speter 
47618354Smckusick stabltype (name, type)
47718354Smckusick char *name;
47818354Smckusick struct nl *type;
47918354Smckusick {
48018354Smckusick     if (opt('g')) {
48118354Smckusick 	putprintf("\t.stabs\t\"%s:t", 1, name);
48218354Smckusick 	gentype(type);
48318354Smckusick 	putprintf("\",0x%x,0,0,0", 0, N_LSYM);
48418354Smckusick     }
48518354Smckusick }
48618354Smckusick 
487826Speter     /*
488826Speter      *	external functions and procedures
489826Speter      */
4907925Smckusick stabefunc( name , typeclass , line )
491826Speter     char	*name;
4927925Smckusick     int		typeclass;
493826Speter     int		line;
494772Speter     {
495826Speter 	int	type;
496772Speter 
4977925Smckusick 	if ( typeclass == FUNC ) {
498842Speter 	    type = N_PEFUNC;
4997925Smckusick 	} else if ( typeclass == PROC ) {
500842Speter 	    type = N_PEPROC;
501826Speter 	} else {
502826Speter 	    return;
503772Speter 	}
504842Speter 	putprintf( "	.stabs	\"%s\",0x%x,0,0x%x,0x%x" , 0
505*18355Smckusick 		    , (int) name , N_PC , type , ABS( line ) );
506772Speter     }
507772Speter 
50818354Smckusick /*
50918354Smckusick  * Generate type information encoded as a string for dbx.
51018354Smckusick  * The fwdptrnum field is used only when the type is a pointer
51118354Smckusick  * to a type that isn't known when it was entered.  When the
51218354Smckusick  * type field is filled for some such tptr, fixfwdtype should
51318354Smckusick  * be called to output an equivalencing type definition.
51418354Smckusick  */
51518354Smckusick 
51618354Smckusick typedef struct TypeDesc *TypeDesc;
51718354Smckusick 
51818354Smckusick struct TypeDesc {
51918354Smckusick     struct nl *tptr;
52018354Smckusick     int tnum;
52118354Smckusick     int fwdptrnum;
52218354Smckusick     TypeDesc chain;
52318354Smckusick };
52418354Smckusick 
52518354Smckusick #define TABLESIZE 2003
52618354Smckusick 
52718354Smckusick #define typehash(t) ( ( ((int) t) >> 2 ) % TABLESIZE )
52818354Smckusick 
52918354Smckusick private int tcount = 1;
53018354Smckusick private TypeDesc typetable[TABLESIZE];
53118354Smckusick 
53218354Smckusick private TypeDesc tdlookup (t)
53318354Smckusick struct nl *t;
53418354Smckusick {
53518354Smckusick     register TypeDesc td;
53618354Smckusick 
53718354Smckusick     td = typetable[typehash(t)];
53818354Smckusick     while (td != NIL && td->tptr != t) {
53918354Smckusick 	td = td->chain;
54018354Smckusick     }
54118354Smckusick     return td;
54218354Smckusick }
54318354Smckusick 
54418354Smckusick private int typelookup (t)
54518354Smckusick struct nl *t;
54618354Smckusick {
54718354Smckusick     register TypeDesc td;
54818354Smckusick     int r;
54918354Smckusick 
55018354Smckusick     td = tdlookup(t);
55118354Smckusick     if (td == NIL) {
55218354Smckusick 	r = 0;
55318354Smckusick     } else {
55418354Smckusick 	r = td->tnum;
55518354Smckusick     }
55618354Smckusick     return r;
55718354Smckusick }
55818354Smckusick 
55918354Smckusick private int entertype (type)
56018354Smckusick struct nl *type;
56118354Smckusick {
56218354Smckusick     register TypeDesc td;
56318354Smckusick     register int i;
56418354Smckusick 
56518354Smckusick     td = (TypeDesc) malloc(sizeof(struct TypeDesc));
56618354Smckusick     td->tptr = type;
56718354Smckusick     td->tnum = tcount;
56818354Smckusick     td->fwdptrnum = 0;
56918354Smckusick     ++tcount;
57018354Smckusick     i = typehash(type);
57118354Smckusick     td->chain = typetable[i];
57218354Smckusick     typetable[i] = td;
57318354Smckusick     return td->tnum;
57418354Smckusick }
57518354Smckusick 
57618354Smckusick /*
57718354Smckusick  * The in_types table currently contains "boolean", "char", "integer",
57818354Smckusick  * "real" and "_nil".  (See nl.c for definition.)
57918354Smckusick  * The lookup call below will give the TYPE class nl entry for these
58018354Smckusick  * types.  In each case except _nil, the type field of that entry is a RANGE
58118354Smckusick  * class nl entry for the type.  Sometimes other symbol table entries
58218354Smckusick  * point to the TYPE entry (e.g., when there is a range over the base type),
58318354Smckusick  * and other entries point to the RANGE entry (e.g., for a variable of the
58418354Smckusick  * given type).  We don't really want to distinguish between these uses
58518354Smckusick  * in dbx, and since it appears that the RANGE entries are not reused if
58618354Smckusick  * a range happens to coincide, we will give the two the same identifying
58718354Smckusick  * dbx type number.
58818354Smckusick  */
58918354Smckusick 
59018354Smckusick private inittypes()
59118354Smckusick {
59218354Smckusick     int i;
59318354Smckusick     extern char *in_types[];
59418354Smckusick     struct nl *p;
59518354Smckusick 
59618354Smckusick     for (i = 0; in_types[i] != NIL; i++) {
59718354Smckusick 	p = lookup(in_types[i]);
59818354Smckusick 	if (p != NIL) {
59918354Smckusick 	    entertype(p);
60018354Smckusick 	    if (p->type != NIL) {
60118354Smckusick 		--tcount; /* see comment above */
60218354Smckusick 		entertype(p->type);
60318354Smckusick 	    }
60418354Smckusick 	}
60518354Smckusick     }
60618354Smckusick }
60718354Smckusick 
60818354Smckusick static genarray (t)
60918354Smckusick struct nl *t;
61018354Smckusick {
61118354Smckusick     register struct nl *p;
61218354Smckusick 
61318354Smckusick     putprintf("a", 1);
61418354Smckusick     for (p = t->chain; p != NIL; p = p->chain) {
61518354Smckusick 	gentype(p);
61618354Smckusick 	putprintf(";", 1);
61718354Smckusick     }
61818354Smckusick     gentype(t->type);
61918354Smckusick }
62018354Smckusick 
62118354Smckusick /*
62218354Smckusick  * Really we should walk through ptr[NL_FIELDLIST] for the fields,
62318354Smckusick  * and then do the variant tag and fields separately, but dbx
62418354Smckusick  * doesn't support this yet.
62518354Smckusick  * So, since all the fields of all the variants are on the chain,
62618354Smckusick  * we walk through that.  Except that this gives the fields in the
62718354Smckusick  * reverse order, so we want to print in reverse order.
62818354Smckusick  */
62918354Smckusick 
63018354Smckusick static genrecord (t)
63118354Smckusick struct nl *t;
63218354Smckusick {
63318354Smckusick     putprintf("s%d", 1, t->value[NL_OFFS]);
63418354Smckusick     if (t->chain != NIL) {
63518354Smckusick 	genrecfield(t->chain, 1);
63618354Smckusick     }
63718354Smckusick     putprintf(";", 1);
63818354Smckusick }
63918354Smckusick 
64018354Smckusick static genrecfield (t, n)
64118354Smckusick struct nl *t;
64218354Smckusick int n;
64318354Smckusick {
64418354Smckusick     if (t->chain != NULL) {
64518354Smckusick 	genrecfield(t->chain, n + 1);
64618354Smckusick 	if (n % 2 == 0) {
64718354Smckusick 	    gencontinue();
64818354Smckusick 	}
64918354Smckusick     }
65018354Smckusick     putprintf("%s:", 1, t->symbol);
65118354Smckusick     gentype(t->type);
65218354Smckusick     putprintf(",%d,%d;", 1, 8*t->value[NL_OFFS], 8*lwidth(t->type));
65318354Smckusick }
65418354Smckusick 
65518354Smckusick static genvarnt (t)
65618354Smckusick struct nl *t;
65718354Smckusick {
65818354Smckusick     genrecord(t);
65918354Smckusick }
66018354Smckusick 
66118354Smckusick static genptr (t)
66218354Smckusick struct nl *t;
66318354Smckusick {
66418354Smckusick     register TypeDesc td;
66518354Smckusick 
66618354Smckusick     putprintf("*", 1);
66718354Smckusick     if (t->type != NIL) {
66818354Smckusick 	gentype(t->type);
66918354Smckusick     } else {
67018354Smckusick 	/*
67118354Smckusick 	 * unresolved forward pointer: use tcount to represent what is
67218354Smckusick          * begin pointed to, to be defined later
67318354Smckusick 	 */
67418354Smckusick 	td = tdlookup(t);
67518354Smckusick 	if (td == NIL) {
67618354Smckusick 	    panic("nil ptr in stab.genptr");
67718354Smckusick 	}
67818354Smckusick 	td->fwdptrnum = tcount;
67918354Smckusick 	putprintf("%d", 1, tcount);
68018354Smckusick 	++tcount;
68118354Smckusick     }
68218354Smckusick }
68318354Smckusick 
68418354Smckusick /*
68518354Smckusick  * The type t is a pointer which has just had its type field filled.
68618354Smckusick  * We need to generate a type stab saying that the number saved
68718354Smckusick  * in t's fwdptrnum is the same as the t->type's number
68818354Smckusick  */
68918354Smckusick 
69018354Smckusick fixfwdtype (t)
69118354Smckusick struct nl *t;
69218354Smckusick {
69318354Smckusick     register TypeDesc td;
69418354Smckusick 
69518354Smckusick     if (opt('g') && oldway == 0) {
69618354Smckusick 	td = tdlookup(t);
69718354Smckusick 	if (td != NIL) {
69818354Smckusick 	    putprintf("\t.stabs\t\":t%d=", 1, td->fwdptrnum);
69918354Smckusick 	    gentype(t->type);
70018354Smckusick 	    putprintf("\",0x%x,0,0,0", 0, N_LSYM);
70118354Smckusick 	}
70218354Smckusick     }
70318354Smckusick }
70418354Smckusick 
70518354Smckusick static genenum (t)
70618354Smckusick struct nl *t;
70718354Smckusick {
70818354Smckusick     register struct nl *e;
70918354Smckusick     register int i;
71018354Smckusick 
71118354Smckusick     putprintf("e", 1);
71218354Smckusick     i = 1;
71318354Smckusick     e = t->chain;
71418354Smckusick     while (e != NULL) {
71518354Smckusick 	if (i > 2) {
71618354Smckusick 	    gencontinue();
71718354Smckusick 	    i = 0;
71818354Smckusick 	}
71918354Smckusick 	putprintf("%s:%d,", 1, e->symbol, e->range[0]);
72018354Smckusick 	e = e->chain;
72118354Smckusick 	++i;
72218354Smckusick     }
72318354Smckusick     putprintf(";", 1);
72418354Smckusick }
72518354Smckusick 
72618354Smckusick static genset (t)
72718354Smckusick struct nl *t;
72818354Smckusick {
72918354Smckusick     putprintf("S", 1);
73018354Smckusick     gentype(t->type);
73118354Smckusick }
73218354Smckusick 
73318354Smckusick static genrange (t)
73418354Smckusick struct nl *t;
73518354Smckusick {
73618354Smckusick     putprintf("r", 1);
73718354Smckusick     gentype(t->type);
73818354Smckusick     putprintf(";%d;%d", 1, t->range[0], t->range[1]);
73918354Smckusick }
74018354Smckusick 
74118354Smckusick static genfparam (t)
74218354Smckusick struct nl *t;
74318354Smckusick {
74418354Smckusick     struct nl *p;
74518354Smckusick     int count;
74618354Smckusick 
74718354Smckusick     if (t->type != NULL) {
74818354Smckusick 	putprintf("f", 1);
74918354Smckusick 	gentype(t->type);
75018354Smckusick 	putprintf(",", 1);
75118354Smckusick     } else {
75218354Smckusick 	putprintf("p", 1);
75318354Smckusick     }
75418354Smckusick     count = 0;
75518354Smckusick     for (p = t->ptr[NL_FCHAIN]; p != NULL; p = p->chain) {
75618354Smckusick 	++count;
75718354Smckusick     }
75818354Smckusick     putprintf("%d;", 1, count);
75918354Smckusick     for (p = t->ptr[NL_FCHAIN]; p != NULL; p = p->chain) {
76018354Smckusick 	gentype(p->type);
76118354Smckusick 	putprintf(",%d;", 1, p->class);
76218354Smckusick     }
76318354Smckusick }
76418354Smckusick 
76518354Smckusick static genfile (t)
76618354Smckusick struct nl *t;
76718354Smckusick {
76818354Smckusick     putprintf("d", 1);
76918354Smckusick     gentype(t->type);
77018354Smckusick }
77118354Smckusick 
77218354Smckusick static gentype (t)
77318354Smckusick struct nl *t;
77418354Smckusick {
77518354Smckusick     int id;
77618354Smckusick 
77718354Smckusick     if (tcount == 1) {
77818354Smckusick 	inittypes();
77918354Smckusick     }
78018354Smckusick     id = typelookup(t);
78118354Smckusick     if (id != 0) {
78218354Smckusick 	putprintf("%d", 1, id);
78318354Smckusick     } else if (t->class == SCAL && t->chain == NULL) {
78418354Smckusick 	id = typelookup(t->type);
78518354Smckusick 	if (id != 0) {
78618354Smckusick 	    putprintf("%d", 1, id);
78718354Smckusick 	} else {
78818354Smckusick 	    genenum(t->type);
78918354Smckusick 	}
79018354Smckusick     } else {
79118354Smckusick 	id = entertype(t);
79218354Smckusick 	putprintf("%d=", 1, id);
79318354Smckusick 	switch (t->class) {
79418354Smckusick 	    case TYPE:
79518354Smckusick 		gentype(t->type);
79618354Smckusick 		break;
79718354Smckusick 
79818354Smckusick 	    case ARRAY:
79918354Smckusick 		genarray(t);
80018354Smckusick 		break;
80118354Smckusick 
80218354Smckusick 	    case RECORD:
80318354Smckusick 		genrecord(t);
80418354Smckusick 		break;
80518354Smckusick 
80618354Smckusick 	    case VARNT:
80718354Smckusick 		genvarnt(t);
80818354Smckusick 		break;
80918354Smckusick 
81018354Smckusick 	    case REF:
81118354Smckusick 		gentype(t->type);
81218354Smckusick 		break;
81318354Smckusick 
81418354Smckusick 	    case PTR:
81518354Smckusick 		genptr(t);
81618354Smckusick 		break;
81718354Smckusick 
81818354Smckusick 	    case SET:
81918354Smckusick 		genset(t);
82018354Smckusick 		break;
82118354Smckusick 
82218354Smckusick 	    case RANGE:
82318354Smckusick 		genrange(t);
82418354Smckusick 		break;
82518354Smckusick 
82618354Smckusick 	    case SCAL:
82718354Smckusick 		genenum(t);
82818354Smckusick 		break;
82918354Smckusick 
83018354Smckusick 	    case FPROC:
83118354Smckusick 	    case FFUNC:
83218354Smckusick 		genfparam(t);
83318354Smckusick 		break;
83418354Smckusick 
83518354Smckusick 	    case FILET:
83618354Smckusick 	    case PTRFILE:
83718354Smckusick 		genfile(t);
83818354Smckusick 		break;
83918354Smckusick 
84018354Smckusick 	    default:
84118354Smckusick 		/* This shouldn't happen */
84218354Smckusick 		/* Rather than bomb outright, let debugging go on */
84318354Smckusick 		warning();
84418354Smckusick 		error("Bad type class found in stab");
84518354Smckusick 		putprintf("1", 1, t->class);
84618354Smckusick 		break;
84718354Smckusick 	}
84818354Smckusick     }
84918354Smckusick }
85018354Smckusick 
85118354Smckusick /*
85218354Smckusick  * Continue stab information in a namelist new entry.  This is necessary
85318354Smckusick  * to avoid overflowing putprintf's buffer.
85418354Smckusick  */
85518354Smckusick 
85618354Smckusick static gencontinue ()
85718354Smckusick {
85818354Smckusick     putprintf("?\",0x%x,0,0,0", 0, N_LSYM);
85918354Smckusick     putprintf("\t.stabs\t\"", 1);
86018354Smckusick }
86118354Smckusick 
862772Speter #endif PC
863