xref: /csrg-svn/usr.bin/pascal/src/fhdr.c (revision 3302)
13191Smckusick /* Copyright (c) 1979 Regents of the University of California */
23191Smckusick 
3*3302Smckusic static char sccsid[] = "@(#)fhdr.c 1.2 03/18/81";
43191Smckusick 
53191Smckusick #include "whoami.h"
63191Smckusick #include "0.h"
73191Smckusick #include "tree.h"
83191Smckusick #include "opcode.h"
93191Smckusick #include "objfmt.h"
103191Smckusick #include "align.h"
113191Smckusick 
123191Smckusick /*
133191Smckusick  * this array keeps the pxp counters associated with
143191Smckusick  * functions and procedures, so that they can be output
153191Smckusick  * when their bodies are encountered
163191Smckusick  */
173191Smckusick int	bodycnts[ DSPLYSZ ];
183191Smckusick 
193191Smckusick #ifdef PC
203191Smckusick #   include "pc.h"
213191Smckusick #   include "pcops.h"
223191Smckusick #endif PC
233191Smckusick 
243191Smckusick #ifdef OBJ
253191Smckusick int	cntpatch;
263191Smckusick int	nfppatch;
273191Smckusick #endif OBJ
283191Smckusick 
293191Smckusick /*
303191Smckusick  * Funchdr inserts
313191Smckusick  * declaration of a the
323191Smckusick  * prog/proc/func into the
333191Smckusick  * namelist. It also handles
343191Smckusick  * the arguments and puts out
353191Smckusick  * a transfer which defines
363191Smckusick  * the entry point of a procedure.
373191Smckusick  */
383191Smckusick 
393191Smckusick struct nl *
403191Smckusick funchdr(r)
413191Smckusick 	int *r;
423191Smckusick {
433191Smckusick 	register struct nl *p;
443191Smckusick 	register *il, **rl;
45*3302Smckusic 	struct nl *cp, *dp;
46*3302Smckusic 	int s, o, *pp;
473191Smckusick 
483191Smckusick 	if (inpflist(r[2])) {
493191Smckusick 		opush('l');
503191Smckusick 		yyretrieve();	/* kludge */
513191Smckusick 	}
523191Smckusick 	pfcnt++;
533191Smckusick 	parts[ cbn ] |= RPRT;
543191Smckusick 	line = r[1];
553191Smckusick 	if (r[3] == NIL && (p=lookup1(r[2])) != NIL && bn == cbn) {
563191Smckusick 		/*
573191Smckusick 		 * Symbol already defined
583191Smckusick 		 * in this block. it is either
593191Smckusick 		 * a redeclared symbol (error)
603191Smckusick 		 * a forward declaration,
613191Smckusick 		 * or an external declaration.
623191Smckusick 		 */
633191Smckusick 		if ((p->class == FUNC || p->class == PROC) && (p->nl_flags & NFORWD) != 0) {
643191Smckusick 			/*
653191Smckusick 			 * Grammar doesnt forbid
663191Smckusick 			 * types on a resolution
673191Smckusick 			 * of a forward function
683191Smckusick 			 * declaration.
693191Smckusick 			 */
703191Smckusick 			if (p->class == FUNC && r[4])
713191Smckusick 				error("Function type should be given only in forward declaration");
723191Smckusick 			/*
733191Smckusick 			 * get another counter for the actual
743191Smckusick 			 */
753191Smckusick 			if ( monflg ) {
763191Smckusick 			    bodycnts[ cbn ] = getcnt();
773191Smckusick 			}
783191Smckusick #			ifdef PC
793191Smckusick 			    enclosing[ cbn ] = p -> symbol;
803191Smckusick #			endif PC
813191Smckusick #			ifdef PTREE
823191Smckusick 				/*
833191Smckusick 				 *	mark this proc/func as forward
843191Smckusick 				 *	in the pTree.
853191Smckusick 				 */
863191Smckusick 			    pDEF( p -> inTree ).PorFForward = TRUE;
873191Smckusick #			endif PTREE
883191Smckusick 			return (p);
893191Smckusick 		}
903191Smckusick 	}
913191Smckusick 
923191Smckusick 	/* if a routine segment is being compiled,
933191Smckusick 	 * do level one processing.
943191Smckusick 	 */
953191Smckusick 
963191Smckusick 	 if ((r[0] != T_PROG) && (!progseen))
973191Smckusick 		level1();
983191Smckusick 
993191Smckusick 
1003191Smckusick 	/*
1013191Smckusick 	 * Declare the prog/proc/func
1023191Smckusick 	 */
1033191Smckusick 	switch (r[0]) {
1043191Smckusick 	    case T_PROG:
1053191Smckusick 		    progseen = TRUE;
1063191Smckusick 		    if (opt('z'))
1073191Smckusick 			    monflg = TRUE;
1083191Smckusick 		    program = p = defnl(r[2], PROG, 0, 0);
1093191Smckusick 		    p->value[3] = r[1];
1103191Smckusick 		    break;
1113191Smckusick 	    case T_PDEC:
1123191Smckusick 		    if (r[4] != NIL)
1133191Smckusick 			    error("Procedures do not have types, only functions do");
1143191Smckusick 		    p = enter(defnl(r[2], PROC, 0, 0));
1153191Smckusick 		    p->nl_flags |= NMOD;
1163191Smckusick #		    ifdef PC
1173191Smckusick 			enclosing[ cbn ] = r[2];
1183191Smckusick #		    endif PC
1193191Smckusick 		    break;
1203191Smckusick 	    case T_FDEC:
1213191Smckusick 		    il = r[4];
1223191Smckusick 		    if (il == NIL)
1233191Smckusick 			    error("Function type must be specified");
1243191Smckusick 		    else if (il[0] != T_TYID) {
1253191Smckusick 			    il = NIL;
1263191Smckusick 			    error("Function type can be specified only by using a type identifier");
1273191Smckusick 		    } else
1283191Smckusick 			    il = gtype(il);
1293191Smckusick 		    p = enter(defnl(r[2], FUNC, il, NIL));
1303191Smckusick 		    p->nl_flags |= NMOD;
1313191Smckusick 		    /*
1323191Smckusick 		     * An arbitrary restriction
1333191Smckusick 		     */
1343191Smckusick 		    switch (o = classify(p->type)) {
1353191Smckusick 			    case TFILE:
1363191Smckusick 			    case TARY:
1373191Smckusick 			    case TREC:
1383191Smckusick 			    case TSET:
1393191Smckusick 			    case TSTR:
1403191Smckusick 				    warning();
1413191Smckusick 				    if (opt('s')) {
1423191Smckusick 					    standard();
1433191Smckusick 				    }
1443191Smckusick 				    error("Functions should not return %ss", clnames[o]);
1453191Smckusick 		    }
1463191Smckusick #		    ifdef PC
1473191Smckusick 			enclosing[ cbn ] = r[2];
1483191Smckusick #		    endif PC
1493191Smckusick 		    break;
1503191Smckusick 	    default:
1513191Smckusick 		    panic("funchdr");
1523191Smckusick 	}
1533191Smckusick 	if (r[0] != T_PROG) {
1543191Smckusick 		/*
1553191Smckusick 		 * Mark this proc/func as
1563191Smckusick 		 * being forward declared
1573191Smckusick 		 */
1583191Smckusick 		p->nl_flags |= NFORWD;
1593191Smckusick 		/*
1603191Smckusick 		 * Enter the parameters
1613191Smckusick 		 * in the next block for
1623191Smckusick 		 * the time being
1633191Smckusick 		 */
1643191Smckusick 		if (++cbn >= DSPLYSZ) {
1653191Smckusick 			error("Procedure/function nesting too deep");
1663191Smckusick 			pexit(ERRS);
1673191Smckusick 		}
1683191Smckusick 		/*
1693191Smckusick 		 * For functions, the function variable
1703191Smckusick 		 */
1713191Smckusick 		if (p->class == FUNC) {
1723191Smckusick #			ifdef OBJ
1733191Smckusick 			    cp = defnl(r[2], FVAR, p->type, 0);
1743191Smckusick #			endif OBJ
1753191Smckusick #			ifdef PC
1763191Smckusick 				/*
1773191Smckusick 				 * fvars used to be allocated and deallocated
1783191Smckusick 				 * by the caller right before the arguments.
1793191Smckusick 				 * the offset of the fvar was kept in
1803191Smckusick 				 * value[NL_OFFS] of function (very wierd,
1813191Smckusick 				 * but see asgnop).
1823191Smckusick 				 * now, they are locals to the function
1833191Smckusick 				 * with the offset kept in the fvar.
1843191Smckusick 				 */
1853191Smckusick 
1863191Smckusick 			    cp = defnl(r[2], FVAR, p->type,
187*3302Smckusic 				(int)-leven(roundup(
188*3302Smckusic 			            (int)(DPOFF1+lwidth(p->type)),
189*3302Smckusic 				    (long)align(p->type))));
1903191Smckusick #			endif PC
1913191Smckusick 			cp->chain = p;
1923191Smckusick 			p->ptr[NL_FVAR] = cp;
1933191Smckusick 		}
1943191Smckusick 		/*
1953191Smckusick 		 * Enter the parameters
1963191Smckusick 		 * and compute total size
1973191Smckusick 		 */
198*3302Smckusic 	        p->value[NL_OFFS] = params(p, r[3]);
199*3302Smckusic 		/*
200*3302Smckusic 		 * because NL_LINENO field in the function
201*3302Smckusic 		 * namelist entry has been used (as have all
202*3302Smckusic 		 * the other fields), the line number is
203*3302Smckusic 		 * stored in the NL_LINENO field of its fvar.
204*3302Smckusic 		 */
205*3302Smckusic 		if (p->class == FUNC)
206*3302Smckusic 		    p->ptr[NL_FVAR]->value[NL_LINENO] = r[1];
207*3302Smckusic 		else
208*3302Smckusic 		    p->value[NL_LINENO] = r[1];
2093191Smckusick 		cbn--;
2103191Smckusick 	} else {
2113191Smckusick 		/*
2123191Smckusick 		 * The wonderful
2133191Smckusick 		 * program statement!
2143191Smckusick 		 */
2153191Smckusick #		ifdef OBJ
2163191Smckusick 		    if (monflg) {
2173191Smckusick 			    put(1, O_PXPBUF);
2183191Smckusick 			    cntpatch = put(2, O_CASE4, (long)0);
2193191Smckusick 			    nfppatch = put(2, O_CASE4, (long)0);
2203191Smckusick 		    }
2213191Smckusick #		endif OBJ
2223191Smckusick 		cp = p;
2233191Smckusick 		for (rl = r[3]; rl; rl = rl[2]) {
2243191Smckusick 			if (rl[1] == NIL)
2253191Smckusick 				continue;
2263191Smckusick 			dp = defnl(rl[1], VAR, 0, 0);
2273191Smckusick 			cp->chain = dp;
2283191Smckusick 			cp = dp;
2293191Smckusick 		}
2303191Smckusick 	}
2313191Smckusick 	/*
2323191Smckusick 	 * Define a branch at
2333191Smckusick 	 * the "entry point" of
2343191Smckusick 	 * the prog/proc/func.
2353191Smckusick 	 */
2363191Smckusick 	p->entloc = getlab();
2373191Smckusick 	if (monflg) {
2383191Smckusick 		bodycnts[ cbn ] = getcnt();
2393191Smckusick 		p->value[ NL_CNTR ] = 0;
2403191Smckusick 	}
2413191Smckusick #	ifdef OBJ
2423191Smckusick 	    put(2, O_TRA4, (long)p->entloc);
2433191Smckusick #	endif OBJ
2443191Smckusick #	ifdef PTREE
2453191Smckusick 	    {
2463191Smckusick 		pPointer	PF = tCopy( r );
2473191Smckusick 
2483191Smckusick 		pSeize( PorFHeader[ nesting ] );
2493191Smckusick 		if ( r[0] != T_PROG ) {
2503191Smckusick 			pPointer	*PFs;
2513191Smckusick 
2523191Smckusick 			PFs = &( pDEF( PorFHeader[ nesting ] ).PorFPFs );
2533191Smckusick 			*PFs = ListAppend( *PFs , PF );
2543191Smckusick 		} else {
2553191Smckusick 			pDEF( PorFHeader[ nesting ] ).GlobProg = PF;
2563191Smckusick 		}
2573191Smckusick 		pRelease( PorFHeader[ nesting ] );
2583191Smckusick 	    }
2593191Smckusick #	endif PTREE
2603191Smckusick 	return (p);
2613191Smckusick }
262*3302Smckusic 
263*3302Smckusic 	/*
264*3302Smckusic 	 * deal with the parameter declaration for a routine.
265*3302Smckusic 	 * p is the namelist entry of the routine.
266*3302Smckusic 	 * formalist is the parse tree for the parameter declaration.
267*3302Smckusic 	 * formalist	[0]	T_LISTPP
268*3302Smckusic 	 *		[1]	pointer to a formal
269*3302Smckusic 	 *		[2]	pointer to next formal
270*3302Smckusic 	 * for by-value or by-reference formals, the formal is
271*3302Smckusic 	 * formal	[0]	T_PVAL or T_PVAR
272*3302Smckusic 	 *		[1]	pointer to id_list
273*3302Smckusic 	 *		[2]	pointer to type (error if not typeid)
274*3302Smckusic 	 * for function and procedure formals, the formal is
275*3302Smckusic 	 * formal	[0]	T_PFUNC or T_PPROC
276*3302Smckusic 	 *		[1]	pointer to id_list (error if more than one)
277*3302Smckusic 	 *		[2]	pointer to type (error if not typeid, or proc)
278*3302Smckusic 	 *		[3]	pointer to formalist for this routine.
279*3302Smckusic 	 */
280*3302Smckusic fparams(p, formal)
281*3302Smckusic 	register struct nl *p;
282*3302Smckusic 	int *formal;
283*3302Smckusic {
284*3302Smckusic 	params(p, formal[3]);
285*3302Smckusic 	p -> value[ NL_LINENO ] = formal[4];
286*3302Smckusic 	p -> ptr[ NL_FCHAIN ] = p -> chain;
287*3302Smckusic 	p -> chain = NIL;
288*3302Smckusic }
289*3302Smckusic 
290*3302Smckusic params(p, formalist)
291*3302Smckusic 	register struct nl *p;
292*3302Smckusic 	int *formalist;
293*3302Smckusic {
294*3302Smckusic 	struct nl *chainp, *savedp;
295*3302Smckusic 	struct nl *dp;
296*3302Smckusic 	register int **formalp;		/* an element of the formal list */
297*3302Smckusic 	register int *formal;		/* a formal */
298*3302Smckusic 	int *typ, *idlist;
299*3302Smckusic 	int w, o;
300*3302Smckusic 
301*3302Smckusic 	/*
302*3302Smckusic 	 * Enter the parameters
303*3302Smckusic 	 * and compute total size
304*3302Smckusic 	 */
305*3302Smckusic 	chainp = savedp = p;
306*3302Smckusic 
307*3302Smckusic #	ifdef OBJ
308*3302Smckusic 	    o = 0;
309*3302Smckusic #	endif OBJ
310*3302Smckusic #	ifdef PC
311*3302Smckusic 		/*
312*3302Smckusic 		 * parameters used to be allocated backwards,
313*3302Smckusic 		 * then fixed.  for pc, they are allocated correctly.
314*3302Smckusic 		 * also, they are aligned.
315*3302Smckusic 		 */
316*3302Smckusic 	    o = DPOFF2;
317*3302Smckusic #	endif PC
318*3302Smckusic 	for (formalp = formalist; formalp != NIL; formalp = formalp[2]) {
319*3302Smckusic 		p = NIL;
320*3302Smckusic 		formal = formalp[1];
321*3302Smckusic 		if (formal == NIL)
322*3302Smckusic 			continue;
323*3302Smckusic 		/*
324*3302Smckusic 		 * Parametric procedures
325*3302Smckusic 		 * don't have types !?!
326*3302Smckusic 		 */
327*3302Smckusic 		typ = formal[2];
328*3302Smckusic 		if ( typ == NIL ) {
329*3302Smckusic 		    if ( formal[0] != T_PPROC ) {
330*3302Smckusic 			error("Types must be specified for arguments");
331*3302Smckusic 			p = NIL;
332*3302Smckusic 		    }
333*3302Smckusic 		} else {
334*3302Smckusic 		    if ( formal[0] == T_PPROC ) {
335*3302Smckusic 			error("Procedures cannot have types");
336*3302Smckusic 			p = NIL;
337*3302Smckusic 		    } else {
338*3302Smckusic 			if (typ[0] != T_TYID) {
339*3302Smckusic 				error("Types for arguments can be specified only by using type identifiers");
340*3302Smckusic 				p = NIL;
341*3302Smckusic 			} else {
342*3302Smckusic 				p = gtype(typ);
343*3302Smckusic 			}
344*3302Smckusic 		    }
345*3302Smckusic 		}
346*3302Smckusic 		for (idlist = formal[1]; idlist != NIL; idlist = idlist[2]) {
347*3302Smckusic 			switch (formal[0]) {
348*3302Smckusic 			    default:
349*3302Smckusic 				    panic("funchdr2");
350*3302Smckusic 			    case T_PVAL:
351*3302Smckusic 				    if (p != NIL) {
352*3302Smckusic 					    if (p->class == FILET)
353*3302Smckusic 						    error("Files cannot be passed by value");
354*3302Smckusic 					    else if (p->nl_flags & NFILES)
355*3302Smckusic 						    error("Files cannot be a component of %ss passed by value",
356*3302Smckusic 							    nameof(p));
357*3302Smckusic 				    }
358*3302Smckusic #				    ifdef OBJ
359*3302Smckusic 					w = lwidth(p);
360*3302Smckusic 					o -= even(w);
361*3302Smckusic #					ifdef DEC11
362*3302Smckusic 					    dp = defnl(idlist[1], VAR, p, o);
363*3302Smckusic #					else
364*3302Smckusic 					    dp = defnl(idlist[1], VAR, p,
365*3302Smckusic 						(w < 2) ? o + 1 : o);
366*3302Smckusic #					endif DEC11
367*3302Smckusic #				    endif OBJ
368*3302Smckusic #				    ifdef PC
369*3302Smckusic 					dp = defnl( idlist[1] , VAR , p
370*3302Smckusic 						, o = roundup( o , (long)A_STACK ) );
371*3302Smckusic 					o += lwidth( p );
372*3302Smckusic #				    endif PC
373*3302Smckusic 				    dp->nl_flags |= NMOD;
374*3302Smckusic 				    break;
375*3302Smckusic 			    case T_PVAR:
376*3302Smckusic #				    ifdef OBJ
377*3302Smckusic 					dp = defnl(idlist[1], REF, p, o -= sizeof ( int * ) );
378*3302Smckusic #				    endif OBJ
379*3302Smckusic #				    ifdef PC
380*3302Smckusic 					dp = defnl( idlist[1] , REF , p
381*3302Smckusic 						, o = roundup( o , (long)A_STACK ) );
382*3302Smckusic 					o += sizeof(char *);
383*3302Smckusic #				    endif PC
384*3302Smckusic 				    break;
385*3302Smckusic 			    case T_PFUNC:
386*3302Smckusic 				    if (idlist[2] != NIL) {
387*3302Smckusic 					error("Each function argument must be declared separately");
388*3302Smckusic 					idlist[2] = NIL;
389*3302Smckusic 				    }
390*3302Smckusic #				    ifdef OBJ
391*3302Smckusic 					dp = defnl(idlist[1], FFUNC, p, o -= sizeof ( int * ) );
392*3302Smckusic #				    endif OBJ
393*3302Smckusic #				    ifdef PC
394*3302Smckusic 					dp = defnl( idlist[1] , FFUNC , p
395*3302Smckusic 						, o = roundup( o , (long)A_STACK ) );
396*3302Smckusic 					o += sizeof(char *);
397*3302Smckusic #				    endif PC
398*3302Smckusic 				    dp -> nl_flags |= NMOD;
399*3302Smckusic 				    fparams(dp, formal);
400*3302Smckusic 				    break;
401*3302Smckusic 			    case T_PPROC:
402*3302Smckusic 				    if (idlist[2] != NIL) {
403*3302Smckusic 					error("Each procedure argument must be declared separately");
404*3302Smckusic 					idlist[2] = NIL;
405*3302Smckusic 				    }
406*3302Smckusic #				    ifdef OBJ
407*3302Smckusic 					dp = defnl(idlist[1], FPROC, p, o -= sizeof ( int * ) );
408*3302Smckusic #				    endif OBJ
409*3302Smckusic #				    ifdef PC
410*3302Smckusic 					dp = defnl( idlist[1] , FPROC , p
411*3302Smckusic 						, o = roundup( o , (long)A_STACK ) );
412*3302Smckusic 					o += sizeof(char *);
413*3302Smckusic #				    endif PC
414*3302Smckusic 				    dp -> nl_flags |= NMOD;
415*3302Smckusic 				    fparams(dp, formal);
416*3302Smckusic 				    break;
417*3302Smckusic 			    }
418*3302Smckusic 			if (dp != NIL) {
419*3302Smckusic 				chainp->chain = dp;
420*3302Smckusic 				chainp = dp;
421*3302Smckusic 			}
422*3302Smckusic 		}
423*3302Smckusic 	}
424*3302Smckusic 	p = savedp;
425*3302Smckusic #	ifdef OBJ
426*3302Smckusic 		/*
427*3302Smckusic 		 * Correct the naivete (naivety)
428*3302Smckusic 		 * of our above code to
429*3302Smckusic 		 * calculate offsets
430*3302Smckusic 		 */
431*3302Smckusic 	    for (dp = p->chain; dp != NIL; dp = dp->chain)
432*3302Smckusic 		    dp->value[NL_OFFS] += -o + DPOFF2;
433*3302Smckusic 	    return (-o + DPOFF2);
434*3302Smckusic #	endif OBJ
435*3302Smckusic #	ifdef PC
436*3302Smckusic 	    return roundup( o , (long)A_STACK );
437*3302Smckusic #	endif PC
438*3302Smckusic }
439