xref: /csrg-svn/usr.bin/pascal/src/stab.c (revision 18354)
1826Speter /* Copyright (c) 1980 Regents of the University of California */
2772Speter 
3*18354Smckusick static	char sccsid[] = "@(#)stab.c 1.9.1.1 03/15/85";
4826Speter 
5772Speter     /*
6*18354Smckusick      *	Procedures to put out symbol table information
7826Speter      *	and stabs for separate compilation type checking.
8*18354Smckusick      *	These use the .stabs, .stabn, and .stabd directives.
9772Speter      */
10772Speter 
11772Speter #include	"whoami.h"
12772Speter #ifdef	PC
13772Speter     /*	and the rest of the file */
14772Speter #   include	"0.h"
1510649Speter #   include	"objfmt.h"
1615952Smckusick #   include	"yy.h"
17772Speter #   include	<stab.h>
18772Speter 
19842Speter     /*
20842Speter      *  additional symbol definition for <stab.h>
21842Speter      *	that is used by the separate compilation facility --
22842Speter      *	eventually, <stab.h> should be updated to include this
23842Speter      */
24772Speter 
25842Speter #   include	"pstab.h"
26772Speter #   include	"pc.h"
27772Speter 
28*18354Smckusick 
29*18354Smckusick #define private static
30*18354Smckusick 
31*18354Smckusick int oldway = 0;
32*18354Smckusick 
33772Speter     /*
34826Speter      *	absolute value: line numbers are negative if error recovery.
35826Speter      */
36826Speter #define	ABS( x )	( x < 0 ? -x : x )
37826Speter 
38*18354Smckusick /*
39*18354Smckusick  * Generate information about variables.
40*18354Smckusick  */
41*18354Smckusick 
42*18354Smckusick stabgvar (p, length, line)
43*18354Smckusick struct nl *p;
44*18354Smckusick int length, line;
45*18354Smckusick {
46*18354Smckusick     putprintf("	.stabs	\"%s\",0x%x,0,0x%x,0x%x",
47*18354Smckusick 	0, p->symbol, N_PC, N_PGVAR, ABS(line)
48*18354Smckusick     );
49*18354Smckusick     if (oldway != 0) {
50*18354Smckusick 	oldstabgvar(p->symbol, p2type(p->type), 0, length, line);
51*18354Smckusick     } else if (opt('g')) {
52*18354Smckusick 	putprintf("\t.stabs\t\"%s:G", 1, p->symbol);
53*18354Smckusick 	gentype(p->type);
54*18354Smckusick 	putprintf("\",0x%x,0,0x%x,0", 0, N_GSYM, length);
55*18354Smckusick     }
56*18354Smckusick }
57*18354Smckusick 
58*18354Smckusick stablvar (p, offset, length)
59*18354Smckusick struct nl *p;
60*18354Smckusick int offset, length;
61*18354Smckusick {
62*18354Smckusick     int level;
63*18354Smckusick 
64*18354Smckusick     level = (p->nl_block & 037);
65*18354Smckusick     if (oldway != 0) {
66*18354Smckusick 	oldstablvar(p->symbol, p2type(p->type), level, offset, length);
67*18354Smckusick     } else if (opt('g')) {
68*18354Smckusick 	putprintf("\t.stabs\t\"%s:", 1, p->symbol);
69*18354Smckusick 	gentype(p->type);
70*18354Smckusick 	putprintf("\",0x%x,0,0x%x,0x%x", 0, N_LSYM, length, offset);
71*18354Smckusick     }
72*18354Smckusick }
73*18354Smckusick 
74826Speter     /*
752164Speter      *	global variables
76772Speter      */
77*18354Smckusick oldstabgvar( name , type , offset , length , line )
78772Speter     char	*name;
79772Speter     int		type;
80772Speter     int		offset;
81772Speter     int		length;
82826Speter     int		line;
83772Speter     {
84772Speter 	if ( ! opt('g') ) {
85772Speter 		return;
86772Speter 	}
87772Speter 	putprintf( "	.stabs	\"" , 1 );
88*18354Smckusick 	putprintf( NAMEFORMAT , 1 , name );
892164Speter 	putprintf( "\",0x%x,0,0x%x,0" , 0 , N_GSYM , type );
902164Speter 	putprintf( "	.stabs	\"" , 1 );
91*18354Smckusick 	putprintf( NAMEFORMAT , 1 , name );
922164Speter 	putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length );
932164Speter }
942164Speter 
952164Speter     /*
962164Speter      *	local variables
972164Speter      */
98*18354Smckusick oldstablvar( name , type , level , offset , length )
992164Speter     char	*name;
1002164Speter     int		type;
1012164Speter     int		level;
1022164Speter     int		offset;
1032164Speter     int		length;
1042164Speter     {
1052164Speter 
1062164Speter 	if ( ! opt('g') ) {
1072164Speter 		return;
108772Speter 	}
109772Speter 	putprintf( "	.stabs	\"" , 1 );
110*18354Smckusick 	putprintf( NAMEFORMAT , 1 , name );
1112164Speter 	putprintf( "\",0x%x,0,0x%x,0x%x" , 0 , N_LSYM , type , -offset );
1122164Speter 	putprintf( "	.stabs	\"" , 1 );
113*18354Smckusick 	putprintf( NAMEFORMAT , 1 , name );
114826Speter 	putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length );
115772Speter }
116772Speter 
117772Speter 
118*18354Smckusick stabparam (p, offset, length)
119*18354Smckusick struct nl *p;
120*18354Smckusick int offset, length;
121*18354Smckusick {
122*18354Smckusick     if (oldway != 0) {
123*18354Smckusick 	oldstabparam(p->symbol, p2type(p->type), offset, length);
124*18354Smckusick     } else if (opt('g')) {
125*18354Smckusick 	putprintf("\t.stabs\t\"%s:", 1, p->symbol);
126*18354Smckusick 	if (p->class == REF) {
127*18354Smckusick 	    putprintf("v", 1);
128*18354Smckusick 	} else {
129*18354Smckusick 	    putprintf("p", 1);
130*18354Smckusick 	}
131*18354Smckusick 	gentype((p->class == FPROC || p->class ==FFUNC) ? p : p->type);
132*18354Smckusick 	putprintf("\",0x%x,0,0x%x,0x%x", 0, N_PSYM, length, offset);
133*18354Smckusick     }
134*18354Smckusick }
135*18354Smckusick 
136772Speter     /*
137772Speter      *	parameters
138772Speter      */
139*18354Smckusick oldstabparam( name , type , offset , length )
140772Speter     char	*name;
141772Speter     int		type;
142772Speter     int		offset;
143772Speter     int		length;
144772Speter     {
145772Speter 
146772Speter 	if ( ! opt('g') ) {
147772Speter 		return;
148772Speter 	}
149772Speter 	putprintf( "	.stabs	\"" , 1 );
150*18354Smckusick 	putprintf( NAMEFORMAT , 1 , name );
151826Speter 	putprintf( "\",0x%x,0,0x%x,0x%x" , 0 , N_PSYM , type , offset );
152772Speter 	putprintf( "	.stabs	\"" , 1 );
153*18354Smckusick 	putprintf( NAMEFORMAT , 1 , name );
154826Speter 	putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length );
155772Speter     }
156772Speter 
157772Speter     /*
158772Speter      *	fields
159772Speter      */
160*18354Smckusick stabfield( name , type , offset , length )
161*18354Smckusick     char	*name;
162*18354Smckusick     int		type;
163*18354Smckusick     int		offset;
164*18354Smckusick     int		length;
165*18354Smckusick     {
166*18354Smckusick 
167*18354Smckusick 	if ( ! opt('g') ) {
168*18354Smckusick 		return;
169*18354Smckusick 	}
170*18354Smckusick 	putprintf( "	.stabs	\"" , 1 );
171*18354Smckusick 	putprintf( NAMEFORMAT , 1 , name );
172*18354Smckusick 	putprintf( "\",0x%x,0,0x%x,0x%x" , 0 , N_SSYM , type , offset );
173*18354Smckusick 	putprintf( "	.stabs	\"" , 1 );
174*18354Smckusick 	putprintf( NAMEFORMAT , 1 , name );
175*18354Smckusick 	putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length );
176*18354Smckusick     }
177772Speter 
178772Speter     /*
179772Speter      *	left brackets
180*18354Smckusick      *  (dbx handles module-2 without these, so we won't use them either)
181772Speter      */
182772Speter stablbrac( level )
183772Speter     int	level;
184772Speter     {
185772Speter 
186*18354Smckusick 	if ( ! opt('g') || oldway == 0 ) {
187772Speter 		return;
188772Speter 	}
189826Speter 	putprintf( "	.stabd	0x%x,0,0x%x" , 0 , N_LBRAC , level );
190772Speter     }
191772Speter 
192772Speter     /*
193772Speter      *	right brackets
194772Speter      */
195772Speter stabrbrac( level )
196772Speter     int	level;
197772Speter     {
198772Speter 
199*18354Smckusick 	if ( ! opt('g') || oldway == 0 ) {
200772Speter 		return;
201772Speter 	}
202826Speter 	putprintf( "	.stabd	0x%x,0,0x%x" , 0 , N_RBRAC , level );
203772Speter     }
204772Speter 
205*18354Smckusick stabfunc (p, name, line, level)
206*18354Smckusick struct nl *p;
207*18354Smckusick char *name;
208*18354Smckusick int line, level;
209*18354Smckusick {
210*18354Smckusick     char extname[BUFSIZ],nestspec[BUFSIZ];
211*18354Smckusick 
212*18354Smckusick     if ( level == 1 ) {
213*18354Smckusick 	if (p->class == FUNC) {
214*18354Smckusick 	    putprintf("	.stabs	\"%s\",0x%x,0,0x%x,0x%x" ,
215*18354Smckusick 		0 , name , N_PC , N_PGFUNC , ABS( line )
216*18354Smckusick 	    );
217*18354Smckusick 	} else if (p->class == PROC) {
218*18354Smckusick 	    putprintf("	.stabs	\"%s\",0x%x,0,0x%x,0x%x" ,
219*18354Smckusick 		0 , name , N_PC , N_PGPROC , ABS( line )
220*18354Smckusick 	    );
221*18354Smckusick 	}
222*18354Smckusick     }
223*18354Smckusick     if (oldway != 0) {
224*18354Smckusick 	oldstabfunc(name, p->class, line, level);
225*18354Smckusick     } else if (opt('g')) {
226*18354Smckusick 	putprintf("\t.stabs\t\"%s:", 1, name);
227*18354Smckusick 	if (p->class == FUNC) {
228*18354Smckusick 	    putprintf("F", 1);
229*18354Smckusick 	    gentype(p->type);
230*18354Smckusick 	    putprintf(",", 1);
231*18354Smckusick 	} else {
232*18354Smckusick 	    putprintf("P,", 1);
233*18354Smckusick 	}
234*18354Smckusick 	sextname(extname, name, level);  /* set extname to entry label */
235*18354Smckusick 	putprintf("%s,", 1, &(extname[1])); /* remove initial underbar */
236*18354Smckusick 	snestspec(nestspec, level);
237*18354Smckusick 	putprintf("%s\",0x%x,0,0,%s", 0, nestspec, N_FUN, extname);
238*18354Smckusick     }
239*18354Smckusick }
240*18354Smckusick 
241772Speter     /*
242*18354Smckusick      * construct the colon-separated static nesting string into a
243*18354Smckusick      * caller-supplied buffer
244*18354Smckusick      */
245*18354Smckusick private snestspec(buffer, level)
246*18354Smckusick     char buffer[];
247*18354Smckusick     int level;
248*18354Smckusick {
249*18354Smckusick     char *starthere;
250*18354Smckusick     int i;
251*18354Smckusick 
252*18354Smckusick     if (level <= 1) {
253*18354Smckusick 	buffer[0] = '\0';
254*18354Smckusick     } else {
255*18354Smckusick 	starthere = &buffer[0];
256*18354Smckusick 	for ( i = 1 ; i < level ; i++ ) {
257*18354Smckusick 	    sprintf(starthere, "%s:", enclosing[i]);
258*18354Smckusick 	    starthere += strlen(enclosing[i]) + 1;
259*18354Smckusick 	}
260*18354Smckusick 	*starthere-- = '\0'; /* remove last colon */
261*18354Smckusick 	if (starthere >= &buffer[BUFSIZ-1]) {
262*18354Smckusick 	    panic("snestspec");
263*18354Smckusick 	}
264*18354Smckusick     }
265*18354Smckusick }
266*18354Smckusick 
267*18354Smckusick     /*
268772Speter      *	functions
269772Speter      */
270*18354Smckusick oldstabfunc( name , typeclass , line , level )
271772Speter     char	*name;
2727925Smckusick     int		typeclass;
273772Speter     int		line;
274772Speter     long	level;
275772Speter     {
276*18354Smckusick 	int	type;
277*18354Smckusick 	long	i;
2783365Speter 	char	extname[ BUFSIZ ];
279772Speter 
280826Speter 	    /*
281826Speter 	     *	for sdb
282826Speter 	     */
283772Speter 	if ( ! opt('g') ) {
284772Speter 		return;
285772Speter 	}
286772Speter 	putprintf( "	.stabs	\"" , 1 );
287*18354Smckusick 	putprintf( NAMEFORMAT , 1 , name );
288*18354Smckusick 	sextname( extname , name , level );
289*18354Smckusick 	putprintf( "\",0x%x,0,0x%x,%s" , 0 , N_FUN , line , extname );
290772Speter     }
291772Speter 
292772Speter     /*
293772Speter      *	source line numbers
294772Speter      */
295772Speter stabline( line )
296772Speter     int	line;
297772Speter     {
298772Speter 	if ( ! opt('g') ) {
299772Speter 		return;
300772Speter 	}
301826Speter 	putprintf( "	.stabd	0x%x,0,0x%x" , 0 , N_SLINE , ABS( line ) );
302772Speter     }
303772Speter 
304772Speter     /*
305*18354Smckusick      *	source files get none or more of these:
306*18354Smckusick      *  one as they are entered,
307*18354Smckusick      *  and one every time they are returned to from nested #includes
308772Speter      */
309*18354Smckusick stabsource(filename, firsttime)
310772Speter     char	*filename;
311*18354Smckusick     bool	firsttime;
31215952Smckusick {
31315952Smckusick     int		label;
31415952Smckusick 
31515952Smckusick 	/*
31615952Smckusick 	 *	for separate compilation
31715952Smckusick 	 */
31815952Smckusick     putprintf("	.stabs	\"%s\",0x%x,0,0x%x,0x%x", 0,
319*18354Smckusick 	    filename, N_PC, N_PSO, N_FLAGCHECKSUM);
32015952Smckusick 	/*
321*18354Smckusick 	 *	for debugger
32215952Smckusick 	 */
32315952Smckusick     if ( ! opt('g') ) {
32415952Smckusick 	    return;
325772Speter     }
326*18354Smckusick     if (oldway != 0) {
327*18354Smckusick 	label = getlab();
328*18354Smckusick 	putprintf( "	.stabs	\"" , 1 );
329*18354Smckusick 	putprintf( NAMEFORMAT , 1 , filename );
330*18354Smckusick 	putprintf( "\",0x%x,0,0," , 1 , N_SO );
331*18354Smckusick 	putprintf( PREFIXFORMAT , 0 , LLABELPREFIX , label );
332*18354Smckusick 	putprintf( PREFIXFORMAT , 1 , LLABELPREFIX , label );
333*18354Smckusick 	putprintf( ":" , 0 );
334*18354Smckusick     } else {
335*18354Smckusick 	if (firsttime) {
336*18354Smckusick 	    putprintf( "	.stabs	\"" , 1 );
337*18354Smckusick 	    putprintf( NAMEFORMAT , 1 , filename );
338*18354Smckusick 	    putprintf( "\",0x%x,0,0,0" , 0 , N_SO );
339*18354Smckusick 	}
340*18354Smckusick     }
34115952Smckusick }
342772Speter 
343772Speter     /*
344772Speter      *	included files get one or more of these:
345772Speter      *	one as they are entered by a #include,
34615952Smckusick      *	and one every time they are returned to from nested #includes.
347772Speter      */
34815952Smckusick stabinclude(filename, firsttime)
349772Speter     char	*filename;
35015952Smckusick     bool	firsttime;
35115952Smckusick {
352*18354Smckusick     int	label;
35315952Smckusick     long	check;
35415952Smckusick 
35515952Smckusick 	/*
35615952Smckusick 	 *	for separate compilation
35715952Smckusick 	 */
35815952Smckusick     if (firsttime) {
35915952Smckusick 	check = checksum(filename);
36015952Smckusick     } else {
36115952Smckusick 	check = N_FLAGCHECKSUM;
36215952Smckusick     }
36315952Smckusick     putprintf("	.stabs	\"%s\",0x%x,0,0x%x,0x%x", 0,
364*18354Smckusick 	    filename, N_PC, N_PSOL, check);
36515952Smckusick 	/*
36615952Smckusick 	 *	for sdb
36715952Smckusick 	 */
36815952Smckusick     if ( ! opt('g') ) {
36915952Smckusick 	    return;
37015952Smckusick     }
371*18354Smckusick     if (oldway != 0) {
372*18354Smckusick 	label = getlab();
373*18354Smckusick 	putprintf( "	.stabs	\"" , 1 );
374*18354Smckusick 	putprintf( NAMEFORMAT , 1 , filename );
375*18354Smckusick 	putprintf( "\",0x%x,0,0," , 1 , N_SOL );
376*18354Smckusick 	putprintf( PREFIXFORMAT , 0 , LLABELPREFIX , label );
377*18354Smckusick 	putprintf( PREFIXFORMAT , 1 , LLABELPREFIX , label );
378*18354Smckusick 	putprintf( ":" , 0 );
379*18354Smckusick     }
38015952Smckusick }
38115952Smckusick 
38215952Smckusick     /*
38315952Smckusick      *	anyone know a good checksum for ascii files?
38415952Smckusick      *	this does a rotate-left and then exclusive-or's in the character.
38515952Smckusick      *	also, it avoids returning checksums of 0.
38615952Smckusick      *	The rotate is implemented by shifting and adding back the
38715952Smckusick      *	sign bit when negative.
38815952Smckusick      */
38915952Smckusick long
39015952Smckusick checksum(filename)
39115952Smckusick     char	*filename;
39215952Smckusick {
39315952Smckusick     FILE		*filep;
39415952Smckusick     register int	input;
39515952Smckusick     register long	check;
39615952Smckusick 
39715952Smckusick     filep = fopen(filename, "r");
39815952Smckusick     if (filep == NULL) {
39915952Smckusick 	perror(filename);
40015952Smckusick 	pexit(DIED);
40115952Smckusick     }
40215952Smckusick     check = 0;
40315952Smckusick     while ((input = getc(filep)) != EOF) {
40415952Smckusick 	if (check < 0) {
40515952Smckusick 	    check <<= 1;
40615952Smckusick 	    check += 1;
40715952Smckusick 	} else {
40815952Smckusick 	    check <<= 1;
40915942Smckusick 	}
41015952Smckusick 	check ^= input;
41114128Speter     }
412*18354Smckusick     fclose(filep);
41315952Smckusick     if ((unsigned) check <= N_FLAGCHECKSUM) {
41415952Smckusick 	return N_FLAGCHECKSUM + 1;
41515952Smckusick     } else {
41615952Smckusick 	return check;
41715952Smckusick     }
41815952Smckusick }
41914128Speter 
420772Speter /*
421772Speter  * global Pascal symbols :
422772Speter  *   labels, types, constants, and external procedure and function names:
423772Speter  *   These are used by the separate compilation facility
424772Speter  *   to be able to check for disjoint header files.
425772Speter  */
426772Speter 
427826Speter     /*
428826Speter      *	global labels
429826Speter      */
430842Speter stabglabel( label , line )
431826Speter     char	*label;
432826Speter     int		line;
433772Speter     {
434772Speter 
435842Speter 	putprintf( "	.stabs	\"%s\",0x%x,0,0x%x,0x%x" , 0
436*18354Smckusick 		    , label , N_PC , N_PGLABEL , ABS( line ) );
437772Speter     }
438772Speter 
439826Speter     /*
440826Speter      *	global constants
441826Speter      */
442842Speter stabgconst( const , line )
443842Speter     char	*const;
444826Speter     int		line;
445772Speter     {
446772Speter 
447842Speter 	    putprintf( "	.stabs	\"%s\",0x%x,0,0x%x,0x%x" , 0
448*18354Smckusick 			, const , N_PC , N_PGCONST , ABS( line ) );
449772Speter     }
450772Speter 
451*18354Smckusick /*
452*18354Smckusick  * Generate symbolic information about a constant.
453*18354Smckusick  */
454772Speter 
455*18354Smckusick stabconst (c)
456*18354Smckusick struct nl *c;
457*18354Smckusick {
458*18354Smckusick     if (opt('g') && oldway == 0) {
459*18354Smckusick 	putprintf("\t.stabs\t\"%s:c=", 1, c->symbol);
460*18354Smckusick 	if (c->type == nl + TSTR) {
461*18354Smckusick 	    putprintf("s'%s'", 1, c->ptr[0]);
462*18354Smckusick 	} else if (c->type == nl + T1CHAR) {
463*18354Smckusick 	    putprintf("c%d", 1, c->range[0]);
464*18354Smckusick 	} else if (isa(c->type, "i")) {
465*18354Smckusick 	    putprintf("i%d", 1, c->range[0]);
466*18354Smckusick 	} else if (isa(c->type, "d")) {
467*18354Smckusick 	    putprintf("r%g", 1, c->real);
468*18354Smckusick 	} else {
469*18354Smckusick 	    putprintf("e", 1);
470*18354Smckusick 	    gentype(c->type);
471*18354Smckusick 	    putprintf(",%d", 1, c->range[0]);
472*18354Smckusick 	}
473*18354Smckusick 	putprintf("\",0x%x,0,0x%x,0x%x", 0, N_LSYM, 0, 0);
474772Speter     }
475*18354Smckusick }
476772Speter 
477*18354Smckusick stabgtype (name, type, line)
478*18354Smckusick char *name;
479*18354Smckusick struct nl *type;
480*18354Smckusick int line;
481*18354Smckusick {
482*18354Smckusick     putprintf("	.stabs	\"%s\",0x%x,0,0x%x,0x%x" ,
483*18354Smckusick 	0, name, N_PC , N_PGTYPE, ABS(line)
484*18354Smckusick     );
485*18354Smckusick     if (oldway == 0) {
486*18354Smckusick 	stabltype(name, type);
487*18354Smckusick     }
488*18354Smckusick }
489772Speter 
490*18354Smckusick stabltype (name, type)
491*18354Smckusick char *name;
492*18354Smckusick struct nl *type;
493*18354Smckusick {
494*18354Smckusick     if (opt('g')) {
495*18354Smckusick 	putprintf("\t.stabs\t\"%s:t", 1, name);
496*18354Smckusick 	gentype(type);
497*18354Smckusick 	putprintf("\",0x%x,0,0,0", 0, N_LSYM);
498*18354Smckusick     }
499*18354Smckusick }
500*18354Smckusick 
501826Speter     /*
502826Speter      *	external functions and procedures
503826Speter      */
5047925Smckusick stabefunc( name , typeclass , line )
505826Speter     char	*name;
5067925Smckusick     int		typeclass;
507826Speter     int		line;
508772Speter     {
509826Speter 	int	type;
510772Speter 
5117925Smckusick 	if ( typeclass == FUNC ) {
512842Speter 	    type = N_PEFUNC;
5137925Smckusick 	} else if ( typeclass == PROC ) {
514842Speter 	    type = N_PEPROC;
515826Speter 	} else {
516826Speter 	    return;
517772Speter 	}
518842Speter 	putprintf( "	.stabs	\"%s\",0x%x,0,0x%x,0x%x" , 0
519*18354Smckusick 		    , name , N_PC , type , ABS( line ) );
520772Speter     }
521772Speter 
522*18354Smckusick /*
523*18354Smckusick  * Generate type information encoded as a string for dbx.
524*18354Smckusick  * The fwdptrnum field is used only when the type is a pointer
525*18354Smckusick  * to a type that isn't known when it was entered.  When the
526*18354Smckusick  * type field is filled for some such tptr, fixfwdtype should
527*18354Smckusick  * be called to output an equivalencing type definition.
528*18354Smckusick  */
529*18354Smckusick 
530*18354Smckusick typedef struct TypeDesc *TypeDesc;
531*18354Smckusick 
532*18354Smckusick struct TypeDesc {
533*18354Smckusick     struct nl *tptr;
534*18354Smckusick     int tnum;
535*18354Smckusick     int fwdptrnum;
536*18354Smckusick     TypeDesc chain;
537*18354Smckusick };
538*18354Smckusick 
539*18354Smckusick #define TABLESIZE 2003
540*18354Smckusick 
541*18354Smckusick #define typehash(t) ( ( ((int) t) >> 2 ) % TABLESIZE )
542*18354Smckusick 
543*18354Smckusick private int tcount = 1;
544*18354Smckusick private TypeDesc typetable[TABLESIZE];
545*18354Smckusick 
546*18354Smckusick private TypeDesc tdlookup (t)
547*18354Smckusick struct nl *t;
548*18354Smckusick {
549*18354Smckusick     register TypeDesc td;
550*18354Smckusick 
551*18354Smckusick     td = typetable[typehash(t)];
552*18354Smckusick     while (td != NIL && td->tptr != t) {
553*18354Smckusick 	td = td->chain;
554*18354Smckusick     }
555*18354Smckusick     return td;
556*18354Smckusick }
557*18354Smckusick 
558*18354Smckusick private int typelookup (t)
559*18354Smckusick struct nl *t;
560*18354Smckusick {
561*18354Smckusick     register TypeDesc td;
562*18354Smckusick     int r;
563*18354Smckusick 
564*18354Smckusick     td = tdlookup(t);
565*18354Smckusick     if (td == NIL) {
566*18354Smckusick 	r = 0;
567*18354Smckusick     } else {
568*18354Smckusick 	r = td->tnum;
569*18354Smckusick     }
570*18354Smckusick     return r;
571*18354Smckusick }
572*18354Smckusick 
573*18354Smckusick private int entertype (type)
574*18354Smckusick struct nl *type;
575*18354Smckusick {
576*18354Smckusick     register TypeDesc td;
577*18354Smckusick     register int i;
578*18354Smckusick 
579*18354Smckusick     td = (TypeDesc) malloc(sizeof(struct TypeDesc));
580*18354Smckusick     td->tptr = type;
581*18354Smckusick     td->tnum = tcount;
582*18354Smckusick     td->fwdptrnum = 0;
583*18354Smckusick     ++tcount;
584*18354Smckusick     i = typehash(type);
585*18354Smckusick     td->chain = typetable[i];
586*18354Smckusick     typetable[i] = td;
587*18354Smckusick     return td->tnum;
588*18354Smckusick }
589*18354Smckusick 
590*18354Smckusick /*
591*18354Smckusick  * The in_types table currently contains "boolean", "char", "integer",
592*18354Smckusick  * "real" and "_nil".  (See nl.c for definition.)
593*18354Smckusick  * The lookup call below will give the TYPE class nl entry for these
594*18354Smckusick  * types.  In each case except _nil, the type field of that entry is a RANGE
595*18354Smckusick  * class nl entry for the type.  Sometimes other symbol table entries
596*18354Smckusick  * point to the TYPE entry (e.g., when there is a range over the base type),
597*18354Smckusick  * and other entries point to the RANGE entry (e.g., for a variable of the
598*18354Smckusick  * given type).  We don't really want to distinguish between these uses
599*18354Smckusick  * in dbx, and since it appears that the RANGE entries are not reused if
600*18354Smckusick  * a range happens to coincide, we will give the two the same identifying
601*18354Smckusick  * dbx type number.
602*18354Smckusick  */
603*18354Smckusick 
604*18354Smckusick private inittypes()
605*18354Smckusick {
606*18354Smckusick     int i;
607*18354Smckusick     extern char *in_types[];
608*18354Smckusick     struct nl *p;
609*18354Smckusick 
610*18354Smckusick     for (i = 0; in_types[i] != NIL; i++) {
611*18354Smckusick 	p = lookup(in_types[i]);
612*18354Smckusick 	if (p != NIL) {
613*18354Smckusick 	    entertype(p);
614*18354Smckusick 	    if (p->type != NIL) {
615*18354Smckusick 		--tcount; /* see comment above */
616*18354Smckusick 		entertype(p->type);
617*18354Smckusick 	    }
618*18354Smckusick 	}
619*18354Smckusick     }
620*18354Smckusick }
621*18354Smckusick 
622*18354Smckusick static genarray (t)
623*18354Smckusick struct nl *t;
624*18354Smckusick {
625*18354Smckusick     register struct nl *p;
626*18354Smckusick 
627*18354Smckusick     putprintf("a", 1);
628*18354Smckusick     for (p = t->chain; p != NIL; p = p->chain) {
629*18354Smckusick 	gentype(p);
630*18354Smckusick 	putprintf(";", 1);
631*18354Smckusick     }
632*18354Smckusick     gentype(t->type);
633*18354Smckusick }
634*18354Smckusick 
635*18354Smckusick /*
636*18354Smckusick  * Really we should walk through ptr[NL_FIELDLIST] for the fields,
637*18354Smckusick  * and then do the variant tag and fields separately, but dbx
638*18354Smckusick  * doesn't support this yet.
639*18354Smckusick  * So, since all the fields of all the variants are on the chain,
640*18354Smckusick  * we walk through that.  Except that this gives the fields in the
641*18354Smckusick  * reverse order, so we want to print in reverse order.
642*18354Smckusick  */
643*18354Smckusick 
644*18354Smckusick static genrecord (t)
645*18354Smckusick struct nl *t;
646*18354Smckusick {
647*18354Smckusick     putprintf("s%d", 1, t->value[NL_OFFS]);
648*18354Smckusick     if (t->chain != NIL) {
649*18354Smckusick 	genrecfield(t->chain, 1);
650*18354Smckusick     }
651*18354Smckusick     putprintf(";", 1);
652*18354Smckusick }
653*18354Smckusick 
654*18354Smckusick static genrecfield (t, n)
655*18354Smckusick struct nl *t;
656*18354Smckusick int n;
657*18354Smckusick {
658*18354Smckusick     if (t->chain != NULL) {
659*18354Smckusick 	genrecfield(t->chain, n + 1);
660*18354Smckusick 	if (n % 2 == 0) {
661*18354Smckusick 	    gencontinue();
662*18354Smckusick 	}
663*18354Smckusick     }
664*18354Smckusick     putprintf("%s:", 1, t->symbol);
665*18354Smckusick     gentype(t->type);
666*18354Smckusick     putprintf(",%d,%d;", 1, 8*t->value[NL_OFFS], 8*lwidth(t->type));
667*18354Smckusick }
668*18354Smckusick 
669*18354Smckusick static genvarnt (t)
670*18354Smckusick struct nl *t;
671*18354Smckusick {
672*18354Smckusick     genrecord(t);
673*18354Smckusick }
674*18354Smckusick 
675*18354Smckusick static genptr (t)
676*18354Smckusick struct nl *t;
677*18354Smckusick {
678*18354Smckusick     register TypeDesc td;
679*18354Smckusick 
680*18354Smckusick     putprintf("*", 1);
681*18354Smckusick     if (t->type != NIL) {
682*18354Smckusick 	gentype(t->type);
683*18354Smckusick     } else {
684*18354Smckusick 	/*
685*18354Smckusick 	 * unresolved forward pointer: use tcount to represent what is
686*18354Smckusick          * begin pointed to, to be defined later
687*18354Smckusick 	 */
688*18354Smckusick 	td = tdlookup(t);
689*18354Smckusick 	if (td == NIL) {
690*18354Smckusick 	    panic("nil ptr in stab.genptr");
691*18354Smckusick 	}
692*18354Smckusick 	td->fwdptrnum = tcount;
693*18354Smckusick 	putprintf("%d", 1, tcount);
694*18354Smckusick 	++tcount;
695*18354Smckusick     }
696*18354Smckusick }
697*18354Smckusick 
698*18354Smckusick /*
699*18354Smckusick  * The type t is a pointer which has just had its type field filled.
700*18354Smckusick  * We need to generate a type stab saying that the number saved
701*18354Smckusick  * in t's fwdptrnum is the same as the t->type's number
702*18354Smckusick  */
703*18354Smckusick 
704*18354Smckusick fixfwdtype (t)
705*18354Smckusick struct nl *t;
706*18354Smckusick {
707*18354Smckusick     register TypeDesc td;
708*18354Smckusick 
709*18354Smckusick     if (opt('g') && oldway == 0) {
710*18354Smckusick 	td = tdlookup(t);
711*18354Smckusick 	if (td != NIL) {
712*18354Smckusick 	    putprintf("\t.stabs\t\":t%d=", 1, td->fwdptrnum);
713*18354Smckusick 	    gentype(t->type);
714*18354Smckusick 	    putprintf("\",0x%x,0,0,0", 0, N_LSYM);
715*18354Smckusick 	}
716*18354Smckusick     }
717*18354Smckusick }
718*18354Smckusick 
719*18354Smckusick static genenum (t)
720*18354Smckusick struct nl *t;
721*18354Smckusick {
722*18354Smckusick     register struct nl *e;
723*18354Smckusick     register int i;
724*18354Smckusick 
725*18354Smckusick     putprintf("e", 1);
726*18354Smckusick     i = 1;
727*18354Smckusick     e = t->chain;
728*18354Smckusick     while (e != NULL) {
729*18354Smckusick 	if (i > 2) {
730*18354Smckusick 	    gencontinue();
731*18354Smckusick 	    i = 0;
732*18354Smckusick 	}
733*18354Smckusick 	putprintf("%s:%d,", 1, e->symbol, e->range[0]);
734*18354Smckusick 	e = e->chain;
735*18354Smckusick 	++i;
736*18354Smckusick     }
737*18354Smckusick     putprintf(";", 1);
738*18354Smckusick }
739*18354Smckusick 
740*18354Smckusick static genset (t)
741*18354Smckusick struct nl *t;
742*18354Smckusick {
743*18354Smckusick     putprintf("S", 1);
744*18354Smckusick     gentype(t->type);
745*18354Smckusick }
746*18354Smckusick 
747*18354Smckusick static genrange (t)
748*18354Smckusick struct nl *t;
749*18354Smckusick {
750*18354Smckusick     putprintf("r", 1);
751*18354Smckusick     gentype(t->type);
752*18354Smckusick     putprintf(";%d;%d", 1, t->range[0], t->range[1]);
753*18354Smckusick }
754*18354Smckusick 
755*18354Smckusick static genfparam (t)
756*18354Smckusick struct nl *t;
757*18354Smckusick {
758*18354Smckusick     struct nl *p;
759*18354Smckusick     int count;
760*18354Smckusick 
761*18354Smckusick     if (t->type != NULL) {
762*18354Smckusick 	putprintf("f", 1);
763*18354Smckusick 	gentype(t->type);
764*18354Smckusick 	putprintf(",", 1);
765*18354Smckusick     } else {
766*18354Smckusick 	putprintf("p", 1);
767*18354Smckusick     }
768*18354Smckusick     count = 0;
769*18354Smckusick     for (p = t->ptr[NL_FCHAIN]; p != NULL; p = p->chain) {
770*18354Smckusick 	++count;
771*18354Smckusick     }
772*18354Smckusick     putprintf("%d;", 1, count);
773*18354Smckusick     for (p = t->ptr[NL_FCHAIN]; p != NULL; p = p->chain) {
774*18354Smckusick 	gentype(p->type);
775*18354Smckusick 	putprintf(",%d;", 1, p->class);
776*18354Smckusick     }
777*18354Smckusick }
778*18354Smckusick 
779*18354Smckusick static genfile (t)
780*18354Smckusick struct nl *t;
781*18354Smckusick {
782*18354Smckusick     putprintf("d", 1);
783*18354Smckusick     gentype(t->type);
784*18354Smckusick }
785*18354Smckusick 
786*18354Smckusick static gentype (t)
787*18354Smckusick struct nl *t;
788*18354Smckusick {
789*18354Smckusick     int id;
790*18354Smckusick 
791*18354Smckusick     if (tcount == 1) {
792*18354Smckusick 	inittypes();
793*18354Smckusick     }
794*18354Smckusick     id = typelookup(t);
795*18354Smckusick     if (id != 0) {
796*18354Smckusick 	putprintf("%d", 1, id);
797*18354Smckusick     } else if (t->class == SCAL && t->chain == NULL) {
798*18354Smckusick 	id = typelookup(t->type);
799*18354Smckusick 	if (id != 0) {
800*18354Smckusick 	    putprintf("%d", 1, id);
801*18354Smckusick 	} else {
802*18354Smckusick 	    genenum(t->type);
803*18354Smckusick 	}
804*18354Smckusick     } else {
805*18354Smckusick 	id = entertype(t);
806*18354Smckusick 	putprintf("%d=", 1, id);
807*18354Smckusick 	switch (t->class) {
808*18354Smckusick 	    case TYPE:
809*18354Smckusick 		gentype(t->type);
810*18354Smckusick 		break;
811*18354Smckusick 
812*18354Smckusick 	    case ARRAY:
813*18354Smckusick 		genarray(t);
814*18354Smckusick 		break;
815*18354Smckusick 
816*18354Smckusick 	    case RECORD:
817*18354Smckusick 		genrecord(t);
818*18354Smckusick 		break;
819*18354Smckusick 
820*18354Smckusick 	    case VARNT:
821*18354Smckusick 		genvarnt(t);
822*18354Smckusick 		break;
823*18354Smckusick 
824*18354Smckusick 	    case REF:
825*18354Smckusick 		gentype(t->type);
826*18354Smckusick 		break;
827*18354Smckusick 
828*18354Smckusick 	    case PTR:
829*18354Smckusick 		genptr(t);
830*18354Smckusick 		break;
831*18354Smckusick 
832*18354Smckusick 	    case SET:
833*18354Smckusick 		genset(t);
834*18354Smckusick 		break;
835*18354Smckusick 
836*18354Smckusick 	    case RANGE:
837*18354Smckusick 		genrange(t);
838*18354Smckusick 		break;
839*18354Smckusick 
840*18354Smckusick 	    case SCAL:
841*18354Smckusick 		genenum(t);
842*18354Smckusick 		break;
843*18354Smckusick 
844*18354Smckusick 	    case FPROC:
845*18354Smckusick 	    case FFUNC:
846*18354Smckusick 		genfparam(t);
847*18354Smckusick 		break;
848*18354Smckusick 
849*18354Smckusick 	    case FILET:
850*18354Smckusick 	    case PTRFILE:
851*18354Smckusick 		genfile(t);
852*18354Smckusick 		break;
853*18354Smckusick 
854*18354Smckusick 	    default:
855*18354Smckusick 		/* This shouldn't happen */
856*18354Smckusick 		/* Rather than bomb outright, let debugging go on */
857*18354Smckusick 		warning();
858*18354Smckusick 		error("Bad type class found in stab");
859*18354Smckusick 		putprintf("1", 1, t->class);
860*18354Smckusick 		break;
861*18354Smckusick 	}
862*18354Smckusick     }
863*18354Smckusick }
864*18354Smckusick 
865*18354Smckusick /*
866*18354Smckusick  * Continue stab information in a namelist new entry.  This is necessary
867*18354Smckusick  * to avoid overflowing putprintf's buffer.
868*18354Smckusick  */
869*18354Smckusick 
870*18354Smckusick static gencontinue ()
871*18354Smckusick {
872*18354Smckusick     putprintf("?\",0x%x,0,0,0", 0, N_LSYM);
873*18354Smckusick     putprintf("\t.stabs\t\"", 1);
874*18354Smckusick }
875*18354Smckusick 
876772Speter #endif PC
877