xref: /csrg-svn/usr.bin/pascal/src/fdec.c (revision 825)
1 /* Copyright (c) 1979 Regents of the University of California */
2 
3 static	char sccsid[] = "@(#)fdec.c 1.2 08/31/80";
4 
5 #include "whoami.h"
6 #include "0.h"
7 #include "tree.h"
8 #include "opcode.h"
9 #include "objfmt.h"
10 #include "align.h"
11 
12 /*
13  * this array keeps the pxp counters associated with
14  * functions and procedures, so that they can be output
15  * when their bodies are encountered
16  */
17 int	bodycnts[ DSPLYSZ ];
18 
19 #ifdef PC
20 #   include "pc.h"
21 #   include "pcops.h"
22 #endif PC
23 
24 #ifdef OBJ
25 int	cntpatch;
26 int	nfppatch;
27 #endif OBJ
28 
29 /*
30  * Funchdr inserts
31  * declaration of a the
32  * prog/proc/func into the
33  * namelist. It also handles
34  * the arguments and puts out
35  * a transfer which defines
36  * the entry point of a procedure.
37  */
38 
39 struct nl *
40 funchdr(r)
41 	int *r;
42 {
43 	register struct nl *p;
44 	register *il, **rl;
45 	int *rll;
46 	struct nl *cp, *dp, *sp;
47 	int s, o, *pp;
48 
49 	if (inpflist(r[2])) {
50 		opush('l');
51 		yyretrieve();	/* kludge */
52 	}
53 	pfcnt++;
54 	line = r[1];
55 	if (r[3] == NIL && (p=lookup1(r[2])) != NIL && bn == cbn) {
56 		/*
57 		 * Symbol already defined
58 		 * in this block. it is either
59 		 * a redeclared symbol (error)
60 		 * a forward declaration,
61 		 * or an external declaration.
62 		 */
63 		if ((p->class == FUNC || p->class == PROC) && (p->nl_flags & NFORWD) != 0) {
64 			/*
65 			 * Grammar doesnt forbid
66 			 * types on a resolution
67 			 * of a forward function
68 			 * declaration.
69 			 */
70 			if (p->class == FUNC && r[4])
71 				error("Function type should be given only in forward declaration");
72 			/*
73 			 * get another counter for the actual
74 			 */
75 			if ( monflg ) {
76 			    bodycnts[ cbn ] = getcnt();
77 			}
78 #			ifdef PC
79 			    enclosing[ cbn ] = p -> symbol;
80 #			endif PC
81 #			ifdef PTREE
82 				/*
83 				 *	mark this proc/func as forward
84 				 *	in the pTree.
85 				 */
86 			    pDEF( p -> inTree ).PorFForward = TRUE;
87 #			endif PTREE
88 			return (p);
89 		}
90 	}
91 
92 	/* if a routine segment is being compiled,
93 	 * do level one processing.
94 	 */
95 
96 	 if ((r[0] != T_PROG) && (!progseen))
97 		level1();
98 
99 
100 	/*
101 	 * Declare the prog/proc/func
102 	 */
103 	switch (r[0]) {
104 	    case T_PROG:
105 		    progseen++;
106 		    if (opt('z'))
107 			    monflg++;
108 		    program = p = defnl(r[2], PROG, 0, 0);
109 		    p->value[3] = r[1];
110 		    break;
111 	    case T_PDEC:
112 		    if (r[4] != NIL)
113 			    error("Procedures do not have types, only functions do");
114 		    p = enter(defnl(r[2], PROC, 0, 0));
115 		    p->nl_flags |= NMOD;
116 #		    ifdef PC
117 			enclosing[ cbn ] = r[2];
118 #		    endif PC
119 		    break;
120 	    case T_FDEC:
121 		    il = r[4];
122 		    if (il == NIL)
123 			    error("Function type must be specified");
124 		    else if (il[0] != T_TYID) {
125 			    il = NIL;
126 			    error("Function type can be specified only by using a type identifier");
127 		    } else
128 			    il = gtype(il);
129 		    p = enter(defnl(r[2], FUNC, il, NIL));
130 		    p->nl_flags |= NMOD;
131 		    /*
132 		     * An arbitrary restriction
133 		     */
134 		    switch (o = classify(p->type)) {
135 			    case TFILE:
136 			    case TARY:
137 			    case TREC:
138 			    case TSET:
139 			    case TSTR:
140 				    warning();
141 				    if (opt('s'))
142 					    standard();
143 				    error("Functions should not return %ss", clnames[o]);
144 		    }
145 #		    ifdef PC
146 			enclosing[ cbn ] = r[2];
147 #		    endif PC
148 		    break;
149 	    default:
150 		    panic("funchdr");
151 	}
152 	if (r[0] != T_PROG) {
153 		/*
154 		 * Mark this proc/func as
155 		 * being forward declared
156 		 */
157 		p->nl_flags |= NFORWD;
158 		/*
159 		 * Enter the parameters
160 		 * in the next block for
161 		 * the time being
162 		 */
163 		if (++cbn >= DSPLYSZ) {
164 			error("Procedure/function nesting too deep");
165 			pexit(ERRS);
166 		}
167 		/*
168 		 * For functions, the function variable
169 		 */
170 		if (p->class == FUNC) {
171 #			ifdef OBJ
172 			    cp = defnl(r[2], FVAR, p->type, 0);
173 #			endif OBJ
174 #			ifdef PC
175 				/*
176 				 * fvars used to be allocated and deallocated
177 				 * by the caller right before the arguments.
178 				 * the offset of the fvar was kept in
179 				 * value[NL_OFFS] of function (very wierd,
180 				 * but see asgnop).
181 				 * now, they are locals to the function
182 				 * with the offset kept in the fvar.
183 				 */
184 
185 			    cp = defnl( r[2] , FVAR , p -> type
186 				      , -( roundup( DPOFF1+width( p -> type )
187 						  , align( p -> type ) ) ) );
188 #			endif PC
189 			cp->chain = p;
190 			p->ptr[NL_FVAR] = cp;
191 		}
192 		/*
193 		 * Enter the parameters
194 		 * and compute total size
195 		 */
196 		cp = sp = p;
197 
198 #		ifdef OBJ
199 		    o = 0;
200 #		endif OBJ
201 #		ifdef PC
202 			/*
203 			 * parameters used to be allocated backwards,
204 			 * then fixed.  for pc, they are allocated correctly.
205 			 * also, they are aligned.
206 			 */
207 		o = DPOFF2;
208 #		endif PC
209 		for (rl = r[3]; rl != NIL; rl = rl[2]) {
210 			p = NIL;
211 			if (rl[1] == NIL)
212 				continue;
213 			/*
214 			 * Parametric procedures
215 			 * don't have types !?!
216 			 */
217 			if (rl[1][0] != T_PPROC) {
218 				rll = rl[1][2];
219 				if (rll[0] != T_TYID) {
220 					error("Types for arguments can be specified only by using type identifiers");
221 					p = NIL;
222 				} else
223 					p = gtype(rll);
224 			}
225 			for (il = rl[1][1]; il != NIL; il = il[2]) {
226 				switch (rl[1][0]) {
227 				    default:
228 					    panic("funchdr2");
229 				    case T_PVAL:
230 					    if (p != NIL) {
231 						    if (p->class == FILET)
232 							    error("Files cannot be passed by value");
233 						    else if (p->nl_flags & NFILES)
234 							    error("Files cannot be a component of %ss passed by value",
235 								    nameof(p));
236 					    }
237 #					    ifdef OBJ
238 						dp = defnl(il[1], VAR, p, o -= even(width(p)));
239 #					    endif OBJ
240 #					    ifdef PC
241 						dp = defnl( il[1] , VAR , p
242 							, o = roundup( o , A_STACK ) );
243 						o += width( p );
244 #					    endif PC
245 					    dp->nl_flags |= NMOD;
246 					    break;
247 				    case T_PVAR:
248 #					    ifdef OBJ
249 						dp = defnl(il[1], REF, p, o -= sizeof ( int * ) );
250 #					    endif OBJ
251 #					    ifdef PC
252 						dp = defnl( il[1] , REF , p
253 							, o = roundup( o , A_STACK ) );
254 						o += sizeof(char *);
255 #					    endif PC
256 					    break;
257 				    case T_PFUNC:
258 				    case T_PPROC:
259 					    error("Procedure/function parameters not implemented");
260 					    continue;
261 				    }
262 				if (dp != NIL) {
263 					cp->chain = dp;
264 					cp = dp;
265 				}
266 			}
267 		}
268 		cbn--;
269 		p = sp;
270 #		ifdef OBJ
271 		    p->value[NL_OFFS] = -o+DPOFF2;
272 			/*
273 			 * Correct the naivete (naievity)
274 			 * of our above code to
275 			 * calculate offsets
276 			 */
277 		    for (il = p->chain; il != NIL; il = il->chain)
278 			    il->value[NL_OFFS] += p->value[NL_OFFS];
279 #		endif OBJ
280 #		ifdef PC
281 		    p -> value[ NL_OFFS ] = o;
282 #		endif PC
283 	} else {
284 		/*
285 		 * The wonderful
286 		 * program statement!
287 		 */
288 #		ifdef OBJ
289 		    if (monflg) {
290 			    put(1, O_PXPBUF);
291 			    cntpatch = put(2, O_CASE4, 0);
292 			    nfppatch = put(2, O_CASE4, 0);
293 		    }
294 #		endif OBJ
295 		cp = p;
296 		for (rl = r[3]; rl; rl = rl[2]) {
297 			if (rl[1] == NIL)
298 				continue;
299 			dp = defnl(rl[1], VAR, 0, 0);
300 			cp->chain = dp;
301 			cp = dp;
302 		}
303 	}
304 	/*
305 	 * Define a branch at
306 	 * the "entry point" of
307 	 * the prog/proc/func.
308 	 */
309 	p->entloc = getlab();
310 	if (monflg) {
311 		bodycnts[ cbn ] = getcnt();
312 		p->value[ NL_CNTR ] = 0;
313 	}
314 #	ifdef OBJ
315 	    put(2, O_TRA4, p->entloc);
316 #	endif OBJ
317 #	ifdef PTREE
318 	    {
319 		pPointer	PF = tCopy( r );
320 
321 		pSeize( PorFHeader[ nesting ] );
322 		if ( r[0] != T_PROG ) {
323 			pPointer	*PFs;
324 
325 			PFs = &( pDEF( PorFHeader[ nesting ] ).PorFPFs );
326 			*PFs = ListAppend( *PFs , PF );
327 		} else {
328 			pDEF( PorFHeader[ nesting ] ).GlobProg = PF;
329 		}
330 		pRelease( PorFHeader[ nesting ] );
331 	    }
332 #	endif PTREE
333 	return (p);
334 }
335 
336 funcfwd(fp)
337 	struct nl *fp;
338 {
339 
340 	    /*
341 	     *	save the counter for this function
342 	     */
343 	if ( monflg ) {
344 	    fp -> value[ NL_CNTR ] = bodycnts[ cbn ];
345 	}
346 	return (fp);
347 }
348 
349 /*
350  * Funcext marks the procedure or
351  * function external in the symbol
352  * table. Funcext should only be
353  * called if PC, and is an error
354  * otherwise.
355  */
356 
357 funcext(fp)
358 	struct nl *fp;
359 {
360 
361 #ifdef PC
362  	if (opt('s')) {
363 		standard();
364 		error("External procedures and functions are not standard");
365 	} else {
366 		if (cbn == 1) {
367 			fp->ext_flags |= NEXTERN;
368 			stabefunc( fp -> symbol , fp -> class , line );
369 		}
370 		else
371 			error("External procedures and functions can only be declared at the outermost level.");
372 	}
373 #endif PC
374 #ifdef OBJ
375 	error("Procedures or functions cannot be declared external.");
376 #endif OBJ
377 
378 	return(fp);
379 }
380 
381 /*
382  * Funcbody is called
383  * when the actual (resolved)
384  * declaration of a procedure is
385  * encountered. It puts the names
386  * of the (function) and parameters
387  * into the symbol table.
388  */
389 funcbody(fp)
390 	struct nl *fp;
391 {
392 	register struct nl *q, *p;
393 
394 	cbn++;
395 	if (cbn >= DSPLYSZ) {
396 		error("Too many levels of function/procedure nesting");
397 		pexit(ERRS);
398 	}
399 	sizes[cbn].om_max = sizes[cbn].om_off = -DPOFF1;
400 	gotos[cbn] = NIL;
401 	errcnt[cbn] = syneflg;
402 	parts = NIL;
403 	dfiles[ cbn ] = FALSE;
404 	if (fp == NIL)
405 		return (NIL);
406 	/*
407 	 * Save the virtual name
408 	 * list stack pointer so
409 	 * the space can be freed
410 	 * later (funcend).
411 	 */
412 	fp->ptr[2] = nlp;
413 #	ifdef PC
414 	    if ( fp -> class != PROG ) {
415 		stabfunc( fp -> symbol , fp -> class , line , cbn - 1 );
416 	    } else {
417 		stabfunc( "program" , fp -> class , line , 0 );
418 	    }
419 #	endif PC
420 	if (fp->class != PROG) {
421 		for (q = fp->chain; q != NIL; q = q->chain) {
422 			enter(q);
423 #			ifdef PC
424 			    stabparam( q -> symbol , p2type( q -> type )
425 					, q -> value[ NL_OFFS ]
426 					, lwidth( q -> type ) );
427 #			endif PC
428 		}
429 	}
430 	if (fp->class == FUNC) {
431 		/*
432 		 * For functions, enter the fvar
433 		 */
434 		enter(fp->ptr[NL_FVAR]);
435 #		ifdef PC
436 		    q = fp -> ptr[ NL_FVAR ];
437 		    sizes[cbn].om_off -= lwidth( q -> type );
438 		    sizes[cbn].om_max = sizes[cbn].om_off;
439 		    stabvar( q -> symbol , p2type( q -> type ) , cbn
440 			    , q -> value[ NL_OFFS ] , lwidth( q -> type )
441 			    , line );
442 #		endif PC
443 	}
444 #	ifdef PTREE
445 		/*
446 		 *	pick up the pointer to porf declaration
447 		 */
448 	    PorFHeader[ ++nesting ] = fp -> inTree;
449 #	endif PTREE
450 	return (fp);
451 }
452 
453 struct	nl *Fp;
454 int	pnumcnt;
455 /*
456  * Funcend is called to
457  * finish a block by generating
458  * the code for the statements.
459  * It then looks for unresolved declarations
460  * of labels, procedures and functions,
461  * and cleans up the name list.
462  * For the program, it checks the
463  * semantics of the program
464  * statement (yuchh).
465  */
466 funcend(fp, bundle, endline)
467 	struct nl *fp;
468 	int *bundle;
469 	int endline;
470 {
471 	register struct nl *p;
472 	register int i, b;
473 	int var, inp, out, chkref, *blk;
474 	struct nl *iop;
475 	char *cp;
476 	extern int cntstat;
477 #	ifdef PC
478 	    int	toplabel = getlab();
479 	    int	botlabel = getlab();
480 #	endif PC
481 
482 	cntstat = 0;
483 /*
484  *	yyoutline();
485  */
486 	if (program != NIL)
487 		line = program->value[3];
488 	blk = bundle[2];
489 	if (fp == NIL) {
490 		cbn--;
491 #		ifdef PTREE
492 		    nesting--;
493 #		endif PTREE
494 		return;
495 	}
496 #ifdef OBJ
497 	/*
498 	 * Patch the branch to the
499 	 * entry point of the function
500 	 */
501 	patch4(fp->entloc);
502 	/*
503 	 * Put out the block entrance code and the block name.
504 	 * the CONG is overlaid by a patch later!
505 	 */
506 	var = put(2, (lenstr(fp->symbol,0) << 8)
507 			| (cbn == 1 && opt('p') == 0 ? O_NODUMP: O_BEG), 0);
508 	put(2, O_CASE2, bundle[1]);
509 	putstr(fp->symbol, 0);
510 #endif OBJ
511 #ifdef PC
512 	/*
513 	 * put out the procedure entry code
514 	 */
515 	if ( fp -> class == PROG ) {
516 	    putprintf( "	.text" , 0 );
517 	    putprintf( "	.align	1" , 0 );
518 	    putprintf( "	.globl	_main" , 0 );
519 	    putprintf( "_main:" , 0 );
520 	    putprintf( "	.word	0" , 0 );
521 	    putprintf( "	calls	$0,_PCSTART" , 0 );
522 	    putprintf( "	movl	4(ap),__argc" , 0 );
523 	    putprintf( "	movl	8(ap),__argv" , 0 );
524 	    putprintf( "	calls	$0,_program" , 0 );
525 	    putprintf( "	calls	$0,_PCEXIT" , 0 );
526 	    ftnno = fp -> entloc;
527 	    putprintf( "	.text" , 0 );
528 	    putprintf( "	.align	1" , 0 );
529 	    putprintf( "	.globl	_program" , 0 );
530 	    putprintf( "_program:" , 0 );
531 	} else {
532 	    ftnno = fp -> entloc;
533 	    putprintf( "	.text" , 0 );
534 	    putprintf( "	.align	1" , 0 );
535 	    putprintf( "	.globl	" , 1 );
536 	    for ( i = 1 ; i < cbn ; i++ ) {
537 		putprintf( EXTFORMAT , 1 , enclosing[ i ] );
538 	    }
539 	    putprintf( "" , 0 );
540 	    for ( i = 1 ; i < cbn ; i++ ) {
541 		putprintf( EXTFORMAT , 1 , enclosing[ i ] );
542 	    }
543 	    putprintf( ":" , 0 );
544 	}
545 	stablbrac( cbn );
546 	    /*
547 	     *	register save mask
548 	     */
549 	if ( opt( 't' ) ) {
550 	    putprintf( "	.word	0x%x" , 0 , RUNCHECK | RSAVEMASK );
551 	} else {
552 	    putprintf( "	.word	0x%x" , 0 , RSAVEMASK );
553 	}
554 	putjbr( botlabel );
555 	putlab( toplabel );
556 	if ( profflag ) {
557 		/*
558 		 *	call mcount for profiling
559 		 */
560 	    putprintf( "	moval	1f,r0" , 0 );
561 	    putprintf( "	jsb	mcount" , 0 );
562 	    putprintf( "	.data" , 0 );
563 	    putprintf( "	.align	2" , 0 );
564 	    putprintf( "1:" , 0 );
565 	    putprintf( "	.long	0" , 0 );
566 	    putprintf( "	.text" , 0 );
567 	}
568 	    /*
569 	     *	set up unwind exception vector.
570 	     */
571 	putprintf( "	moval	%s,%d(%s)" , 0
572 		, UNWINDNAME , UNWINDOFFSET , P2FPNAME );
573 	    /*
574 	     *	save address of display entry, for unwind.
575 	     */
576 	putprintf( "	moval	%s+%d,%d(%s)" , 0
577 		, DISPLAYNAME , cbn * sizeof(struct dispsave)
578 		, DPTROFFSET , P2FPNAME );
579 	    /*
580 	     *	save old display
581 	     */
582 	putprintf( "	movq	%s+%d,%d(%s)" , 0
583 		, DISPLAYNAME , cbn * sizeof(struct dispsave)
584 		, DSAVEOFFSET , P2FPNAME );
585 	    /*
586 	     *	set up new display by saving AP and FP in appropriate
587 	     *	slot in display structure.
588 	     */
589 	putprintf( "	movq	%s,%s+%d" , 0
590 		, P2APNAME , DISPLAYNAME , cbn * sizeof(struct dispsave) );
591 	    /*
592 	     *	ask second pass to allocate known locals
593 	     */
594 	putlbracket( ftnno , -sizes[ cbn ].om_max );
595 	    /*
596 	     *	and zero them if checking is on
597 	     *	by calling zframe( bytes of locals , highest local address );
598 	     */
599 	if ( opt( 't' ) && ( -sizes[ cbn ].om_max ) > DPOFF1 ) {
600 	    putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
601 		    , "_ZFRAME" );
602 	    putleaf( P2ICON ,  ( -sizes[ cbn ].om_max ) - DPOFF1
603 		    , 0 , P2INT , 0 );
604 	    putLV( 0 , cbn , sizes[ cbn ].om_max , P2CHAR );
605 	    putop( P2LISTOP , P2INT );
606 	    putop( P2CALL , P2INT );
607 	    putdot( filename , line );
608 	}
609 #endif PC
610 	if ( monflg ) {
611 		if ( fp -> value[ NL_CNTR ] != 0 ) {
612 			inccnt( fp -> value [ NL_CNTR ] );
613 		}
614 		inccnt( bodycnts[ fp -> nl_block & 037 ] );
615 	}
616 	if (fp->class == PROG) {
617 		/*
618 		 * The glorious buffers option.
619 		 *          0 = don't buffer output
620 		 *          1 = line buffer output
621 		 *          2 = 512 byte buffer output
622 		 */
623 #		ifdef OBJ
624 		    if (opt('b') != 1)
625 			    put(1, O_BUFF | opt('b') << 8);
626 #		endif OBJ
627 #		ifdef PC
628 		    if ( opt( 'b' ) != 1 ) {
629 			putleaf( P2ICON , 0 , 0
630 				, ADDTYPE( P2FTN | P2INT , P2PTR ) , "_BUFF" );
631 			putleaf( P2ICON , opt( 'b' ) , 0 , P2INT , 0 );
632 			putop( P2CALL , P2INT );
633 			putdot( filename , line );
634 		    }
635 #		endif PC
636 		out = 0;
637 		for (p = fp->chain; p != NIL; p = p->chain) {
638 			if (strcmp(p->symbol, "input") == 0) {
639 				inp++;
640 				continue;
641 			}
642 			if (strcmp(p->symbol, "output") == 0) {
643 				out++;
644 				continue;
645 			}
646 			iop = lookup1(p->symbol);
647 			if (iop == NIL || bn != cbn) {
648 				error("File %s listed in program statement but not declared", p->symbol);
649 				continue;
650 			}
651 			if (iop->class != VAR) {
652 				error("File %s listed in program statement but declared as a %s", p->symbol, classes[iop->class]);
653 				continue;
654 			}
655 			if (iop->type == NIL)
656 				continue;
657 			if (iop->type->class != FILET) {
658 				error("File %s listed in program statement but defined as %s",
659 					p->symbol, nameof(iop->type));
660 				continue;
661 			}
662 #			ifdef OBJ
663 			    put(2, O_LV | bn << 8+INDX, iop->value[NL_OFFS]);
664 			    i = lenstr(p->symbol,0);
665 			    put(2, O_LVCON, i);
666 			    putstr(p->symbol, 0);
667 			    do {
668 				i--;
669 			    } while (p->symbol+i == 0);
670 			    put(2, O_CON24, i+1);
671 			    put(2, O_CON24, text(iop->type) ? 0 : width(iop->type->type));
672 			    put(1, O_DEFNAME);
673 #			endif OBJ
674 #			ifdef PC
675 			    putleaf( P2ICON , 0 , 0
676 				    , ADDTYPE( P2FTN | P2INT , P2PTR )
677 				    , "_DEFNAME" );
678 			    putLV( p -> symbol , bn , iop -> value[NL_OFFS]
679 				    , p2type( iop ) );
680 			    putCONG( p -> symbol , strlen( p -> symbol )
681 				    , LREQ );
682 			    putop( P2LISTOP , P2INT );
683 			    putleaf( P2ICON , strlen( p -> symbol )
684 				    , 0 , P2INT , 0 );
685 			    putop( P2LISTOP , P2INT );
686 			    putleaf( P2ICON
687 				, text(iop->type) ? 0 : width(iop->type->type)
688 				, 0 , P2INT , 0 );
689 			    putop( P2LISTOP , P2INT );
690 			    putop( P2CALL , P2INT );
691 			    putdot( filename , line );
692 #			endif PC
693 		}
694 		if (out == 0 && fp->chain != NIL) {
695 			recovered();
696 			error("The file output must appear in the program statement file list");
697 		}
698 	}
699 	/*
700 	 * Process the prog/proc/func body
701 	 */
702 	noreach = 0;
703 	line = bundle[1];
704 	statlist(blk);
705 #	ifdef PTREE
706 	    {
707 		pPointer Body = tCopy( blk );
708 
709 		pDEF( PorFHeader[ nesting -- ] ).PorFBody = Body;
710 	    }
711 #	endif PTREE
712 #	ifdef OBJ
713 	    if (cbn== 1 && monflg != 0) {
714 		    patchfil(cntpatch - 2, cnts, 2);
715 		    patchfil(nfppatch - 2, pfcnt, 2);
716 	    }
717 #	endif OBJ
718 #	ifdef PC
719 	    if ( fp -> class == PROG && monflg ) {
720 		putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
721 			, "_PMFLUSH" );
722 		putleaf( P2ICON , cnts , 0 , P2INT , 0 );
723 		putleaf( P2ICON , pfcnt , 0 , P2INT , 0 );
724 		putop( P2LISTOP , P2INT );
725 		putop( P2CALL , P2INT );
726 		putdot( filename , line );
727 	    }
728 #	endif PC
729 	if (fp->class == PROG && inp == 0 && (input->nl_flags & (NUSED|NMOD)) != 0) {
730 		recovered();
731 		error("Input is used but not defined in the program statement");
732 	}
733 	/*
734 	 * Clean up the symbol table displays and check for unresolves
735 	 */
736 	line = endline;
737 	b = cbn;
738 	Fp = fp;
739 	chkref = syneflg == errcnt[cbn] && opt('w') == 0;
740 	for (i = 0; i <= 077; i++) {
741 		for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) {
742 			/*
743 			 * Check for variables defined
744 			 * but not referenced
745 			 */
746 			if (chkref && p->symbol != NIL)
747 			switch (p->class) {
748 				case FIELD:
749 					/*
750 					 * If the corresponding record is
751 					 * unused, we shouldn't complain about
752 					 * the fields.
753 					 */
754 				default:
755 					if ((p->nl_flags & (NUSED|NMOD)) == 0) {
756 						warning();
757 						nerror("%s %s is neither used nor set", classes[p->class], p->symbol);
758 						break;
759 					}
760 					/*
761 					 * If a var parameter is either
762 					 * modified or used that is enough.
763 					 */
764 					if (p->class == REF)
765 						continue;
766 #					ifdef OBJ
767 					    if ((p->nl_flags & NUSED) == 0) {
768 						warning();
769 						nerror("%s %s is never used", classes[p->class], p->symbol);
770 						break;
771 					    }
772 #					endif OBJ
773 #					ifdef PC
774 					    if (((p->nl_flags & NUSED) == 0) && ((p->ext_flags & NEXTERN) == 0)) {
775 						warning();
776 						nerror("%s %s is never used", classes[p->class], p->symbol);
777 						break;
778 					    }
779 #					endif PC
780 					if ((p->nl_flags & NMOD) == 0) {
781 						warning();
782 						nerror("%s %s is used but never set", classes[p->class], p->symbol);
783 						break;
784 					}
785 				case LABEL:
786 				case FVAR:
787 				case BADUSE:
788 					break;
789 			}
790 			switch (p->class) {
791 				case BADUSE:
792 					cp = "s";
793 					if (p->chain->ud_next == NIL)
794 						cp++;
795 					eholdnl();
796 					if (p->value[NL_KINDS] & ISUNDEF)
797 						nerror("%s undefined on line%s", p->symbol, cp);
798 					else
799 						nerror("%s improperly used on line%s", p->symbol, cp);
800 					pnumcnt = 10;
801 					pnums(p->chain);
802 					pchr('\n');
803 					break;
804 
805 				case FUNC:
806 				case PROC:
807 #					ifdef OBJ
808 					    if ((p->nl_flags & NFORWD))
809 						nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol);
810 #					endif OBJ
811 #					ifdef PC
812 					    if ((p->nl_flags & NFORWD) && ((p->ext_flags & NEXTERN) == 0))
813 						nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol);
814 #					endif PC
815 					break;
816 
817 				case LABEL:
818 					if (p->nl_flags & NFORWD)
819 						nerror("label %s was declared but not defined", p->symbol);
820 					break;
821 				case FVAR:
822 					if ((p->nl_flags & NMOD) == 0)
823 						nerror("No assignment to the function variable");
824 					break;
825 			}
826 		}
827 		/*
828 		 * Pop this symbol
829 		 * table slot
830 		 */
831 		disptab[i] = p;
832 	}
833 
834 #	ifdef OBJ
835 	    put(1, O_END);
836 #	endif OBJ
837 #	ifdef PC
838 		/*
839 		 *	if there were file variables declared at this level
840 		 *	call pclose( &__disply[ cbn ] ) to clean them up.
841 		 */
842 	    if ( dfiles[ cbn ] ) {
843 		putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
844 			, "_PCLOSE" );
845 		putRV( DISPLAYNAME , 0 , cbn * sizeof( struct dispsave )
846 			, P2PTR | P2CHAR );
847 		putop( P2CALL , P2INT );
848 		putdot( filename , line );
849 	    }
850 		/*
851 		 *	if this is a function,
852 		 *	the function variable is the return value.
853 		 *	if it's a scalar valued function, return scalar,
854 		 *	else, return a pointer to the structure value.
855 		 */
856 	    if ( fp -> class == FUNC ) {
857 		struct nl	*fvar = fp -> ptr[ NL_FVAR ];
858 		long		fvartype = p2type( fvar -> type );
859 
860 		switch ( classify( fvar -> type ) ) {
861 		    case TBOOL:
862 		    case TCHAR:
863 		    case TINT:
864 		    case TSCAL:
865 		    case TDOUBLE:
866 		    case TPTR:
867 			putRV( fvar -> symbol , ( fvar -> nl_block ) & 037
868 				, fvar -> value[ NL_OFFS ] , fvartype );
869 			break;
870 		    default:
871 			putLV( fvar -> symbol , ( fvar -> nl_block ) & 037
872 				, fvar -> value[ NL_OFFS ] , fvartype );
873 			break;
874 		}
875 		putop( P2FORCE , fvartype );
876 		putdot( filename , line );
877 	    }
878 		/*
879 		 *	restore old display entry from save area
880 		 */
881 
882 	    putprintf( "	movq	%d(%s),%s+%d" , 0
883 		, DSAVEOFFSET , P2FPNAME
884 		, DISPLAYNAME , cbn * sizeof(struct dispsave) );
885 	    stabrbrac( cbn );
886 	    putprintf( "	ret" , 0 );
887 		/*
888 		 *	let the second pass allocate locals
889 		 */
890 	    putlab( botlabel );
891 	    putprintf( "	subl2	$LF%d,sp" , 0 , ftnno );
892 	    putrbracket( ftnno );
893 	    putjbr( toplabel );
894 		/*
895 		 *	declare pcp counters, if any
896 		 */
897 	    if ( monflg && fp -> class == PROG ) {
898 		putprintf( "	.data" , 0 );
899 		putprintf( "	.comm	" , 1 );
900 		putprintf( PCPCOUNT , 1 );
901 		putprintf( ",%d" , 0 , ( cnts + 1 ) * sizeof (long) );
902 		putprintf( "	.text" , 0 );
903 	    }
904 #	endif PC
905 #ifdef DEBUG
906 	dumpnl(fp->ptr[2], fp->symbol);
907 #endif
908 	/*
909 	 * Restore the
910 	 * (virtual) name list
911 	 * position
912 	 */
913 	nlfree(fp->ptr[2]);
914 	/*
915 	 * Proc/func has been
916 	 * resolved
917 	 */
918 	fp->nl_flags &= ~NFORWD;
919 	/*
920 	 * Patch the beg
921 	 * of the proc/func to
922 	 * the proper variable size
923 	 */
924 	if (Fp == NIL)
925 		elineon();
926 #	ifdef OBJ
927 	    patchfil(var, sizes[cbn].om_max, 2);
928 #	endif OBJ
929 	cbn--;
930 	if (inpflist(fp->symbol)) {
931 		opop('l');
932 	}
933 }
934 
935 
936 /*
937  * Segend is called to check for
938  * unresolved variables, funcs and
939  * procs, and deliver unresolved and
940  * baduse error diagnostics at the
941  * end of a routine segment (a separately
942  * compiled segment that is not the
943  * main program) for PC. This
944  * routine should only be called
945  * by PC (not standard).
946  */
947  segend()
948  {
949 	register struct nl *p;
950 	register int i,b;
951 	char *cp;
952 
953 #ifdef PC
954 	if (opt('s')) {
955 		standard();
956 		error("Separately compiled routine segments are not standard.");
957 	} else {
958 		b = cbn;
959 		for (i=0; i<077; i++) {
960 			for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) {
961 			switch (p->class) {
962 				case BADUSE:
963 					cp = 's';
964 					if (p->chain->ud_next == NIL)
965 						cp++;
966 					eholdnl();
967 					if (p->value[NL_KINDS] & ISUNDEF)
968 						nerror("%s undefined on line%s", p->symbol, cp);
969 					else
970 						nerror("%s improperly used on line%s", p->symbol, cp);
971 					pnumcnt = 10;
972 					pnums(p->chain);
973 					pchr('\n');
974 					break;
975 
976 				case FUNC:
977 				case PROC:
978 					if ((p->nl_flags & NFORWD) && ((p->ext_flags & NEXTERN) == 0))
979 						nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol);
980 					break;
981 
982 				case FVAR:
983 					if (((p->nl_flags & NMOD) == 0) && ((p->chain->ext_flags & NEXTERN) == 0))
984 						nerror("No assignment to the function variable");
985 					break;
986 			    }
987 			   }
988 			   disptab[i] = p;
989 		    }
990 	}
991 #endif PC
992 #ifdef OBJ
993 	error("Missing program statement and program body");
994 #endif OBJ
995 
996 }
997 
998 
999 /*
1000  * Level1 does level one processing for
1001  * separately compiled routine segments
1002  */
1003 level1()
1004 {
1005 
1006 #	ifdef OBJ
1007 	    error("Missing program statement");
1008 #	endif OBJ
1009 #	ifdef PC
1010 	    if (opt('s')) {
1011 		    standard();
1012 		    error("Missing program statement");
1013 	    }
1014 #	endif PC
1015 
1016 	cbn++;
1017 	sizes[cbn].om_max = sizes[cbn].om_off = -DPOFF1;
1018 	parts = NIL;
1019 	progseen++;
1020 }
1021 
1022 
1023 
1024 pnums(p)
1025 	struct udinfo *p;
1026 {
1027 
1028 	if (p->ud_next != NIL)
1029 		pnums(p->ud_next);
1030 	if (pnumcnt == 0) {
1031 		printf("\n\t");
1032 		pnumcnt = 20;
1033 	}
1034 	pnumcnt--;
1035 	printf(" %d", p->ud_line);
1036 }
1037 
1038 nerror(a1, a2, a3)
1039 {
1040 
1041 	if (Fp != NIL) {
1042 		yySsync();
1043 #ifndef PI1
1044 		if (opt('l'))
1045 			yyoutline();
1046 #endif
1047 		yysetfile(filename);
1048 		printf("In %s %s:\n", classes[Fp->class], Fp->symbol);
1049 		Fp = NIL;
1050 		elineoff();
1051 	}
1052 	error(a1, a2, a3);
1053 }
1054