xref: /plan9-contrib/sys/src/cmd/acid/expr.c (revision ab3dc52f122c98aa4bc2bd64bd2292bb7b80fba2)
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,
23219b2ee8SDavid du Colombier 	['X'] 4,
247dd7cddfSDavid du Colombier 	['Y'] 8,
257dd7cddfSDavid du Colombier 	['W'] 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,
39bd389b36SDavid du Colombier };
40bd389b36SDavid du Colombier 
41bd389b36SDavid du Colombier int
42bd389b36SDavid du Colombier fmtsize(Value *v)
43bd389b36SDavid du Colombier {
44219b2ee8SDavid du Colombier 	int ret;
45219b2ee8SDavid du Colombier 
46bd389b36SDavid du Colombier 	switch(v->fmt) {
47bd389b36SDavid du Colombier 	default:
48bd389b36SDavid du Colombier 		return  fsize[v->fmt];
49bd389b36SDavid du Colombier 	case 'i':
50bd389b36SDavid du Colombier 	case 'I':
51219b2ee8SDavid du Colombier 		if(v->type != TINT || machdata == 0)
52bd389b36SDavid du Colombier 			error("no size for i fmt pointer ++/--");
53219b2ee8SDavid du Colombier 		ret = (*machdata->instsize)(cormap, v->ival);
54219b2ee8SDavid du Colombier 		if(ret < 0) {
55219b2ee8SDavid du Colombier 			ret = (*machdata->instsize)(symmap, v->ival);
56219b2ee8SDavid du Colombier 			if(ret < 0)
57219b2ee8SDavid du Colombier 				error("%r");
58219b2ee8SDavid du Colombier 		}
59219b2ee8SDavid du Colombier 		return ret;
60bd389b36SDavid du Colombier 	}
61bd389b36SDavid du Colombier }
62bd389b36SDavid du Colombier 
63bd389b36SDavid du Colombier void
64bd389b36SDavid du Colombier chklval(Node *lp)
65bd389b36SDavid du Colombier {
66bd389b36SDavid du Colombier 	if(lp->op != ONAME)
67bd389b36SDavid du Colombier 		error("need l-value");
68bd389b36SDavid du Colombier }
69bd389b36SDavid du Colombier 
70bd389b36SDavid du Colombier void
71219b2ee8SDavid du Colombier olist(Node *n, Node *res)
72219b2ee8SDavid du Colombier {
73219b2ee8SDavid du Colombier 	expr(n->left, res);
74219b2ee8SDavid du Colombier 	expr(n->right, res);
75219b2ee8SDavid du Colombier }
76219b2ee8SDavid du Colombier 
77219b2ee8SDavid du Colombier void
78219b2ee8SDavid du Colombier oeval(Node *n, Node *res)
79219b2ee8SDavid du Colombier {
80219b2ee8SDavid du Colombier 	expr(n->left, res);
81219b2ee8SDavid du Colombier 	if(res->type != TCODE)
82219b2ee8SDavid du Colombier 		error("bad type for eval");
83219b2ee8SDavid du Colombier 	expr(res->cc, res);
84219b2ee8SDavid du Colombier }
85219b2ee8SDavid du Colombier 
86219b2ee8SDavid du Colombier void
87219b2ee8SDavid du Colombier ocast(Node *n, Node *res)
88219b2ee8SDavid du Colombier {
89219b2ee8SDavid du Colombier 	if(n->sym->lt == 0)
90219b2ee8SDavid du Colombier 		error("%s is not a complex type", n->sym->name);
91219b2ee8SDavid du Colombier 
92219b2ee8SDavid du Colombier 	expr(n->left, res);
93219b2ee8SDavid du Colombier 	res->comt = n->sym->lt;
94219b2ee8SDavid du Colombier 	res->fmt = 'a';
95219b2ee8SDavid du Colombier }
96219b2ee8SDavid du Colombier 
97219b2ee8SDavid du Colombier void
98219b2ee8SDavid du Colombier oindm(Node *n, Node *res)
99bd389b36SDavid du Colombier {
100bd389b36SDavid du Colombier 	Map *m;
101219b2ee8SDavid du Colombier 	Node l;
102bd389b36SDavid du Colombier 
103bd389b36SDavid du Colombier 	m = cormap;
104bd389b36SDavid du Colombier 	if(m == 0)
105219b2ee8SDavid du Colombier 		m = symmap;
106219b2ee8SDavid du Colombier 	expr(n->left, &l);
107219b2ee8SDavid du Colombier 	if(l.type != TINT)
108219b2ee8SDavid du Colombier 		error("bad type for *");
109219b2ee8SDavid du Colombier 	if(m == 0)
110219b2ee8SDavid du Colombier 		error("no map for *");
111bd389b36SDavid du Colombier 	indir(m, l.ival, l.fmt, res);
112bd389b36SDavid du Colombier 	res->comt = l.comt;
113219b2ee8SDavid du Colombier }
114219b2ee8SDavid du Colombier 
115219b2ee8SDavid du Colombier void
116219b2ee8SDavid du Colombier oindc(Node *n, Node *res)
117219b2ee8SDavid du Colombier {
118219b2ee8SDavid du Colombier 	Map *m;
119219b2ee8SDavid du Colombier 	Node l;
120219b2ee8SDavid du Colombier 
121219b2ee8SDavid du Colombier 	m = symmap;
122219b2ee8SDavid du Colombier 	if(m == 0)
123219b2ee8SDavid du Colombier 		m = cormap;
124219b2ee8SDavid du Colombier 	expr(n->left, &l);
125219b2ee8SDavid du Colombier 	if(l.type != TINT)
126219b2ee8SDavid du Colombier 		error("bad type for @");
127219b2ee8SDavid du Colombier 	if(m == 0)
128219b2ee8SDavid du Colombier 		error("no map for @");
129219b2ee8SDavid du Colombier 	indir(m, l.ival, l.fmt, res);
130219b2ee8SDavid du Colombier 	res->comt = l.comt;
131219b2ee8SDavid du Colombier }
132219b2ee8SDavid du Colombier 
133219b2ee8SDavid du Colombier void
134219b2ee8SDavid du Colombier oframe(Node *n, Node *res)
135219b2ee8SDavid du Colombier {
136219b2ee8SDavid du Colombier 	char *p;
137219b2ee8SDavid du Colombier 	Node *lp;
138219b2ee8SDavid du Colombier 	long ival;
139219b2ee8SDavid du Colombier 	Frtype *f;
140219b2ee8SDavid du Colombier 
141219b2ee8SDavid du Colombier 	p = n->sym->name;
142219b2ee8SDavid du Colombier 	while(*p && *p == '$')
143219b2ee8SDavid du Colombier 		p++;
144219b2ee8SDavid du Colombier 	lp = n->left;
145219b2ee8SDavid du Colombier 	if(localaddr(cormap, p, lp->sym->name, &ival, rget) < 0)
146219b2ee8SDavid du Colombier 		error("colon: %r");
147219b2ee8SDavid du Colombier 
148219b2ee8SDavid du Colombier 	res->ival = ival;
149219b2ee8SDavid du Colombier 	res->op = OCONST;
150219b2ee8SDavid du Colombier 	res->fmt = 'X';
151219b2ee8SDavid du Colombier 	res->type = TINT;
152219b2ee8SDavid du Colombier 
153219b2ee8SDavid du Colombier 	/* Try and set comt */
154219b2ee8SDavid du Colombier 	for(f = n->sym->local; f; f = f->next) {
155219b2ee8SDavid du Colombier 		if(f->var == lp->sym) {
156219b2ee8SDavid du Colombier 			res->comt = f->type;
157219b2ee8SDavid du Colombier 			res->fmt = 'a';
158bd389b36SDavid du Colombier 			break;
159219b2ee8SDavid du Colombier 		}
160219b2ee8SDavid du Colombier 	}
161219b2ee8SDavid du Colombier }
162219b2ee8SDavid du Colombier 
163219b2ee8SDavid du Colombier void
164219b2ee8SDavid du Colombier oindex(Node *n, Node *res)
165219b2ee8SDavid du Colombier {
166219b2ee8SDavid du Colombier 	Node l, r;
167219b2ee8SDavid du Colombier 
168219b2ee8SDavid du Colombier 	expr(n->left, &l);
169219b2ee8SDavid du Colombier 	expr(n->right, &r);
170219b2ee8SDavid du Colombier 
171bd389b36SDavid du Colombier 	if(r.type != TINT)
172bd389b36SDavid du Colombier 		error("bad type for []");
173219b2ee8SDavid du Colombier 
174bd389b36SDavid du Colombier 	switch(l.type) {
175bd389b36SDavid du Colombier 	default:
176bd389b36SDavid du Colombier 		error("lhs[] has bad type");
177bd389b36SDavid du Colombier 	case TINT:
178219b2ee8SDavid du Colombier 		indir(cormap, l.ival+(r.ival*fsize[l.fmt]), l.fmt, res);
179219b2ee8SDavid du Colombier 		res->comt = l.comt;
180219b2ee8SDavid du Colombier 		res->fmt = l.fmt;
181bd389b36SDavid du Colombier 		break;
182bd389b36SDavid du Colombier 	case TLIST:
183bd389b36SDavid du Colombier 		nthelem(l.l, r.ival, res);
184bd389b36SDavid du Colombier 		break;
185bd389b36SDavid du Colombier 	case TSTRING:
186bd389b36SDavid du Colombier 		res->ival = 0;
187219b2ee8SDavid du Colombier 		if(r.ival >= 0 && r.ival < l.string->len) {
188219b2ee8SDavid du Colombier 			int xx8;	/* to get around bug in vc */
189219b2ee8SDavid du Colombier 			xx8 = r.ival;
190219b2ee8SDavid du Colombier 			res->ival = l.string->string[xx8];
191219b2ee8SDavid du Colombier 		}
192bd389b36SDavid du Colombier 		res->op = OCONST;
193bd389b36SDavid du Colombier 		res->type = TINT;
194bd389b36SDavid du Colombier 		res->fmt = 'c';
195bd389b36SDavid du Colombier 		break;
196bd389b36SDavid du Colombier 	}
197219b2ee8SDavid du Colombier }
198219b2ee8SDavid du Colombier 
199219b2ee8SDavid du Colombier void
200219b2ee8SDavid du Colombier oappend(Node *n, Node *res)
201219b2ee8SDavid du Colombier {
202219b2ee8SDavid du Colombier 	Node r, l;
203219b2ee8SDavid du Colombier 
204219b2ee8SDavid du Colombier 	expr(n->left, &l);
205219b2ee8SDavid du Colombier 	expr(n->right, &r);
206bd389b36SDavid du Colombier 	if(l.type != TLIST)
207bd389b36SDavid du Colombier 		error("must append to list");
208bd389b36SDavid du Colombier 	append(res, &l, &r);
209219b2ee8SDavid du Colombier }
210219b2ee8SDavid du Colombier 
211219b2ee8SDavid du Colombier void
212219b2ee8SDavid du Colombier odelete(Node *n, Node *res)
213219b2ee8SDavid du Colombier {
214219b2ee8SDavid du Colombier 	Node l, r;
215219b2ee8SDavid du Colombier 
216219b2ee8SDavid du Colombier 	expr(n->left, &l);
217219b2ee8SDavid du Colombier 	expr(n->right, &r);
218bd389b36SDavid du Colombier 	if(l.type != TLIST)
219bd389b36SDavid du Colombier 		error("must delete from list");
220bd389b36SDavid du Colombier 	if(r.type != TINT)
221bd389b36SDavid du Colombier 		error("delete index must be integer");
222bd389b36SDavid du Colombier 
223bd389b36SDavid du Colombier 	delete(l.l, r.ival, res);
224219b2ee8SDavid du Colombier }
225219b2ee8SDavid du Colombier 
226219b2ee8SDavid du Colombier void
227219b2ee8SDavid du Colombier ohead(Node *n, Node *res)
228219b2ee8SDavid du Colombier {
229219b2ee8SDavid du Colombier 	Node l;
230219b2ee8SDavid du Colombier 
231219b2ee8SDavid du Colombier 	expr(n->left, &l);
232bd389b36SDavid du Colombier 	if(l.type != TLIST)
233bd389b36SDavid du Colombier 		error("head needs list");
234bd389b36SDavid du Colombier 	res->op = OCONST;
235bd389b36SDavid du Colombier 	if(l.l) {
236bd389b36SDavid du Colombier 		res->type = l.l->type;
237bd389b36SDavid du Colombier 		res->Store = l.l->Store;
238bd389b36SDavid du Colombier 	}
239bd389b36SDavid du Colombier 	else {
240bd389b36SDavid du Colombier 		res->type = TLIST;
241bd389b36SDavid du Colombier 		res->l = 0;
242bd389b36SDavid du Colombier 	}
243219b2ee8SDavid du Colombier }
244219b2ee8SDavid du Colombier 
245219b2ee8SDavid du Colombier void
246219b2ee8SDavid du Colombier otail(Node *n, Node *res)
247219b2ee8SDavid du Colombier {
248219b2ee8SDavid du Colombier 	Node l;
249219b2ee8SDavid du Colombier 
250219b2ee8SDavid du Colombier 	expr(n->left, &l);
251bd389b36SDavid du Colombier 	if(l.type != TLIST)
252bd389b36SDavid du Colombier 		error("tail needs list");
253bd389b36SDavid du Colombier 	res->op = OCONST;
254bd389b36SDavid du Colombier 	res->type = TLIST;
255bd389b36SDavid du Colombier 	if(l.l)
256219b2ee8SDavid du Colombier 		res->l = l.l->next;
257bd389b36SDavid du Colombier 	else
258219b2ee8SDavid du Colombier 		res->l = 0;
259219b2ee8SDavid du Colombier }
260219b2ee8SDavid du Colombier 
261219b2ee8SDavid du Colombier void
262219b2ee8SDavid du Colombier oconst(Node *n, Node *res)
263219b2ee8SDavid du Colombier {
264219b2ee8SDavid du Colombier 	res->op = OCONST;
265219b2ee8SDavid du Colombier 	res->type = n->type;
266219b2ee8SDavid du Colombier 	res->Store = n->Store;
267219b2ee8SDavid du Colombier 	res->comt = n->comt;
268219b2ee8SDavid du Colombier }
269219b2ee8SDavid du Colombier 
270219b2ee8SDavid du Colombier void
271219b2ee8SDavid du Colombier oname(Node *n, Node *res)
272219b2ee8SDavid du Colombier {
273219b2ee8SDavid du Colombier 	Value *v;
274219b2ee8SDavid du Colombier 
275bd389b36SDavid du Colombier 	v = n->sym->v;
276bd389b36SDavid du Colombier 	if(v->set == 0)
277bd389b36SDavid du Colombier 		error("%s used but not set", n->sym->name);
278bd389b36SDavid du Colombier 	res->op = OCONST;
279bd389b36SDavid du Colombier 	res->type = v->type;
280bd389b36SDavid du Colombier 	res->Store = v->Store;
281219b2ee8SDavid du Colombier 	res->comt = v->comt;
282219b2ee8SDavid du Colombier }
283219b2ee8SDavid du Colombier 
284219b2ee8SDavid du Colombier void
285219b2ee8SDavid du Colombier octruct(Node *n, Node *res)
286219b2ee8SDavid du Colombier {
287bd389b36SDavid du Colombier 	res->op = OCONST;
288bd389b36SDavid du Colombier 	res->type = TLIST;
289219b2ee8SDavid du Colombier 	res->l = construct(n->left);
290219b2ee8SDavid du Colombier }
291219b2ee8SDavid du Colombier 
292219b2ee8SDavid du Colombier void
293219b2ee8SDavid du Colombier oasgn(Node *n, Node *res)
294219b2ee8SDavid du Colombier {
295219b2ee8SDavid du Colombier 	Node *lp, r;
296219b2ee8SDavid du Colombier 	Value *v;
297219b2ee8SDavid du Colombier 
298219b2ee8SDavid du Colombier 	lp = n->left;
299bd389b36SDavid du Colombier 	switch(lp->op) {
300bd389b36SDavid du Colombier 	case OINDM:
301219b2ee8SDavid du Colombier 		windir(cormap, lp->left, n->right, res);
302bd389b36SDavid du Colombier 		break;
303bd389b36SDavid du Colombier 	case OINDC:
304219b2ee8SDavid du Colombier 		windir(symmap, lp->left, n->right, res);
305bd389b36SDavid du Colombier 		break;
306bd389b36SDavid du Colombier 	default:
307bd389b36SDavid du Colombier 		chklval(lp);
308bd389b36SDavid du Colombier 		v = lp->sym->v;
309219b2ee8SDavid du Colombier 		expr(n->right, &r);
310bd389b36SDavid du Colombier 		v->set = 1;
311bd389b36SDavid du Colombier 		v->type = r.type;
312bd389b36SDavid du Colombier 		v->Store = r.Store;
313219b2ee8SDavid du Colombier 		res->op = OCONST;
314219b2ee8SDavid du Colombier 		res->type = v->type;
315219b2ee8SDavid du Colombier 		res->Store = v->Store;
316219b2ee8SDavid du Colombier 		res->comt = v->comt;
317bd389b36SDavid du Colombier 	}
318219b2ee8SDavid du Colombier }
319219b2ee8SDavid du Colombier 
320219b2ee8SDavid du Colombier void
321219b2ee8SDavid du Colombier oadd(Node *n, Node *res)
322219b2ee8SDavid du Colombier {
323219b2ee8SDavid du Colombier 	Node l, r;
324219b2ee8SDavid du Colombier 
325219b2ee8SDavid du Colombier 	expr(n->left, &l);
326219b2ee8SDavid du Colombier 	expr(n->right, &r);
327bd389b36SDavid du Colombier 	res->fmt = l.fmt;
328bd389b36SDavid du Colombier 	res->op = OCONST;
329bd389b36SDavid du Colombier 	res->type = TFLOAT;
330bd389b36SDavid du Colombier 	switch(l.type) {
331219b2ee8SDavid du Colombier 	default:
332219b2ee8SDavid du Colombier 		error("bad lhs type +");
333bd389b36SDavid du Colombier 	case TINT:
334bd389b36SDavid du Colombier 		switch(r.type) {
335bd389b36SDavid du Colombier 		case TINT:
336bd389b36SDavid du Colombier 			res->type = TINT;
337bd389b36SDavid du Colombier 			res->ival = l.ival+r.ival;
338bd389b36SDavid du Colombier 			break;
339bd389b36SDavid du Colombier 		case TFLOAT:
340bd389b36SDavid du Colombier 			res->fval = l.ival+r.fval;
341bd389b36SDavid du Colombier 			break;
342219b2ee8SDavid du Colombier 		default:
343219b2ee8SDavid du Colombier 			error("bad rhs type +");
344bd389b36SDavid du Colombier 		}
345bd389b36SDavid du Colombier 		break;
346bd389b36SDavid du Colombier 	case TFLOAT:
347bd389b36SDavid du Colombier 		switch(r.type) {
348bd389b36SDavid du Colombier 		case TINT:
349bd389b36SDavid du Colombier 			res->fval = l.fval+r.ival;
350bd389b36SDavid du Colombier 			break;
351bd389b36SDavid du Colombier 		case TFLOAT:
352bd389b36SDavid du Colombier 			res->fval = l.fval+r.fval;
353bd389b36SDavid du Colombier 			break;
354219b2ee8SDavid du Colombier 		default:
355219b2ee8SDavid du Colombier 			error("bad rhs type +");
356bd389b36SDavid du Colombier 		}
357bd389b36SDavid du Colombier 		break;
358bd389b36SDavid du Colombier 	case TSTRING:
359bd389b36SDavid du Colombier 		if(r.type == TSTRING) {
360bd389b36SDavid du Colombier 			res->type = TSTRING;
361bd389b36SDavid du Colombier 			res->fmt = 's';
362bd389b36SDavid du Colombier 			res->string = stradd(l.string, r.string);
363bd389b36SDavid du Colombier 			break;
364bd389b36SDavid du Colombier 		}
365*ab3dc52fSDavid du Colombier 		if(r.type == TINT) {
366*ab3dc52fSDavid du Colombier 			res->type = TSTRING;
367*ab3dc52fSDavid du Colombier 			res->fmt = 's';
368*ab3dc52fSDavid du Colombier 			res->string = straddrune(l.string, r.ival);
369*ab3dc52fSDavid du Colombier 			break;
370*ab3dc52fSDavid du Colombier 		}
371bd389b36SDavid du Colombier 		error("bad rhs for +");
372bd389b36SDavid du Colombier 	case TLIST:
373bd389b36SDavid du Colombier 		res->type = TLIST;
374bd389b36SDavid du Colombier 		switch(r.type) {
375bd389b36SDavid du Colombier 		case TLIST:
376bd389b36SDavid du Colombier 			res->l = addlist(l.l, r.l);
377bd389b36SDavid du Colombier 			break;
378bd389b36SDavid du Colombier 		default:
379bd389b36SDavid du Colombier 			r.left = 0;
380bd389b36SDavid du Colombier 			r.right = 0;
381bd389b36SDavid du Colombier 			res->l = addlist(l.l, construct(&r));
382bd389b36SDavid du Colombier 			break;
383bd389b36SDavid du Colombier 		}
384bd389b36SDavid du Colombier 	}
385219b2ee8SDavid du Colombier }
386219b2ee8SDavid du Colombier 
387219b2ee8SDavid du Colombier void
388219b2ee8SDavid du Colombier osub(Node *n, Node *res)
389219b2ee8SDavid du Colombier {
390219b2ee8SDavid du Colombier 	Node l, r;
391219b2ee8SDavid du Colombier 
392219b2ee8SDavid du Colombier 	expr(n->left, &l);
393219b2ee8SDavid du Colombier 	expr(n->right, &r);
394bd389b36SDavid du Colombier 	res->fmt = l.fmt;
395bd389b36SDavid du Colombier 	res->op = OCONST;
396bd389b36SDavid du Colombier 	res->type = TFLOAT;
397bd389b36SDavid du Colombier 	switch(l.type) {
398219b2ee8SDavid du Colombier 	default:
399219b2ee8SDavid du Colombier 		error("bad lhs type -");
400bd389b36SDavid du Colombier 	case TINT:
401bd389b36SDavid du Colombier 		switch(r.type) {
402bd389b36SDavid du Colombier 		case TINT:
403bd389b36SDavid du Colombier 			res->type = TINT;
404bd389b36SDavid du Colombier 			res->ival = l.ival-r.ival;
405bd389b36SDavid du Colombier 			break;
406bd389b36SDavid du Colombier 		case TFLOAT:
407bd389b36SDavid du Colombier 			res->fval = l.ival-r.fval;
408bd389b36SDavid du Colombier 			break;
409219b2ee8SDavid du Colombier 		default:
410219b2ee8SDavid du Colombier 			error("bad rhs type -");
411bd389b36SDavid du Colombier 		}
412bd389b36SDavid du Colombier 		break;
413bd389b36SDavid du Colombier 	case TFLOAT:
414219b2ee8SDavid du Colombier 		switch(r.type) {
415bd389b36SDavid du Colombier 		case TINT:
416bd389b36SDavid du Colombier 			res->fval = l.fval-r.ival;
417bd389b36SDavid du Colombier 			break;
418bd389b36SDavid du Colombier 		case TFLOAT:
419bd389b36SDavid du Colombier 			res->fval = l.fval-r.fval;
420bd389b36SDavid du Colombier 			break;
421219b2ee8SDavid du Colombier 		default:
422219b2ee8SDavid du Colombier 			error("bad rhs type -");
423bd389b36SDavid du Colombier 		}
424bd389b36SDavid du Colombier 		break;
425bd389b36SDavid du Colombier 	}
426219b2ee8SDavid du Colombier }
427219b2ee8SDavid du Colombier 
428219b2ee8SDavid du Colombier void
429219b2ee8SDavid du Colombier omul(Node *n, Node *res)
430219b2ee8SDavid du Colombier {
431219b2ee8SDavid du Colombier 	Node l, r;
432219b2ee8SDavid du Colombier 
433219b2ee8SDavid du Colombier 	expr(n->left, &l);
434219b2ee8SDavid du Colombier 	expr(n->right, &r);
435bd389b36SDavid du Colombier 	res->fmt = l.fmt;
436bd389b36SDavid du Colombier 	res->op = OCONST;
437bd389b36SDavid du Colombier 	res->type = TFLOAT;
438bd389b36SDavid du Colombier 	switch(l.type) {
439219b2ee8SDavid du Colombier 	default:
440219b2ee8SDavid du Colombier 		error("bad lhs type *");
441bd389b36SDavid du Colombier 	case TINT:
442bd389b36SDavid du Colombier 		switch(r.type) {
443bd389b36SDavid du Colombier 		case TINT:
444bd389b36SDavid du Colombier 			res->type = TINT;
445bd389b36SDavid du Colombier 			res->ival = l.ival*r.ival;
446bd389b36SDavid du Colombier 			break;
447bd389b36SDavid du Colombier 		case TFLOAT:
448bd389b36SDavid du Colombier 			res->fval = l.ival*r.fval;
449bd389b36SDavid du Colombier 			break;
450219b2ee8SDavid du Colombier 		default:
451219b2ee8SDavid du Colombier 			error("bad rhs type *");
452bd389b36SDavid du Colombier 		}
453bd389b36SDavid du Colombier 		break;
454bd389b36SDavid du Colombier 	case TFLOAT:
455219b2ee8SDavid du Colombier 		switch(r.type) {
456bd389b36SDavid du Colombier 		case TINT:
457bd389b36SDavid du Colombier 			res->fval = l.fval*r.ival;
458bd389b36SDavid du Colombier 			break;
459bd389b36SDavid du Colombier 		case TFLOAT:
460bd389b36SDavid du Colombier 			res->fval = l.fval*r.fval;
461bd389b36SDavid du Colombier 			break;
462219b2ee8SDavid du Colombier 		default:
463219b2ee8SDavid du Colombier 			error("bad rhs type *");
464bd389b36SDavid du Colombier 		}
465bd389b36SDavid du Colombier 		break;
466bd389b36SDavid du Colombier 	}
467219b2ee8SDavid du Colombier }
468219b2ee8SDavid du Colombier 
469219b2ee8SDavid du Colombier void
470219b2ee8SDavid du Colombier odiv(Node *n, Node *res)
471219b2ee8SDavid du Colombier {
472219b2ee8SDavid du Colombier 	Node l, r;
473219b2ee8SDavid du Colombier 
474219b2ee8SDavid du Colombier 	expr(n->left, &l);
475219b2ee8SDavid du Colombier 	expr(n->right, &r);
476bd389b36SDavid du Colombier 	res->fmt = l.fmt;
477bd389b36SDavid du Colombier 	res->op = OCONST;
478bd389b36SDavid du Colombier 	res->type = TFLOAT;
479bd389b36SDavid du Colombier 	switch(l.type) {
480219b2ee8SDavid du Colombier 	default:
481219b2ee8SDavid du Colombier 		error("bad lhs type /");
482bd389b36SDavid du Colombier 	case TINT:
483bd389b36SDavid du Colombier 		switch(r.type) {
484bd389b36SDavid du Colombier 		case TINT:
485bd389b36SDavid du Colombier 			res->type = TINT;
486219b2ee8SDavid du Colombier 			if(r.ival == 0)
487219b2ee8SDavid du Colombier 				error("zero divide");
488bd389b36SDavid du Colombier 			res->ival = l.ival/r.ival;
489bd389b36SDavid du Colombier 			break;
490bd389b36SDavid du Colombier 		case TFLOAT:
491219b2ee8SDavid du Colombier 			if(r.fval == 0)
492219b2ee8SDavid du Colombier 				error("zero divide");
493bd389b36SDavid du Colombier 			res->fval = l.ival/r.fval;
494bd389b36SDavid du Colombier 			break;
495219b2ee8SDavid du Colombier 		default:
496219b2ee8SDavid du Colombier 			error("bad rhs type /");
497bd389b36SDavid du Colombier 		}
498bd389b36SDavid du Colombier 		break;
499bd389b36SDavid du Colombier 	case TFLOAT:
500219b2ee8SDavid du Colombier 		switch(r.type) {
501bd389b36SDavid du Colombier 		case TINT:
502bd389b36SDavid du Colombier 			res->fval = l.fval/r.ival;
503bd389b36SDavid du Colombier 			break;
504bd389b36SDavid du Colombier 		case TFLOAT:
505bd389b36SDavid du Colombier 			res->fval = l.fval/r.fval;
506bd389b36SDavid du Colombier 			break;
507219b2ee8SDavid du Colombier 		default:
508219b2ee8SDavid du Colombier 			error("bad rhs type /");
509bd389b36SDavid du Colombier 		}
510bd389b36SDavid du Colombier 		break;
511bd389b36SDavid du Colombier 	}
512219b2ee8SDavid du Colombier }
513219b2ee8SDavid du Colombier 
514219b2ee8SDavid du Colombier void
515219b2ee8SDavid du Colombier omod(Node *n, Node *res)
516219b2ee8SDavid du Colombier {
517219b2ee8SDavid du Colombier 	Node l, r;
518219b2ee8SDavid du Colombier 
519219b2ee8SDavid du Colombier 	expr(n->left, &l);
520219b2ee8SDavid du Colombier 	expr(n->right, &r);
521bd389b36SDavid du Colombier 	res->fmt = l.fmt;
522bd389b36SDavid du Colombier 	res->op = OCONST;
523bd389b36SDavid du Colombier 	res->type = TINT;
524bd389b36SDavid du Colombier 	if(l.type != TINT || r.type != TINT)
525bd389b36SDavid du Colombier 		error("bad expr type %");
526bd389b36SDavid du Colombier 	res->ival = l.ival%r.ival;
527219b2ee8SDavid du Colombier }
528219b2ee8SDavid du Colombier 
529219b2ee8SDavid du Colombier void
530219b2ee8SDavid du Colombier olsh(Node *n, Node *res)
531219b2ee8SDavid du Colombier {
532219b2ee8SDavid du Colombier 	Node l, r;
533219b2ee8SDavid du Colombier 
534219b2ee8SDavid du Colombier 	expr(n->left, &l);
535219b2ee8SDavid du Colombier 	expr(n->right, &r);
536bd389b36SDavid du Colombier 	res->fmt = l.fmt;
537bd389b36SDavid du Colombier 	res->op = OCONST;
538bd389b36SDavid du Colombier 	res->type = TINT;
539bd389b36SDavid du Colombier 	if(l.type != TINT || r.type != TINT)
540bd389b36SDavid du Colombier 		error("bad expr type <<");
541bd389b36SDavid du Colombier 	res->ival = l.ival<<r.ival;
542219b2ee8SDavid du Colombier }
543219b2ee8SDavid du Colombier 
544219b2ee8SDavid du Colombier void
545219b2ee8SDavid du Colombier orsh(Node *n, Node *res)
546219b2ee8SDavid du Colombier {
547219b2ee8SDavid du Colombier 	Node l, r;
548219b2ee8SDavid du Colombier 
549219b2ee8SDavid du Colombier 	expr(n->left, &l);
550219b2ee8SDavid du Colombier 	expr(n->right, &r);
551bd389b36SDavid du Colombier 	res->fmt = l.fmt;
552bd389b36SDavid du Colombier 	res->op = OCONST;
553bd389b36SDavid du Colombier 	res->type = TINT;
554bd389b36SDavid du Colombier 	if(l.type != TINT || r.type != TINT)
555bd389b36SDavid du Colombier 		error("bad expr type >>");
5567dd7cddfSDavid du Colombier 	res->ival = (unsigned)l.ival>>r.ival;
557219b2ee8SDavid du Colombier }
558219b2ee8SDavid du Colombier 
559219b2ee8SDavid du Colombier void
560219b2ee8SDavid du Colombier olt(Node *n, Node *res)
561219b2ee8SDavid du Colombier {
562219b2ee8SDavid du Colombier 	Node l, r;
563219b2ee8SDavid du Colombier 
564219b2ee8SDavid du Colombier 	expr(n->left, &l);
565219b2ee8SDavid du Colombier 	expr(n->right, &r);
566219b2ee8SDavid du Colombier 
567bd389b36SDavid du Colombier 	res->fmt = l.fmt;
568bd389b36SDavid du Colombier 	res->op = OCONST;
569bd389b36SDavid du Colombier 	res->type = TINT;
570bd389b36SDavid du Colombier 	switch(l.type) {
571219b2ee8SDavid du Colombier 	default:
572219b2ee8SDavid du Colombier 		error("bad lhs type <");
573bd389b36SDavid du Colombier 	case TINT:
574bd389b36SDavid du Colombier 		switch(r.type) {
575bd389b36SDavid du Colombier 		case TINT:
576bd389b36SDavid du Colombier 			res->ival = l.ival < r.ival;
577bd389b36SDavid du Colombier 			break;
578bd389b36SDavid du Colombier 		case TFLOAT:
579bd389b36SDavid du Colombier 			res->ival = l.ival < r.fval;
580bd389b36SDavid du Colombier 			break;
581219b2ee8SDavid du Colombier 		default:
582219b2ee8SDavid du Colombier 			error("bad rhs type <");
583bd389b36SDavid du Colombier 		}
584bd389b36SDavid du Colombier 		break;
585bd389b36SDavid du Colombier 	case TFLOAT:
586219b2ee8SDavid du Colombier 		switch(r.type) {
587bd389b36SDavid du Colombier 		case TINT:
588bd389b36SDavid du Colombier 			res->ival = l.fval < r.ival;
589bd389b36SDavid du Colombier 			break;
590bd389b36SDavid du Colombier 		case TFLOAT:
591bd389b36SDavid du Colombier 			res->ival = l.fval < r.fval;
592bd389b36SDavid du Colombier 			break;
593219b2ee8SDavid du Colombier 		default:
594219b2ee8SDavid du Colombier 			error("bad rhs type <");
595bd389b36SDavid du Colombier 		}
596bd389b36SDavid du Colombier 		break;
597bd389b36SDavid du Colombier 	}
598219b2ee8SDavid du Colombier }
599219b2ee8SDavid du Colombier 
600219b2ee8SDavid du Colombier void
601219b2ee8SDavid du Colombier ogt(Node *n, Node *res)
602219b2ee8SDavid du Colombier {
603219b2ee8SDavid du Colombier 	Node l, r;
604219b2ee8SDavid du Colombier 
605219b2ee8SDavid du Colombier 	expr(n->left, &l);
606219b2ee8SDavid du Colombier 	expr(n->right, &r);
607bd389b36SDavid du Colombier 	res->fmt = 'D';
608bd389b36SDavid du Colombier 	res->op = OCONST;
609bd389b36SDavid du Colombier 	res->type = TINT;
610bd389b36SDavid du Colombier 	switch(l.type) {
611219b2ee8SDavid du Colombier 	default:
612219b2ee8SDavid du Colombier 		error("bad lhs type >");
613bd389b36SDavid du Colombier 	case TINT:
614bd389b36SDavid du Colombier 		switch(r.type) {
615bd389b36SDavid du Colombier 		case TINT:
616bd389b36SDavid du Colombier 			res->ival = l.ival > r.ival;
617bd389b36SDavid du Colombier 			break;
618bd389b36SDavid du Colombier 		case TFLOAT:
619bd389b36SDavid du Colombier 			res->ival = l.ival > r.fval;
620bd389b36SDavid du Colombier 			break;
621219b2ee8SDavid du Colombier 		default:
622219b2ee8SDavid du Colombier 			error("bad rhs type >");
623bd389b36SDavid du Colombier 		}
624bd389b36SDavid du Colombier 		break;
625bd389b36SDavid du Colombier 	case TFLOAT:
626219b2ee8SDavid du Colombier 		switch(r.type) {
627bd389b36SDavid du Colombier 		case TINT:
628bd389b36SDavid du Colombier 			res->ival = l.fval > r.ival;
629bd389b36SDavid du Colombier 			break;
630bd389b36SDavid du Colombier 		case TFLOAT:
631bd389b36SDavid du Colombier 			res->ival = l.fval > r.fval;
632bd389b36SDavid du Colombier 			break;
633219b2ee8SDavid du Colombier 		default:
634219b2ee8SDavid du Colombier 			error("bad rhs type >");
635bd389b36SDavid du Colombier 		}
636bd389b36SDavid du Colombier 		break;
637bd389b36SDavid du Colombier 	}
638219b2ee8SDavid du Colombier }
639219b2ee8SDavid du Colombier 
640219b2ee8SDavid du Colombier void
641219b2ee8SDavid du Colombier oleq(Node *n, Node *res)
642219b2ee8SDavid du Colombier {
643219b2ee8SDavid du Colombier 	Node l, r;
644219b2ee8SDavid du Colombier 
645219b2ee8SDavid du Colombier 	expr(n->left, &l);
646219b2ee8SDavid du Colombier 	expr(n->right, &r);
647bd389b36SDavid du Colombier 	res->fmt = 'D';
648bd389b36SDavid du Colombier 	res->op = OCONST;
649bd389b36SDavid du Colombier 	res->type = TINT;
650bd389b36SDavid du Colombier 	switch(l.type) {
651219b2ee8SDavid du Colombier 	default:
652219b2ee8SDavid du Colombier 		error("bad expr type <=");
653bd389b36SDavid du Colombier 	case TINT:
654bd389b36SDavid du Colombier 		switch(r.type) {
655bd389b36SDavid du Colombier 		case TINT:
656bd389b36SDavid du Colombier 			res->ival = l.ival <= r.ival;
657bd389b36SDavid du Colombier 			break;
658bd389b36SDavid du Colombier 		case TFLOAT:
659bd389b36SDavid du Colombier 			res->ival = l.ival <= r.fval;
660bd389b36SDavid du Colombier 			break;
661219b2ee8SDavid du Colombier 		default:
662bd389b36SDavid du Colombier 			error("bad expr type <=");
663bd389b36SDavid du Colombier 		}
664bd389b36SDavid du Colombier 		break;
665bd389b36SDavid du Colombier 	case TFLOAT:
666219b2ee8SDavid du Colombier 		switch(r.type) {
667bd389b36SDavid du Colombier 		case TINT:
668bd389b36SDavid du Colombier 			res->ival = l.fval <= r.ival;
669bd389b36SDavid du Colombier 			break;
670bd389b36SDavid du Colombier 		case TFLOAT:
671bd389b36SDavid du Colombier 			res->ival = l.fval <= r.fval;
672bd389b36SDavid du Colombier 			break;
673219b2ee8SDavid du Colombier 		default:
674bd389b36SDavid du Colombier 			error("bad expr type <=");
675bd389b36SDavid du Colombier 		}
676bd389b36SDavid du Colombier 		break;
677bd389b36SDavid du Colombier 	}
678219b2ee8SDavid du Colombier }
679219b2ee8SDavid du Colombier 
680219b2ee8SDavid du Colombier void
681219b2ee8SDavid du Colombier ogeq(Node *n, Node *res)
682219b2ee8SDavid du Colombier {
683219b2ee8SDavid du Colombier 	Node l, r;
684219b2ee8SDavid du Colombier 
685219b2ee8SDavid du Colombier 	expr(n->left, &l);
686219b2ee8SDavid du Colombier 	expr(n->right, &r);
687bd389b36SDavid du Colombier 	res->fmt = 'D';
688bd389b36SDavid du Colombier 	res->op = OCONST;
689bd389b36SDavid du Colombier 	res->type = TINT;
690bd389b36SDavid du Colombier 	switch(l.type) {
691219b2ee8SDavid du Colombier 	default:
692219b2ee8SDavid du Colombier 		error("bad lhs type >=");
693bd389b36SDavid du Colombier 	case TINT:
694bd389b36SDavid du Colombier 		switch(r.type) {
695bd389b36SDavid du Colombier 		case TINT:
696bd389b36SDavid du Colombier 			res->ival = l.ival >= r.ival;
697bd389b36SDavid du Colombier 			break;
698bd389b36SDavid du Colombier 		case TFLOAT:
699bd389b36SDavid du Colombier 			res->ival = l.ival >= r.fval;
700bd389b36SDavid du Colombier 			break;
701219b2ee8SDavid du Colombier 		default:
702219b2ee8SDavid du Colombier 			error("bad rhs type >=");
703bd389b36SDavid du Colombier 		}
704bd389b36SDavid du Colombier 		break;
705bd389b36SDavid du Colombier 	case TFLOAT:
706219b2ee8SDavid du Colombier 		switch(r.type) {
707bd389b36SDavid du Colombier 		case TINT:
708bd389b36SDavid du Colombier 			res->ival = l.fval >= r.ival;
709bd389b36SDavid du Colombier 			break;
710bd389b36SDavid du Colombier 		case TFLOAT:
711bd389b36SDavid du Colombier 			res->ival = l.fval >= r.fval;
712bd389b36SDavid du Colombier 			break;
713219b2ee8SDavid du Colombier 		default:
714219b2ee8SDavid du Colombier 			error("bad rhs type >=");
715bd389b36SDavid du Colombier 		}
716bd389b36SDavid du Colombier 		break;
717bd389b36SDavid du Colombier 	}
718219b2ee8SDavid du Colombier }
719219b2ee8SDavid du Colombier 
720219b2ee8SDavid du Colombier void
721219b2ee8SDavid du Colombier oeq(Node *n, Node *res)
722219b2ee8SDavid du Colombier {
723219b2ee8SDavid du Colombier 	Node l, r;
724219b2ee8SDavid du Colombier 
725219b2ee8SDavid du Colombier 	expr(n->left, &l);
726219b2ee8SDavid du Colombier 	expr(n->right, &r);
727bd389b36SDavid du Colombier 	res->fmt = 'D';
728bd389b36SDavid du Colombier 	res->op = OCONST;
729bd389b36SDavid du Colombier 	res->type = TINT;
730219b2ee8SDavid du Colombier 	res->ival = 0;
731bd389b36SDavid du Colombier 	switch(l.type) {
732219b2ee8SDavid du Colombier 	default:
733219b2ee8SDavid du Colombier 		break;
734bd389b36SDavid du Colombier 	case TINT:
735bd389b36SDavid du Colombier 		switch(r.type) {
736bd389b36SDavid du Colombier 		case TINT:
737bd389b36SDavid du Colombier 			res->ival = l.ival == r.ival;
738bd389b36SDavid du Colombier 			break;
739bd389b36SDavid du Colombier 		case TFLOAT:
740bd389b36SDavid du Colombier 			res->ival = l.ival == r.fval;
741bd389b36SDavid du Colombier 			break;
742219b2ee8SDavid du Colombier 		default:
743219b2ee8SDavid du Colombier 			break;
744bd389b36SDavid du Colombier 		}
745bd389b36SDavid du Colombier 		break;
746bd389b36SDavid du Colombier 	case TFLOAT:
747219b2ee8SDavid du Colombier 		switch(r.type) {
748bd389b36SDavid du Colombier 		case TINT:
749bd389b36SDavid du Colombier 			res->ival = l.fval == r.ival;
750bd389b36SDavid du Colombier 			break;
751bd389b36SDavid du Colombier 		case TFLOAT:
752bd389b36SDavid du Colombier 			res->ival = l.fval == r.fval;
753bd389b36SDavid du Colombier 			break;
754219b2ee8SDavid du Colombier 		default:
755219b2ee8SDavid du Colombier 			break;
756bd389b36SDavid du Colombier 		}
757bd389b36SDavid du Colombier 		break;
758bd389b36SDavid du Colombier 	case TSTRING:
759bd389b36SDavid du Colombier 		if(r.type == TSTRING) {
760bd389b36SDavid du Colombier 			res->ival = scmp(r.string, l.string);
761bd389b36SDavid du Colombier 			break;
762bd389b36SDavid du Colombier 		}
763219b2ee8SDavid du Colombier 		break;
764bd389b36SDavid du Colombier 	case TLIST:
765bd389b36SDavid du Colombier 		if(r.type == TLIST) {
766bd389b36SDavid du Colombier 			res->ival = listcmp(l.l, r.l);
767bd389b36SDavid du Colombier 			break;
768bd389b36SDavid du Colombier 		}
769bd389b36SDavid du Colombier 		break;
770bd389b36SDavid du Colombier 	}
771219b2ee8SDavid du Colombier 	if(n->op == ONEQ)
772219b2ee8SDavid du Colombier 		res->ival = !res->ival;
773bd389b36SDavid du Colombier }
774219b2ee8SDavid du Colombier 
775219b2ee8SDavid du Colombier 
776219b2ee8SDavid du Colombier void
777219b2ee8SDavid du Colombier oland(Node *n, Node *res)
778219b2ee8SDavid du Colombier {
779219b2ee8SDavid du Colombier 	Node l, r;
780219b2ee8SDavid du Colombier 
781219b2ee8SDavid du Colombier 	expr(n->left, &l);
782219b2ee8SDavid du Colombier 	expr(n->right, &r);
783bd389b36SDavid du Colombier 	res->fmt = l.fmt;
784bd389b36SDavid du Colombier 	res->op = OCONST;
785bd389b36SDavid du Colombier 	res->type = TINT;
786bd389b36SDavid du Colombier 	if(l.type != TINT || r.type != TINT)
787bd389b36SDavid du Colombier 		error("bad expr type &");
788bd389b36SDavid du Colombier 	res->ival = l.ival&r.ival;
789219b2ee8SDavid du Colombier }
790219b2ee8SDavid du Colombier 
791219b2ee8SDavid du Colombier void
792219b2ee8SDavid du Colombier oxor(Node *n, Node *res)
793219b2ee8SDavid du Colombier {
794219b2ee8SDavid du Colombier 	Node l, r;
795219b2ee8SDavid du Colombier 
796219b2ee8SDavid du Colombier 	expr(n->left, &l);
797219b2ee8SDavid du Colombier 	expr(n->right, &r);
798bd389b36SDavid du Colombier 	res->fmt = l.fmt;
799bd389b36SDavid du Colombier 	res->op = OCONST;
800bd389b36SDavid du Colombier 	res->type = TINT;
801bd389b36SDavid du Colombier 	if(l.type != TINT || r.type != TINT)
802bd389b36SDavid du Colombier 		error("bad expr type ^");
803bd389b36SDavid du Colombier 	res->ival = l.ival^r.ival;
804219b2ee8SDavid du Colombier }
805219b2ee8SDavid du Colombier 
806219b2ee8SDavid du Colombier void
807219b2ee8SDavid du Colombier olor(Node *n, Node *res)
808219b2ee8SDavid du Colombier {
809219b2ee8SDavid du Colombier 	Node l, r;
810219b2ee8SDavid du Colombier 
811219b2ee8SDavid du Colombier 	expr(n->left, &l);
812219b2ee8SDavid du Colombier 	expr(n->right, &r);
813bd389b36SDavid du Colombier 	res->fmt = l.fmt;
814bd389b36SDavid du Colombier 	res->op = OCONST;
815bd389b36SDavid du Colombier 	res->type = TINT;
816bd389b36SDavid du Colombier 	if(l.type != TINT || r.type != TINT)
817bd389b36SDavid du Colombier 		error("bad expr type |");
818bd389b36SDavid du Colombier 	res->ival = l.ival|r.ival;
819219b2ee8SDavid du Colombier }
820219b2ee8SDavid du Colombier 
821219b2ee8SDavid du Colombier void
822219b2ee8SDavid du Colombier ocand(Node *n, Node *res)
823219b2ee8SDavid du Colombier {
824219b2ee8SDavid du Colombier 	Node l, r;
825219b2ee8SDavid du Colombier 
826bd389b36SDavid du Colombier 	res->fmt = l.fmt;
827bd389b36SDavid du Colombier 	res->op = OCONST;
828bd389b36SDavid du Colombier 	res->type = TINT;
829219b2ee8SDavid du Colombier 	res->ival = 0;
830219b2ee8SDavid du Colombier 	expr(n->left, &l);
831219b2ee8SDavid du Colombier 	if(bool(&l) == 0)
832219b2ee8SDavid du Colombier 		return;
833219b2ee8SDavid du Colombier 	expr(n->right, &r);
834219b2ee8SDavid du Colombier 	if(bool(&r) == 0)
835219b2ee8SDavid du Colombier 		return;
836219b2ee8SDavid du Colombier 	res->ival = 1;
837219b2ee8SDavid du Colombier }
838219b2ee8SDavid du Colombier 
839219b2ee8SDavid du Colombier void
840219b2ee8SDavid du Colombier onot(Node *n, Node *res)
841219b2ee8SDavid du Colombier {
842219b2ee8SDavid du Colombier 	Node l;
843219b2ee8SDavid du Colombier 
844bd389b36SDavid du Colombier 	res->op = OCONST;
845bd389b36SDavid du Colombier 	res->type = TINT;
846219b2ee8SDavid du Colombier 	res->ival = 0;
847219b2ee8SDavid du Colombier 	expr(n->left, &l);
848219b2ee8SDavid du Colombier 	if(bool(&l) == 0)
849219b2ee8SDavid du Colombier 		res->ival = 1;
850219b2ee8SDavid du Colombier }
851219b2ee8SDavid du Colombier 
852219b2ee8SDavid du Colombier void
853219b2ee8SDavid du Colombier ocor(Node *n, Node *res)
854219b2ee8SDavid du Colombier {
855219b2ee8SDavid du Colombier 	Node l, r;
856219b2ee8SDavid du Colombier 
857219b2ee8SDavid du Colombier 	res->op = OCONST;
858219b2ee8SDavid du Colombier 	res->type = TINT;
859219b2ee8SDavid du Colombier 	res->ival = 0;
860219b2ee8SDavid du Colombier 	expr(n->left, &l);
861219b2ee8SDavid du Colombier 	if(bool(&l)) {
862219b2ee8SDavid du Colombier 		res->ival = 1;
863219b2ee8SDavid du Colombier 		return;
864219b2ee8SDavid du Colombier 	}
865219b2ee8SDavid du Colombier 	expr(n->right, &r);
866219b2ee8SDavid du Colombier 	if(bool(&r)) {
867219b2ee8SDavid du Colombier 		res->ival = 1;
868219b2ee8SDavid du Colombier 		return;
869219b2ee8SDavid du Colombier 	}
870219b2ee8SDavid du Colombier }
871219b2ee8SDavid du Colombier 
872219b2ee8SDavid du Colombier void
873219b2ee8SDavid du Colombier oeinc(Node *n, Node *res)
874219b2ee8SDavid du Colombier {
875219b2ee8SDavid du Colombier 	Value *v;
876219b2ee8SDavid du Colombier 
877219b2ee8SDavid du Colombier 	chklval(n->left);
878219b2ee8SDavid du Colombier 	v = n->left->sym->v;
879bd389b36SDavid du Colombier 	res->op = OCONST;
880bd389b36SDavid du Colombier 	res->type = v->type;
881bd389b36SDavid du Colombier 	switch(v->type) {
882bd389b36SDavid du Colombier 	case TINT:
883bd389b36SDavid du Colombier 		if(n->op == OEDEC)
884bd389b36SDavid du Colombier 			v->ival -= fmtsize(v);
885bd389b36SDavid du Colombier 		else
886bd389b36SDavid du Colombier 			v->ival += fmtsize(v);
887bd389b36SDavid du Colombier 		break;
888bd389b36SDavid du Colombier 	case TFLOAT:
889bd389b36SDavid du Colombier 		if(n->op == OEDEC)
890bd389b36SDavid du Colombier 			v->fval--;
891bd389b36SDavid du Colombier 		else
892bd389b36SDavid du Colombier 			v->fval++;
893bd389b36SDavid du Colombier 		break;
894bd389b36SDavid du Colombier 	default:
895bd389b36SDavid du Colombier 		error("bad type for pre --/++");
896bd389b36SDavid du Colombier 	}
897bd389b36SDavid du Colombier 	res->Store = v->Store;
898219b2ee8SDavid du Colombier }
899219b2ee8SDavid du Colombier 
900219b2ee8SDavid du Colombier void
901219b2ee8SDavid du Colombier opinc(Node *n, Node *res)
902219b2ee8SDavid du Colombier {
903219b2ee8SDavid du Colombier 	Value *v;
904219b2ee8SDavid du Colombier 
905219b2ee8SDavid du Colombier 	chklval(n->left);
906219b2ee8SDavid du Colombier 	v = n->left->sym->v;
907bd389b36SDavid du Colombier 	res->op = OCONST;
908bd389b36SDavid du Colombier 	res->type = v->type;
909bd389b36SDavid du Colombier 	res->Store = v->Store;
910bd389b36SDavid du Colombier 	switch(v->type) {
911bd389b36SDavid du Colombier 	case TINT:
912bd389b36SDavid du Colombier 		if(n->op == OPDEC)
913bd389b36SDavid du Colombier 			v->ival -= fmtsize(v);
914bd389b36SDavid du Colombier 		else
915bd389b36SDavid du Colombier 			v->ival += fmtsize(v);
916bd389b36SDavid du Colombier 		break;
917bd389b36SDavid du Colombier 	case TFLOAT:
918bd389b36SDavid du Colombier 		if(n->op == OPDEC)
919bd389b36SDavid du Colombier 			v->fval--;
920bd389b36SDavid du Colombier 		else
921bd389b36SDavid du Colombier 			v->fval++;
922bd389b36SDavid du Colombier 		break;
923bd389b36SDavid du Colombier 	default:
924bd389b36SDavid du Colombier 		error("bad type for post --/++");
925bd389b36SDavid du Colombier 	}
926219b2ee8SDavid du Colombier }
927219b2ee8SDavid du Colombier 
928219b2ee8SDavid du Colombier void
929219b2ee8SDavid du Colombier ocall(Node *n, Node *res)
930219b2ee8SDavid du Colombier {
931219b2ee8SDavid du Colombier 	Lsym *s;
932219b2ee8SDavid du Colombier 	Rplace *rsav;
933219b2ee8SDavid du Colombier 
934bd389b36SDavid du Colombier 	res->op = OCONST;		/* Default return value */
935bd389b36SDavid du Colombier 	res->type = TLIST;
936bd389b36SDavid du Colombier 	res->l = 0;
937bd389b36SDavid du Colombier 
938219b2ee8SDavid du Colombier 	chklval(n->left);
939219b2ee8SDavid du Colombier 	s = n->left->sym;
940bd389b36SDavid du Colombier 
9410b459c2cSDavid du Colombier 	if(n->builtin && !s->builtin){
9420b459c2cSDavid du Colombier 		error("no builtin %s", s->name);
9430b459c2cSDavid du Colombier 		return;
9440b459c2cSDavid du Colombier 	}
9450b459c2cSDavid du Colombier 	if(s->builtin && (n->builtin || s->proc == 0)) {
946219b2ee8SDavid du Colombier 		(*s->builtin)(res, n->right);
947219b2ee8SDavid du Colombier 		return;
948bd389b36SDavid du Colombier 	}
949bd389b36SDavid du Colombier 	if(s->proc == 0)
950bd389b36SDavid du Colombier 		error("no function %s", s->name);
951bd389b36SDavid du Colombier 
952bd389b36SDavid du Colombier 	rsav = ret;
953219b2ee8SDavid du Colombier 	call(s->name, n->right, s->proc->left, s->proc->right, res);
954bd389b36SDavid du Colombier 	ret = rsav;
955bd389b36SDavid du Colombier }
956219b2ee8SDavid du Colombier 
957219b2ee8SDavid du Colombier void
958219b2ee8SDavid du Colombier ofmt(Node *n, Node *res)
959219b2ee8SDavid du Colombier {
960219b2ee8SDavid du Colombier 	expr(n->left, res);
961219b2ee8SDavid du Colombier 	res->fmt = n->right->ival;
962bd389b36SDavid du Colombier }
963219b2ee8SDavid du Colombier 
964219b2ee8SDavid du Colombier void
965219b2ee8SDavid du Colombier owhat(Node *n, Node *res)
966219b2ee8SDavid du Colombier {
967219b2ee8SDavid du Colombier 	res->op = OCONST;		/* Default return value */
968219b2ee8SDavid du Colombier 	res->type = TLIST;
969219b2ee8SDavid du Colombier 	res->l = 0;
970219b2ee8SDavid du Colombier 	whatis(n->sym);
971219b2ee8SDavid du Colombier }
972219b2ee8SDavid du Colombier 
973219b2ee8SDavid du Colombier void (*expop[])(Node*, Node*) =
974219b2ee8SDavid du Colombier {
975219b2ee8SDavid du Colombier 	[ONAME]		oname,
976219b2ee8SDavid du Colombier 	[OCONST]	oconst,
977219b2ee8SDavid du Colombier 	[OMUL]		omul,
978219b2ee8SDavid du Colombier 	[ODIV]		odiv,
979219b2ee8SDavid du Colombier 	[OMOD]		omod,
980219b2ee8SDavid du Colombier 	[OADD]		oadd,
981219b2ee8SDavid du Colombier 	[OSUB]		osub,
982219b2ee8SDavid du Colombier 	[ORSH]		orsh,
983219b2ee8SDavid du Colombier 	[OLSH]		olsh,
984219b2ee8SDavid du Colombier 	[OLT]		olt,
985219b2ee8SDavid du Colombier 	[OGT]		ogt,
986219b2ee8SDavid du Colombier 	[OLEQ]		oleq,
987219b2ee8SDavid du Colombier 	[OGEQ]		ogeq,
988219b2ee8SDavid du Colombier 	[OEQ]		oeq,
989219b2ee8SDavid du Colombier 	[ONEQ]		oeq,
990219b2ee8SDavid du Colombier 	[OLAND]		oland,
991219b2ee8SDavid du Colombier 	[OXOR]		oxor,
992219b2ee8SDavid du Colombier 	[OLOR]		olor,
993219b2ee8SDavid du Colombier 	[OCAND]		ocand,
994219b2ee8SDavid du Colombier 	[OCOR]		ocor,
995219b2ee8SDavid du Colombier 	[OASGN]		oasgn,
996219b2ee8SDavid du Colombier 	[OINDM]		oindm,
997219b2ee8SDavid du Colombier 	[OEDEC]		oeinc,
998219b2ee8SDavid du Colombier 	[OEINC]		oeinc,
999219b2ee8SDavid du Colombier 	[OPINC]		opinc,
1000219b2ee8SDavid du Colombier 	[OPDEC]		opinc,
1001219b2ee8SDavid du Colombier 	[ONOT]		onot,
1002219b2ee8SDavid du Colombier 	[OIF]		0,
1003219b2ee8SDavid du Colombier 	[ODO]		0,
1004219b2ee8SDavid du Colombier 	[OLIST]		olist,
1005219b2ee8SDavid du Colombier 	[OCALL]		ocall,
1006219b2ee8SDavid du Colombier 	[OCTRUCT]	octruct,
1007219b2ee8SDavid du Colombier 	[OWHILE]	0,
1008219b2ee8SDavid du Colombier 	[OELSE]		0,
1009219b2ee8SDavid du Colombier 	[OHEAD]		ohead,
1010219b2ee8SDavid du Colombier 	[OTAIL]		otail,
1011219b2ee8SDavid du Colombier 	[OAPPEND]	oappend,
1012219b2ee8SDavid du Colombier 	[ORET]		0,
1013219b2ee8SDavid du Colombier 	[OINDEX]	oindex,
1014219b2ee8SDavid du Colombier 	[OINDC]		oindc,
1015219b2ee8SDavid du Colombier 	[ODOT]		odot,
1016219b2ee8SDavid du Colombier 	[OLOCAL]	0,
1017219b2ee8SDavid du Colombier 	[OFRAME]	oframe,
1018219b2ee8SDavid du Colombier 	[OCOMPLEX]	0,
1019219b2ee8SDavid du Colombier 	[ODELETE]	odelete,
1020219b2ee8SDavid du Colombier 	[OCAST]		ocast,
1021219b2ee8SDavid du Colombier 	[OFMT]		ofmt,
1022219b2ee8SDavid du Colombier 	[OEVAL]		oeval,
1023219b2ee8SDavid du Colombier 	[OWHAT]		owhat,
1024219b2ee8SDavid du Colombier };
1025