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