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