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