xref: /plan9/sys/src/cmd/acid/exec.c (revision 6f222ee0511ff8945178a4cdc386e7136467042b)
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