xref: /original-bsd/usr.bin/pascal/src/fdec.c (revision f0fd5f8a)
1 /* Copyright (c) 1979 Regents of the University of California */
2 
3 static char sccsid[] = "@(#)fdec.c 1.22 08/12/82";
4 
5 #include "whoami.h"
6 #include "0.h"
7 #include "tree.h"
8 #include "opcode.h"
9 #include "objfmt.h"
10 #include "align.h"
11 
12 /*
13  * this array keeps the pxp counters associated with
14  * functions and procedures, so that they can be output
15  * when their bodies are encountered
16  */
17 int	bodycnts[ DSPLYSZ ];
18 
19 #ifdef PC
20 #   include "pc.h"
21 #   include "pcops.h"
22 #endif PC
23 
24 #ifdef OBJ
25 int	cntpatch;
26 int	nfppatch;
27 #endif OBJ
28 
29 funcfwd(fp)
30 	struct nl *fp;
31 {
32 
33 	    /*
34 	     *	save the counter for this function
35 	     */
36 	if ( monflg ) {
37 	    fp -> value[ NL_CNTR ] = bodycnts[ cbn ];
38 	}
39 	return (fp);
40 }
41 
42 /*
43  * Funcext marks the procedure or
44  * function external in the symbol
45  * table. Funcext should only be
46  * called if PC, and is an error
47  * otherwise.
48  */
49 
50 funcext(fp)
51 	struct nl *fp;
52 {
53 
54 #ifdef OBJ
55 	error("Procedures or functions cannot be declared external.");
56 #endif OBJ
57 
58 #ifdef PC
59 	    /*
60 	     *	save the counter for this function
61 	     */
62 	if ( monflg ) {
63 	    fp -> value[ NL_CNTR ] = bodycnts[ cbn ];
64 	}
65  	if (opt('s')) {
66 		standard();
67 		error("External procedures and functions are not standard");
68 	} else {
69 		if (cbn == 1) {
70 			fp->extra_flags |= NEXTERN;
71 			stabefunc( fp -> symbol , fp -> class , line );
72 		}
73 		else
74 			error("External procedures and functions can only be declared at the outermost level.");
75 	}
76 #endif PC
77 
78 	return(fp);
79 }
80 
81 /*
82  * Funcbody is called
83  * when the actual (resolved)
84  * declaration of a procedure is
85  * encountered. It puts the names
86  * of the (function) and parameters
87  * into the symbol table.
88  */
89 funcbody(fp)
90 	struct nl *fp;
91 {
92 	register struct nl *q, *p;
93 	struct nl	*functemp;
94 
95 	cbn++;
96 	if (cbn >= DSPLYSZ) {
97 		error("Too many levels of function/procedure nesting");
98 		pexit(ERRS);
99 	}
100 	sizes[cbn].om_max = sizes[cbn].curtmps.om_off = -DPOFF1;
101 	sizes[cbn].reg_max = -1;
102 	sizes[cbn].curtmps.reg_off = 0;
103 	gotos[cbn] = NIL;
104 	errcnt[cbn] = syneflg;
105 	parts[ cbn ] = NIL;
106 	dfiles[ cbn ] = FALSE;
107 	if (fp == NIL)
108 		return (NIL);
109 	/*
110 	 * Save the virtual name
111 	 * list stack pointer so
112 	 * the space can be freed
113 	 * later (funcend).
114 	 */
115 	fp->ptr[2] = nlp;
116 	if (fp->class != PROG) {
117 		for (q = fp->chain; q != NIL; q = q->chain) {
118 			enter(q);
119 #			ifdef PC
120 			    q -> extra_flags |= NPARAM;
121 #			endif PC
122 		}
123 	}
124 	if (fp->class == FUNC) {
125 		/*
126 		 * For functions, enter the fvar
127 		 */
128 		enter(fp->ptr[NL_FVAR]);
129 #		ifdef PC
130 		    q = fp -> ptr[ NL_FVAR ];
131 		    if (q -> type != NIL ) {
132 			functemp = tmpalloc(
133 					leven(
134 					    roundup(
135 						(int)lwidth(q -> type),
136 						(long)align(q -> type))),
137 					q -> type, NOREG);
138 			if ( q -> ptr[NL_OFFS] != functemp->value[NL_OFFS] )
139 			    panic("func var");
140 		    }
141 		    q -> extra_flags |= functemp -> extra_flags;
142 #		endif PC
143 	}
144 #	ifdef PTREE
145 		/*
146 		 *	pick up the pointer to porf declaration
147 		 */
148 	    PorFHeader[ ++nesting ] = fp -> inTree;
149 #	endif PTREE
150 	return (fp);
151 }
152 
153 /*
154  * Segend is called to check for
155  * unresolved variables, funcs and
156  * procs, and deliver unresolved and
157  * baduse error diagnostics at the
158  * end of a routine segment (a separately
159  * compiled segment that is not the
160  * main program) for PC. This
161  * routine should only be called
162  * by PC (not standard).
163  */
164  segend()
165  {
166 	register struct nl *p;
167 	register int i,b;
168 	char *cp;
169 
170 #ifdef PC
171 	if ( monflg ) {
172 	    error("Only the module containing the \"program\" statement");
173 	    cerror("can be profiled with ``pxp''.\n");
174 	}
175 	if (opt('s')) {
176 		standard();
177 		error("Separately compiled routine segments are not standard.");
178 	} else {
179 		b = cbn;
180 		for (i=0; i<077; i++) {
181 			for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) {
182 			switch (p->class) {
183 				case BADUSE:
184 					cp = 's';
185 					if (p->chain->ud_next == NIL)
186 						cp++;
187 					eholdnl();
188 					if (p->value[NL_KINDS] & ISUNDEF)
189 						nerror("%s undefined on line%s", p->symbol, cp);
190 					else
191 						nerror("%s improperly used on line%s", p->symbol, cp);
192 					pnumcnt = 10;
193 					pnums(p->chain);
194 					pchr('\n');
195 					break;
196 
197 				case FUNC:
198 				case PROC:
199 					if ((p->nl_flags & NFORWD) &&
200 					    ((p->extra_flags & NEXTERN) == 0))
201 						nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol);
202 					break;
203 
204 				case FVAR:
205 					if (((p->nl_flags & NMOD) == 0) &&
206 					    ((p->chain->extra_flags & NEXTERN) == 0))
207 						nerror("No assignment to the function variable");
208 					break;
209 			    }
210 			   }
211 			   disptab[i] = p;
212 		    }
213 	}
214 #endif PC
215 #ifdef OBJ
216 	error("Missing program statement and program body");
217 #endif OBJ
218 
219 }
220 
221 
222 /*
223  * Level1 does level one processing for
224  * separately compiled routine segments
225  */
226 level1()
227 {
228 
229 #	ifdef OBJ
230 	    error("Missing program statement");
231 #	endif OBJ
232 #	ifdef PC
233 	    if (opt('s')) {
234 		    standard();
235 		    error("Missing program statement");
236 	    }
237 #	endif PC
238 
239 	cbn++;
240 	sizes[cbn].om_max = sizes[cbn].curtmps.om_off = -DPOFF1;
241 	gotos[cbn] = NIL;
242 	errcnt[cbn] = syneflg;
243 	parts[ cbn ] = NIL;
244 	dfiles[ cbn ] = FALSE;
245 	progseen = TRUE;
246 }
247 
248 
249 
250 pnums(p)
251 	struct udinfo *p;
252 {
253 
254 	if (p->ud_next != NIL)
255 		pnums(p->ud_next);
256 	if (pnumcnt == 0) {
257 		printf("\n\t");
258 		pnumcnt = 20;
259 	}
260 	pnumcnt--;
261 	printf(" %d", p->ud_line);
262 }
263 
264 nerror(a1, a2, a3)
265 {
266 
267 	if (Fp != NIL) {
268 		yySsync();
269 #ifndef PI1
270 		if (opt('l'))
271 			yyoutline();
272 #endif
273 		yysetfile(filename);
274 		printf("In %s %s:\n", classes[Fp->class], Fp->symbol);
275 		Fp = NIL;
276 		elineoff();
277 	}
278 	error(a1, a2, a3);
279 }
280