xref: /plan9/sys/src/cmd/acid/expr.c (revision b249590635b298a2b629c4458908d752eced8f6f)
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
fmtsize(Value * v)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
chklval(Node * lp)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
olist(Node * n,Node * res)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
oeval(Node * n,Node * res)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
ocast(Node * n,Node * res)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
oindm(Node * n,Node * res)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
oindc(Node * n,Node * res)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
oframe(Node * n,Node * res)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
oindex(Node * n,Node * res)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
oappend(Node * n,Node * res)202219b2ee8SDavid du Colombier oappend(Node *n, Node *res)
203219b2ee8SDavid du Colombier {
2047c70c028SDavid du Colombier 	Value *v;
205219b2ee8SDavid du Colombier 	Node r, l;
2067c70c028SDavid 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");
2127c70c028SDavid du Colombier 	empty = (l.l == nil && (n->left->op == ONAME));
213bd389b36SDavid du Colombier 	append(res, &l, &r);
2147c70c028SDavid du Colombier 	if(empty) {
2157c70c028SDavid du Colombier 		v = n->left->sym->v;
2167c70c028SDavid du Colombier 		v->type = res->type;
2177c70c028SDavid du Colombier 		v->Store = res->Store;
2187c70c028SDavid du Colombier 		v->comt = res->comt;
2197c70c028SDavid du Colombier 	}
220219b2ee8SDavid du Colombier }
221219b2ee8SDavid du Colombier 
222219b2ee8SDavid du Colombier void
odelete(Node * n,Node * res)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
ohead(Node * n,Node * res)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
otail(Node * n,Node * res)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
oconst(Node * n,Node * res)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
oname(Node * n,Node * res)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
octruct(Node * n,Node * res)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
oasgn(Node * n,Node * res)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
oadd(Node * n,Node * res)332219b2ee8SDavid du Colombier oadd(Node *n, Node *res)
333219b2ee8SDavid du Colombier {
334219b2ee8SDavid du Colombier 	Node l, r;
335219b2ee8SDavid du Colombier 
3366f222ee0SDavid du Colombier 	if(n->right == nil){		/* unary + */
3376f222ee0SDavid du Colombier 		expr(n->left, res);
3386f222ee0SDavid du Colombier 		return;
3396f222ee0SDavid du Colombier 	}
340219b2ee8SDavid du Colombier 	expr(n->left, &l);
341219b2ee8SDavid du Colombier 	expr(n->right, &r);
342bd389b36SDavid du Colombier 	res->fmt = l.fmt;
343bd389b36SDavid du Colombier 	res->op = OCONST;
344bd389b36SDavid du Colombier 	res->type = TFLOAT;
345bd389b36SDavid du Colombier 	switch(l.type) {
346219b2ee8SDavid du Colombier 	default:
347219b2ee8SDavid du Colombier 		error("bad lhs type +");
348bd389b36SDavid du Colombier 	case TINT:
349bd389b36SDavid du Colombier 		switch(r.type) {
350bd389b36SDavid du Colombier 		case TINT:
351bd389b36SDavid du Colombier 			res->type = TINT;
352bd389b36SDavid du Colombier 			res->ival = l.ival+r.ival;
353bd389b36SDavid du Colombier 			break;
354bd389b36SDavid du Colombier 		case TFLOAT:
355bd389b36SDavid du Colombier 			res->fval = l.ival+r.fval;
356bd389b36SDavid du Colombier 			break;
357219b2ee8SDavid du Colombier 		default:
358219b2ee8SDavid du Colombier 			error("bad rhs type +");
359bd389b36SDavid du Colombier 		}
360bd389b36SDavid du Colombier 		break;
361bd389b36SDavid du Colombier 	case TFLOAT:
362bd389b36SDavid du Colombier 		switch(r.type) {
363bd389b36SDavid du Colombier 		case TINT:
364bd389b36SDavid du Colombier 			res->fval = l.fval+r.ival;
365bd389b36SDavid du Colombier 			break;
366bd389b36SDavid du Colombier 		case TFLOAT:
367bd389b36SDavid du Colombier 			res->fval = l.fval+r.fval;
368bd389b36SDavid du Colombier 			break;
369219b2ee8SDavid du Colombier 		default:
370219b2ee8SDavid du Colombier 			error("bad rhs type +");
371bd389b36SDavid du Colombier 		}
372bd389b36SDavid du Colombier 		break;
373bd389b36SDavid du Colombier 	case TSTRING:
374bd389b36SDavid du Colombier 		if(r.type == TSTRING) {
375bd389b36SDavid du Colombier 			res->type = TSTRING;
376bd389b36SDavid du Colombier 			res->fmt = 's';
377bd389b36SDavid du Colombier 			res->string = stradd(l.string, r.string);
378bd389b36SDavid du Colombier 			break;
379bd389b36SDavid du Colombier 		}
380ab3dc52fSDavid du Colombier 		if(r.type == TINT) {
381ab3dc52fSDavid du Colombier 			res->type = TSTRING;
382ab3dc52fSDavid du Colombier 			res->fmt = 's';
383ab3dc52fSDavid du Colombier 			res->string = straddrune(l.string, r.ival);
384ab3dc52fSDavid du Colombier 			break;
385ab3dc52fSDavid du Colombier 		}
386bd389b36SDavid du Colombier 		error("bad rhs for +");
387bd389b36SDavid du Colombier 	case TLIST:
388bd389b36SDavid du Colombier 		res->type = TLIST;
389bd389b36SDavid du Colombier 		switch(r.type) {
390bd389b36SDavid du Colombier 		case TLIST:
391bd389b36SDavid du Colombier 			res->l = addlist(l.l, r.l);
392bd389b36SDavid du Colombier 			break;
393bd389b36SDavid du Colombier 		default:
394bd389b36SDavid du Colombier 			r.left = 0;
395bd389b36SDavid du Colombier 			r.right = 0;
396bd389b36SDavid du Colombier 			res->l = addlist(l.l, construct(&r));
397bd389b36SDavid du Colombier 			break;
398bd389b36SDavid du Colombier 		}
399bd389b36SDavid du Colombier 	}
400219b2ee8SDavid du Colombier }
401219b2ee8SDavid du Colombier 
402219b2ee8SDavid du Colombier void
osub(Node * n,Node * res)403219b2ee8SDavid du Colombier osub(Node *n, Node *res)
404219b2ee8SDavid du Colombier {
405219b2ee8SDavid du Colombier 	Node l, r;
406219b2ee8SDavid du Colombier 
407219b2ee8SDavid du Colombier 	expr(n->left, &l);
408219b2ee8SDavid du Colombier 	expr(n->right, &r);
409bd389b36SDavid du Colombier 	res->fmt = l.fmt;
410bd389b36SDavid du Colombier 	res->op = OCONST;
411bd389b36SDavid du Colombier 	res->type = TFLOAT;
412bd389b36SDavid du Colombier 	switch(l.type) {
413219b2ee8SDavid du Colombier 	default:
414219b2ee8SDavid du Colombier 		error("bad lhs type -");
415bd389b36SDavid du Colombier 	case TINT:
416bd389b36SDavid du Colombier 		switch(r.type) {
417bd389b36SDavid du Colombier 		case TINT:
418bd389b36SDavid du Colombier 			res->type = TINT;
419bd389b36SDavid du Colombier 			res->ival = l.ival-r.ival;
420bd389b36SDavid du Colombier 			break;
421bd389b36SDavid du Colombier 		case TFLOAT:
422bd389b36SDavid du Colombier 			res->fval = l.ival-r.fval;
423bd389b36SDavid du Colombier 			break;
424219b2ee8SDavid du Colombier 		default:
425219b2ee8SDavid du Colombier 			error("bad rhs type -");
426bd389b36SDavid du Colombier 		}
427bd389b36SDavid du Colombier 		break;
428bd389b36SDavid du Colombier 	case TFLOAT:
429219b2ee8SDavid du Colombier 		switch(r.type) {
430bd389b36SDavid du Colombier 		case TINT:
431bd389b36SDavid du Colombier 			res->fval = l.fval-r.ival;
432bd389b36SDavid du Colombier 			break;
433bd389b36SDavid du Colombier 		case TFLOAT:
434bd389b36SDavid du Colombier 			res->fval = l.fval-r.fval;
435bd389b36SDavid du Colombier 			break;
436219b2ee8SDavid du Colombier 		default:
437219b2ee8SDavid du Colombier 			error("bad rhs type -");
438bd389b36SDavid du Colombier 		}
439bd389b36SDavid du Colombier 		break;
440bd389b36SDavid du Colombier 	}
441219b2ee8SDavid du Colombier }
442219b2ee8SDavid du Colombier 
443219b2ee8SDavid du Colombier void
omul(Node * n,Node * res)444219b2ee8SDavid du Colombier omul(Node *n, Node *res)
445219b2ee8SDavid du Colombier {
446219b2ee8SDavid du Colombier 	Node l, r;
447219b2ee8SDavid du Colombier 
448219b2ee8SDavid du Colombier 	expr(n->left, &l);
449219b2ee8SDavid du Colombier 	expr(n->right, &r);
450bd389b36SDavid du Colombier 	res->fmt = l.fmt;
451bd389b36SDavid du Colombier 	res->op = OCONST;
452bd389b36SDavid du Colombier 	res->type = TFLOAT;
453bd389b36SDavid du Colombier 	switch(l.type) {
454219b2ee8SDavid du Colombier 	default:
455219b2ee8SDavid du Colombier 		error("bad lhs type *");
456bd389b36SDavid du Colombier 	case TINT:
457bd389b36SDavid du Colombier 		switch(r.type) {
458bd389b36SDavid du Colombier 		case TINT:
459bd389b36SDavid du Colombier 			res->type = TINT;
460bd389b36SDavid du Colombier 			res->ival = l.ival*r.ival;
461bd389b36SDavid du Colombier 			break;
462bd389b36SDavid du Colombier 		case TFLOAT:
463bd389b36SDavid du Colombier 			res->fval = l.ival*r.fval;
464bd389b36SDavid du Colombier 			break;
465219b2ee8SDavid du Colombier 		default:
466219b2ee8SDavid du Colombier 			error("bad rhs type *");
467bd389b36SDavid du Colombier 		}
468bd389b36SDavid du Colombier 		break;
469bd389b36SDavid du Colombier 	case TFLOAT:
470219b2ee8SDavid du Colombier 		switch(r.type) {
471bd389b36SDavid du Colombier 		case TINT:
472bd389b36SDavid du Colombier 			res->fval = l.fval*r.ival;
473bd389b36SDavid du Colombier 			break;
474bd389b36SDavid du Colombier 		case TFLOAT:
475bd389b36SDavid du Colombier 			res->fval = l.fval*r.fval;
476bd389b36SDavid du Colombier 			break;
477219b2ee8SDavid du Colombier 		default:
478219b2ee8SDavid du Colombier 			error("bad rhs type *");
479bd389b36SDavid du Colombier 		}
480bd389b36SDavid du Colombier 		break;
481bd389b36SDavid du Colombier 	}
482219b2ee8SDavid du Colombier }
483219b2ee8SDavid du Colombier 
484219b2ee8SDavid du Colombier void
odiv(Node * n,Node * res)485219b2ee8SDavid du Colombier odiv(Node *n, Node *res)
486219b2ee8SDavid du Colombier {
487219b2ee8SDavid du Colombier 	Node l, r;
488219b2ee8SDavid du Colombier 
489219b2ee8SDavid du Colombier 	expr(n->left, &l);
490219b2ee8SDavid du Colombier 	expr(n->right, &r);
491bd389b36SDavid du Colombier 	res->fmt = l.fmt;
492bd389b36SDavid du Colombier 	res->op = OCONST;
493bd389b36SDavid du Colombier 	res->type = TFLOAT;
494bd389b36SDavid du Colombier 	switch(l.type) {
495219b2ee8SDavid du Colombier 	default:
496219b2ee8SDavid du Colombier 		error("bad lhs type /");
497bd389b36SDavid du Colombier 	case TINT:
498bd389b36SDavid du Colombier 		switch(r.type) {
499bd389b36SDavid du Colombier 		case TINT:
500bd389b36SDavid du Colombier 			res->type = TINT;
501219b2ee8SDavid du Colombier 			if(r.ival == 0)
502219b2ee8SDavid du Colombier 				error("zero divide");
503bd389b36SDavid du Colombier 			res->ival = l.ival/r.ival;
504bd389b36SDavid du Colombier 			break;
505bd389b36SDavid du Colombier 		case TFLOAT:
506219b2ee8SDavid du Colombier 			if(r.fval == 0)
507219b2ee8SDavid du Colombier 				error("zero divide");
508bd389b36SDavid du Colombier 			res->fval = l.ival/r.fval;
509bd389b36SDavid du Colombier 			break;
510219b2ee8SDavid du Colombier 		default:
511219b2ee8SDavid du Colombier 			error("bad rhs type /");
512bd389b36SDavid du Colombier 		}
513bd389b36SDavid du Colombier 		break;
514bd389b36SDavid du Colombier 	case TFLOAT:
515219b2ee8SDavid du Colombier 		switch(r.type) {
516bd389b36SDavid du Colombier 		case TINT:
517bd389b36SDavid du Colombier 			res->fval = l.fval/r.ival;
518bd389b36SDavid du Colombier 			break;
519bd389b36SDavid du Colombier 		case TFLOAT:
520bd389b36SDavid du Colombier 			res->fval = l.fval/r.fval;
521bd389b36SDavid du Colombier 			break;
522219b2ee8SDavid du Colombier 		default:
523219b2ee8SDavid du Colombier 			error("bad rhs type /");
524bd389b36SDavid du Colombier 		}
525bd389b36SDavid du Colombier 		break;
526bd389b36SDavid du Colombier 	}
527219b2ee8SDavid du Colombier }
528219b2ee8SDavid du Colombier 
529219b2ee8SDavid du Colombier void
omod(Node * n,Node * res)530219b2ee8SDavid du Colombier omod(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
olsh(Node * n,Node * res)545219b2ee8SDavid du Colombier olsh(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 <<");
556bd389b36SDavid du Colombier 	res->ival = l.ival<<r.ival;
557219b2ee8SDavid du Colombier }
558219b2ee8SDavid du Colombier 
559219b2ee8SDavid du Colombier void
orsh(Node * n,Node * res)560219b2ee8SDavid du Colombier orsh(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);
566bd389b36SDavid du Colombier 	res->fmt = l.fmt;
567bd389b36SDavid du Colombier 	res->op = OCONST;
568bd389b36SDavid du Colombier 	res->type = TINT;
569bd389b36SDavid du Colombier 	if(l.type != TINT || r.type != TINT)
570bd389b36SDavid du Colombier 		error("bad expr type >>");
5714de34a7eSDavid du Colombier 	res->ival = (uvlong)l.ival>>r.ival;
572219b2ee8SDavid du Colombier }
573219b2ee8SDavid du Colombier 
574219b2ee8SDavid du Colombier void
olt(Node * n,Node * res)575219b2ee8SDavid du Colombier olt(Node *n, Node *res)
576219b2ee8SDavid du Colombier {
577219b2ee8SDavid du Colombier 	Node l, r;
578219b2ee8SDavid du Colombier 
579219b2ee8SDavid du Colombier 	expr(n->left, &l);
580219b2ee8SDavid du Colombier 	expr(n->right, &r);
581219b2ee8SDavid du Colombier 
582bd389b36SDavid du Colombier 	res->fmt = l.fmt;
583bd389b36SDavid du Colombier 	res->op = OCONST;
584bd389b36SDavid du Colombier 	res->type = TINT;
585bd389b36SDavid du Colombier 	switch(l.type) {
586219b2ee8SDavid du Colombier 	default:
587219b2ee8SDavid du Colombier 		error("bad lhs type <");
588bd389b36SDavid du Colombier 	case TINT:
589bd389b36SDavid du Colombier 		switch(r.type) {
590bd389b36SDavid du Colombier 		case TINT:
591bd389b36SDavid du Colombier 			res->ival = l.ival < r.ival;
592bd389b36SDavid du Colombier 			break;
593bd389b36SDavid du Colombier 		case TFLOAT:
594bd389b36SDavid du Colombier 			res->ival = l.ival < r.fval;
595bd389b36SDavid du Colombier 			break;
596219b2ee8SDavid du Colombier 		default:
597219b2ee8SDavid du Colombier 			error("bad rhs type <");
598bd389b36SDavid du Colombier 		}
599bd389b36SDavid du Colombier 		break;
600bd389b36SDavid du Colombier 	case TFLOAT:
601219b2ee8SDavid du Colombier 		switch(r.type) {
602bd389b36SDavid du Colombier 		case TINT:
603bd389b36SDavid du Colombier 			res->ival = l.fval < r.ival;
604bd389b36SDavid du Colombier 			break;
605bd389b36SDavid du Colombier 		case TFLOAT:
606bd389b36SDavid du Colombier 			res->ival = l.fval < r.fval;
607bd389b36SDavid du Colombier 			break;
608219b2ee8SDavid du Colombier 		default:
609219b2ee8SDavid du Colombier 			error("bad rhs type <");
610bd389b36SDavid du Colombier 		}
611bd389b36SDavid du Colombier 		break;
612bd389b36SDavid du Colombier 	}
613219b2ee8SDavid du Colombier }
614219b2ee8SDavid du Colombier 
615219b2ee8SDavid du Colombier void
ogt(Node * n,Node * res)616219b2ee8SDavid du Colombier ogt(Node *n, Node *res)
617219b2ee8SDavid du Colombier {
618219b2ee8SDavid du Colombier 	Node l, r;
619219b2ee8SDavid du Colombier 
620219b2ee8SDavid du Colombier 	expr(n->left, &l);
621219b2ee8SDavid du Colombier 	expr(n->right, &r);
622bd389b36SDavid du Colombier 	res->fmt = 'D';
623bd389b36SDavid du Colombier 	res->op = OCONST;
624bd389b36SDavid du Colombier 	res->type = TINT;
625bd389b36SDavid du Colombier 	switch(l.type) {
626219b2ee8SDavid du Colombier 	default:
627219b2ee8SDavid du Colombier 		error("bad lhs type >");
628bd389b36SDavid du Colombier 	case TINT:
629bd389b36SDavid du Colombier 		switch(r.type) {
630bd389b36SDavid du Colombier 		case TINT:
631bd389b36SDavid du Colombier 			res->ival = l.ival > r.ival;
632bd389b36SDavid du Colombier 			break;
633bd389b36SDavid du Colombier 		case TFLOAT:
634bd389b36SDavid du Colombier 			res->ival = l.ival > r.fval;
635bd389b36SDavid du Colombier 			break;
636219b2ee8SDavid du Colombier 		default:
637219b2ee8SDavid du Colombier 			error("bad rhs type >");
638bd389b36SDavid du Colombier 		}
639bd389b36SDavid du Colombier 		break;
640bd389b36SDavid du Colombier 	case TFLOAT:
641219b2ee8SDavid du Colombier 		switch(r.type) {
642bd389b36SDavid du Colombier 		case TINT:
643bd389b36SDavid du Colombier 			res->ival = l.fval > r.ival;
644bd389b36SDavid du Colombier 			break;
645bd389b36SDavid du Colombier 		case TFLOAT:
646bd389b36SDavid du Colombier 			res->ival = l.fval > r.fval;
647bd389b36SDavid du Colombier 			break;
648219b2ee8SDavid du Colombier 		default:
649219b2ee8SDavid du Colombier 			error("bad rhs type >");
650bd389b36SDavid du Colombier 		}
651bd389b36SDavid du Colombier 		break;
652bd389b36SDavid du Colombier 	}
653219b2ee8SDavid du Colombier }
654219b2ee8SDavid du Colombier 
655219b2ee8SDavid du Colombier void
oleq(Node * n,Node * res)656219b2ee8SDavid du Colombier oleq(Node *n, Node *res)
657219b2ee8SDavid du Colombier {
658219b2ee8SDavid du Colombier 	Node l, r;
659219b2ee8SDavid du Colombier 
660219b2ee8SDavid du Colombier 	expr(n->left, &l);
661219b2ee8SDavid du Colombier 	expr(n->right, &r);
662bd389b36SDavid du Colombier 	res->fmt = 'D';
663bd389b36SDavid du Colombier 	res->op = OCONST;
664bd389b36SDavid du Colombier 	res->type = TINT;
665bd389b36SDavid du Colombier 	switch(l.type) {
666219b2ee8SDavid du Colombier 	default:
667219b2ee8SDavid du Colombier 		error("bad expr type <=");
668bd389b36SDavid du Colombier 	case TINT:
669bd389b36SDavid du Colombier 		switch(r.type) {
670bd389b36SDavid du Colombier 		case TINT:
671bd389b36SDavid du Colombier 			res->ival = l.ival <= r.ival;
672bd389b36SDavid du Colombier 			break;
673bd389b36SDavid du Colombier 		case TFLOAT:
674bd389b36SDavid du Colombier 			res->ival = l.ival <= r.fval;
675bd389b36SDavid du Colombier 			break;
676219b2ee8SDavid du Colombier 		default:
677bd389b36SDavid du Colombier 			error("bad expr type <=");
678bd389b36SDavid du Colombier 		}
679bd389b36SDavid du Colombier 		break;
680bd389b36SDavid du Colombier 	case TFLOAT:
681219b2ee8SDavid du Colombier 		switch(r.type) {
682bd389b36SDavid du Colombier 		case TINT:
683bd389b36SDavid du Colombier 			res->ival = l.fval <= r.ival;
684bd389b36SDavid du Colombier 			break;
685bd389b36SDavid du Colombier 		case TFLOAT:
686bd389b36SDavid du Colombier 			res->ival = l.fval <= r.fval;
687bd389b36SDavid du Colombier 			break;
688219b2ee8SDavid du Colombier 		default:
689bd389b36SDavid du Colombier 			error("bad expr type <=");
690bd389b36SDavid du Colombier 		}
691bd389b36SDavid du Colombier 		break;
692bd389b36SDavid du Colombier 	}
693219b2ee8SDavid du Colombier }
694219b2ee8SDavid du Colombier 
695219b2ee8SDavid du Colombier void
ogeq(Node * n,Node * res)696219b2ee8SDavid du Colombier ogeq(Node *n, Node *res)
697219b2ee8SDavid du Colombier {
698219b2ee8SDavid du Colombier 	Node l, r;
699219b2ee8SDavid du Colombier 
700219b2ee8SDavid du Colombier 	expr(n->left, &l);
701219b2ee8SDavid du Colombier 	expr(n->right, &r);
702bd389b36SDavid du Colombier 	res->fmt = 'D';
703bd389b36SDavid du Colombier 	res->op = OCONST;
704bd389b36SDavid du Colombier 	res->type = TINT;
705bd389b36SDavid du Colombier 	switch(l.type) {
706219b2ee8SDavid du Colombier 	default:
707219b2ee8SDavid du Colombier 		error("bad lhs type >=");
708bd389b36SDavid du Colombier 	case TINT:
709bd389b36SDavid du Colombier 		switch(r.type) {
710bd389b36SDavid du Colombier 		case TINT:
711bd389b36SDavid du Colombier 			res->ival = l.ival >= r.ival;
712bd389b36SDavid du Colombier 			break;
713bd389b36SDavid du Colombier 		case TFLOAT:
714bd389b36SDavid du Colombier 			res->ival = l.ival >= r.fval;
715bd389b36SDavid du Colombier 			break;
716219b2ee8SDavid du Colombier 		default:
717219b2ee8SDavid du Colombier 			error("bad rhs type >=");
718bd389b36SDavid du Colombier 		}
719bd389b36SDavid du Colombier 		break;
720bd389b36SDavid du Colombier 	case TFLOAT:
721219b2ee8SDavid du Colombier 		switch(r.type) {
722bd389b36SDavid du Colombier 		case TINT:
723bd389b36SDavid du Colombier 			res->ival = l.fval >= r.ival;
724bd389b36SDavid du Colombier 			break;
725bd389b36SDavid du Colombier 		case TFLOAT:
726bd389b36SDavid du Colombier 			res->ival = l.fval >= r.fval;
727bd389b36SDavid du Colombier 			break;
728219b2ee8SDavid du Colombier 		default:
729219b2ee8SDavid du Colombier 			error("bad rhs type >=");
730bd389b36SDavid du Colombier 		}
731bd389b36SDavid du Colombier 		break;
732bd389b36SDavid du Colombier 	}
733219b2ee8SDavid du Colombier }
734219b2ee8SDavid du Colombier 
735219b2ee8SDavid du Colombier void
oeq(Node * n,Node * res)736219b2ee8SDavid du Colombier oeq(Node *n, Node *res)
737219b2ee8SDavid du Colombier {
738219b2ee8SDavid du Colombier 	Node l, r;
739219b2ee8SDavid du Colombier 
740219b2ee8SDavid du Colombier 	expr(n->left, &l);
741219b2ee8SDavid du Colombier 	expr(n->right, &r);
742bd389b36SDavid du Colombier 	res->fmt = 'D';
743bd389b36SDavid du Colombier 	res->op = OCONST;
744bd389b36SDavid du Colombier 	res->type = TINT;
745219b2ee8SDavid du Colombier 	res->ival = 0;
746bd389b36SDavid du Colombier 	switch(l.type) {
747219b2ee8SDavid du Colombier 	default:
748219b2ee8SDavid du Colombier 		break;
749bd389b36SDavid du Colombier 	case TINT:
750bd389b36SDavid du Colombier 		switch(r.type) {
751bd389b36SDavid du Colombier 		case TINT:
752bd389b36SDavid du Colombier 			res->ival = l.ival == r.ival;
753bd389b36SDavid du Colombier 			break;
754bd389b36SDavid du Colombier 		case TFLOAT:
755bd389b36SDavid du Colombier 			res->ival = l.ival == r.fval;
756bd389b36SDavid du Colombier 			break;
757219b2ee8SDavid du Colombier 		default:
758219b2ee8SDavid du Colombier 			break;
759bd389b36SDavid du Colombier 		}
760bd389b36SDavid du Colombier 		break;
761bd389b36SDavid du Colombier 	case TFLOAT:
762219b2ee8SDavid du Colombier 		switch(r.type) {
763bd389b36SDavid du Colombier 		case TINT:
764bd389b36SDavid du Colombier 			res->ival = l.fval == r.ival;
765bd389b36SDavid du Colombier 			break;
766bd389b36SDavid du Colombier 		case TFLOAT:
767bd389b36SDavid du Colombier 			res->ival = l.fval == r.fval;
768bd389b36SDavid du Colombier 			break;
769219b2ee8SDavid du Colombier 		default:
770219b2ee8SDavid du Colombier 			break;
771bd389b36SDavid du Colombier 		}
772bd389b36SDavid du Colombier 		break;
773bd389b36SDavid du Colombier 	case TSTRING:
774bd389b36SDavid du Colombier 		if(r.type == TSTRING) {
775bd389b36SDavid du Colombier 			res->ival = scmp(r.string, l.string);
776bd389b36SDavid du Colombier 			break;
777bd389b36SDavid du Colombier 		}
778219b2ee8SDavid du Colombier 		break;
779bd389b36SDavid du Colombier 	case TLIST:
780bd389b36SDavid du Colombier 		if(r.type == TLIST) {
781bd389b36SDavid du Colombier 			res->ival = listcmp(l.l, r.l);
782bd389b36SDavid du Colombier 			break;
783bd389b36SDavid du Colombier 		}
784bd389b36SDavid du Colombier 		break;
785bd389b36SDavid du Colombier 	}
786219b2ee8SDavid du Colombier 	if(n->op == ONEQ)
787219b2ee8SDavid du Colombier 		res->ival = !res->ival;
788bd389b36SDavid du Colombier }
789219b2ee8SDavid du Colombier 
790219b2ee8SDavid du Colombier 
791219b2ee8SDavid du Colombier void
oland(Node * n,Node * res)792219b2ee8SDavid du Colombier oland(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
oxor(Node * n,Node * res)807219b2ee8SDavid du Colombier oxor(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
olor(Node * n,Node * res)822219b2ee8SDavid du Colombier olor(Node *n, Node *res)
823219b2ee8SDavid du Colombier {
824219b2ee8SDavid du Colombier 	Node l, r;
825219b2ee8SDavid du Colombier 
826219b2ee8SDavid du Colombier 	expr(n->left, &l);
827219b2ee8SDavid du Colombier 	expr(n->right, &r);
828bd389b36SDavid du Colombier 	res->fmt = l.fmt;
829bd389b36SDavid du Colombier 	res->op = OCONST;
830bd389b36SDavid du Colombier 	res->type = TINT;
831bd389b36SDavid du Colombier 	if(l.type != TINT || r.type != TINT)
832bd389b36SDavid du Colombier 		error("bad expr type |");
833bd389b36SDavid du Colombier 	res->ival = l.ival|r.ival;
834219b2ee8SDavid du Colombier }
835219b2ee8SDavid du Colombier 
836219b2ee8SDavid du Colombier void
ocand(Node * n,Node * res)837219b2ee8SDavid du Colombier ocand(Node *n, Node *res)
838219b2ee8SDavid du Colombier {
839219b2ee8SDavid du Colombier 	Node l, r;
840219b2ee8SDavid du Colombier 
841bd389b36SDavid du Colombier 	res->op = OCONST;
842bd389b36SDavid du Colombier 	res->type = TINT;
843219b2ee8SDavid du Colombier 	res->ival = 0;
844*b2495906SDavid du Colombier 	res->fmt = 'D';
845219b2ee8SDavid du Colombier 	expr(n->left, &l);
846219b2ee8SDavid du Colombier 	if(bool(&l) == 0)
847219b2ee8SDavid du Colombier 		return;
848219b2ee8SDavid du Colombier 	expr(n->right, &r);
849219b2ee8SDavid du Colombier 	if(bool(&r) == 0)
850219b2ee8SDavid du Colombier 		return;
851219b2ee8SDavid du Colombier 	res->ival = 1;
852219b2ee8SDavid du Colombier }
853219b2ee8SDavid du Colombier 
854219b2ee8SDavid du Colombier void
onot(Node * n,Node * res)855219b2ee8SDavid du Colombier onot(Node *n, Node *res)
856219b2ee8SDavid du Colombier {
857219b2ee8SDavid du Colombier 	Node l;
858219b2ee8SDavid du Colombier 
859bd389b36SDavid du Colombier 	res->op = OCONST;
860bd389b36SDavid du Colombier 	res->type = TINT;
861219b2ee8SDavid du Colombier 	res->ival = 0;
862219b2ee8SDavid du Colombier 	expr(n->left, &l);
863*b2495906SDavid du Colombier 	res->fmt = l.fmt;
864219b2ee8SDavid du Colombier 	if(bool(&l) == 0)
865219b2ee8SDavid du Colombier 		res->ival = 1;
866219b2ee8SDavid du Colombier }
867219b2ee8SDavid du Colombier 
868219b2ee8SDavid du Colombier void
ocor(Node * n,Node * res)869219b2ee8SDavid du Colombier ocor(Node *n, Node *res)
870219b2ee8SDavid du Colombier {
871219b2ee8SDavid du Colombier 	Node l, r;
872219b2ee8SDavid du Colombier 
873219b2ee8SDavid du Colombier 	res->op = OCONST;
874219b2ee8SDavid du Colombier 	res->type = TINT;
875219b2ee8SDavid du Colombier 	res->ival = 0;
876*b2495906SDavid du Colombier 	res->fmt = 'D';
877219b2ee8SDavid du Colombier 	expr(n->left, &l);
878219b2ee8SDavid du Colombier 	if(bool(&l)) {
879219b2ee8SDavid du Colombier 		res->ival = 1;
880219b2ee8SDavid du Colombier 		return;
881219b2ee8SDavid du Colombier 	}
882219b2ee8SDavid du Colombier 	expr(n->right, &r);
883219b2ee8SDavid du Colombier 	if(bool(&r)) {
884219b2ee8SDavid du Colombier 		res->ival = 1;
885219b2ee8SDavid du Colombier 		return;
886219b2ee8SDavid du Colombier 	}
887219b2ee8SDavid du Colombier }
888219b2ee8SDavid du Colombier 
889219b2ee8SDavid du Colombier void
oeinc(Node * n,Node * res)890219b2ee8SDavid du Colombier oeinc(Node *n, Node *res)
891219b2ee8SDavid du Colombier {
892219b2ee8SDavid du Colombier 	Value *v;
893219b2ee8SDavid du Colombier 
894219b2ee8SDavid du Colombier 	chklval(n->left);
895219b2ee8SDavid du Colombier 	v = n->left->sym->v;
896bd389b36SDavid du Colombier 	res->op = OCONST;
897bd389b36SDavid du Colombier 	res->type = v->type;
898bd389b36SDavid du Colombier 	switch(v->type) {
899bd389b36SDavid du Colombier 	case TINT:
900bd389b36SDavid du Colombier 		if(n->op == OEDEC)
901bd389b36SDavid du Colombier 			v->ival -= fmtsize(v);
902bd389b36SDavid du Colombier 		else
903bd389b36SDavid du Colombier 			v->ival += fmtsize(v);
904bd389b36SDavid du Colombier 		break;
905bd389b36SDavid du Colombier 	case TFLOAT:
906bd389b36SDavid du Colombier 		if(n->op == OEDEC)
907bd389b36SDavid du Colombier 			v->fval--;
908bd389b36SDavid du Colombier 		else
909bd389b36SDavid du Colombier 			v->fval++;
910bd389b36SDavid du Colombier 		break;
911bd389b36SDavid du Colombier 	default:
912bd389b36SDavid du Colombier 		error("bad type for pre --/++");
913bd389b36SDavid du Colombier 	}
914bd389b36SDavid du Colombier 	res->Store = v->Store;
915219b2ee8SDavid du Colombier }
916219b2ee8SDavid du Colombier 
917219b2ee8SDavid du Colombier void
opinc(Node * n,Node * res)918219b2ee8SDavid du Colombier opinc(Node *n, Node *res)
919219b2ee8SDavid du Colombier {
920219b2ee8SDavid du Colombier 	Value *v;
921219b2ee8SDavid du Colombier 
922219b2ee8SDavid du Colombier 	chklval(n->left);
923219b2ee8SDavid du Colombier 	v = n->left->sym->v;
924bd389b36SDavid du Colombier 	res->op = OCONST;
925bd389b36SDavid du Colombier 	res->type = v->type;
926bd389b36SDavid du Colombier 	res->Store = v->Store;
927bd389b36SDavid du Colombier 	switch(v->type) {
928bd389b36SDavid du Colombier 	case TINT:
929bd389b36SDavid du Colombier 		if(n->op == OPDEC)
930bd389b36SDavid du Colombier 			v->ival -= fmtsize(v);
931bd389b36SDavid du Colombier 		else
932bd389b36SDavid du Colombier 			v->ival += fmtsize(v);
933bd389b36SDavid du Colombier 		break;
934bd389b36SDavid du Colombier 	case TFLOAT:
935bd389b36SDavid du Colombier 		if(n->op == OPDEC)
936bd389b36SDavid du Colombier 			v->fval--;
937bd389b36SDavid du Colombier 		else
938bd389b36SDavid du Colombier 			v->fval++;
939bd389b36SDavid du Colombier 		break;
940bd389b36SDavid du Colombier 	default:
941bd389b36SDavid du Colombier 		error("bad type for post --/++");
942bd389b36SDavid du Colombier 	}
943219b2ee8SDavid du Colombier }
944219b2ee8SDavid du Colombier 
945219b2ee8SDavid du Colombier void
ocall(Node * n,Node * res)946219b2ee8SDavid du Colombier ocall(Node *n, Node *res)
947219b2ee8SDavid du Colombier {
948219b2ee8SDavid du Colombier 	Lsym *s;
949219b2ee8SDavid du Colombier 	Rplace *rsav;
950219b2ee8SDavid du Colombier 
951bd389b36SDavid du Colombier 	res->op = OCONST;		/* Default return value */
952bd389b36SDavid du Colombier 	res->type = TLIST;
953bd389b36SDavid du Colombier 	res->l = 0;
954bd389b36SDavid du Colombier 
955219b2ee8SDavid du Colombier 	chklval(n->left);
956219b2ee8SDavid du Colombier 	s = n->left->sym;
957bd389b36SDavid du Colombier 
9580b459c2cSDavid du Colombier 	if(n->builtin && !s->builtin){
9590b459c2cSDavid du Colombier 		error("no builtin %s", s->name);
9600b459c2cSDavid du Colombier 		return;
9610b459c2cSDavid du Colombier 	}
9620b459c2cSDavid du Colombier 	if(s->builtin && (n->builtin || s->proc == 0)) {
963219b2ee8SDavid du Colombier 		(*s->builtin)(res, n->right);
964219b2ee8SDavid du Colombier 		return;
965bd389b36SDavid du Colombier 	}
966bd389b36SDavid du Colombier 	if(s->proc == 0)
967bd389b36SDavid du Colombier 		error("no function %s", s->name);
968bd389b36SDavid du Colombier 
969bd389b36SDavid du Colombier 	rsav = ret;
970219b2ee8SDavid du Colombier 	call(s->name, n->right, s->proc->left, s->proc->right, res);
971bd389b36SDavid du Colombier 	ret = rsav;
972bd389b36SDavid du Colombier }
973219b2ee8SDavid du Colombier 
974219b2ee8SDavid du Colombier void
ofmt(Node * n,Node * res)975219b2ee8SDavid du Colombier ofmt(Node *n, Node *res)
976219b2ee8SDavid du Colombier {
977219b2ee8SDavid du Colombier 	expr(n->left, res);
978219b2ee8SDavid du Colombier 	res->fmt = n->right->ival;
979bd389b36SDavid du Colombier }
980219b2ee8SDavid du Colombier 
981219b2ee8SDavid du Colombier void
owhat(Node * n,Node * res)982219b2ee8SDavid du Colombier owhat(Node *n, Node *res)
983219b2ee8SDavid du Colombier {
984219b2ee8SDavid du Colombier 	res->op = OCONST;		/* Default return value */
985219b2ee8SDavid du Colombier 	res->type = TLIST;
986219b2ee8SDavid du Colombier 	res->l = 0;
987219b2ee8SDavid du Colombier 	whatis(n->sym);
988219b2ee8SDavid du Colombier }
989219b2ee8SDavid du Colombier 
990219b2ee8SDavid du Colombier void (*expop[])(Node*, Node*) =
991219b2ee8SDavid du Colombier {
992219b2ee8SDavid du Colombier 	[ONAME]		oname,
993219b2ee8SDavid du Colombier 	[OCONST]	oconst,
994219b2ee8SDavid du Colombier 	[OMUL]		omul,
995219b2ee8SDavid du Colombier 	[ODIV]		odiv,
996219b2ee8SDavid du Colombier 	[OMOD]		omod,
997219b2ee8SDavid du Colombier 	[OADD]		oadd,
998219b2ee8SDavid du Colombier 	[OSUB]		osub,
999219b2ee8SDavid du Colombier 	[ORSH]		orsh,
1000219b2ee8SDavid du Colombier 	[OLSH]		olsh,
1001219b2ee8SDavid du Colombier 	[OLT]		olt,
1002219b2ee8SDavid du Colombier 	[OGT]		ogt,
1003219b2ee8SDavid du Colombier 	[OLEQ]		oleq,
1004219b2ee8SDavid du Colombier 	[OGEQ]		ogeq,
1005219b2ee8SDavid du Colombier 	[OEQ]		oeq,
1006219b2ee8SDavid du Colombier 	[ONEQ]		oeq,
1007219b2ee8SDavid du Colombier 	[OLAND]		oland,
1008219b2ee8SDavid du Colombier 	[OXOR]		oxor,
1009219b2ee8SDavid du Colombier 	[OLOR]		olor,
1010219b2ee8SDavid du Colombier 	[OCAND]		ocand,
1011219b2ee8SDavid du Colombier 	[OCOR]		ocor,
1012219b2ee8SDavid du Colombier 	[OASGN]		oasgn,
1013219b2ee8SDavid du Colombier 	[OINDM]		oindm,
1014219b2ee8SDavid du Colombier 	[OEDEC]		oeinc,
1015219b2ee8SDavid du Colombier 	[OEINC]		oeinc,
1016219b2ee8SDavid du Colombier 	[OPINC]		opinc,
1017219b2ee8SDavid du Colombier 	[OPDEC]		opinc,
1018219b2ee8SDavid du Colombier 	[ONOT]		onot,
1019219b2ee8SDavid du Colombier 	[OIF]		0,
1020219b2ee8SDavid du Colombier 	[ODO]		0,
1021219b2ee8SDavid du Colombier 	[OLIST]		olist,
1022219b2ee8SDavid du Colombier 	[OCALL]		ocall,
1023219b2ee8SDavid du Colombier 	[OCTRUCT]	octruct,
1024219b2ee8SDavid du Colombier 	[OWHILE]	0,
1025219b2ee8SDavid du Colombier 	[OELSE]		0,
1026219b2ee8SDavid du Colombier 	[OHEAD]		ohead,
1027219b2ee8SDavid du Colombier 	[OTAIL]		otail,
1028219b2ee8SDavid du Colombier 	[OAPPEND]	oappend,
1029219b2ee8SDavid du Colombier 	[ORET]		0,
1030219b2ee8SDavid du Colombier 	[OINDEX]	oindex,
1031219b2ee8SDavid du Colombier 	[OINDC]		oindc,
1032219b2ee8SDavid du Colombier 	[ODOT]		odot,
1033219b2ee8SDavid du Colombier 	[OLOCAL]	0,
1034219b2ee8SDavid du Colombier 	[OFRAME]	oframe,
1035219b2ee8SDavid du Colombier 	[OCOMPLEX]	0,
1036219b2ee8SDavid du Colombier 	[ODELETE]	odelete,
1037219b2ee8SDavid du Colombier 	[OCAST]		ocast,
1038219b2ee8SDavid du Colombier 	[OFMT]		ofmt,
1039219b2ee8SDavid du Colombier 	[OEVAL]		oeval,
1040219b2ee8SDavid du Colombier 	[OWHAT]		owhat,
1041219b2ee8SDavid du Colombier };
1042