xref: /original-bsd/usr.bin/pascal/src/fend.c (revision 5b396f44)
1348a2a57Smckusick /* Copyright (c) 1979 Regents of the University of California */
2348a2a57Smckusick 
3*5b396f44Speter static char sccsid[] = "@(#)fend.c 1.4 03/24/81";
4348a2a57Smckusick 
5348a2a57Smckusick #include "whoami.h"
6348a2a57Smckusick #include "0.h"
7348a2a57Smckusick #include "tree.h"
8348a2a57Smckusick #include "opcode.h"
9348a2a57Smckusick #include "objfmt.h"
10348a2a57Smckusick #include "align.h"
11348a2a57Smckusick 
12348a2a57Smckusick /*
13348a2a57Smckusick  * this array keeps the pxp counters associated with
14348a2a57Smckusick  * functions and procedures, so that they can be output
15348a2a57Smckusick  * when their bodies are encountered
16348a2a57Smckusick  */
17348a2a57Smckusick int	bodycnts[ DSPLYSZ ];
18348a2a57Smckusick 
19348a2a57Smckusick #ifdef PC
20348a2a57Smckusick #   include "pc.h"
21348a2a57Smckusick #   include "pcops.h"
22348a2a57Smckusick #endif PC
23348a2a57Smckusick 
24348a2a57Smckusick #ifdef OBJ
25348a2a57Smckusick int	cntpatch;
26348a2a57Smckusick int	nfppatch;
27348a2a57Smckusick #endif OBJ
28348a2a57Smckusick 
29348a2a57Smckusick struct	nl *Fp;
30348a2a57Smckusick int	pnumcnt;
31348a2a57Smckusick /*
32348a2a57Smckusick  * Funcend is called to
33348a2a57Smckusick  * finish a block by generating
34348a2a57Smckusick  * the code for the statements.
35348a2a57Smckusick  * It then looks for unresolved declarations
36348a2a57Smckusick  * of labels, procedures and functions,
37348a2a57Smckusick  * and cleans up the name list.
38348a2a57Smckusick  * For the program, it checks the
39348a2a57Smckusick  * semantics of the program
40348a2a57Smckusick  * statement (yuchh).
41348a2a57Smckusick  */
42348a2a57Smckusick funcend(fp, bundle, endline)
43348a2a57Smckusick 	struct nl *fp;
44348a2a57Smckusick 	int *bundle;
45348a2a57Smckusick 	int endline;
46348a2a57Smckusick {
47348a2a57Smckusick 	register struct nl *p;
48348a2a57Smckusick 	register int i, b;
49348a2a57Smckusick 	int var, inp, out, *blk;
50348a2a57Smckusick 	bool chkref;
51348a2a57Smckusick 	struct nl *iop;
52348a2a57Smckusick 	char *cp;
53348a2a57Smckusick 	extern int cntstat;
54348a2a57Smckusick #	ifdef PC
55f617c19fSmckusic 	    int		savlabel = getlab();
56348a2a57Smckusick 	    int		toplabel = getlab();
57348a2a57Smckusick 	    int		botlabel = getlab();
58*5b396f44Speter 	    char	extname[ BUFSIZ ];
59348a2a57Smckusick #	endif PC
60348a2a57Smckusick 
61348a2a57Smckusick 	cntstat = 0;
62348a2a57Smckusick /*
63348a2a57Smckusick  *	yyoutline();
64348a2a57Smckusick  */
65348a2a57Smckusick 	if (program != NIL)
66348a2a57Smckusick 		line = program->value[3];
67348a2a57Smckusick 	blk = bundle[2];
68348a2a57Smckusick 	if (fp == NIL) {
69348a2a57Smckusick 		cbn--;
70348a2a57Smckusick #		ifdef PTREE
71348a2a57Smckusick 		    nesting--;
72348a2a57Smckusick #		endif PTREE
73348a2a57Smckusick 		return;
74348a2a57Smckusick 	}
75348a2a57Smckusick #ifdef OBJ
76348a2a57Smckusick 	/*
77348a2a57Smckusick 	 * Patch the branch to the
78348a2a57Smckusick 	 * entry point of the function
79348a2a57Smckusick 	 */
80348a2a57Smckusick 	patch4(fp->entloc);
81348a2a57Smckusick 	/*
82348a2a57Smckusick 	 * Put out the block entrance code and the block name.
83348a2a57Smckusick 	 * HDRSZE is the number of bytes of info in the static
84348a2a57Smckusick 	 * BEG data area exclusive of the proc name. It is
85348a2a57Smckusick 	 * currently defined as:
86348a2a57Smckusick 	/*	struct hdr {
87348a2a57Smckusick 	/*		long framesze;	/* number of bytes of local vars */
88348a2a57Smckusick 	/*		long nargs;	/* number of bytes of arguments */
89348a2a57Smckusick 	/*		bool tests;	/* TRUE => perform runtime tests */
90348a2a57Smckusick 	/*		short offset;	/* offset of procedure in source file */
91348a2a57Smckusick 	/*		char name[1];	/* name of active procedure */
92348a2a57Smckusick 	/*	};
93348a2a57Smckusick 	 */
94348a2a57Smckusick #	define HDRSZE (2 * sizeof(long) + sizeof(short) + sizeof(bool))
95348a2a57Smckusick 	var = put(2, ((lenstr(fp->symbol,0) + HDRSZE) << 8)
96348a2a57Smckusick 		| (cbn == 1 && opt('p') == 0 ? O_NODUMP: O_BEG), (long)0);
97348a2a57Smckusick 	    /*
98348a2a57Smckusick 	     *  output the number of bytes of arguments
99348a2a57Smckusick 	     *  this is only checked on formal calls.
100348a2a57Smckusick 	     */
101348a2a57Smckusick 	put(2, O_CASE4, cbn == 1 ? (long)0 : (long)(fp->value[NL_OFFS]-DPOFF2));
102348a2a57Smckusick 	    /*
103348a2a57Smckusick 	     *	Output the runtime test mode for the routine
104348a2a57Smckusick 	     */
105348a2a57Smckusick 	put(2, sizeof(bool) == 2 ? O_CASE2 : O_CASE4, opt('t') ? TRUE : FALSE);
106348a2a57Smckusick 	    /*
107348a2a57Smckusick 	     *	Output line number and routine name
108348a2a57Smckusick 	     */
109348a2a57Smckusick 	put(2, O_CASE2, bundle[1]);
110348a2a57Smckusick 	putstr(fp->symbol, 0);
111348a2a57Smckusick #endif OBJ
112348a2a57Smckusick #ifdef PC
113348a2a57Smckusick 	/*
114348a2a57Smckusick 	 * put out the procedure entry code
115348a2a57Smckusick 	 */
116348a2a57Smckusick 	if ( fp -> class == PROG ) {
117348a2a57Smckusick 	    putprintf( "	.text" , 0 );
118348a2a57Smckusick 	    putprintf( "	.align	1" , 0 );
119348a2a57Smckusick 	    putprintf( "	.globl	_main" , 0 );
120348a2a57Smckusick 	    putprintf( "_main:" , 0 );
121348a2a57Smckusick 	    putprintf( "	.word	0" , 0 );
122348a2a57Smckusick 	    putprintf( "	calls	$0,_PCSTART" , 0 );
123348a2a57Smckusick 	    putprintf( "	movl	4(ap),__argc" , 0 );
124348a2a57Smckusick 	    putprintf( "	movl	8(ap),__argv" , 0 );
125348a2a57Smckusick 	    putprintf( "	calls	$0,_program" , 0 );
126348a2a57Smckusick 	    putprintf( "	calls	$0,_PCEXIT" , 0 );
127348a2a57Smckusick 	    ftnno = fp -> entloc;
128348a2a57Smckusick 	    putprintf( "	.text" , 0 );
129348a2a57Smckusick 	    putprintf( "	.align	1" , 0 );
130348a2a57Smckusick 	    putprintf( "	.globl	_program" , 0 );
131348a2a57Smckusick 	    putprintf( "_program:" , 0 );
132348a2a57Smckusick 	    stabfunc( "program" , fp -> class , bundle[1] , 0 );
133348a2a57Smckusick 	} else {
134348a2a57Smckusick 	    ftnno = fp -> entloc;
135348a2a57Smckusick 	    putprintf( "	.text" , 0 );
136348a2a57Smckusick 	    putprintf( "	.align	1" , 0 );
137*5b396f44Speter 	    sextname( extname , fp -> symbol , cbn );
138*5b396f44Speter 	    putprintf( "	.globl	%s" , 0 , extname );
139*5b396f44Speter 	    putprintf( "%s:" , 0 , extname );
140348a2a57Smckusick 	    stabfunc( fp -> symbol , fp -> class , bundle[1] , cbn - 1 );
141348a2a57Smckusick 	    for ( p = fp -> chain ; p != NIL ; p = p -> chain ) {
142348a2a57Smckusick 		stabparam( p -> symbol , p2type( p -> type )
143348a2a57Smckusick 			    , p -> value[ NL_OFFS ] , lwidth( p -> type ) );
144348a2a57Smckusick 	    }
145348a2a57Smckusick 	    if ( fp -> class == FUNC ) {
146348a2a57Smckusick 		    /*
147348a2a57Smckusick 		     *	stab the function variable
148348a2a57Smckusick 		     */
149348a2a57Smckusick 		p = fp -> ptr[ NL_FVAR ];
150348a2a57Smckusick 		stablvar( p -> symbol , p2type( p -> type ) , cbn
151348a2a57Smckusick 			, p -> value[ NL_OFFS ] , lwidth( p -> type ) );
152348a2a57Smckusick 	    }
153348a2a57Smckusick 		/*
154348a2a57Smckusick 		 *	stab local variables
155348a2a57Smckusick 		 *	rummage down hash chain links.
156348a2a57Smckusick 		 */
157348a2a57Smckusick 	    for ( i = 0 ; i <= 077 ; i++ ) {
158348a2a57Smckusick 		for ( p = disptab[ i ] ; p != NIL ; p = p->nl_next) {
159348a2a57Smckusick 		    if ( ( p -> nl_block & 037 ) != cbn ) {
160348a2a57Smckusick 			break;
161348a2a57Smckusick 		    }
162348a2a57Smckusick 		    /*
163348a2a57Smckusick 		     *	stab local variables
164348a2a57Smckusick 		     *	that's named variables, but not params
165348a2a57Smckusick 		     */
166348a2a57Smckusick 		    if (   ( p -> symbol != NIL )
167348a2a57Smckusick 			&& ( p -> class == VAR )
168348a2a57Smckusick 			&& ( p -> value[ NL_OFFS ] < 0 ) ) {
169348a2a57Smckusick 			stablvar( p -> symbol , p2type( p -> type ) , cbn
170348a2a57Smckusick 			    , p -> value[ NL_OFFS ] , lwidth( p -> type ) );
171348a2a57Smckusick 		    }
172348a2a57Smckusick 		}
173348a2a57Smckusick 	    }
174348a2a57Smckusick 	}
175348a2a57Smckusick 	stablbrac( cbn );
176348a2a57Smckusick 	    /*
177348a2a57Smckusick 	     *	register save mask
178348a2a57Smckusick 	     */
179f617c19fSmckusic 	putprintf( "	.word	" , 1 );
180f617c19fSmckusic         putprintf( PREFIXFORMAT , 0 , LABELPREFIX , savlabel );
181348a2a57Smckusick 	putjbr( botlabel );
182348a2a57Smckusick 	putlab( toplabel );
183348a2a57Smckusick 	if ( profflag ) {
184348a2a57Smckusick 		/*
185348a2a57Smckusick 		 *	call mcount for profiling
186348a2a57Smckusick 		 */
187348a2a57Smckusick 	    putprintf( "	moval	1f,r0" , 0 );
188348a2a57Smckusick 	    putprintf( "	jsb	mcount" , 0 );
189348a2a57Smckusick 	    putprintf( "	.data" , 0 );
190348a2a57Smckusick 	    putprintf( "	.align	2" , 0 );
191348a2a57Smckusick 	    putprintf( "1:" , 0 );
192348a2a57Smckusick 	    putprintf( "	.long	0" , 0 );
193348a2a57Smckusick 	    putprintf( "	.text" , 0 );
194348a2a57Smckusick 	}
195348a2a57Smckusick 	    /*
196348a2a57Smckusick 	     *	set up unwind exception vector.
197348a2a57Smckusick 	     */
198348a2a57Smckusick 	putprintf( "	moval	%s,%d(%s)" , 0
199348a2a57Smckusick 		, UNWINDNAME , UNWINDOFFSET , P2FPNAME );
200348a2a57Smckusick 	    /*
201348a2a57Smckusick 	     *	save address of display entry, for unwind.
202348a2a57Smckusick 	     */
203348a2a57Smckusick 	putprintf( "	moval	%s+%d,%d(%s)" , 0
204348a2a57Smckusick 		, DISPLAYNAME , cbn * sizeof(struct dispsave)
205348a2a57Smckusick 		, DPTROFFSET , P2FPNAME );
206348a2a57Smckusick 	    /*
207348a2a57Smckusick 	     *	save old display
208348a2a57Smckusick 	     */
209348a2a57Smckusick 	putprintf( "	movq	%s+%d,%d(%s)" , 0
210348a2a57Smckusick 		, DISPLAYNAME , cbn * sizeof(struct dispsave)
211348a2a57Smckusick 		, DSAVEOFFSET , P2FPNAME );
212348a2a57Smckusick 	    /*
213348a2a57Smckusick 	     *	set up new display by saving AP and FP in appropriate
214348a2a57Smckusick 	     *	slot in display structure.
215348a2a57Smckusick 	     */
216348a2a57Smckusick 	putprintf( "	movq	%s,%s+%d" , 0
217348a2a57Smckusick 		, P2APNAME , DISPLAYNAME , cbn * sizeof(struct dispsave) );
218348a2a57Smckusick 	    /*
219348a2a57Smckusick 	     *	ask second pass to allocate known locals
220348a2a57Smckusick 	     */
221348a2a57Smckusick 	putlbracket( ftnno , -sizes[ cbn ].om_max );
222348a2a57Smckusick 	    /*
223348a2a57Smckusick 	     *	and zero them if checking is on
224348a2a57Smckusick 	     *	by calling blkclr( bytes of locals , starting local address );
225348a2a57Smckusick 	     */
226403dbb08Smckusic 	if ( opt( 't' ) && ( -sizes[ cbn ].om_max ) > DPOFF1 ) {
227348a2a57Smckusick 	    putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
228348a2a57Smckusick 		    , "_blkclr" );
229348a2a57Smckusick 	    putleaf( P2ICON ,  ( -sizes[ cbn ].om_max ) - DPOFF1
230348a2a57Smckusick 		    , 0 , P2INT , 0 );
231348a2a57Smckusick 	    putLV( 0 , cbn , sizes[ cbn ].om_max , P2CHAR );
232348a2a57Smckusick 	    putop( P2LISTOP , P2INT );
233348a2a57Smckusick 	    putop( P2CALL , P2INT );
234348a2a57Smckusick 	    putdot( filename , line );
235348a2a57Smckusick 	}
236348a2a57Smckusick #endif PC
237348a2a57Smckusick 	if ( monflg ) {
238348a2a57Smckusick 		if ( fp -> value[ NL_CNTR ] != 0 ) {
239348a2a57Smckusick 			inccnt( fp -> value [ NL_CNTR ] );
240348a2a57Smckusick 		}
241348a2a57Smckusick 		inccnt( bodycnts[ fp -> nl_block & 037 ] );
242348a2a57Smckusick 	}
243348a2a57Smckusick 	if (fp->class == PROG) {
244348a2a57Smckusick 		/*
245348a2a57Smckusick 		 * The glorious buffers option.
246348a2a57Smckusick 		 *          0 = don't buffer output
247348a2a57Smckusick 		 *          1 = line buffer output
248348a2a57Smckusick 		 *          2 = 512 byte buffer output
249348a2a57Smckusick 		 */
250348a2a57Smckusick #		ifdef OBJ
251348a2a57Smckusick 		    if (opt('b') != 1)
252348a2a57Smckusick 			    put(1, O_BUFF | opt('b') << 8);
253348a2a57Smckusick #		endif OBJ
254348a2a57Smckusick #		ifdef PC
255348a2a57Smckusick 		    if ( opt( 'b' ) != 1 ) {
256348a2a57Smckusick 			putleaf( P2ICON , 0 , 0
257348a2a57Smckusick 				, ADDTYPE( P2FTN | P2INT , P2PTR ) , "_BUFF" );
258348a2a57Smckusick 			putleaf( P2ICON , opt( 'b' ) , 0 , P2INT , 0 );
259348a2a57Smckusick 			putop( P2CALL , P2INT );
260348a2a57Smckusick 			putdot( filename , line );
261348a2a57Smckusick 		    }
262348a2a57Smckusick #		endif PC
263348a2a57Smckusick 		out = 0;
264348a2a57Smckusick 		for (p = fp->chain; p != NIL; p = p->chain) {
265348a2a57Smckusick 			if (strcmp(p->symbol, "input") == 0) {
266348a2a57Smckusick 				inp++;
267348a2a57Smckusick 				continue;
268348a2a57Smckusick 			}
269348a2a57Smckusick 			if (strcmp(p->symbol, "output") == 0) {
270348a2a57Smckusick 				out++;
271348a2a57Smckusick 				continue;
272348a2a57Smckusick 			}
273348a2a57Smckusick 			iop = lookup1(p->symbol);
274348a2a57Smckusick 			if (iop == NIL || bn != cbn) {
275348a2a57Smckusick 				error("File %s listed in program statement but not declared", p->symbol);
276348a2a57Smckusick 				continue;
277348a2a57Smckusick 			}
278348a2a57Smckusick 			if (iop->class != VAR) {
279348a2a57Smckusick 				error("File %s listed in program statement but declared as a %s", p->symbol, classes[iop->class]);
280348a2a57Smckusick 				continue;
281348a2a57Smckusick 			}
282348a2a57Smckusick 			if (iop->type == NIL)
283348a2a57Smckusick 				continue;
284348a2a57Smckusick 			if (iop->type->class != FILET) {
285348a2a57Smckusick 				error("File %s listed in program statement but defined as %s",
286348a2a57Smckusick 					p->symbol, nameof(iop->type));
287348a2a57Smckusick 				continue;
288348a2a57Smckusick 			}
289348a2a57Smckusick #			ifdef OBJ
290348a2a57Smckusick 			    put(2, O_CON24, text(iop->type) ? 0 : width(iop->type->type));
291348a2a57Smckusick 			    i = lenstr(p->symbol,0);
292348a2a57Smckusick 			    put(2, O_CON24, i);
293348a2a57Smckusick 			    put(2, O_LVCON, i);
294348a2a57Smckusick 			    putstr(p->symbol, 0);
295348a2a57Smckusick 			    put(2, O_LV | bn<<8+INDX, (int)iop->value[NL_OFFS]);
296348a2a57Smckusick 			    put(1, O_DEFNAME);
297348a2a57Smckusick #			endif OBJ
298348a2a57Smckusick #			ifdef PC
299348a2a57Smckusick 			    putleaf( P2ICON , 0 , 0
300348a2a57Smckusick 				    , ADDTYPE( P2FTN | P2INT , P2PTR )
301348a2a57Smckusick 				    , "_DEFNAME" );
302348a2a57Smckusick 			    putLV( p -> symbol , bn , iop -> value[NL_OFFS]
303348a2a57Smckusick 				    , p2type( iop ) );
304348a2a57Smckusick 			    putCONG( p -> symbol , strlen( p -> symbol )
305348a2a57Smckusick 				    , LREQ );
306348a2a57Smckusick 			    putop( P2LISTOP , P2INT );
307348a2a57Smckusick 			    putleaf( P2ICON , strlen( p -> symbol )
308348a2a57Smckusick 				    , 0 , P2INT , 0 );
309348a2a57Smckusick 			    putop( P2LISTOP , P2INT );
310348a2a57Smckusick 			    putleaf( P2ICON
311348a2a57Smckusick 				, text(iop->type) ? 0 : width(iop->type->type)
312348a2a57Smckusick 				, 0 , P2INT , 0 );
313348a2a57Smckusick 			    putop( P2LISTOP , P2INT );
314348a2a57Smckusick 			    putop( P2CALL , P2INT );
315348a2a57Smckusick 			    putdot( filename , line );
316348a2a57Smckusick #			endif PC
317348a2a57Smckusick 		}
318348a2a57Smckusick 		if (out == 0 && fp->chain != NIL) {
319348a2a57Smckusick 			recovered();
320348a2a57Smckusick 			error("The file output must appear in the program statement file list");
321348a2a57Smckusick 		}
322348a2a57Smckusick 	}
323348a2a57Smckusick 	/*
324348a2a57Smckusick 	 * Process the prog/proc/func body
325348a2a57Smckusick 	 */
326348a2a57Smckusick 	noreach = 0;
327348a2a57Smckusick 	line = bundle[1];
328348a2a57Smckusick 	statlist(blk);
329348a2a57Smckusick #	ifdef PTREE
330348a2a57Smckusick 	    {
331348a2a57Smckusick 		pPointer Body = tCopy( blk );
332348a2a57Smckusick 
333348a2a57Smckusick 		pDEF( PorFHeader[ nesting -- ] ).PorFBody = Body;
334348a2a57Smckusick 	    }
335348a2a57Smckusick #	endif PTREE
336348a2a57Smckusick #	ifdef OBJ
337348a2a57Smckusick 	    if (cbn== 1 && monflg != 0) {
338348a2a57Smckusick 		    patchfil(cntpatch - 2, (long)cnts, 2);
339348a2a57Smckusick 		    patchfil(nfppatch - 2, (long)pfcnt, 2);
340348a2a57Smckusick 	    }
341348a2a57Smckusick #	endif OBJ
342348a2a57Smckusick #	ifdef PC
343348a2a57Smckusick 	    if ( fp -> class == PROG && monflg ) {
344348a2a57Smckusick 		putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
345348a2a57Smckusick 			, "_PMFLUSH" );
346348a2a57Smckusick 		putleaf( P2ICON , cnts , 0 , P2INT , 0 );
347348a2a57Smckusick 		putleaf( P2ICON , pfcnt , 0 , P2INT , 0 );
348348a2a57Smckusick 		putop( P2LISTOP , P2INT );
349348a2a57Smckusick 		putLV( PCPCOUNT , 0 , 0 , P2INT );
350348a2a57Smckusick 		putop( P2LISTOP , P2INT );
351348a2a57Smckusick 		putop( P2CALL , P2INT );
352348a2a57Smckusick 		putdot( filename , line );
353348a2a57Smckusick 	    }
354348a2a57Smckusick #	endif PC
355348a2a57Smckusick 	if (fp->class == PROG && inp == 0 && (input->nl_flags & (NUSED|NMOD)) != 0) {
356348a2a57Smckusick 		recovered();
357348a2a57Smckusick 		error("Input is used but not defined in the program statement");
358348a2a57Smckusick 	}
359348a2a57Smckusick 	/*
360348a2a57Smckusick 	 * Clean up the symbol table displays and check for unresolves
361348a2a57Smckusick 	 */
362348a2a57Smckusick 	line = endline;
363348a2a57Smckusick 	b = cbn;
364348a2a57Smckusick 	Fp = fp;
365348a2a57Smckusick 	chkref = syneflg == errcnt[cbn] && opt('w') == 0;
366348a2a57Smckusick 	for (i = 0; i <= 077; i++) {
367348a2a57Smckusick 		for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) {
368348a2a57Smckusick 			/*
369348a2a57Smckusick 			 * Check for variables defined
370348a2a57Smckusick 			 * but not referenced
371348a2a57Smckusick 			 */
372348a2a57Smckusick 			if (chkref && p->symbol != NIL)
373348a2a57Smckusick 			switch (p->class) {
374348a2a57Smckusick 				case FIELD:
375348a2a57Smckusick 					/*
376348a2a57Smckusick 					 * If the corresponding record is
377348a2a57Smckusick 					 * unused, we shouldn't complain about
378348a2a57Smckusick 					 * the fields.
379348a2a57Smckusick 					 */
380348a2a57Smckusick 				default:
381348a2a57Smckusick 					if ((p->nl_flags & (NUSED|NMOD)) == 0) {
382348a2a57Smckusick 						warning();
383348a2a57Smckusick 						nerror("%s %s is neither used nor set", classes[p->class], p->symbol);
384348a2a57Smckusick 						break;
385348a2a57Smckusick 					}
386348a2a57Smckusick 					/*
387348a2a57Smckusick 					 * If a var parameter is either
388348a2a57Smckusick 					 * modified or used that is enough.
389348a2a57Smckusick 					 */
390348a2a57Smckusick 					if (p->class == REF)
391348a2a57Smckusick 						continue;
392348a2a57Smckusick #					ifdef OBJ
393348a2a57Smckusick 					    if ((p->nl_flags & NUSED) == 0) {
394348a2a57Smckusick 						warning();
395348a2a57Smckusick 						nerror("%s %s is never used", classes[p->class], p->symbol);
396348a2a57Smckusick 						break;
397348a2a57Smckusick 					    }
398348a2a57Smckusick #					endif OBJ
399348a2a57Smckusick #					ifdef PC
400348a2a57Smckusick 					    if (((p->nl_flags & NUSED) == 0) && ((p->ext_flags & NEXTERN) == 0)) {
401348a2a57Smckusick 						warning();
402348a2a57Smckusick 						nerror("%s %s is never used", classes[p->class], p->symbol);
403348a2a57Smckusick 						break;
404348a2a57Smckusick 					    }
405348a2a57Smckusick #					endif PC
406348a2a57Smckusick 					if ((p->nl_flags & NMOD) == 0) {
407348a2a57Smckusick 						warning();
408348a2a57Smckusick 						nerror("%s %s is used but never set", classes[p->class], p->symbol);
409348a2a57Smckusick 						break;
410348a2a57Smckusick 					}
411348a2a57Smckusick 				case LABEL:
412348a2a57Smckusick 				case FVAR:
413348a2a57Smckusick 				case BADUSE:
414348a2a57Smckusick 					break;
415348a2a57Smckusick 			}
416348a2a57Smckusick 			switch (p->class) {
417348a2a57Smckusick 				case BADUSE:
418348a2a57Smckusick 					cp = "s";
419348a2a57Smckusick 					if (p->chain->ud_next == NIL)
420348a2a57Smckusick 						cp++;
421348a2a57Smckusick 					eholdnl();
422348a2a57Smckusick 					if (p->value[NL_KINDS] & ISUNDEF)
423348a2a57Smckusick 						nerror("%s undefined on line%s", p->symbol, cp);
424348a2a57Smckusick 					else
425348a2a57Smckusick 						nerror("%s improperly used on line%s", p->symbol, cp);
426348a2a57Smckusick 					pnumcnt = 10;
427348a2a57Smckusick 					pnums(p->chain);
428348a2a57Smckusick 					pchr('\n');
429348a2a57Smckusick 					break;
430348a2a57Smckusick 
431348a2a57Smckusick 				case FUNC:
432348a2a57Smckusick 				case PROC:
433348a2a57Smckusick #					ifdef OBJ
434348a2a57Smckusick 					    if ((p->nl_flags & NFORWD))
435348a2a57Smckusick 						nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol);
436348a2a57Smckusick #					endif OBJ
437348a2a57Smckusick #					ifdef PC
438348a2a57Smckusick 					    if ((p->nl_flags & NFORWD) && ((p->ext_flags & NEXTERN) == 0))
439348a2a57Smckusick 						nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol);
440348a2a57Smckusick #					endif PC
441348a2a57Smckusick 					break;
442348a2a57Smckusick 
443348a2a57Smckusick 				case LABEL:
444348a2a57Smckusick 					if (p->nl_flags & NFORWD)
445348a2a57Smckusick 						nerror("label %s was declared but not defined", p->symbol);
446348a2a57Smckusick 					break;
447348a2a57Smckusick 				case FVAR:
448348a2a57Smckusick 					if ((p->nl_flags & NMOD) == 0)
449348a2a57Smckusick 						nerror("No assignment to the function variable");
450348a2a57Smckusick 					break;
451348a2a57Smckusick 			}
452348a2a57Smckusick 		}
453348a2a57Smckusick 		/*
454348a2a57Smckusick 		 * Pop this symbol
455348a2a57Smckusick 		 * table slot
456348a2a57Smckusick 		 */
457348a2a57Smckusick 		disptab[i] = p;
458348a2a57Smckusick 	}
459348a2a57Smckusick 
460348a2a57Smckusick #	ifdef OBJ
461348a2a57Smckusick 	    put(1, O_END);
462348a2a57Smckusick #	endif OBJ
463348a2a57Smckusick #	ifdef PC
464348a2a57Smckusick 		/*
465348a2a57Smckusick 		 *	if there were file variables declared at this level
466348a2a57Smckusick 		 *	call pclose( &__disply[ cbn ] ) to clean them up.
467348a2a57Smckusick 		 */
468348a2a57Smckusick 	    if ( dfiles[ cbn ] ) {
469348a2a57Smckusick 		putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
470348a2a57Smckusick 			, "_PCLOSE" );
471348a2a57Smckusick 		putRV( DISPLAYNAME , 0 , cbn * sizeof( struct dispsave )
472348a2a57Smckusick 			, P2PTR | P2CHAR );
473348a2a57Smckusick 		putop( P2CALL , P2INT );
474348a2a57Smckusick 		putdot( filename , line );
475348a2a57Smckusick 	    }
476348a2a57Smckusick 		/*
477348a2a57Smckusick 		 *	if this is a function,
478348a2a57Smckusick 		 *	the function variable is the return value.
479348a2a57Smckusick 		 *	if it's a scalar valued function, return scalar,
480348a2a57Smckusick 		 *	else, return a pointer to the structure value.
481348a2a57Smckusick 		 */
482348a2a57Smckusick 	    if ( fp -> class == FUNC ) {
483348a2a57Smckusick 		struct nl	*fvar = fp -> ptr[ NL_FVAR ];
484348a2a57Smckusick 		long		fvartype = p2type( fvar -> type );
485348a2a57Smckusick 		long		label;
486348a2a57Smckusick 		char		labelname[ BUFSIZ ];
487348a2a57Smckusick 
488348a2a57Smckusick 		switch ( classify( fvar -> type ) ) {
489348a2a57Smckusick 		    case TBOOL:
490348a2a57Smckusick 		    case TCHAR:
491348a2a57Smckusick 		    case TINT:
492348a2a57Smckusick 		    case TSCAL:
493348a2a57Smckusick 		    case TDOUBLE:
494348a2a57Smckusick 		    case TPTR:
495348a2a57Smckusick 			putRV( fvar -> symbol , ( fvar -> nl_block ) & 037
496348a2a57Smckusick 				, fvar -> value[ NL_OFFS ] , fvartype );
497348a2a57Smckusick 			break;
498348a2a57Smckusick 		    default:
499348a2a57Smckusick 			label = getlab();
500348a2a57Smckusick 			sprintf( labelname , PREFIXFORMAT ,
501348a2a57Smckusick 				LABELPREFIX , label );
502348a2a57Smckusick 			putprintf( "	.data" , 0 );
503348a2a57Smckusick 			putprintf( "	.lcomm	%s,%d" , 0 ,
504348a2a57Smckusick 				    labelname , lwidth( fvar -> type ) );
505348a2a57Smckusick 			putprintf( "	.text" , 0 );
506348a2a57Smckusick 			putleaf( P2NAME , 0 , 0 , fvartype , labelname );
507348a2a57Smckusick 			putLV( fvar -> symbol , ( fvar -> nl_block ) & 037
508348a2a57Smckusick 				, fvar -> value[ NL_OFFS ] , fvartype );
509348a2a57Smckusick 			putstrop( P2STASG , fvartype , lwidth( fvar -> type ) ,
510348a2a57Smckusick 				align( fvar -> type ) );
511348a2a57Smckusick 			putdot( filename , line );
512348a2a57Smckusick 			putleaf( P2ICON , 0 , 0 , fvartype , labelname );
513348a2a57Smckusick 			break;
514348a2a57Smckusick 		}
515348a2a57Smckusick 		putop( P2FORCE , fvartype );
516348a2a57Smckusick 		putdot( filename , line );
517348a2a57Smckusick 	    }
518348a2a57Smckusick 		/*
519348a2a57Smckusick 		 *	restore old display entry from save area
520348a2a57Smckusick 		 */
521348a2a57Smckusick 
522348a2a57Smckusick 	    putprintf( "	movq	%d(%s),%s+%d" , 0
523348a2a57Smckusick 		, DSAVEOFFSET , P2FPNAME
524348a2a57Smckusick 		, DISPLAYNAME , cbn * sizeof(struct dispsave) );
525348a2a57Smckusick 	    stabrbrac( cbn );
526348a2a57Smckusick 	    putprintf( "	ret" , 0 );
527348a2a57Smckusick 		/*
528348a2a57Smckusick 		 *	let the second pass allocate locals
529f617c19fSmckusic 		 * 	and registers
530348a2a57Smckusick 		 */
531f617c19fSmckusic 	    putprintf( "	.set	" , 1 );
532f617c19fSmckusic 	    putprintf( PREFIXFORMAT , 1 , LABELPREFIX , savlabel );
533f617c19fSmckusic 	    putprintf( ", 0x%x" , 0 , savmask() );
534348a2a57Smckusick 	    putlab( botlabel );
535348a2a57Smckusick 	    putprintf( "	subl2	$LF%d,sp" , 0 , ftnno );
536348a2a57Smckusick 	    putrbracket( ftnno );
537348a2a57Smckusick 	    putjbr( toplabel );
538348a2a57Smckusick 		/*
539348a2a57Smckusick 		 *	declare pcp counters, if any
540348a2a57Smckusick 		 */
541348a2a57Smckusick 	    if ( monflg && fp -> class == PROG ) {
542348a2a57Smckusick 		putprintf( "	.data" , 0 );
543348a2a57Smckusick 		putprintf( "	.comm	" , 1 );
544348a2a57Smckusick 		putprintf( PCPCOUNT , 1 );
545348a2a57Smckusick 		putprintf( ",%d" , 0 , ( cnts + 1 ) * sizeof (long) );
546348a2a57Smckusick 		putprintf( "	.text" , 0 );
547348a2a57Smckusick 	    }
548348a2a57Smckusick #	endif PC
549348a2a57Smckusick #ifdef DEBUG
550348a2a57Smckusick 	dumpnl(fp->ptr[2], fp->symbol);
551348a2a57Smckusick #endif
552348a2a57Smckusick 	/*
553348a2a57Smckusick 	 * Restore the
554348a2a57Smckusick 	 * (virtual) name list
555348a2a57Smckusick 	 * position
556348a2a57Smckusick 	 */
557348a2a57Smckusick 	nlfree(fp->ptr[2]);
558348a2a57Smckusick 	/*
559348a2a57Smckusick 	 * Proc/func has been
560348a2a57Smckusick 	 * resolved
561348a2a57Smckusick 	 */
562348a2a57Smckusick 	fp->nl_flags &= ~NFORWD;
563348a2a57Smckusick 	/*
564348a2a57Smckusick 	 * Patch the beg
565348a2a57Smckusick 	 * of the proc/func to
566348a2a57Smckusick 	 * the proper variable size
567348a2a57Smckusick 	 */
568348a2a57Smckusick 	if (Fp == NIL)
569348a2a57Smckusick 		elineon();
570348a2a57Smckusick #	ifdef OBJ
571348a2a57Smckusick 	    patchfil(var, (long)(-sizes[cbn].om_max), 2);
572348a2a57Smckusick #	endif OBJ
573348a2a57Smckusick 	cbn--;
574348a2a57Smckusick 	if (inpflist(fp->symbol)) {
575348a2a57Smckusick 		opop('l');
576348a2a57Smckusick 	}
577348a2a57Smckusick }
578*5b396f44Speter 
579*5b396f44Speter #ifdef PC
580*5b396f44Speter     /*
581*5b396f44Speter      *	construct the long name of a function based on it's static nesting.
582*5b396f44Speter      *	into a caller-supplied buffer (that should be about BUFSIZ big).
583*5b396f44Speter      */
584*5b396f44Speter sextname( buffer , name , level )
585*5b396f44Speter     char	buffer[];
586*5b396f44Speter     char	*name;
587*5b396f44Speter     int		level;
588*5b396f44Speter {
589*5b396f44Speter     char	*starthere;
590*5b396f44Speter     int	i;
591*5b396f44Speter 
592*5b396f44Speter     starthere = &buffer[0];
593*5b396f44Speter     for ( i = 1 ; i < level ; i++ ) {
594*5b396f44Speter 	sprintf( starthere , EXTFORMAT , enclosing[ i ] );
595*5b396f44Speter 	starthere += strlen( enclosing[ i ] ) + 1;
596*5b396f44Speter     }
597*5b396f44Speter     sprintf( starthere , EXTFORMAT , p -> symbol );
598*5b396f44Speter     starthere += strlen( p -> symbol ) + 1;
599*5b396f44Speter     if ( starthere >= &buffer[ BUFSIZ ] ) {
600*5b396f44Speter 	panic( "sextname" );
601*5b396f44Speter     }
602*5b396f44Speter }
603*5b396f44Speter #endif PC
604