|
|
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.