BSD 2 development
[unix-history] / src / pi0 / fdec.c
CommitLineData
0758c694
BJ
1/* Copyright (c) 1979 Regents of the University of California */
2#
3/*
4 * pi - Pascal interpreter code translator
5 *
6 * Charles Haley, Bill Joy UCB
7 * Version 1.2 January 1979
8 */
9
10#include "0.h"
11#include "tree.h"
12
13/*
14 * Funchdr inserts
15 * declaration of a the
16 * prog/proc/func into the
17 * namelist. It also handles
18 * the arguments and puts out
19 * a transfer which defines
20 * the entry point of a procedure.
21 */
22
23funchdr(r)
24 int *r;
25{
26 register struct nl *p;
27 register *il, **rl;
28 int *rll, o;
29 struct nl *cp, *dp, *sp;
30 int *pp;
31
32 send(REVFHDR, r);
33 if (inpflist(r[2])) {
34 opush('l');
35 yyretrieve(); /* kludge */
36 }
37 line = r[1];
38 if (r[3] == NIL && (p=lookup1(r[2])) != NIL && bn == cbn) {
39 /*
40 * Symbol already defined
41 * in this block. it is either
42 * a redeclared symbol (error)
43 * or a forward declaration.
44 */
45 if ((p->class == FUNC || p->class == PROC) && (p->nl_flags & NFORWD) != 0) {
46 /*
47 * Grammar doesnt forbid
48 * types on a resolution
49 * of a forward function
50 * declaration.
51 */
52 if (p->class == FUNC && r[4])
53 error("Function type should be given only in forward declaration");
54 return (p);
55 }
56 }
57 /*
58 * Declare the prog/proc/func
59 */
60 switch (r[0]) {
61 case T_PROG:
62 program = p = defnl(r[2], PROG, 0, 0);
63 break;
64 case T_PDEC:
65 if (r[4] != NIL)
66 error("Procedures do not have types, only functions do");
67 p = enter(defnl(r[2], PROC, 0, 0));
68 break;
69 case T_FDEC:
70 il = r[4];
71 if (il == NIL)
72 error("Function type must be specified");
73 else if (il[0] != T_TYID) {
74 il = NIL;
75 error("Function type can be specified only by using a type identifier");
76 } else
77 il = gtype(il);
78 p = enter(defnl(r[2], FUNC, il, NIL));
79 /*
80 * An arbitrary restriction
81 */
82 switch (o = classify(p->type)) {
83 case TFILE:
84 case TARY:
85 case TREC:
86 case TSET:
87 case TSTR:
88 warning();
89 if (opt('s'))
90 standard();
91 error("Functions should not return %ss", clnames[o]);
92 }
93 break;
94 default:
95 panic("funchdr");
96 }
97 if (r[0] != T_PROG) {
98 /*
99 * Mark this proc/func as
100 * begin forward declared
101 */
102 p->nl_flags =| NFORWD;
103 /*
104 * Enter the parameters
105 * in the next block for
106 * the time being
107 */
108 if (++cbn >= DSPLYSZ) {
109 error("Procedure/function nesting too deep");
110 pexit(ERRS);
111 }
112 /*
113 * For functions, the function variable
114 */
115 if (p->class == FUNC) {
116 cp = defnl(r[2], FVAR, p->type, 0);
117 cp->chain = p;
118 p->value[NL_FVAR] = cp;
119 }
120 /*
121 * Enter the parameters
122 */
123 cp = sp = p;
124 for (rl = r[3]; rl != NIL; rl = rl[2]) {
125 p = NIL;
126 if (rl[1] == NIL)
127 continue;
128 /*
129 * Parametric procedures
130 * don't have types
131 */
132 if (rl[1][0] != T_PPROC) {
133 rll = rl[1][2];
134 if (rll[0] != T_TYID) {
135 error("Types for arguments can be specified only by using type identifiers");
136 p = NIL;
137 } else
138 p = gtype(rll);
139 }
140 for (il = rl[1][1]; il != NIL; il = il[2]) {
141 switch (rl[1][0]) {
142 default:
143 panic("funchdr2");
144 case T_PVAL:
145 if (p != NIL) {
146 if (p->class == FILE)
147 error("Files cannot be passed by value");
148 else if (p->nl_flags & NFILES)
149 error("Files cannot be a component of %ss passed by value",
150 nameof(p));
151 }
152 dp = defnl(il[1], VAR, p, 0);
153 break;
154 case T_PVAR:
155 dp = defnl(il[1], REF, p, 0);
156 break;
157 case T_PFUNC:
158 case T_PPROC:
159 error("Procedure/function parameters not implemented");
160 continue;
161 }
162 if (dp != NIL) {
163 cp->chain = dp;
164 cp = dp;
165 }
166 }
167 }
168 cbn--;
169 p = sp;
170 } else {
171 cp = p;
172 for (rl = r[3]; rl; rl = rl[2]) {
173 if (rl[1] == NIL)
174 continue;
175 dp = defnl(rl[1], VAR, 0, 0);
176 cp->chain = dp;
177 cp = dp;
178 }
179 }
180 return (p);
181}
182
183/*
184 * Funcbody is called
185 * when the actual (resolved)
186 * declaration of a procedure is
187 * encountered. It puts the names
188 * of the (function) and parameters
189 * into the symbol table.
190 */
191funcbody(fp)
192 struct nl *fp;
193{
194 register struct nl *q, *p;
195
196 cbn++;
197 if (cbn >= DSPLYSZ) {
198 error("Too many levels of function/procedure nesting");
199 pexit(ERRS);
200 }
201 send(REVFBDY);
202 errcnt[cbn] = syneflg;
203 parts = NIL;
204 if (fp == NIL)
205 return (NIL);
206 /*
207 * Save the virtual name
208 * list stack pointer so
209 * the space can be freed
210 * later (funcend).
211 */
212 fp->value[2] = nlp;
213 if (fp->class != PROG)
214 for (q = fp->chain; q != NIL; q = q->chain)
215 enter(q);
216 if (fp->class == FUNC) {
217 /*
218 * For functions, enter the fvar
219 */
220 enter(fp->value[NL_FVAR]);
221 }
222 return (fp);
223}
224
225int pnumcnt;
226struct nl *Fp;
227/*
228 * Funcend is called to
229 * finish a block by generating
230 * the code for the statements.
231 * It then looks for unresolved declarations
232 * of labels, procedures and functions,
233 * and cleans up the name list.
234 * For the program, it checks the
235 * semantics of the program
236 * statement (yuchh).
237 */
238funcend(fp, bundle, endline)
239 struct nl *fp;
240 int *bundle;
241 int endline;
242{
243 register struct nl *p;
244 register int i, b;
245 int *blk;
246 char *cp;
247
248 blk = bundle[2];
249 if (fp == NIL) {
250 cbn--;
251 return;
252 }
253 send(REVFEND, bundle, endline, syneflg == errcnt[cbn]);
254 if (Fp != NIL)
255 Fp = fp;
256 /*
257 * Clean up the symbol table displays and check for unresolves
258 */
259 line = endline;
260 b = cbn;
261 for (i = 0; i <= 077; i++) {
262 for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next)
263 if (p->class == BADUSE) {
264 cp = "s";
265 if (p->chain->ud_next == NIL)
266 cp++;
267 eholdnl();
268 if (p->value[NL_KINDS] & ISUNDEF)
269 nerror("%s undefined on line%s", p->symbol, cp);
270 else
271 nerror("%s improperly used on line%s", p->symbol, cp);
272 pnumcnt = 10;
273 pnums(p->chain);
274 putchar('\n');
275 }
276 /*
277 * Pop this symbol
278 * table slot
279 */
280 disptab[i] = p;
281 }
282
283#ifdef DEBUG
284 dumpnl(fp->value[2], fp->symbol);
285#endif
286 /*
287 * Restore the
288 * (virtual) name list
289 * position
290 */
291 nlfree(fp->value[2]);
292 /*
293 * Proc/func has been
294 * resolved
295 */
296 fp->nl_flags =& ~NFORWD;
297 elineon();
298 cbn--;
299 if (inpflist(fp->symbol)) {
300 opop('l');
301 }
302}
303
304pnums(p)
305 struct udinfo *p;
306{
307
308 if (p->ud_next != NIL)
309 pnums(p->ud_next);
310 if (pnumcnt == 0) {
311 printf("\n\t");
312 pnumcnt = 20;
313 }
314 pnumcnt--;
315 printf(" %d", p->ud_line);
316}
317
318nerror(a1, a2, a3)
319{
320
321 if (Fp != NIL) {
322 yySsync();
323 printf("In %s %s:\n", classes[Fp->class], Fp->symbol);
324 Fp = NIL;
325 }
326 elineoff();
327 error(a1, a2, a3);
328}