xref: /plan9/sys/src/cmd/acid/expr.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 
9*219b2ee8SDavid du Colombier static int fsize[] =
10bd389b36SDavid du Colombier {
11bd389b36SDavid du Colombier 	['C'] 1,
12bd389b36SDavid du Colombier 	['D'] 4,
13*219b2ee8SDavid du Colombier 	['F'] 8,
14*219b2ee8SDavid du Colombier 	['G'] 8,
15bd389b36SDavid du Colombier 	['O'] 4,
16bd389b36SDavid du Colombier 	['Q'] 4,
17*219b2ee8SDavid du Colombier 	['R'] 4,
18*219b2ee8SDavid du Colombier 	['S'] 4,
19*219b2ee8SDavid du Colombier 	['U'] 4,
20*219b2ee8SDavid du Colombier 	['X'] 4,
21*219b2ee8SDavid du Colombier 	['Y'] 4,
22*219b2ee8SDavid du Colombier 	['a'] 4,
23*219b2ee8SDavid du Colombier 	['b'] 1,
24*219b2ee8SDavid du Colombier 	['c'] 1,
25*219b2ee8SDavid du Colombier 	['d'] 2,
26*219b2ee8SDavid du Colombier 	['f'] 4,
27*219b2ee8SDavid du Colombier 	['g'] 4,
28*219b2ee8SDavid du Colombier 	['o'] 2,
29*219b2ee8SDavid du Colombier 	['q'] 2,
30bd389b36SDavid du Colombier 	['r'] 2,
31*219b2ee8SDavid du Colombier 	['s'] 4,
32*219b2ee8SDavid du Colombier 	['u'] 2,
33*219b2ee8SDavid du Colombier 	['x'] 2,
34*219b2ee8SDavid du Colombier 	['A'] 4,
35*219b2ee8SDavid du Colombier 	['B'] 4,
36bd389b36SDavid du Colombier };
37bd389b36SDavid du Colombier 
38bd389b36SDavid du Colombier int
39bd389b36SDavid du Colombier fmtsize(Value *v)
40bd389b36SDavid du Colombier {
41*219b2ee8SDavid du Colombier 	int ret;
42*219b2ee8SDavid du Colombier 
43bd389b36SDavid du Colombier 	switch(v->fmt) {
44bd389b36SDavid du Colombier 	default:
45bd389b36SDavid du Colombier 		return  fsize[v->fmt];
46bd389b36SDavid du Colombier 	case 'i':
47bd389b36SDavid du Colombier 	case 'I':
48*219b2ee8SDavid du Colombier 		if(v->type != TINT || machdata == 0)
49bd389b36SDavid du Colombier 			error("no size for i fmt pointer ++/--");
50*219b2ee8SDavid du Colombier 		ret = (*machdata->instsize)(cormap, v->ival);
51*219b2ee8SDavid du Colombier 		if(ret < 0) {
52*219b2ee8SDavid du Colombier 			ret = (*machdata->instsize)(symmap, v->ival);
53*219b2ee8SDavid du Colombier 			if(ret < 0)
54*219b2ee8SDavid du Colombier 				error("%r");
55*219b2ee8SDavid du Colombier 		}
56*219b2ee8SDavid du Colombier 		return ret;
57bd389b36SDavid du Colombier 	}
58bd389b36SDavid du Colombier }
59bd389b36SDavid du Colombier 
60bd389b36SDavid du Colombier void
61bd389b36SDavid du Colombier chklval(Node *lp)
62bd389b36SDavid du Colombier {
63bd389b36SDavid du Colombier 	if(lp->op != ONAME)
64bd389b36SDavid du Colombier 		error("need l-value");
65bd389b36SDavid du Colombier }
66bd389b36SDavid du Colombier 
67bd389b36SDavid du Colombier void
68*219b2ee8SDavid du Colombier olist(Node *n, Node *res)
69*219b2ee8SDavid du Colombier {
70*219b2ee8SDavid du Colombier 	expr(n->left, res);
71*219b2ee8SDavid du Colombier 	expr(n->right, res);
72*219b2ee8SDavid du Colombier }
73*219b2ee8SDavid du Colombier 
74*219b2ee8SDavid du Colombier void
75*219b2ee8SDavid du Colombier oeval(Node *n, Node *res)
76*219b2ee8SDavid du Colombier {
77*219b2ee8SDavid du Colombier 	expr(n->left, res);
78*219b2ee8SDavid du Colombier 	if(res->type != TCODE)
79*219b2ee8SDavid du Colombier 		error("bad type for eval");
80*219b2ee8SDavid du Colombier 	expr(res->cc, res);
81*219b2ee8SDavid du Colombier }
82*219b2ee8SDavid du Colombier 
83*219b2ee8SDavid du Colombier void
84*219b2ee8SDavid du Colombier ocast(Node *n, Node *res)
85*219b2ee8SDavid du Colombier {
86*219b2ee8SDavid du Colombier 	if(n->sym->lt == 0)
87*219b2ee8SDavid du Colombier 		error("%s is not a complex type", n->sym->name);
88*219b2ee8SDavid du Colombier 
89*219b2ee8SDavid du Colombier 	expr(n->left, res);
90*219b2ee8SDavid du Colombier 	res->comt = n->sym->lt;
91*219b2ee8SDavid du Colombier 	res->fmt = 'a';
92*219b2ee8SDavid du Colombier }
93*219b2ee8SDavid du Colombier 
94*219b2ee8SDavid du Colombier void
95*219b2ee8SDavid du Colombier oindm(Node *n, Node *res)
96bd389b36SDavid du Colombier {
97bd389b36SDavid du Colombier 	Map *m;
98*219b2ee8SDavid du Colombier 	Node l;
99bd389b36SDavid du Colombier 
100bd389b36SDavid du Colombier 	m = cormap;
101bd389b36SDavid du Colombier 	if(m == 0)
102*219b2ee8SDavid du Colombier 		m = symmap;
103*219b2ee8SDavid du Colombier 	expr(n->left, &l);
104*219b2ee8SDavid du Colombier 	if(l.type != TINT)
105*219b2ee8SDavid du Colombier 		error("bad type for *");
106*219b2ee8SDavid du Colombier 	if(m == 0)
107*219b2ee8SDavid du Colombier 		error("no map for *");
108bd389b36SDavid du Colombier 	indir(m, l.ival, l.fmt, res);
109bd389b36SDavid du Colombier 	res->comt = l.comt;
110*219b2ee8SDavid du Colombier }
111*219b2ee8SDavid du Colombier 
112*219b2ee8SDavid du Colombier void
113*219b2ee8SDavid du Colombier oindc(Node *n, Node *res)
114*219b2ee8SDavid du Colombier {
115*219b2ee8SDavid du Colombier 	Map *m;
116*219b2ee8SDavid du Colombier 	Node l;
117*219b2ee8SDavid du Colombier 
118*219b2ee8SDavid du Colombier 	m = symmap;
119*219b2ee8SDavid du Colombier 	if(m == 0)
120*219b2ee8SDavid du Colombier 		m = cormap;
121*219b2ee8SDavid du Colombier 	expr(n->left, &l);
122*219b2ee8SDavid du Colombier 	if(l.type != TINT)
123*219b2ee8SDavid du Colombier 		error("bad type for @");
124*219b2ee8SDavid du Colombier 	if(m == 0)
125*219b2ee8SDavid du Colombier 		error("no map for @");
126*219b2ee8SDavid du Colombier 	indir(m, l.ival, l.fmt, res);
127*219b2ee8SDavid du Colombier 	res->comt = l.comt;
128*219b2ee8SDavid du Colombier }
129*219b2ee8SDavid du Colombier 
130*219b2ee8SDavid du Colombier void
131*219b2ee8SDavid du Colombier oframe(Node *n, Node *res)
132*219b2ee8SDavid du Colombier {
133*219b2ee8SDavid du Colombier 	char *p;
134*219b2ee8SDavid du Colombier 	Node *lp;
135*219b2ee8SDavid du Colombier 	long ival;
136*219b2ee8SDavid du Colombier 	Frtype *f;
137*219b2ee8SDavid du Colombier 
138*219b2ee8SDavid du Colombier 	p = n->sym->name;
139*219b2ee8SDavid du Colombier 	while(*p && *p == '$')
140*219b2ee8SDavid du Colombier 		p++;
141*219b2ee8SDavid du Colombier 	lp = n->left;
142*219b2ee8SDavid du Colombier 	if(localaddr(cormap, p, lp->sym->name, &ival, rget) < 0)
143*219b2ee8SDavid du Colombier 		error("colon: %r");
144*219b2ee8SDavid du Colombier 
145*219b2ee8SDavid du Colombier 	res->ival = ival;
146*219b2ee8SDavid du Colombier 	res->op = OCONST;
147*219b2ee8SDavid du Colombier 	res->fmt = 'X';
148*219b2ee8SDavid du Colombier 	res->type = TINT;
149*219b2ee8SDavid du Colombier 
150*219b2ee8SDavid du Colombier 	/* Try and set comt */
151*219b2ee8SDavid du Colombier 	for(f = n->sym->local; f; f = f->next) {
152*219b2ee8SDavid du Colombier 		if(f->var == lp->sym) {
153*219b2ee8SDavid du Colombier 			res->comt = f->type;
154*219b2ee8SDavid du Colombier 			res->fmt = 'a';
155bd389b36SDavid du Colombier 			break;
156*219b2ee8SDavid du Colombier 		}
157*219b2ee8SDavid du Colombier 	}
158*219b2ee8SDavid du Colombier }
159*219b2ee8SDavid du Colombier 
160*219b2ee8SDavid du Colombier void
161*219b2ee8SDavid du Colombier oindex(Node *n, Node *res)
162*219b2ee8SDavid du Colombier {
163*219b2ee8SDavid du Colombier 	Node l, r;
164*219b2ee8SDavid du Colombier 
165*219b2ee8SDavid du Colombier 	expr(n->left, &l);
166*219b2ee8SDavid du Colombier 	expr(n->right, &r);
167*219b2ee8SDavid du Colombier 
168bd389b36SDavid du Colombier 	if(r.type != TINT)
169bd389b36SDavid du Colombier 		error("bad type for []");
170*219b2ee8SDavid du Colombier 
171bd389b36SDavid du Colombier 	switch(l.type) {
172bd389b36SDavid du Colombier 	default:
173bd389b36SDavid du Colombier 		error("lhs[] has bad type");
174bd389b36SDavid du Colombier 	case TINT:
175*219b2ee8SDavid du Colombier 		indir(cormap, l.ival+(r.ival*fsize[l.fmt]), l.fmt, res);
176*219b2ee8SDavid du Colombier 		res->comt = l.comt;
177*219b2ee8SDavid du Colombier 		res->fmt = l.fmt;
178bd389b36SDavid du Colombier 		break;
179bd389b36SDavid du Colombier 	case TLIST:
180bd389b36SDavid du Colombier 		nthelem(l.l, r.ival, res);
181bd389b36SDavid du Colombier 		break;
182bd389b36SDavid du Colombier 	case TSTRING:
183bd389b36SDavid du Colombier 		res->ival = 0;
184*219b2ee8SDavid du Colombier 		if(r.ival >= 0 && r.ival < l.string->len) {
185*219b2ee8SDavid du Colombier 			int xx8;	/* to get around bug in vc */
186*219b2ee8SDavid du Colombier 			xx8 = r.ival;
187*219b2ee8SDavid du Colombier 			res->ival = l.string->string[xx8];
188*219b2ee8SDavid du Colombier 		}
189bd389b36SDavid du Colombier 		res->op = OCONST;
190bd389b36SDavid du Colombier 		res->type = TINT;
191bd389b36SDavid du Colombier 		res->fmt = 'c';
192bd389b36SDavid du Colombier 		break;
193bd389b36SDavid du Colombier 	}
194*219b2ee8SDavid du Colombier }
195*219b2ee8SDavid du Colombier 
196*219b2ee8SDavid du Colombier void
197*219b2ee8SDavid du Colombier oappend(Node *n, Node *res)
198*219b2ee8SDavid du Colombier {
199*219b2ee8SDavid du Colombier 	Node r, l;
200*219b2ee8SDavid du Colombier 
201*219b2ee8SDavid du Colombier 	expr(n->left, &l);
202*219b2ee8SDavid du Colombier 	expr(n->right, &r);
203bd389b36SDavid du Colombier 	if(l.type != TLIST)
204bd389b36SDavid du Colombier 		error("must append to list");
205bd389b36SDavid du Colombier 	append(res, &l, &r);
206*219b2ee8SDavid du Colombier }
207*219b2ee8SDavid du Colombier 
208*219b2ee8SDavid du Colombier void
209*219b2ee8SDavid du Colombier odelete(Node *n, Node *res)
210*219b2ee8SDavid du Colombier {
211*219b2ee8SDavid du Colombier 	Node l, r;
212*219b2ee8SDavid du Colombier 
213*219b2ee8SDavid du Colombier 	expr(n->left, &l);
214*219b2ee8SDavid du Colombier 	expr(n->right, &r);
215bd389b36SDavid du Colombier 	if(l.type != TLIST)
216bd389b36SDavid du Colombier 		error("must delete from list");
217bd389b36SDavid du Colombier 	if(r.type != TINT)
218bd389b36SDavid du Colombier 		error("delete index must be integer");
219bd389b36SDavid du Colombier 
220bd389b36SDavid du Colombier 	delete(l.l, r.ival, res);
221*219b2ee8SDavid du Colombier }
222*219b2ee8SDavid du Colombier 
223*219b2ee8SDavid du Colombier void
224*219b2ee8SDavid du Colombier ohead(Node *n, Node *res)
225*219b2ee8SDavid du Colombier {
226*219b2ee8SDavid du Colombier 	Node l;
227*219b2ee8SDavid du Colombier 
228*219b2ee8SDavid du Colombier 	expr(n->left, &l);
229bd389b36SDavid du Colombier 	if(l.type != TLIST)
230bd389b36SDavid du Colombier 		error("head needs list");
231bd389b36SDavid du Colombier 	res->op = OCONST;
232bd389b36SDavid du Colombier 	if(l.l) {
233bd389b36SDavid du Colombier 		res->type = l.l->type;
234bd389b36SDavid du Colombier 		res->Store = l.l->Store;
235bd389b36SDavid du Colombier 	}
236bd389b36SDavid du Colombier 	else {
237bd389b36SDavid du Colombier 		res->type = TLIST;
238bd389b36SDavid du Colombier 		res->l = 0;
239bd389b36SDavid du Colombier 	}
240*219b2ee8SDavid du Colombier }
241*219b2ee8SDavid du Colombier 
242*219b2ee8SDavid du Colombier void
243*219b2ee8SDavid du Colombier otail(Node *n, Node *res)
244*219b2ee8SDavid du Colombier {
245*219b2ee8SDavid du Colombier 	Node l;
246*219b2ee8SDavid du Colombier 
247*219b2ee8SDavid du Colombier 	expr(n->left, &l);
248bd389b36SDavid du Colombier 	if(l.type != TLIST)
249bd389b36SDavid du Colombier 		error("tail needs list");
250bd389b36SDavid du Colombier 	res->op = OCONST;
251bd389b36SDavid du Colombier 	res->type = TLIST;
252bd389b36SDavid du Colombier 	if(l.l)
253*219b2ee8SDavid du Colombier 		res->l = l.l->next;
254bd389b36SDavid du Colombier 	else
255*219b2ee8SDavid du Colombier 		res->l = 0;
256*219b2ee8SDavid du Colombier }
257*219b2ee8SDavid du Colombier 
258*219b2ee8SDavid du Colombier void
259*219b2ee8SDavid du Colombier oconst(Node *n, Node *res)
260*219b2ee8SDavid du Colombier {
261*219b2ee8SDavid du Colombier 	res->op = OCONST;
262*219b2ee8SDavid du Colombier 	res->type = n->type;
263*219b2ee8SDavid du Colombier 	res->Store = n->Store;
264*219b2ee8SDavid du Colombier 	res->comt = n->comt;
265*219b2ee8SDavid du Colombier }
266*219b2ee8SDavid du Colombier 
267*219b2ee8SDavid du Colombier void
268*219b2ee8SDavid du Colombier oname(Node *n, Node *res)
269*219b2ee8SDavid du Colombier {
270*219b2ee8SDavid du Colombier 	Value *v;
271*219b2ee8SDavid du Colombier 
272bd389b36SDavid du Colombier 	v = n->sym->v;
273bd389b36SDavid du Colombier 	if(v->set == 0)
274bd389b36SDavid du Colombier 		error("%s used but not set", n->sym->name);
275bd389b36SDavid du Colombier 	res->op = OCONST;
276bd389b36SDavid du Colombier 	res->type = v->type;
277bd389b36SDavid du Colombier 	res->Store = v->Store;
278*219b2ee8SDavid du Colombier 	res->comt = v->comt;
279*219b2ee8SDavid du Colombier }
280*219b2ee8SDavid du Colombier 
281*219b2ee8SDavid du Colombier void
282*219b2ee8SDavid du Colombier octruct(Node *n, Node *res)
283*219b2ee8SDavid du Colombier {
284bd389b36SDavid du Colombier 	res->op = OCONST;
285bd389b36SDavid du Colombier 	res->type = TLIST;
286*219b2ee8SDavid du Colombier 	res->l = construct(n->left);
287*219b2ee8SDavid du Colombier }
288*219b2ee8SDavid du Colombier 
289*219b2ee8SDavid du Colombier void
290*219b2ee8SDavid du Colombier oasgn(Node *n, Node *res)
291*219b2ee8SDavid du Colombier {
292*219b2ee8SDavid du Colombier 	Node *lp, r;
293*219b2ee8SDavid du Colombier 	Value *v;
294*219b2ee8SDavid du Colombier 
295*219b2ee8SDavid du Colombier 	lp = n->left;
296bd389b36SDavid du Colombier 	switch(lp->op) {
297bd389b36SDavid du Colombier 	case OINDM:
298*219b2ee8SDavid du Colombier 		windir(cormap, lp->left, n->right, res);
299bd389b36SDavid du Colombier 		break;
300bd389b36SDavid du Colombier 	case OINDC:
301*219b2ee8SDavid du Colombier 		windir(symmap, lp->left, n->right, res);
302bd389b36SDavid du Colombier 		break;
303bd389b36SDavid du Colombier 	default:
304bd389b36SDavid du Colombier 		chklval(lp);
305bd389b36SDavid du Colombier 		v = lp->sym->v;
306*219b2ee8SDavid du Colombier 		expr(n->right, &r);
307bd389b36SDavid du Colombier 		v->set = 1;
308bd389b36SDavid du Colombier 		v->type = r.type;
309bd389b36SDavid du Colombier 		v->Store = r.Store;
310*219b2ee8SDavid du Colombier 		res->op = OCONST;
311*219b2ee8SDavid du Colombier 		res->type = v->type;
312*219b2ee8SDavid du Colombier 		res->Store = v->Store;
313*219b2ee8SDavid du Colombier 		res->comt = v->comt;
314bd389b36SDavid du Colombier 	}
315*219b2ee8SDavid du Colombier }
316*219b2ee8SDavid du Colombier 
317*219b2ee8SDavid du Colombier void
318*219b2ee8SDavid du Colombier oadd(Node *n, Node *res)
319*219b2ee8SDavid du Colombier {
320*219b2ee8SDavid du Colombier 	Node l, r;
321*219b2ee8SDavid du Colombier 
322*219b2ee8SDavid du Colombier 	expr(n->left, &l);
323*219b2ee8SDavid du Colombier 	expr(n->right, &r);
324bd389b36SDavid du Colombier 	res->fmt = l.fmt;
325bd389b36SDavid du Colombier 	res->op = OCONST;
326bd389b36SDavid du Colombier 	res->type = TFLOAT;
327bd389b36SDavid du Colombier 	switch(l.type) {
328*219b2ee8SDavid du Colombier 	default:
329*219b2ee8SDavid du Colombier 		error("bad lhs type +");
330bd389b36SDavid du Colombier 	case TINT:
331bd389b36SDavid du Colombier 		switch(r.type) {
332bd389b36SDavid du Colombier 		case TINT:
333bd389b36SDavid du Colombier 			res->type = TINT;
334bd389b36SDavid du Colombier 			res->ival = l.ival+r.ival;
335bd389b36SDavid du Colombier 			break;
336bd389b36SDavid du Colombier 		case TFLOAT:
337bd389b36SDavid du Colombier 			res->fval = l.ival+r.fval;
338bd389b36SDavid du Colombier 			break;
339*219b2ee8SDavid du Colombier 		default:
340*219b2ee8SDavid du Colombier 			error("bad rhs type +");
341bd389b36SDavid du Colombier 		}
342bd389b36SDavid du Colombier 		break;
343bd389b36SDavid du Colombier 	case TFLOAT:
344bd389b36SDavid du Colombier 		switch(r.type) {
345bd389b36SDavid du Colombier 		case TINT:
346bd389b36SDavid du Colombier 			res->fval = l.fval+r.ival;
347bd389b36SDavid du Colombier 			break;
348bd389b36SDavid du Colombier 		case TFLOAT:
349bd389b36SDavid du Colombier 			res->fval = l.fval+r.fval;
350bd389b36SDavid du Colombier 			break;
351*219b2ee8SDavid du Colombier 		default:
352*219b2ee8SDavid du Colombier 			error("bad rhs type +");
353bd389b36SDavid du Colombier 		}
354bd389b36SDavid du Colombier 		break;
355bd389b36SDavid du Colombier 	case TSTRING:
356bd389b36SDavid du Colombier 		if(r.type == TSTRING) {
357bd389b36SDavid du Colombier 			res->type = TSTRING;
358bd389b36SDavid du Colombier 			res->fmt = 's';
359bd389b36SDavid du Colombier 			res->string = stradd(l.string, r.string);
360bd389b36SDavid du Colombier 			break;
361bd389b36SDavid du Colombier 		}
362bd389b36SDavid du Colombier 		error("bad rhs for +");
363bd389b36SDavid du Colombier 	case TLIST:
364bd389b36SDavid du Colombier 		res->type = TLIST;
365bd389b36SDavid du Colombier 		switch(r.type) {
366bd389b36SDavid du Colombier 		case TLIST:
367bd389b36SDavid du Colombier 			res->l = addlist(l.l, r.l);
368bd389b36SDavid du Colombier 			break;
369bd389b36SDavid du Colombier 		default:
370bd389b36SDavid du Colombier 			r.left = 0;
371bd389b36SDavid du Colombier 			r.right = 0;
372bd389b36SDavid du Colombier 			res->l = addlist(l.l, construct(&r));
373bd389b36SDavid du Colombier 			break;
374bd389b36SDavid du Colombier 		}
375bd389b36SDavid du Colombier 	}
376*219b2ee8SDavid du Colombier }
377*219b2ee8SDavid du Colombier 
378*219b2ee8SDavid du Colombier void
379*219b2ee8SDavid du Colombier osub(Node *n, Node *res)
380*219b2ee8SDavid du Colombier {
381*219b2ee8SDavid du Colombier 	Node l, r;
382*219b2ee8SDavid du Colombier 
383*219b2ee8SDavid du Colombier 	expr(n->left, &l);
384*219b2ee8SDavid du Colombier 	expr(n->right, &r);
385bd389b36SDavid du Colombier 	res->fmt = l.fmt;
386bd389b36SDavid du Colombier 	res->op = OCONST;
387bd389b36SDavid du Colombier 	res->type = TFLOAT;
388bd389b36SDavid du Colombier 	switch(l.type) {
389*219b2ee8SDavid du Colombier 	default:
390*219b2ee8SDavid du Colombier 		error("bad lhs type -");
391bd389b36SDavid du Colombier 	case TINT:
392bd389b36SDavid du Colombier 		switch(r.type) {
393bd389b36SDavid du Colombier 		case TINT:
394bd389b36SDavid du Colombier 			res->type = TINT;
395bd389b36SDavid du Colombier 			res->ival = l.ival-r.ival;
396bd389b36SDavid du Colombier 			break;
397bd389b36SDavid du Colombier 		case TFLOAT:
398bd389b36SDavid du Colombier 			res->fval = l.ival-r.fval;
399bd389b36SDavid du Colombier 			break;
400*219b2ee8SDavid du Colombier 		default:
401*219b2ee8SDavid du Colombier 			error("bad rhs type -");
402bd389b36SDavid du Colombier 		}
403bd389b36SDavid du Colombier 		break;
404bd389b36SDavid du Colombier 	case TFLOAT:
405*219b2ee8SDavid du Colombier 		switch(r.type) {
406bd389b36SDavid du Colombier 		case TINT:
407bd389b36SDavid du Colombier 			res->fval = l.fval-r.ival;
408bd389b36SDavid du Colombier 			break;
409bd389b36SDavid du Colombier 		case TFLOAT:
410bd389b36SDavid du Colombier 			res->fval = l.fval-r.fval;
411bd389b36SDavid du Colombier 			break;
412*219b2ee8SDavid du Colombier 		default:
413*219b2ee8SDavid du Colombier 			error("bad rhs type -");
414bd389b36SDavid du Colombier 		}
415bd389b36SDavid du Colombier 		break;
416bd389b36SDavid du Colombier 	}
417*219b2ee8SDavid du Colombier }
418*219b2ee8SDavid du Colombier 
419*219b2ee8SDavid du Colombier void
420*219b2ee8SDavid du Colombier omul(Node *n, Node *res)
421*219b2ee8SDavid du Colombier {
422*219b2ee8SDavid du Colombier 	Node l, r;
423*219b2ee8SDavid du Colombier 
424*219b2ee8SDavid du Colombier 	expr(n->left, &l);
425*219b2ee8SDavid du Colombier 	expr(n->right, &r);
426bd389b36SDavid du Colombier 	res->fmt = l.fmt;
427bd389b36SDavid du Colombier 	res->op = OCONST;
428bd389b36SDavid du Colombier 	res->type = TFLOAT;
429bd389b36SDavid du Colombier 	switch(l.type) {
430*219b2ee8SDavid du Colombier 	default:
431*219b2ee8SDavid du Colombier 		error("bad lhs type *");
432bd389b36SDavid du Colombier 	case TINT:
433bd389b36SDavid du Colombier 		switch(r.type) {
434bd389b36SDavid du Colombier 		case TINT:
435bd389b36SDavid du Colombier 			res->type = TINT;
436bd389b36SDavid du Colombier 			res->ival = l.ival*r.ival;
437bd389b36SDavid du Colombier 			break;
438bd389b36SDavid du Colombier 		case TFLOAT:
439bd389b36SDavid du Colombier 			res->fval = l.ival*r.fval;
440bd389b36SDavid du Colombier 			break;
441*219b2ee8SDavid du Colombier 		default:
442*219b2ee8SDavid du Colombier 			error("bad rhs type *");
443bd389b36SDavid du Colombier 		}
444bd389b36SDavid du Colombier 		break;
445bd389b36SDavid du Colombier 	case TFLOAT:
446*219b2ee8SDavid du Colombier 		switch(r.type) {
447bd389b36SDavid du Colombier 		case TINT:
448bd389b36SDavid du Colombier 			res->fval = l.fval*r.ival;
449bd389b36SDavid du Colombier 			break;
450bd389b36SDavid du Colombier 		case TFLOAT:
451bd389b36SDavid du Colombier 			res->fval = l.fval*r.fval;
452bd389b36SDavid du Colombier 			break;
453*219b2ee8SDavid du Colombier 		default:
454*219b2ee8SDavid du Colombier 			error("bad rhs type *");
455bd389b36SDavid du Colombier 		}
456bd389b36SDavid du Colombier 		break;
457bd389b36SDavid du Colombier 	}
458*219b2ee8SDavid du Colombier }
459*219b2ee8SDavid du Colombier 
460*219b2ee8SDavid du Colombier void
461*219b2ee8SDavid du Colombier odiv(Node *n, Node *res)
462*219b2ee8SDavid du Colombier {
463*219b2ee8SDavid du Colombier 	Node l, r;
464*219b2ee8SDavid du Colombier 
465*219b2ee8SDavid du Colombier 	expr(n->left, &l);
466*219b2ee8SDavid du Colombier 	expr(n->right, &r);
467bd389b36SDavid du Colombier 	res->fmt = l.fmt;
468bd389b36SDavid du Colombier 	res->op = OCONST;
469bd389b36SDavid du Colombier 	res->type = TFLOAT;
470bd389b36SDavid du Colombier 	switch(l.type) {
471*219b2ee8SDavid du Colombier 	default:
472*219b2ee8SDavid du Colombier 		error("bad lhs type /");
473bd389b36SDavid du Colombier 	case TINT:
474bd389b36SDavid du Colombier 		switch(r.type) {
475bd389b36SDavid du Colombier 		case TINT:
476bd389b36SDavid du Colombier 			res->type = TINT;
477*219b2ee8SDavid du Colombier 			if(r.ival == 0)
478*219b2ee8SDavid du Colombier 				error("zero divide");
479bd389b36SDavid du Colombier 			res->ival = l.ival/r.ival;
480bd389b36SDavid du Colombier 			break;
481bd389b36SDavid du Colombier 		case TFLOAT:
482*219b2ee8SDavid du Colombier 			if(r.fval == 0)
483*219b2ee8SDavid du Colombier 				error("zero divide");
484bd389b36SDavid du Colombier 			res->fval = l.ival/r.fval;
485bd389b36SDavid du Colombier 			break;
486*219b2ee8SDavid du Colombier 		default:
487*219b2ee8SDavid du Colombier 			error("bad rhs type /");
488bd389b36SDavid du Colombier 		}
489bd389b36SDavid du Colombier 		break;
490bd389b36SDavid du Colombier 	case TFLOAT:
491*219b2ee8SDavid du Colombier 		switch(r.type) {
492bd389b36SDavid du Colombier 		case TINT:
493bd389b36SDavid du Colombier 			res->fval = l.fval/r.ival;
494bd389b36SDavid du Colombier 			break;
495bd389b36SDavid du Colombier 		case TFLOAT:
496bd389b36SDavid du Colombier 			res->fval = l.fval/r.fval;
497bd389b36SDavid du Colombier 			break;
498*219b2ee8SDavid du Colombier 		default:
499*219b2ee8SDavid du Colombier 			error("bad rhs type /");
500bd389b36SDavid du Colombier 		}
501bd389b36SDavid du Colombier 		break;
502bd389b36SDavid du Colombier 	}
503*219b2ee8SDavid du Colombier }
504*219b2ee8SDavid du Colombier 
505*219b2ee8SDavid du Colombier void
506*219b2ee8SDavid du Colombier omod(Node *n, Node *res)
507*219b2ee8SDavid du Colombier {
508*219b2ee8SDavid du Colombier 	Node l, r;
509*219b2ee8SDavid du Colombier 
510*219b2ee8SDavid du Colombier 	expr(n->left, &l);
511*219b2ee8SDavid du Colombier 	expr(n->right, &r);
512bd389b36SDavid du Colombier 	res->fmt = l.fmt;
513bd389b36SDavid du Colombier 	res->op = OCONST;
514bd389b36SDavid du Colombier 	res->type = TINT;
515bd389b36SDavid du Colombier 	if(l.type != TINT || r.type != TINT)
516bd389b36SDavid du Colombier 		error("bad expr type %");
517bd389b36SDavid du Colombier 	res->ival = l.ival%r.ival;
518*219b2ee8SDavid du Colombier }
519*219b2ee8SDavid du Colombier 
520*219b2ee8SDavid du Colombier void
521*219b2ee8SDavid du Colombier olsh(Node *n, Node *res)
522*219b2ee8SDavid du Colombier {
523*219b2ee8SDavid du Colombier 	Node l, r;
524*219b2ee8SDavid du Colombier 
525*219b2ee8SDavid du Colombier 	expr(n->left, &l);
526*219b2ee8SDavid du Colombier 	expr(n->right, &r);
527bd389b36SDavid du Colombier 	res->fmt = l.fmt;
528bd389b36SDavid du Colombier 	res->op = OCONST;
529bd389b36SDavid du Colombier 	res->type = TINT;
530bd389b36SDavid du Colombier 	if(l.type != TINT || r.type != TINT)
531bd389b36SDavid du Colombier 		error("bad expr type <<");
532bd389b36SDavid du Colombier 	res->ival = l.ival<<r.ival;
533*219b2ee8SDavid du Colombier }
534*219b2ee8SDavid du Colombier 
535*219b2ee8SDavid du Colombier void
536*219b2ee8SDavid du Colombier orsh(Node *n, Node *res)
537*219b2ee8SDavid du Colombier {
538*219b2ee8SDavid du Colombier 	Node l, r;
539*219b2ee8SDavid du Colombier 
540*219b2ee8SDavid du Colombier 	expr(n->left, &l);
541*219b2ee8SDavid du Colombier 	expr(n->right, &r);
542bd389b36SDavid du Colombier 	res->fmt = l.fmt;
543bd389b36SDavid du Colombier 	res->op = OCONST;
544bd389b36SDavid du Colombier 	res->type = TINT;
545bd389b36SDavid du Colombier 	if(l.type != TINT || r.type != TINT)
546bd389b36SDavid du Colombier 		error("bad expr type >>");
547bd389b36SDavid du Colombier 	res->ival = l.ival>>r.ival;
548*219b2ee8SDavid du Colombier }
549*219b2ee8SDavid du Colombier 
550*219b2ee8SDavid du Colombier void
551*219b2ee8SDavid du Colombier olt(Node *n, Node *res)
552*219b2ee8SDavid du Colombier {
553*219b2ee8SDavid du Colombier 	Node l, r;
554*219b2ee8SDavid du Colombier 
555*219b2ee8SDavid du Colombier 	expr(n->left, &l);
556*219b2ee8SDavid du Colombier 	expr(n->right, &r);
557*219b2ee8SDavid du Colombier 
558bd389b36SDavid du Colombier 	res->fmt = l.fmt;
559bd389b36SDavid du Colombier 	res->op = OCONST;
560bd389b36SDavid du Colombier 	res->type = TINT;
561bd389b36SDavid du Colombier 	switch(l.type) {
562*219b2ee8SDavid du Colombier 	default:
563*219b2ee8SDavid du Colombier 		error("bad lhs type <");
564bd389b36SDavid du Colombier 	case TINT:
565bd389b36SDavid du Colombier 		switch(r.type) {
566bd389b36SDavid du Colombier 		case TINT:
567bd389b36SDavid du Colombier 			res->ival = l.ival < r.ival;
568bd389b36SDavid du Colombier 			break;
569bd389b36SDavid du Colombier 		case TFLOAT:
570bd389b36SDavid du Colombier 			res->ival = l.ival < r.fval;
571bd389b36SDavid du Colombier 			break;
572*219b2ee8SDavid du Colombier 		default:
573*219b2ee8SDavid du Colombier 			error("bad rhs type <");
574bd389b36SDavid du Colombier 		}
575bd389b36SDavid du Colombier 		break;
576bd389b36SDavid du Colombier 	case TFLOAT:
577*219b2ee8SDavid du Colombier 		switch(r.type) {
578bd389b36SDavid du Colombier 		case TINT:
579bd389b36SDavid du Colombier 			res->ival = l.fval < r.ival;
580bd389b36SDavid du Colombier 			break;
581bd389b36SDavid du Colombier 		case TFLOAT:
582bd389b36SDavid du Colombier 			res->ival = l.fval < r.fval;
583bd389b36SDavid du Colombier 			break;
584*219b2ee8SDavid du Colombier 		default:
585*219b2ee8SDavid du Colombier 			error("bad rhs type <");
586bd389b36SDavid du Colombier 		}
587bd389b36SDavid du Colombier 		break;
588bd389b36SDavid du Colombier 	}
589*219b2ee8SDavid du Colombier }
590*219b2ee8SDavid du Colombier 
591*219b2ee8SDavid du Colombier void
592*219b2ee8SDavid du Colombier ogt(Node *n, Node *res)
593*219b2ee8SDavid du Colombier {
594*219b2ee8SDavid du Colombier 	Node l, r;
595*219b2ee8SDavid du Colombier 
596*219b2ee8SDavid du Colombier 	expr(n->left, &l);
597*219b2ee8SDavid du Colombier 	expr(n->right, &r);
598bd389b36SDavid du Colombier 	res->fmt = 'D';
599bd389b36SDavid du Colombier 	res->op = OCONST;
600bd389b36SDavid du Colombier 	res->type = TINT;
601bd389b36SDavid du Colombier 	switch(l.type) {
602*219b2ee8SDavid du Colombier 	default:
603*219b2ee8SDavid du Colombier 		error("bad lhs type >");
604bd389b36SDavid du Colombier 	case TINT:
605bd389b36SDavid du Colombier 		switch(r.type) {
606bd389b36SDavid du Colombier 		case TINT:
607bd389b36SDavid du Colombier 			res->ival = l.ival > r.ival;
608bd389b36SDavid du Colombier 			break;
609bd389b36SDavid du Colombier 		case TFLOAT:
610bd389b36SDavid du Colombier 			res->ival = l.ival > r.fval;
611bd389b36SDavid du Colombier 			break;
612*219b2ee8SDavid du Colombier 		default:
613*219b2ee8SDavid du Colombier 			error("bad rhs type >");
614bd389b36SDavid du Colombier 		}
615bd389b36SDavid du Colombier 		break;
616bd389b36SDavid du Colombier 	case TFLOAT:
617*219b2ee8SDavid du Colombier 		switch(r.type) {
618bd389b36SDavid du Colombier 		case TINT:
619bd389b36SDavid du Colombier 			res->ival = l.fval > r.ival;
620bd389b36SDavid du Colombier 			break;
621bd389b36SDavid du Colombier 		case TFLOAT:
622bd389b36SDavid du Colombier 			res->ival = l.fval > r.fval;
623bd389b36SDavid du Colombier 			break;
624*219b2ee8SDavid du Colombier 		default:
625*219b2ee8SDavid du Colombier 			error("bad rhs type >");
626bd389b36SDavid du Colombier 		}
627bd389b36SDavid du Colombier 		break;
628bd389b36SDavid du Colombier 	}
629*219b2ee8SDavid du Colombier }
630*219b2ee8SDavid du Colombier 
631*219b2ee8SDavid du Colombier void
632*219b2ee8SDavid du Colombier oleq(Node *n, Node *res)
633*219b2ee8SDavid du Colombier {
634*219b2ee8SDavid du Colombier 	Node l, r;
635*219b2ee8SDavid du Colombier 
636*219b2ee8SDavid du Colombier 	expr(n->left, &l);
637*219b2ee8SDavid du Colombier 	expr(n->right, &r);
638bd389b36SDavid du Colombier 	res->fmt = 'D';
639bd389b36SDavid du Colombier 	res->op = OCONST;
640bd389b36SDavid du Colombier 	res->type = TINT;
641bd389b36SDavid du Colombier 	switch(l.type) {
642*219b2ee8SDavid du Colombier 	default:
643*219b2ee8SDavid du Colombier 		error("bad expr type <=");
644bd389b36SDavid du Colombier 	case TINT:
645bd389b36SDavid du Colombier 		switch(r.type) {
646bd389b36SDavid du Colombier 		case TINT:
647bd389b36SDavid du Colombier 			res->ival = l.ival <= r.ival;
648bd389b36SDavid du Colombier 			break;
649bd389b36SDavid du Colombier 		case TFLOAT:
650bd389b36SDavid du Colombier 			res->ival = l.ival <= r.fval;
651bd389b36SDavid du Colombier 			break;
652*219b2ee8SDavid du Colombier 		default:
653bd389b36SDavid du Colombier 			error("bad expr type <=");
654bd389b36SDavid du Colombier 		}
655bd389b36SDavid du Colombier 		break;
656bd389b36SDavid du Colombier 	case TFLOAT:
657*219b2ee8SDavid du Colombier 		switch(r.type) {
658bd389b36SDavid du Colombier 		case TINT:
659bd389b36SDavid du Colombier 			res->ival = l.fval <= r.ival;
660bd389b36SDavid du Colombier 			break;
661bd389b36SDavid du Colombier 		case TFLOAT:
662bd389b36SDavid du Colombier 			res->ival = l.fval <= r.fval;
663bd389b36SDavid du Colombier 			break;
664*219b2ee8SDavid du Colombier 		default:
665bd389b36SDavid du Colombier 			error("bad expr type <=");
666bd389b36SDavid du Colombier 		}
667bd389b36SDavid du Colombier 		break;
668bd389b36SDavid du Colombier 	}
669*219b2ee8SDavid du Colombier }
670*219b2ee8SDavid du Colombier 
671*219b2ee8SDavid du Colombier void
672*219b2ee8SDavid du Colombier ogeq(Node *n, Node *res)
673*219b2ee8SDavid du Colombier {
674*219b2ee8SDavid du Colombier 	Node l, r;
675*219b2ee8SDavid du Colombier 
676*219b2ee8SDavid du Colombier 	expr(n->left, &l);
677*219b2ee8SDavid du Colombier 	expr(n->right, &r);
678bd389b36SDavid du Colombier 	res->fmt = 'D';
679bd389b36SDavid du Colombier 	res->op = OCONST;
680bd389b36SDavid du Colombier 	res->type = TINT;
681bd389b36SDavid du Colombier 	switch(l.type) {
682*219b2ee8SDavid du Colombier 	default:
683*219b2ee8SDavid du Colombier 		error("bad lhs type >=");
684bd389b36SDavid du Colombier 	case TINT:
685bd389b36SDavid du Colombier 		switch(r.type) {
686bd389b36SDavid du Colombier 		case TINT:
687bd389b36SDavid du Colombier 			res->ival = l.ival >= r.ival;
688bd389b36SDavid du Colombier 			break;
689bd389b36SDavid du Colombier 		case TFLOAT:
690bd389b36SDavid du Colombier 			res->ival = l.ival >= r.fval;
691bd389b36SDavid du Colombier 			break;
692*219b2ee8SDavid du Colombier 		default:
693*219b2ee8SDavid du Colombier 			error("bad rhs type >=");
694bd389b36SDavid du Colombier 		}
695bd389b36SDavid du Colombier 		break;
696bd389b36SDavid du Colombier 	case TFLOAT:
697*219b2ee8SDavid du Colombier 		switch(r.type) {
698bd389b36SDavid du Colombier 		case TINT:
699bd389b36SDavid du Colombier 			res->ival = l.fval >= r.ival;
700bd389b36SDavid du Colombier 			break;
701bd389b36SDavid du Colombier 		case TFLOAT:
702bd389b36SDavid du Colombier 			res->ival = l.fval >= r.fval;
703bd389b36SDavid du Colombier 			break;
704*219b2ee8SDavid du Colombier 		default:
705*219b2ee8SDavid du Colombier 			error("bad rhs type >=");
706bd389b36SDavid du Colombier 		}
707bd389b36SDavid du Colombier 		break;
708bd389b36SDavid du Colombier 	}
709*219b2ee8SDavid du Colombier }
710*219b2ee8SDavid du Colombier 
711*219b2ee8SDavid du Colombier void
712*219b2ee8SDavid du Colombier oeq(Node *n, Node *res)
713*219b2ee8SDavid du Colombier {
714*219b2ee8SDavid du Colombier 	Node l, r;
715*219b2ee8SDavid du Colombier 
716*219b2ee8SDavid du Colombier 	expr(n->left, &l);
717*219b2ee8SDavid du Colombier 	expr(n->right, &r);
718bd389b36SDavid du Colombier 	res->fmt = 'D';
719bd389b36SDavid du Colombier 	res->op = OCONST;
720bd389b36SDavid du Colombier 	res->type = TINT;
721*219b2ee8SDavid du Colombier 	res->ival = 0;
722bd389b36SDavid du Colombier 	switch(l.type) {
723*219b2ee8SDavid du Colombier 	default:
724*219b2ee8SDavid du Colombier 		break;
725bd389b36SDavid du Colombier 	case TINT:
726bd389b36SDavid du Colombier 		switch(r.type) {
727bd389b36SDavid du Colombier 		case TINT:
728bd389b36SDavid du Colombier 			res->ival = l.ival == r.ival;
729bd389b36SDavid du Colombier 			break;
730bd389b36SDavid du Colombier 		case TFLOAT:
731bd389b36SDavid du Colombier 			res->ival = l.ival == r.fval;
732bd389b36SDavid du Colombier 			break;
733*219b2ee8SDavid du Colombier 		default:
734*219b2ee8SDavid du Colombier 			break;
735bd389b36SDavid du Colombier 		}
736bd389b36SDavid du Colombier 		break;
737bd389b36SDavid du Colombier 	case TFLOAT:
738*219b2ee8SDavid du Colombier 		switch(r.type) {
739bd389b36SDavid du Colombier 		case TINT:
740bd389b36SDavid du Colombier 			res->ival = l.fval == r.ival;
741bd389b36SDavid du Colombier 			break;
742bd389b36SDavid du Colombier 		case TFLOAT:
743bd389b36SDavid du Colombier 			res->ival = l.fval == r.fval;
744bd389b36SDavid du Colombier 			break;
745*219b2ee8SDavid du Colombier 		default:
746*219b2ee8SDavid du Colombier 			break;
747bd389b36SDavid du Colombier 		}
748bd389b36SDavid du Colombier 		break;
749bd389b36SDavid du Colombier 	case TSTRING:
750bd389b36SDavid du Colombier 		if(r.type == TSTRING) {
751bd389b36SDavid du Colombier 			res->ival = scmp(r.string, l.string);
752bd389b36SDavid du Colombier 			break;
753bd389b36SDavid du Colombier 		}
754*219b2ee8SDavid du Colombier 		break;
755bd389b36SDavid du Colombier 	case TLIST:
756bd389b36SDavid du Colombier 		if(r.type == TLIST) {
757bd389b36SDavid du Colombier 			res->ival = listcmp(l.l, r.l);
758bd389b36SDavid du Colombier 			break;
759bd389b36SDavid du Colombier 		}
760bd389b36SDavid du Colombier 		break;
761bd389b36SDavid du Colombier 	}
762*219b2ee8SDavid du Colombier 	if(n->op == ONEQ)
763*219b2ee8SDavid du Colombier 		res->ival = !res->ival;
764bd389b36SDavid du Colombier }
765*219b2ee8SDavid du Colombier 
766*219b2ee8SDavid du Colombier 
767*219b2ee8SDavid du Colombier void
768*219b2ee8SDavid du Colombier oland(Node *n, Node *res)
769*219b2ee8SDavid du Colombier {
770*219b2ee8SDavid du Colombier 	Node l, r;
771*219b2ee8SDavid du Colombier 
772*219b2ee8SDavid du Colombier 	expr(n->left, &l);
773*219b2ee8SDavid du Colombier 	expr(n->right, &r);
774bd389b36SDavid du Colombier 	res->fmt = l.fmt;
775bd389b36SDavid du Colombier 	res->op = OCONST;
776bd389b36SDavid du Colombier 	res->type = TINT;
777bd389b36SDavid du Colombier 	if(l.type != TINT || r.type != TINT)
778bd389b36SDavid du Colombier 		error("bad expr type &");
779bd389b36SDavid du Colombier 	res->ival = l.ival&r.ival;
780*219b2ee8SDavid du Colombier }
781*219b2ee8SDavid du Colombier 
782*219b2ee8SDavid du Colombier void
783*219b2ee8SDavid du Colombier oxor(Node *n, Node *res)
784*219b2ee8SDavid du Colombier {
785*219b2ee8SDavid du Colombier 	Node l, r;
786*219b2ee8SDavid du Colombier 
787*219b2ee8SDavid du Colombier 	expr(n->left, &l);
788*219b2ee8SDavid du Colombier 	expr(n->right, &r);
789bd389b36SDavid du Colombier 	res->fmt = l.fmt;
790bd389b36SDavid du Colombier 	res->op = OCONST;
791bd389b36SDavid du Colombier 	res->type = TINT;
792bd389b36SDavid du Colombier 	if(l.type != TINT || r.type != TINT)
793bd389b36SDavid du Colombier 		error("bad expr type ^");
794bd389b36SDavid du Colombier 	res->ival = l.ival^r.ival;
795*219b2ee8SDavid du Colombier }
796*219b2ee8SDavid du Colombier 
797*219b2ee8SDavid du Colombier void
798*219b2ee8SDavid du Colombier olor(Node *n, Node *res)
799*219b2ee8SDavid du Colombier {
800*219b2ee8SDavid du Colombier 	Node l, r;
801*219b2ee8SDavid du Colombier 
802*219b2ee8SDavid du Colombier 	expr(n->left, &l);
803*219b2ee8SDavid du Colombier 	expr(n->right, &r);
804bd389b36SDavid du Colombier 	res->fmt = l.fmt;
805bd389b36SDavid du Colombier 	res->op = OCONST;
806bd389b36SDavid du Colombier 	res->type = TINT;
807bd389b36SDavid du Colombier 	if(l.type != TINT || r.type != TINT)
808bd389b36SDavid du Colombier 		error("bad expr type |");
809bd389b36SDavid du Colombier 	res->ival = l.ival|r.ival;
810*219b2ee8SDavid du Colombier }
811*219b2ee8SDavid du Colombier 
812*219b2ee8SDavid du Colombier void
813*219b2ee8SDavid du Colombier ocand(Node *n, Node *res)
814*219b2ee8SDavid du Colombier {
815*219b2ee8SDavid du Colombier 	Node l, r;
816*219b2ee8SDavid du Colombier 
817bd389b36SDavid du Colombier 	res->fmt = l.fmt;
818bd389b36SDavid du Colombier 	res->op = OCONST;
819bd389b36SDavid du Colombier 	res->type = TINT;
820*219b2ee8SDavid du Colombier 	res->ival = 0;
821*219b2ee8SDavid du Colombier 	expr(n->left, &l);
822*219b2ee8SDavid du Colombier 	if(bool(&l) == 0)
823*219b2ee8SDavid du Colombier 		return;
824*219b2ee8SDavid du Colombier 	expr(n->right, &r);
825*219b2ee8SDavid du Colombier 	if(bool(&r) == 0)
826*219b2ee8SDavid du Colombier 		return;
827*219b2ee8SDavid du Colombier 	res->ival = 1;
828*219b2ee8SDavid du Colombier }
829*219b2ee8SDavid du Colombier 
830*219b2ee8SDavid du Colombier void
831*219b2ee8SDavid du Colombier onot(Node *n, Node *res)
832*219b2ee8SDavid du Colombier {
833*219b2ee8SDavid du Colombier 	Node l;
834*219b2ee8SDavid du Colombier 
835bd389b36SDavid du Colombier 	res->op = OCONST;
836bd389b36SDavid du Colombier 	res->type = TINT;
837*219b2ee8SDavid du Colombier 	res->ival = 0;
838*219b2ee8SDavid du Colombier 	expr(n->left, &l);
839*219b2ee8SDavid du Colombier 	if(bool(&l) == 0)
840*219b2ee8SDavid du Colombier 		res->ival = 1;
841*219b2ee8SDavid du Colombier }
842*219b2ee8SDavid du Colombier 
843*219b2ee8SDavid du Colombier void
844*219b2ee8SDavid du Colombier ocor(Node *n, Node *res)
845*219b2ee8SDavid du Colombier {
846*219b2ee8SDavid du Colombier 	Node l, r;
847*219b2ee8SDavid du Colombier 
848*219b2ee8SDavid du Colombier 	res->op = OCONST;
849*219b2ee8SDavid du Colombier 	res->type = TINT;
850*219b2ee8SDavid du Colombier 	res->ival = 0;
851*219b2ee8SDavid du Colombier 	expr(n->left, &l);
852*219b2ee8SDavid du Colombier 	if(bool(&l)) {
853*219b2ee8SDavid du Colombier 		res->ival = 1;
854*219b2ee8SDavid du Colombier 		return;
855*219b2ee8SDavid du Colombier 	}
856*219b2ee8SDavid du Colombier 	expr(n->right, &r);
857*219b2ee8SDavid du Colombier 	if(bool(&r)) {
858*219b2ee8SDavid du Colombier 		res->ival = 1;
859*219b2ee8SDavid du Colombier 		return;
860*219b2ee8SDavid du Colombier 	}
861*219b2ee8SDavid du Colombier }
862*219b2ee8SDavid du Colombier 
863*219b2ee8SDavid du Colombier void
864*219b2ee8SDavid du Colombier oeinc(Node *n, Node *res)
865*219b2ee8SDavid du Colombier {
866*219b2ee8SDavid du Colombier 	Value *v;
867*219b2ee8SDavid du Colombier 
868*219b2ee8SDavid du Colombier 	chklval(n->left);
869*219b2ee8SDavid du Colombier 	v = n->left->sym->v;
870bd389b36SDavid du Colombier 	res->op = OCONST;
871bd389b36SDavid du Colombier 	res->type = v->type;
872bd389b36SDavid du Colombier 	switch(v->type) {
873bd389b36SDavid du Colombier 	case TINT:
874bd389b36SDavid du Colombier 		if(n->op == OEDEC)
875bd389b36SDavid du Colombier 			v->ival -= fmtsize(v);
876bd389b36SDavid du Colombier 		else
877bd389b36SDavid du Colombier 			v->ival += fmtsize(v);
878bd389b36SDavid du Colombier 		break;
879bd389b36SDavid du Colombier 	case TFLOAT:
880bd389b36SDavid du Colombier 		if(n->op == OEDEC)
881bd389b36SDavid du Colombier 			v->fval--;
882bd389b36SDavid du Colombier 		else
883bd389b36SDavid du Colombier 			v->fval++;
884bd389b36SDavid du Colombier 		break;
885bd389b36SDavid du Colombier 	default:
886bd389b36SDavid du Colombier 		error("bad type for pre --/++");
887bd389b36SDavid du Colombier 	}
888bd389b36SDavid du Colombier 	res->Store = v->Store;
889*219b2ee8SDavid du Colombier }
890*219b2ee8SDavid du Colombier 
891*219b2ee8SDavid du Colombier void
892*219b2ee8SDavid du Colombier opinc(Node *n, Node *res)
893*219b2ee8SDavid du Colombier {
894*219b2ee8SDavid du Colombier 	Value *v;
895*219b2ee8SDavid du Colombier 
896*219b2ee8SDavid du Colombier 	chklval(n->left);
897*219b2ee8SDavid du Colombier 	v = n->left->sym->v;
898bd389b36SDavid du Colombier 	res->op = OCONST;
899bd389b36SDavid du Colombier 	res->type = v->type;
900bd389b36SDavid du Colombier 	res->Store = v->Store;
901bd389b36SDavid du Colombier 	switch(v->type) {
902bd389b36SDavid du Colombier 	case TINT:
903bd389b36SDavid du Colombier 		if(n->op == OPDEC)
904bd389b36SDavid du Colombier 			v->ival -= fmtsize(v);
905bd389b36SDavid du Colombier 		else
906bd389b36SDavid du Colombier 			v->ival += fmtsize(v);
907bd389b36SDavid du Colombier 		break;
908bd389b36SDavid du Colombier 	case TFLOAT:
909bd389b36SDavid du Colombier 		if(n->op == OPDEC)
910bd389b36SDavid du Colombier 			v->fval--;
911bd389b36SDavid du Colombier 		else
912bd389b36SDavid du Colombier 			v->fval++;
913bd389b36SDavid du Colombier 		break;
914bd389b36SDavid du Colombier 	default:
915bd389b36SDavid du Colombier 		error("bad type for post --/++");
916bd389b36SDavid du Colombier 	}
917*219b2ee8SDavid du Colombier }
918*219b2ee8SDavid du Colombier 
919*219b2ee8SDavid du Colombier void
920*219b2ee8SDavid du Colombier ocall(Node *n, Node *res)
921*219b2ee8SDavid du Colombier {
922*219b2ee8SDavid du Colombier 	Lsym *s;
923*219b2ee8SDavid du Colombier 	Rplace *rsav;
924*219b2ee8SDavid du Colombier 
925bd389b36SDavid du Colombier 	res->op = OCONST;		/* Default return value */
926bd389b36SDavid du Colombier 	res->type = TLIST;
927bd389b36SDavid du Colombier 	res->l = 0;
928bd389b36SDavid du Colombier 
929*219b2ee8SDavid du Colombier 	chklval(n->left);
930*219b2ee8SDavid du Colombier 	s = n->left->sym;
931bd389b36SDavid du Colombier 
932bd389b36SDavid du Colombier 	if(s->builtin) {
933*219b2ee8SDavid du Colombier 		(*s->builtin)(res, n->right);
934*219b2ee8SDavid du Colombier 		return;
935bd389b36SDavid du Colombier 	}
936bd389b36SDavid du Colombier 	if(s->proc == 0)
937bd389b36SDavid du Colombier 		error("no function %s", s->name);
938bd389b36SDavid du Colombier 
939bd389b36SDavid du Colombier 	rsav = ret;
940*219b2ee8SDavid du Colombier 	call(s->name, n->right, s->proc->left, s->proc->right, res);
941bd389b36SDavid du Colombier 	ret = rsav;
942bd389b36SDavid du Colombier }
943*219b2ee8SDavid du Colombier 
944*219b2ee8SDavid du Colombier void
945*219b2ee8SDavid du Colombier ofmt(Node *n, Node *res)
946*219b2ee8SDavid du Colombier {
947*219b2ee8SDavid du Colombier 	expr(n->left, res);
948*219b2ee8SDavid du Colombier 	res->fmt = n->right->ival;
949bd389b36SDavid du Colombier }
950*219b2ee8SDavid du Colombier 
951*219b2ee8SDavid du Colombier void
952*219b2ee8SDavid du Colombier owhat(Node *n, Node *res)
953*219b2ee8SDavid du Colombier {
954*219b2ee8SDavid du Colombier 	res->op = OCONST;		/* Default return value */
955*219b2ee8SDavid du Colombier 	res->type = TLIST;
956*219b2ee8SDavid du Colombier 	res->l = 0;
957*219b2ee8SDavid du Colombier 	whatis(n->sym);
958*219b2ee8SDavid du Colombier }
959*219b2ee8SDavid du Colombier 
960*219b2ee8SDavid du Colombier void (*expop[])(Node*, Node*) =
961*219b2ee8SDavid du Colombier {
962*219b2ee8SDavid du Colombier 	[ONAME]		oname,
963*219b2ee8SDavid du Colombier 	[OCONST]	oconst,
964*219b2ee8SDavid du Colombier 	[OMUL]		omul,
965*219b2ee8SDavid du Colombier 	[ODIV]		odiv,
966*219b2ee8SDavid du Colombier 	[OMOD]		omod,
967*219b2ee8SDavid du Colombier 	[OADD]		oadd,
968*219b2ee8SDavid du Colombier 	[OSUB]		osub,
969*219b2ee8SDavid du Colombier 	[ORSH]		orsh,
970*219b2ee8SDavid du Colombier 	[OLSH]		olsh,
971*219b2ee8SDavid du Colombier 	[OLT]		olt,
972*219b2ee8SDavid du Colombier 	[OGT]		ogt,
973*219b2ee8SDavid du Colombier 	[OLEQ]		oleq,
974*219b2ee8SDavid du Colombier 	[OGEQ]		ogeq,
975*219b2ee8SDavid du Colombier 	[OEQ]		oeq,
976*219b2ee8SDavid du Colombier 	[ONEQ]		oeq,
977*219b2ee8SDavid du Colombier 	[OLAND]		oland,
978*219b2ee8SDavid du Colombier 	[OXOR]		oxor,
979*219b2ee8SDavid du Colombier 	[OLOR]		olor,
980*219b2ee8SDavid du Colombier 	[OCAND]		ocand,
981*219b2ee8SDavid du Colombier 	[OCOR]		ocor,
982*219b2ee8SDavid du Colombier 	[OASGN]		oasgn,
983*219b2ee8SDavid du Colombier 	[OINDM]		oindm,
984*219b2ee8SDavid du Colombier 	[OEDEC]		oeinc,
985*219b2ee8SDavid du Colombier 	[OEINC]		oeinc,
986*219b2ee8SDavid du Colombier 	[OPINC]		opinc,
987*219b2ee8SDavid du Colombier 	[OPDEC]		opinc,
988*219b2ee8SDavid du Colombier 	[ONOT]		onot,
989*219b2ee8SDavid du Colombier 	[OIF]		0,
990*219b2ee8SDavid du Colombier 	[ODO]		0,
991*219b2ee8SDavid du Colombier 	[OLIST]		olist,
992*219b2ee8SDavid du Colombier 	[OCALL]		ocall,
993*219b2ee8SDavid du Colombier 	[OCTRUCT]	octruct,
994*219b2ee8SDavid du Colombier 	[OWHILE]	0,
995*219b2ee8SDavid du Colombier 	[OELSE]		0,
996*219b2ee8SDavid du Colombier 	[OHEAD]		ohead,
997*219b2ee8SDavid du Colombier 	[OTAIL]		otail,
998*219b2ee8SDavid du Colombier 	[OAPPEND]	oappend,
999*219b2ee8SDavid du Colombier 	[ORET]		0,
1000*219b2ee8SDavid du Colombier 	[OINDEX]	oindex,
1001*219b2ee8SDavid du Colombier 	[OINDC]		oindc,
1002*219b2ee8SDavid du Colombier 	[ODOT]		odot,
1003*219b2ee8SDavid du Colombier 	[OLOCAL]	0,
1004*219b2ee8SDavid du Colombier 	[OFRAME]	oframe,
1005*219b2ee8SDavid du Colombier 	[OCOMPLEX]	0,
1006*219b2ee8SDavid du Colombier 	[ODELETE]	odelete,
1007*219b2ee8SDavid du Colombier 	[OCAST]		ocast,
1008*219b2ee8SDavid du Colombier 	[OFMT]		ofmt,
1009*219b2ee8SDavid du Colombier 	[OEVAL]		oeval,
1010*219b2ee8SDavid du Colombier 	[OWHAT]		owhat,
1011*219b2ee8SDavid du Colombier };
1012