xref: /plan9/sys/src/cmd/acid/exec.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
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 {
12219b2ee8SDavid du Colombier 	int i;
13219b2ee8SDavid du Colombier 	char buf[2048];
14*7dd7cddfSDavid 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 {
30*7dd7cddfSDavid du Colombier 		va_start(arg, fmt);
31*7dd7cddfSDavid du Colombier 		doprint(buf, buf+sizeof(buf), fmt, arg);
32*7dd7cddfSDavid 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
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
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;
65bd389b36SDavid du Colombier 	int i, s, e;
66219b2ee8SDavid du Colombier 	Node res, xx;
67bd389b36SDavid du Colombier 	static int stmnt;
68bd389b36SDavid du Colombier 
69bd389b36SDavid du Colombier 	if(gotint)
70bd389b36SDavid du Colombier 		error("interrupted");
71bd389b36SDavid du Colombier 
72bd389b36SDavid du Colombier 	if(n == 0)
73bd389b36SDavid du Colombier 		return;
74bd389b36SDavid du Colombier 
75219b2ee8SDavid du Colombier 	if(stmnt++ > 5000) {
76bd389b36SDavid du Colombier 		Bflush(bout);
77bd389b36SDavid du Colombier 		stmnt = 0;
78bd389b36SDavid du Colombier 	}
79bd389b36SDavid du Colombier 
80bd389b36SDavid du Colombier 	l = n->left;
81bd389b36SDavid du Colombier 	r = n->right;
82bd389b36SDavid du Colombier 
83bd389b36SDavid du Colombier 	switch(n->op) {
84bd389b36SDavid du Colombier 	default:
85bd389b36SDavid du Colombier 		expr(n, &res);
86219b2ee8SDavid du Colombier 		if(ret || (res.type == TLIST && res.l == 0))
87219b2ee8SDavid du Colombier 			break;
88219b2ee8SDavid du Colombier 		prnt->right = &res;
89219b2ee8SDavid du Colombier 		expr(prnt, &xx);
90219b2ee8SDavid du Colombier 		break;
91219b2ee8SDavid du Colombier 	case OASGN:
92219b2ee8SDavid du Colombier 	case OCALL:
93219b2ee8SDavid du Colombier 		expr(n, &res);
94bd389b36SDavid du Colombier 		break;
95bd389b36SDavid du Colombier 	case OCOMPLEX:
96219b2ee8SDavid du Colombier 		decl(n);
97bd389b36SDavid du Colombier 		break;
98bd389b36SDavid du Colombier 	case OLOCAL:
99219b2ee8SDavid du Colombier 		for(n = n->left; n; n = n->left) {
100bd389b36SDavid du Colombier 			if(ret == 0)
101bd389b36SDavid du Colombier 				error("local not in function");
102bd389b36SDavid du Colombier 			sl = n->sym;
103bd389b36SDavid du Colombier 			if(sl->v->ret == ret)
104219b2ee8SDavid du Colombier 				error("%s declared twice", sl->name);
105bd389b36SDavid du Colombier 			v = gmalloc(sizeof(Value));
106bd389b36SDavid du Colombier 			v->ret = ret;
107bd389b36SDavid du Colombier 			v->pop = sl->v;
108bd389b36SDavid du Colombier 			sl->v = v;
109bd389b36SDavid du Colombier 			v->scope = 0;
110bd389b36SDavid du Colombier 			*(ret->tail) = sl;
111bd389b36SDavid du Colombier 			ret->tail = &v->scope;
112bd389b36SDavid du Colombier 			v->set = 0;
113219b2ee8SDavid du Colombier 		}
114bd389b36SDavid du Colombier 		break;
115bd389b36SDavid du Colombier 	case ORET:
116bd389b36SDavid du Colombier 		if(ret == 0)
117bd389b36SDavid du Colombier 			error("return not in function");
118bd389b36SDavid du Colombier 		expr(n->left, ret->val);
119bd389b36SDavid du Colombier 		longjmp(ret->rlab, 1);
120bd389b36SDavid du Colombier 	case OLIST:
121bd389b36SDavid du Colombier 		execute(n->left);
122bd389b36SDavid du Colombier 		execute(n->right);
123bd389b36SDavid du Colombier 		break;
124bd389b36SDavid du Colombier 	case OIF:
125bd389b36SDavid du Colombier 		expr(l, &res);
126bd389b36SDavid du Colombier 		if(r && r->op == OELSE) {
127bd389b36SDavid du Colombier 			if(bool(&res))
128bd389b36SDavid du Colombier 				execute(r->left);
129bd389b36SDavid du Colombier 			else
130bd389b36SDavid du Colombier 				execute(r->right);
131bd389b36SDavid du Colombier 		}
132bd389b36SDavid du Colombier 		else if(bool(&res))
133bd389b36SDavid du Colombier 			execute(r);
134bd389b36SDavid du Colombier 		break;
135bd389b36SDavid du Colombier 	case OWHILE:
136bd389b36SDavid du Colombier 		for(;;) {
137bd389b36SDavid du Colombier 			expr(l, &res);
138bd389b36SDavid du Colombier 			if(!bool(&res))
139bd389b36SDavid du Colombier 				break;
140bd389b36SDavid du Colombier 			execute(r);
141bd389b36SDavid du Colombier 		}
142bd389b36SDavid du Colombier 		break;
143bd389b36SDavid du Colombier 	case ODO:
144bd389b36SDavid du Colombier 		expr(l->left, &res);
145bd389b36SDavid du Colombier 		if(res.type != TINT)
146219b2ee8SDavid du Colombier 			error("loop must have integer start");
147bd389b36SDavid du Colombier 		s = res.ival;
148bd389b36SDavid du Colombier 		expr(l->right, &res);
149bd389b36SDavid du Colombier 		if(res.type != TINT)
150219b2ee8SDavid du Colombier 			error("loop must have integer end");
151bd389b36SDavid du Colombier 		e = res.ival;
152219b2ee8SDavid du Colombier 		for(i = s; i <= e; i++)
153bd389b36SDavid du Colombier 			execute(r);
154bd389b36SDavid du Colombier 		break;
155bd389b36SDavid du Colombier 	}
156bd389b36SDavid du Colombier }
157bd389b36SDavid du Colombier 
158bd389b36SDavid du Colombier int
159bd389b36SDavid du Colombier bool(Node *n)
160bd389b36SDavid du Colombier {
161bd389b36SDavid du Colombier 	int true = 0;
162bd389b36SDavid du Colombier 
163bd389b36SDavid du Colombier 	if(n->op != OCONST)
164bd389b36SDavid du Colombier 		fatal("bool: not const");
165bd389b36SDavid du Colombier 
166bd389b36SDavid du Colombier 	switch(n->type) {
167bd389b36SDavid du Colombier 	case TINT:
168bd389b36SDavid du Colombier 		if(n->ival != 0)
169bd389b36SDavid du Colombier 			true = 1;
170bd389b36SDavid du Colombier 		break;
171bd389b36SDavid du Colombier 	case TFLOAT:
172bd389b36SDavid du Colombier 		if(n->fval != 0.0)
173bd389b36SDavid du Colombier 			true = 1;
174bd389b36SDavid du Colombier 		break;
175bd389b36SDavid du Colombier 	case TSTRING:
176bd389b36SDavid du Colombier 		if(n->string->len)
177bd389b36SDavid du Colombier 			true = 1;
178bd389b36SDavid du Colombier 		break;
179bd389b36SDavid du Colombier 	case TLIST:
180bd389b36SDavid du Colombier 		if(n->l)
181bd389b36SDavid du Colombier 			true = 1;
182bd389b36SDavid du Colombier 		break;
183bd389b36SDavid du Colombier 	}
184bd389b36SDavid du Colombier 	return true;
185bd389b36SDavid du Colombier }
186bd389b36SDavid du Colombier 
187bd389b36SDavid du Colombier void
188219b2ee8SDavid du Colombier convflt(Node *r, char *flt)
189219b2ee8SDavid du Colombier {
190219b2ee8SDavid du Colombier 	char c;
191219b2ee8SDavid du Colombier 
192219b2ee8SDavid du Colombier 	c = flt[0];
193219b2ee8SDavid du Colombier 	if(('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) {
194219b2ee8SDavid du Colombier 		r->type = TSTRING;
195219b2ee8SDavid du Colombier 		r->fmt = 's';
196219b2ee8SDavid du Colombier 		r->string = strnode(flt);
197219b2ee8SDavid du Colombier 	}
198219b2ee8SDavid du Colombier 	else {
199219b2ee8SDavid du Colombier 		r->type = TFLOAT;
200219b2ee8SDavid du Colombier 		r->fval = atof(flt);
201219b2ee8SDavid du Colombier 	}
202219b2ee8SDavid du Colombier }
203219b2ee8SDavid du Colombier 
204219b2ee8SDavid du Colombier void
205bd389b36SDavid du Colombier indir(Map *m, ulong addr, char fmt, Node *r)
206bd389b36SDavid du Colombier {
207bd389b36SDavid du Colombier 	int i;
208219b2ee8SDavid du Colombier 	long ival;
209*7dd7cddfSDavid du Colombier 	vlong vval;
210219b2ee8SDavid du Colombier 	int ret;
211bd389b36SDavid du Colombier 	uchar cval;
212bd389b36SDavid du Colombier 	ushort sval;
213219b2ee8SDavid du Colombier 	char buf[512], reg[12];
214bd389b36SDavid du Colombier 
215bd389b36SDavid du Colombier 	r->op = OCONST;
216bd389b36SDavid du Colombier 	r->fmt = fmt;
217bd389b36SDavid du Colombier 	switch(fmt) {
218bd389b36SDavid du Colombier 	default:
219bd389b36SDavid du Colombier 		error("bad pointer format '%c' for *", fmt);
220bd389b36SDavid du Colombier 	case 'c':
221bd389b36SDavid du Colombier 	case 'C':
222bd389b36SDavid du Colombier 	case 'b':
223bd389b36SDavid du Colombier 		r->type = TINT;
224219b2ee8SDavid du Colombier 		ret = get1(m, addr, &cval, 1);
225219b2ee8SDavid du Colombier 		if (ret < 0)
226219b2ee8SDavid du Colombier 			error("indir: %r");
227bd389b36SDavid du Colombier 		r->ival = cval;
228bd389b36SDavid du Colombier 		break;
229bd389b36SDavid du Colombier 	case 'x':
230bd389b36SDavid du Colombier 	case 'd':
231bd389b36SDavid du Colombier 	case 'u':
232bd389b36SDavid du Colombier 	case 'o':
233bd389b36SDavid du Colombier 	case 'q':
234219b2ee8SDavid du Colombier 	case 'r':
235bd389b36SDavid du Colombier 		r->type = TINT;
236219b2ee8SDavid du Colombier 		ret = get2(m, addr, &sval);
237219b2ee8SDavid du Colombier 		if (ret < 0)
238219b2ee8SDavid du Colombier 			error("indir: %r");
239bd389b36SDavid du Colombier 		r->ival = sval;
240bd389b36SDavid du Colombier 		break;
241219b2ee8SDavid du Colombier 	case 'a':
242219b2ee8SDavid du Colombier 	case 'A':
243219b2ee8SDavid du Colombier 	case 'B':
244bd389b36SDavid du Colombier 	case 'X':
245bd389b36SDavid du Colombier 	case 'D':
246bd389b36SDavid du Colombier 	case 'U':
247bd389b36SDavid du Colombier 	case 'O':
248bd389b36SDavid du Colombier 	case 'Q':
249bd389b36SDavid du Colombier 		r->type = TINT;
250219b2ee8SDavid du Colombier 		ret = get4(m, addr, &ival);
251219b2ee8SDavid du Colombier 		if (ret < 0)
252219b2ee8SDavid du Colombier 			error("indir: %r");
253bd389b36SDavid du Colombier 		r->ival = ival;
254bd389b36SDavid du Colombier 		break;
255*7dd7cddfSDavid du Colombier 	case 'V':
256*7dd7cddfSDavid du Colombier 	case 'W':
257*7dd7cddfSDavid du Colombier 	case 'Y':
258*7dd7cddfSDavid du Colombier 	case 'Z':
259*7dd7cddfSDavid du Colombier 		r->type = TINT;
260*7dd7cddfSDavid du Colombier 		ret = get8(m, addr, &vval);
261*7dd7cddfSDavid du Colombier 		if (ret < 0)
262*7dd7cddfSDavid du Colombier 			error("indir: %r");
263*7dd7cddfSDavid du Colombier 		r->ival = vval;
264*7dd7cddfSDavid du Colombier 		break;
265bd389b36SDavid du Colombier 	case 's':
266bd389b36SDavid du Colombier 		r->type = TSTRING;
267bd389b36SDavid du Colombier 		for(i = 0; i < sizeof(buf)-1; i++) {
268219b2ee8SDavid du Colombier 			ret = get1(m, addr, (uchar*)&buf[i], 1);
269219b2ee8SDavid du Colombier 			if (ret < 0)
270219b2ee8SDavid du Colombier 				error("indir: %r");
271bd389b36SDavid du Colombier 			addr++;
272bd389b36SDavid du Colombier 			if(buf[i] == '\0')
273bd389b36SDavid du Colombier 				break;
274bd389b36SDavid du Colombier 		}
275bd389b36SDavid du Colombier 		buf[i] = 0;
276219b2ee8SDavid du Colombier 		if(i == 0)
277219b2ee8SDavid du Colombier 			strcpy(buf, "(null)");
278bd389b36SDavid du Colombier 		r->string = strnode(buf);
279bd389b36SDavid du Colombier 		break;
280bd389b36SDavid du Colombier 	case 'R':
281bd389b36SDavid du Colombier 		r->type = TSTRING;
282219b2ee8SDavid du Colombier 		for(i = 0; i < sizeof(buf)-2; i += 2) {
283219b2ee8SDavid du Colombier 			ret = get1(m, addr, (uchar*)&buf[i], 2);
284219b2ee8SDavid du Colombier 			if (ret < 0)
285219b2ee8SDavid du Colombier 				error("indir: %r");
286bd389b36SDavid du Colombier 			addr += 2;
287bd389b36SDavid du Colombier 			if(buf[i] == 0 && buf[i+1] == 0)
288bd389b36SDavid du Colombier 				break;
289bd389b36SDavid du Colombier 		}
290219b2ee8SDavid du Colombier 		buf[i++] = 0;
291bd389b36SDavid du Colombier 		buf[i] = 0;
292219b2ee8SDavid du Colombier 		r->string = runenode((Rune*)buf);
293bd389b36SDavid du Colombier 		break;
294bd389b36SDavid du Colombier 	case 'i':
295bd389b36SDavid du Colombier 	case 'I':
296219b2ee8SDavid du Colombier 		if ((*machdata->das)(m, addr, fmt, buf, sizeof(buf)) < 0)
297219b2ee8SDavid du Colombier 			error("indir: %r");
298bd389b36SDavid du Colombier 		r->type = TSTRING;
299bd389b36SDavid du Colombier 		r->fmt = 's';
300219b2ee8SDavid du Colombier 		r->string = strnode(buf);
301bd389b36SDavid du Colombier 		break;
302bd389b36SDavid du Colombier 	case 'f':
303219b2ee8SDavid du Colombier 		ret = get1(m, addr, (uchar*)buf, mach->szfloat);
304219b2ee8SDavid du Colombier 		if (ret < 0)
305219b2ee8SDavid du Colombier 			error("indir: %r");
306219b2ee8SDavid du Colombier 		machdata->sftos(buf, sizeof(buf), (void*) buf);
307219b2ee8SDavid du Colombier 		convflt(r, buf);
308219b2ee8SDavid du Colombier 		break;
309219b2ee8SDavid du Colombier 	case 'g':
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 		r->type = TSTRING;
315219b2ee8SDavid du Colombier 		r->string = strnode(buf);
316bd389b36SDavid du Colombier 		break;
317bd389b36SDavid du Colombier 	case 'F':
318219b2ee8SDavid du Colombier 		ret = get1(m, addr, (uchar*)buf, mach->szdouble);
319219b2ee8SDavid du Colombier 		if (ret < 0)
320219b2ee8SDavid du Colombier 			error("indir: %r");
321219b2ee8SDavid du Colombier 		machdata->dftos(buf, sizeof(buf), (void*) buf);
322219b2ee8SDavid du Colombier 		convflt(r, buf);
323219b2ee8SDavid du Colombier 		break;
324219b2ee8SDavid du Colombier 	case '3':	/* little endian ieee 80 with hole in bytes 8&9 */
325219b2ee8SDavid du Colombier 		ret = get1(m, addr, (uchar*)reg, 10);
326219b2ee8SDavid du Colombier 		if (ret < 0)
327219b2ee8SDavid du Colombier 			error("indir: %r");
328219b2ee8SDavid du Colombier 		memmove(reg+10, reg+8, 2);	/* open hole */
329219b2ee8SDavid du Colombier 		memset(reg+8, 0, 2);		/* fill it */
330219b2ee8SDavid du Colombier 		leieee80ftos(buf, sizeof(buf), reg);
331219b2ee8SDavid du Colombier 		convflt(r, buf);
332219b2ee8SDavid du Colombier 		break;
333219b2ee8SDavid du Colombier 	case '8':	/* big-endian ieee 80 */
334219b2ee8SDavid du Colombier 		ret = get1(m, addr, (uchar*)reg, 10);
335219b2ee8SDavid du Colombier 		if (ret < 0)
336219b2ee8SDavid du Colombier 			error("indir: %r");
337219b2ee8SDavid du Colombier 		beieee80ftos(buf, sizeof(buf), reg);
338219b2ee8SDavid du Colombier 		convflt(r, buf);
339219b2ee8SDavid du Colombier 		break;
340219b2ee8SDavid du Colombier 	case 'G':
341219b2ee8SDavid du Colombier 		ret = get1(m, addr, (uchar*)buf, mach->szdouble);
342219b2ee8SDavid du Colombier 		if (ret < 0)
343219b2ee8SDavid du Colombier 			error("indir: %r");
344219b2ee8SDavid du Colombier 		machdata->dftos(buf, sizeof(buf), (void*) buf);
345219b2ee8SDavid du Colombier 		r->type = TSTRING;
346219b2ee8SDavid du Colombier 		r->string = strnode(buf);
347bd389b36SDavid du Colombier 		break;
348bd389b36SDavid du Colombier 	}
349bd389b36SDavid du Colombier }
350bd389b36SDavid du Colombier 
351bd389b36SDavid du Colombier void
352bd389b36SDavid du Colombier windir(Map *m, Node *addr, Node *rval, Node *r)
353bd389b36SDavid du Colombier {
354bd389b36SDavid du Colombier 	uchar cval;
355bd389b36SDavid du Colombier 	ushort sval;
356bd389b36SDavid du Colombier 	Node res, aes;
357219b2ee8SDavid du Colombier 	int ret;
358bd389b36SDavid du Colombier 
359bd389b36SDavid du Colombier 	if(m == 0)
360bd389b36SDavid du Colombier 		error("no map for */@=");
361bd389b36SDavid du Colombier 
362bd389b36SDavid du Colombier 	expr(rval, &res);
363bd389b36SDavid du Colombier 	expr(addr, &aes);
364bd389b36SDavid du Colombier 
365bd389b36SDavid du Colombier 	if(aes.type != TINT)
366bd389b36SDavid du Colombier 		error("bad type lhs of @/*");
367bd389b36SDavid du Colombier 
368219b2ee8SDavid du Colombier 	if(m != cormap && wtflag == 0)
369219b2ee8SDavid du Colombier 		error("not in write mode");
370219b2ee8SDavid du Colombier 
371bd389b36SDavid du Colombier 	r->type = res.type;
372bd389b36SDavid du Colombier 	r->fmt = res.fmt;
373bd389b36SDavid du Colombier 	r->Store = res.Store;
374bd389b36SDavid du Colombier 
375bd389b36SDavid du Colombier 	switch(res.fmt) {
376bd389b36SDavid du Colombier 	default:
377bd389b36SDavid du Colombier 		error("bad pointer format '%c' for */@=", res.fmt);
378bd389b36SDavid du Colombier 	case 'c':
379bd389b36SDavid du Colombier 	case 'C':
380bd389b36SDavid du Colombier 	case 'b':
381bd389b36SDavid du Colombier 		cval = res.ival;
382219b2ee8SDavid du Colombier 		ret = put1(m, aes.ival, &cval, 1);
383bd389b36SDavid du Colombier 		break;
384bd389b36SDavid du Colombier 	case 'r':
385bd389b36SDavid du Colombier 	case 'x':
386bd389b36SDavid du Colombier 	case 'd':
387bd389b36SDavid du Colombier 	case 'u':
388bd389b36SDavid du Colombier 	case 'o':
389bd389b36SDavid du Colombier 		sval = res.ival;
390219b2ee8SDavid du Colombier 		ret = put2(m, aes.ival, sval);
391bd389b36SDavid du Colombier 		r->ival = sval;
392bd389b36SDavid du Colombier 		break;
393219b2ee8SDavid du Colombier 	case 'a':
394219b2ee8SDavid du Colombier 	case 'A':
395219b2ee8SDavid du Colombier 	case 'B':
396bd389b36SDavid du Colombier 	case 'X':
397bd389b36SDavid du Colombier 	case 'D':
398bd389b36SDavid du Colombier 	case 'U':
399bd389b36SDavid du Colombier 	case 'O':
400219b2ee8SDavid du Colombier 		ret = put4(m, aes.ival, res.ival);
401bd389b36SDavid du Colombier 		break;
402*7dd7cddfSDavid du Colombier 	case 'V':
403*7dd7cddfSDavid du Colombier 	case 'W':
404*7dd7cddfSDavid du Colombier 	case 'Y':
405*7dd7cddfSDavid du Colombier 	case 'Z':
406*7dd7cddfSDavid du Colombier 		ret = put8(m, aes.ival, res.ival);
407*7dd7cddfSDavid du Colombier 		break;
408bd389b36SDavid du Colombier 	case 's':
409bd389b36SDavid du Colombier 	case 'R':
410219b2ee8SDavid du Colombier 		ret = put1(m, aes.ival, (uchar*)res.string->string, res.string->len);
411bd389b36SDavid du Colombier 		break;
412bd389b36SDavid du Colombier 	}
413219b2ee8SDavid du Colombier 	if (ret < 0)
414219b2ee8SDavid du Colombier 		error("windir: %r");
415bd389b36SDavid du Colombier }
416bd389b36SDavid du Colombier 
417bd389b36SDavid du Colombier void
418bd389b36SDavid du Colombier call(char *fn, Node *parameters, Node *local, Node *body, Node *retexp)
419bd389b36SDavid du Colombier {
420bd389b36SDavid du Colombier 	int np, i;
421bd389b36SDavid du Colombier 	Rplace rlab;
422bd389b36SDavid du Colombier 	Node *n, res;
423bd389b36SDavid du Colombier 	Value *v, *f;
424bd389b36SDavid du Colombier 	Lsym *s, *next;
425bd389b36SDavid du Colombier 	Node *avp[Maxarg], *ava[Maxarg];
426bd389b36SDavid du Colombier 
427219b2ee8SDavid du Colombier 	rlab.local = 0;
428219b2ee8SDavid du Colombier 
429bd389b36SDavid du Colombier 	na = 0;
430bd389b36SDavid du Colombier 	flatten(avp, parameters);
431bd389b36SDavid du Colombier 	np = na;
432bd389b36SDavid du Colombier 	na = 0;
433bd389b36SDavid du Colombier 	flatten(ava, local);
434bd389b36SDavid du Colombier 	if(np != na) {
435bd389b36SDavid du Colombier 		if(np < na)
436bd389b36SDavid du Colombier 			error("%s: too few arguments", fn);
437bd389b36SDavid du Colombier 		error("%s: too many arguments", fn);
438bd389b36SDavid du Colombier 	}
439bd389b36SDavid du Colombier 
440bd389b36SDavid du Colombier 	rlab.tail = &rlab.local;
441bd389b36SDavid du Colombier 
442bd389b36SDavid du Colombier 	ret = &rlab;
443bd389b36SDavid du Colombier 	for(i = 0; i < np; i++) {
444bd389b36SDavid du Colombier 		n = ava[i];
445219b2ee8SDavid du Colombier 		switch(n->op) {
446219b2ee8SDavid du Colombier 		default:
447bd389b36SDavid du Colombier 			error("%s: %d formal not a name", fn, i);
448219b2ee8SDavid du Colombier 		case ONAME:
449bd389b36SDavid du Colombier 			expr(avp[i], &res);
450bd389b36SDavid du Colombier 			s = n->sym;
451219b2ee8SDavid du Colombier 			break;
452219b2ee8SDavid du Colombier 		case OINDM:
453219b2ee8SDavid du Colombier 			res.cc = avp[i];
454219b2ee8SDavid du Colombier 			res.type = TCODE;
455219b2ee8SDavid du Colombier 			res.comt = 0;
456219b2ee8SDavid du Colombier 			if(n->left->op != ONAME)
457219b2ee8SDavid du Colombier 				error("%s: %d formal not a name", fn, i);
458219b2ee8SDavid du Colombier 			s = n->left->sym;
459219b2ee8SDavid du Colombier 			break;
460219b2ee8SDavid du Colombier 		}
461bd389b36SDavid du Colombier 		if(s->v->ret == ret)
462bd389b36SDavid du Colombier 			error("%s already declared at this scope", s->name);
463bd389b36SDavid du Colombier 
464bd389b36SDavid du Colombier 		v = gmalloc(sizeof(Value));
465bd389b36SDavid du Colombier 		v->ret = ret;
466bd389b36SDavid du Colombier 		v->pop = s->v;
467bd389b36SDavid du Colombier 		s->v = v;
468bd389b36SDavid du Colombier 		v->scope = 0;
469bd389b36SDavid du Colombier 		*(rlab.tail) = s;
470bd389b36SDavid du Colombier 		rlab.tail = &v->scope;
471bd389b36SDavid du Colombier 
472bd389b36SDavid du Colombier 		v->Store = res.Store;
473bd389b36SDavid du Colombier 		v->type = res.type;
474bd389b36SDavid du Colombier 		v->set = 1;
475bd389b36SDavid du Colombier 	}
476bd389b36SDavid du Colombier 
477bd389b36SDavid du Colombier 	ret->val = retexp;
478bd389b36SDavid du Colombier 	if(setjmp(rlab.rlab) == 0)
479bd389b36SDavid du Colombier 		execute(body);
480bd389b36SDavid du Colombier 
481bd389b36SDavid du Colombier 	for(s = rlab.local; s; s = next) {
482bd389b36SDavid du Colombier 		f = s->v;
483bd389b36SDavid du Colombier 		next = f->scope;
484bd389b36SDavid du Colombier 		s->v = f->pop;
485bd389b36SDavid du Colombier 		free(f);
486bd389b36SDavid du Colombier 	}
487bd389b36SDavid du Colombier }
488