|
|
1.1 ! root 1: #include <stdio.h> ! 2: #include <setjmp.h> ! 3: #include <assert.h> ! 4: #include "bc.h" ! 5: ! 6: ! 7: /* ! 8: * The jump buffer bcmenv is used to hold the environment of ! 9: * the bc-machine interpreter. If some error is detected while ! 10: * executing some bc-machine code, after an error message is ! 11: * printed, return is to the environment saved here. ! 12: */ ! 13: ! 14: static jmp_buf bcmenv; ! 15: ! 16: ! 17: /* ! 18: * Interp is the routine which interprets bc-machine code. ! 19: */ ! 20: ! 21: interp() ! 22: { ! 23: stkent stack[MAXSTACK]; ! 24: register stkent *tos = &stack[-1]; ! 25: register code *pc = cstream; ! 26: register rvalue *temp; ! 27: stkent *frame; ! 28: func *fnc; ! 29: ! 30: if (setjmp(bcmenv)) { ! 31: /* One might wonder if things on the stack ! 32: * should be cleaned up? ! 33: */ ! 34: return; ! 35: } ! 36: for (;;) { ! 37: if (tos >= &stack[MAXSTACK - 1]) ! 38: bcmerr("Out of runtime stack"); ! 39: switch (pc++->opcode) { ! 40: case LOAD: ! 41: temp = tos->lvalue; ! 42: minit(&tos->rvalue.mantissa); ! 43: mcopy(&temp->mantissa, &tos->rvalue.mantissa); ! 44: tos->rvalue.scale = temp->scale; ! 45: break; ! 46: case LIBASE: ! 47: minit(&(++tos)->rvalue.mantissa); ! 48: mitom(ibase, &tos->rvalue.mantissa); ! 49: tos->rvalue.scale = 0; ! 50: break; ! 51: case LOBASE: ! 52: minit(&(++tos)->rvalue.mantissa); ! 53: mcopy(&outbase, &tos->rvalue.mantissa); ! 54: tos->rvalue.scale = 0; ! 55: break; ! 56: case LSCALE: ! 57: minit(&(++tos)->rvalue.mantissa); ! 58: mitom(scale, &tos->rvalue.mantissa); ! 59: tos->rvalue.scale = 0; ! 60: break; ! 61: case STORE: ! 62: temp = (--tos)->lvalue; ! 63: *tos = tos[1]; ! 64: mcopy(&tos->rvalue.mantissa, &temp->mantissa); ! 65: temp->scale = tos->rvalue.scale; ! 66: break; ! 67: case SIBASE: ! 68: sibase(&tos->rvalue); ! 69: break; ! 70: case SOBASE: ! 71: sobase(&tos->rvalue); ! 72: break; ! 73: case SSCALE: ! 74: sscale(&tos->rvalue); ! 75: break; ! 76: case POP: ! 77: mvfree(&tos--->rvalue.mantissa); ! 78: break; ! 79: case PRVAL: ! 80: temp = tos++->lvalue; ! 81: minit(&tos->rvalue.mantissa); ! 82: mcopy(&temp->mantissa, &tos->rvalue.mantissa); ! 83: tos->rvalue.scale = temp->scale; ! 84: break; ! 85: case PGLSC: ! 86: case PLISC: ! 87: (++tos)->lvalue = pc++->lvalue; ! 88: break; ! 89: case PLOSC: ! 90: (++tos)->lvalue = &frame[pc++->ivalue].rvalue; ! 91: break; ! 92: case PGLAE: ! 93: temp = select(pc++->alvalue, rtoint(&tos->rvalue)); ! 94: mvfree(&tos->rvalue.mantissa); ! 95: tos->lvalue = temp; ! 96: break; ! 97: case PLOAE: ! 98: temp = select(frame[pc++->ivalue].alvalue, ! 99: rtoint(&tos->rvalue)); ! 100: mvfree(&tos->rvalue.mantissa); ! 101: tos->lvalue = temp; ! 102: break; ! 103: case PGLAR: ! 104: (++tos)->alvalue = pc++->alvalue; ! 105: break; ! 106: case PLOAR: ! 107: (++tos)->alvalue = frame[pc++->ivalue].alvalue; ! 108: break; ! 109: case STOP: ! 110: return; ! 111: case CALL: ! 112: chkcall(pc[0].dvalue, pc[1].ivalue); ! 113: fnc = &pc->dvalue->globalv.fvalue; ! 114: tos = pauto(fnc, tos, &stack[MAXSTACK-1]); ! 115: tos->bcstate.spc = pc + 2; ! 116: tos->bcstate.sfp = frame; ! 117: tos->bcstate.stos = frame = newframe(fnc, tos); ! 118: pc = fnc->body; ! 119: break; ! 120: case RETURN: ! 121: temp = &tos->rvalue; ! 122: bcclean(&pc->dvalue->globalv.fvalue, tos - 2); ! 123: pc = tos[-1].bcstate.spc; ! 124: frame = tos[-1].bcstate.sfp; ! 125: tos = tos[-1].bcstate.stos; ! 126: tos->rvalue = *temp; ! 127: break; ! 128: case INC: ! 129: madd(&tos->rvalue.mantissa, pow10(tos->rvalue.scale), ! 130: &tos->rvalue.mantissa); ! 131: break; ! 132: case DEC: ! 133: msub(&tos->rvalue.mantissa, pow10(tos->rvalue.scale), ! 134: &tos->rvalue.mantissa); ! 135: break; ! 136: case PRNUM: ! 137: putnum(&tos->rvalue); ! 138: mvfree(&dot.mantissa); ! 139: dot = tos->rvalue; ! 140: --tos; ! 141: break; ! 142: case PRSTR: ! 143: pstring(pc++->svalue, 0); ! 144: break; ! 145: case PRNL: ! 146: pnewln(); ! 147: break; ! 148: case LENGTH: ! 149: mitom(tos->rvalue.mantissa.len, &tos->rvalue.mantissa); ! 150: tos->rvalue.scale = 0; ! 151: break; ! 152: case SCALE: ! 153: mitom(tos->rvalue.scale, &tos->rvalue.mantissa); ! 154: tos->rvalue.scale = 0; ! 155: break; ! 156: case SQRT: ! 157: bcsqrt(&tos->rvalue); ! 158: break; ! 159: case ADD: ! 160: bcadd(&tos[0].rvalue, &tos[-1].rvalue); ! 161: --tos; ! 162: break; ! 163: case SUB: ! 164: mneg(&tos[0].rvalue.mantissa, ! 165: &tos[0].rvalue.mantissa); ! 166: bcadd(&tos[0].rvalue, &tos[-1].rvalue); ! 167: --tos; ! 168: break; ! 169: case MUL: ! 170: bcmul(&tos[0].rvalue, &tos[-1].rvalue); ! 171: --tos; ! 172: break; ! 173: case DIV: ! 174: bcdiv(&tos[0].rvalue, &tos[-1].rvalue); ! 175: --tos; ! 176: break; ! 177: case REM: ! 178: bcrem(&tos[0].rvalue, &tos[-1].rvalue); ! 179: --tos; ! 180: break; ! 181: case EXP: ! 182: bcexp(&tos[0].rvalue, &tos[-1].rvalue); ! 183: --tos; ! 184: break; ! 185: case NEG: ! 186: mneg(&tos[0].rvalue.mantissa, &tos[0].rvalue.mantissa); ! 187: break; ! 188: case BRALW: ! 189: pc += pc->address; ! 190: break; ! 191: case BRNEV: ! 192: pc += 2; ! 193: break; ! 194: case BRLT: ! 195: if (bccmp(&tos[0].rvalue, &tos[-1].rvalue) < 0) ! 196: pc += pc->address; ! 197: else ! 198: ++pc; ! 199: tos -= 2; ! 200: break; ! 201: case BRLE: ! 202: if (bccmp(&tos[0].rvalue, &tos[-1].rvalue) <= 0) ! 203: pc += pc->address; ! 204: else ! 205: ++pc; ! 206: tos -= 2; ! 207: break; ! 208: case BREQ: ! 209: if (bccmp(&tos[0].rvalue, &tos[-1].rvalue) == 0) ! 210: pc += pc->address; ! 211: else ! 212: ++pc; ! 213: tos -= 2; ! 214: break; ! 215: case BRGE: ! 216: if (bccmp(&tos[0].rvalue, &tos[-1].rvalue) >= 0) ! 217: pc += pc->address; ! 218: else ! 219: ++pc; ! 220: tos -= 2; ! 221: break; ! 222: case BRGT: ! 223: if (bccmp(&tos[0].rvalue, &tos[-1].rvalue) > 0) ! 224: pc += pc->address; ! 225: else ! 226: ++pc; ! 227: tos -= 2; ! 228: break; ! 229: case BRNE: ! 230: if (bccmp(&tos[0].rvalue, &tos[-1].rvalue) != 0) ! 231: pc += pc->address; ! 232: else ! 233: ++pc; ! 234: tos -= 2; ! 235: break; ! 236: case EXIT: ! 237: exit(0); ! 238: break; ! 239: default: ! 240: assert(FALSE); ! 241: } ! 242: } ! 243: } ! 244: ! 245: /* ! 246: * Bcmerr is called when any bc-machine error occurrs. ! 247: * It prints out an error message and causes interp to ! 248: * return. ! 249: */ ! 250: ! 251: bcmerr(str) ! 252: char *str; ! 253: { ! 254: fprintf(stderr, "%r\n", &str); ! 255: longjmp(bcmenv, TRUE); ! 256: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.