|
|
1.1 root 1: /*
2: * DC - Reverse Polish desk calculator (multi-precision)
3: * Depends on mint value being defined as a `char *'
4: * so mint may also be char string
5: */
6: #include <stdio.h>
7: #include "bc.h"
8:
9: char *version = "DC Version 1.00.\n";
10:
11: #define NREG 256
12: #define NSTACK 256
13:
14: struct reg_t {
15: struct reg_t *next;
16: rvalue regval;
17: } *reg[NREG];
18:
19: rvalue stack[NSTACK],
20: *sp = &stack[0];
21:
22: static char *soflmsg = "Out of pushdown",
23: *suflmsg = "stack empty",
24: *oospmsg = "Out of space",
25: *nregmsg = "Missing reg name";
26:
27: #define skiperr(m) {fprintf(stderr,"%s\n",m);return(-1);}
28:
29: #define push(x) {if(sp==&stack[NSTACK]){skiperr(soflmsg);}else{x=sp++;}}
30:
31: #define pop(x) {if(sp==&stack[0]){skiperr(suflmsg);}else{x=--sp;}}
32:
33: #define new(x) {push(x);minit(&(x)->mantissa);}
34:
35: #define temp(x) {push(x);pop(x);}
36:
37: #define tos(x) {pop(x);push(x);}
38:
39: #define getreg(c,r){if((c=getc(infile))==EOF){skiperr(nregmsg);}else{r=reg[c];}}
40:
41: #define newreg(c, r) {\
42: struct reg_t *nr=(struct reg_t *)malloc(sizeof(struct reg_t));\
43: if (nr == NULL) {\
44: skiperr(oospmsg);\
45: } else {\
46: nr->next = r;\
47: r = reg[c] = nr;\
48: }\
49: }
50:
51: #define execute(x, y) if((x)->scale<0){\
52: FILE f;char *s=(x)->mantissa.val;if(y)minit(&(x)->mantissa);\
53: _stropen(s,strlen(s),&f);c=interp(&f);infile=fp;if(y)mpfree(s);\
54: if(c)return(c-1);}
55:
56: main(argc, argv)
57: int argc;
58: char *argv[];
59: {
60: FILE *fp;
61:
62: init();
63: if (argc > 1)
64: if (!strcmp(argv[1], "-V")) {
65: fprintf(stderr, version);
66: exit(0);
67: } else if ((fp=fopen(argv[1], "r"))==NULL) {
68: fprintf(stderr, "Dc: can't open %s\n", argv[1]);
69: return (1);
70: } else if (interp(fp) > 0)
71: return (0);
72: else
73: fclose(fp);
74: while (interp(stdin) < 0)
75: ;
76: return (0);
77: }
78:
79: interp(fp)
80: FILE *fp;
81: {
82: register int c;
83: register rvalue *a, *b;
84: struct reg_t *r;
85: int (*f)();
86: int d;
87: extern int iseq(), isne(), islt(), isle(), isge(), isgt();
88: extern int dcsub(), bcadd(), bcmul(), bcdiv(), bcrem(), bcexp();
89: extern int sibase(), sobase(), output();
90:
91: infile = fp;
92: for (f=NULL;;f=NULL) switch (c = getc(infile)) {
93: case EOF:
94: return (0);
95: case ' ':
96: case '\t':
97: case '\n':
98: continue;
99: case '_':
100: c = getc(infile);
101: f = mneg;
102: /* Fall through */
103: case '0': case '1': case '2': case '3':
104: case '4': case '5': case '6': case '7':
105: case '8': case '9': case 'A': case 'B':
106: case 'C': case 'D': case 'E': case 'F':
107: case '.':
108: push(a);
109: b = getnum(c);
110: *a = *b;
111: mpfree((char *)b);
112: if (f!=NULL)
113: (*f)(&a->mantissa, &a->mantissa);
114: continue;
115: case '-':
116: f = dcsub;
117: goto binary;
118: case '+':
119: f = bcadd;
120: goto binary;
121: case '*':
122: f = bcmul;
123: goto binary;
124: case '/':
125: f = bcdiv;
126: goto binary;
127: case '%':
128: f = bcrem;
129: goto binary;
130: case '^':
131: f = bcexp;
132: /* Fall through */
133: binary:
134: pop(b);
135: pop(a);
136: (*f)(b, a);
137: push(a);
138: continue;
139: case '[':
140: push(a);
141: if (c = rdstring(a))
142: return (c);
143: continue;
144: case '<':
145: f = islt;
146: goto compare;
147: case '=':
148: f = iseq;
149: goto compare;
150: case '>':
151: f = isgt;
152: goto compare;
153: case '!':
154: switch (c=getc(infile)) {
155: case '<':
156: f = isge;
157: goto compare;
158: case '=':
159: f = isne;
160: goto compare;
161: case '>':
162: f = isle;
163: goto compare;
164: default:
165: ungetc(c, infile);
166: temp(a);
167: rdline(a, infile);
168: system(a->mantissa.val);
169: printf("!\n");
170: mvfree(&a->mantissa);
171: continue;
172: }
173: compare:
174: pop(b);
175: pop(a);
176: d = (*f)(bccmp(b, a));
177: getreg(c, r);
178: if (d && r != NULL)
179: execute(&r->regval, 0);
180: continue;
181: case '?':
182: temp(a);
183: rdline(a, stdin);
184: execute(a, 1);
185: continue;
186: case 'c':
187: while (sp != &stack[0]) {
188: pop(a);
189: mvfree(&a->mantissa);
190: }
191: continue;
192: case 'd':
193: tos(a);
194: new(b);
195: mcopy(&a->mantissa, &b->mantissa);
196: b->scale = a->scale;
197: continue;
198: case 'f':
199: for (c = 0; c != NREG; c++)
200: if ((r=reg[c]) != NULL) {
201: printf("`%c': ", c);
202: output(&r->regval);
203: }
204: printf("stack:\n");
205: for (a = &stack[0]; a < sp; a++)
206: output(a);
207: continue;
208: case 'i':
209: f = sibase;
210: goto unary;
211: case 'I':
212: case 'K':
213: new(a);
214: mitom((c=='I' ? ibase : scale), &a->mantissa);
215: a->scale = 0;
216: continue;
217: case 'k':
218: pop(a);
219: scale = rtoint(a);
220: mvfree(&a->mantissa);
221: if (scale < 0) {
222: scale = 0;
223: skiperr("Scale < 0");
224: }
225: continue;
226: case 'l':
227: case 'L':
228: getreg(c, r);
229: new(a);
230: if (r == NULL) {
231: newscalar(a);
232: } else if (c == 'l') {
233: mcopy(&r->regval.mantissa, &a->mantissa);
234: a->scale = r->regval.scale;
235: } else {
236: reg[c] = r->next;
237: *a = r->regval;
238: free((char *)r);
239: }
240: continue;
241: case 'o':
242: f = sobase;
243: goto unary;
244: case 'O':
245: new(a);
246: mcopy(&outbase, &a->mantissa);
247: a->scale = 0;
248: continue;
249: case 'p':
250: tos(a);
251: output(a);
252: continue;
253: case 'P':
254: f = output;
255: /* Fall through */
256: unary:
257: pop(a);
258: (*f)(a);
259: mvfree(&a->mantissa);
260: continue;
261: case 'q':
262: return (1);
263: continue;
264: case 'Q':
265: pop(a);
266: c = rtoint(a);
267: mvfree(&a->mantissa);
268: return (--c > 0 ? c : 0);
269: continue;
270: case 's':
271: getreg(c, r);
272: pop(a);
273: if (r != NULL) {
274: mvfree(&r->regval.mantissa);
275: } else
276: newreg(c, r);
277: r->regval = *a;
278: continue;
279: case 'S':
280: getreg(c, r);
281: pop(a);
282: newreg(c, r);
283: r->regval = *a;
284: continue;
285: case 'v':
286: tos(a);
287: bcsqrt(a);
288: continue;
289: case 'x':
290: pop(a);
291: execute(a, 1);
292: continue;
293: case 'X':
294: tos(a);
295: mitom(a->scale, &a->mantissa);
296: a->scale = 0;
297: continue;
298: case 'z':
299: new(a);
300: mitom(sp - &stack[0], &a->mantissa);
301: a->scale = 0;
302: continue;
303: case 'Z':
304: {
305: char *s;
306:
307: tos(a);
308: s = mtos(&a->mantissa);
309: mitom(strlen(s), &a->mantissa);
310: a->scale = 0;
311: mpfree(s);
312: }
313: continue;
314: default:
315: fprintf(stderr, "`%c'", c);
316: skiperr("?");
317: }
318: }
319:
320: iseq(x)
321: {
322: return (x==0);
323: }
324:
325: isne(x)
326: {
327: return (x!=0);
328: }
329:
330: islt(x)
331: {
332: return (x<0);
333: }
334:
335: isle(x)
336: {
337: return (x<=0);
338: }
339:
340: isge(x)
341: {
342: return (x>=0);
343: }
344:
345: isgt(x)
346: {
347: return (x>0);
348: }
349:
350: rdstring(v)
351: rvalue *v;
352: {
353: register int c;
354: register char *s,
355: *str;
356: unsigned int len,
357: d = 0; /* nesting depth */
358:
359: s = str = malloc(len=16);
360: while ((c=getc(infile)) != EOF) {
361: if (c == '[')
362: ++d;
363: else if (c == ']' && d-- == 0)
364: break;
365: if (str != NULL)
366: *s++ = c;
367: if (s == &str[len]) {
368: str = realloc(str, len*=2);
369: s = &str[len/2];
370: }
371: }
372: if (str == NULL) {
373: skiperr(oospmsg);
374: } else if (c == EOF) {
375: skiperr("Missing ']'");
376: } else {
377: *s = '\0';
378: v->mantissa.val = str;
379: v->mantissa.len = len;
380: v->scale = -1;
381: return (0);
382: }
383: }
384: rdline(v, fp)
385: rvalue *v;
386: FILE *fp;
387: {
388: register int c;
389: register char *s,
390: *str;
391: unsigned int len;
392:
393: s = str = malloc(len=16);
394: while ((c=getc(fp))!= EOF && c != '\n') {
395: if (str != NULL)
396: *s++ = c;
397: if (s == &str[len]) {
398: str = realloc(str, len*=2);
399: s = &str[len/2];
400: }
401: }
402: if (str == NULL) {
403: skiperr(oospmsg);
404: } else {
405: *s = '\0';
406: v->mantissa.val = str;
407: v->mantissa.len = len;
408: v->scale = -1;
409: return (0);
410: }
411: }
412:
413: output(v)
414: rvalue *v;
415: {
416: if (v->scale < 0)
417: printf("%s\n", v->mantissa.val);
418: else {
419: putnum(v);
420: pnewln();
421: }
422: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.