xref: /csrg-svn/usr.bin/pascal/src/fhdr.c (revision 3191)
1*3191Smckusick /* Copyright (c) 1979 Regents of the University of California */
2*3191Smckusick 
3*3191Smckusick static char sccsid[] = "@(#)fhdr.c 1.1 03/11/81";
4*3191Smckusick 
5*3191Smckusick #include "whoami.h"
6*3191Smckusick #include "0.h"
7*3191Smckusick #include "tree.h"
8*3191Smckusick #include "opcode.h"
9*3191Smckusick #include "objfmt.h"
10*3191Smckusick #include "align.h"
11*3191Smckusick 
12*3191Smckusick /*
13*3191Smckusick  * this array keeps the pxp counters associated with
14*3191Smckusick  * functions and procedures, so that they can be output
15*3191Smckusick  * when their bodies are encountered
16*3191Smckusick  */
17*3191Smckusick int	bodycnts[ DSPLYSZ ];
18*3191Smckusick 
19*3191Smckusick #ifdef PC
20*3191Smckusick #   include "pc.h"
21*3191Smckusick #   include "pcops.h"
22*3191Smckusick #endif PC
23*3191Smckusick 
24*3191Smckusick #ifdef OBJ
25*3191Smckusick int	cntpatch;
26*3191Smckusick int	nfppatch;
27*3191Smckusick #endif OBJ
28*3191Smckusick 
29*3191Smckusick /*
30*3191Smckusick  * Funchdr inserts
31*3191Smckusick  * declaration of a the
32*3191Smckusick  * prog/proc/func into the
33*3191Smckusick  * namelist. It also handles
34*3191Smckusick  * the arguments and puts out
35*3191Smckusick  * a transfer which defines
36*3191Smckusick  * the entry point of a procedure.
37*3191Smckusick  */
38*3191Smckusick 
39*3191Smckusick struct nl *
40*3191Smckusick funchdr(r)
41*3191Smckusick 	int *r;
42*3191Smckusick {
43*3191Smckusick 	register struct nl *p;
44*3191Smckusick 	register *il, **rl;
45*3191Smckusick 	int *rll;
46*3191Smckusick 	struct nl *cp, *dp, *sp;
47*3191Smckusick 	int w, s, o, *pp;
48*3191Smckusick 
49*3191Smckusick 	if (inpflist(r[2])) {
50*3191Smckusick 		opush('l');
51*3191Smckusick 		yyretrieve();	/* kludge */
52*3191Smckusick 	}
53*3191Smckusick 	pfcnt++;
54*3191Smckusick 	parts[ cbn ] |= RPRT;
55*3191Smckusick 	line = r[1];
56*3191Smckusick 	if (r[3] == NIL && (p=lookup1(r[2])) != NIL && bn == cbn) {
57*3191Smckusick 		/*
58*3191Smckusick 		 * Symbol already defined
59*3191Smckusick 		 * in this block. it is either
60*3191Smckusick 		 * a redeclared symbol (error)
61*3191Smckusick 		 * a forward declaration,
62*3191Smckusick 		 * or an external declaration.
63*3191Smckusick 		 */
64*3191Smckusick 		if ((p->class == FUNC || p->class == PROC) && (p->nl_flags & NFORWD) != 0) {
65*3191Smckusick 			/*
66*3191Smckusick 			 * Grammar doesnt forbid
67*3191Smckusick 			 * types on a resolution
68*3191Smckusick 			 * of a forward function
69*3191Smckusick 			 * declaration.
70*3191Smckusick 			 */
71*3191Smckusick 			if (p->class == FUNC && r[4])
72*3191Smckusick 				error("Function type should be given only in forward declaration");
73*3191Smckusick 			/*
74*3191Smckusick 			 * get another counter for the actual
75*3191Smckusick 			 */
76*3191Smckusick 			if ( monflg ) {
77*3191Smckusick 			    bodycnts[ cbn ] = getcnt();
78*3191Smckusick 			}
79*3191Smckusick #			ifdef PC
80*3191Smckusick 			    enclosing[ cbn ] = p -> symbol;
81*3191Smckusick #			endif PC
82*3191Smckusick #			ifdef PTREE
83*3191Smckusick 				/*
84*3191Smckusick 				 *	mark this proc/func as forward
85*3191Smckusick 				 *	in the pTree.
86*3191Smckusick 				 */
87*3191Smckusick 			    pDEF( p -> inTree ).PorFForward = TRUE;
88*3191Smckusick #			endif PTREE
89*3191Smckusick 			return (p);
90*3191Smckusick 		}
91*3191Smckusick 	}
92*3191Smckusick 
93*3191Smckusick 	/* if a routine segment is being compiled,
94*3191Smckusick 	 * do level one processing.
95*3191Smckusick 	 */
96*3191Smckusick 
97*3191Smckusick 	 if ((r[0] != T_PROG) && (!progseen))
98*3191Smckusick 		level1();
99*3191Smckusick 
100*3191Smckusick 
101*3191Smckusick 	/*
102*3191Smckusick 	 * Declare the prog/proc/func
103*3191Smckusick 	 */
104*3191Smckusick 	switch (r[0]) {
105*3191Smckusick 	    case T_PROG:
106*3191Smckusick 		    progseen = TRUE;
107*3191Smckusick 		    if (opt('z'))
108*3191Smckusick 			    monflg = TRUE;
109*3191Smckusick 		    program = p = defnl(r[2], PROG, 0, 0);
110*3191Smckusick 		    p->value[3] = r[1];
111*3191Smckusick 		    break;
112*3191Smckusick 	    case T_PDEC:
113*3191Smckusick 		    if (r[4] != NIL)
114*3191Smckusick 			    error("Procedures do not have types, only functions do");
115*3191Smckusick 		    p = enter(defnl(r[2], PROC, 0, 0));
116*3191Smckusick 		    p->nl_flags |= NMOD;
117*3191Smckusick #		    ifdef PC
118*3191Smckusick 			enclosing[ cbn ] = r[2];
119*3191Smckusick #		    endif PC
120*3191Smckusick 		    break;
121*3191Smckusick 	    case T_FDEC:
122*3191Smckusick 		    il = r[4];
123*3191Smckusick 		    if (il == NIL)
124*3191Smckusick 			    error("Function type must be specified");
125*3191Smckusick 		    else if (il[0] != T_TYID) {
126*3191Smckusick 			    il = NIL;
127*3191Smckusick 			    error("Function type can be specified only by using a type identifier");
128*3191Smckusick 		    } else
129*3191Smckusick 			    il = gtype(il);
130*3191Smckusick 		    p = enter(defnl(r[2], FUNC, il, NIL));
131*3191Smckusick 		    p->nl_flags |= NMOD;
132*3191Smckusick 		    /*
133*3191Smckusick 		     * An arbitrary restriction
134*3191Smckusick 		     */
135*3191Smckusick 		    switch (o = classify(p->type)) {
136*3191Smckusick 			    case TFILE:
137*3191Smckusick 			    case TARY:
138*3191Smckusick 			    case TREC:
139*3191Smckusick 			    case TSET:
140*3191Smckusick 			    case TSTR:
141*3191Smckusick 				    warning();
142*3191Smckusick 				    if (opt('s')) {
143*3191Smckusick 					    standard();
144*3191Smckusick 				    }
145*3191Smckusick 				    error("Functions should not return %ss", clnames[o]);
146*3191Smckusick 		    }
147*3191Smckusick #		    ifdef PC
148*3191Smckusick 			enclosing[ cbn ] = r[2];
149*3191Smckusick #		    endif PC
150*3191Smckusick 		    break;
151*3191Smckusick 	    default:
152*3191Smckusick 		    panic("funchdr");
153*3191Smckusick 	}
154*3191Smckusick 	if (r[0] != T_PROG) {
155*3191Smckusick 		/*
156*3191Smckusick 		 * Mark this proc/func as
157*3191Smckusick 		 * being forward declared
158*3191Smckusick 		 */
159*3191Smckusick 		p->nl_flags |= NFORWD;
160*3191Smckusick 		/*
161*3191Smckusick 		 * Enter the parameters
162*3191Smckusick 		 * in the next block for
163*3191Smckusick 		 * the time being
164*3191Smckusick 		 */
165*3191Smckusick 		if (++cbn >= DSPLYSZ) {
166*3191Smckusick 			error("Procedure/function nesting too deep");
167*3191Smckusick 			pexit(ERRS);
168*3191Smckusick 		}
169*3191Smckusick 		/*
170*3191Smckusick 		 * For functions, the function variable
171*3191Smckusick 		 */
172*3191Smckusick 		if (p->class == FUNC) {
173*3191Smckusick #			ifdef OBJ
174*3191Smckusick 			    cp = defnl(r[2], FVAR, p->type, 0);
175*3191Smckusick #			endif OBJ
176*3191Smckusick #			ifdef PC
177*3191Smckusick 				/*
178*3191Smckusick 				 * fvars used to be allocated and deallocated
179*3191Smckusick 				 * by the caller right before the arguments.
180*3191Smckusick 				 * the offset of the fvar was kept in
181*3191Smckusick 				 * value[NL_OFFS] of function (very wierd,
182*3191Smckusick 				 * but see asgnop).
183*3191Smckusick 				 * now, they are locals to the function
184*3191Smckusick 				 * with the offset kept in the fvar.
185*3191Smckusick 				 */
186*3191Smckusick 
187*3191Smckusick 			    cp = defnl(r[2], FVAR, p->type,
188*3191Smckusick 				    -(roundup((int)(DPOFF1+lwidth(p->type)),
189*3191Smckusick 					(long)align(p->type))));
190*3191Smckusick #			endif PC
191*3191Smckusick 			cp->chain = p;
192*3191Smckusick 			p->ptr[NL_FVAR] = cp;
193*3191Smckusick 		}
194*3191Smckusick 		/*
195*3191Smckusick 		 * Enter the parameters
196*3191Smckusick 		 * and compute total size
197*3191Smckusick 		 */
198*3191Smckusick 		cp = sp = p;
199*3191Smckusick 
200*3191Smckusick #		ifdef OBJ
201*3191Smckusick 		    o = 0;
202*3191Smckusick #		endif OBJ
203*3191Smckusick #		ifdef PC
204*3191Smckusick 			/*
205*3191Smckusick 			 * parameters used to be allocated backwards,
206*3191Smckusick 			 * then fixed.  for pc, they are allocated correctly.
207*3191Smckusick 			 * also, they are aligned.
208*3191Smckusick 			 */
209*3191Smckusick 		o = DPOFF2;
210*3191Smckusick #		endif PC
211*3191Smckusick 		for (rl = r[3]; rl != NIL; rl = rl[2]) {
212*3191Smckusick 			p = NIL;
213*3191Smckusick 			if (rl[1] == NIL)
214*3191Smckusick 				continue;
215*3191Smckusick 			/*
216*3191Smckusick 			 * Parametric procedures
217*3191Smckusick 			 * don't have types !?!
218*3191Smckusick 			 */
219*3191Smckusick 			if (rl[1][0] != T_PPROC) {
220*3191Smckusick 				rll = rl[1][2];
221*3191Smckusick 				if (rll[0] != T_TYID) {
222*3191Smckusick 					error("Types for arguments can be specified only by using type identifiers");
223*3191Smckusick 					p = NIL;
224*3191Smckusick 				} else
225*3191Smckusick 					p = gtype(rll);
226*3191Smckusick 			}
227*3191Smckusick 			for (il = rl[1][1]; il != NIL; il = il[2]) {
228*3191Smckusick 				switch (rl[1][0]) {
229*3191Smckusick 				    default:
230*3191Smckusick 					    panic("funchdr2");
231*3191Smckusick 				    case T_PVAL:
232*3191Smckusick 					    if (p != NIL) {
233*3191Smckusick 						    if (p->class == FILET)
234*3191Smckusick 							    error("Files cannot be passed by value");
235*3191Smckusick 						    else if (p->nl_flags & NFILES)
236*3191Smckusick 							    error("Files cannot be a component of %ss passed by value",
237*3191Smckusick 								    nameof(p));
238*3191Smckusick 					    }
239*3191Smckusick #					    ifdef OBJ
240*3191Smckusick 						w = width(p);
241*3191Smckusick 						o -= even(w);
242*3191Smckusick #						ifdef DEC11
243*3191Smckusick 						    dp = defnl(il[1], VAR, p, o);
244*3191Smckusick #						else
245*3191Smckusick 						    dp = defnl(il[1], VAR, p,
246*3191Smckusick 							(w < 2) ? o + 1 : o);
247*3191Smckusick #						endif DEC11
248*3191Smckusick #					    endif OBJ
249*3191Smckusick #					    ifdef PC
250*3191Smckusick 						dp = defnl( il[1] , VAR , p
251*3191Smckusick 							, o = roundup( o , (long)A_STACK ) );
252*3191Smckusick 						o += width( p );
253*3191Smckusick #					    endif PC
254*3191Smckusick 					    dp->nl_flags |= NMOD;
255*3191Smckusick 					    break;
256*3191Smckusick 				    case T_PVAR:
257*3191Smckusick #					    ifdef OBJ
258*3191Smckusick 						dp = defnl(il[1], REF, p, o -= sizeof ( int * ) );
259*3191Smckusick #					    endif OBJ
260*3191Smckusick #					    ifdef PC
261*3191Smckusick 						dp = defnl( il[1] , REF , p
262*3191Smckusick 							, o = roundup( o , (long)A_STACK ) );
263*3191Smckusick 						o += sizeof(char *);
264*3191Smckusick #					    endif PC
265*3191Smckusick 					    break;
266*3191Smckusick 				    case T_PFUNC:
267*3191Smckusick #					    ifdef OBJ
268*3191Smckusick 						dp = defnl(il[1], FFUNC, p, o -= sizeof ( int * ) );
269*3191Smckusick #					    endif OBJ
270*3191Smckusick #					    ifdef PC
271*3191Smckusick 						dp = defnl( il[1] , FFUNC , p
272*3191Smckusick 							, o = roundup( o , (long)A_STACK ) );
273*3191Smckusick 						o += sizeof(char *);
274*3191Smckusick #					    endif PC
275*3191Smckusick 					    dp -> nl_flags |= NMOD;
276*3191Smckusick 					    break;
277*3191Smckusick 				    case T_PPROC:
278*3191Smckusick #					    ifdef OBJ
279*3191Smckusick 						dp = defnl(il[1], FPROC, p, o -= sizeof ( int * ) );
280*3191Smckusick #					    endif OBJ
281*3191Smckusick #					    ifdef PC
282*3191Smckusick 						dp = defnl( il[1] , FPROC , p
283*3191Smckusick 							, o = roundup( o , (long)A_STACK ) );
284*3191Smckusick 						o += sizeof(char *);
285*3191Smckusick #					    endif PC
286*3191Smckusick 					    dp -> nl_flags |= NMOD;
287*3191Smckusick 					    break;
288*3191Smckusick 				    }
289*3191Smckusick 				if (dp != NIL) {
290*3191Smckusick 					cp->chain = dp;
291*3191Smckusick 					cp = dp;
292*3191Smckusick 				}
293*3191Smckusick 			}
294*3191Smckusick 		}
295*3191Smckusick 		cbn--;
296*3191Smckusick 		p = sp;
297*3191Smckusick #		ifdef OBJ
298*3191Smckusick 		    p->value[NL_OFFS] = -o+DPOFF2;
299*3191Smckusick 			/*
300*3191Smckusick 			 * Correct the naivete (naievity)
301*3191Smckusick 			 * of our above code to
302*3191Smckusick 			 * calculate offsets
303*3191Smckusick 			 */
304*3191Smckusick 		    for (il = p->chain; il != NIL; il = il->chain)
305*3191Smckusick 			    il->value[NL_OFFS] += p->value[NL_OFFS];
306*3191Smckusick #		endif OBJ
307*3191Smckusick #		ifdef PC
308*3191Smckusick 		    p -> value[ NL_OFFS ] = roundup( o , (long)A_STACK );
309*3191Smckusick #		endif PC
310*3191Smckusick 	} else {
311*3191Smckusick 		/*
312*3191Smckusick 		 * The wonderful
313*3191Smckusick 		 * program statement!
314*3191Smckusick 		 */
315*3191Smckusick #		ifdef OBJ
316*3191Smckusick 		    if (monflg) {
317*3191Smckusick 			    put(1, O_PXPBUF);
318*3191Smckusick 			    cntpatch = put(2, O_CASE4, (long)0);
319*3191Smckusick 			    nfppatch = put(2, O_CASE4, (long)0);
320*3191Smckusick 		    }
321*3191Smckusick #		endif OBJ
322*3191Smckusick 		cp = p;
323*3191Smckusick 		for (rl = r[3]; rl; rl = rl[2]) {
324*3191Smckusick 			if (rl[1] == NIL)
325*3191Smckusick 				continue;
326*3191Smckusick 			dp = defnl(rl[1], VAR, 0, 0);
327*3191Smckusick 			cp->chain = dp;
328*3191Smckusick 			cp = dp;
329*3191Smckusick 		}
330*3191Smckusick 	}
331*3191Smckusick 	/*
332*3191Smckusick 	 * Define a branch at
333*3191Smckusick 	 * the "entry point" of
334*3191Smckusick 	 * the prog/proc/func.
335*3191Smckusick 	 */
336*3191Smckusick 	p->entloc = getlab();
337*3191Smckusick 	if (monflg) {
338*3191Smckusick 		bodycnts[ cbn ] = getcnt();
339*3191Smckusick 		p->value[ NL_CNTR ] = 0;
340*3191Smckusick 	}
341*3191Smckusick #	ifdef OBJ
342*3191Smckusick 	    put(2, O_TRA4, (long)p->entloc);
343*3191Smckusick #	endif OBJ
344*3191Smckusick #	ifdef PTREE
345*3191Smckusick 	    {
346*3191Smckusick 		pPointer	PF = tCopy( r );
347*3191Smckusick 
348*3191Smckusick 		pSeize( PorFHeader[ nesting ] );
349*3191Smckusick 		if ( r[0] != T_PROG ) {
350*3191Smckusick 			pPointer	*PFs;
351*3191Smckusick 
352*3191Smckusick 			PFs = &( pDEF( PorFHeader[ nesting ] ).PorFPFs );
353*3191Smckusick 			*PFs = ListAppend( *PFs , PF );
354*3191Smckusick 		} else {
355*3191Smckusick 			pDEF( PorFHeader[ nesting ] ).GlobProg = PF;
356*3191Smckusick 		}
357*3191Smckusick 		pRelease( PorFHeader[ nesting ] );
358*3191Smckusick 	    }
359*3191Smckusick #	endif PTREE
360*3191Smckusick 	return (p);
361*3191Smckusick }
362