xref: /plan9-contrib/sys/src/cmd/acid/exec.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
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
10bd389b36SDavid du Colombier error(char *fmt, ...)
11bd389b36SDavid du Colombier {
12*219b2ee8SDavid du Colombier 	int i;
13*219b2ee8SDavid du Colombier 	char buf[2048];
14*219b2ee8SDavid du Colombier 
15*219b2ee8SDavid du Colombier 	/* Unstack io channels */
16*219b2ee8SDavid du Colombier 	if(iop != 0) {
17*219b2ee8SDavid du Colombier 		for(i = 1; i < iop; i++)
18*219b2ee8SDavid du Colombier 			Bterm(io[i]);
19*219b2ee8SDavid du Colombier 		bout = io[0];
20*219b2ee8SDavid du Colombier 		iop = 0;
21*219b2ee8SDavid du Colombier 	}
22bd389b36SDavid du Colombier 
23bd389b36SDavid du Colombier 	ret = 0;
24bd389b36SDavid du Colombier 	gotint = 0;
25bd389b36SDavid du Colombier 	Bflush(bout);
26*219b2ee8SDavid du Colombier 	if(silent)
27*219b2ee8SDavid du Colombier 		silent = 0;
28*219b2ee8SDavid du Colombier 	else {
29bd389b36SDavid du Colombier 		doprint(buf, buf+sizeof(buf), fmt, (&fmt+1));
30*219b2ee8SDavid du Colombier 		fprint(2, "%L: (error) %s\n", buf);
31*219b2ee8SDavid du Colombier 	}
32*219b2ee8SDavid du Colombier 	while(popio())
33*219b2ee8SDavid du Colombier 		;
34*219b2ee8SDavid du Colombier 	interactive = 1;
35bd389b36SDavid du Colombier 	longjmp(err, 1);
36bd389b36SDavid du Colombier }
37bd389b36SDavid du Colombier 
38bd389b36SDavid du Colombier void
39bd389b36SDavid du Colombier unwind(void)
40bd389b36SDavid du Colombier {
41bd389b36SDavid du Colombier 	int i;
42bd389b36SDavid du Colombier 	Lsym *s;
43bd389b36SDavid du Colombier 	Value *v;
44bd389b36SDavid du Colombier 
45bd389b36SDavid du Colombier 	for(i = 0; i < Hashsize; i++) {
46bd389b36SDavid du Colombier 		for(s = hash[i]; s; s = s->hash) {
47bd389b36SDavid du Colombier 			while(s->v->pop) {
48bd389b36SDavid du Colombier 				v = s->v->pop;
49bd389b36SDavid du Colombier 				free(s->v);
50bd389b36SDavid du Colombier 				s->v = v;
51bd389b36SDavid du Colombier 			}
52bd389b36SDavid du Colombier 		}
53bd389b36SDavid du Colombier 	}
54bd389b36SDavid du Colombier }
55bd389b36SDavid du Colombier 
56bd389b36SDavid du Colombier void
57bd389b36SDavid du Colombier execute(Node *n)
58bd389b36SDavid du Colombier {
59bd389b36SDavid du Colombier 	Value *v;
60bd389b36SDavid du Colombier 	Lsym *sl;
61bd389b36SDavid du Colombier 	Node *l, *r;
62bd389b36SDavid du Colombier 	int i, s, e;
63*219b2ee8SDavid du Colombier 	Node res, xx;
64bd389b36SDavid du Colombier 	static int stmnt;
65bd389b36SDavid du Colombier 
66bd389b36SDavid du Colombier 	if(gotint)
67bd389b36SDavid du Colombier 		error("interrupted");
68bd389b36SDavid du Colombier 
69bd389b36SDavid du Colombier 	if(n == 0)
70bd389b36SDavid du Colombier 		return;
71bd389b36SDavid du Colombier 
72*219b2ee8SDavid du Colombier 	if(stmnt++ > 5000) {
73bd389b36SDavid du Colombier 		Bflush(bout);
74bd389b36SDavid du Colombier 		stmnt = 0;
75bd389b36SDavid du Colombier 	}
76bd389b36SDavid du Colombier 
77bd389b36SDavid du Colombier 	l = n->left;
78bd389b36SDavid du Colombier 	r = n->right;
79bd389b36SDavid du Colombier 
80bd389b36SDavid du Colombier 	switch(n->op) {
81bd389b36SDavid du Colombier 	default:
82bd389b36SDavid du Colombier 		expr(n, &res);
83*219b2ee8SDavid du Colombier 		if(ret || (res.type == TLIST && res.l == 0))
84*219b2ee8SDavid du Colombier 			break;
85*219b2ee8SDavid du Colombier 		prnt->right = &res;
86*219b2ee8SDavid du Colombier 		expr(prnt, &xx);
87*219b2ee8SDavid du Colombier 		break;
88*219b2ee8SDavid du Colombier 	case OASGN:
89*219b2ee8SDavid du Colombier 	case OCALL:
90*219b2ee8SDavid du Colombier 		expr(n, &res);
91bd389b36SDavid du Colombier 		break;
92bd389b36SDavid du Colombier 	case OCOMPLEX:
93*219b2ee8SDavid du Colombier 		decl(n);
94bd389b36SDavid du Colombier 		break;
95bd389b36SDavid du Colombier 	case OLOCAL:
96*219b2ee8SDavid du Colombier 		for(n = n->left; n; n = n->left) {
97bd389b36SDavid du Colombier 			if(ret == 0)
98bd389b36SDavid du Colombier 				error("local not in function");
99bd389b36SDavid du Colombier 			sl = n->sym;
100bd389b36SDavid du Colombier 			if(sl->v->ret == ret)
101*219b2ee8SDavid du Colombier 				error("%s declared twice", sl->name);
102bd389b36SDavid du Colombier 			v = gmalloc(sizeof(Value));
103bd389b36SDavid du Colombier 			v->ret = ret;
104bd389b36SDavid du Colombier 			v->pop = sl->v;
105bd389b36SDavid du Colombier 			sl->v = v;
106bd389b36SDavid du Colombier 			v->scope = 0;
107bd389b36SDavid du Colombier 			*(ret->tail) = sl;
108bd389b36SDavid du Colombier 			ret->tail = &v->scope;
109bd389b36SDavid du Colombier 			v->set = 0;
110*219b2ee8SDavid du Colombier 		}
111bd389b36SDavid du Colombier 		break;
112bd389b36SDavid du Colombier 	case ORET:
113bd389b36SDavid du Colombier 		if(ret == 0)
114bd389b36SDavid du Colombier 			error("return not in function");
115bd389b36SDavid du Colombier 		expr(n->left, ret->val);
116bd389b36SDavid du Colombier 		longjmp(ret->rlab, 1);
117bd389b36SDavid du Colombier 	case OLIST:
118bd389b36SDavid du Colombier 		execute(n->left);
119bd389b36SDavid du Colombier 		execute(n->right);
120bd389b36SDavid du Colombier 		break;
121bd389b36SDavid du Colombier 	case OIF:
122bd389b36SDavid du Colombier 		expr(l, &res);
123bd389b36SDavid du Colombier 		if(r && r->op == OELSE) {
124bd389b36SDavid du Colombier 			if(bool(&res))
125bd389b36SDavid du Colombier 				execute(r->left);
126bd389b36SDavid du Colombier 			else
127bd389b36SDavid du Colombier 				execute(r->right);
128bd389b36SDavid du Colombier 		}
129bd389b36SDavid du Colombier 		else if(bool(&res))
130bd389b36SDavid du Colombier 			execute(r);
131bd389b36SDavid du Colombier 		break;
132bd389b36SDavid du Colombier 	case OWHILE:
133bd389b36SDavid du Colombier 		for(;;) {
134bd389b36SDavid du Colombier 			expr(l, &res);
135bd389b36SDavid du Colombier 			if(!bool(&res))
136bd389b36SDavid du Colombier 				break;
137bd389b36SDavid du Colombier 			execute(r);
138bd389b36SDavid du Colombier 		}
139bd389b36SDavid du Colombier 		break;
140bd389b36SDavid du Colombier 	case ODO:
141bd389b36SDavid du Colombier 		expr(l->left, &res);
142bd389b36SDavid du Colombier 		if(res.type != TINT)
143*219b2ee8SDavid du Colombier 			error("loop must have integer start");
144bd389b36SDavid du Colombier 		s = res.ival;
145bd389b36SDavid du Colombier 		expr(l->right, &res);
146bd389b36SDavid du Colombier 		if(res.type != TINT)
147*219b2ee8SDavid du Colombier 			error("loop must have integer end");
148bd389b36SDavid du Colombier 		e = res.ival;
149*219b2ee8SDavid du Colombier 		for(i = s; i <= e; i++)
150bd389b36SDavid du Colombier 			execute(r);
151bd389b36SDavid du Colombier 		break;
152bd389b36SDavid du Colombier 	}
153bd389b36SDavid du Colombier }
154bd389b36SDavid du Colombier 
155bd389b36SDavid du Colombier int
156bd389b36SDavid du Colombier bool(Node *n)
157bd389b36SDavid du Colombier {
158bd389b36SDavid du Colombier 	int true = 0;
159bd389b36SDavid du Colombier 
160bd389b36SDavid du Colombier 	if(n->op != OCONST)
161bd389b36SDavid du Colombier 		fatal("bool: not const");
162bd389b36SDavid du Colombier 
163bd389b36SDavid du Colombier 	switch(n->type) {
164bd389b36SDavid du Colombier 	case TINT:
165bd389b36SDavid du Colombier 		if(n->ival != 0)
166bd389b36SDavid du Colombier 			true = 1;
167bd389b36SDavid du Colombier 		break;
168bd389b36SDavid du Colombier 	case TFLOAT:
169bd389b36SDavid du Colombier 		if(n->fval != 0.0)
170bd389b36SDavid du Colombier 			true = 1;
171bd389b36SDavid du Colombier 		break;
172bd389b36SDavid du Colombier 	case TSTRING:
173bd389b36SDavid du Colombier 		if(n->string->len)
174bd389b36SDavid du Colombier 			true = 1;
175bd389b36SDavid du Colombier 		break;
176bd389b36SDavid du Colombier 	case TLIST:
177bd389b36SDavid du Colombier 		if(n->l)
178bd389b36SDavid du Colombier 			true = 1;
179bd389b36SDavid du Colombier 		break;
180bd389b36SDavid du Colombier 	}
181bd389b36SDavid du Colombier 	return true;
182bd389b36SDavid du Colombier }
183bd389b36SDavid du Colombier 
184bd389b36SDavid du Colombier void
185*219b2ee8SDavid du Colombier convflt(Node *r, char *flt)
186*219b2ee8SDavid du Colombier {
187*219b2ee8SDavid du Colombier 	char c;
188*219b2ee8SDavid du Colombier 
189*219b2ee8SDavid du Colombier 	c = flt[0];
190*219b2ee8SDavid du Colombier 	if(('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) {
191*219b2ee8SDavid du Colombier 		r->type = TSTRING;
192*219b2ee8SDavid du Colombier 		r->fmt = 's';
193*219b2ee8SDavid du Colombier 		r->string = strnode(flt);
194*219b2ee8SDavid du Colombier 	}
195*219b2ee8SDavid du Colombier 	else {
196*219b2ee8SDavid du Colombier 		r->type = TFLOAT;
197*219b2ee8SDavid du Colombier 		r->fval = atof(flt);
198*219b2ee8SDavid du Colombier 	}
199*219b2ee8SDavid du Colombier }
200*219b2ee8SDavid du Colombier 
201*219b2ee8SDavid du Colombier void
202bd389b36SDavid du Colombier indir(Map *m, ulong addr, char fmt, Node *r)
203bd389b36SDavid du Colombier {
204bd389b36SDavid du Colombier 	int i;
205*219b2ee8SDavid du Colombier 	long ival;
206*219b2ee8SDavid du Colombier 	int ret;
207bd389b36SDavid du Colombier 	uchar cval;
208bd389b36SDavid du Colombier 	ushort sval;
209*219b2ee8SDavid du Colombier 	char buf[512], reg[12];
210bd389b36SDavid du Colombier 
211bd389b36SDavid du Colombier 	r->op = OCONST;
212bd389b36SDavid du Colombier 	r->fmt = fmt;
213bd389b36SDavid du Colombier 	switch(fmt) {
214bd389b36SDavid du Colombier 	default:
215bd389b36SDavid du Colombier 		error("bad pointer format '%c' for *", fmt);
216bd389b36SDavid du Colombier 	case 'c':
217bd389b36SDavid du Colombier 	case 'C':
218bd389b36SDavid du Colombier 	case 'b':
219bd389b36SDavid du Colombier 		r->type = TINT;
220*219b2ee8SDavid du Colombier 		ret = get1(m, addr, &cval, 1);
221*219b2ee8SDavid du Colombier 		if (ret < 0)
222*219b2ee8SDavid du Colombier 			error("indir: %r");
223bd389b36SDavid du Colombier 		r->ival = cval;
224bd389b36SDavid du Colombier 		break;
225bd389b36SDavid du Colombier 	case 'x':
226bd389b36SDavid du Colombier 	case 'd':
227bd389b36SDavid du Colombier 	case 'u':
228bd389b36SDavid du Colombier 	case 'o':
229bd389b36SDavid du Colombier 	case 'q':
230*219b2ee8SDavid du Colombier 	case 'r':
231bd389b36SDavid du Colombier 		r->type = TINT;
232*219b2ee8SDavid du Colombier 		ret = get2(m, addr, &sval);
233*219b2ee8SDavid du Colombier 		if (ret < 0)
234*219b2ee8SDavid du Colombier 			error("indir: %r");
235bd389b36SDavid du Colombier 		r->ival = sval;
236bd389b36SDavid du Colombier 		break;
237*219b2ee8SDavid du Colombier 	case 'a':
238*219b2ee8SDavid du Colombier 	case 'A':
239*219b2ee8SDavid du Colombier 	case 'B':
240bd389b36SDavid du Colombier 	case 'X':
241bd389b36SDavid du Colombier 	case 'D':
242bd389b36SDavid du Colombier 	case 'U':
243bd389b36SDavid du Colombier 	case 'O':
244bd389b36SDavid du Colombier 	case 'Q':
245bd389b36SDavid du Colombier 	case 'Y':
246bd389b36SDavid du Colombier 		r->type = TINT;
247*219b2ee8SDavid du Colombier 		ret = get4(m, addr, &ival);
248*219b2ee8SDavid du Colombier 		if (ret < 0)
249*219b2ee8SDavid du Colombier 			error("indir: %r");
250bd389b36SDavid du Colombier 		r->ival = ival;
251bd389b36SDavid du Colombier 		break;
252bd389b36SDavid du Colombier 	case 's':
253bd389b36SDavid du Colombier 		r->type = TSTRING;
254bd389b36SDavid du Colombier 		for(i = 0; i < sizeof(buf)-1; i++) {
255*219b2ee8SDavid du Colombier 			ret = get1(m, addr, (uchar*)&buf[i], 1);
256*219b2ee8SDavid du Colombier 			if (ret < 0)
257*219b2ee8SDavid du Colombier 				error("indir: %r");
258bd389b36SDavid du Colombier 			addr++;
259bd389b36SDavid du Colombier 			if(buf[i] == '\0')
260bd389b36SDavid du Colombier 				break;
261bd389b36SDavid du Colombier 		}
262bd389b36SDavid du Colombier 		buf[i] = 0;
263*219b2ee8SDavid du Colombier 		if(i == 0)
264*219b2ee8SDavid du Colombier 			strcpy(buf, "(null)");
265bd389b36SDavid du Colombier 		r->string = strnode(buf);
266bd389b36SDavid du Colombier 		break;
267bd389b36SDavid du Colombier 	case 'R':
268bd389b36SDavid du Colombier 		r->type = TSTRING;
269*219b2ee8SDavid du Colombier 		for(i = 0; i < sizeof(buf)-2; i += 2) {
270*219b2ee8SDavid du Colombier 			ret = get1(m, addr, (uchar*)&buf[i], 2);
271*219b2ee8SDavid du Colombier 			if (ret < 0)
272*219b2ee8SDavid du Colombier 				error("indir: %r");
273bd389b36SDavid du Colombier 			addr += 2;
274bd389b36SDavid du Colombier 			if(buf[i] == 0 && buf[i+1] == 0)
275bd389b36SDavid du Colombier 				break;
276bd389b36SDavid du Colombier 		}
277*219b2ee8SDavid du Colombier 		buf[i++] = 0;
278bd389b36SDavid du Colombier 		buf[i] = 0;
279*219b2ee8SDavid du Colombier 		r->string = runenode((Rune*)buf);
280bd389b36SDavid du Colombier 		break;
281bd389b36SDavid du Colombier 	case 'i':
282bd389b36SDavid du Colombier 	case 'I':
283*219b2ee8SDavid du Colombier 		if ((*machdata->das)(m, addr, fmt, buf, sizeof(buf)) < 0)
284*219b2ee8SDavid du Colombier 			error("indir: %r");
285bd389b36SDavid du Colombier 		r->type = TSTRING;
286bd389b36SDavid du Colombier 		r->fmt = 's';
287*219b2ee8SDavid du Colombier 		r->string = strnode(buf);
288bd389b36SDavid du Colombier 		break;
289bd389b36SDavid du Colombier 	case 'f':
290*219b2ee8SDavid du Colombier 		ret = get1(m, addr, (uchar*)buf, mach->szfloat);
291*219b2ee8SDavid du Colombier 		if (ret < 0)
292*219b2ee8SDavid du Colombier 			error("indir: %r");
293*219b2ee8SDavid du Colombier 		machdata->sftos(buf, sizeof(buf), (void*) buf);
294*219b2ee8SDavid du Colombier 		convflt(r, buf);
295*219b2ee8SDavid du Colombier 		break;
296*219b2ee8SDavid du Colombier 	case 'g':
297*219b2ee8SDavid du Colombier 		ret = get1(m, addr, (uchar*)buf, mach->szfloat);
298*219b2ee8SDavid du Colombier 		if (ret < 0)
299*219b2ee8SDavid du Colombier 			error("indir: %r");
300*219b2ee8SDavid du Colombier 		machdata->sftos(buf, sizeof(buf), (void*) buf);
301*219b2ee8SDavid du Colombier 		r->type = TSTRING;
302*219b2ee8SDavid du Colombier 		r->string = strnode(buf);
303bd389b36SDavid du Colombier 		break;
304bd389b36SDavid du Colombier 	case 'F':
305*219b2ee8SDavid du Colombier 		ret = get1(m, addr, (uchar*)buf, mach->szdouble);
306*219b2ee8SDavid du Colombier 		if (ret < 0)
307*219b2ee8SDavid du Colombier 			error("indir: %r");
308*219b2ee8SDavid du Colombier 		machdata->dftos(buf, sizeof(buf), (void*) buf);
309*219b2ee8SDavid du Colombier 		convflt(r, buf);
310*219b2ee8SDavid du Colombier 		break;
311*219b2ee8SDavid du Colombier 	case '3':	/* little endian ieee 80 with hole in bytes 8&9 */
312*219b2ee8SDavid du Colombier 		ret = get1(m, addr, (uchar*)reg, 10);
313*219b2ee8SDavid du Colombier 		if (ret < 0)
314*219b2ee8SDavid du Colombier 			error("indir: %r");
315*219b2ee8SDavid du Colombier 		memmove(reg+10, reg+8, 2);	/* open hole */
316*219b2ee8SDavid du Colombier 		memset(reg+8, 0, 2);		/* fill it */
317*219b2ee8SDavid du Colombier 		leieee80ftos(buf, sizeof(buf), reg);
318*219b2ee8SDavid du Colombier 		convflt(r, buf);
319*219b2ee8SDavid du Colombier 		break;
320*219b2ee8SDavid du Colombier 	case '8':	/* big-endian ieee 80 */
321*219b2ee8SDavid du Colombier 		ret = get1(m, addr, (uchar*)reg, 10);
322*219b2ee8SDavid du Colombier 		if (ret < 0)
323*219b2ee8SDavid du Colombier 			error("indir: %r");
324*219b2ee8SDavid du Colombier 		beieee80ftos(buf, sizeof(buf), reg);
325*219b2ee8SDavid du Colombier 		convflt(r, buf);
326*219b2ee8SDavid du Colombier 		break;
327*219b2ee8SDavid du Colombier 	case 'G':
328*219b2ee8SDavid du Colombier 		ret = get1(m, addr, (uchar*)buf, mach->szdouble);
329*219b2ee8SDavid du Colombier 		if (ret < 0)
330*219b2ee8SDavid du Colombier 			error("indir: %r");
331*219b2ee8SDavid du Colombier 		machdata->dftos(buf, sizeof(buf), (void*) buf);
332*219b2ee8SDavid du Colombier 		r->type = TSTRING;
333*219b2ee8SDavid du Colombier 		r->string = strnode(buf);
334bd389b36SDavid du Colombier 		break;
335bd389b36SDavid du Colombier 	}
336bd389b36SDavid du Colombier }
337bd389b36SDavid du Colombier 
338bd389b36SDavid du Colombier void
339bd389b36SDavid du Colombier windir(Map *m, Node *addr, Node *rval, Node *r)
340bd389b36SDavid du Colombier {
341bd389b36SDavid du Colombier 	uchar cval;
342bd389b36SDavid du Colombier 	ushort sval;
343bd389b36SDavid du Colombier 	Node res, aes;
344*219b2ee8SDavid du Colombier 	int ret;
345bd389b36SDavid du Colombier 
346bd389b36SDavid du Colombier 	if(m == 0)
347bd389b36SDavid du Colombier 		error("no map for */@=");
348bd389b36SDavid du Colombier 
349bd389b36SDavid du Colombier 	expr(rval, &res);
350bd389b36SDavid du Colombier 	expr(addr, &aes);
351bd389b36SDavid du Colombier 
352bd389b36SDavid du Colombier 	if(aes.type != TINT)
353bd389b36SDavid du Colombier 		error("bad type lhs of @/*");
354bd389b36SDavid du Colombier 
355*219b2ee8SDavid du Colombier 	if(m != cormap && wtflag == 0)
356*219b2ee8SDavid du Colombier 		error("not in write mode");
357*219b2ee8SDavid du Colombier 
358bd389b36SDavid du Colombier 	r->type = res.type;
359bd389b36SDavid du Colombier 	r->fmt = res.fmt;
360bd389b36SDavid du Colombier 	r->Store = res.Store;
361bd389b36SDavid du Colombier 
362bd389b36SDavid du Colombier 	switch(res.fmt) {
363bd389b36SDavid du Colombier 	default:
364bd389b36SDavid du Colombier 		error("bad pointer format '%c' for */@=", res.fmt);
365bd389b36SDavid du Colombier 	case 'c':
366bd389b36SDavid du Colombier 	case 'C':
367bd389b36SDavid du Colombier 	case 'b':
368bd389b36SDavid du Colombier 		cval = res.ival;
369*219b2ee8SDavid du Colombier 		ret = put1(m, aes.ival, &cval, 1);
370bd389b36SDavid du Colombier 		break;
371bd389b36SDavid du Colombier 	case 'r':
372bd389b36SDavid du Colombier 	case 'x':
373bd389b36SDavid du Colombier 	case 'd':
374bd389b36SDavid du Colombier 	case 'u':
375bd389b36SDavid du Colombier 	case 'o':
376bd389b36SDavid du Colombier 		sval = res.ival;
377*219b2ee8SDavid du Colombier 		ret = put2(m, aes.ival, sval);
378bd389b36SDavid du Colombier 		r->ival = sval;
379bd389b36SDavid du Colombier 		break;
380*219b2ee8SDavid du Colombier 	case 'a':
381*219b2ee8SDavid du Colombier 	case 'A':
382*219b2ee8SDavid du Colombier 	case 'B':
383bd389b36SDavid du Colombier 	case 'X':
384bd389b36SDavid du Colombier 	case 'D':
385bd389b36SDavid du Colombier 	case 'U':
386bd389b36SDavid du Colombier 	case 'O':
387bd389b36SDavid du Colombier 	case 'Y':
388*219b2ee8SDavid du Colombier 		ret = put4(m, aes.ival, res.ival);
389bd389b36SDavid du Colombier 		break;
390bd389b36SDavid du Colombier 	case 's':
391bd389b36SDavid du Colombier 	case 'R':
392*219b2ee8SDavid du Colombier 		ret = put1(m, aes.ival, (uchar*)res.string->string, res.string->len);
393bd389b36SDavid du Colombier 		break;
394bd389b36SDavid du Colombier 	}
395*219b2ee8SDavid du Colombier 	if (ret < 0)
396*219b2ee8SDavid du Colombier 		error("windir: %r");
397bd389b36SDavid du Colombier }
398bd389b36SDavid du Colombier 
399bd389b36SDavid du Colombier void
400bd389b36SDavid du Colombier call(char *fn, Node *parameters, Node *local, Node *body, Node *retexp)
401bd389b36SDavid du Colombier {
402bd389b36SDavid du Colombier 	int np, i;
403bd389b36SDavid du Colombier 	Rplace rlab;
404bd389b36SDavid du Colombier 	Node *n, res;
405bd389b36SDavid du Colombier 	Value *v, *f;
406bd389b36SDavid du Colombier 	Lsym *s, *next;
407bd389b36SDavid du Colombier 	Node *avp[Maxarg], *ava[Maxarg];
408bd389b36SDavid du Colombier 
409*219b2ee8SDavid du Colombier 	rlab.local = 0;
410*219b2ee8SDavid du Colombier 
411bd389b36SDavid du Colombier 	na = 0;
412bd389b36SDavid du Colombier 	flatten(avp, parameters);
413bd389b36SDavid du Colombier 	np = na;
414bd389b36SDavid du Colombier 	na = 0;
415bd389b36SDavid du Colombier 	flatten(ava, local);
416bd389b36SDavid du Colombier 	if(np != na) {
417bd389b36SDavid du Colombier 		if(np < na)
418bd389b36SDavid du Colombier 			error("%s: too few arguments", fn);
419bd389b36SDavid du Colombier 		error("%s: too many arguments", fn);
420bd389b36SDavid du Colombier 	}
421bd389b36SDavid du Colombier 
422bd389b36SDavid du Colombier 	rlab.tail = &rlab.local;
423bd389b36SDavid du Colombier 
424bd389b36SDavid du Colombier 	ret = &rlab;
425bd389b36SDavid du Colombier 	for(i = 0; i < np; i++) {
426bd389b36SDavid du Colombier 		n = ava[i];
427*219b2ee8SDavid du Colombier 		switch(n->op) {
428*219b2ee8SDavid du Colombier 		default:
429bd389b36SDavid du Colombier 			error("%s: %d formal not a name", fn, i);
430*219b2ee8SDavid du Colombier 		case ONAME:
431bd389b36SDavid du Colombier 			expr(avp[i], &res);
432bd389b36SDavid du Colombier 			s = n->sym;
433*219b2ee8SDavid du Colombier 			break;
434*219b2ee8SDavid du Colombier 		case OINDM:
435*219b2ee8SDavid du Colombier 			res.cc = avp[i];
436*219b2ee8SDavid du Colombier 			res.type = TCODE;
437*219b2ee8SDavid du Colombier 			res.comt = 0;
438*219b2ee8SDavid du Colombier 			if(n->left->op != ONAME)
439*219b2ee8SDavid du Colombier 				error("%s: %d formal not a name", fn, i);
440*219b2ee8SDavid du Colombier 			s = n->left->sym;
441*219b2ee8SDavid du Colombier 			break;
442*219b2ee8SDavid du Colombier 		}
443bd389b36SDavid du Colombier 		if(s->v->ret == ret)
444bd389b36SDavid du Colombier 			error("%s already declared at this scope", s->name);
445bd389b36SDavid du Colombier 
446bd389b36SDavid du Colombier 		v = gmalloc(sizeof(Value));
447bd389b36SDavid du Colombier 		v->ret = ret;
448bd389b36SDavid du Colombier 		v->pop = s->v;
449bd389b36SDavid du Colombier 		s->v = v;
450bd389b36SDavid du Colombier 		v->scope = 0;
451bd389b36SDavid du Colombier 		*(rlab.tail) = s;
452bd389b36SDavid du Colombier 		rlab.tail = &v->scope;
453bd389b36SDavid du Colombier 
454bd389b36SDavid du Colombier 		v->Store = res.Store;
455bd389b36SDavid du Colombier 		v->type = res.type;
456bd389b36SDavid du Colombier 		v->set = 1;
457bd389b36SDavid du Colombier 	}
458bd389b36SDavid du Colombier 
459bd389b36SDavid du Colombier 	ret->val = retexp;
460bd389b36SDavid du Colombier 	if(setjmp(rlab.rlab) == 0)
461bd389b36SDavid du Colombier 		execute(body);
462bd389b36SDavid du Colombier 
463bd389b36SDavid du Colombier 	for(s = rlab.local; s; s = next) {
464bd389b36SDavid du Colombier 		f = s->v;
465bd389b36SDavid du Colombier 		next = f->scope;
466bd389b36SDavid du Colombier 		s->v = f->pop;
467bd389b36SDavid du Colombier 		free(f);
468bd389b36SDavid du Colombier 	}
469bd389b36SDavid du Colombier }
470