xref: /csrg-svn/usr.bin/pascal/src/fhdr.c (revision 7589)
13191Smckusick /* Copyright (c) 1979 Regents of the University of California */
23191Smckusick 
3*7589Speter static char sccsid[] = "@(#)fhdr.c 1.4 07/29/82";
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;
453302Smckusic 	struct nl *cp, *dp;
463302Smckusic 	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.
62*7589Speter 		 * check that forwards are of the right kind:
63*7589Speter 		 *     if this fails, we are trying to redefine it
64*7589Speter 		 *     and enter() will complain.
653191Smckusick 		 */
66*7589Speter 		if (  ( ( p->nl_flags & NFORWD ) != 0 )
67*7589Speter 		   && (  ( p->class == FUNC && r[0] == T_FDEC )
68*7589Speter 		      || ( p->class == PROC && r[0] == T_PDEC ) ) ) {
693191Smckusick 			/*
703191Smckusick 			 * Grammar doesnt forbid
713191Smckusick 			 * types on a resolution
723191Smckusick 			 * of a forward function
733191Smckusick 			 * declaration.
743191Smckusick 			 */
753191Smckusick 			if (p->class == FUNC && r[4])
763191Smckusick 				error("Function type should be given only in forward declaration");
773191Smckusick 			/*
783191Smckusick 			 * get another counter for the actual
793191Smckusick 			 */
803191Smckusick 			if ( monflg ) {
813191Smckusick 			    bodycnts[ cbn ] = getcnt();
823191Smckusick 			}
833191Smckusick #			ifdef PC
843191Smckusick 			    enclosing[ cbn ] = p -> symbol;
853191Smckusick #			endif PC
863191Smckusick #			ifdef PTREE
873191Smckusick 				/*
883191Smckusick 				 *	mark this proc/func as forward
893191Smckusick 				 *	in the pTree.
903191Smckusick 				 */
913191Smckusick 			    pDEF( p -> inTree ).PorFForward = TRUE;
923191Smckusick #			endif PTREE
933191Smckusick 			return (p);
943191Smckusick 		}
953191Smckusick 	}
963191Smckusick 
973191Smckusick 	/* if a routine segment is being compiled,
983191Smckusick 	 * do level one processing.
993191Smckusick 	 */
1003191Smckusick 
1013191Smckusick 	 if ((r[0] != T_PROG) && (!progseen))
1023191Smckusick 		level1();
1033191Smckusick 
1043191Smckusick 
1053191Smckusick 	/*
1063191Smckusick 	 * Declare the prog/proc/func
1073191Smckusick 	 */
1083191Smckusick 	switch (r[0]) {
1093191Smckusick 	    case T_PROG:
1103191Smckusick 		    progseen = TRUE;
1113191Smckusick 		    if (opt('z'))
1123191Smckusick 			    monflg = TRUE;
1133191Smckusick 		    program = p = defnl(r[2], PROG, 0, 0);
1143191Smckusick 		    p->value[3] = r[1];
1153191Smckusick 		    break;
1163191Smckusick 	    case T_PDEC:
1173191Smckusick 		    if (r[4] != NIL)
1183191Smckusick 			    error("Procedures do not have types, only functions do");
1193191Smckusick 		    p = enter(defnl(r[2], PROC, 0, 0));
1203191Smckusick 		    p->nl_flags |= NMOD;
1213191Smckusick #		    ifdef PC
1223191Smckusick 			enclosing[ cbn ] = r[2];
1233838Speter 			p -> extra_flags |= NGLOBAL;
1243191Smckusick #		    endif PC
1253191Smckusick 		    break;
1263191Smckusick 	    case T_FDEC:
1273191Smckusick 		    il = r[4];
1283191Smckusick 		    if (il == NIL)
1293191Smckusick 			    error("Function type must be specified");
1303191Smckusick 		    else if (il[0] != T_TYID) {
1313191Smckusick 			    il = NIL;
1323191Smckusick 			    error("Function type can be specified only by using a type identifier");
1333191Smckusick 		    } else
1343191Smckusick 			    il = gtype(il);
1353191Smckusick 		    p = enter(defnl(r[2], FUNC, il, NIL));
1363191Smckusick 		    p->nl_flags |= NMOD;
1373191Smckusick 		    /*
1383191Smckusick 		     * An arbitrary restriction
1393191Smckusick 		     */
1403191Smckusick 		    switch (o = classify(p->type)) {
1413191Smckusick 			    case TFILE:
1423191Smckusick 			    case TARY:
1433191Smckusick 			    case TREC:
1443191Smckusick 			    case TSET:
1453191Smckusick 			    case TSTR:
1463191Smckusick 				    warning();
1473191Smckusick 				    if (opt('s')) {
1483191Smckusick 					    standard();
1493191Smckusick 				    }
1503191Smckusick 				    error("Functions should not return %ss", clnames[o]);
1513191Smckusick 		    }
1523191Smckusick #		    ifdef PC
1533191Smckusick 			enclosing[ cbn ] = r[2];
1543838Speter 			p -> extra_flags |= NGLOBAL;
1553191Smckusick #		    endif PC
1563191Smckusick 		    break;
1573191Smckusick 	    default:
1583191Smckusick 		    panic("funchdr");
1593191Smckusick 	}
1603191Smckusick 	if (r[0] != T_PROG) {
1613191Smckusick 		/*
1623191Smckusick 		 * Mark this proc/func as
1633191Smckusick 		 * being forward declared
1643191Smckusick 		 */
1653191Smckusick 		p->nl_flags |= NFORWD;
1663191Smckusick 		/*
1673191Smckusick 		 * Enter the parameters
1683191Smckusick 		 * in the next block for
1693191Smckusick 		 * the time being
1703191Smckusick 		 */
1713191Smckusick 		if (++cbn >= DSPLYSZ) {
1723191Smckusick 			error("Procedure/function nesting too deep");
1733191Smckusick 			pexit(ERRS);
1743191Smckusick 		}
1753191Smckusick 		/*
1763191Smckusick 		 * For functions, the function variable
1773191Smckusick 		 */
1783191Smckusick 		if (p->class == FUNC) {
1793191Smckusick #			ifdef OBJ
1803191Smckusick 			    cp = defnl(r[2], FVAR, p->type, 0);
1813191Smckusick #			endif OBJ
1823191Smckusick #			ifdef PC
1833191Smckusick 				/*
1843191Smckusick 				 * fvars used to be allocated and deallocated
1853191Smckusick 				 * by the caller right before the arguments.
1863191Smckusick 				 * the offset of the fvar was kept in
1873191Smckusick 				 * value[NL_OFFS] of function (very wierd,
1883191Smckusick 				 * but see asgnop).
1893191Smckusick 				 * now, they are locals to the function
1903191Smckusick 				 * with the offset kept in the fvar.
1913191Smckusick 				 */
1923191Smckusick 
1933191Smckusick 			    cp = defnl(r[2], FVAR, p->type,
1943302Smckusic 				(int)-leven(roundup(
1953302Smckusic 			            (int)(DPOFF1+lwidth(p->type)),
1963302Smckusic 				    (long)align(p->type))));
1973838Speter 			    cp -> extra_flags |= NLOCAL;
1983191Smckusick #			endif PC
1993191Smckusick 			cp->chain = p;
2003191Smckusick 			p->ptr[NL_FVAR] = cp;
2013191Smckusick 		}
2023191Smckusick 		/*
2033191Smckusick 		 * Enter the parameters
2043191Smckusick 		 * and compute total size
2053191Smckusick 		 */
2063302Smckusic 	        p->value[NL_OFFS] = params(p, r[3]);
2073302Smckusic 		/*
2083302Smckusic 		 * because NL_LINENO field in the function
2093302Smckusic 		 * namelist entry has been used (as have all
2103302Smckusic 		 * the other fields), the line number is
2113302Smckusic 		 * stored in the NL_LINENO field of its fvar.
2123302Smckusic 		 */
2133302Smckusic 		if (p->class == FUNC)
2143302Smckusic 		    p->ptr[NL_FVAR]->value[NL_LINENO] = r[1];
2153302Smckusic 		else
2163302Smckusic 		    p->value[NL_LINENO] = r[1];
2173191Smckusick 		cbn--;
2183191Smckusick 	} else {
2193191Smckusick 		/*
2203191Smckusick 		 * The wonderful
2213191Smckusick 		 * program statement!
2223191Smckusick 		 */
2233191Smckusick #		ifdef OBJ
2243191Smckusick 		    if (monflg) {
2253191Smckusick 			    put(1, O_PXPBUF);
2263191Smckusick 			    cntpatch = put(2, O_CASE4, (long)0);
2273191Smckusick 			    nfppatch = put(2, O_CASE4, (long)0);
2283191Smckusick 		    }
2293191Smckusick #		endif OBJ
2303191Smckusick 		cp = p;
2313191Smckusick 		for (rl = r[3]; rl; rl = rl[2]) {
2323191Smckusick 			if (rl[1] == NIL)
2333191Smckusick 				continue;
2343191Smckusick 			dp = defnl(rl[1], VAR, 0, 0);
2353191Smckusick 			cp->chain = dp;
2363191Smckusick 			cp = dp;
2373191Smckusick 		}
2383191Smckusick 	}
2393191Smckusick 	/*
2403191Smckusick 	 * Define a branch at
2413191Smckusick 	 * the "entry point" of
2423191Smckusick 	 * the prog/proc/func.
2433191Smckusick 	 */
2443191Smckusick 	p->entloc = getlab();
2453191Smckusick 	if (monflg) {
2463191Smckusick 		bodycnts[ cbn ] = getcnt();
2473191Smckusick 		p->value[ NL_CNTR ] = 0;
2483191Smckusick 	}
2493191Smckusick #	ifdef OBJ
2503191Smckusick 	    put(2, O_TRA4, (long)p->entloc);
2513191Smckusick #	endif OBJ
2523191Smckusick #	ifdef PTREE
2533191Smckusick 	    {
2543191Smckusick 		pPointer	PF = tCopy( r );
2553191Smckusick 
2563191Smckusick 		pSeize( PorFHeader[ nesting ] );
2573191Smckusick 		if ( r[0] != T_PROG ) {
2583191Smckusick 			pPointer	*PFs;
2593191Smckusick 
2603191Smckusick 			PFs = &( pDEF( PorFHeader[ nesting ] ).PorFPFs );
2613191Smckusick 			*PFs = ListAppend( *PFs , PF );
2623191Smckusick 		} else {
2633191Smckusick 			pDEF( PorFHeader[ nesting ] ).GlobProg = PF;
2643191Smckusick 		}
2653191Smckusick 		pRelease( PorFHeader[ nesting ] );
2663191Smckusick 	    }
2673191Smckusick #	endif PTREE
2683191Smckusick 	return (p);
2693191Smckusick }
2703302Smckusic 
2713302Smckusic 	/*
2723302Smckusic 	 * deal with the parameter declaration for a routine.
2733302Smckusic 	 * p is the namelist entry of the routine.
2743302Smckusic 	 * formalist is the parse tree for the parameter declaration.
2753302Smckusic 	 * formalist	[0]	T_LISTPP
2763302Smckusic 	 *		[1]	pointer to a formal
2773302Smckusic 	 *		[2]	pointer to next formal
2783302Smckusic 	 * for by-value or by-reference formals, the formal is
2793302Smckusic 	 * formal	[0]	T_PVAL or T_PVAR
2803302Smckusic 	 *		[1]	pointer to id_list
2813302Smckusic 	 *		[2]	pointer to type (error if not typeid)
2823302Smckusic 	 * for function and procedure formals, the formal is
2833302Smckusic 	 * formal	[0]	T_PFUNC or T_PPROC
2843302Smckusic 	 *		[1]	pointer to id_list (error if more than one)
2853302Smckusic 	 *		[2]	pointer to type (error if not typeid, or proc)
2863302Smckusic 	 *		[3]	pointer to formalist for this routine.
2873302Smckusic 	 */
2883302Smckusic fparams(p, formal)
2893302Smckusic 	register struct nl *p;
2903302Smckusic 	int *formal;
2913302Smckusic {
2923302Smckusic 	params(p, formal[3]);
2933302Smckusic 	p -> value[ NL_LINENO ] = formal[4];
2943302Smckusic 	p -> ptr[ NL_FCHAIN ] = p -> chain;
2953302Smckusic 	p -> chain = NIL;
2963302Smckusic }
2973302Smckusic 
2983302Smckusic params(p, formalist)
2993302Smckusic 	register struct nl *p;
3003302Smckusic 	int *formalist;
3013302Smckusic {
3023302Smckusic 	struct nl *chainp, *savedp;
3033302Smckusic 	struct nl *dp;
3043302Smckusic 	register int **formalp;		/* an element of the formal list */
3053302Smckusic 	register int *formal;		/* a formal */
3063302Smckusic 	int *typ, *idlist;
3073302Smckusic 	int w, o;
3083302Smckusic 
3093302Smckusic 	/*
3103302Smckusic 	 * Enter the parameters
3113302Smckusic 	 * and compute total size
3123302Smckusic 	 */
3133302Smckusic 	chainp = savedp = p;
3143302Smckusic 
3153302Smckusic #	ifdef OBJ
3163302Smckusic 	    o = 0;
3173302Smckusic #	endif OBJ
3183302Smckusic #	ifdef PC
3193302Smckusic 		/*
3203302Smckusic 		 * parameters used to be allocated backwards,
3213302Smckusic 		 * then fixed.  for pc, they are allocated correctly.
3223302Smckusic 		 * also, they are aligned.
3233302Smckusic 		 */
3243302Smckusic 	    o = DPOFF2;
3253302Smckusic #	endif PC
3263302Smckusic 	for (formalp = formalist; formalp != NIL; formalp = formalp[2]) {
3273302Smckusic 		p = NIL;
3283302Smckusic 		formal = formalp[1];
3293302Smckusic 		if (formal == NIL)
3303302Smckusic 			continue;
3313302Smckusic 		/*
3323302Smckusic 		 * Parametric procedures
3333302Smckusic 		 * don't have types !?!
3343302Smckusic 		 */
3353302Smckusic 		typ = formal[2];
3363302Smckusic 		if ( typ == NIL ) {
3373302Smckusic 		    if ( formal[0] != T_PPROC ) {
3383302Smckusic 			error("Types must be specified for arguments");
3393302Smckusic 			p = NIL;
3403302Smckusic 		    }
3413302Smckusic 		} else {
3423302Smckusic 		    if ( formal[0] == T_PPROC ) {
3433302Smckusic 			error("Procedures cannot have types");
3443302Smckusic 			p = NIL;
3453302Smckusic 		    } else {
3463302Smckusic 			if (typ[0] != T_TYID) {
3473302Smckusic 				error("Types for arguments can be specified only by using type identifiers");
3483302Smckusic 				p = NIL;
3493302Smckusic 			} else {
3503302Smckusic 				p = gtype(typ);
3513302Smckusic 			}
3523302Smckusic 		    }
3533302Smckusic 		}
3543302Smckusic 		for (idlist = formal[1]; idlist != NIL; idlist = idlist[2]) {
3553302Smckusic 			switch (formal[0]) {
3563302Smckusic 			    default:
3573302Smckusic 				    panic("funchdr2");
3583302Smckusic 			    case T_PVAL:
3593302Smckusic 				    if (p != NIL) {
3603302Smckusic 					    if (p->class == FILET)
3613302Smckusic 						    error("Files cannot be passed by value");
3623302Smckusic 					    else if (p->nl_flags & NFILES)
3633302Smckusic 						    error("Files cannot be a component of %ss passed by value",
3643302Smckusic 							    nameof(p));
3653302Smckusic 				    }
3663302Smckusic #				    ifdef OBJ
3673302Smckusic 					w = lwidth(p);
3683302Smckusic 					o -= even(w);
3693302Smckusic #					ifdef DEC11
3703302Smckusic 					    dp = defnl(idlist[1], VAR, p, o);
3713302Smckusic #					else
3723302Smckusic 					    dp = defnl(idlist[1], VAR, p,
3733302Smckusic 						(w < 2) ? o + 1 : o);
3743302Smckusic #					endif DEC11
3753302Smckusic #				    endif OBJ
3763302Smckusic #				    ifdef PC
3773302Smckusic 					dp = defnl( idlist[1] , VAR , p
3783302Smckusic 						, o = roundup( o , (long)A_STACK ) );
3793302Smckusic 					o += lwidth( p );
3803302Smckusic #				    endif PC
3813302Smckusic 				    dp->nl_flags |= NMOD;
3823302Smckusic 				    break;
3833302Smckusic 			    case T_PVAR:
3843302Smckusic #				    ifdef OBJ
3853302Smckusic 					dp = defnl(idlist[1], REF, p, o -= sizeof ( int * ) );
3863302Smckusic #				    endif OBJ
3873302Smckusic #				    ifdef PC
3883302Smckusic 					dp = defnl( idlist[1] , REF , p
3893302Smckusic 						, o = roundup( o , (long)A_STACK ) );
3903302Smckusic 					o += sizeof(char *);
3913302Smckusic #				    endif PC
3923302Smckusic 				    break;
3933302Smckusic 			    case T_PFUNC:
3943302Smckusic 				    if (idlist[2] != NIL) {
3953302Smckusic 					error("Each function argument must be declared separately");
3963302Smckusic 					idlist[2] = NIL;
3973302Smckusic 				    }
3983302Smckusic #				    ifdef OBJ
3993302Smckusic 					dp = defnl(idlist[1], FFUNC, p, o -= sizeof ( int * ) );
4003302Smckusic #				    endif OBJ
4013302Smckusic #				    ifdef PC
4023302Smckusic 					dp = defnl( idlist[1] , FFUNC , p
4033302Smckusic 						, o = roundup( o , (long)A_STACK ) );
4043302Smckusic 					o += sizeof(char *);
4053302Smckusic #				    endif PC
4063302Smckusic 				    dp -> nl_flags |= NMOD;
4073302Smckusic 				    fparams(dp, formal);
4083302Smckusic 				    break;
4093302Smckusic 			    case T_PPROC:
4103302Smckusic 				    if (idlist[2] != NIL) {
4113302Smckusic 					error("Each procedure argument must be declared separately");
4123302Smckusic 					idlist[2] = NIL;
4133302Smckusic 				    }
4143302Smckusic #				    ifdef OBJ
4153302Smckusic 					dp = defnl(idlist[1], FPROC, p, o -= sizeof ( int * ) );
4163302Smckusic #				    endif OBJ
4173302Smckusic #				    ifdef PC
4183302Smckusic 					dp = defnl( idlist[1] , FPROC , p
4193302Smckusic 						, o = roundup( o , (long)A_STACK ) );
4203302Smckusic 					o += sizeof(char *);
4213302Smckusic #				    endif PC
4223302Smckusic 				    dp -> nl_flags |= NMOD;
4233302Smckusic 				    fparams(dp, formal);
4243302Smckusic 				    break;
4253302Smckusic 			    }
4263302Smckusic 			if (dp != NIL) {
4273838Speter #				ifdef PC
4283838Speter 				    dp -> extra_flags |= NPARAM;
4293838Speter #				endif PC
4303302Smckusic 				chainp->chain = dp;
4313302Smckusic 				chainp = dp;
4323302Smckusic 			}
4333302Smckusic 		}
4343302Smckusic 	}
4353302Smckusic 	p = savedp;
4363302Smckusic #	ifdef OBJ
4373302Smckusic 		/*
4383302Smckusic 		 * Correct the naivete (naivety)
4393302Smckusic 		 * of our above code to
4403302Smckusic 		 * calculate offsets
4413302Smckusic 		 */
4423302Smckusic 	    for (dp = p->chain; dp != NIL; dp = dp->chain)
4433302Smckusic 		    dp->value[NL_OFFS] += -o + DPOFF2;
4443302Smckusic 	    return (-o + DPOFF2);
4453302Smckusic #	endif OBJ
4463302Smckusic #	ifdef PC
4473302Smckusic 	    return roundup( o , (long)A_STACK );
4483302Smckusic #	endif PC
4493302Smckusic }
450