xref: /plan9-contrib/sys/src/cmd/acid/expr.c (revision 7c70c028d2d46a27a61ae88e6df0eb0935d9da7a)
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 
9219b2ee8SDavid du Colombier static int fsize[] =
10bd389b36SDavid du Colombier {
117dd7cddfSDavid du Colombier 	['A'] 4,
127dd7cddfSDavid du Colombier 	['B'] 4,
13bd389b36SDavid du Colombier 	['C'] 1,
14bd389b36SDavid du Colombier 	['D'] 4,
15219b2ee8SDavid du Colombier 	['F'] 8,
16219b2ee8SDavid du Colombier 	['G'] 8,
17bd389b36SDavid du Colombier 	['O'] 4,
18bd389b36SDavid du Colombier 	['Q'] 4,
19219b2ee8SDavid du Colombier 	['R'] 4,
20219b2ee8SDavid du Colombier 	['S'] 4,
21219b2ee8SDavid du Colombier 	['U'] 4,
227dd7cddfSDavid du Colombier 	['V'] 8,
231bd28109SDavid du Colombier 	['W'] 8,
24219b2ee8SDavid du Colombier 	['X'] 4,
257dd7cddfSDavid du Colombier 	['Y'] 8,
267dd7cddfSDavid du Colombier 	['Z'] 8,
27219b2ee8SDavid du Colombier 	['a'] 4,
28219b2ee8SDavid du Colombier 	['b'] 1,
29219b2ee8SDavid du Colombier 	['c'] 1,
30219b2ee8SDavid du Colombier 	['d'] 2,
31219b2ee8SDavid du Colombier 	['f'] 4,
32219b2ee8SDavid du Colombier 	['g'] 4,
33219b2ee8SDavid du Colombier 	['o'] 2,
34219b2ee8SDavid du Colombier 	['q'] 2,
35bd389b36SDavid du Colombier 	['r'] 2,
36219b2ee8SDavid du Colombier 	['s'] 4,
37219b2ee8SDavid du Colombier 	['u'] 2,
38219b2ee8SDavid du Colombier 	['x'] 2,
3937e88e97SDavid du Colombier 	['3'] 10,
4037e88e97SDavid du Colombier 	['8'] 10,
41bd389b36SDavid du Colombier };
42bd389b36SDavid du Colombier 
43bd389b36SDavid du Colombier int
44bd389b36SDavid du Colombier fmtsize(Value *v)
45bd389b36SDavid du Colombier {
46219b2ee8SDavid du Colombier 	int ret;
47219b2ee8SDavid du Colombier 
48bd389b36SDavid du Colombier 	switch(v->fmt) {
49bd389b36SDavid du Colombier 	default:
50bd389b36SDavid du Colombier 		return  fsize[v->fmt];
51bd389b36SDavid du Colombier 	case 'i':
52bd389b36SDavid du Colombier 	case 'I':
53219b2ee8SDavid du Colombier 		if(v->type != TINT || machdata == 0)
54bd389b36SDavid du Colombier 			error("no size for i fmt pointer ++/--");
55219b2ee8SDavid du Colombier 		ret = (*machdata->instsize)(cormap, v->ival);
56219b2ee8SDavid du Colombier 		if(ret < 0) {
57219b2ee8SDavid du Colombier 			ret = (*machdata->instsize)(symmap, v->ival);
58219b2ee8SDavid du Colombier 			if(ret < 0)
59219b2ee8SDavid du Colombier 				error("%r");
60219b2ee8SDavid du Colombier 		}
61219b2ee8SDavid du Colombier 		return ret;
62bd389b36SDavid du Colombier 	}
63bd389b36SDavid du Colombier }
64bd389b36SDavid du Colombier 
65bd389b36SDavid du Colombier void
66bd389b36SDavid du Colombier chklval(Node *lp)
67bd389b36SDavid du Colombier {
68bd389b36SDavid du Colombier 	if(lp->op != ONAME)
69bd389b36SDavid du Colombier 		error("need l-value");
70bd389b36SDavid du Colombier }
71bd389b36SDavid du Colombier 
72bd389b36SDavid du Colombier void
73219b2ee8SDavid du Colombier olist(Node *n, Node *res)
74219b2ee8SDavid du Colombier {
75219b2ee8SDavid du Colombier 	expr(n->left, res);
76219b2ee8SDavid du Colombier 	expr(n->right, res);
77219b2ee8SDavid du Colombier }
78219b2ee8SDavid du Colombier 
79219b2ee8SDavid du Colombier void
80219b2ee8SDavid du Colombier oeval(Node *n, Node *res)
81219b2ee8SDavid du Colombier {
82219b2ee8SDavid du Colombier 	expr(n->left, res);
83219b2ee8SDavid du Colombier 	if(res->type != TCODE)
84219b2ee8SDavid du Colombier 		error("bad type for eval");
85219b2ee8SDavid du Colombier 	expr(res->cc, res);
86219b2ee8SDavid du Colombier }
87219b2ee8SDavid du Colombier 
88219b2ee8SDavid du Colombier void
89219b2ee8SDavid du Colombier ocast(Node *n, Node *res)
90219b2ee8SDavid du Colombier {
91219b2ee8SDavid du Colombier 	if(n->sym->lt == 0)
92219b2ee8SDavid du Colombier 		error("%s is not a complex type", n->sym->name);
93219b2ee8SDavid du Colombier 
94219b2ee8SDavid du Colombier 	expr(n->left, res);
95219b2ee8SDavid du Colombier 	res->comt = n->sym->lt;
96219b2ee8SDavid du Colombier 	res->fmt = 'a';
97219b2ee8SDavid du Colombier }
98219b2ee8SDavid du Colombier 
99219b2ee8SDavid du Colombier void
100219b2ee8SDavid du Colombier oindm(Node *n, Node *res)
101bd389b36SDavid du Colombier {
102bd389b36SDavid du Colombier 	Map *m;
103219b2ee8SDavid du Colombier 	Node l;
104bd389b36SDavid du Colombier 
105bd389b36SDavid du Colombier 	m = cormap;
106bd389b36SDavid du Colombier 	if(m == 0)
107219b2ee8SDavid du Colombier 		m = symmap;
108219b2ee8SDavid du Colombier 	expr(n->left, &l);
109219b2ee8SDavid du Colombier 	if(l.type != TINT)
110219b2ee8SDavid du Colombier 		error("bad type for *");
111219b2ee8SDavid du Colombier 	if(m == 0)
112219b2ee8SDavid du Colombier 		error("no map for *");
113bd389b36SDavid du Colombier 	indir(m, l.ival, l.fmt, res);
114bd389b36SDavid du Colombier 	res->comt = l.comt;
115219b2ee8SDavid du Colombier }
116219b2ee8SDavid du Colombier 
117219b2ee8SDavid du Colombier void
118219b2ee8SDavid du Colombier oindc(Node *n, Node *res)
119219b2ee8SDavid du Colombier {
120219b2ee8SDavid du Colombier 	Map *m;
121219b2ee8SDavid du Colombier 	Node l;
122219b2ee8SDavid du Colombier 
123219b2ee8SDavid du Colombier 	m = symmap;
124219b2ee8SDavid du Colombier 	if(m == 0)
125219b2ee8SDavid du Colombier 		m = cormap;
126219b2ee8SDavid du Colombier 	expr(n->left, &l);
127219b2ee8SDavid du Colombier 	if(l.type != TINT)
128219b2ee8SDavid du Colombier 		error("bad type for @");
129219b2ee8SDavid du Colombier 	if(m == 0)
130219b2ee8SDavid du Colombier 		error("no map for @");
131219b2ee8SDavid du Colombier 	indir(m, l.ival, l.fmt, res);
132219b2ee8SDavid du Colombier 	res->comt = l.comt;
133219b2ee8SDavid du Colombier }
134219b2ee8SDavid du Colombier 
135219b2ee8SDavid du Colombier void
136219b2ee8SDavid du Colombier oframe(Node *n, Node *res)
137219b2ee8SDavid du Colombier {
138219b2ee8SDavid du Colombier 	char *p;
139219b2ee8SDavid du Colombier 	Node *lp;
1404de34a7eSDavid du Colombier 	uvlong ival;
141219b2ee8SDavid du Colombier 	Frtype *f;
142219b2ee8SDavid du Colombier 
143219b2ee8SDavid du Colombier 	p = n->sym->name;
144219b2ee8SDavid du Colombier 	while(*p && *p == '$')
145219b2ee8SDavid du Colombier 		p++;
146219b2ee8SDavid du Colombier 	lp = n->left;
147219b2ee8SDavid du Colombier 	if(localaddr(cormap, p, lp->sym->name, &ival, rget) < 0)
148219b2ee8SDavid du Colombier 		error("colon: %r");
149219b2ee8SDavid du Colombier 
150219b2ee8SDavid du Colombier 	res->ival = ival;
151219b2ee8SDavid du Colombier 	res->op = OCONST;
152219b2ee8SDavid du Colombier 	res->fmt = 'X';
153219b2ee8SDavid du Colombier 	res->type = TINT;
154219b2ee8SDavid du Colombier 
155219b2ee8SDavid du Colombier 	/* Try and set comt */
156219b2ee8SDavid du Colombier 	for(f = n->sym->local; f; f = f->next) {
157219b2ee8SDavid du Colombier 		if(f->var == lp->sym) {
158219b2ee8SDavid du Colombier 			res->comt = f->type;
159219b2ee8SDavid du Colombier 			res->fmt = 'a';
160bd389b36SDavid du Colombier 			break;
161219b2ee8SDavid du Colombier 		}
162219b2ee8SDavid du Colombier 	}
163219b2ee8SDavid du Colombier }
164219b2ee8SDavid du Colombier 
165219b2ee8SDavid du Colombier void
166219b2ee8SDavid du Colombier oindex(Node *n, Node *res)
167219b2ee8SDavid du Colombier {
168219b2ee8SDavid du Colombier 	Node l, r;
169219b2ee8SDavid du Colombier 
170219b2ee8SDavid du Colombier 	expr(n->left, &l);
171219b2ee8SDavid du Colombier 	expr(n->right, &r);
172219b2ee8SDavid du Colombier 
173bd389b36SDavid du Colombier 	if(r.type != TINT)
174bd389b36SDavid du Colombier 		error("bad type for []");
175219b2ee8SDavid du Colombier 
176bd389b36SDavid du Colombier 	switch(l.type) {
177bd389b36SDavid du Colombier 	default:
178bd389b36SDavid du Colombier 		error("lhs[] has bad type");
179bd389b36SDavid du Colombier 	case TINT:
180219b2ee8SDavid du Colombier 		indir(cormap, l.ival+(r.ival*fsize[l.fmt]), l.fmt, res);
181219b2ee8SDavid du Colombier 		res->comt = l.comt;
182219b2ee8SDavid du Colombier 		res->fmt = l.fmt;
183bd389b36SDavid du Colombier 		break;
184bd389b36SDavid du Colombier 	case TLIST:
185bd389b36SDavid du Colombier 		nthelem(l.l, r.ival, res);
186bd389b36SDavid du Colombier 		break;
187bd389b36SDavid du Colombier 	case TSTRING:
188bd389b36SDavid du Colombier 		res->ival = 0;
189219b2ee8SDavid du Colombier 		if(r.ival >= 0 && r.ival < l.string->len) {
190219b2ee8SDavid du Colombier 			int xx8;	/* to get around bug in vc */
191219b2ee8SDavid du Colombier 			xx8 = r.ival;
192219b2ee8SDavid du Colombier 			res->ival = l.string->string[xx8];
193219b2ee8SDavid du Colombier 		}
194bd389b36SDavid du Colombier 		res->op = OCONST;
195bd389b36SDavid du Colombier 		res->type = TINT;
196bd389b36SDavid du Colombier 		res->fmt = 'c';
197bd389b36SDavid du Colombier 		break;
198bd389b36SDavid du Colombier 	}
199219b2ee8SDavid du Colombier }
200219b2ee8SDavid du Colombier 
201219b2ee8SDavid du Colombier void
202219b2ee8SDavid du Colombier oappend(Node *n, Node *res)
203219b2ee8SDavid du Colombier {
204*7c70c028SDavid du Colombier 	Value *v;
205219b2ee8SDavid du Colombier 	Node r, l;
206*7c70c028SDavid du Colombier 	int  empty;
207219b2ee8SDavid du Colombier 
208219b2ee8SDavid du Colombier 	expr(n->left, &l);
209219b2ee8SDavid du Colombier 	expr(n->right, &r);
210bd389b36SDavid du Colombier 	if(l.type != TLIST)
211bd389b36SDavid du Colombier 		error("must append to list");
212*7c70c028SDavid du Colombier 	empty = (l.l == nil && (n->left->op == ONAME));
213bd389b36SDavid du Colombier 	append(res, &l, &r);
214*7c70c028SDavid du Colombier 	if(empty) {
215*7c70c028SDavid du Colombier 		v = n->left->sym->v;
216*7c70c028SDavid du Colombier 		v->type = res->type;
217*7c70c028SDavid du Colombier 		v->Store = res->Store;
218*7c70c028SDavid du Colombier 		v->comt = res->comt;
219*7c70c028SDavid du Colombier 	}
220219b2ee8SDavid du Colombier }
221219b2ee8SDavid du Colombier 
222219b2ee8SDavid du Colombier void
223219b2ee8SDavid du Colombier odelete(Node *n, Node *res)
224219b2ee8SDavid du Colombier {
225219b2ee8SDavid du Colombier 	Node l, r;
226219b2ee8SDavid du Colombier 
227219b2ee8SDavid du Colombier 	expr(n->left, &l);
228219b2ee8SDavid du Colombier 	expr(n->right, &r);
229bd389b36SDavid du Colombier 	if(l.type != TLIST)
230bd389b36SDavid du Colombier 		error("must delete from list");
231bd389b36SDavid du Colombier 	if(r.type != TINT)
232bd389b36SDavid du Colombier 		error("delete index must be integer");
233bd389b36SDavid du Colombier 
234bd389b36SDavid du Colombier 	delete(l.l, r.ival, res);
235219b2ee8SDavid du Colombier }
236219b2ee8SDavid du Colombier 
237219b2ee8SDavid du Colombier void
238219b2ee8SDavid du Colombier ohead(Node *n, Node *res)
239219b2ee8SDavid du Colombier {
240219b2ee8SDavid du Colombier 	Node l;
241219b2ee8SDavid du Colombier 
242219b2ee8SDavid du Colombier 	expr(n->left, &l);
243bd389b36SDavid du Colombier 	if(l.type != TLIST)
244bd389b36SDavid du Colombier 		error("head needs list");
245bd389b36SDavid du Colombier 	res->op = OCONST;
246bd389b36SDavid du Colombier 	if(l.l) {
247bd389b36SDavid du Colombier 		res->type = l.l->type;
248bd389b36SDavid du Colombier 		res->Store = l.l->Store;
249bd389b36SDavid du Colombier 	}
250bd389b36SDavid du Colombier 	else {
251bd389b36SDavid du Colombier 		res->type = TLIST;
252bd389b36SDavid du Colombier 		res->l = 0;
253bd389b36SDavid du Colombier 	}
254219b2ee8SDavid du Colombier }
255219b2ee8SDavid du Colombier 
256219b2ee8SDavid du Colombier void
257219b2ee8SDavid du Colombier otail(Node *n, Node *res)
258219b2ee8SDavid du Colombier {
259219b2ee8SDavid du Colombier 	Node l;
260219b2ee8SDavid du Colombier 
261219b2ee8SDavid du Colombier 	expr(n->left, &l);
262bd389b36SDavid du Colombier 	if(l.type != TLIST)
263bd389b36SDavid du Colombier 		error("tail needs list");
264bd389b36SDavid du Colombier 	res->op = OCONST;
265bd389b36SDavid du Colombier 	res->type = TLIST;
266bd389b36SDavid du Colombier 	if(l.l)
267219b2ee8SDavid du Colombier 		res->l = l.l->next;
268bd389b36SDavid du Colombier 	else
269219b2ee8SDavid du Colombier 		res->l = 0;
270219b2ee8SDavid du Colombier }
271219b2ee8SDavid du Colombier 
272219b2ee8SDavid du Colombier void
273219b2ee8SDavid du Colombier oconst(Node *n, Node *res)
274219b2ee8SDavid du Colombier {
275219b2ee8SDavid du Colombier 	res->op = OCONST;
276219b2ee8SDavid du Colombier 	res->type = n->type;
277219b2ee8SDavid du Colombier 	res->Store = n->Store;
278219b2ee8SDavid du Colombier 	res->comt = n->comt;
279219b2ee8SDavid du Colombier }
280219b2ee8SDavid du Colombier 
281219b2ee8SDavid du Colombier void
282219b2ee8SDavid du Colombier oname(Node *n, Node *res)
283219b2ee8SDavid du Colombier {
284219b2ee8SDavid du Colombier 	Value *v;
285219b2ee8SDavid du Colombier 
286bd389b36SDavid du Colombier 	v = n->sym->v;
287bd389b36SDavid du Colombier 	if(v->set == 0)
288bd389b36SDavid du Colombier 		error("%s used but not set", n->sym->name);
289bd389b36SDavid du Colombier 	res->op = OCONST;
290bd389b36SDavid du Colombier 	res->type = v->type;
291bd389b36SDavid du Colombier 	res->Store = v->Store;
292219b2ee8SDavid du Colombier 	res->comt = v->comt;
293219b2ee8SDavid du Colombier }
294219b2ee8SDavid du Colombier 
295219b2ee8SDavid du Colombier void
296219b2ee8SDavid du Colombier octruct(Node *n, Node *res)
297219b2ee8SDavid du Colombier {
298bd389b36SDavid du Colombier 	res->op = OCONST;
299bd389b36SDavid du Colombier 	res->type = TLIST;
300219b2ee8SDavid du Colombier 	res->l = construct(n->left);
301219b2ee8SDavid du Colombier }
302219b2ee8SDavid du Colombier 
303219b2ee8SDavid du Colombier void
304219b2ee8SDavid du Colombier oasgn(Node *n, Node *res)
305219b2ee8SDavid du Colombier {
306219b2ee8SDavid du Colombier 	Node *lp, r;
307219b2ee8SDavid du Colombier 	Value *v;
308219b2ee8SDavid du Colombier 
309219b2ee8SDavid du Colombier 	lp = n->left;
310bd389b36SDavid du Colombier 	switch(lp->op) {
311bd389b36SDavid du Colombier 	case OINDM:
312219b2ee8SDavid du Colombier 		windir(cormap, lp->left, n->right, res);
313bd389b36SDavid du Colombier 		break;
314bd389b36SDavid du Colombier 	case OINDC:
315219b2ee8SDavid du Colombier 		windir(symmap, lp->left, n->right, res);
316bd389b36SDavid du Colombier 		break;
317bd389b36SDavid du Colombier 	default:
318bd389b36SDavid du Colombier 		chklval(lp);
319bd389b36SDavid du Colombier 		v = lp->sym->v;
320219b2ee8SDavid du Colombier 		expr(n->right, &r);
321bd389b36SDavid du Colombier 		v->set = 1;
322bd389b36SDavid du Colombier 		v->type = r.type;
323bd389b36SDavid du Colombier 		v->Store = r.Store;
324219b2ee8SDavid du Colombier 		res->op = OCONST;
325219b2ee8SDavid du Colombier 		res->type = v->type;
326219b2ee8SDavid du Colombier 		res->Store = v->Store;
327219b2ee8SDavid du Colombier 		res->comt = v->comt;
328bd389b36SDavid du Colombier 	}
329219b2ee8SDavid du Colombier }
330219b2ee8SDavid du Colombier 
331219b2ee8SDavid du Colombier void
332219b2ee8SDavid du Colombier oadd(Node *n, Node *res)
333219b2ee8SDavid du Colombier {
334219b2ee8SDavid du Colombier 	Node l, r;
335219b2ee8SDavid du Colombier 
336219b2ee8SDavid du Colombier 	expr(n->left, &l);
337219b2ee8SDavid du Colombier 	expr(n->right, &r);
338bd389b36SDavid du Colombier 	res->fmt = l.fmt;
339bd389b36SDavid du Colombier 	res->op = OCONST;
340bd389b36SDavid du Colombier 	res->type = TFLOAT;
341bd389b36SDavid du Colombier 	switch(l.type) {
342219b2ee8SDavid du Colombier 	default:
343219b2ee8SDavid du Colombier 		error("bad lhs type +");
344bd389b36SDavid du Colombier 	case TINT:
345bd389b36SDavid du Colombier 		switch(r.type) {
346bd389b36SDavid du Colombier 		case TINT:
347bd389b36SDavid du Colombier 			res->type = TINT;
348bd389b36SDavid du Colombier 			res->ival = l.ival+r.ival;
349bd389b36SDavid du Colombier 			break;
350bd389b36SDavid du Colombier 		case TFLOAT:
351bd389b36SDavid du Colombier 			res->fval = l.ival+r.fval;
352bd389b36SDavid du Colombier 			break;
353219b2ee8SDavid du Colombier 		default:
354219b2ee8SDavid du Colombier 			error("bad rhs type +");
355bd389b36SDavid du Colombier 		}
356bd389b36SDavid du Colombier 		break;
357bd389b36SDavid du Colombier 	case TFLOAT:
358bd389b36SDavid du Colombier 		switch(r.type) {
359bd389b36SDavid du Colombier 		case TINT:
360bd389b36SDavid du Colombier 			res->fval = l.fval+r.ival;
361bd389b36SDavid du Colombier 			break;
362bd389b36SDavid du Colombier 		case TFLOAT:
363bd389b36SDavid du Colombier 			res->fval = l.fval+r.fval;
364bd389b36SDavid du Colombier 			break;
365219b2ee8SDavid du Colombier 		default:
366219b2ee8SDavid du Colombier 			error("bad rhs type +");
367bd389b36SDavid du Colombier 		}
368bd389b36SDavid du Colombier 		break;
369bd389b36SDavid du Colombier 	case TSTRING:
370bd389b36SDavid du Colombier 		if(r.type == TSTRING) {
371bd389b36SDavid du Colombier 			res->type = TSTRING;
372bd389b36SDavid du Colombier 			res->fmt = 's';
373bd389b36SDavid du Colombier 			res->string = stradd(l.string, r.string);
374bd389b36SDavid du Colombier 			break;
375bd389b36SDavid du Colombier 		}
376ab3dc52fSDavid du Colombier 		if(r.type == TINT) {
377ab3dc52fSDavid du Colombier 			res->type = TSTRING;
378ab3dc52fSDavid du Colombier 			res->fmt = 's';
379ab3dc52fSDavid du Colombier 			res->string = straddrune(l.string, r.ival);
380ab3dc52fSDavid du Colombier 			break;
381ab3dc52fSDavid du Colombier 		}
382bd389b36SDavid du Colombier 		error("bad rhs for +");
383bd389b36SDavid du Colombier 	case TLIST:
384bd389b36SDavid du Colombier 		res->type = TLIST;
385bd389b36SDavid du Colombier 		switch(r.type) {
386bd389b36SDavid du Colombier 		case TLIST:
387bd389b36SDavid du Colombier 			res->l = addlist(l.l, r.l);
388bd389b36SDavid du Colombier 			break;
389bd389b36SDavid du Colombier 		default:
390bd389b36SDavid du Colombier 			r.left = 0;
391bd389b36SDavid du Colombier 			r.right = 0;
392bd389b36SDavid du Colombier 			res->l = addlist(l.l, construct(&r));
393bd389b36SDavid du Colombier 			break;
394bd389b36SDavid du Colombier 		}
395bd389b36SDavid du Colombier 	}
396219b2ee8SDavid du Colombier }
397219b2ee8SDavid du Colombier 
398219b2ee8SDavid du Colombier void
399219b2ee8SDavid du Colombier osub(Node *n, Node *res)
400219b2ee8SDavid du Colombier {
401219b2ee8SDavid du Colombier 	Node l, r;
402219b2ee8SDavid du Colombier 
403219b2ee8SDavid du Colombier 	expr(n->left, &l);
404219b2ee8SDavid du Colombier 	expr(n->right, &r);
405bd389b36SDavid du Colombier 	res->fmt = l.fmt;
406bd389b36SDavid du Colombier 	res->op = OCONST;
407bd389b36SDavid du Colombier 	res->type = TFLOAT;
408bd389b36SDavid du Colombier 	switch(l.type) {
409219b2ee8SDavid du Colombier 	default:
410219b2ee8SDavid du Colombier 		error("bad lhs type -");
411bd389b36SDavid du Colombier 	case TINT:
412bd389b36SDavid du Colombier 		switch(r.type) {
413bd389b36SDavid du Colombier 		case TINT:
414bd389b36SDavid du Colombier 			res->type = TINT;
415bd389b36SDavid du Colombier 			res->ival = l.ival-r.ival;
416bd389b36SDavid du Colombier 			break;
417bd389b36SDavid du Colombier 		case TFLOAT:
418bd389b36SDavid du Colombier 			res->fval = l.ival-r.fval;
419bd389b36SDavid du Colombier 			break;
420219b2ee8SDavid du Colombier 		default:
421219b2ee8SDavid du Colombier 			error("bad rhs type -");
422bd389b36SDavid du Colombier 		}
423bd389b36SDavid du Colombier 		break;
424bd389b36SDavid du Colombier 	case TFLOAT:
425219b2ee8SDavid du Colombier 		switch(r.type) {
426bd389b36SDavid du Colombier 		case TINT:
427bd389b36SDavid du Colombier 			res->fval = l.fval-r.ival;
428bd389b36SDavid du Colombier 			break;
429bd389b36SDavid du Colombier 		case TFLOAT:
430bd389b36SDavid du Colombier 			res->fval = l.fval-r.fval;
431bd389b36SDavid du Colombier 			break;
432219b2ee8SDavid du Colombier 		default:
433219b2ee8SDavid du Colombier 			error("bad rhs type -");
434bd389b36SDavid du Colombier 		}
435bd389b36SDavid du Colombier 		break;
436bd389b36SDavid du Colombier 	}
437219b2ee8SDavid du Colombier }
438219b2ee8SDavid du Colombier 
439219b2ee8SDavid du Colombier void
440219b2ee8SDavid du Colombier omul(Node *n, Node *res)
441219b2ee8SDavid du Colombier {
442219b2ee8SDavid du Colombier 	Node l, r;
443219b2ee8SDavid du Colombier 
444219b2ee8SDavid du Colombier 	expr(n->left, &l);
445219b2ee8SDavid du Colombier 	expr(n->right, &r);
446bd389b36SDavid du Colombier 	res->fmt = l.fmt;
447bd389b36SDavid du Colombier 	res->op = OCONST;
448bd389b36SDavid du Colombier 	res->type = TFLOAT;
449bd389b36SDavid du Colombier 	switch(l.type) {
450219b2ee8SDavid du Colombier 	default:
451219b2ee8SDavid du Colombier 		error("bad lhs type *");
452bd389b36SDavid du Colombier 	case TINT:
453bd389b36SDavid du Colombier 		switch(r.type) {
454bd389b36SDavid du Colombier 		case TINT:
455bd389b36SDavid du Colombier 			res->type = TINT;
456bd389b36SDavid du Colombier 			res->ival = l.ival*r.ival;
457bd389b36SDavid du Colombier 			break;
458bd389b36SDavid du Colombier 		case TFLOAT:
459bd389b36SDavid du Colombier 			res->fval = l.ival*r.fval;
460bd389b36SDavid du Colombier 			break;
461219b2ee8SDavid du Colombier 		default:
462219b2ee8SDavid du Colombier 			error("bad rhs type *");
463bd389b36SDavid du Colombier 		}
464bd389b36SDavid du Colombier 		break;
465bd389b36SDavid du Colombier 	case TFLOAT:
466219b2ee8SDavid du Colombier 		switch(r.type) {
467bd389b36SDavid du Colombier 		case TINT:
468bd389b36SDavid du Colombier 			res->fval = l.fval*r.ival;
469bd389b36SDavid du Colombier 			break;
470bd389b36SDavid du Colombier 		case TFLOAT:
471bd389b36SDavid du Colombier 			res->fval = l.fval*r.fval;
472bd389b36SDavid du Colombier 			break;
473219b2ee8SDavid du Colombier 		default:
474219b2ee8SDavid du Colombier 			error("bad rhs type *");
475bd389b36SDavid du Colombier 		}
476bd389b36SDavid du Colombier 		break;
477bd389b36SDavid du Colombier 	}
478219b2ee8SDavid du Colombier }
479219b2ee8SDavid du Colombier 
480219b2ee8SDavid du Colombier void
481219b2ee8SDavid du Colombier odiv(Node *n, Node *res)
482219b2ee8SDavid du Colombier {
483219b2ee8SDavid du Colombier 	Node l, r;
484219b2ee8SDavid du Colombier 
485219b2ee8SDavid du Colombier 	expr(n->left, &l);
486219b2ee8SDavid du Colombier 	expr(n->right, &r);
487bd389b36SDavid du Colombier 	res->fmt = l.fmt;
488bd389b36SDavid du Colombier 	res->op = OCONST;
489bd389b36SDavid du Colombier 	res->type = TFLOAT;
490bd389b36SDavid du Colombier 	switch(l.type) {
491219b2ee8SDavid du Colombier 	default:
492219b2ee8SDavid du Colombier 		error("bad lhs type /");
493bd389b36SDavid du Colombier 	case TINT:
494bd389b36SDavid du Colombier 		switch(r.type) {
495bd389b36SDavid du Colombier 		case TINT:
496bd389b36SDavid du Colombier 			res->type = TINT;
497219b2ee8SDavid du Colombier 			if(r.ival == 0)
498219b2ee8SDavid du Colombier 				error("zero divide");
499bd389b36SDavid du Colombier 			res->ival = l.ival/r.ival;
500bd389b36SDavid du Colombier 			break;
501bd389b36SDavid du Colombier 		case TFLOAT:
502219b2ee8SDavid du Colombier 			if(r.fval == 0)
503219b2ee8SDavid du Colombier 				error("zero divide");
504bd389b36SDavid du Colombier 			res->fval = l.ival/r.fval;
505bd389b36SDavid du Colombier 			break;
506219b2ee8SDavid du Colombier 		default:
507219b2ee8SDavid du Colombier 			error("bad rhs type /");
508bd389b36SDavid du Colombier 		}
509bd389b36SDavid du Colombier 		break;
510bd389b36SDavid du Colombier 	case TFLOAT:
511219b2ee8SDavid du Colombier 		switch(r.type) {
512bd389b36SDavid du Colombier 		case TINT:
513bd389b36SDavid du Colombier 			res->fval = l.fval/r.ival;
514bd389b36SDavid du Colombier 			break;
515bd389b36SDavid du Colombier 		case TFLOAT:
516bd389b36SDavid du Colombier 			res->fval = l.fval/r.fval;
517bd389b36SDavid du Colombier 			break;
518219b2ee8SDavid du Colombier 		default:
519219b2ee8SDavid du Colombier 			error("bad rhs type /");
520bd389b36SDavid du Colombier 		}
521bd389b36SDavid du Colombier 		break;
522bd389b36SDavid du Colombier 	}
523219b2ee8SDavid du Colombier }
524219b2ee8SDavid du Colombier 
525219b2ee8SDavid du Colombier void
526219b2ee8SDavid du Colombier omod(Node *n, Node *res)
527219b2ee8SDavid du Colombier {
528219b2ee8SDavid du Colombier 	Node l, r;
529219b2ee8SDavid du Colombier 
530219b2ee8SDavid du Colombier 	expr(n->left, &l);
531219b2ee8SDavid du Colombier 	expr(n->right, &r);
532bd389b36SDavid du Colombier 	res->fmt = l.fmt;
533bd389b36SDavid du Colombier 	res->op = OCONST;
534bd389b36SDavid du Colombier 	res->type = TINT;
535bd389b36SDavid du Colombier 	if(l.type != TINT || r.type != TINT)
536bd389b36SDavid du Colombier 		error("bad expr type %");
537bd389b36SDavid du Colombier 	res->ival = l.ival%r.ival;
538219b2ee8SDavid du Colombier }
539219b2ee8SDavid du Colombier 
540219b2ee8SDavid du Colombier void
541219b2ee8SDavid du Colombier olsh(Node *n, Node *res)
542219b2ee8SDavid du Colombier {
543219b2ee8SDavid du Colombier 	Node l, r;
544219b2ee8SDavid du Colombier 
545219b2ee8SDavid du Colombier 	expr(n->left, &l);
546219b2ee8SDavid du Colombier 	expr(n->right, &r);
547bd389b36SDavid du Colombier 	res->fmt = l.fmt;
548bd389b36SDavid du Colombier 	res->op = OCONST;
549bd389b36SDavid du Colombier 	res->type = TINT;
550bd389b36SDavid du Colombier 	if(l.type != TINT || r.type != TINT)
551bd389b36SDavid du Colombier 		error("bad expr type <<");
552bd389b36SDavid du Colombier 	res->ival = l.ival<<r.ival;
553219b2ee8SDavid du Colombier }
554219b2ee8SDavid du Colombier 
555219b2ee8SDavid du Colombier void
556219b2ee8SDavid du Colombier orsh(Node *n, Node *res)
557219b2ee8SDavid du Colombier {
558219b2ee8SDavid du Colombier 	Node l, r;
559219b2ee8SDavid du Colombier 
560219b2ee8SDavid du Colombier 	expr(n->left, &l);
561219b2ee8SDavid du Colombier 	expr(n->right, &r);
562bd389b36SDavid du Colombier 	res->fmt = l.fmt;
563bd389b36SDavid du Colombier 	res->op = OCONST;
564bd389b36SDavid du Colombier 	res->type = TINT;
565bd389b36SDavid du Colombier 	if(l.type != TINT || r.type != TINT)
566bd389b36SDavid du Colombier 		error("bad expr type >>");
5674de34a7eSDavid du Colombier 	res->ival = (uvlong)l.ival>>r.ival;
568219b2ee8SDavid du Colombier }
569219b2ee8SDavid du Colombier 
570219b2ee8SDavid du Colombier void
571219b2ee8SDavid du Colombier olt(Node *n, Node *res)
572219b2ee8SDavid du Colombier {
573219b2ee8SDavid du Colombier 	Node l, r;
574219b2ee8SDavid du Colombier 
575219b2ee8SDavid du Colombier 	expr(n->left, &l);
576219b2ee8SDavid du Colombier 	expr(n->right, &r);
577219b2ee8SDavid du Colombier 
578bd389b36SDavid du Colombier 	res->fmt = l.fmt;
579bd389b36SDavid du Colombier 	res->op = OCONST;
580bd389b36SDavid du Colombier 	res->type = TINT;
581bd389b36SDavid du Colombier 	switch(l.type) {
582219b2ee8SDavid du Colombier 	default:
583219b2ee8SDavid du Colombier 		error("bad lhs type <");
584bd389b36SDavid du Colombier 	case TINT:
585bd389b36SDavid du Colombier 		switch(r.type) {
586bd389b36SDavid du Colombier 		case TINT:
587bd389b36SDavid du Colombier 			res->ival = l.ival < r.ival;
588bd389b36SDavid du Colombier 			break;
589bd389b36SDavid du Colombier 		case TFLOAT:
590bd389b36SDavid du Colombier 			res->ival = l.ival < r.fval;
591bd389b36SDavid du Colombier 			break;
592219b2ee8SDavid du Colombier 		default:
593219b2ee8SDavid du Colombier 			error("bad rhs type <");
594bd389b36SDavid du Colombier 		}
595bd389b36SDavid du Colombier 		break;
596bd389b36SDavid du Colombier 	case TFLOAT:
597219b2ee8SDavid du Colombier 		switch(r.type) {
598bd389b36SDavid du Colombier 		case TINT:
599bd389b36SDavid du Colombier 			res->ival = l.fval < r.ival;
600bd389b36SDavid du Colombier 			break;
601bd389b36SDavid du Colombier 		case TFLOAT:
602bd389b36SDavid du Colombier 			res->ival = l.fval < r.fval;
603bd389b36SDavid du Colombier 			break;
604219b2ee8SDavid du Colombier 		default:
605219b2ee8SDavid du Colombier 			error("bad rhs type <");
606bd389b36SDavid du Colombier 		}
607bd389b36SDavid du Colombier 		break;
608bd389b36SDavid du Colombier 	}
609219b2ee8SDavid du Colombier }
610219b2ee8SDavid du Colombier 
611219b2ee8SDavid du Colombier void
612219b2ee8SDavid du Colombier ogt(Node *n, Node *res)
613219b2ee8SDavid du Colombier {
614219b2ee8SDavid du Colombier 	Node l, r;
615219b2ee8SDavid du Colombier 
616219b2ee8SDavid du Colombier 	expr(n->left, &l);
617219b2ee8SDavid du Colombier 	expr(n->right, &r);
618bd389b36SDavid du Colombier 	res->fmt = 'D';
619bd389b36SDavid du Colombier 	res->op = OCONST;
620bd389b36SDavid du Colombier 	res->type = TINT;
621bd389b36SDavid du Colombier 	switch(l.type) {
622219b2ee8SDavid du Colombier 	default:
623219b2ee8SDavid du Colombier 		error("bad lhs type >");
624bd389b36SDavid du Colombier 	case TINT:
625bd389b36SDavid du Colombier 		switch(r.type) {
626bd389b36SDavid du Colombier 		case TINT:
627bd389b36SDavid du Colombier 			res->ival = l.ival > r.ival;
628bd389b36SDavid du Colombier 			break;
629bd389b36SDavid du Colombier 		case TFLOAT:
630bd389b36SDavid du Colombier 			res->ival = l.ival > r.fval;
631bd389b36SDavid du Colombier 			break;
632219b2ee8SDavid du Colombier 		default:
633219b2ee8SDavid du Colombier 			error("bad rhs type >");
634bd389b36SDavid du Colombier 		}
635bd389b36SDavid du Colombier 		break;
636bd389b36SDavid du Colombier 	case TFLOAT:
637219b2ee8SDavid du Colombier 		switch(r.type) {
638bd389b36SDavid du Colombier 		case TINT:
639bd389b36SDavid du Colombier 			res->ival = l.fval > r.ival;
640bd389b36SDavid du Colombier 			break;
641bd389b36SDavid du Colombier 		case TFLOAT:
642bd389b36SDavid du Colombier 			res->ival = l.fval > r.fval;
643bd389b36SDavid du Colombier 			break;
644219b2ee8SDavid du Colombier 		default:
645219b2ee8SDavid du Colombier 			error("bad rhs type >");
646bd389b36SDavid du Colombier 		}
647bd389b36SDavid du Colombier 		break;
648bd389b36SDavid du Colombier 	}
649219b2ee8SDavid du Colombier }
650219b2ee8SDavid du Colombier 
651219b2ee8SDavid du Colombier void
652219b2ee8SDavid du Colombier oleq(Node *n, Node *res)
653219b2ee8SDavid du Colombier {
654219b2ee8SDavid du Colombier 	Node l, r;
655219b2ee8SDavid du Colombier 
656219b2ee8SDavid du Colombier 	expr(n->left, &l);
657219b2ee8SDavid du Colombier 	expr(n->right, &r);
658bd389b36SDavid du Colombier 	res->fmt = 'D';
659bd389b36SDavid du Colombier 	res->op = OCONST;
660bd389b36SDavid du Colombier 	res->type = TINT;
661bd389b36SDavid du Colombier 	switch(l.type) {
662219b2ee8SDavid du Colombier 	default:
663219b2ee8SDavid du Colombier 		error("bad expr type <=");
664bd389b36SDavid du Colombier 	case TINT:
665bd389b36SDavid du Colombier 		switch(r.type) {
666bd389b36SDavid du Colombier 		case TINT:
667bd389b36SDavid du Colombier 			res->ival = l.ival <= r.ival;
668bd389b36SDavid du Colombier 			break;
669bd389b36SDavid du Colombier 		case TFLOAT:
670bd389b36SDavid du Colombier 			res->ival = l.ival <= r.fval;
671bd389b36SDavid du Colombier 			break;
672219b2ee8SDavid du Colombier 		default:
673bd389b36SDavid du Colombier 			error("bad expr type <=");
674bd389b36SDavid du Colombier 		}
675bd389b36SDavid du Colombier 		break;
676bd389b36SDavid du Colombier 	case TFLOAT:
677219b2ee8SDavid du Colombier 		switch(r.type) {
678bd389b36SDavid du Colombier 		case TINT:
679bd389b36SDavid du Colombier 			res->ival = l.fval <= r.ival;
680bd389b36SDavid du Colombier 			break;
681bd389b36SDavid du Colombier 		case TFLOAT:
682bd389b36SDavid du Colombier 			res->ival = l.fval <= r.fval;
683bd389b36SDavid du Colombier 			break;
684219b2ee8SDavid du Colombier 		default:
685bd389b36SDavid du Colombier 			error("bad expr type <=");
686bd389b36SDavid du Colombier 		}
687bd389b36SDavid du Colombier 		break;
688bd389b36SDavid du Colombier 	}
689219b2ee8SDavid du Colombier }
690219b2ee8SDavid du Colombier 
691219b2ee8SDavid du Colombier void
692219b2ee8SDavid du Colombier ogeq(Node *n, Node *res)
693219b2ee8SDavid du Colombier {
694219b2ee8SDavid du Colombier 	Node l, r;
695219b2ee8SDavid du Colombier 
696219b2ee8SDavid du Colombier 	expr(n->left, &l);
697219b2ee8SDavid du Colombier 	expr(n->right, &r);
698bd389b36SDavid du Colombier 	res->fmt = 'D';
699bd389b36SDavid du Colombier 	res->op = OCONST;
700bd389b36SDavid du Colombier 	res->type = TINT;
701bd389b36SDavid du Colombier 	switch(l.type) {
702219b2ee8SDavid du Colombier 	default:
703219b2ee8SDavid du Colombier 		error("bad lhs type >=");
704bd389b36SDavid du Colombier 	case TINT:
705bd389b36SDavid du Colombier 		switch(r.type) {
706bd389b36SDavid du Colombier 		case TINT:
707bd389b36SDavid du Colombier 			res->ival = l.ival >= r.ival;
708bd389b36SDavid du Colombier 			break;
709bd389b36SDavid du Colombier 		case TFLOAT:
710bd389b36SDavid du Colombier 			res->ival = l.ival >= r.fval;
711bd389b36SDavid du Colombier 			break;
712219b2ee8SDavid du Colombier 		default:
713219b2ee8SDavid du Colombier 			error("bad rhs type >=");
714bd389b36SDavid du Colombier 		}
715bd389b36SDavid du Colombier 		break;
716bd389b36SDavid du Colombier 	case TFLOAT:
717219b2ee8SDavid du Colombier 		switch(r.type) {
718bd389b36SDavid du Colombier 		case TINT:
719bd389b36SDavid du Colombier 			res->ival = l.fval >= r.ival;
720bd389b36SDavid du Colombier 			break;
721bd389b36SDavid du Colombier 		case TFLOAT:
722bd389b36SDavid du Colombier 			res->ival = l.fval >= r.fval;
723bd389b36SDavid du Colombier 			break;
724219b2ee8SDavid du Colombier 		default:
725219b2ee8SDavid du Colombier 			error("bad rhs type >=");
726bd389b36SDavid du Colombier 		}
727bd389b36SDavid du Colombier 		break;
728bd389b36SDavid du Colombier 	}
729219b2ee8SDavid du Colombier }
730219b2ee8SDavid du Colombier 
731219b2ee8SDavid du Colombier void
732219b2ee8SDavid du Colombier oeq(Node *n, Node *res)
733219b2ee8SDavid du Colombier {
734219b2ee8SDavid du Colombier 	Node l, r;
735219b2ee8SDavid du Colombier 
736219b2ee8SDavid du Colombier 	expr(n->left, &l);
737219b2ee8SDavid du Colombier 	expr(n->right, &r);
738bd389b36SDavid du Colombier 	res->fmt = 'D';
739bd389b36SDavid du Colombier 	res->op = OCONST;
740bd389b36SDavid du Colombier 	res->type = TINT;
741219b2ee8SDavid du Colombier 	res->ival = 0;
742bd389b36SDavid du Colombier 	switch(l.type) {
743219b2ee8SDavid du Colombier 	default:
744219b2ee8SDavid du Colombier 		break;
745bd389b36SDavid du Colombier 	case TINT:
746bd389b36SDavid du Colombier 		switch(r.type) {
747bd389b36SDavid du Colombier 		case TINT:
748bd389b36SDavid du Colombier 			res->ival = l.ival == r.ival;
749bd389b36SDavid du Colombier 			break;
750bd389b36SDavid du Colombier 		case TFLOAT:
751bd389b36SDavid du Colombier 			res->ival = l.ival == r.fval;
752bd389b36SDavid du Colombier 			break;
753219b2ee8SDavid du Colombier 		default:
754219b2ee8SDavid du Colombier 			break;
755bd389b36SDavid du Colombier 		}
756bd389b36SDavid du Colombier 		break;
757bd389b36SDavid du Colombier 	case TFLOAT:
758219b2ee8SDavid du Colombier 		switch(r.type) {
759bd389b36SDavid du Colombier 		case TINT:
760bd389b36SDavid du Colombier 			res->ival = l.fval == r.ival;
761bd389b36SDavid du Colombier 			break;
762bd389b36SDavid du Colombier 		case TFLOAT:
763bd389b36SDavid du Colombier 			res->ival = l.fval == r.fval;
764bd389b36SDavid du Colombier 			break;
765219b2ee8SDavid du Colombier 		default:
766219b2ee8SDavid du Colombier 			break;
767bd389b36SDavid du Colombier 		}
768bd389b36SDavid du Colombier 		break;
769bd389b36SDavid du Colombier 	case TSTRING:
770bd389b36SDavid du Colombier 		if(r.type == TSTRING) {
771bd389b36SDavid du Colombier 			res->ival = scmp(r.string, l.string);
772bd389b36SDavid du Colombier 			break;
773bd389b36SDavid du Colombier 		}
774219b2ee8SDavid du Colombier 		break;
775bd389b36SDavid du Colombier 	case TLIST:
776bd389b36SDavid du Colombier 		if(r.type == TLIST) {
777bd389b36SDavid du Colombier 			res->ival = listcmp(l.l, r.l);
778bd389b36SDavid du Colombier 			break;
779bd389b36SDavid du Colombier 		}
780bd389b36SDavid du Colombier 		break;
781bd389b36SDavid du Colombier 	}
782219b2ee8SDavid du Colombier 	if(n->op == ONEQ)
783219b2ee8SDavid du Colombier 		res->ival = !res->ival;
784bd389b36SDavid du Colombier }
785219b2ee8SDavid du Colombier 
786219b2ee8SDavid du Colombier 
787219b2ee8SDavid du Colombier void
788219b2ee8SDavid du Colombier oland(Node *n, Node *res)
789219b2ee8SDavid du Colombier {
790219b2ee8SDavid du Colombier 	Node l, r;
791219b2ee8SDavid du Colombier 
792219b2ee8SDavid du Colombier 	expr(n->left, &l);
793219b2ee8SDavid du Colombier 	expr(n->right, &r);
794bd389b36SDavid du Colombier 	res->fmt = l.fmt;
795bd389b36SDavid du Colombier 	res->op = OCONST;
796bd389b36SDavid du Colombier 	res->type = TINT;
797bd389b36SDavid du Colombier 	if(l.type != TINT || r.type != TINT)
798bd389b36SDavid du Colombier 		error("bad expr type &");
799bd389b36SDavid du Colombier 	res->ival = l.ival&r.ival;
800219b2ee8SDavid du Colombier }
801219b2ee8SDavid du Colombier 
802219b2ee8SDavid du Colombier void
803219b2ee8SDavid du Colombier oxor(Node *n, Node *res)
804219b2ee8SDavid du Colombier {
805219b2ee8SDavid du Colombier 	Node l, r;
806219b2ee8SDavid du Colombier 
807219b2ee8SDavid du Colombier 	expr(n->left, &l);
808219b2ee8SDavid du Colombier 	expr(n->right, &r);
809bd389b36SDavid du Colombier 	res->fmt = l.fmt;
810bd389b36SDavid du Colombier 	res->op = OCONST;
811bd389b36SDavid du Colombier 	res->type = TINT;
812bd389b36SDavid du Colombier 	if(l.type != TINT || r.type != TINT)
813bd389b36SDavid du Colombier 		error("bad expr type ^");
814bd389b36SDavid du Colombier 	res->ival = l.ival^r.ival;
815219b2ee8SDavid du Colombier }
816219b2ee8SDavid du Colombier 
817219b2ee8SDavid du Colombier void
818219b2ee8SDavid du Colombier olor(Node *n, Node *res)
819219b2ee8SDavid du Colombier {
820219b2ee8SDavid du Colombier 	Node l, r;
821219b2ee8SDavid du Colombier 
822219b2ee8SDavid du Colombier 	expr(n->left, &l);
823219b2ee8SDavid du Colombier 	expr(n->right, &r);
824bd389b36SDavid du Colombier 	res->fmt = l.fmt;
825bd389b36SDavid du Colombier 	res->op = OCONST;
826bd389b36SDavid du Colombier 	res->type = TINT;
827bd389b36SDavid du Colombier 	if(l.type != TINT || r.type != TINT)
828bd389b36SDavid du Colombier 		error("bad expr type |");
829bd389b36SDavid du Colombier 	res->ival = l.ival|r.ival;
830219b2ee8SDavid du Colombier }
831219b2ee8SDavid du Colombier 
832219b2ee8SDavid du Colombier void
833219b2ee8SDavid du Colombier ocand(Node *n, Node *res)
834219b2ee8SDavid du Colombier {
835219b2ee8SDavid du Colombier 	Node l, r;
836219b2ee8SDavid du Colombier 
837bd389b36SDavid du Colombier 	res->fmt = l.fmt;
838bd389b36SDavid du Colombier 	res->op = OCONST;
839bd389b36SDavid du Colombier 	res->type = TINT;
840219b2ee8SDavid du Colombier 	res->ival = 0;
841219b2ee8SDavid du Colombier 	expr(n->left, &l);
842219b2ee8SDavid du Colombier 	if(bool(&l) == 0)
843219b2ee8SDavid du Colombier 		return;
844219b2ee8SDavid du Colombier 	expr(n->right, &r);
845219b2ee8SDavid du Colombier 	if(bool(&r) == 0)
846219b2ee8SDavid du Colombier 		return;
847219b2ee8SDavid du Colombier 	res->ival = 1;
848219b2ee8SDavid du Colombier }
849219b2ee8SDavid du Colombier 
850219b2ee8SDavid du Colombier void
851219b2ee8SDavid du Colombier onot(Node *n, Node *res)
852219b2ee8SDavid du Colombier {
853219b2ee8SDavid du Colombier 	Node l;
854219b2ee8SDavid du Colombier 
855bd389b36SDavid du Colombier 	res->op = OCONST;
856bd389b36SDavid du Colombier 	res->type = TINT;
857219b2ee8SDavid du Colombier 	res->ival = 0;
858219b2ee8SDavid du Colombier 	expr(n->left, &l);
859219b2ee8SDavid du Colombier 	if(bool(&l) == 0)
860219b2ee8SDavid du Colombier 		res->ival = 1;
861219b2ee8SDavid du Colombier }
862219b2ee8SDavid du Colombier 
863219b2ee8SDavid du Colombier void
864219b2ee8SDavid du Colombier ocor(Node *n, Node *res)
865219b2ee8SDavid du Colombier {
866219b2ee8SDavid du Colombier 	Node l, r;
867219b2ee8SDavid du Colombier 
868219b2ee8SDavid du Colombier 	res->op = OCONST;
869219b2ee8SDavid du Colombier 	res->type = TINT;
870219b2ee8SDavid du Colombier 	res->ival = 0;
871219b2ee8SDavid du Colombier 	expr(n->left, &l);
872219b2ee8SDavid du Colombier 	if(bool(&l)) {
873219b2ee8SDavid du Colombier 		res->ival = 1;
874219b2ee8SDavid du Colombier 		return;
875219b2ee8SDavid du Colombier 	}
876219b2ee8SDavid du Colombier 	expr(n->right, &r);
877219b2ee8SDavid du Colombier 	if(bool(&r)) {
878219b2ee8SDavid du Colombier 		res->ival = 1;
879219b2ee8SDavid du Colombier 		return;
880219b2ee8SDavid du Colombier 	}
881219b2ee8SDavid du Colombier }
882219b2ee8SDavid du Colombier 
883219b2ee8SDavid du Colombier void
884219b2ee8SDavid du Colombier oeinc(Node *n, Node *res)
885219b2ee8SDavid du Colombier {
886219b2ee8SDavid du Colombier 	Value *v;
887219b2ee8SDavid du Colombier 
888219b2ee8SDavid du Colombier 	chklval(n->left);
889219b2ee8SDavid du Colombier 	v = n->left->sym->v;
890bd389b36SDavid du Colombier 	res->op = OCONST;
891bd389b36SDavid du Colombier 	res->type = v->type;
892bd389b36SDavid du Colombier 	switch(v->type) {
893bd389b36SDavid du Colombier 	case TINT:
894bd389b36SDavid du Colombier 		if(n->op == OEDEC)
895bd389b36SDavid du Colombier 			v->ival -= fmtsize(v);
896bd389b36SDavid du Colombier 		else
897bd389b36SDavid du Colombier 			v->ival += fmtsize(v);
898bd389b36SDavid du Colombier 		break;
899bd389b36SDavid du Colombier 	case TFLOAT:
900bd389b36SDavid du Colombier 		if(n->op == OEDEC)
901bd389b36SDavid du Colombier 			v->fval--;
902bd389b36SDavid du Colombier 		else
903bd389b36SDavid du Colombier 			v->fval++;
904bd389b36SDavid du Colombier 		break;
905bd389b36SDavid du Colombier 	default:
906bd389b36SDavid du Colombier 		error("bad type for pre --/++");
907bd389b36SDavid du Colombier 	}
908bd389b36SDavid du Colombier 	res->Store = v->Store;
909219b2ee8SDavid du Colombier }
910219b2ee8SDavid du Colombier 
911219b2ee8SDavid du Colombier void
912219b2ee8SDavid du Colombier opinc(Node *n, Node *res)
913219b2ee8SDavid du Colombier {
914219b2ee8SDavid du Colombier 	Value *v;
915219b2ee8SDavid du Colombier 
916219b2ee8SDavid du Colombier 	chklval(n->left);
917219b2ee8SDavid du Colombier 	v = n->left->sym->v;
918bd389b36SDavid du Colombier 	res->op = OCONST;
919bd389b36SDavid du Colombier 	res->type = v->type;
920bd389b36SDavid du Colombier 	res->Store = v->Store;
921bd389b36SDavid du Colombier 	switch(v->type) {
922bd389b36SDavid du Colombier 	case TINT:
923bd389b36SDavid du Colombier 		if(n->op == OPDEC)
924bd389b36SDavid du Colombier 			v->ival -= fmtsize(v);
925bd389b36SDavid du Colombier 		else
926bd389b36SDavid du Colombier 			v->ival += fmtsize(v);
927bd389b36SDavid du Colombier 		break;
928bd389b36SDavid du Colombier 	case TFLOAT:
929bd389b36SDavid du Colombier 		if(n->op == OPDEC)
930bd389b36SDavid du Colombier 			v->fval--;
931bd389b36SDavid du Colombier 		else
932bd389b36SDavid du Colombier 			v->fval++;
933bd389b36SDavid du Colombier 		break;
934bd389b36SDavid du Colombier 	default:
935bd389b36SDavid du Colombier 		error("bad type for post --/++");
936bd389b36SDavid du Colombier 	}
937219b2ee8SDavid du Colombier }
938219b2ee8SDavid du Colombier 
939219b2ee8SDavid du Colombier void
940219b2ee8SDavid du Colombier ocall(Node *n, Node *res)
941219b2ee8SDavid du Colombier {
942219b2ee8SDavid du Colombier 	Lsym *s;
943219b2ee8SDavid du Colombier 	Rplace *rsav;
944219b2ee8SDavid du Colombier 
945bd389b36SDavid du Colombier 	res->op = OCONST;		/* Default return value */
946bd389b36SDavid du Colombier 	res->type = TLIST;
947bd389b36SDavid du Colombier 	res->l = 0;
948bd389b36SDavid du Colombier 
949219b2ee8SDavid du Colombier 	chklval(n->left);
950219b2ee8SDavid du Colombier 	s = n->left->sym;
951bd389b36SDavid du Colombier 
9520b459c2cSDavid du Colombier 	if(n->builtin && !s->builtin){
9530b459c2cSDavid du Colombier 		error("no builtin %s", s->name);
9540b459c2cSDavid du Colombier 		return;
9550b459c2cSDavid du Colombier 	}
9560b459c2cSDavid du Colombier 	if(s->builtin && (n->builtin || s->proc == 0)) {
957219b2ee8SDavid du Colombier 		(*s->builtin)(res, n->right);
958219b2ee8SDavid du Colombier 		return;
959bd389b36SDavid du Colombier 	}
960bd389b36SDavid du Colombier 	if(s->proc == 0)
961bd389b36SDavid du Colombier 		error("no function %s", s->name);
962bd389b36SDavid du Colombier 
963bd389b36SDavid du Colombier 	rsav = ret;
964219b2ee8SDavid du Colombier 	call(s->name, n->right, s->proc->left, s->proc->right, res);
965bd389b36SDavid du Colombier 	ret = rsav;
966bd389b36SDavid du Colombier }
967219b2ee8SDavid du Colombier 
968219b2ee8SDavid du Colombier void
969219b2ee8SDavid du Colombier ofmt(Node *n, Node *res)
970219b2ee8SDavid du Colombier {
971219b2ee8SDavid du Colombier 	expr(n->left, res);
972219b2ee8SDavid du Colombier 	res->fmt = n->right->ival;
973bd389b36SDavid du Colombier }
974219b2ee8SDavid du Colombier 
975219b2ee8SDavid du Colombier void
976219b2ee8SDavid du Colombier owhat(Node *n, Node *res)
977219b2ee8SDavid du Colombier {
978219b2ee8SDavid du Colombier 	res->op = OCONST;		/* Default return value */
979219b2ee8SDavid du Colombier 	res->type = TLIST;
980219b2ee8SDavid du Colombier 	res->l = 0;
981219b2ee8SDavid du Colombier 	whatis(n->sym);
982219b2ee8SDavid du Colombier }
983219b2ee8SDavid du Colombier 
984219b2ee8SDavid du Colombier void (*expop[])(Node*, Node*) =
985219b2ee8SDavid du Colombier {
986219b2ee8SDavid du Colombier 	[ONAME]		oname,
987219b2ee8SDavid du Colombier 	[OCONST]	oconst,
988219b2ee8SDavid du Colombier 	[OMUL]		omul,
989219b2ee8SDavid du Colombier 	[ODIV]		odiv,
990219b2ee8SDavid du Colombier 	[OMOD]		omod,
991219b2ee8SDavid du Colombier 	[OADD]		oadd,
992219b2ee8SDavid du Colombier 	[OSUB]		osub,
993219b2ee8SDavid du Colombier 	[ORSH]		orsh,
994219b2ee8SDavid du Colombier 	[OLSH]		olsh,
995219b2ee8SDavid du Colombier 	[OLT]		olt,
996219b2ee8SDavid du Colombier 	[OGT]		ogt,
997219b2ee8SDavid du Colombier 	[OLEQ]		oleq,
998219b2ee8SDavid du Colombier 	[OGEQ]		ogeq,
999219b2ee8SDavid du Colombier 	[OEQ]		oeq,
1000219b2ee8SDavid du Colombier 	[ONEQ]		oeq,
1001219b2ee8SDavid du Colombier 	[OLAND]		oland,
1002219b2ee8SDavid du Colombier 	[OXOR]		oxor,
1003219b2ee8SDavid du Colombier 	[OLOR]		olor,
1004219b2ee8SDavid du Colombier 	[OCAND]		ocand,
1005219b2ee8SDavid du Colombier 	[OCOR]		ocor,
1006219b2ee8SDavid du Colombier 	[OASGN]		oasgn,
1007219b2ee8SDavid du Colombier 	[OINDM]		oindm,
1008219b2ee8SDavid du Colombier 	[OEDEC]		oeinc,
1009219b2ee8SDavid du Colombier 	[OEINC]		oeinc,
1010219b2ee8SDavid du Colombier 	[OPINC]		opinc,
1011219b2ee8SDavid du Colombier 	[OPDEC]		opinc,
1012219b2ee8SDavid du Colombier 	[ONOT]		onot,
1013219b2ee8SDavid du Colombier 	[OIF]		0,
1014219b2ee8SDavid du Colombier 	[ODO]		0,
1015219b2ee8SDavid du Colombier 	[OLIST]		olist,
1016219b2ee8SDavid du Colombier 	[OCALL]		ocall,
1017219b2ee8SDavid du Colombier 	[OCTRUCT]	octruct,
1018219b2ee8SDavid du Colombier 	[OWHILE]	0,
1019219b2ee8SDavid du Colombier 	[OELSE]		0,
1020219b2ee8SDavid du Colombier 	[OHEAD]		ohead,
1021219b2ee8SDavid du Colombier 	[OTAIL]		otail,
1022219b2ee8SDavid du Colombier 	[OAPPEND]	oappend,
1023219b2ee8SDavid du Colombier 	[ORET]		0,
1024219b2ee8SDavid du Colombier 	[OINDEX]	oindex,
1025219b2ee8SDavid du Colombier 	[OINDC]		oindc,
1026219b2ee8SDavid du Colombier 	[ODOT]		odot,
1027219b2ee8SDavid du Colombier 	[OLOCAL]	0,
1028219b2ee8SDavid du Colombier 	[OFRAME]	oframe,
1029219b2ee8SDavid du Colombier 	[OCOMPLEX]	0,
1030219b2ee8SDavid du Colombier 	[ODELETE]	odelete,
1031219b2ee8SDavid du Colombier 	[OCAST]		ocast,
1032219b2ee8SDavid du Colombier 	[OFMT]		ofmt,
1033219b2ee8SDavid du Colombier 	[OEVAL]		oeval,
1034219b2ee8SDavid du Colombier 	[OWHAT]		owhat,
1035219b2ee8SDavid du Colombier };
1036