xref: /csrg-svn/usr.bin/pascal/src/fend.c (revision 3192)
1*3192Smckusick /* Copyright (c) 1979 Regents of the University of California */
2*3192Smckusick 
3*3192Smckusick static char sccsid[] = "@(#)fend.c 1.1 03/11/81";
4*3192Smckusick 
5*3192Smckusick #include "whoami.h"
6*3192Smckusick #include "0.h"
7*3192Smckusick #include "tree.h"
8*3192Smckusick #include "opcode.h"
9*3192Smckusick #include "objfmt.h"
10*3192Smckusick #include "align.h"
11*3192Smckusick 
12*3192Smckusick /*
13*3192Smckusick  * this array keeps the pxp counters associated with
14*3192Smckusick  * functions and procedures, so that they can be output
15*3192Smckusick  * when their bodies are encountered
16*3192Smckusick  */
17*3192Smckusick int	bodycnts[ DSPLYSZ ];
18*3192Smckusick 
19*3192Smckusick #ifdef PC
20*3192Smckusick #   include "pc.h"
21*3192Smckusick #   include "pcops.h"
22*3192Smckusick #endif PC
23*3192Smckusick 
24*3192Smckusick #ifdef OBJ
25*3192Smckusick int	cntpatch;
26*3192Smckusick int	nfppatch;
27*3192Smckusick #endif OBJ
28*3192Smckusick 
29*3192Smckusick struct	nl *Fp;
30*3192Smckusick int	pnumcnt;
31*3192Smckusick /*
32*3192Smckusick  * Funcend is called to
33*3192Smckusick  * finish a block by generating
34*3192Smckusick  * the code for the statements.
35*3192Smckusick  * It then looks for unresolved declarations
36*3192Smckusick  * of labels, procedures and functions,
37*3192Smckusick  * and cleans up the name list.
38*3192Smckusick  * For the program, it checks the
39*3192Smckusick  * semantics of the program
40*3192Smckusick  * statement (yuchh).
41*3192Smckusick  */
42*3192Smckusick funcend(fp, bundle, endline)
43*3192Smckusick 	struct nl *fp;
44*3192Smckusick 	int *bundle;
45*3192Smckusick 	int endline;
46*3192Smckusick {
47*3192Smckusick 	register struct nl *p;
48*3192Smckusick 	register int i, b;
49*3192Smckusick 	int var, inp, out, *blk;
50*3192Smckusick 	bool chkref;
51*3192Smckusick 	struct nl *iop;
52*3192Smckusick 	char *cp;
53*3192Smckusick 	extern int cntstat;
54*3192Smckusick #	ifdef PC
55*3192Smckusick 	    int	toplabel = getlab();
56*3192Smckusick 	    int	botlabel = getlab();
57*3192Smckusick #	endif PC
58*3192Smckusick 
59*3192Smckusick 	cntstat = 0;
60*3192Smckusick /*
61*3192Smckusick  *	yyoutline();
62*3192Smckusick  */
63*3192Smckusick 	if (program != NIL)
64*3192Smckusick 		line = program->value[3];
65*3192Smckusick 	blk = bundle[2];
66*3192Smckusick 	if (fp == NIL) {
67*3192Smckusick 		cbn--;
68*3192Smckusick #		ifdef PTREE
69*3192Smckusick 		    nesting--;
70*3192Smckusick #		endif PTREE
71*3192Smckusick 		return;
72*3192Smckusick 	}
73*3192Smckusick #ifdef OBJ
74*3192Smckusick 	/*
75*3192Smckusick 	 * Patch the branch to the
76*3192Smckusick 	 * entry point of the function
77*3192Smckusick 	 */
78*3192Smckusick 	patch4(fp->entloc);
79*3192Smckusick 	/*
80*3192Smckusick 	 * Put out the block entrance code and the block name.
81*3192Smckusick 	 * HDRSZE is the number of bytes of info in the static
82*3192Smckusick 	 * BEG data area exclusive of the proc name. It is
83*3192Smckusick 	 * currently defined as:
84*3192Smckusick 	/*	struct hdr {
85*3192Smckusick 	/*		long framesze;	/* number of bytes of local vars */
86*3192Smckusick 	/*		long nargs;	/* number of bytes of arguments */
87*3192Smckusick 	/*		bool tests;	/* TRUE => perform runtime tests */
88*3192Smckusick 	/*		short offset;	/* offset of procedure in source file */
89*3192Smckusick 	/*		char name[1];	/* name of active procedure */
90*3192Smckusick 	/*	};
91*3192Smckusick 	 */
92*3192Smckusick #	define HDRSZE (2 * sizeof(long) + sizeof(short) + sizeof(bool))
93*3192Smckusick 	var = put(2, ((lenstr(fp->symbol,0) + HDRSZE) << 8)
94*3192Smckusick 		| (cbn == 1 && opt('p') == 0 ? O_NODUMP: O_BEG), (long)0);
95*3192Smckusick 	    /*
96*3192Smckusick 	     *  output the number of bytes of arguments
97*3192Smckusick 	     *  this is only checked on formal calls.
98*3192Smckusick 	     */
99*3192Smckusick 	put(2, O_CASE4, cbn == 1 ? (long)0 : (long)(fp->value[NL_OFFS]-DPOFF2));
100*3192Smckusick 	    /*
101*3192Smckusick 	     *	Output the runtime test mode for the routine
102*3192Smckusick 	     */
103*3192Smckusick 	put(2, sizeof(bool) == 2 ? O_CASE2 : O_CASE4, opt('t') ? TRUE : FALSE);
104*3192Smckusick 	    /*
105*3192Smckusick 	     *	Output line number and routine name
106*3192Smckusick 	     */
107*3192Smckusick 	put(2, O_CASE2, bundle[1]);
108*3192Smckusick 	putstr(fp->symbol, 0);
109*3192Smckusick #endif OBJ
110*3192Smckusick #ifdef PC
111*3192Smckusick 	/*
112*3192Smckusick 	 * put out the procedure entry code
113*3192Smckusick 	 */
114*3192Smckusick 	if ( fp -> class == PROG ) {
115*3192Smckusick 	    putprintf( "	.text" , 0 );
116*3192Smckusick 	    putprintf( "	.align	1" , 0 );
117*3192Smckusick 	    putprintf( "	.globl	_main" , 0 );
118*3192Smckusick 	    putprintf( "_main:" , 0 );
119*3192Smckusick 	    putprintf( "	.word	0" , 0 );
120*3192Smckusick 	    putprintf( "	calls	$0,_PCSTART" , 0 );
121*3192Smckusick 	    putprintf( "	movl	4(ap),__argc" , 0 );
122*3192Smckusick 	    putprintf( "	movl	8(ap),__argv" , 0 );
123*3192Smckusick 	    putprintf( "	calls	$0,_program" , 0 );
124*3192Smckusick 	    putprintf( "	calls	$0,_PCEXIT" , 0 );
125*3192Smckusick 	    ftnno = fp -> entloc;
126*3192Smckusick 	    putprintf( "	.text" , 0 );
127*3192Smckusick 	    putprintf( "	.align	1" , 0 );
128*3192Smckusick 	    putprintf( "	.globl	_program" , 0 );
129*3192Smckusick 	    putprintf( "_program:" , 0 );
130*3192Smckusick 	    stabfunc( "program" , fp -> class , bundle[1] , 0 );
131*3192Smckusick 	} else {
132*3192Smckusick 	    ftnno = fp -> entloc;
133*3192Smckusick 	    putprintf( "	.text" , 0 );
134*3192Smckusick 	    putprintf( "	.align	1" , 0 );
135*3192Smckusick 	    putprintf( "	.globl	" , 1 );
136*3192Smckusick 	    for ( i = 1 ; i < cbn ; i++ ) {
137*3192Smckusick 		putprintf( EXTFORMAT , 1 , enclosing[ i ] );
138*3192Smckusick 	    }
139*3192Smckusick 	    putprintf( "" , 0 );
140*3192Smckusick 	    for ( i = 1 ; i < cbn ; i++ ) {
141*3192Smckusick 		putprintf( EXTFORMAT , 1 , enclosing[ i ] );
142*3192Smckusick 	    }
143*3192Smckusick 	    putprintf( ":" , 0 );
144*3192Smckusick 	    stabfunc( fp -> symbol , fp -> class , bundle[1] , cbn - 1 );
145*3192Smckusick 	    for ( p = fp -> chain ; p != NIL ; p = p -> chain ) {
146*3192Smckusick 		stabparam( p -> symbol , p2type( p -> type )
147*3192Smckusick 			    , p -> value[ NL_OFFS ] , lwidth( p -> type ) );
148*3192Smckusick 	    }
149*3192Smckusick 	    if ( fp -> class == FUNC ) {
150*3192Smckusick 		    /*
151*3192Smckusick 		     *	stab the function variable
152*3192Smckusick 		     */
153*3192Smckusick 		p = fp -> ptr[ NL_FVAR ];
154*3192Smckusick 		stablvar( p -> symbol , p2type( p -> type ) , cbn
155*3192Smckusick 			, p -> value[ NL_OFFS ] , lwidth( p -> type ) );
156*3192Smckusick 	    }
157*3192Smckusick 		/*
158*3192Smckusick 		 *	stab local variables
159*3192Smckusick 		 *	rummage down hash chain links.
160*3192Smckusick 		 */
161*3192Smckusick 	    for ( i = 0 ; i <= 077 ; i++ ) {
162*3192Smckusick 		for ( p = disptab[ i ] ; p != NIL ; p = p->nl_next) {
163*3192Smckusick 		    if ( ( p -> nl_block & 037 ) != cbn ) {
164*3192Smckusick 			break;
165*3192Smckusick 		    }
166*3192Smckusick 		    /*
167*3192Smckusick 		     *	stab local variables
168*3192Smckusick 		     *	that's named variables, but not params
169*3192Smckusick 		     */
170*3192Smckusick 		    if (   ( p -> symbol != NIL )
171*3192Smckusick 			&& ( p -> class == VAR )
172*3192Smckusick 			&& ( p -> value[ NL_OFFS ] < 0 ) ) {
173*3192Smckusick 			stablvar( p -> symbol , p2type( p -> type ) , cbn
174*3192Smckusick 			    , p -> value[ NL_OFFS ] , lwidth( p -> type ) );
175*3192Smckusick 		    }
176*3192Smckusick 		}
177*3192Smckusick 	    }
178*3192Smckusick 	}
179*3192Smckusick 	stablbrac( cbn );
180*3192Smckusick 	    /*
181*3192Smckusick 	     *	register save mask
182*3192Smckusick 	     */
183*3192Smckusick 	if ( opt( 't' ) ) {
184*3192Smckusick 	    putprintf( "	.word	0x%x" , 0 , RUNCHECK | RSAVEMASK );
185*3192Smckusick 	} else {
186*3192Smckusick 	    putprintf( "	.word	0x%x" , 0 , RSAVEMASK );
187*3192Smckusick 	}
188*3192Smckusick 	putjbr( botlabel );
189*3192Smckusick 	putlab( toplabel );
190*3192Smckusick 	if ( profflag ) {
191*3192Smckusick 		/*
192*3192Smckusick 		 *	call mcount for profiling
193*3192Smckusick 		 */
194*3192Smckusick 	    putprintf( "	moval	1f,r0" , 0 );
195*3192Smckusick 	    putprintf( "	jsb	mcount" , 0 );
196*3192Smckusick 	    putprintf( "	.data" , 0 );
197*3192Smckusick 	    putprintf( "	.align	2" , 0 );
198*3192Smckusick 	    putprintf( "1:" , 0 );
199*3192Smckusick 	    putprintf( "	.long	0" , 0 );
200*3192Smckusick 	    putprintf( "	.text" , 0 );
201*3192Smckusick 	}
202*3192Smckusick 	    /*
203*3192Smckusick 	     *	set up unwind exception vector.
204*3192Smckusick 	     */
205*3192Smckusick 	putprintf( "	moval	%s,%d(%s)" , 0
206*3192Smckusick 		, UNWINDNAME , UNWINDOFFSET , P2FPNAME );
207*3192Smckusick 	    /*
208*3192Smckusick 	     *	save address of display entry, for unwind.
209*3192Smckusick 	     */
210*3192Smckusick 	putprintf( "	moval	%s+%d,%d(%s)" , 0
211*3192Smckusick 		, DISPLAYNAME , cbn * sizeof(struct dispsave)
212*3192Smckusick 		, DPTROFFSET , P2FPNAME );
213*3192Smckusick 	    /*
214*3192Smckusick 	     *	save old display
215*3192Smckusick 	     */
216*3192Smckusick 	putprintf( "	movq	%s+%d,%d(%s)" , 0
217*3192Smckusick 		, DISPLAYNAME , cbn * sizeof(struct dispsave)
218*3192Smckusick 		, DSAVEOFFSET , P2FPNAME );
219*3192Smckusick 	    /*
220*3192Smckusick 	     *	set up new display by saving AP and FP in appropriate
221*3192Smckusick 	     *	slot in display structure.
222*3192Smckusick 	     */
223*3192Smckusick 	putprintf( "	movq	%s,%s+%d" , 0
224*3192Smckusick 		, P2APNAME , DISPLAYNAME , cbn * sizeof(struct dispsave) );
225*3192Smckusick 	    /*
226*3192Smckusick 	     *	ask second pass to allocate known locals
227*3192Smckusick 	     */
228*3192Smckusick 	putlbracket( ftnno , -sizes[ cbn ].om_max );
229*3192Smckusick 	    /*
230*3192Smckusick 	     *	and zero them if checking is on
231*3192Smckusick 	     *	by calling blkclr( bytes of locals , starting local address );
232*3192Smckusick 	     */
233*3192Smckusick 	if ( opt( 't' ) ) {
234*3192Smckusick 	    if ( ( -sizes[ cbn ].om_max ) > DPOFF1 ) {
235*3192Smckusick 		putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
236*3192Smckusick 			, "_blkclr" );
237*3192Smckusick 		putleaf( P2ICON ,  ( -sizes[ cbn ].om_max ) - DPOFF1
238*3192Smckusick 			, 0 , P2INT , 0 );
239*3192Smckusick 		putLV( 0 , cbn , sizes[ cbn ].om_max , P2CHAR );
240*3192Smckusick 		putop( P2LISTOP , P2INT );
241*3192Smckusick 		putop( P2CALL , P2INT );
242*3192Smckusick 		putdot( filename , line );
243*3192Smckusick 	    }
244*3192Smckusick 		/*
245*3192Smckusick 		 *  check number of longs of arguments
246*3192Smckusick 		 *  this can only be wrong for formal calls.
247*3192Smckusick 		 */
248*3192Smckusick 	    if ( fp -> class != PROG ) {
249*3192Smckusick 		    putleaf( P2ICON , 0 , 0 , ADDTYPE( P2PTR , P2FTN | P2INT ) ,
250*3192Smckusick 			    "_NARGCHK" );
251*3192Smckusick 		    putleaf( P2ICON ,
252*3192Smckusick 			(fp->value[NL_OFFS] - DPOFF2) / sizeof(long) ,
253*3192Smckusick 			0 , P2INT , 0 );
254*3192Smckusick 		    putop( P2CALL , P2INT );
255*3192Smckusick 		    putdot( filename , line );
256*3192Smckusick 	    }
257*3192Smckusick 	}
258*3192Smckusick #endif PC
259*3192Smckusick 	if ( monflg ) {
260*3192Smckusick 		if ( fp -> value[ NL_CNTR ] != 0 ) {
261*3192Smckusick 			inccnt( fp -> value [ NL_CNTR ] );
262*3192Smckusick 		}
263*3192Smckusick 		inccnt( bodycnts[ fp -> nl_block & 037 ] );
264*3192Smckusick 	}
265*3192Smckusick 	if (fp->class == PROG) {
266*3192Smckusick 		/*
267*3192Smckusick 		 * The glorious buffers option.
268*3192Smckusick 		 *          0 = don't buffer output
269*3192Smckusick 		 *          1 = line buffer output
270*3192Smckusick 		 *          2 = 512 byte buffer output
271*3192Smckusick 		 */
272*3192Smckusick #		ifdef OBJ
273*3192Smckusick 		    if (opt('b') != 1)
274*3192Smckusick 			    put(1, O_BUFF | opt('b') << 8);
275*3192Smckusick #		endif OBJ
276*3192Smckusick #		ifdef PC
277*3192Smckusick 		    if ( opt( 'b' ) != 1 ) {
278*3192Smckusick 			putleaf( P2ICON , 0 , 0
279*3192Smckusick 				, ADDTYPE( P2FTN | P2INT , P2PTR ) , "_BUFF" );
280*3192Smckusick 			putleaf( P2ICON , opt( 'b' ) , 0 , P2INT , 0 );
281*3192Smckusick 			putop( P2CALL , P2INT );
282*3192Smckusick 			putdot( filename , line );
283*3192Smckusick 		    }
284*3192Smckusick #		endif PC
285*3192Smckusick 		out = 0;
286*3192Smckusick 		for (p = fp->chain; p != NIL; p = p->chain) {
287*3192Smckusick 			if (strcmp(p->symbol, "input") == 0) {
288*3192Smckusick 				inp++;
289*3192Smckusick 				continue;
290*3192Smckusick 			}
291*3192Smckusick 			if (strcmp(p->symbol, "output") == 0) {
292*3192Smckusick 				out++;
293*3192Smckusick 				continue;
294*3192Smckusick 			}
295*3192Smckusick 			iop = lookup1(p->symbol);
296*3192Smckusick 			if (iop == NIL || bn != cbn) {
297*3192Smckusick 				error("File %s listed in program statement but not declared", p->symbol);
298*3192Smckusick 				continue;
299*3192Smckusick 			}
300*3192Smckusick 			if (iop->class != VAR) {
301*3192Smckusick 				error("File %s listed in program statement but declared as a %s", p->symbol, classes[iop->class]);
302*3192Smckusick 				continue;
303*3192Smckusick 			}
304*3192Smckusick 			if (iop->type == NIL)
305*3192Smckusick 				continue;
306*3192Smckusick 			if (iop->type->class != FILET) {
307*3192Smckusick 				error("File %s listed in program statement but defined as %s",
308*3192Smckusick 					p->symbol, nameof(iop->type));
309*3192Smckusick 				continue;
310*3192Smckusick 			}
311*3192Smckusick #			ifdef OBJ
312*3192Smckusick 			    put(2, O_CON24, text(iop->type) ? 0 : width(iop->type->type));
313*3192Smckusick 			    i = lenstr(p->symbol,0);
314*3192Smckusick 			    put(2, O_CON24, i);
315*3192Smckusick 			    put(2, O_LVCON, i);
316*3192Smckusick 			    putstr(p->symbol, 0);
317*3192Smckusick 			    put(2, O_LV | bn<<8+INDX, (int)iop->value[NL_OFFS]);
318*3192Smckusick 			    put(1, O_DEFNAME);
319*3192Smckusick #			endif OBJ
320*3192Smckusick #			ifdef PC
321*3192Smckusick 			    putleaf( P2ICON , 0 , 0
322*3192Smckusick 				    , ADDTYPE( P2FTN | P2INT , P2PTR )
323*3192Smckusick 				    , "_DEFNAME" );
324*3192Smckusick 			    putLV( p -> symbol , bn , iop -> value[NL_OFFS]
325*3192Smckusick 				    , p2type( iop ) );
326*3192Smckusick 			    putCONG( p -> symbol , strlen( p -> symbol )
327*3192Smckusick 				    , LREQ );
328*3192Smckusick 			    putop( P2LISTOP , P2INT );
329*3192Smckusick 			    putleaf( P2ICON , strlen( p -> symbol )
330*3192Smckusick 				    , 0 , P2INT , 0 );
331*3192Smckusick 			    putop( P2LISTOP , P2INT );
332*3192Smckusick 			    putleaf( P2ICON
333*3192Smckusick 				, text(iop->type) ? 0 : width(iop->type->type)
334*3192Smckusick 				, 0 , P2INT , 0 );
335*3192Smckusick 			    putop( P2LISTOP , P2INT );
336*3192Smckusick 			    putop( P2CALL , P2INT );
337*3192Smckusick 			    putdot( filename , line );
338*3192Smckusick #			endif PC
339*3192Smckusick 		}
340*3192Smckusick 		if (out == 0 && fp->chain != NIL) {
341*3192Smckusick 			recovered();
342*3192Smckusick 			error("The file output must appear in the program statement file list");
343*3192Smckusick 		}
344*3192Smckusick 	}
345*3192Smckusick 	/*
346*3192Smckusick 	 * Process the prog/proc/func body
347*3192Smckusick 	 */
348*3192Smckusick 	noreach = 0;
349*3192Smckusick 	line = bundle[1];
350*3192Smckusick 	statlist(blk);
351*3192Smckusick #	ifdef PTREE
352*3192Smckusick 	    {
353*3192Smckusick 		pPointer Body = tCopy( blk );
354*3192Smckusick 
355*3192Smckusick 		pDEF( PorFHeader[ nesting -- ] ).PorFBody = Body;
356*3192Smckusick 	    }
357*3192Smckusick #	endif PTREE
358*3192Smckusick #	ifdef OBJ
359*3192Smckusick 	    if (cbn== 1 && monflg != 0) {
360*3192Smckusick 		    patchfil(cntpatch - 2, (long)cnts, 2);
361*3192Smckusick 		    patchfil(nfppatch - 2, (long)pfcnt, 2);
362*3192Smckusick 	    }
363*3192Smckusick #	endif OBJ
364*3192Smckusick #	ifdef PC
365*3192Smckusick 	    if ( fp -> class == PROG && monflg ) {
366*3192Smckusick 		putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
367*3192Smckusick 			, "_PMFLUSH" );
368*3192Smckusick 		putleaf( P2ICON , cnts , 0 , P2INT , 0 );
369*3192Smckusick 		putleaf( P2ICON , pfcnt , 0 , P2INT , 0 );
370*3192Smckusick 		putop( P2LISTOP , P2INT );
371*3192Smckusick 		putLV( PCPCOUNT , 0 , 0 , P2INT );
372*3192Smckusick 		putop( P2LISTOP , P2INT );
373*3192Smckusick 		putop( P2CALL , P2INT );
374*3192Smckusick 		putdot( filename , line );
375*3192Smckusick 	    }
376*3192Smckusick #	endif PC
377*3192Smckusick 	if (fp->class == PROG && inp == 0 && (input->nl_flags & (NUSED|NMOD)) != 0) {
378*3192Smckusick 		recovered();
379*3192Smckusick 		error("Input is used but not defined in the program statement");
380*3192Smckusick 	}
381*3192Smckusick 	/*
382*3192Smckusick 	 * Clean up the symbol table displays and check for unresolves
383*3192Smckusick 	 */
384*3192Smckusick 	line = endline;
385*3192Smckusick 	b = cbn;
386*3192Smckusick 	Fp = fp;
387*3192Smckusick 	chkref = syneflg == errcnt[cbn] && opt('w') == 0;
388*3192Smckusick 	for (i = 0; i <= 077; i++) {
389*3192Smckusick 		for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) {
390*3192Smckusick 			/*
391*3192Smckusick 			 * Check for variables defined
392*3192Smckusick 			 * but not referenced
393*3192Smckusick 			 */
394*3192Smckusick 			if (chkref && p->symbol != NIL)
395*3192Smckusick 			switch (p->class) {
396*3192Smckusick 				case FIELD:
397*3192Smckusick 					/*
398*3192Smckusick 					 * If the corresponding record is
399*3192Smckusick 					 * unused, we shouldn't complain about
400*3192Smckusick 					 * the fields.
401*3192Smckusick 					 */
402*3192Smckusick 				default:
403*3192Smckusick 					if ((p->nl_flags & (NUSED|NMOD)) == 0) {
404*3192Smckusick 						warning();
405*3192Smckusick 						nerror("%s %s is neither used nor set", classes[p->class], p->symbol);
406*3192Smckusick 						break;
407*3192Smckusick 					}
408*3192Smckusick 					/*
409*3192Smckusick 					 * If a var parameter is either
410*3192Smckusick 					 * modified or used that is enough.
411*3192Smckusick 					 */
412*3192Smckusick 					if (p->class == REF)
413*3192Smckusick 						continue;
414*3192Smckusick #					ifdef OBJ
415*3192Smckusick 					    if ((p->nl_flags & NUSED) == 0) {
416*3192Smckusick 						warning();
417*3192Smckusick 						nerror("%s %s is never used", classes[p->class], p->symbol);
418*3192Smckusick 						break;
419*3192Smckusick 					    }
420*3192Smckusick #					endif OBJ
421*3192Smckusick #					ifdef PC
422*3192Smckusick 					    if (((p->nl_flags & NUSED) == 0) && ((p->ext_flags & NEXTERN) == 0)) {
423*3192Smckusick 						warning();
424*3192Smckusick 						nerror("%s %s is never used", classes[p->class], p->symbol);
425*3192Smckusick 						break;
426*3192Smckusick 					    }
427*3192Smckusick #					endif PC
428*3192Smckusick 					if ((p->nl_flags & NMOD) == 0) {
429*3192Smckusick 						warning();
430*3192Smckusick 						nerror("%s %s is used but never set", classes[p->class], p->symbol);
431*3192Smckusick 						break;
432*3192Smckusick 					}
433*3192Smckusick 				case LABEL:
434*3192Smckusick 				case FVAR:
435*3192Smckusick 				case BADUSE:
436*3192Smckusick 					break;
437*3192Smckusick 			}
438*3192Smckusick 			switch (p->class) {
439*3192Smckusick 				case BADUSE:
440*3192Smckusick 					cp = "s";
441*3192Smckusick 					if (p->chain->ud_next == NIL)
442*3192Smckusick 						cp++;
443*3192Smckusick 					eholdnl();
444*3192Smckusick 					if (p->value[NL_KINDS] & ISUNDEF)
445*3192Smckusick 						nerror("%s undefined on line%s", p->symbol, cp);
446*3192Smckusick 					else
447*3192Smckusick 						nerror("%s improperly used on line%s", p->symbol, cp);
448*3192Smckusick 					pnumcnt = 10;
449*3192Smckusick 					pnums(p->chain);
450*3192Smckusick 					pchr('\n');
451*3192Smckusick 					break;
452*3192Smckusick 
453*3192Smckusick 				case FUNC:
454*3192Smckusick 				case PROC:
455*3192Smckusick #					ifdef OBJ
456*3192Smckusick 					    if ((p->nl_flags & NFORWD))
457*3192Smckusick 						nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol);
458*3192Smckusick #					endif OBJ
459*3192Smckusick #					ifdef PC
460*3192Smckusick 					    if ((p->nl_flags & NFORWD) && ((p->ext_flags & NEXTERN) == 0))
461*3192Smckusick 						nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol);
462*3192Smckusick #					endif PC
463*3192Smckusick 					break;
464*3192Smckusick 
465*3192Smckusick 				case LABEL:
466*3192Smckusick 					if (p->nl_flags & NFORWD)
467*3192Smckusick 						nerror("label %s was declared but not defined", p->symbol);
468*3192Smckusick 					break;
469*3192Smckusick 				case FVAR:
470*3192Smckusick 					if ((p->nl_flags & NMOD) == 0)
471*3192Smckusick 						nerror("No assignment to the function variable");
472*3192Smckusick 					break;
473*3192Smckusick 			}
474*3192Smckusick 		}
475*3192Smckusick 		/*
476*3192Smckusick 		 * Pop this symbol
477*3192Smckusick 		 * table slot
478*3192Smckusick 		 */
479*3192Smckusick 		disptab[i] = p;
480*3192Smckusick 	}
481*3192Smckusick 
482*3192Smckusick #	ifdef OBJ
483*3192Smckusick 	    put(1, O_END);
484*3192Smckusick #	endif OBJ
485*3192Smckusick #	ifdef PC
486*3192Smckusick 		/*
487*3192Smckusick 		 *	if there were file variables declared at this level
488*3192Smckusick 		 *	call pclose( &__disply[ cbn ] ) to clean them up.
489*3192Smckusick 		 */
490*3192Smckusick 	    if ( dfiles[ cbn ] ) {
491*3192Smckusick 		putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
492*3192Smckusick 			, "_PCLOSE" );
493*3192Smckusick 		putRV( DISPLAYNAME , 0 , cbn * sizeof( struct dispsave )
494*3192Smckusick 			, P2PTR | P2CHAR );
495*3192Smckusick 		putop( P2CALL , P2INT );
496*3192Smckusick 		putdot( filename , line );
497*3192Smckusick 	    }
498*3192Smckusick 		/*
499*3192Smckusick 		 *	if this is a function,
500*3192Smckusick 		 *	the function variable is the return value.
501*3192Smckusick 		 *	if it's a scalar valued function, return scalar,
502*3192Smckusick 		 *	else, return a pointer to the structure value.
503*3192Smckusick 		 */
504*3192Smckusick 	    if ( fp -> class == FUNC ) {
505*3192Smckusick 		struct nl	*fvar = fp -> ptr[ NL_FVAR ];
506*3192Smckusick 		long		fvartype = p2type( fvar -> type );
507*3192Smckusick 		long		label;
508*3192Smckusick 		char		labelname[ BUFSIZ ];
509*3192Smckusick 
510*3192Smckusick 		switch ( classify( fvar -> type ) ) {
511*3192Smckusick 		    case TBOOL:
512*3192Smckusick 		    case TCHAR:
513*3192Smckusick 		    case TINT:
514*3192Smckusick 		    case TSCAL:
515*3192Smckusick 		    case TDOUBLE:
516*3192Smckusick 		    case TPTR:
517*3192Smckusick 			putRV( fvar -> symbol , ( fvar -> nl_block ) & 037
518*3192Smckusick 				, fvar -> value[ NL_OFFS ] , fvartype );
519*3192Smckusick 			break;
520*3192Smckusick 		    default:
521*3192Smckusick 			label = getlab();
522*3192Smckusick 			sprintf( labelname , PREFIXFORMAT ,
523*3192Smckusick 				LABELPREFIX , label );
524*3192Smckusick 			putprintf( "	.data" , 0 );
525*3192Smckusick 			putprintf( "	.lcomm	%s,%d" , 0 ,
526*3192Smckusick 				    labelname , lwidth( fvar -> type ) );
527*3192Smckusick 			putprintf( "	.text" , 0 );
528*3192Smckusick 			putleaf( P2NAME , 0 , 0 , fvartype , labelname );
529*3192Smckusick 			putLV( fvar -> symbol , ( fvar -> nl_block ) & 037
530*3192Smckusick 				, fvar -> value[ NL_OFFS ] , fvartype );
531*3192Smckusick 			putstrop( P2STASG , fvartype , lwidth( fvar -> type ) ,
532*3192Smckusick 				align( fvar -> type ) );
533*3192Smckusick 			putdot( filename , line );
534*3192Smckusick 			putleaf( P2ICON , 0 , 0 , fvartype , labelname );
535*3192Smckusick 			break;
536*3192Smckusick 		}
537*3192Smckusick 		putop( P2FORCE , fvartype );
538*3192Smckusick 		putdot( filename , line );
539*3192Smckusick 	    }
540*3192Smckusick 		/*
541*3192Smckusick 		 *	restore old display entry from save area
542*3192Smckusick 		 */
543*3192Smckusick 
544*3192Smckusick 	    putprintf( "	movq	%d(%s),%s+%d" , 0
545*3192Smckusick 		, DSAVEOFFSET , P2FPNAME
546*3192Smckusick 		, DISPLAYNAME , cbn * sizeof(struct dispsave) );
547*3192Smckusick 	    stabrbrac( cbn );
548*3192Smckusick 	    putprintf( "	ret" , 0 );
549*3192Smckusick 		/*
550*3192Smckusick 		 *	let the second pass allocate locals
551*3192Smckusick 		 */
552*3192Smckusick 	    putlab( botlabel );
553*3192Smckusick 	    putprintf( "	subl2	$LF%d,sp" , 0 , ftnno );
554*3192Smckusick 	    putrbracket( ftnno );
555*3192Smckusick 	    putjbr( toplabel );
556*3192Smckusick 		/*
557*3192Smckusick 		 *	declare pcp counters, if any
558*3192Smckusick 		 */
559*3192Smckusick 	    if ( monflg && fp -> class == PROG ) {
560*3192Smckusick 		putprintf( "	.data" , 0 );
561*3192Smckusick 		putprintf( "	.comm	" , 1 );
562*3192Smckusick 		putprintf( PCPCOUNT , 1 );
563*3192Smckusick 		putprintf( ",%d" , 0 , ( cnts + 1 ) * sizeof (long) );
564*3192Smckusick 		putprintf( "	.text" , 0 );
565*3192Smckusick 	    }
566*3192Smckusick #	endif PC
567*3192Smckusick #ifdef DEBUG
568*3192Smckusick 	dumpnl(fp->ptr[2], fp->symbol);
569*3192Smckusick #endif
570*3192Smckusick 	/*
571*3192Smckusick 	 * Restore the
572*3192Smckusick 	 * (virtual) name list
573*3192Smckusick 	 * position
574*3192Smckusick 	 */
575*3192Smckusick 	nlfree(fp->ptr[2]);
576*3192Smckusick 	/*
577*3192Smckusick 	 * Proc/func has been
578*3192Smckusick 	 * resolved
579*3192Smckusick 	 */
580*3192Smckusick 	fp->nl_flags &= ~NFORWD;
581*3192Smckusick 	/*
582*3192Smckusick 	 * Patch the beg
583*3192Smckusick 	 * of the proc/func to
584*3192Smckusick 	 * the proper variable size
585*3192Smckusick 	 */
586*3192Smckusick 	if (Fp == NIL)
587*3192Smckusick 		elineon();
588*3192Smckusick #	ifdef OBJ
589*3192Smckusick 	    patchfil(var, (long)(-sizes[cbn].om_max), 2);
590*3192Smckusick #	endif OBJ
591*3192Smckusick 	cbn--;
592*3192Smckusick 	if (inpflist(fp->symbol)) {
593*3192Smckusick 		opop('l');
594*3192Smckusick 	}
595*3192Smckusick }
596