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