Introduction
Introduction Statistics Contact Development Disclaimer Help
code.c - 9base - revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log
Files
Refs
README
LICENSE
---
code.c (10181B)
---
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 nop(void)
42 {
43 }
44
45 void
46 push(Datum d)
47 {
48 if (stackp >= &stack[NSTACK])
49 execerror("stack too deep", 0);
50 *stackp++ = d;
51 }
52
53 Datum
54 pop(void)
55 {
56 if (stackp == stack)
57 execerror("stack underflow", 0);
58 return *--stackp;
59 }
60
61 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
70 constpush(void)
71 {
72 Datum d;
73 d.val = ((Symbol *)*pc++)->u.val;
74 push(d);
75 }
76
77 void
78 varpush(void)
79 {
80 Datum d;
81 d.sym = (Symbol *)(*pc++);
82 push(d);
83 }
84
85 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
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
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
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
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 argumen…
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
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
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
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
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
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
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
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
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
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
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
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
323 negate(void)
324 {
325 Datum d;
326 d = pop();
327 d.val = -d.val;
328 push(d);
329 }
330
331 void
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
566 ppush(Datum *d)
567 {
568 push(*d);
569 }
570
571 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
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
606 prexpr(void) /* print numeric value */
607 {
608 Datum d;
609 d = pop();
610 print("%.17g ", d.val);
611 }
612
613 void
614 prstr(void) /* print string value */
615 {
616 print("%s", (char *) *pc++);
617 }
618
619 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*
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
662 execute(Inst* p)
663 {
664 for (pc = p; *pc != STOP && !returning; )
665 (*((++pc)[-1]))();
666 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.