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