xref: /plan9-contrib/sys/src/cmd/hoc/code.c (revision 3e12c5d1bb89fc02707907988834ef147769ddaf)
1*3e12c5d1SDavid du Colombier #include <u.h>
2*3e12c5d1SDavid du Colombier #include <libc.h>
3*3e12c5d1SDavid du Colombier #include <bio.h>
4*3e12c5d1SDavid du Colombier #include "hoc.h"
5*3e12c5d1SDavid du Colombier #include "y.tab.h"
6*3e12c5d1SDavid du Colombier 
7*3e12c5d1SDavid du Colombier #define	NSTACK	256
8*3e12c5d1SDavid du Colombier 
9*3e12c5d1SDavid du Colombier static Datum stack[NSTACK];	/* the stack */
10*3e12c5d1SDavid du Colombier static Datum *stackp;		/* next free spot on stack */
11*3e12c5d1SDavid du Colombier 
12*3e12c5d1SDavid du Colombier #define	NPROG	2000
13*3e12c5d1SDavid du Colombier Inst	prog[NPROG];	/* the machine */
14*3e12c5d1SDavid du Colombier Inst	*progp;		/* next free spot for code generation */
15*3e12c5d1SDavid du Colombier Inst	*pc;		/* program counter during execution */
16*3e12c5d1SDavid du Colombier Inst	*progbase = prog; /* start of current subprogram */
17*3e12c5d1SDavid du Colombier int	returning;	/* 1 if return stmt seen */
18*3e12c5d1SDavid du Colombier 
19*3e12c5d1SDavid du Colombier typedef struct Frame {	/* proc/func call stack frame */
20*3e12c5d1SDavid du Colombier 	Symbol	*sp;	/* symbol table entry */
21*3e12c5d1SDavid du Colombier 	Inst	*retpc;	/* where to resume after return */
22*3e12c5d1SDavid du Colombier 	Datum	*argn;	/* n-th argument on stack */
23*3e12c5d1SDavid du Colombier 	int	nargs;	/* number of arguments */
24*3e12c5d1SDavid du Colombier } Frame;
25*3e12c5d1SDavid du Colombier #define	NFRAME	100
26*3e12c5d1SDavid du Colombier Frame	frame[NFRAME];
27*3e12c5d1SDavid du Colombier Frame	*fp;		/* frame pointer */
28*3e12c5d1SDavid du Colombier 
29*3e12c5d1SDavid du Colombier void
30*3e12c5d1SDavid du Colombier initcode(void)
31*3e12c5d1SDavid du Colombier {
32*3e12c5d1SDavid du Colombier 	progp = progbase;
33*3e12c5d1SDavid du Colombier 	stackp = stack;
34*3e12c5d1SDavid du Colombier 	fp = frame;
35*3e12c5d1SDavid du Colombier 	returning = 0;
36*3e12c5d1SDavid du Colombier }
37*3e12c5d1SDavid du Colombier 
38*3e12c5d1SDavid du Colombier void
39*3e12c5d1SDavid du Colombier push(Datum d)
40*3e12c5d1SDavid du Colombier {
41*3e12c5d1SDavid du Colombier 	if (stackp >= &stack[NSTACK])
42*3e12c5d1SDavid du Colombier 		execerror("stack too deep", 0);
43*3e12c5d1SDavid du Colombier 	*stackp++ = d;
44*3e12c5d1SDavid du Colombier }
45*3e12c5d1SDavid du Colombier 
46*3e12c5d1SDavid du Colombier Datum
47*3e12c5d1SDavid du Colombier pop(void)
48*3e12c5d1SDavid du Colombier {
49*3e12c5d1SDavid du Colombier 	if (stackp == stack)
50*3e12c5d1SDavid du Colombier 		execerror("stack underflow", 0);
51*3e12c5d1SDavid du Colombier 	return *--stackp;
52*3e12c5d1SDavid du Colombier }
53*3e12c5d1SDavid du Colombier 
54*3e12c5d1SDavid du Colombier void
55*3e12c5d1SDavid du Colombier xpop(void)	/* for when no value is wanted */
56*3e12c5d1SDavid du Colombier {
57*3e12c5d1SDavid du Colombier 	if (stackp == stack)
58*3e12c5d1SDavid du Colombier 		execerror("stack underflow", (char *)0);
59*3e12c5d1SDavid du Colombier 	--stackp;
60*3e12c5d1SDavid du Colombier }
61*3e12c5d1SDavid du Colombier 
62*3e12c5d1SDavid du Colombier void
63*3e12c5d1SDavid du Colombier constpush(void)
64*3e12c5d1SDavid du Colombier {
65*3e12c5d1SDavid du Colombier 	Datum d;
66*3e12c5d1SDavid du Colombier 	d.val = ((Symbol *)*pc++)->u.val;
67*3e12c5d1SDavid du Colombier 	push(d);
68*3e12c5d1SDavid du Colombier }
69*3e12c5d1SDavid du Colombier 
70*3e12c5d1SDavid du Colombier void
71*3e12c5d1SDavid du Colombier varpush(void)
72*3e12c5d1SDavid du Colombier {
73*3e12c5d1SDavid du Colombier 	Datum d;
74*3e12c5d1SDavid du Colombier 	d.sym = (Symbol *)(*pc++);
75*3e12c5d1SDavid du Colombier 	push(d);
76*3e12c5d1SDavid du Colombier }
77*3e12c5d1SDavid du Colombier 
78*3e12c5d1SDavid du Colombier void
79*3e12c5d1SDavid du Colombier whilecode(void)
80*3e12c5d1SDavid du Colombier {
81*3e12c5d1SDavid du Colombier 	Datum d;
82*3e12c5d1SDavid du Colombier 	Inst *savepc = pc;
83*3e12c5d1SDavid du Colombier 
84*3e12c5d1SDavid du Colombier 	execute(savepc+2);	/* condition */
85*3e12c5d1SDavid du Colombier 	d = pop();
86*3e12c5d1SDavid du Colombier 	while (d.val) {
87*3e12c5d1SDavid du Colombier 		execute(*((Inst **)(savepc)));	/* body */
88*3e12c5d1SDavid du Colombier 		if (returning)
89*3e12c5d1SDavid du Colombier 			break;
90*3e12c5d1SDavid du Colombier 		execute(savepc+2);	/* condition */
91*3e12c5d1SDavid du Colombier 		d = pop();
92*3e12c5d1SDavid du Colombier 	}
93*3e12c5d1SDavid du Colombier 	if (!returning)
94*3e12c5d1SDavid du Colombier 		pc = *((Inst **)(savepc+1)); /* next stmt */
95*3e12c5d1SDavid du Colombier }
96*3e12c5d1SDavid du Colombier 
97*3e12c5d1SDavid du Colombier void
98*3e12c5d1SDavid du Colombier forcode(void)
99*3e12c5d1SDavid du Colombier {
100*3e12c5d1SDavid du Colombier 	Datum d;
101*3e12c5d1SDavid du Colombier 	Inst *savepc = pc;
102*3e12c5d1SDavid du Colombier 
103*3e12c5d1SDavid du Colombier 	execute(savepc+4);		/* precharge */
104*3e12c5d1SDavid du Colombier 	pop();
105*3e12c5d1SDavid du Colombier 	execute(*((Inst **)(savepc)));	/* condition */
106*3e12c5d1SDavid du Colombier 	d = pop();
107*3e12c5d1SDavid du Colombier 	while (d.val) {
108*3e12c5d1SDavid du Colombier 		execute(*((Inst **)(savepc+2)));	/* body */
109*3e12c5d1SDavid du Colombier 		if (returning)
110*3e12c5d1SDavid du Colombier 			break;
111*3e12c5d1SDavid du Colombier 		execute(*((Inst **)(savepc+1)));	/* post loop */
112*3e12c5d1SDavid du Colombier 		pop();
113*3e12c5d1SDavid du Colombier 		execute(*((Inst **)(savepc)));	/* condition */
114*3e12c5d1SDavid du Colombier 		d = pop();
115*3e12c5d1SDavid du Colombier 	}
116*3e12c5d1SDavid du Colombier 	if (!returning)
117*3e12c5d1SDavid du Colombier 		pc = *((Inst **)(savepc+3)); /* next stmt */
118*3e12c5d1SDavid du Colombier }
119*3e12c5d1SDavid du Colombier 
120*3e12c5d1SDavid du Colombier void
121*3e12c5d1SDavid du Colombier ifcode(void)
122*3e12c5d1SDavid du Colombier {
123*3e12c5d1SDavid du Colombier 	Datum d;
124*3e12c5d1SDavid du Colombier 	Inst *savepc = pc;	/* then part */
125*3e12c5d1SDavid du Colombier 
126*3e12c5d1SDavid du Colombier 	execute(savepc+3);	/* condition */
127*3e12c5d1SDavid du Colombier 	d = pop();
128*3e12c5d1SDavid du Colombier 	if (d.val)
129*3e12c5d1SDavid du Colombier 		execute(*((Inst **)(savepc)));
130*3e12c5d1SDavid du Colombier 	else if (*((Inst **)(savepc+1))) /* else part? */
131*3e12c5d1SDavid du Colombier 		execute(*((Inst **)(savepc+1)));
132*3e12c5d1SDavid du Colombier 	if (!returning)
133*3e12c5d1SDavid du Colombier 		pc = *((Inst **)(savepc+2)); /* next stmt */
134*3e12c5d1SDavid du Colombier }
135*3e12c5d1SDavid du Colombier 
136*3e12c5d1SDavid du Colombier void
137*3e12c5d1SDavid du Colombier define(Symbol* sp)	/* put func/proc in symbol table */
138*3e12c5d1SDavid du Colombier {
139*3e12c5d1SDavid du Colombier 	sp->u.defn = progbase;	/* start of code */
140*3e12c5d1SDavid du Colombier 	progbase = progp;	/* next code starts here */
141*3e12c5d1SDavid du Colombier }
142*3e12c5d1SDavid du Colombier 
143*3e12c5d1SDavid du Colombier void
144*3e12c5d1SDavid du Colombier call(void) 		/* call a function */
145*3e12c5d1SDavid du Colombier {
146*3e12c5d1SDavid du Colombier 	Symbol *sp = (Symbol *)pc[0]; /* symbol table entry */
147*3e12c5d1SDavid du Colombier 				      /* for function */
148*3e12c5d1SDavid du Colombier 	if (fp++ >= &frame[NFRAME-1])
149*3e12c5d1SDavid du Colombier 		execerror(sp->name, "call nested too deeply");
150*3e12c5d1SDavid du Colombier 	fp->sp = sp;
151*3e12c5d1SDavid du Colombier 	fp->nargs = (int)pc[1];
152*3e12c5d1SDavid du Colombier 	fp->retpc = pc + 2;
153*3e12c5d1SDavid du Colombier 	fp->argn = stackp - 1;	/* last argument */
154*3e12c5d1SDavid du Colombier 	execute(sp->u.defn);
155*3e12c5d1SDavid du Colombier 	returning = 0;
156*3e12c5d1SDavid du Colombier }
157*3e12c5d1SDavid du Colombier 
158*3e12c5d1SDavid du Colombier static void
159*3e12c5d1SDavid du Colombier ret(void) 		/* common return from func or proc */
160*3e12c5d1SDavid du Colombier {
161*3e12c5d1SDavid du Colombier 	int i;
162*3e12c5d1SDavid du Colombier 	for (i = 0; i < fp->nargs; i++)
163*3e12c5d1SDavid du Colombier 		pop();	/* pop arguments */
164*3e12c5d1SDavid du Colombier 	pc = (Inst *)fp->retpc;
165*3e12c5d1SDavid du Colombier 	--fp;
166*3e12c5d1SDavid du Colombier 	returning = 1;
167*3e12c5d1SDavid du Colombier }
168*3e12c5d1SDavid du Colombier 
169*3e12c5d1SDavid du Colombier void
170*3e12c5d1SDavid du Colombier funcret(void) 	/* return from a function */
171*3e12c5d1SDavid du Colombier {
172*3e12c5d1SDavid du Colombier 	Datum d;
173*3e12c5d1SDavid du Colombier 	if (fp->sp->type == PROCEDURE)
174*3e12c5d1SDavid du Colombier 		execerror(fp->sp->name, "(proc) returns value");
175*3e12c5d1SDavid du Colombier 	d = pop();	/* preserve function return value */
176*3e12c5d1SDavid du Colombier 	ret();
177*3e12c5d1SDavid du Colombier 	push(d);
178*3e12c5d1SDavid du Colombier }
179*3e12c5d1SDavid du Colombier 
180*3e12c5d1SDavid du Colombier void
181*3e12c5d1SDavid du Colombier procret(void) 	/* return from a procedure */
182*3e12c5d1SDavid du Colombier {
183*3e12c5d1SDavid du Colombier 	if (fp->sp->type == FUNCTION)
184*3e12c5d1SDavid du Colombier 		execerror(fp->sp->name,
185*3e12c5d1SDavid du Colombier 			"(func) returns no value");
186*3e12c5d1SDavid du Colombier 	ret();
187*3e12c5d1SDavid du Colombier }
188*3e12c5d1SDavid du Colombier 
189*3e12c5d1SDavid du Colombier double*
190*3e12c5d1SDavid du Colombier getarg(void) 	/* return pointer to argument */
191*3e12c5d1SDavid du Colombier {
192*3e12c5d1SDavid du Colombier 	int nargs = (int) *pc++;
193*3e12c5d1SDavid du Colombier 	if (nargs > fp->nargs)
194*3e12c5d1SDavid du Colombier 	    execerror(fp->sp->name, "not enough arguments");
195*3e12c5d1SDavid du Colombier 	return &fp->argn[nargs - fp->nargs].val;
196*3e12c5d1SDavid du Colombier }
197*3e12c5d1SDavid du Colombier 
198*3e12c5d1SDavid du Colombier void
199*3e12c5d1SDavid du Colombier arg(void) 	/* push argument onto stack */
200*3e12c5d1SDavid du Colombier {
201*3e12c5d1SDavid du Colombier 	Datum d;
202*3e12c5d1SDavid du Colombier 	d.val = *getarg();
203*3e12c5d1SDavid du Colombier 	push(d);
204*3e12c5d1SDavid du Colombier }
205*3e12c5d1SDavid du Colombier 
206*3e12c5d1SDavid du Colombier void
207*3e12c5d1SDavid du Colombier argassign(void) 	/* store top of stack in argument */
208*3e12c5d1SDavid du Colombier {
209*3e12c5d1SDavid du Colombier 	Datum d;
210*3e12c5d1SDavid du Colombier 	d = pop();
211*3e12c5d1SDavid du Colombier 	push(d);	/* leave value on stack */
212*3e12c5d1SDavid du Colombier 	*getarg() = d.val;
213*3e12c5d1SDavid du Colombier }
214*3e12c5d1SDavid du Colombier 
215*3e12c5d1SDavid du Colombier void
216*3e12c5d1SDavid du Colombier argaddeq(void) 	/* store top of stack in argument */
217*3e12c5d1SDavid du Colombier {
218*3e12c5d1SDavid du Colombier 	Datum d;
219*3e12c5d1SDavid du Colombier 	d = pop();
220*3e12c5d1SDavid du Colombier 	d.val = *getarg() += d.val;
221*3e12c5d1SDavid du Colombier 	push(d);	/* leave value on stack */
222*3e12c5d1SDavid du Colombier }
223*3e12c5d1SDavid du Colombier 
224*3e12c5d1SDavid du Colombier void
225*3e12c5d1SDavid du Colombier argsubeq(void) 	/* store top of stack in argument */
226*3e12c5d1SDavid du Colombier {
227*3e12c5d1SDavid du Colombier 	Datum d;
228*3e12c5d1SDavid du Colombier 	d = pop();
229*3e12c5d1SDavid du Colombier 	d.val = *getarg() -= d.val;
230*3e12c5d1SDavid du Colombier 	push(d);	/* leave value on stack */
231*3e12c5d1SDavid du Colombier }
232*3e12c5d1SDavid du Colombier 
233*3e12c5d1SDavid du Colombier void
234*3e12c5d1SDavid du Colombier argmuleq(void) 	/* store top of stack in argument */
235*3e12c5d1SDavid du Colombier {
236*3e12c5d1SDavid du Colombier 	Datum d;
237*3e12c5d1SDavid du Colombier 	d = pop();
238*3e12c5d1SDavid du Colombier 	d.val = *getarg() *= d.val;
239*3e12c5d1SDavid du Colombier 	push(d);	/* leave value on stack */
240*3e12c5d1SDavid du Colombier }
241*3e12c5d1SDavid du Colombier 
242*3e12c5d1SDavid du Colombier void
243*3e12c5d1SDavid du Colombier argdiveq(void) 	/* store top of stack in argument */
244*3e12c5d1SDavid du Colombier {
245*3e12c5d1SDavid du Colombier 	Datum d;
246*3e12c5d1SDavid du Colombier 	d = pop();
247*3e12c5d1SDavid du Colombier 	d.val = *getarg() /= d.val;
248*3e12c5d1SDavid du Colombier 	push(d);	/* leave value on stack */
249*3e12c5d1SDavid du Colombier }
250*3e12c5d1SDavid du Colombier 
251*3e12c5d1SDavid du Colombier void
252*3e12c5d1SDavid du Colombier argmodeq(void) 	/* store top of stack in argument */
253*3e12c5d1SDavid du Colombier {
254*3e12c5d1SDavid du Colombier 	Datum d;
255*3e12c5d1SDavid du Colombier 	double *x;
256*3e12c5d1SDavid du Colombier 	long y;
257*3e12c5d1SDavid du Colombier 	d = pop();
258*3e12c5d1SDavid du Colombier 	/* d.val = *getarg() %= d.val; */
259*3e12c5d1SDavid du Colombier 	x = getarg();
260*3e12c5d1SDavid du Colombier 	y = *x;
261*3e12c5d1SDavid du Colombier 	d.val = *x = y % (long) d.val;
262*3e12c5d1SDavid du Colombier 	push(d);	/* leave value on stack */
263*3e12c5d1SDavid du Colombier }
264*3e12c5d1SDavid du Colombier 
265*3e12c5d1SDavid du Colombier void
266*3e12c5d1SDavid du Colombier bltin(void)
267*3e12c5d1SDavid du Colombier {
268*3e12c5d1SDavid du Colombier 
269*3e12c5d1SDavid du Colombier 	Datum d;
270*3e12c5d1SDavid du Colombier 	d = pop();
271*3e12c5d1SDavid du Colombier 	d.val = (*(double (*)(double))*pc++)(d.val);
272*3e12c5d1SDavid du Colombier 	push(d);
273*3e12c5d1SDavid du Colombier }
274*3e12c5d1SDavid du Colombier 
275*3e12c5d1SDavid du Colombier void
276*3e12c5d1SDavid du Colombier add(void)
277*3e12c5d1SDavid du Colombier {
278*3e12c5d1SDavid du Colombier 	Datum d1, d2;
279*3e12c5d1SDavid du Colombier 	d2 = pop();
280*3e12c5d1SDavid du Colombier 	d1 = pop();
281*3e12c5d1SDavid du Colombier 	d1.val += d2.val;
282*3e12c5d1SDavid du Colombier 	push(d1);
283*3e12c5d1SDavid du Colombier }
284*3e12c5d1SDavid du Colombier 
285*3e12c5d1SDavid du Colombier void
286*3e12c5d1SDavid du Colombier sub(void)
287*3e12c5d1SDavid du Colombier {
288*3e12c5d1SDavid du Colombier 	Datum d1, d2;
289*3e12c5d1SDavid du Colombier 	d2 = pop();
290*3e12c5d1SDavid du Colombier 	d1 = pop();
291*3e12c5d1SDavid du Colombier 	d1.val -= d2.val;
292*3e12c5d1SDavid du Colombier 	push(d1);
293*3e12c5d1SDavid du Colombier }
294*3e12c5d1SDavid du Colombier 
295*3e12c5d1SDavid du Colombier void
296*3e12c5d1SDavid du Colombier mul(void)
297*3e12c5d1SDavid du Colombier {
298*3e12c5d1SDavid du Colombier 	Datum d1, d2;
299*3e12c5d1SDavid du Colombier 	d2 = pop();
300*3e12c5d1SDavid du Colombier 	d1 = pop();
301*3e12c5d1SDavid du Colombier 	d1.val *= d2.val;
302*3e12c5d1SDavid du Colombier 	push(d1);
303*3e12c5d1SDavid du Colombier }
304*3e12c5d1SDavid du Colombier 
305*3e12c5d1SDavid du Colombier void
306*3e12c5d1SDavid du Colombier div(void)
307*3e12c5d1SDavid du Colombier {
308*3e12c5d1SDavid du Colombier 	Datum d1, d2;
309*3e12c5d1SDavid du Colombier 	d2 = pop();
310*3e12c5d1SDavid du Colombier 	if (d2.val == 0.0)
311*3e12c5d1SDavid du Colombier 		execerror("division by zero", (char *)0);
312*3e12c5d1SDavid du Colombier 	d1 = pop();
313*3e12c5d1SDavid du Colombier 	d1.val /= d2.val;
314*3e12c5d1SDavid du Colombier 	push(d1);
315*3e12c5d1SDavid du Colombier }
316*3e12c5d1SDavid du Colombier 
317*3e12c5d1SDavid du Colombier void
318*3e12c5d1SDavid du Colombier mod(void)
319*3e12c5d1SDavid du Colombier {
320*3e12c5d1SDavid du Colombier 	Datum d1, d2;
321*3e12c5d1SDavid du Colombier 	long x;
322*3e12c5d1SDavid du Colombier 	d2 = pop();
323*3e12c5d1SDavid du Colombier 	if (d2.val == 0.0)
324*3e12c5d1SDavid du Colombier 		execerror("division by zero", (char *)0);
325*3e12c5d1SDavid du Colombier 	d1 = pop();
326*3e12c5d1SDavid du Colombier 	/* d1.val %= d2.val; */
327*3e12c5d1SDavid du Colombier 	x = d1.val;
328*3e12c5d1SDavid du Colombier 	x %= (long) d2.val;
329*3e12c5d1SDavid du Colombier 	d1.val = d2.val = x;
330*3e12c5d1SDavid du Colombier 	push(d1);
331*3e12c5d1SDavid du Colombier }
332*3e12c5d1SDavid du Colombier 
333*3e12c5d1SDavid du Colombier void
334*3e12c5d1SDavid du Colombier negate(void)
335*3e12c5d1SDavid du Colombier {
336*3e12c5d1SDavid du Colombier 	Datum d;
337*3e12c5d1SDavid du Colombier 	d = pop();
338*3e12c5d1SDavid du Colombier 	d.val = -d.val;
339*3e12c5d1SDavid du Colombier 	push(d);
340*3e12c5d1SDavid du Colombier }
341*3e12c5d1SDavid du Colombier 
342*3e12c5d1SDavid du Colombier void
343*3e12c5d1SDavid du Colombier verify(Symbol* s)
344*3e12c5d1SDavid du Colombier {
345*3e12c5d1SDavid du Colombier 	if (s->type != VAR && s->type != UNDEF)
346*3e12c5d1SDavid du Colombier 		execerror("attempt to evaluate non-variable", s->name);
347*3e12c5d1SDavid du Colombier 	if (s->type == UNDEF)
348*3e12c5d1SDavid du Colombier 		execerror("undefined variable", s->name);
349*3e12c5d1SDavid du Colombier }
350*3e12c5d1SDavid du Colombier 
351*3e12c5d1SDavid du Colombier void
352*3e12c5d1SDavid du Colombier eval(void)		/* evaluate variable on stack */
353*3e12c5d1SDavid du Colombier {
354*3e12c5d1SDavid du Colombier 	Datum d;
355*3e12c5d1SDavid du Colombier 	d = pop();
356*3e12c5d1SDavid du Colombier 	verify(d.sym);
357*3e12c5d1SDavid du Colombier 	d.val = d.sym->u.val;
358*3e12c5d1SDavid du Colombier 	push(d);
359*3e12c5d1SDavid du Colombier }
360*3e12c5d1SDavid du Colombier 
361*3e12c5d1SDavid du Colombier void
362*3e12c5d1SDavid du Colombier preinc(void)
363*3e12c5d1SDavid du Colombier {
364*3e12c5d1SDavid du Colombier 	Datum d;
365*3e12c5d1SDavid du Colombier 	d.sym = (Symbol *)(*pc++);
366*3e12c5d1SDavid du Colombier 	verify(d.sym);
367*3e12c5d1SDavid du Colombier 	d.val = d.sym->u.val += 1.0;
368*3e12c5d1SDavid du Colombier 	push(d);
369*3e12c5d1SDavid du Colombier }
370*3e12c5d1SDavid du Colombier 
371*3e12c5d1SDavid du Colombier void
372*3e12c5d1SDavid du Colombier predec(void)
373*3e12c5d1SDavid du Colombier {
374*3e12c5d1SDavid du Colombier 	Datum d;
375*3e12c5d1SDavid du Colombier 	d.sym = (Symbol *)(*pc++);
376*3e12c5d1SDavid du Colombier 	verify(d.sym);
377*3e12c5d1SDavid du Colombier 	d.val = d.sym->u.val -= 1.0;
378*3e12c5d1SDavid du Colombier 	push(d);
379*3e12c5d1SDavid du Colombier }
380*3e12c5d1SDavid du Colombier 
381*3e12c5d1SDavid du Colombier void
382*3e12c5d1SDavid du Colombier postinc(void)
383*3e12c5d1SDavid du Colombier {
384*3e12c5d1SDavid du Colombier 	Datum d;
385*3e12c5d1SDavid du Colombier 	double v;
386*3e12c5d1SDavid du Colombier 	d.sym = (Symbol *)(*pc++);
387*3e12c5d1SDavid du Colombier 	verify(d.sym);
388*3e12c5d1SDavid du Colombier 	v = d.sym->u.val;
389*3e12c5d1SDavid du Colombier 	d.sym->u.val += 1.0;
390*3e12c5d1SDavid du Colombier 	d.val = v;
391*3e12c5d1SDavid du Colombier 	push(d);
392*3e12c5d1SDavid du Colombier }
393*3e12c5d1SDavid du Colombier 
394*3e12c5d1SDavid du Colombier void
395*3e12c5d1SDavid du Colombier postdec(void)
396*3e12c5d1SDavid du Colombier {
397*3e12c5d1SDavid du Colombier 	Datum d;
398*3e12c5d1SDavid du Colombier 	double v;
399*3e12c5d1SDavid du Colombier 	d.sym = (Symbol *)(*pc++);
400*3e12c5d1SDavid du Colombier 	verify(d.sym);
401*3e12c5d1SDavid du Colombier 	v = d.sym->u.val;
402*3e12c5d1SDavid du Colombier 	d.sym->u.val -= 1.0;
403*3e12c5d1SDavid du Colombier 	d.val = v;
404*3e12c5d1SDavid du Colombier 	push(d);
405*3e12c5d1SDavid du Colombier }
406*3e12c5d1SDavid du Colombier 
407*3e12c5d1SDavid du Colombier void
408*3e12c5d1SDavid du Colombier gt(void)
409*3e12c5d1SDavid du Colombier {
410*3e12c5d1SDavid du Colombier 	Datum d1, d2;
411*3e12c5d1SDavid du Colombier 	d2 = pop();
412*3e12c5d1SDavid du Colombier 	d1 = pop();
413*3e12c5d1SDavid du Colombier 	d1.val = (double)(d1.val > d2.val);
414*3e12c5d1SDavid du Colombier 	push(d1);
415*3e12c5d1SDavid du Colombier }
416*3e12c5d1SDavid du Colombier 
417*3e12c5d1SDavid du Colombier void
418*3e12c5d1SDavid du Colombier lt(void)
419*3e12c5d1SDavid du Colombier {
420*3e12c5d1SDavid du Colombier 	Datum d1, d2;
421*3e12c5d1SDavid du Colombier 	d2 = pop();
422*3e12c5d1SDavid du Colombier 	d1 = pop();
423*3e12c5d1SDavid du Colombier 	d1.val = (double)(d1.val < d2.val);
424*3e12c5d1SDavid du Colombier 	push(d1);
425*3e12c5d1SDavid du Colombier }
426*3e12c5d1SDavid du Colombier 
427*3e12c5d1SDavid du Colombier void
428*3e12c5d1SDavid du Colombier ge(void)
429*3e12c5d1SDavid du Colombier {
430*3e12c5d1SDavid du Colombier 	Datum d1, d2;
431*3e12c5d1SDavid du Colombier 	d2 = pop();
432*3e12c5d1SDavid du Colombier 	d1 = pop();
433*3e12c5d1SDavid du Colombier 	d1.val = (double)(d1.val >= d2.val);
434*3e12c5d1SDavid du Colombier 	push(d1);
435*3e12c5d1SDavid du Colombier }
436*3e12c5d1SDavid du Colombier 
437*3e12c5d1SDavid du Colombier void
438*3e12c5d1SDavid du Colombier le(void)
439*3e12c5d1SDavid du Colombier {
440*3e12c5d1SDavid du Colombier 	Datum d1, d2;
441*3e12c5d1SDavid du Colombier 	d2 = pop();
442*3e12c5d1SDavid du Colombier 	d1 = pop();
443*3e12c5d1SDavid du Colombier 	d1.val = (double)(d1.val <= d2.val);
444*3e12c5d1SDavid du Colombier 	push(d1);
445*3e12c5d1SDavid du Colombier }
446*3e12c5d1SDavid du Colombier 
447*3e12c5d1SDavid du Colombier void
448*3e12c5d1SDavid du Colombier eq(void)
449*3e12c5d1SDavid du Colombier {
450*3e12c5d1SDavid du Colombier 	Datum d1, d2;
451*3e12c5d1SDavid du Colombier 	d2 = pop();
452*3e12c5d1SDavid du Colombier 	d1 = pop();
453*3e12c5d1SDavid du Colombier 	d1.val = (double)(d1.val == d2.val);
454*3e12c5d1SDavid du Colombier 	push(d1);
455*3e12c5d1SDavid du Colombier }
456*3e12c5d1SDavid du Colombier 
457*3e12c5d1SDavid du Colombier void
458*3e12c5d1SDavid du Colombier ne(void)
459*3e12c5d1SDavid du Colombier {
460*3e12c5d1SDavid du Colombier 	Datum d1, d2;
461*3e12c5d1SDavid du Colombier 	d2 = pop();
462*3e12c5d1SDavid du Colombier 	d1 = pop();
463*3e12c5d1SDavid du Colombier 	d1.val = (double)(d1.val != d2.val);
464*3e12c5d1SDavid du Colombier 	push(d1);
465*3e12c5d1SDavid du Colombier }
466*3e12c5d1SDavid du Colombier 
467*3e12c5d1SDavid du Colombier void
468*3e12c5d1SDavid du Colombier and(void)
469*3e12c5d1SDavid du Colombier {
470*3e12c5d1SDavid du Colombier 	Datum d1, d2;
471*3e12c5d1SDavid du Colombier 	d2 = pop();
472*3e12c5d1SDavid du Colombier 	d1 = pop();
473*3e12c5d1SDavid du Colombier 	d1.val = (double)(d1.val != 0.0 && d2.val != 0.0);
474*3e12c5d1SDavid du Colombier 	push(d1);
475*3e12c5d1SDavid du Colombier }
476*3e12c5d1SDavid du Colombier 
477*3e12c5d1SDavid du Colombier void
478*3e12c5d1SDavid du Colombier or(void)
479*3e12c5d1SDavid du Colombier {
480*3e12c5d1SDavid du Colombier 	Datum d1, d2;
481*3e12c5d1SDavid du Colombier 	d2 = pop();
482*3e12c5d1SDavid du Colombier 	d1 = pop();
483*3e12c5d1SDavid du Colombier 	d1.val = (double)(d1.val != 0.0 || d2.val != 0.0);
484*3e12c5d1SDavid du Colombier 	push(d1);
485*3e12c5d1SDavid du Colombier }
486*3e12c5d1SDavid du Colombier 
487*3e12c5d1SDavid du Colombier void
488*3e12c5d1SDavid du Colombier not(void)
489*3e12c5d1SDavid du Colombier {
490*3e12c5d1SDavid du Colombier 	Datum d;
491*3e12c5d1SDavid du Colombier 	d = pop();
492*3e12c5d1SDavid du Colombier 	d.val = (double)(d.val == 0.0);
493*3e12c5d1SDavid du Colombier 	push(d);
494*3e12c5d1SDavid du Colombier }
495*3e12c5d1SDavid du Colombier 
496*3e12c5d1SDavid du Colombier void
497*3e12c5d1SDavid du Colombier power(void)
498*3e12c5d1SDavid du Colombier {
499*3e12c5d1SDavid du Colombier 	Datum d1, d2;
500*3e12c5d1SDavid du Colombier 	d2 = pop();
501*3e12c5d1SDavid du Colombier 	d1 = pop();
502*3e12c5d1SDavid du Colombier 	d1.val = Pow(d1.val, d2.val);
503*3e12c5d1SDavid du Colombier 	push(d1);
504*3e12c5d1SDavid du Colombier }
505*3e12c5d1SDavid du Colombier 
506*3e12c5d1SDavid du Colombier void
507*3e12c5d1SDavid du Colombier assign(void)
508*3e12c5d1SDavid du Colombier {
509*3e12c5d1SDavid du Colombier 	Datum d1, d2;
510*3e12c5d1SDavid du Colombier 	d1 = pop();
511*3e12c5d1SDavid du Colombier 	d2 = pop();
512*3e12c5d1SDavid du Colombier 	if (d1.sym->type != VAR && d1.sym->type != UNDEF)
513*3e12c5d1SDavid du Colombier 		execerror("assignment to non-variable",
514*3e12c5d1SDavid du Colombier 			d1.sym->name);
515*3e12c5d1SDavid du Colombier 	d1.sym->u.val = d2.val;
516*3e12c5d1SDavid du Colombier 	d1.sym->type = VAR;
517*3e12c5d1SDavid du Colombier 	push(d2);
518*3e12c5d1SDavid du Colombier }
519*3e12c5d1SDavid du Colombier 
520*3e12c5d1SDavid du Colombier void
521*3e12c5d1SDavid du Colombier addeq(void)
522*3e12c5d1SDavid du Colombier {
523*3e12c5d1SDavid du Colombier 	Datum d1, d2;
524*3e12c5d1SDavid du Colombier 	d1 = pop();
525*3e12c5d1SDavid du Colombier 	d2 = pop();
526*3e12c5d1SDavid du Colombier 	if (d1.sym->type != VAR && d1.sym->type != UNDEF)
527*3e12c5d1SDavid du Colombier 		execerror("assignment to non-variable",
528*3e12c5d1SDavid du Colombier 			d1.sym->name);
529*3e12c5d1SDavid du Colombier 	d2.val = d1.sym->u.val += d2.val;
530*3e12c5d1SDavid du Colombier 	d1.sym->type = VAR;
531*3e12c5d1SDavid du Colombier 	push(d2);
532*3e12c5d1SDavid du Colombier }
533*3e12c5d1SDavid du Colombier 
534*3e12c5d1SDavid du Colombier void
535*3e12c5d1SDavid du Colombier subeq(void)
536*3e12c5d1SDavid du Colombier {
537*3e12c5d1SDavid du Colombier 	Datum d1, d2;
538*3e12c5d1SDavid du Colombier 	d1 = pop();
539*3e12c5d1SDavid du Colombier 	d2 = pop();
540*3e12c5d1SDavid du Colombier 	if (d1.sym->type != VAR && d1.sym->type != UNDEF)
541*3e12c5d1SDavid du Colombier 		execerror("assignment to non-variable",
542*3e12c5d1SDavid du Colombier 			d1.sym->name);
543*3e12c5d1SDavid du Colombier 	d2.val = d1.sym->u.val -= d2.val;
544*3e12c5d1SDavid du Colombier 	d1.sym->type = VAR;
545*3e12c5d1SDavid du Colombier 	push(d2);
546*3e12c5d1SDavid du Colombier }
547*3e12c5d1SDavid du Colombier 
548*3e12c5d1SDavid du Colombier void
549*3e12c5d1SDavid du Colombier muleq(void)
550*3e12c5d1SDavid du Colombier {
551*3e12c5d1SDavid du Colombier 	Datum d1, d2;
552*3e12c5d1SDavid du Colombier 	d1 = pop();
553*3e12c5d1SDavid du Colombier 	d2 = pop();
554*3e12c5d1SDavid du Colombier 	if (d1.sym->type != VAR && d1.sym->type != UNDEF)
555*3e12c5d1SDavid du Colombier 		execerror("assignment to non-variable",
556*3e12c5d1SDavid du Colombier 			d1.sym->name);
557*3e12c5d1SDavid du Colombier 	d2.val = d1.sym->u.val *= d2.val;
558*3e12c5d1SDavid du Colombier 	d1.sym->type = VAR;
559*3e12c5d1SDavid du Colombier 	push(d2);
560*3e12c5d1SDavid du Colombier }
561*3e12c5d1SDavid du Colombier 
562*3e12c5d1SDavid du Colombier void
563*3e12c5d1SDavid du Colombier diveq(void)
564*3e12c5d1SDavid du Colombier {
565*3e12c5d1SDavid du Colombier 	Datum d1, d2;
566*3e12c5d1SDavid du Colombier 	d1 = pop();
567*3e12c5d1SDavid du Colombier 	d2 = pop();
568*3e12c5d1SDavid du Colombier 	if (d1.sym->type != VAR && d1.sym->type != UNDEF)
569*3e12c5d1SDavid du Colombier 		execerror("assignment to non-variable",
570*3e12c5d1SDavid du Colombier 			d1.sym->name);
571*3e12c5d1SDavid du Colombier 	d2.val = d1.sym->u.val /= d2.val;
572*3e12c5d1SDavid du Colombier 	d1.sym->type = VAR;
573*3e12c5d1SDavid du Colombier 	push(d2);
574*3e12c5d1SDavid du Colombier }
575*3e12c5d1SDavid du Colombier 
576*3e12c5d1SDavid du Colombier void
577*3e12c5d1SDavid du Colombier modeq(void)
578*3e12c5d1SDavid du Colombier {
579*3e12c5d1SDavid du Colombier 	Datum d1, d2;
580*3e12c5d1SDavid du Colombier 	long x;
581*3e12c5d1SDavid du Colombier 	d1 = pop();
582*3e12c5d1SDavid du Colombier 	d2 = pop();
583*3e12c5d1SDavid du Colombier 	if (d1.sym->type != VAR && d1.sym->type != UNDEF)
584*3e12c5d1SDavid du Colombier 		execerror("assignment to non-variable",
585*3e12c5d1SDavid du Colombier 			d1.sym->name);
586*3e12c5d1SDavid du Colombier 	/* d2.val = d1.sym->u.val %= d2.val; */
587*3e12c5d1SDavid du Colombier 	x = d1.sym->u.val;
588*3e12c5d1SDavid du Colombier 	x %= (long) d2.val;
589*3e12c5d1SDavid du Colombier 	d2.val = d1.sym->u.val = x;
590*3e12c5d1SDavid du Colombier 	d1.sym->type = VAR;
591*3e12c5d1SDavid du Colombier 	push(d2);
592*3e12c5d1SDavid du Colombier }
593*3e12c5d1SDavid du Colombier 
594*3e12c5d1SDavid du Colombier void
595*3e12c5d1SDavid du Colombier printtop(void)	/* pop top value from stack, print it */
596*3e12c5d1SDavid du Colombier {
597*3e12c5d1SDavid du Colombier 	Datum d;
598*3e12c5d1SDavid du Colombier 	static Symbol *s;	/* last value computed */
599*3e12c5d1SDavid du Colombier 	if (s == 0)
600*3e12c5d1SDavid du Colombier 		s = install("_", VAR, 0.0);
601*3e12c5d1SDavid du Colombier 	d = pop();
602*3e12c5d1SDavid du Colombier 	print("%.12g\n", d.val);
603*3e12c5d1SDavid du Colombier 	s->u.val = d.val;
604*3e12c5d1SDavid du Colombier }
605*3e12c5d1SDavid du Colombier 
606*3e12c5d1SDavid du Colombier void
607*3e12c5d1SDavid du Colombier prexpr(void)	/* print numeric value */
608*3e12c5d1SDavid du Colombier {
609*3e12c5d1SDavid du Colombier 	Datum d;
610*3e12c5d1SDavid du Colombier 	d = pop();
611*3e12c5d1SDavid du Colombier 	print("%.12g ", d.val);
612*3e12c5d1SDavid du Colombier }
613*3e12c5d1SDavid du Colombier 
614*3e12c5d1SDavid du Colombier void
615*3e12c5d1SDavid du Colombier prstr(void)		/* print string value */
616*3e12c5d1SDavid du Colombier {
617*3e12c5d1SDavid du Colombier 	print("%s", (char *) *pc++);
618*3e12c5d1SDavid du Colombier }
619*3e12c5d1SDavid du Colombier 
620*3e12c5d1SDavid du Colombier void
621*3e12c5d1SDavid du Colombier varread(void)	/* read into variable */
622*3e12c5d1SDavid du Colombier {
623*3e12c5d1SDavid du Colombier 	Datum d;
624*3e12c5d1SDavid du Colombier 	extern Biobuf *bin;
625*3e12c5d1SDavid du Colombier 	Symbol *var = (Symbol *) *pc++;
626*3e12c5d1SDavid du Colombier 	int c;
627*3e12c5d1SDavid du Colombier 
628*3e12c5d1SDavid du Colombier   Again:
629*3e12c5d1SDavid du Colombier 	do
630*3e12c5d1SDavid du Colombier 		c = Bgetc(bin);
631*3e12c5d1SDavid du Colombier 	while(c==' ' || c=='\t');
632*3e12c5d1SDavid du Colombier 	if(c == Beof){
633*3e12c5d1SDavid du Colombier   Iseof:
634*3e12c5d1SDavid du Colombier 		if(moreinput())
635*3e12c5d1SDavid du Colombier 			goto Again;
636*3e12c5d1SDavid du Colombier 		d.val = var->u.val = 0.0;
637*3e12c5d1SDavid du Colombier 		goto Return;
638*3e12c5d1SDavid du Colombier 	}
639*3e12c5d1SDavid du Colombier 
640*3e12c5d1SDavid du Colombier 	if(strchr("+-.0123456789", c) == 0)
641*3e12c5d1SDavid du Colombier 		execerror("non-number read into", var->name);
642*3e12c5d1SDavid du Colombier 	Bungetc(bin);
643*3e12c5d1SDavid du Colombier 	if(Bgetd(bin, &var->u.val) == Beof)
644*3e12c5d1SDavid du Colombier 		goto Iseof;
645*3e12c5d1SDavid du Colombier 	else
646*3e12c5d1SDavid du Colombier 		d.val = 1.0;
647*3e12c5d1SDavid du Colombier   Return:
648*3e12c5d1SDavid du Colombier 	var->type = VAR;
649*3e12c5d1SDavid du Colombier 	push(d);
650*3e12c5d1SDavid du Colombier }
651*3e12c5d1SDavid du Colombier 
652*3e12c5d1SDavid du Colombier Inst*
653*3e12c5d1SDavid du Colombier code(Inst f)	/* install one instruction or operand */
654*3e12c5d1SDavid du Colombier {
655*3e12c5d1SDavid du Colombier 	Inst *oprogp = progp;
656*3e12c5d1SDavid du Colombier 	if (progp >= &prog[NPROG])
657*3e12c5d1SDavid du Colombier 		execerror("program too big", (char *)0);
658*3e12c5d1SDavid du Colombier 	*progp++ = f;
659*3e12c5d1SDavid du Colombier 	return oprogp;
660*3e12c5d1SDavid du Colombier }
661*3e12c5d1SDavid du Colombier 
662*3e12c5d1SDavid du Colombier void
663*3e12c5d1SDavid du Colombier execute(Inst* p)
664*3e12c5d1SDavid du Colombier {
665*3e12c5d1SDavid du Colombier 	for (pc = p; *pc != STOP && !returning; )
666*3e12c5d1SDavid du Colombier 		(*((++pc)[-1]))();
667*3e12c5d1SDavid du Colombier }
668