code.c - 9base - revived minimalist port of Plan 9 userland to Unix
 (HTM) git clone git://git.suckless.org/9base
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) 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 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
          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 }