xref: /csrg-svn/usr.bin/pascal/src/fdec.c (revision 825)
1752Speter /* Copyright (c) 1979 Regents of the University of California */
2752Speter 
3*825Speter static	char sccsid[] = "@(#)fdec.c 1.2 08/31/80";
4752Speter 
5752Speter #include "whoami.h"
6752Speter #include "0.h"
7752Speter #include "tree.h"
8752Speter #include "opcode.h"
9752Speter #include "objfmt.h"
10752Speter #include "align.h"
11752Speter 
12752Speter /*
13752Speter  * this array keeps the pxp counters associated with
14752Speter  * functions and procedures, so that they can be output
15752Speter  * when their bodies are encountered
16752Speter  */
17752Speter int	bodycnts[ DSPLYSZ ];
18752Speter 
19752Speter #ifdef PC
20752Speter #   include "pc.h"
21752Speter #   include "pcops.h"
22752Speter #endif PC
23752Speter 
24752Speter #ifdef OBJ
25752Speter int	cntpatch;
26752Speter int	nfppatch;
27752Speter #endif OBJ
28752Speter 
29752Speter /*
30752Speter  * Funchdr inserts
31752Speter  * declaration of a the
32752Speter  * prog/proc/func into the
33752Speter  * namelist. It also handles
34752Speter  * the arguments and puts out
35752Speter  * a transfer which defines
36752Speter  * the entry point of a procedure.
37752Speter  */
38752Speter 
39752Speter struct nl *
40752Speter funchdr(r)
41752Speter 	int *r;
42752Speter {
43752Speter 	register struct nl *p;
44752Speter 	register *il, **rl;
45752Speter 	int *rll;
46752Speter 	struct nl *cp, *dp, *sp;
47752Speter 	int s, o, *pp;
48752Speter 
49752Speter 	if (inpflist(r[2])) {
50752Speter 		opush('l');
51752Speter 		yyretrieve();	/* kludge */
52752Speter 	}
53752Speter 	pfcnt++;
54752Speter 	line = r[1];
55752Speter 	if (r[3] == NIL && (p=lookup1(r[2])) != NIL && bn == cbn) {
56752Speter 		/*
57752Speter 		 * Symbol already defined
58752Speter 		 * in this block. it is either
59752Speter 		 * a redeclared symbol (error)
60752Speter 		 * a forward declaration,
61752Speter 		 * or an external declaration.
62752Speter 		 */
63752Speter 		if ((p->class == FUNC || p->class == PROC) && (p->nl_flags & NFORWD) != 0) {
64752Speter 			/*
65752Speter 			 * Grammar doesnt forbid
66752Speter 			 * types on a resolution
67752Speter 			 * of a forward function
68752Speter 			 * declaration.
69752Speter 			 */
70752Speter 			if (p->class == FUNC && r[4])
71752Speter 				error("Function type should be given only in forward declaration");
72752Speter 			/*
73752Speter 			 * get another counter for the actual
74752Speter 			 */
75752Speter 			if ( monflg ) {
76752Speter 			    bodycnts[ cbn ] = getcnt();
77752Speter 			}
78752Speter #			ifdef PC
79752Speter 			    enclosing[ cbn ] = p -> symbol;
80752Speter #			endif PC
81752Speter #			ifdef PTREE
82752Speter 				/*
83752Speter 				 *	mark this proc/func as forward
84752Speter 				 *	in the pTree.
85752Speter 				 */
86752Speter 			    pDEF( p -> inTree ).PorFForward = TRUE;
87752Speter #			endif PTREE
88752Speter 			return (p);
89752Speter 		}
90752Speter 	}
91752Speter 
92752Speter 	/* if a routine segment is being compiled,
93752Speter 	 * do level one processing.
94752Speter 	 */
95752Speter 
96752Speter 	 if ((r[0] != T_PROG) && (!progseen))
97752Speter 		level1();
98752Speter 
99752Speter 
100752Speter 	/*
101752Speter 	 * Declare the prog/proc/func
102752Speter 	 */
103752Speter 	switch (r[0]) {
104752Speter 	    case T_PROG:
105752Speter 		    progseen++;
106752Speter 		    if (opt('z'))
107752Speter 			    monflg++;
108752Speter 		    program = p = defnl(r[2], PROG, 0, 0);
109752Speter 		    p->value[3] = r[1];
110752Speter 		    break;
111752Speter 	    case T_PDEC:
112752Speter 		    if (r[4] != NIL)
113752Speter 			    error("Procedures do not have types, only functions do");
114752Speter 		    p = enter(defnl(r[2], PROC, 0, 0));
115752Speter 		    p->nl_flags |= NMOD;
116752Speter #		    ifdef PC
117752Speter 			enclosing[ cbn ] = r[2];
118752Speter #		    endif PC
119752Speter 		    break;
120752Speter 	    case T_FDEC:
121752Speter 		    il = r[4];
122752Speter 		    if (il == NIL)
123752Speter 			    error("Function type must be specified");
124752Speter 		    else if (il[0] != T_TYID) {
125752Speter 			    il = NIL;
126752Speter 			    error("Function type can be specified only by using a type identifier");
127752Speter 		    } else
128752Speter 			    il = gtype(il);
129752Speter 		    p = enter(defnl(r[2], FUNC, il, NIL));
130752Speter 		    p->nl_flags |= NMOD;
131752Speter 		    /*
132752Speter 		     * An arbitrary restriction
133752Speter 		     */
134752Speter 		    switch (o = classify(p->type)) {
135752Speter 			    case TFILE:
136752Speter 			    case TARY:
137752Speter 			    case TREC:
138752Speter 			    case TSET:
139752Speter 			    case TSTR:
140752Speter 				    warning();
141752Speter 				    if (opt('s'))
142752Speter 					    standard();
143752Speter 				    error("Functions should not return %ss", clnames[o]);
144752Speter 		    }
145752Speter #		    ifdef PC
146752Speter 			enclosing[ cbn ] = r[2];
147752Speter #		    endif PC
148752Speter 		    break;
149752Speter 	    default:
150752Speter 		    panic("funchdr");
151752Speter 	}
152752Speter 	if (r[0] != T_PROG) {
153752Speter 		/*
154752Speter 		 * Mark this proc/func as
155752Speter 		 * being forward declared
156752Speter 		 */
157752Speter 		p->nl_flags |= NFORWD;
158752Speter 		/*
159752Speter 		 * Enter the parameters
160752Speter 		 * in the next block for
161752Speter 		 * the time being
162752Speter 		 */
163752Speter 		if (++cbn >= DSPLYSZ) {
164752Speter 			error("Procedure/function nesting too deep");
165752Speter 			pexit(ERRS);
166752Speter 		}
167752Speter 		/*
168752Speter 		 * For functions, the function variable
169752Speter 		 */
170752Speter 		if (p->class == FUNC) {
171752Speter #			ifdef OBJ
172752Speter 			    cp = defnl(r[2], FVAR, p->type, 0);
173752Speter #			endif OBJ
174752Speter #			ifdef PC
175752Speter 				/*
176752Speter 				 * fvars used to be allocated and deallocated
177752Speter 				 * by the caller right before the arguments.
178752Speter 				 * the offset of the fvar was kept in
179752Speter 				 * value[NL_OFFS] of function (very wierd,
180752Speter 				 * but see asgnop).
181752Speter 				 * now, they are locals to the function
182752Speter 				 * with the offset kept in the fvar.
183752Speter 				 */
184752Speter 
185752Speter 			    cp = defnl( r[2] , FVAR , p -> type
186752Speter 				      , -( roundup( DPOFF1+width( p -> type )
187752Speter 						  , align( p -> type ) ) ) );
188752Speter #			endif PC
189752Speter 			cp->chain = p;
190752Speter 			p->ptr[NL_FVAR] = cp;
191752Speter 		}
192752Speter 		/*
193752Speter 		 * Enter the parameters
194752Speter 		 * and compute total size
195752Speter 		 */
196752Speter 		cp = sp = p;
197752Speter 
198752Speter #		ifdef OBJ
199752Speter 		    o = 0;
200752Speter #		endif OBJ
201752Speter #		ifdef PC
202752Speter 			/*
203752Speter 			 * parameters used to be allocated backwards,
204752Speter 			 * then fixed.  for pc, they are allocated correctly.
205752Speter 			 * also, they are aligned.
206752Speter 			 */
207752Speter 		o = DPOFF2;
208752Speter #		endif PC
209752Speter 		for (rl = r[3]; rl != NIL; rl = rl[2]) {
210752Speter 			p = NIL;
211752Speter 			if (rl[1] == NIL)
212752Speter 				continue;
213752Speter 			/*
214752Speter 			 * Parametric procedures
215752Speter 			 * don't have types !?!
216752Speter 			 */
217752Speter 			if (rl[1][0] != T_PPROC) {
218752Speter 				rll = rl[1][2];
219752Speter 				if (rll[0] != T_TYID) {
220752Speter 					error("Types for arguments can be specified only by using type identifiers");
221752Speter 					p = NIL;
222752Speter 				} else
223752Speter 					p = gtype(rll);
224752Speter 			}
225752Speter 			for (il = rl[1][1]; il != NIL; il = il[2]) {
226752Speter 				switch (rl[1][0]) {
227752Speter 				    default:
228752Speter 					    panic("funchdr2");
229752Speter 				    case T_PVAL:
230752Speter 					    if (p != NIL) {
231752Speter 						    if (p->class == FILET)
232752Speter 							    error("Files cannot be passed by value");
233752Speter 						    else if (p->nl_flags & NFILES)
234752Speter 							    error("Files cannot be a component of %ss passed by value",
235752Speter 								    nameof(p));
236752Speter 					    }
237752Speter #					    ifdef OBJ
238752Speter 						dp = defnl(il[1], VAR, p, o -= even(width(p)));
239752Speter #					    endif OBJ
240752Speter #					    ifdef PC
241752Speter 						dp = defnl( il[1] , VAR , p
242752Speter 							, o = roundup( o , A_STACK ) );
243752Speter 						o += width( p );
244752Speter #					    endif PC
245752Speter 					    dp->nl_flags |= NMOD;
246752Speter 					    break;
247752Speter 				    case T_PVAR:
248752Speter #					    ifdef OBJ
249752Speter 						dp = defnl(il[1], REF, p, o -= sizeof ( int * ) );
250752Speter #					    endif OBJ
251752Speter #					    ifdef PC
252752Speter 						dp = defnl( il[1] , REF , p
253752Speter 							, o = roundup( o , A_STACK ) );
254752Speter 						o += sizeof(char *);
255752Speter #					    endif PC
256752Speter 					    break;
257752Speter 				    case T_PFUNC:
258752Speter 				    case T_PPROC:
259752Speter 					    error("Procedure/function parameters not implemented");
260752Speter 					    continue;
261752Speter 				    }
262752Speter 				if (dp != NIL) {
263752Speter 					cp->chain = dp;
264752Speter 					cp = dp;
265752Speter 				}
266752Speter 			}
267752Speter 		}
268752Speter 		cbn--;
269752Speter 		p = sp;
270752Speter #		ifdef OBJ
271752Speter 		    p->value[NL_OFFS] = -o+DPOFF2;
272752Speter 			/*
273752Speter 			 * Correct the naivete (naievity)
274752Speter 			 * of our above code to
275752Speter 			 * calculate offsets
276752Speter 			 */
277752Speter 		    for (il = p->chain; il != NIL; il = il->chain)
278752Speter 			    il->value[NL_OFFS] += p->value[NL_OFFS];
279752Speter #		endif OBJ
280752Speter #		ifdef PC
281752Speter 		    p -> value[ NL_OFFS ] = o;
282752Speter #		endif PC
283752Speter 	} else {
284752Speter 		/*
285752Speter 		 * The wonderful
286752Speter 		 * program statement!
287752Speter 		 */
288752Speter #		ifdef OBJ
289752Speter 		    if (monflg) {
290752Speter 			    put(1, O_PXPBUF);
291752Speter 			    cntpatch = put(2, O_CASE4, 0);
292752Speter 			    nfppatch = put(2, O_CASE4, 0);
293752Speter 		    }
294752Speter #		endif OBJ
295752Speter 		cp = p;
296752Speter 		for (rl = r[3]; rl; rl = rl[2]) {
297752Speter 			if (rl[1] == NIL)
298752Speter 				continue;
299752Speter 			dp = defnl(rl[1], VAR, 0, 0);
300752Speter 			cp->chain = dp;
301752Speter 			cp = dp;
302752Speter 		}
303752Speter 	}
304752Speter 	/*
305752Speter 	 * Define a branch at
306752Speter 	 * the "entry point" of
307752Speter 	 * the prog/proc/func.
308752Speter 	 */
309752Speter 	p->entloc = getlab();
310752Speter 	if (monflg) {
311752Speter 		bodycnts[ cbn ] = getcnt();
312752Speter 		p->value[ NL_CNTR ] = 0;
313752Speter 	}
314752Speter #	ifdef OBJ
315752Speter 	    put(2, O_TRA4, p->entloc);
316752Speter #	endif OBJ
317752Speter #	ifdef PTREE
318752Speter 	    {
319752Speter 		pPointer	PF = tCopy( r );
320752Speter 
321752Speter 		pSeize( PorFHeader[ nesting ] );
322752Speter 		if ( r[0] != T_PROG ) {
323752Speter 			pPointer	*PFs;
324752Speter 
325752Speter 			PFs = &( pDEF( PorFHeader[ nesting ] ).PorFPFs );
326752Speter 			*PFs = ListAppend( *PFs , PF );
327752Speter 		} else {
328752Speter 			pDEF( PorFHeader[ nesting ] ).GlobProg = PF;
329752Speter 		}
330752Speter 		pRelease( PorFHeader[ nesting ] );
331752Speter 	    }
332752Speter #	endif PTREE
333752Speter 	return (p);
334752Speter }
335752Speter 
336752Speter funcfwd(fp)
337752Speter 	struct nl *fp;
338752Speter {
339752Speter 
340752Speter 	    /*
341752Speter 	     *	save the counter for this function
342752Speter 	     */
343752Speter 	if ( monflg ) {
344752Speter 	    fp -> value[ NL_CNTR ] = bodycnts[ cbn ];
345752Speter 	}
346752Speter 	return (fp);
347752Speter }
348752Speter 
349752Speter /*
350752Speter  * Funcext marks the procedure or
351752Speter  * function external in the symbol
352752Speter  * table. Funcext should only be
353752Speter  * called if PC, and is an error
354752Speter  * otherwise.
355752Speter  */
356752Speter 
357752Speter funcext(fp)
358752Speter 	struct nl *fp;
359752Speter {
360752Speter 
361752Speter #ifdef PC
362752Speter  	if (opt('s')) {
363752Speter 		standard();
364752Speter 		error("External procedures and functions are not standard");
365752Speter 	} else {
366752Speter 		if (cbn == 1) {
367752Speter 			fp->ext_flags |= NEXTERN;
368*825Speter 			stabefunc( fp -> symbol , fp -> class , line );
369752Speter 		}
370752Speter 		else
371752Speter 			error("External procedures and functions can only be declared at the outermost level.");
372752Speter 	}
373752Speter #endif PC
374752Speter #ifdef OBJ
375752Speter 	error("Procedures or functions cannot be declared external.");
376752Speter #endif OBJ
377752Speter 
378752Speter 	return(fp);
379752Speter }
380752Speter 
381752Speter /*
382752Speter  * Funcbody is called
383752Speter  * when the actual (resolved)
384752Speter  * declaration of a procedure is
385752Speter  * encountered. It puts the names
386752Speter  * of the (function) and parameters
387752Speter  * into the symbol table.
388752Speter  */
389752Speter funcbody(fp)
390752Speter 	struct nl *fp;
391752Speter {
392752Speter 	register struct nl *q, *p;
393752Speter 
394752Speter 	cbn++;
395752Speter 	if (cbn >= DSPLYSZ) {
396752Speter 		error("Too many levels of function/procedure nesting");
397752Speter 		pexit(ERRS);
398752Speter 	}
399752Speter 	sizes[cbn].om_max = sizes[cbn].om_off = -DPOFF1;
400752Speter 	gotos[cbn] = NIL;
401752Speter 	errcnt[cbn] = syneflg;
402752Speter 	parts = NIL;
403752Speter 	dfiles[ cbn ] = FALSE;
404752Speter 	if (fp == NIL)
405752Speter 		return (NIL);
406752Speter 	/*
407752Speter 	 * Save the virtual name
408752Speter 	 * list stack pointer so
409752Speter 	 * the space can be freed
410752Speter 	 * later (funcend).
411752Speter 	 */
412752Speter 	fp->ptr[2] = nlp;
413752Speter #	ifdef PC
414752Speter 	    if ( fp -> class != PROG ) {
415*825Speter 		stabfunc( fp -> symbol , fp -> class , line , cbn - 1 );
416752Speter 	    } else {
417*825Speter 		stabfunc( "program" , fp -> class , line , 0 );
418752Speter 	    }
419752Speter #	endif PC
420752Speter 	if (fp->class != PROG) {
421752Speter 		for (q = fp->chain; q != NIL; q = q->chain) {
422752Speter 			enter(q);
423752Speter #			ifdef PC
424752Speter 			    stabparam( q -> symbol , p2type( q -> type )
425752Speter 					, q -> value[ NL_OFFS ]
426752Speter 					, lwidth( q -> type ) );
427752Speter #			endif PC
428752Speter 		}
429752Speter 	}
430752Speter 	if (fp->class == FUNC) {
431752Speter 		/*
432752Speter 		 * For functions, enter the fvar
433752Speter 		 */
434752Speter 		enter(fp->ptr[NL_FVAR]);
435752Speter #		ifdef PC
436752Speter 		    q = fp -> ptr[ NL_FVAR ];
437752Speter 		    sizes[cbn].om_off -= lwidth( q -> type );
438752Speter 		    sizes[cbn].om_max = sizes[cbn].om_off;
439*825Speter 		    stabvar( q -> symbol , p2type( q -> type ) , cbn
440*825Speter 			    , q -> value[ NL_OFFS ] , lwidth( q -> type )
441*825Speter 			    , line );
442752Speter #		endif PC
443752Speter 	}
444752Speter #	ifdef PTREE
445752Speter 		/*
446752Speter 		 *	pick up the pointer to porf declaration
447752Speter 		 */
448752Speter 	    PorFHeader[ ++nesting ] = fp -> inTree;
449752Speter #	endif PTREE
450752Speter 	return (fp);
451752Speter }
452752Speter 
453752Speter struct	nl *Fp;
454752Speter int	pnumcnt;
455752Speter /*
456752Speter  * Funcend is called to
457752Speter  * finish a block by generating
458752Speter  * the code for the statements.
459752Speter  * It then looks for unresolved declarations
460752Speter  * of labels, procedures and functions,
461752Speter  * and cleans up the name list.
462752Speter  * For the program, it checks the
463752Speter  * semantics of the program
464752Speter  * statement (yuchh).
465752Speter  */
466752Speter funcend(fp, bundle, endline)
467752Speter 	struct nl *fp;
468752Speter 	int *bundle;
469752Speter 	int endline;
470752Speter {
471752Speter 	register struct nl *p;
472752Speter 	register int i, b;
473752Speter 	int var, inp, out, chkref, *blk;
474752Speter 	struct nl *iop;
475752Speter 	char *cp;
476752Speter 	extern int cntstat;
477752Speter #	ifdef PC
478752Speter 	    int	toplabel = getlab();
479752Speter 	    int	botlabel = getlab();
480752Speter #	endif PC
481752Speter 
482752Speter 	cntstat = 0;
483752Speter /*
484752Speter  *	yyoutline();
485752Speter  */
486752Speter 	if (program != NIL)
487752Speter 		line = program->value[3];
488752Speter 	blk = bundle[2];
489752Speter 	if (fp == NIL) {
490752Speter 		cbn--;
491752Speter #		ifdef PTREE
492752Speter 		    nesting--;
493752Speter #		endif PTREE
494752Speter 		return;
495752Speter 	}
496752Speter #ifdef OBJ
497752Speter 	/*
498752Speter 	 * Patch the branch to the
499752Speter 	 * entry point of the function
500752Speter 	 */
501752Speter 	patch4(fp->entloc);
502752Speter 	/*
503752Speter 	 * Put out the block entrance code and the block name.
504752Speter 	 * the CONG is overlaid by a patch later!
505752Speter 	 */
506752Speter 	var = put(2, (lenstr(fp->symbol,0) << 8)
507752Speter 			| (cbn == 1 && opt('p') == 0 ? O_NODUMP: O_BEG), 0);
508752Speter 	put(2, O_CASE2, bundle[1]);
509752Speter 	putstr(fp->symbol, 0);
510752Speter #endif OBJ
511752Speter #ifdef PC
512752Speter 	/*
513752Speter 	 * put out the procedure entry code
514752Speter 	 */
515752Speter 	if ( fp -> class == PROG ) {
516752Speter 	    putprintf( "	.text" , 0 );
517752Speter 	    putprintf( "	.align	1" , 0 );
518752Speter 	    putprintf( "	.globl	_main" , 0 );
519752Speter 	    putprintf( "_main:" , 0 );
520752Speter 	    putprintf( "	.word	0" , 0 );
521752Speter 	    putprintf( "	calls	$0,_PCSTART" , 0 );
522752Speter 	    putprintf( "	movl	4(ap),__argc" , 0 );
523752Speter 	    putprintf( "	movl	8(ap),__argv" , 0 );
524752Speter 	    putprintf( "	calls	$0,_program" , 0 );
525752Speter 	    putprintf( "	calls	$0,_PCEXIT" , 0 );
526752Speter 	    ftnno = fp -> entloc;
527752Speter 	    putprintf( "	.text" , 0 );
528752Speter 	    putprintf( "	.align	1" , 0 );
529752Speter 	    putprintf( "	.globl	_program" , 0 );
530752Speter 	    putprintf( "_program:" , 0 );
531752Speter 	} else {
532752Speter 	    ftnno = fp -> entloc;
533752Speter 	    putprintf( "	.text" , 0 );
534752Speter 	    putprintf( "	.align	1" , 0 );
535752Speter 	    putprintf( "	.globl	" , 1 );
536752Speter 	    for ( i = 1 ; i < cbn ; i++ ) {
537752Speter 		putprintf( EXTFORMAT , 1 , enclosing[ i ] );
538752Speter 	    }
539752Speter 	    putprintf( "" , 0 );
540752Speter 	    for ( i = 1 ; i < cbn ; i++ ) {
541752Speter 		putprintf( EXTFORMAT , 1 , enclosing[ i ] );
542752Speter 	    }
543752Speter 	    putprintf( ":" , 0 );
544752Speter 	}
545752Speter 	stablbrac( cbn );
546752Speter 	    /*
547752Speter 	     *	register save mask
548752Speter 	     */
549752Speter 	if ( opt( 't' ) ) {
550752Speter 	    putprintf( "	.word	0x%x" , 0 , RUNCHECK | RSAVEMASK );
551752Speter 	} else {
552752Speter 	    putprintf( "	.word	0x%x" , 0 , RSAVEMASK );
553752Speter 	}
554752Speter 	putjbr( botlabel );
555752Speter 	putlab( toplabel );
556752Speter 	if ( profflag ) {
557752Speter 		/*
558752Speter 		 *	call mcount for profiling
559752Speter 		 */
560752Speter 	    putprintf( "	moval	1f,r0" , 0 );
561752Speter 	    putprintf( "	jsb	mcount" , 0 );
562752Speter 	    putprintf( "	.data" , 0 );
563752Speter 	    putprintf( "	.align	2" , 0 );
564752Speter 	    putprintf( "1:" , 0 );
565752Speter 	    putprintf( "	.long	0" , 0 );
566752Speter 	    putprintf( "	.text" , 0 );
567752Speter 	}
568752Speter 	    /*
569752Speter 	     *	set up unwind exception vector.
570752Speter 	     */
571752Speter 	putprintf( "	moval	%s,%d(%s)" , 0
572752Speter 		, UNWINDNAME , UNWINDOFFSET , P2FPNAME );
573752Speter 	    /*
574752Speter 	     *	save address of display entry, for unwind.
575752Speter 	     */
576752Speter 	putprintf( "	moval	%s+%d,%d(%s)" , 0
577752Speter 		, DISPLAYNAME , cbn * sizeof(struct dispsave)
578752Speter 		, DPTROFFSET , P2FPNAME );
579752Speter 	    /*
580752Speter 	     *	save old display
581752Speter 	     */
582752Speter 	putprintf( "	movq	%s+%d,%d(%s)" , 0
583752Speter 		, DISPLAYNAME , cbn * sizeof(struct dispsave)
584752Speter 		, DSAVEOFFSET , P2FPNAME );
585752Speter 	    /*
586752Speter 	     *	set up new display by saving AP and FP in appropriate
587752Speter 	     *	slot in display structure.
588752Speter 	     */
589752Speter 	putprintf( "	movq	%s,%s+%d" , 0
590752Speter 		, P2APNAME , DISPLAYNAME , cbn * sizeof(struct dispsave) );
591752Speter 	    /*
592752Speter 	     *	ask second pass to allocate known locals
593752Speter 	     */
594752Speter 	putlbracket( ftnno , -sizes[ cbn ].om_max );
595752Speter 	    /*
596752Speter 	     *	and zero them if checking is on
597752Speter 	     *	by calling zframe( bytes of locals , highest local address );
598752Speter 	     */
599752Speter 	if ( opt( 't' ) && ( -sizes[ cbn ].om_max ) > DPOFF1 ) {
600752Speter 	    putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
601752Speter 		    , "_ZFRAME" );
602752Speter 	    putleaf( P2ICON ,  ( -sizes[ cbn ].om_max ) - DPOFF1
603752Speter 		    , 0 , P2INT , 0 );
604752Speter 	    putLV( 0 , cbn , sizes[ cbn ].om_max , P2CHAR );
605752Speter 	    putop( P2LISTOP , P2INT );
606752Speter 	    putop( P2CALL , P2INT );
607752Speter 	    putdot( filename , line );
608752Speter 	}
609752Speter #endif PC
610752Speter 	if ( monflg ) {
611752Speter 		if ( fp -> value[ NL_CNTR ] != 0 ) {
612752Speter 			inccnt( fp -> value [ NL_CNTR ] );
613752Speter 		}
614752Speter 		inccnt( bodycnts[ fp -> nl_block & 037 ] );
615752Speter 	}
616752Speter 	if (fp->class == PROG) {
617752Speter 		/*
618752Speter 		 * The glorious buffers option.
619752Speter 		 *          0 = don't buffer output
620752Speter 		 *          1 = line buffer output
621752Speter 		 *          2 = 512 byte buffer output
622752Speter 		 */
623752Speter #		ifdef OBJ
624752Speter 		    if (opt('b') != 1)
625752Speter 			    put(1, O_BUFF | opt('b') << 8);
626752Speter #		endif OBJ
627752Speter #		ifdef PC
628752Speter 		    if ( opt( 'b' ) != 1 ) {
629752Speter 			putleaf( P2ICON , 0 , 0
630752Speter 				, ADDTYPE( P2FTN | P2INT , P2PTR ) , "_BUFF" );
631752Speter 			putleaf( P2ICON , opt( 'b' ) , 0 , P2INT , 0 );
632752Speter 			putop( P2CALL , P2INT );
633752Speter 			putdot( filename , line );
634752Speter 		    }
635752Speter #		endif PC
636752Speter 		out = 0;
637752Speter 		for (p = fp->chain; p != NIL; p = p->chain) {
638752Speter 			if (strcmp(p->symbol, "input") == 0) {
639752Speter 				inp++;
640752Speter 				continue;
641752Speter 			}
642752Speter 			if (strcmp(p->symbol, "output") == 0) {
643752Speter 				out++;
644752Speter 				continue;
645752Speter 			}
646752Speter 			iop = lookup1(p->symbol);
647752Speter 			if (iop == NIL || bn != cbn) {
648752Speter 				error("File %s listed in program statement but not declared", p->symbol);
649752Speter 				continue;
650752Speter 			}
651752Speter 			if (iop->class != VAR) {
652752Speter 				error("File %s listed in program statement but declared as a %s", p->symbol, classes[iop->class]);
653752Speter 				continue;
654752Speter 			}
655752Speter 			if (iop->type == NIL)
656752Speter 				continue;
657752Speter 			if (iop->type->class != FILET) {
658752Speter 				error("File %s listed in program statement but defined as %s",
659752Speter 					p->symbol, nameof(iop->type));
660752Speter 				continue;
661752Speter 			}
662752Speter #			ifdef OBJ
663752Speter 			    put(2, O_LV | bn << 8+INDX, iop->value[NL_OFFS]);
664752Speter 			    i = lenstr(p->symbol,0);
665752Speter 			    put(2, O_LVCON, i);
666752Speter 			    putstr(p->symbol, 0);
667752Speter 			    do {
668752Speter 				i--;
669752Speter 			    } while (p->symbol+i == 0);
670752Speter 			    put(2, O_CON24, i+1);
671752Speter 			    put(2, O_CON24, text(iop->type) ? 0 : width(iop->type->type));
672752Speter 			    put(1, O_DEFNAME);
673752Speter #			endif OBJ
674752Speter #			ifdef PC
675752Speter 			    putleaf( P2ICON , 0 , 0
676752Speter 				    , ADDTYPE( P2FTN | P2INT , P2PTR )
677752Speter 				    , "_DEFNAME" );
678752Speter 			    putLV( p -> symbol , bn , iop -> value[NL_OFFS]
679752Speter 				    , p2type( iop ) );
680752Speter 			    putCONG( p -> symbol , strlen( p -> symbol )
681752Speter 				    , LREQ );
682752Speter 			    putop( P2LISTOP , P2INT );
683752Speter 			    putleaf( P2ICON , strlen( p -> symbol )
684752Speter 				    , 0 , P2INT , 0 );
685752Speter 			    putop( P2LISTOP , P2INT );
686752Speter 			    putleaf( P2ICON
687752Speter 				, text(iop->type) ? 0 : width(iop->type->type)
688752Speter 				, 0 , P2INT , 0 );
689752Speter 			    putop( P2LISTOP , P2INT );
690752Speter 			    putop( P2CALL , P2INT );
691752Speter 			    putdot( filename , line );
692752Speter #			endif PC
693752Speter 		}
694752Speter 		if (out == 0 && fp->chain != NIL) {
695752Speter 			recovered();
696752Speter 			error("The file output must appear in the program statement file list");
697752Speter 		}
698752Speter 	}
699752Speter 	/*
700752Speter 	 * Process the prog/proc/func body
701752Speter 	 */
702752Speter 	noreach = 0;
703752Speter 	line = bundle[1];
704752Speter 	statlist(blk);
705752Speter #	ifdef PTREE
706752Speter 	    {
707752Speter 		pPointer Body = tCopy( blk );
708752Speter 
709752Speter 		pDEF( PorFHeader[ nesting -- ] ).PorFBody = Body;
710752Speter 	    }
711752Speter #	endif PTREE
712752Speter #	ifdef OBJ
713752Speter 	    if (cbn== 1 && monflg != 0) {
714752Speter 		    patchfil(cntpatch - 2, cnts, 2);
715752Speter 		    patchfil(nfppatch - 2, pfcnt, 2);
716752Speter 	    }
717752Speter #	endif OBJ
718752Speter #	ifdef PC
719752Speter 	    if ( fp -> class == PROG && monflg ) {
720752Speter 		putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
721752Speter 			, "_PMFLUSH" );
722752Speter 		putleaf( P2ICON , cnts , 0 , P2INT , 0 );
723752Speter 		putleaf( P2ICON , pfcnt , 0 , P2INT , 0 );
724752Speter 		putop( P2LISTOP , P2INT );
725752Speter 		putop( P2CALL , P2INT );
726752Speter 		putdot( filename , line );
727752Speter 	    }
728752Speter #	endif PC
729752Speter 	if (fp->class == PROG && inp == 0 && (input->nl_flags & (NUSED|NMOD)) != 0) {
730752Speter 		recovered();
731752Speter 		error("Input is used but not defined in the program statement");
732752Speter 	}
733752Speter 	/*
734752Speter 	 * Clean up the symbol table displays and check for unresolves
735752Speter 	 */
736752Speter 	line = endline;
737752Speter 	b = cbn;
738752Speter 	Fp = fp;
739752Speter 	chkref = syneflg == errcnt[cbn] && opt('w') == 0;
740752Speter 	for (i = 0; i <= 077; i++) {
741752Speter 		for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) {
742752Speter 			/*
743752Speter 			 * Check for variables defined
744752Speter 			 * but not referenced
745752Speter 			 */
746752Speter 			if (chkref && p->symbol != NIL)
747752Speter 			switch (p->class) {
748752Speter 				case FIELD:
749752Speter 					/*
750752Speter 					 * If the corresponding record is
751752Speter 					 * unused, we shouldn't complain about
752752Speter 					 * the fields.
753752Speter 					 */
754752Speter 				default:
755752Speter 					if ((p->nl_flags & (NUSED|NMOD)) == 0) {
756752Speter 						warning();
757752Speter 						nerror("%s %s is neither used nor set", classes[p->class], p->symbol);
758752Speter 						break;
759752Speter 					}
760752Speter 					/*
761752Speter 					 * If a var parameter is either
762752Speter 					 * modified or used that is enough.
763752Speter 					 */
764752Speter 					if (p->class == REF)
765752Speter 						continue;
766752Speter #					ifdef OBJ
767752Speter 					    if ((p->nl_flags & NUSED) == 0) {
768752Speter 						warning();
769752Speter 						nerror("%s %s is never used", classes[p->class], p->symbol);
770752Speter 						break;
771752Speter 					    }
772752Speter #					endif OBJ
773752Speter #					ifdef PC
774752Speter 					    if (((p->nl_flags & NUSED) == 0) && ((p->ext_flags & NEXTERN) == 0)) {
775752Speter 						warning();
776752Speter 						nerror("%s %s is never used", classes[p->class], p->symbol);
777752Speter 						break;
778752Speter 					    }
779752Speter #					endif PC
780752Speter 					if ((p->nl_flags & NMOD) == 0) {
781752Speter 						warning();
782752Speter 						nerror("%s %s is used but never set", classes[p->class], p->symbol);
783752Speter 						break;
784752Speter 					}
785752Speter 				case LABEL:
786752Speter 				case FVAR:
787752Speter 				case BADUSE:
788752Speter 					break;
789752Speter 			}
790752Speter 			switch (p->class) {
791752Speter 				case BADUSE:
792752Speter 					cp = "s";
793752Speter 					if (p->chain->ud_next == NIL)
794752Speter 						cp++;
795752Speter 					eholdnl();
796752Speter 					if (p->value[NL_KINDS] & ISUNDEF)
797752Speter 						nerror("%s undefined on line%s", p->symbol, cp);
798752Speter 					else
799752Speter 						nerror("%s improperly used on line%s", p->symbol, cp);
800752Speter 					pnumcnt = 10;
801752Speter 					pnums(p->chain);
802752Speter 					pchr('\n');
803752Speter 					break;
804752Speter 
805752Speter 				case FUNC:
806752Speter 				case PROC:
807752Speter #					ifdef OBJ
808752Speter 					    if ((p->nl_flags & NFORWD))
809752Speter 						nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol);
810752Speter #					endif OBJ
811752Speter #					ifdef PC
812752Speter 					    if ((p->nl_flags & NFORWD) && ((p->ext_flags & NEXTERN) == 0))
813752Speter 						nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol);
814752Speter #					endif PC
815752Speter 					break;
816752Speter 
817752Speter 				case LABEL:
818752Speter 					if (p->nl_flags & NFORWD)
819752Speter 						nerror("label %s was declared but not defined", p->symbol);
820752Speter 					break;
821752Speter 				case FVAR:
822752Speter 					if ((p->nl_flags & NMOD) == 0)
823752Speter 						nerror("No assignment to the function variable");
824752Speter 					break;
825752Speter 			}
826752Speter 		}
827752Speter 		/*
828752Speter 		 * Pop this symbol
829752Speter 		 * table slot
830752Speter 		 */
831752Speter 		disptab[i] = p;
832752Speter 	}
833752Speter 
834752Speter #	ifdef OBJ
835752Speter 	    put(1, O_END);
836752Speter #	endif OBJ
837752Speter #	ifdef PC
838752Speter 		/*
839752Speter 		 *	if there were file variables declared at this level
840752Speter 		 *	call pclose( &__disply[ cbn ] ) to clean them up.
841752Speter 		 */
842752Speter 	    if ( dfiles[ cbn ] ) {
843752Speter 		putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
844752Speter 			, "_PCLOSE" );
845752Speter 		putRV( DISPLAYNAME , 0 , cbn * sizeof( struct dispsave )
846752Speter 			, P2PTR | P2CHAR );
847752Speter 		putop( P2CALL , P2INT );
848752Speter 		putdot( filename , line );
849752Speter 	    }
850752Speter 		/*
851752Speter 		 *	if this is a function,
852752Speter 		 *	the function variable is the return value.
853752Speter 		 *	if it's a scalar valued function, return scalar,
854752Speter 		 *	else, return a pointer to the structure value.
855752Speter 		 */
856752Speter 	    if ( fp -> class == FUNC ) {
857752Speter 		struct nl	*fvar = fp -> ptr[ NL_FVAR ];
858752Speter 		long		fvartype = p2type( fvar -> type );
859752Speter 
860752Speter 		switch ( classify( fvar -> type ) ) {
861752Speter 		    case TBOOL:
862752Speter 		    case TCHAR:
863752Speter 		    case TINT:
864752Speter 		    case TSCAL:
865752Speter 		    case TDOUBLE:
866752Speter 		    case TPTR:
867752Speter 			putRV( fvar -> symbol , ( fvar -> nl_block ) & 037
868752Speter 				, fvar -> value[ NL_OFFS ] , fvartype );
869752Speter 			break;
870752Speter 		    default:
871752Speter 			putLV( fvar -> symbol , ( fvar -> nl_block ) & 037
872752Speter 				, fvar -> value[ NL_OFFS ] , fvartype );
873752Speter 			break;
874752Speter 		}
875752Speter 		putop( P2FORCE , fvartype );
876752Speter 		putdot( filename , line );
877752Speter 	    }
878752Speter 		/*
879752Speter 		 *	restore old display entry from save area
880752Speter 		 */
881752Speter 
882752Speter 	    putprintf( "	movq	%d(%s),%s+%d" , 0
883752Speter 		, DSAVEOFFSET , P2FPNAME
884752Speter 		, DISPLAYNAME , cbn * sizeof(struct dispsave) );
885752Speter 	    stabrbrac( cbn );
886752Speter 	    putprintf( "	ret" , 0 );
887752Speter 		/*
888752Speter 		 *	let the second pass allocate locals
889752Speter 		 */
890752Speter 	    putlab( botlabel );
891752Speter 	    putprintf( "	subl2	$LF%d,sp" , 0 , ftnno );
892752Speter 	    putrbracket( ftnno );
893752Speter 	    putjbr( toplabel );
894752Speter 		/*
895752Speter 		 *	declare pcp counters, if any
896752Speter 		 */
897752Speter 	    if ( monflg && fp -> class == PROG ) {
898752Speter 		putprintf( "	.data" , 0 );
899752Speter 		putprintf( "	.comm	" , 1 );
900752Speter 		putprintf( PCPCOUNT , 1 );
901752Speter 		putprintf( ",%d" , 0 , ( cnts + 1 ) * sizeof (long) );
902752Speter 		putprintf( "	.text" , 0 );
903752Speter 	    }
904752Speter #	endif PC
905752Speter #ifdef DEBUG
906752Speter 	dumpnl(fp->ptr[2], fp->symbol);
907752Speter #endif
908752Speter 	/*
909752Speter 	 * Restore the
910752Speter 	 * (virtual) name list
911752Speter 	 * position
912752Speter 	 */
913752Speter 	nlfree(fp->ptr[2]);
914752Speter 	/*
915752Speter 	 * Proc/func has been
916752Speter 	 * resolved
917752Speter 	 */
918752Speter 	fp->nl_flags &= ~NFORWD;
919752Speter 	/*
920752Speter 	 * Patch the beg
921752Speter 	 * of the proc/func to
922752Speter 	 * the proper variable size
923752Speter 	 */
924752Speter 	if (Fp == NIL)
925752Speter 		elineon();
926752Speter #	ifdef OBJ
927752Speter 	    patchfil(var, sizes[cbn].om_max, 2);
928752Speter #	endif OBJ
929752Speter 	cbn--;
930752Speter 	if (inpflist(fp->symbol)) {
931752Speter 		opop('l');
932752Speter 	}
933752Speter }
934752Speter 
935752Speter 
936752Speter /*
937752Speter  * Segend is called to check for
938752Speter  * unresolved variables, funcs and
939752Speter  * procs, and deliver unresolved and
940752Speter  * baduse error diagnostics at the
941752Speter  * end of a routine segment (a separately
942752Speter  * compiled segment that is not the
943752Speter  * main program) for PC. This
944752Speter  * routine should only be called
945752Speter  * by PC (not standard).
946752Speter  */
947752Speter  segend()
948752Speter  {
949752Speter 	register struct nl *p;
950752Speter 	register int i,b;
951752Speter 	char *cp;
952752Speter 
953752Speter #ifdef PC
954752Speter 	if (opt('s')) {
955752Speter 		standard();
956752Speter 		error("Separately compiled routine segments are not standard.");
957752Speter 	} else {
958752Speter 		b = cbn;
959752Speter 		for (i=0; i<077; i++) {
960752Speter 			for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) {
961752Speter 			switch (p->class) {
962752Speter 				case BADUSE:
963752Speter 					cp = 's';
964752Speter 					if (p->chain->ud_next == NIL)
965752Speter 						cp++;
966752Speter 					eholdnl();
967752Speter 					if (p->value[NL_KINDS] & ISUNDEF)
968752Speter 						nerror("%s undefined on line%s", p->symbol, cp);
969752Speter 					else
970752Speter 						nerror("%s improperly used on line%s", p->symbol, cp);
971752Speter 					pnumcnt = 10;
972752Speter 					pnums(p->chain);
973752Speter 					pchr('\n');
974752Speter 					break;
975752Speter 
976752Speter 				case FUNC:
977752Speter 				case PROC:
978752Speter 					if ((p->nl_flags & NFORWD) && ((p->ext_flags & NEXTERN) == 0))
979752Speter 						nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol);
980752Speter 					break;
981752Speter 
982752Speter 				case FVAR:
983752Speter 					if (((p->nl_flags & NMOD) == 0) && ((p->chain->ext_flags & NEXTERN) == 0))
984752Speter 						nerror("No assignment to the function variable");
985752Speter 					break;
986752Speter 			    }
987752Speter 			   }
988752Speter 			   disptab[i] = p;
989752Speter 		    }
990752Speter 	}
991752Speter #endif PC
992752Speter #ifdef OBJ
993752Speter 	error("Missing program statement and program body");
994752Speter #endif OBJ
995752Speter 
996752Speter }
997752Speter 
998752Speter 
999752Speter /*
1000752Speter  * Level1 does level one processing for
1001752Speter  * separately compiled routine segments
1002752Speter  */
1003752Speter level1()
1004752Speter {
1005752Speter 
1006752Speter #	ifdef OBJ
1007752Speter 	    error("Missing program statement");
1008752Speter #	endif OBJ
1009752Speter #	ifdef PC
1010752Speter 	    if (opt('s')) {
1011752Speter 		    standard();
1012752Speter 		    error("Missing program statement");
1013752Speter 	    }
1014752Speter #	endif PC
1015752Speter 
1016752Speter 	cbn++;
1017752Speter 	sizes[cbn].om_max = sizes[cbn].om_off = -DPOFF1;
1018752Speter 	parts = NIL;
1019752Speter 	progseen++;
1020752Speter }
1021752Speter 
1022752Speter 
1023752Speter 
1024752Speter pnums(p)
1025752Speter 	struct udinfo *p;
1026752Speter {
1027752Speter 
1028752Speter 	if (p->ud_next != NIL)
1029752Speter 		pnums(p->ud_next);
1030752Speter 	if (pnumcnt == 0) {
1031752Speter 		printf("\n\t");
1032752Speter 		pnumcnt = 20;
1033752Speter 	}
1034752Speter 	pnumcnt--;
1035752Speter 	printf(" %d", p->ud_line);
1036752Speter }
1037752Speter 
1038752Speter nerror(a1, a2, a3)
1039752Speter {
1040752Speter 
1041752Speter 	if (Fp != NIL) {
1042752Speter 		yySsync();
1043752Speter #ifndef PI1
1044752Speter 		if (opt('l'))
1045752Speter 			yyoutline();
1046752Speter #endif
1047752Speter 		yysetfile(filename);
1048752Speter 		printf("In %s %s:\n", classes[Fp->class], Fp->symbol);
1049752Speter 		Fp = NIL;
1050752Speter 		elineoff();
1051752Speter 	}
1052752Speter 	error(a1, a2, a3);
1053752Speter }
1054