1bd389b36SDavid du Colombier #include <u.h>
2bd389b36SDavid du Colombier #include <libc.h>
3bd389b36SDavid du Colombier #include <bio.h>
4bd389b36SDavid du Colombier #include <ctype.h>
5bd389b36SDavid du Colombier #include <mach.h>
6bd389b36SDavid du Colombier #define Extern extern
7bd389b36SDavid du Colombier #include "acid.h"
8bd389b36SDavid du Colombier
9bd389b36SDavid du Colombier void
error(char * fmt,...)10bd389b36SDavid du Colombier error(char *fmt, ...)
11bd389b36SDavid du Colombier {
12219b2ee8SDavid du Colombier int i;
13219b2ee8SDavid du Colombier char buf[2048];
147dd7cddfSDavid du Colombier va_list arg;
15219b2ee8SDavid du Colombier
16219b2ee8SDavid du Colombier /* Unstack io channels */
17219b2ee8SDavid du Colombier if(iop != 0) {
18219b2ee8SDavid du Colombier for(i = 1; i < iop; i++)
19219b2ee8SDavid du Colombier Bterm(io[i]);
20219b2ee8SDavid du Colombier bout = io[0];
21219b2ee8SDavid du Colombier iop = 0;
22219b2ee8SDavid du Colombier }
23bd389b36SDavid du Colombier
24bd389b36SDavid du Colombier ret = 0;
25bd389b36SDavid du Colombier gotint = 0;
26bd389b36SDavid du Colombier Bflush(bout);
27219b2ee8SDavid du Colombier if(silent)
28219b2ee8SDavid du Colombier silent = 0;
29219b2ee8SDavid du Colombier else {
307dd7cddfSDavid du Colombier va_start(arg, fmt);
319a747e4fSDavid du Colombier vseprint(buf, buf+sizeof(buf), fmt, arg);
327dd7cddfSDavid du Colombier va_end(arg);
33219b2ee8SDavid du Colombier fprint(2, "%L: (error) %s\n", buf);
34219b2ee8SDavid du Colombier }
35219b2ee8SDavid du Colombier while(popio())
36219b2ee8SDavid du Colombier ;
37219b2ee8SDavid du Colombier interactive = 1;
38bd389b36SDavid du Colombier longjmp(err, 1);
39bd389b36SDavid du Colombier }
40bd389b36SDavid du Colombier
41bd389b36SDavid du Colombier void
unwind(void)42bd389b36SDavid du Colombier unwind(void)
43bd389b36SDavid du Colombier {
44bd389b36SDavid du Colombier int i;
45bd389b36SDavid du Colombier Lsym *s;
46bd389b36SDavid du Colombier Value *v;
47bd389b36SDavid du Colombier
48bd389b36SDavid du Colombier for(i = 0; i < Hashsize; i++) {
49bd389b36SDavid du Colombier for(s = hash[i]; s; s = s->hash) {
50bd389b36SDavid du Colombier while(s->v->pop) {
51bd389b36SDavid du Colombier v = s->v->pop;
52bd389b36SDavid du Colombier free(s->v);
53bd389b36SDavid du Colombier s->v = v;
54bd389b36SDavid du Colombier }
55bd389b36SDavid du Colombier }
56bd389b36SDavid du Colombier }
57bd389b36SDavid du Colombier }
58bd389b36SDavid du Colombier
59bd389b36SDavid du Colombier void
execute(Node * n)60bd389b36SDavid du Colombier execute(Node *n)
61bd389b36SDavid du Colombier {
62bd389b36SDavid du Colombier Value *v;
63bd389b36SDavid du Colombier Lsym *sl;
64bd389b36SDavid du Colombier Node *l, *r;
654de34a7eSDavid du Colombier vlong i, s, e;
66219b2ee8SDavid du Colombier Node res, xx;
67bd389b36SDavid du Colombier static int stmnt;
68bd389b36SDavid du Colombier
699a747e4fSDavid du Colombier gc();
70bd389b36SDavid du Colombier if(gotint)
71bd389b36SDavid du Colombier error("interrupted");
72bd389b36SDavid du Colombier
73bd389b36SDavid du Colombier if(n == 0)
74bd389b36SDavid du Colombier return;
75bd389b36SDavid du Colombier
76219b2ee8SDavid du Colombier if(stmnt++ > 5000) {
77bd389b36SDavid du Colombier Bflush(bout);
78bd389b36SDavid du Colombier stmnt = 0;
79bd389b36SDavid du Colombier }
80bd389b36SDavid du Colombier
81bd389b36SDavid du Colombier l = n->left;
82bd389b36SDavid du Colombier r = n->right;
83bd389b36SDavid du Colombier
84bd389b36SDavid du Colombier switch(n->op) {
85bd389b36SDavid du Colombier default:
86bd389b36SDavid du Colombier expr(n, &res);
87*6f222ee0SDavid du Colombier if(ret || (res.type == TLIST && res.l == 0 && n->op != OADD))
88219b2ee8SDavid du Colombier break;
89219b2ee8SDavid du Colombier prnt->right = &res;
90219b2ee8SDavid du Colombier expr(prnt, &xx);
91219b2ee8SDavid du Colombier break;
92219b2ee8SDavid du Colombier case OASGN:
93219b2ee8SDavid du Colombier case OCALL:
94219b2ee8SDavid du Colombier expr(n, &res);
95bd389b36SDavid du Colombier break;
96bd389b36SDavid du Colombier case OCOMPLEX:
97219b2ee8SDavid du Colombier decl(n);
98bd389b36SDavid du Colombier break;
99bd389b36SDavid du Colombier case OLOCAL:
100219b2ee8SDavid du Colombier for(n = n->left; n; n = n->left) {
101bd389b36SDavid du Colombier if(ret == 0)
102bd389b36SDavid du Colombier error("local not in function");
103bd389b36SDavid du Colombier sl = n->sym;
104bd389b36SDavid du Colombier if(sl->v->ret == ret)
105219b2ee8SDavid du Colombier error("%s declared twice", sl->name);
106bd389b36SDavid du Colombier v = gmalloc(sizeof(Value));
107bd389b36SDavid du Colombier v->ret = ret;
108bd389b36SDavid du Colombier v->pop = sl->v;
109bd389b36SDavid du Colombier sl->v = v;
110bd389b36SDavid du Colombier v->scope = 0;
111bd389b36SDavid du Colombier *(ret->tail) = sl;
112bd389b36SDavid du Colombier ret->tail = &v->scope;
113bd389b36SDavid du Colombier v->set = 0;
114219b2ee8SDavid du Colombier }
115bd389b36SDavid du Colombier break;
116bd389b36SDavid du Colombier case ORET:
117bd389b36SDavid du Colombier if(ret == 0)
118bd389b36SDavid du Colombier error("return not in function");
119bd389b36SDavid du Colombier expr(n->left, ret->val);
120bd389b36SDavid du Colombier longjmp(ret->rlab, 1);
121bd389b36SDavid du Colombier case OLIST:
122bd389b36SDavid du Colombier execute(n->left);
123bd389b36SDavid du Colombier execute(n->right);
124bd389b36SDavid du Colombier break;
125bd389b36SDavid du Colombier case OIF:
126bd389b36SDavid du Colombier expr(l, &res);
127bd389b36SDavid du Colombier if(r && r->op == OELSE) {
128bd389b36SDavid du Colombier if(bool(&res))
129bd389b36SDavid du Colombier execute(r->left);
130bd389b36SDavid du Colombier else
131bd389b36SDavid du Colombier execute(r->right);
132bd389b36SDavid du Colombier }
133bd389b36SDavid du Colombier else if(bool(&res))
134bd389b36SDavid du Colombier execute(r);
135bd389b36SDavid du Colombier break;
136bd389b36SDavid du Colombier case OWHILE:
137bd389b36SDavid du Colombier for(;;) {
138bd389b36SDavid du Colombier expr(l, &res);
139bd389b36SDavid du Colombier if(!bool(&res))
140bd389b36SDavid du Colombier break;
141bd389b36SDavid du Colombier execute(r);
142bd389b36SDavid du Colombier }
143bd389b36SDavid du Colombier break;
144bd389b36SDavid du Colombier case ODO:
145bd389b36SDavid du Colombier expr(l->left, &res);
146bd389b36SDavid du Colombier if(res.type != TINT)
147219b2ee8SDavid du Colombier error("loop must have integer start");
148bd389b36SDavid du Colombier s = res.ival;
149bd389b36SDavid du Colombier expr(l->right, &res);
150bd389b36SDavid du Colombier if(res.type != TINT)
151219b2ee8SDavid du Colombier error("loop must have integer end");
152bd389b36SDavid du Colombier e = res.ival;
153219b2ee8SDavid du Colombier for(i = s; i <= e; i++)
154bd389b36SDavid du Colombier execute(r);
155bd389b36SDavid du Colombier break;
156bd389b36SDavid du Colombier }
157bd389b36SDavid du Colombier }
158bd389b36SDavid du Colombier
159bd389b36SDavid du Colombier int
160bd389b36SDavid du Colombier bool(Node *n)
161bd389b36SDavid du Colombier {
162bd389b36SDavid du Colombier int true = 0;
163bd389b36SDavid du Colombier
164bd389b36SDavid du Colombier if(n->op != OCONST)
165bd389b36SDavid du Colombier fatal("bool: not const");
166bd389b36SDavid du Colombier
167bd389b36SDavid du Colombier switch(n->type) {
168bd389b36SDavid du Colombier case TINT:
169bd389b36SDavid du Colombier if(n->ival != 0)
170bd389b36SDavid du Colombier true = 1;
171bd389b36SDavid du Colombier break;
172bd389b36SDavid du Colombier case TFLOAT:
173bd389b36SDavid du Colombier if(n->fval != 0.0)
174bd389b36SDavid du Colombier true = 1;
175bd389b36SDavid du Colombier break;
176bd389b36SDavid du Colombier case TSTRING:
177bd389b36SDavid du Colombier if(n->string->len)
178bd389b36SDavid du Colombier true = 1;
179bd389b36SDavid du Colombier break;
180bd389b36SDavid du Colombier case TLIST:
181bd389b36SDavid du Colombier if(n->l)
182bd389b36SDavid du Colombier true = 1;
183bd389b36SDavid du Colombier break;
184bd389b36SDavid du Colombier }
185bd389b36SDavid du Colombier return true;
186bd389b36SDavid du Colombier }
187bd389b36SDavid du Colombier
188bd389b36SDavid du Colombier void
convflt(Node * r,char * flt)189219b2ee8SDavid du Colombier convflt(Node *r, char *flt)
190219b2ee8SDavid du Colombier {
191219b2ee8SDavid du Colombier char c;
192219b2ee8SDavid du Colombier
193219b2ee8SDavid du Colombier c = flt[0];
194219b2ee8SDavid du Colombier if(('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) {
195219b2ee8SDavid du Colombier r->type = TSTRING;
196219b2ee8SDavid du Colombier r->fmt = 's';
197219b2ee8SDavid du Colombier r->string = strnode(flt);
198219b2ee8SDavid du Colombier }
199219b2ee8SDavid du Colombier else {
200219b2ee8SDavid du Colombier r->type = TFLOAT;
201219b2ee8SDavid du Colombier r->fval = atof(flt);
202219b2ee8SDavid du Colombier }
203219b2ee8SDavid du Colombier }
204219b2ee8SDavid du Colombier
205219b2ee8SDavid du Colombier void
indir(Map * m,uvlong addr,char fmt,Node * r)2064de34a7eSDavid du Colombier indir(Map *m, uvlong addr, char fmt, Node *r)
207bd389b36SDavid du Colombier {
208bd389b36SDavid du Colombier int i;
2094de34a7eSDavid du Colombier ulong lval;
2104de34a7eSDavid du Colombier uvlong uvval;
211219b2ee8SDavid du Colombier int ret;
212bd389b36SDavid du Colombier uchar cval;
213bd389b36SDavid du Colombier ushort sval;
214219b2ee8SDavid du Colombier char buf[512], reg[12];
215bd389b36SDavid du Colombier
216bd389b36SDavid du Colombier r->op = OCONST;
217bd389b36SDavid du Colombier r->fmt = fmt;
218bd389b36SDavid du Colombier switch(fmt) {
219bd389b36SDavid du Colombier default:
220bd389b36SDavid du Colombier error("bad pointer format '%c' for *", fmt);
221bd389b36SDavid du Colombier case 'c':
222bd389b36SDavid du Colombier case 'C':
223bd389b36SDavid du Colombier case 'b':
224bd389b36SDavid du Colombier r->type = TINT;
225219b2ee8SDavid du Colombier ret = get1(m, addr, &cval, 1);
226219b2ee8SDavid du Colombier if (ret < 0)
227219b2ee8SDavid du Colombier error("indir: %r");
228bd389b36SDavid du Colombier r->ival = cval;
229bd389b36SDavid du Colombier break;
230bd389b36SDavid du Colombier case 'x':
231bd389b36SDavid du Colombier case 'd':
232bd389b36SDavid du Colombier case 'u':
233bd389b36SDavid du Colombier case 'o':
234bd389b36SDavid du Colombier case 'q':
235219b2ee8SDavid du Colombier case 'r':
236bd389b36SDavid du Colombier r->type = TINT;
237219b2ee8SDavid du Colombier ret = get2(m, addr, &sval);
238219b2ee8SDavid du Colombier if (ret < 0)
239219b2ee8SDavid du Colombier error("indir: %r");
240bd389b36SDavid du Colombier r->ival = sval;
241bd389b36SDavid du Colombier break;
242219b2ee8SDavid du Colombier case 'a':
243219b2ee8SDavid du Colombier case 'A':
2440f1069eeSDavid du Colombier case 'W':
2454de34a7eSDavid du Colombier r->type = TINT;
2464de34a7eSDavid du Colombier ret = geta(m, addr, &uvval);
2474de34a7eSDavid du Colombier if (ret < 0)
2484de34a7eSDavid du Colombier error("indir: %r");
2494de34a7eSDavid du Colombier r->ival = uvval;
2504de34a7eSDavid du Colombier break;
251219b2ee8SDavid du Colombier case 'B':
252bd389b36SDavid du Colombier case 'X':
253bd389b36SDavid du Colombier case 'D':
254bd389b36SDavid du Colombier case 'U':
255bd389b36SDavid du Colombier case 'O':
256bd389b36SDavid du Colombier case 'Q':
257bd389b36SDavid du Colombier r->type = TINT;
2584de34a7eSDavid du Colombier ret = get4(m, addr, &lval);
259219b2ee8SDavid du Colombier if (ret < 0)
260219b2ee8SDavid du Colombier error("indir: %r");
2614de34a7eSDavid du Colombier r->ival = lval;
262bd389b36SDavid du Colombier break;
2637dd7cddfSDavid du Colombier case 'V':
2647dd7cddfSDavid du Colombier case 'Y':
2657dd7cddfSDavid du Colombier case 'Z':
2667dd7cddfSDavid du Colombier r->type = TINT;
2674de34a7eSDavid du Colombier ret = get8(m, addr, &uvval);
2687dd7cddfSDavid du Colombier if (ret < 0)
2697dd7cddfSDavid du Colombier error("indir: %r");
2704de34a7eSDavid du Colombier r->ival = uvval;
2717dd7cddfSDavid du Colombier break;
272bd389b36SDavid du Colombier case 's':
273bd389b36SDavid du Colombier r->type = TSTRING;
274bd389b36SDavid du Colombier for(i = 0; i < sizeof(buf)-1; i++) {
275219b2ee8SDavid du Colombier ret = get1(m, addr, (uchar*)&buf[i], 1);
276219b2ee8SDavid du Colombier if (ret < 0)
277219b2ee8SDavid du Colombier error("indir: %r");
278bd389b36SDavid du Colombier addr++;
279bd389b36SDavid du Colombier if(buf[i] == '\0')
280bd389b36SDavid du Colombier break;
281bd389b36SDavid du Colombier }
282bd389b36SDavid du Colombier buf[i] = 0;
283219b2ee8SDavid du Colombier if(i == 0)
284219b2ee8SDavid du Colombier strcpy(buf, "(null)");
285bd389b36SDavid du Colombier r->string = strnode(buf);
286bd389b36SDavid du Colombier break;
287bd389b36SDavid du Colombier case 'R':
288bd389b36SDavid du Colombier r->type = TSTRING;
289219b2ee8SDavid du Colombier for(i = 0; i < sizeof(buf)-2; i += 2) {
290219b2ee8SDavid du Colombier ret = get1(m, addr, (uchar*)&buf[i], 2);
291219b2ee8SDavid du Colombier if (ret < 0)
292219b2ee8SDavid du Colombier error("indir: %r");
293bd389b36SDavid du Colombier addr += 2;
294bd389b36SDavid du Colombier if(buf[i] == 0 && buf[i+1] == 0)
295bd389b36SDavid du Colombier break;
296bd389b36SDavid du Colombier }
297219b2ee8SDavid du Colombier buf[i++] = 0;
298bd389b36SDavid du Colombier buf[i] = 0;
299219b2ee8SDavid du Colombier r->string = runenode((Rune*)buf);
300bd389b36SDavid du Colombier break;
301bd389b36SDavid du Colombier case 'i':
302bd389b36SDavid du Colombier case 'I':
303219b2ee8SDavid du Colombier if ((*machdata->das)(m, addr, fmt, buf, sizeof(buf)) < 0)
304219b2ee8SDavid du Colombier error("indir: %r");
305bd389b36SDavid du Colombier r->type = TSTRING;
306bd389b36SDavid du Colombier r->fmt = 's';
307219b2ee8SDavid du Colombier r->string = strnode(buf);
308bd389b36SDavid du Colombier break;
309bd389b36SDavid du Colombier case 'f':
310219b2ee8SDavid du Colombier ret = get1(m, addr, (uchar*)buf, mach->szfloat);
311219b2ee8SDavid du Colombier if (ret < 0)
312219b2ee8SDavid du Colombier error("indir: %r");
313219b2ee8SDavid du Colombier machdata->sftos(buf, sizeof(buf), (void*) buf);
314219b2ee8SDavid du Colombier convflt(r, buf);
315219b2ee8SDavid du Colombier break;
316219b2ee8SDavid du Colombier case 'g':
317219b2ee8SDavid du Colombier ret = get1(m, addr, (uchar*)buf, mach->szfloat);
318219b2ee8SDavid du Colombier if (ret < 0)
319219b2ee8SDavid du Colombier error("indir: %r");
320219b2ee8SDavid du Colombier machdata->sftos(buf, sizeof(buf), (void*) buf);
321219b2ee8SDavid du Colombier r->type = TSTRING;
322219b2ee8SDavid du Colombier r->string = strnode(buf);
323bd389b36SDavid du Colombier break;
324bd389b36SDavid du Colombier case 'F':
325219b2ee8SDavid du Colombier ret = get1(m, addr, (uchar*)buf, mach->szdouble);
326219b2ee8SDavid du Colombier if (ret < 0)
327219b2ee8SDavid du Colombier error("indir: %r");
328219b2ee8SDavid du Colombier machdata->dftos(buf, sizeof(buf), (void*) buf);
329219b2ee8SDavid du Colombier convflt(r, buf);
330219b2ee8SDavid du Colombier break;
331219b2ee8SDavid du Colombier case '3': /* little endian ieee 80 with hole in bytes 8&9 */
332219b2ee8SDavid du Colombier ret = get1(m, addr, (uchar*)reg, 10);
333219b2ee8SDavid du Colombier if (ret < 0)
334219b2ee8SDavid du Colombier error("indir: %r");
335219b2ee8SDavid du Colombier memmove(reg+10, reg+8, 2); /* open hole */
336219b2ee8SDavid du Colombier memset(reg+8, 0, 2); /* fill it */
337219b2ee8SDavid du Colombier leieee80ftos(buf, sizeof(buf), reg);
338219b2ee8SDavid du Colombier convflt(r, buf);
339219b2ee8SDavid du Colombier break;
340219b2ee8SDavid du Colombier case '8': /* big-endian ieee 80 */
341219b2ee8SDavid du Colombier ret = get1(m, addr, (uchar*)reg, 10);
342219b2ee8SDavid du Colombier if (ret < 0)
343219b2ee8SDavid du Colombier error("indir: %r");
344219b2ee8SDavid du Colombier beieee80ftos(buf, sizeof(buf), reg);
345219b2ee8SDavid du Colombier convflt(r, buf);
346219b2ee8SDavid du Colombier break;
347219b2ee8SDavid du Colombier case 'G':
348219b2ee8SDavid du Colombier ret = get1(m, addr, (uchar*)buf, mach->szdouble);
349219b2ee8SDavid du Colombier if (ret < 0)
350219b2ee8SDavid du Colombier error("indir: %r");
351219b2ee8SDavid du Colombier machdata->dftos(buf, sizeof(buf), (void*) buf);
352219b2ee8SDavid du Colombier r->type = TSTRING;
353219b2ee8SDavid du Colombier r->string = strnode(buf);
354bd389b36SDavid du Colombier break;
355bd389b36SDavid du Colombier }
356bd389b36SDavid du Colombier }
357bd389b36SDavid du Colombier
358bd389b36SDavid du Colombier void
windir(Map * m,Node * addr,Node * rval,Node * r)359bd389b36SDavid du Colombier windir(Map *m, Node *addr, Node *rval, Node *r)
360bd389b36SDavid du Colombier {
361bd389b36SDavid du Colombier uchar cval;
362bd389b36SDavid du Colombier ushort sval;
3634de34a7eSDavid du Colombier long lval;
364bd389b36SDavid du Colombier Node res, aes;
365219b2ee8SDavid du Colombier int ret;
366bd389b36SDavid du Colombier
367bd389b36SDavid du Colombier if(m == 0)
368bd389b36SDavid du Colombier error("no map for */@=");
369bd389b36SDavid du Colombier
370bd389b36SDavid du Colombier expr(rval, &res);
371bd389b36SDavid du Colombier expr(addr, &aes);
372bd389b36SDavid du Colombier
373bd389b36SDavid du Colombier if(aes.type != TINT)
374bd389b36SDavid du Colombier error("bad type lhs of @/*");
375bd389b36SDavid du Colombier
376219b2ee8SDavid du Colombier if(m != cormap && wtflag == 0)
377219b2ee8SDavid du Colombier error("not in write mode");
378219b2ee8SDavid du Colombier
379bd389b36SDavid du Colombier r->type = res.type;
380bd389b36SDavid du Colombier r->fmt = res.fmt;
381bd389b36SDavid du Colombier r->Store = res.Store;
382bd389b36SDavid du Colombier
383bd389b36SDavid du Colombier switch(res.fmt) {
384bd389b36SDavid du Colombier default:
385bd389b36SDavid du Colombier error("bad pointer format '%c' for */@=", res.fmt);
386bd389b36SDavid du Colombier case 'c':
387bd389b36SDavid du Colombier case 'C':
388bd389b36SDavid du Colombier case 'b':
389bd389b36SDavid du Colombier cval = res.ival;
390219b2ee8SDavid du Colombier ret = put1(m, aes.ival, &cval, 1);
391bd389b36SDavid du Colombier break;
392bd389b36SDavid du Colombier case 'r':
393bd389b36SDavid du Colombier case 'x':
394bd389b36SDavid du Colombier case 'd':
395bd389b36SDavid du Colombier case 'u':
396bd389b36SDavid du Colombier case 'o':
397bd389b36SDavid du Colombier sval = res.ival;
398219b2ee8SDavid du Colombier ret = put2(m, aes.ival, sval);
399bd389b36SDavid du Colombier r->ival = sval;
400bd389b36SDavid du Colombier break;
401219b2ee8SDavid du Colombier case 'a':
402219b2ee8SDavid du Colombier case 'A':
4030f1069eeSDavid du Colombier case 'W':
4044de34a7eSDavid du Colombier ret = puta(m, aes.ival, res.ival);
4054de34a7eSDavid du Colombier break;
406219b2ee8SDavid du Colombier case 'B':
407bd389b36SDavid du Colombier case 'X':
408bd389b36SDavid du Colombier case 'D':
409bd389b36SDavid du Colombier case 'U':
410bd389b36SDavid du Colombier case 'O':
4114de34a7eSDavid du Colombier lval = res.ival;
4124de34a7eSDavid du Colombier ret = put4(m, aes.ival, lval);
413bd389b36SDavid du Colombier break;
4147dd7cddfSDavid du Colombier case 'V':
4157dd7cddfSDavid du Colombier case 'Y':
4167dd7cddfSDavid du Colombier case 'Z':
4177dd7cddfSDavid du Colombier ret = put8(m, aes.ival, res.ival);
4187dd7cddfSDavid du Colombier break;
419bd389b36SDavid du Colombier case 's':
420bd389b36SDavid du Colombier case 'R':
421219b2ee8SDavid du Colombier ret = put1(m, aes.ival, (uchar*)res.string->string, res.string->len);
422bd389b36SDavid du Colombier break;
423bd389b36SDavid du Colombier }
424219b2ee8SDavid du Colombier if (ret < 0)
425219b2ee8SDavid du Colombier error("windir: %r");
426bd389b36SDavid du Colombier }
427bd389b36SDavid du Colombier
428bd389b36SDavid du Colombier void
call(char * fn,Node * parameters,Node * local,Node * body,Node * retexp)429bd389b36SDavid du Colombier call(char *fn, Node *parameters, Node *local, Node *body, Node *retexp)
430bd389b36SDavid du Colombier {
431bd389b36SDavid du Colombier int np, i;
432bd389b36SDavid du Colombier Rplace rlab;
433bd389b36SDavid du Colombier Node *n, res;
434bd389b36SDavid du Colombier Value *v, *f;
435bd389b36SDavid du Colombier Lsym *s, *next;
436bd389b36SDavid du Colombier Node *avp[Maxarg], *ava[Maxarg];
437bd389b36SDavid du Colombier
438219b2ee8SDavid du Colombier rlab.local = 0;
439219b2ee8SDavid du Colombier
440bd389b36SDavid du Colombier na = 0;
441bd389b36SDavid du Colombier flatten(avp, parameters);
442bd389b36SDavid du Colombier np = na;
443bd389b36SDavid du Colombier na = 0;
444bd389b36SDavid du Colombier flatten(ava, local);
445bd389b36SDavid du Colombier if(np != na) {
446bd389b36SDavid du Colombier if(np < na)
447bd389b36SDavid du Colombier error("%s: too few arguments", fn);
448bd389b36SDavid du Colombier error("%s: too many arguments", fn);
449bd389b36SDavid du Colombier }
450bd389b36SDavid du Colombier
451bd389b36SDavid du Colombier rlab.tail = &rlab.local;
452bd389b36SDavid du Colombier
453bd389b36SDavid du Colombier ret = &rlab;
454bd389b36SDavid du Colombier for(i = 0; i < np; i++) {
455bd389b36SDavid du Colombier n = ava[i];
456219b2ee8SDavid du Colombier switch(n->op) {
457219b2ee8SDavid du Colombier default:
458bd389b36SDavid du Colombier error("%s: %d formal not a name", fn, i);
459219b2ee8SDavid du Colombier case ONAME:
460bd389b36SDavid du Colombier expr(avp[i], &res);
461bd389b36SDavid du Colombier s = n->sym;
462219b2ee8SDavid du Colombier break;
463219b2ee8SDavid du Colombier case OINDM:
464219b2ee8SDavid du Colombier res.cc = avp[i];
465219b2ee8SDavid du Colombier res.type = TCODE;
466219b2ee8SDavid du Colombier res.comt = 0;
467219b2ee8SDavid du Colombier if(n->left->op != ONAME)
468219b2ee8SDavid du Colombier error("%s: %d formal not a name", fn, i);
469219b2ee8SDavid du Colombier s = n->left->sym;
470219b2ee8SDavid du Colombier break;
471219b2ee8SDavid du Colombier }
472bd389b36SDavid du Colombier if(s->v->ret == ret)
473bd389b36SDavid du Colombier error("%s already declared at this scope", s->name);
474bd389b36SDavid du Colombier
475bd389b36SDavid du Colombier v = gmalloc(sizeof(Value));
476bd389b36SDavid du Colombier v->ret = ret;
477bd389b36SDavid du Colombier v->pop = s->v;
478bd389b36SDavid du Colombier s->v = v;
479bd389b36SDavid du Colombier v->scope = 0;
480bd389b36SDavid du Colombier *(rlab.tail) = s;
481bd389b36SDavid du Colombier rlab.tail = &v->scope;
482bd389b36SDavid du Colombier
483bd389b36SDavid du Colombier v->Store = res.Store;
484bd389b36SDavid du Colombier v->type = res.type;
485bd389b36SDavid du Colombier v->set = 1;
486bd389b36SDavid du Colombier }
487bd389b36SDavid du Colombier
488bd389b36SDavid du Colombier ret->val = retexp;
489bd389b36SDavid du Colombier if(setjmp(rlab.rlab) == 0)
490bd389b36SDavid du Colombier execute(body);
491bd389b36SDavid du Colombier
492bd389b36SDavid du Colombier for(s = rlab.local; s; s = next) {
493bd389b36SDavid du Colombier f = s->v;
494bd389b36SDavid du Colombier next = f->scope;
495bd389b36SDavid du Colombier s->v = f->pop;
496bd389b36SDavid du Colombier free(f);
497bd389b36SDavid du Colombier }
498bd389b36SDavid du Colombier }
499