xref: /csrg-svn/usr.bin/pascal/src/fend.c (revision 9129)
13192Smckusick /* Copyright (c) 1979 Regents of the University of California */
23192Smckusick 
3*9129Smckusick static char sccsid[] = "@(#)fend.c 1.16 11/12/82";
43192Smckusick 
53192Smckusick #include "whoami.h"
63192Smckusick #include "0.h"
73192Smckusick #include "tree.h"
83192Smckusick #include "opcode.h"
93192Smckusick #include "objfmt.h"
103192Smckusick #include "align.h"
113192Smckusick 
123192Smckusick /*
133192Smckusick  * this array keeps the pxp counters associated with
143192Smckusick  * functions and procedures, so that they can be output
153192Smckusick  * when their bodies are encountered
163192Smckusick  */
173192Smckusick int	bodycnts[ DSPLYSZ ];
183192Smckusick 
193192Smckusick #ifdef PC
203192Smckusick #   include "pc.h"
213192Smckusick #   include "pcops.h"
223192Smckusick #endif PC
233192Smckusick 
243192Smckusick #ifdef OBJ
253192Smckusick int	cntpatch;
263192Smckusick int	nfppatch;
273192Smckusick #endif OBJ
283192Smckusick 
293192Smckusick struct	nl *Fp;
303192Smckusick int	pnumcnt;
313192Smckusick /*
323192Smckusick  * Funcend is called to
333192Smckusick  * finish a block by generating
343192Smckusick  * the code for the statements.
353192Smckusick  * It then looks for unresolved declarations
363192Smckusick  * of labels, procedures and functions,
373192Smckusick  * and cleans up the name list.
383192Smckusick  * For the program, it checks the
393192Smckusick  * semantics of the program
403192Smckusick  * statement (yuchh).
413192Smckusick  */
423192Smckusick funcend(fp, bundle, endline)
433192Smckusick 	struct nl *fp;
443192Smckusick 	int *bundle;
453192Smckusick 	int endline;
463192Smckusick {
473192Smckusick 	register struct nl *p;
483192Smckusick 	register int i, b;
493192Smckusick 	int var, inp, out, *blk;
503192Smckusick 	bool chkref;
513192Smckusick 	struct nl *iop;
523192Smckusick 	char *cp;
533192Smckusick 	extern int cntstat;
543192Smckusick #	ifdef PC
553363Speter 	    int		savlabel = getlab();
563363Speter 	    int		toplabel = getlab();
573649Speter 	    int		proflabel = getlab();
589121Smckusick 	    int		skip = getlab();
593363Speter 	    char	extname[ BUFSIZ ];
603192Smckusick #	endif PC
613192Smckusick 
623192Smckusick 	cntstat = 0;
633192Smckusick /*
643192Smckusick  *	yyoutline();
653192Smckusick  */
663192Smckusick 	if (program != NIL)
673192Smckusick 		line = program->value[3];
683192Smckusick 	blk = bundle[2];
693192Smckusick 	if (fp == NIL) {
703192Smckusick 		cbn--;
713192Smckusick #		ifdef PTREE
723192Smckusick 		    nesting--;
733192Smckusick #		endif PTREE
743192Smckusick 		return;
753192Smckusick 	}
763192Smckusick #ifdef OBJ
773192Smckusick 	/*
783192Smckusick 	 * Patch the branch to the
793192Smckusick 	 * entry point of the function
803192Smckusick 	 */
817917Smckusick 	patch4(fp->value[NL_ENTLOC]);
823192Smckusick 	/*
833192Smckusick 	 * Put out the block entrance code and the block name.
843192Smckusick 	 * HDRSZE is the number of bytes of info in the static
853192Smckusick 	 * BEG data area exclusive of the proc name. It is
863192Smckusick 	 * currently defined as:
873192Smckusick 	/*	struct hdr {
883192Smckusick 	/*		long framesze;	/* number of bytes of local vars */
893192Smckusick 	/*		long nargs;	/* number of bytes of arguments */
903192Smckusick 	/*		bool tests;	/* TRUE => perform runtime tests */
913192Smckusick 	/*		short offset;	/* offset of procedure in source file */
923192Smckusick 	/*		char name[1];	/* name of active procedure */
933192Smckusick 	/*	};
943192Smckusick 	 */
953192Smckusick #	define HDRSZE (2 * sizeof(long) + sizeof(short) + sizeof(bool))
963192Smckusick 	var = put(2, ((lenstr(fp->symbol,0) + HDRSZE) << 8)
973192Smckusick 		| (cbn == 1 && opt('p') == 0 ? O_NODUMP: O_BEG), (long)0);
983192Smckusick 	    /*
993192Smckusick 	     *  output the number of bytes of arguments
1003192Smckusick 	     *  this is only checked on formal calls.
1013192Smckusick 	     */
1023192Smckusick 	put(2, O_CASE4, cbn == 1 ? (long)0 : (long)(fp->value[NL_OFFS]-DPOFF2));
1033192Smckusick 	    /*
1043192Smckusick 	     *	Output the runtime test mode for the routine
1053192Smckusick 	     */
1063192Smckusick 	put(2, sizeof(bool) == 2 ? O_CASE2 : O_CASE4, opt('t') ? TRUE : FALSE);
1073192Smckusick 	    /*
1083192Smckusick 	     *	Output line number and routine name
1093192Smckusick 	     */
1103192Smckusick 	put(2, O_CASE2, bundle[1]);
1113192Smckusick 	putstr(fp->symbol, 0);
1123192Smckusick #endif OBJ
1133192Smckusick #ifdef PC
1143192Smckusick 	/*
1153192Smckusick 	 * put out the procedure entry code
1163192Smckusick 	 */
1173192Smckusick 	if ( fp -> class == PROG ) {
118*9129Smckusick 		/*
119*9129Smckusick 		 *	If there is a label declaration in the main routine
120*9129Smckusick 		 *	then there may be a non-local goto to it that does
121*9129Smckusick 		 *	not appear in this module. We have to assume that
122*9129Smckusick 		 *	such a reference may occur and generate code to
123*9129Smckusick 		 *	prepare for it.
124*9129Smckusick 		 */
125*9129Smckusick 	    if ( parts[ cbn ] & LPRT ) {
126*9129Smckusick 		parts[ cbn ] |= ( NONLOCALVAR | NONLOCALGOTO );
127*9129Smckusick 	    }
1283192Smckusick 	    putprintf( "	.text" , 0 );
1293192Smckusick 	    putprintf( "	.align	1" , 0 );
1303192Smckusick 	    putprintf( "	.globl	_main" , 0 );
1313192Smckusick 	    putprintf( "_main:" , 0 );
1323192Smckusick 	    putprintf( "	.word	0" , 0 );
1335677Smckusic 	    if ( opt ( 't' ) ) {
1345677Smckusic 	        putprintf( "	pushl	$1" , 0 );
1355677Smckusic 	    } else {
1365677Smckusic 	        putprintf( "	pushl	$0" , 0 );
1375677Smckusic 	    }
1385677Smckusic 	    putprintf( "	calls	$1,_PCSTART" , 0 );
1393192Smckusick 	    putprintf( "	movl	4(ap),__argc" , 0 );
1403192Smckusick 	    putprintf( "	movl	8(ap),__argv" , 0 );
1413192Smckusick 	    putprintf( "	calls	$0,_program" , 0 );
1427646Speter 	    putprintf( "	pushl	$0" , 0 );
1437646Speter 	    putprintf( "	calls	$1,_PCEXIT" , 0 );
1447917Smckusick 	    ftnno = fp -> value[NL_ENTLOC];
1453192Smckusick 	    putprintf( "	.text" , 0 );
1463192Smckusick 	    putprintf( "	.align	1" , 0 );
1473192Smckusick 	    putprintf( "	.globl	_program" , 0 );
1483192Smckusick 	    putprintf( "_program:" , 0 );
1493192Smckusick 	    stabfunc( "program" , fp -> class , bundle[1] , 0 );
1503192Smckusick 	} else {
1517917Smckusick 	    ftnno = fp -> value[NL_ENTLOC];
1523192Smckusick 	    putprintf( "	.text" , 0 );
1533192Smckusick 	    putprintf( "	.align	1" , 0 );
1543367Speter 	    sextname( extname , fp -> symbol , cbn - 1 );
1553428Speter 	    putprintf( "	.globl	%s%s" , 0 , FORMALPREFIX , extname );
1563363Speter 	    putprintf( "	.globl	%s" , 0 , extname );
1573363Speter 	    putprintf( "%s:" , 0 , extname );
1583192Smckusick 	    stabfunc( fp -> symbol , fp -> class , bundle[1] , cbn - 1 );
1593192Smckusick 	    for ( p = fp -> chain ; p != NIL ; p = p -> chain ) {
1603192Smckusick 		stabparam( p -> symbol , p2type( p -> type )
1613192Smckusick 			    , p -> value[ NL_OFFS ] , lwidth( p -> type ) );
1623192Smckusick 	    }
1633192Smckusick 	    if ( fp -> class == FUNC ) {
1643192Smckusick 		    /*
1653192Smckusick 		     *	stab the function variable
1663192Smckusick 		     */
1673192Smckusick 		p = fp -> ptr[ NL_FVAR ];
1683192Smckusick 		stablvar( p -> symbol , p2type( p -> type ) , cbn
1693192Smckusick 			, p -> value[ NL_OFFS ] , lwidth( p -> type ) );
1703192Smckusick 	    }
1713192Smckusick 		/*
1723192Smckusick 		 *	stab local variables
1733192Smckusick 		 *	rummage down hash chain links.
1743192Smckusick 		 */
1753192Smckusick 	    for ( i = 0 ; i <= 077 ; i++ ) {
1763192Smckusick 		for ( p = disptab[ i ] ; p != NIL ; p = p->nl_next) {
1773192Smckusick 		    if ( ( p -> nl_block & 037 ) != cbn ) {
1783192Smckusick 			break;
1793192Smckusick 		    }
1803192Smckusick 		    /*
1813192Smckusick 		     *	stab local variables
1823192Smckusick 		     *	that's named variables, but not params
1833192Smckusick 		     */
1843192Smckusick 		    if (   ( p -> symbol != NIL )
1853192Smckusick 			&& ( p -> class == VAR )
1863192Smckusick 			&& ( p -> value[ NL_OFFS ] < 0 ) ) {
1873192Smckusick 			stablvar( p -> symbol , p2type( p -> type ) , cbn
1883192Smckusick 			    , p -> value[ NL_OFFS ] , lwidth( p -> type ) );
1893192Smckusick 		    }
1903192Smckusick 		}
1913192Smckusick 	    }
1923192Smckusick 	}
1933192Smckusick 	stablbrac( cbn );
1943192Smckusick 	    /*
1953192Smckusick 	     *	register save mask
1963192Smckusick 	     */
1973279Smckusic 	putprintf( "	.word	" , 1 );
1983279Smckusic         putprintf( PREFIXFORMAT , 0 , LABELPREFIX , savlabel );
1993192Smckusick 	putlab( toplabel );
2009127Smckusick 	putprintf( "	subl2	$LF%d,sp" , 0 , ftnno );
2013192Smckusick 	if ( profflag ) {
2023192Smckusick 		/*
2033192Smckusick 		 *	call mcount for profiling
2043192Smckusick 		 */
2053649Speter 	    putprintf( "	moval	" , 1 );
2063649Speter 	    putprintf( PREFIXFORMAT , 1 , LABELPREFIX , proflabel );
2073649Speter 	    putprintf( ",r0" , 0 );
2083192Smckusick 	    putprintf( "	jsb	mcount" , 0 );
2093192Smckusick 	    putprintf( "	.data" , 0 );
2103192Smckusick 	    putprintf( "	.align	2" , 0 );
2113649Speter 	    putlab( proflabel );
2123192Smckusick 	    putprintf( "	.long	0" , 0 );
2133192Smckusick 	    putprintf( "	.text" , 0 );
2143192Smckusick 	}
2153192Smckusick 	    /*
216*9129Smckusick 	     *	if there are nested procedures that access our variables
217*9129Smckusick 	     *	we must save the display.
2183192Smckusick 	     */
2199127Smckusick 	if ( parts[ cbn ] & NONLOCALVAR ) {
2209127Smckusick 		/*
2219127Smckusick 		 *	save old display
2229127Smckusick 		 */
2239127Smckusick 	    putprintf( "	movq	%s+%d,%d(%s)" , 0
2249127Smckusick 		    , DISPLAYNAME , cbn * sizeof(struct dispsave)
2259127Smckusick 		    , DSAVEOFFSET , P2FPNAME );
2269127Smckusick 		/*
2279127Smckusick 		 *	set up new display by saving AP and FP in appropriate
2289127Smckusick 		 *	slot in display structure.
2299127Smckusick 		 */
2309127Smckusick 	    putprintf( "	movq	%s,%s+%d" , 0
2319127Smckusick 		    , P2APNAME , DISPLAYNAME , cbn * sizeof(struct dispsave) );
2329127Smckusick 	}
2333192Smckusick 	    /*
2345677Smckusic 	     *	set underflow checking if runtime tests
2355677Smckusic 	     */
2365677Smckusic 	if ( opt( 't' ) ) {
2375677Smckusic 	    putprintf( "	bispsw	$0xe0" , 0 );
2385677Smckusic 	}
2395677Smckusic 	    /*
2403192Smckusick 	     *	ask second pass to allocate known locals
2413192Smckusick 	     */
2423192Smckusick 	putlbracket( ftnno , -sizes[ cbn ].om_max );
2433192Smckusick 	    /*
2443192Smckusick 	     *	and zero them if checking is on
2453192Smckusick 	     *	by calling blkclr( bytes of locals , starting local address );
2463192Smckusick 	     */
2473301Smckusic 	if ( opt( 't' ) && ( -sizes[ cbn ].om_max ) > DPOFF1 ) {
2483301Smckusic 	    putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
2493301Smckusic 		    , "_blkclr" );
2503301Smckusic 	    putleaf( P2ICON ,  ( -sizes[ cbn ].om_max ) - DPOFF1
2513301Smckusic 		    , 0 , P2INT , 0 );
2523837Speter 	    putLV( 0 , cbn , sizes[ cbn ].om_max , NLOCAL , P2CHAR );
2533301Smckusic 	    putop( P2LISTOP , P2INT );
2543301Smckusic 	    putop( P2CALL , P2INT );
2553301Smckusic 	    putdot( filename , line );
2563192Smckusick 	}
2579121Smckusick 	    /*
258*9129Smckusick 	     *  set up goto vector if non-local goto to this frame
2599121Smckusick 	     */
260*9129Smckusick 	if ( parts[ cbn ] & NONLOCALGOTO ) {
2619127Smckusick 	    putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
2629127Smckusick 		    , "_setjmp" );
2639127Smckusick 	    putLV( 0 , cbn , GOTOENVOFFSET , NLOCAL , P2PTR|P2STRTY );
2649127Smckusick 	    putop( P2CALL , P2INT );
2659127Smckusick 	    putleaf( P2ICON , 0 , 0 , P2INT , 0 );
2669127Smckusick 	    putop( P2NE , P2INT );
2679127Smckusick 	    putleaf( P2ICON , skip , 0 , P2INT , 0 );
2689127Smckusick 	    putop( P2CBRANCH , P2INT );
2699127Smckusick 	    putdot( filename , line );
2709127Smckusick 		/*
2719127Smckusick 		 *	on non-local goto, setjmp returns with address to
2729127Smckusick 		 *	be branched to.
2739127Smckusick 		 */
2749127Smckusick 	    putprintf( "	jmp	(r0)" , 0 );
2759127Smckusick 	    putlab(skip);
2769127Smckusick 	}
2773192Smckusick #endif PC
2783192Smckusick 	if ( monflg ) {
2793192Smckusick 		if ( fp -> value[ NL_CNTR ] != 0 ) {
2803192Smckusick 			inccnt( fp -> value [ NL_CNTR ] );
2813192Smckusick 		}
2823192Smckusick 		inccnt( bodycnts[ fp -> nl_block & 037 ] );
2833192Smckusick 	}
2843192Smckusick 	if (fp->class == PROG) {
2853192Smckusick 		/*
2863192Smckusick 		 * The glorious buffers option.
2873192Smckusick 		 *          0 = don't buffer output
2883192Smckusick 		 *          1 = line buffer output
2893192Smckusick 		 *          2 = 512 byte buffer output
2903192Smckusick 		 */
2913192Smckusick #		ifdef OBJ
2923192Smckusick 		    if (opt('b') != 1)
2933192Smckusick 			    put(1, O_BUFF | opt('b') << 8);
2943192Smckusick #		endif OBJ
2953192Smckusick #		ifdef PC
2963192Smckusick 		    if ( opt( 'b' ) != 1 ) {
2973192Smckusick 			putleaf( P2ICON , 0 , 0
2983192Smckusick 				, ADDTYPE( P2FTN | P2INT , P2PTR ) , "_BUFF" );
2993192Smckusick 			putleaf( P2ICON , opt( 'b' ) , 0 , P2INT , 0 );
3003192Smckusick 			putop( P2CALL , P2INT );
3013192Smckusick 			putdot( filename , line );
3023192Smckusick 		    }
3033192Smckusick #		endif PC
3047953Speter 		inp = 0;
3053192Smckusick 		out = 0;
3063192Smckusick 		for (p = fp->chain; p != NIL; p = p->chain) {
3077953Speter 			if (strcmp(p->symbol, input->symbol) == 0) {
3083192Smckusick 				inp++;
3093192Smckusick 				continue;
3103192Smckusick 			}
3117953Speter 			if (strcmp(p->symbol, output->symbol) == 0) {
3123192Smckusick 				out++;
3133192Smckusick 				continue;
3143192Smckusick 			}
3153192Smckusick 			iop = lookup1(p->symbol);
3163192Smckusick 			if (iop == NIL || bn != cbn) {
3173192Smckusick 				error("File %s listed in program statement but not declared", p->symbol);
3183192Smckusick 				continue;
3193192Smckusick 			}
3203192Smckusick 			if (iop->class != VAR) {
3213192Smckusick 				error("File %s listed in program statement but declared as a %s", p->symbol, classes[iop->class]);
3223192Smckusick 				continue;
3233192Smckusick 			}
3243192Smckusick 			if (iop->type == NIL)
3253192Smckusick 				continue;
3263192Smckusick 			if (iop->type->class != FILET) {
3273192Smckusick 				error("File %s listed in program statement but defined as %s",
3283192Smckusick 					p->symbol, nameof(iop->type));
3293192Smckusick 				continue;
3303192Smckusick 			}
3313192Smckusick #			ifdef OBJ
3323192Smckusick 			    put(2, O_CON24, text(iop->type) ? 0 : width(iop->type->type));
3333192Smckusick 			    i = lenstr(p->symbol,0);
3343192Smckusick 			    put(2, O_CON24, i);
3353192Smckusick 			    put(2, O_LVCON, i);
3363192Smckusick 			    putstr(p->symbol, 0);
3373192Smckusick 			    put(2, O_LV | bn<<8+INDX, (int)iop->value[NL_OFFS]);
3383192Smckusick 			    put(1, O_DEFNAME);
3393192Smckusick #			endif OBJ
3403192Smckusick #			ifdef PC
3413192Smckusick 			    putleaf( P2ICON , 0 , 0
3423192Smckusick 				    , ADDTYPE( P2FTN | P2INT , P2PTR )
3433192Smckusick 				    , "_DEFNAME" );
3443837Speter 			    putLV( p -> symbol , bn , iop -> value[NL_OFFS] ,
3453837Speter 				    iop -> extra_flags , p2type( iop ) );
3463192Smckusick 			    putCONG( p -> symbol , strlen( p -> symbol )
3473192Smckusick 				    , LREQ );
3483192Smckusick 			    putop( P2LISTOP , P2INT );
3493192Smckusick 			    putleaf( P2ICON , strlen( p -> symbol )
3503192Smckusick 				    , 0 , P2INT , 0 );
3513192Smckusick 			    putop( P2LISTOP , P2INT );
3523192Smckusick 			    putleaf( P2ICON
3533192Smckusick 				, text(iop->type) ? 0 : width(iop->type->type)
3543192Smckusick 				, 0 , P2INT , 0 );
3553192Smckusick 			    putop( P2LISTOP , P2INT );
3563192Smckusick 			    putop( P2CALL , P2INT );
3573192Smckusick 			    putdot( filename , line );
3583192Smckusick #			endif PC
3593192Smckusick 		}
3603192Smckusick 	}
3613192Smckusick 	/*
3623192Smckusick 	 * Process the prog/proc/func body
3633192Smckusick 	 */
3643192Smckusick 	noreach = 0;
3653192Smckusick 	line = bundle[1];
3663192Smckusick 	statlist(blk);
3673192Smckusick #	ifdef PTREE
3683192Smckusick 	    {
3693192Smckusick 		pPointer Body = tCopy( blk );
3703192Smckusick 
3713192Smckusick 		pDEF( PorFHeader[ nesting -- ] ).PorFBody = Body;
3723192Smckusick 	    }
3733192Smckusick #	endif PTREE
3743192Smckusick #	ifdef OBJ
3753192Smckusick 	    if (cbn== 1 && monflg != 0) {
3763192Smckusick 		    patchfil(cntpatch - 2, (long)cnts, 2);
3773192Smckusick 		    patchfil(nfppatch - 2, (long)pfcnt, 2);
3783192Smckusick 	    }
3793192Smckusick #	endif OBJ
3803192Smckusick #	ifdef PC
3813192Smckusick 	    if ( fp -> class == PROG && monflg ) {
3823192Smckusick 		putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
3833192Smckusick 			, "_PMFLUSH" );
3843192Smckusick 		putleaf( P2ICON , cnts , 0 , P2INT , 0 );
3853192Smckusick 		putleaf( P2ICON , pfcnt , 0 , P2INT , 0 );
3863192Smckusick 		putop( P2LISTOP , P2INT );
3873837Speter 		putLV( PCPCOUNT , 0 , 0 , NGLOBAL , P2INT );
3883192Smckusick 		putop( P2LISTOP , P2INT );
3893192Smckusick 		putop( P2CALL , P2INT );
3903192Smckusick 		putdot( filename , line );
3913192Smckusick 	    }
3923192Smckusick #	endif PC
3937953Speter 	/*
3947953Speter 	 * Clean up the symbol table displays and check for unresolves
3957953Speter 	 */
3967953Speter 	line = endline;
3973192Smckusick 	if (fp->class == PROG && inp == 0 && (input->nl_flags & (NUSED|NMOD)) != 0) {
3983192Smckusick 		recovered();
3993192Smckusick 		error("Input is used but not defined in the program statement");
4003192Smckusick 	}
4017953Speter 	if (fp->class == PROG && out == 0 && (output->nl_flags & (NUSED|NMOD)) != 0) {
4027953Speter 		recovered();
4037953Speter 		error("Output is used but not defined in the program statement");
4047953Speter 	}
4053192Smckusick 	b = cbn;
4063192Smckusick 	Fp = fp;
4073192Smckusick 	chkref = syneflg == errcnt[cbn] && opt('w') == 0;
4083192Smckusick 	for (i = 0; i <= 077; i++) {
4093192Smckusick 		for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) {
4103192Smckusick 			/*
4113192Smckusick 			 * Check for variables defined
4123192Smckusick 			 * but not referenced
4133192Smckusick 			 */
4143192Smckusick 			if (chkref && p->symbol != NIL)
4153192Smckusick 			switch (p->class) {
4163192Smckusick 				case FIELD:
4173192Smckusick 					/*
4183192Smckusick 					 * If the corresponding record is
4193192Smckusick 					 * unused, we shouldn't complain about
4203192Smckusick 					 * the fields.
4213192Smckusick 					 */
4223192Smckusick 				default:
4233192Smckusick 					if ((p->nl_flags & (NUSED|NMOD)) == 0) {
4243192Smckusick 						warning();
4253192Smckusick 						nerror("%s %s is neither used nor set", classes[p->class], p->symbol);
4263192Smckusick 						break;
4273192Smckusick 					}
4283192Smckusick 					/*
4293192Smckusick 					 * If a var parameter is either
4303192Smckusick 					 * modified or used that is enough.
4313192Smckusick 					 */
4323192Smckusick 					if (p->class == REF)
4333192Smckusick 						continue;
4343192Smckusick #					ifdef OBJ
4353192Smckusick 					    if ((p->nl_flags & NUSED) == 0) {
4363192Smckusick 						warning();
4373192Smckusick 						nerror("%s %s is never used", classes[p->class], p->symbol);
4383192Smckusick 						break;
4393192Smckusick 					    }
4403192Smckusick #					endif OBJ
4413192Smckusick #					ifdef PC
4423837Speter 					    if (((p->nl_flags & NUSED) == 0) && ((p->extra_flags & NEXTERN) == 0)) {
4433192Smckusick 						warning();
4443192Smckusick 						nerror("%s %s is never used", classes[p->class], p->symbol);
4453192Smckusick 						break;
4463192Smckusick 					    }
4473192Smckusick #					endif PC
4483192Smckusick 					if ((p->nl_flags & NMOD) == 0) {
4493192Smckusick 						warning();
4503192Smckusick 						nerror("%s %s is used but never set", classes[p->class], p->symbol);
4513192Smckusick 						break;
4523192Smckusick 					}
4533192Smckusick 				case LABEL:
4543192Smckusick 				case FVAR:
4553192Smckusick 				case BADUSE:
4563192Smckusick 					break;
4573192Smckusick 			}
4583192Smckusick 			switch (p->class) {
4593192Smckusick 				case BADUSE:
4603192Smckusick 					cp = "s";
4613192Smckusick 					if (p->chain->ud_next == NIL)
4623192Smckusick 						cp++;
4633192Smckusick 					eholdnl();
4643192Smckusick 					if (p->value[NL_KINDS] & ISUNDEF)
4653192Smckusick 						nerror("%s undefined on line%s", p->symbol, cp);
4663192Smckusick 					else
4673192Smckusick 						nerror("%s improperly used on line%s", p->symbol, cp);
4683192Smckusick 					pnumcnt = 10;
4693192Smckusick 					pnums(p->chain);
4703192Smckusick 					pchr('\n');
4713192Smckusick 					break;
4723192Smckusick 
4733192Smckusick 				case FUNC:
4743192Smckusick 				case PROC:
4753192Smckusick #					ifdef OBJ
4763192Smckusick 					    if ((p->nl_flags & NFORWD))
4773192Smckusick 						nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol);
4783192Smckusick #					endif OBJ
4793192Smckusick #					ifdef PC
4803837Speter 					    if ((p->nl_flags & NFORWD) && ((p->extra_flags & NEXTERN) == 0))
4813192Smckusick 						nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol);
4823192Smckusick #					endif PC
4833192Smckusick 					break;
4843192Smckusick 
4853192Smckusick 				case LABEL:
4863192Smckusick 					if (p->nl_flags & NFORWD)
4873192Smckusick 						nerror("label %s was declared but not defined", p->symbol);
4883192Smckusick 					break;
4893192Smckusick 				case FVAR:
4903192Smckusick 					if ((p->nl_flags & NMOD) == 0)
4913192Smckusick 						nerror("No assignment to the function variable");
4923192Smckusick 					break;
4933192Smckusick 			}
4943192Smckusick 		}
4953192Smckusick 		/*
4963192Smckusick 		 * Pop this symbol
4973192Smckusick 		 * table slot
4983192Smckusick 		 */
4993192Smckusick 		disptab[i] = p;
5003192Smckusick 	}
5013192Smckusick 
5023192Smckusick #	ifdef OBJ
5033192Smckusick 	    put(1, O_END);
5043192Smckusick #	endif OBJ
5053192Smckusick #	ifdef PC
5063192Smckusick 		/*
5073192Smckusick 		 *	if there were file variables declared at this level
5089127Smckusick 		 *	call PCLOSE( ap ) to clean them up.
5093192Smckusick 		 */
5103192Smckusick 	    if ( dfiles[ cbn ] ) {
5113192Smckusick 		putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
5123192Smckusick 			, "_PCLOSE" );
5139127Smckusick 		putleaf( P2REG , 0 , P2AP , ADDTYPE( P2CHAR , P2PTR ) , 0 );
5143192Smckusick 		putop( P2CALL , P2INT );
5153192Smckusick 		putdot( filename , line );
5163192Smckusick 	    }
5173192Smckusick 		/*
5183192Smckusick 		 *	if this is a function,
5193192Smckusick 		 *	the function variable is the return value.
5203192Smckusick 		 *	if it's a scalar valued function, return scalar,
5213192Smckusick 		 *	else, return a pointer to the structure value.
5223192Smckusick 		 */
5233192Smckusick 	    if ( fp -> class == FUNC ) {
5243192Smckusick 		struct nl	*fvar = fp -> ptr[ NL_FVAR ];
5253192Smckusick 		long		fvartype = p2type( fvar -> type );
5263192Smckusick 		long		label;
5273192Smckusick 		char		labelname[ BUFSIZ ];
5283192Smckusick 
5293192Smckusick 		switch ( classify( fvar -> type ) ) {
5303192Smckusick 		    case TBOOL:
5313192Smckusick 		    case TCHAR:
5323192Smckusick 		    case TINT:
5333192Smckusick 		    case TSCAL:
5343192Smckusick 		    case TDOUBLE:
5353192Smckusick 		    case TPTR:
5363837Speter 			putRV( fvar -> symbol , ( fvar -> nl_block ) & 037 ,
5373837Speter 				fvar -> value[ NL_OFFS ] ,
5383837Speter 				fvar -> extra_flags ,
5393837Speter 				fvartype );
5403192Smckusick 			break;
5413192Smckusick 		    default:
5423192Smckusick 			label = getlab();
5433192Smckusick 			sprintf( labelname , PREFIXFORMAT ,
5443192Smckusick 				LABELPREFIX , label );
5453192Smckusick 			putprintf( "	.data" , 0 );
5463192Smckusick 			putprintf( "	.lcomm	%s,%d" , 0 ,
5473192Smckusick 				    labelname , lwidth( fvar -> type ) );
5483192Smckusick 			putprintf( "	.text" , 0 );
5493192Smckusick 			putleaf( P2NAME , 0 , 0 , fvartype , labelname );
5503837Speter 			putLV( fvar -> symbol , ( fvar -> nl_block ) & 037 ,
5513837Speter 				fvar -> value[ NL_OFFS ] ,
5523837Speter 				fvar -> extra_flags ,
5533837Speter 				fvartype );
5543192Smckusick 			putstrop( P2STASG , fvartype , lwidth( fvar -> type ) ,
5553192Smckusick 				align( fvar -> type ) );
5563192Smckusick 			putdot( filename , line );
5573192Smckusick 			putleaf( P2ICON , 0 , 0 , fvartype , labelname );
5583192Smckusick 			break;
5593192Smckusick 		}
5603192Smckusick 		putop( P2FORCE , fvartype );
5613192Smckusick 		putdot( filename , line );
5623192Smckusick 	    }
5633192Smckusick 		/*
5649127Smckusick 		 *	if there are nested procedures we must save the display.
5653192Smckusick 		 */
5669127Smckusick 	    if ( parts[ cbn ] & NONLOCALVAR ) {
5679127Smckusick 		    /*
5689127Smckusick 		     *	restore old display entry from save area
5699127Smckusick 		     */
5709127Smckusick 		putprintf( "	movq	%d(%s),%s+%d" , 0
5719127Smckusick 		    , DSAVEOFFSET , P2FPNAME
5729127Smckusick 		    , DISPLAYNAME , cbn * sizeof(struct dispsave) );
5739127Smckusick 	    }
5743192Smckusick 	    stabrbrac( cbn );
5753192Smckusick 	    putprintf( "	ret" , 0 );
5763192Smckusick 		/*
5773192Smckusick 		 *	let the second pass allocate locals
5783279Smckusic 		 * 	and registers
5793192Smckusick 		 */
5803279Smckusic 	    putprintf( "	.set	" , 1 );
5813279Smckusic 	    putprintf( PREFIXFORMAT , 1 , LABELPREFIX , savlabel );
5823279Smckusic 	    putprintf( ", 0x%x" , 0 , savmask() );
5833192Smckusick 	    putrbracket( ftnno );
5843192Smckusick 		/*
5853428Speter 		 *  put down the entry point for formal calls
5863428Speter 		 *  the arguments for FCALL have been passed to us
5873428Speter 		 *  as hidden parameters after the regular arguments.
5883428Speter 		 */
5893428Speter 	    if ( fp -> class != PROG ) {
5903428Speter 		putprintf( "%s%s:" , 0 , FORMALPREFIX , extname );
5913428Speter 		putprintf( "	.word	" , 1 );
5923428Speter 		putprintf( PREFIXFORMAT , 0 , LABELPREFIX , savlabel );
5933428Speter 		putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) ,
5943428Speter 			"_FCALL" );
5953428Speter 		putRV( 0 , cbn ,
5963428Speter 		    fp -> value[ NL_OFFS ] + sizeof( struct formalrtn * ) ,
5973837Speter 		    NPARAM ,
5983428Speter 		    P2PTR | P2STRTY );
5993837Speter 		putRV( 0 , cbn , fp -> value[ NL_OFFS ] ,
6003837Speter 			NPARAM , P2PTR|P2STRTY );
6013428Speter 		putop( P2LISTOP , P2INT );
6023428Speter 		putop( P2CALL , P2INT );
6033428Speter 		putdot( filename , line );
6049127Smckusick 		putjbr( toplabel );
6053428Speter 	    }
6063428Speter 		/*
6073192Smckusick 		 *	declare pcp counters, if any
6083192Smckusick 		 */
6093192Smckusick 	    if ( monflg && fp -> class == PROG ) {
6103192Smckusick 		putprintf( "	.data" , 0 );
6113192Smckusick 		putprintf( "	.comm	" , 1 );
6123192Smckusick 		putprintf( PCPCOUNT , 1 );
6133192Smckusick 		putprintf( ",%d" , 0 , ( cnts + 1 ) * sizeof (long) );
6143192Smckusick 		putprintf( "	.text" , 0 );
6153192Smckusick 	    }
6163192Smckusick #	endif PC
6173192Smckusick #ifdef DEBUG
6183192Smckusick 	dumpnl(fp->ptr[2], fp->symbol);
6193192Smckusick #endif
6205654Slinton 
6215654Slinton #ifdef OBJ
6223192Smckusick 	/*
6235654Slinton 	 * save the namelist for the debugger pdx
6245654Slinton 	 */
6255654Slinton 
6265654Slinton 	savenl(fp->ptr[2], fp->symbol);
6275654Slinton #endif
6285654Slinton 
6295654Slinton 	/*
6303192Smckusick 	 * Restore the
6313192Smckusick 	 * (virtual) name list
6323192Smckusick 	 * position
6333192Smckusick 	 */
6343192Smckusick 	nlfree(fp->ptr[2]);
6353192Smckusick 	/*
6363192Smckusick 	 * Proc/func has been
6373192Smckusick 	 * resolved
6383192Smckusick 	 */
6393192Smckusick 	fp->nl_flags &= ~NFORWD;
6403192Smckusick 	/*
6413192Smckusick 	 * Patch the beg
6423192Smckusick 	 * of the proc/func to
6433192Smckusick 	 * the proper variable size
6443192Smckusick 	 */
6453192Smckusick 	if (Fp == NIL)
6463192Smckusick 		elineon();
6473192Smckusick #	ifdef OBJ
6483192Smckusick 	    patchfil(var, (long)(-sizes[cbn].om_max), 2);
6493192Smckusick #	endif OBJ
6503192Smckusick 	cbn--;
6513192Smckusick 	if (inpflist(fp->symbol)) {
6523192Smckusick 		opop('l');
6533192Smckusick 	}
6543192Smckusick }
6553363Speter 
6563363Speter #ifdef PC
6573363Speter     /*
6583363Speter      *	construct the long name of a function based on it's static nesting.
6593363Speter      *	into a caller-supplied buffer (that should be about BUFSIZ big).
6603363Speter      */
6613363Speter sextname( buffer , name , level )
6623363Speter     char	buffer[];
6633363Speter     char	*name;
6643363Speter     int		level;
6653363Speter {
6663363Speter     char	*starthere;
6673363Speter     int	i;
6683363Speter 
6693363Speter     starthere = &buffer[0];
6703363Speter     for ( i = 1 ; i < level ; i++ ) {
6713363Speter 	sprintf( starthere , EXTFORMAT , enclosing[ i ] );
6723363Speter 	starthere += strlen( enclosing[ i ] ) + 1;
6733363Speter     }
6743367Speter     sprintf( starthere , EXTFORMAT , name );
6753367Speter     starthere += strlen( name ) + 1;
6763363Speter     if ( starthere >= &buffer[ BUFSIZ ] ) {
6773363Speter 	panic( "sextname" );
6783363Speter     }
6793363Speter }
6803363Speter #endif PC
681