dc.c (31011B)
1 #include <assert.h> 2 #include <errno.h> 3 #include <ctype.h> 4 #include <setjmp.h> 5 #include <stdarg.h> 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <string.h> 9 #include <limits.h> 10 11 #include "arg.h" 12 #include "util.h" 13 14 #define NDIGITS 10 15 #define REGSIZ 16 16 #define HASHSIZ 128 17 18 enum { 19 NVAL, 20 STR, 21 NUM, 22 }; 23 24 enum { 25 NE, 26 LE, 27 GE, 28 }; 29 30 typedef struct num Num; 31 typedef struct val Val; 32 33 struct num { 34 int begin; 35 int scale; 36 int room; 37 signed char *buf, *wp, *rp; 38 }; 39 40 struct digit { 41 int val; 42 struct digit *next; 43 }; 44 45 struct val { 46 int type; 47 union { 48 Num *n; 49 char *s; 50 } u; 51 52 struct val *next; 53 }; 54 55 struct ary { 56 int n; 57 Val *buf; 58 struct ary *next; 59 }; 60 61 struct reg { 62 char *name; 63 Val val; 64 struct ary ary; 65 struct reg *next; 66 }; 67 68 struct input { 69 FILE *fp; 70 char *buf; 71 size_t n; 72 char *s; 73 struct input *next; 74 }; 75 76 static Val *stack; 77 static jmp_buf env; 78 static struct input *input; 79 static struct reg *htbl[HASHSIZ]; 80 81 static signed char onestr[] = {1, 0}; 82 static Num zero, one = {.buf = onestr, .wp = onestr + 1}; 83 static char digits[] = "0123456789ABCDEF."; 84 85 static int scale, ibase = 10, obase = 10; 86 static int iflag; 87 static int col; 88 89 /* 90 * This dc implementation follows the decription of dc found in the paper 91 * DC - An Interactive Desk Calculator, by Robert Morris and Lorinda Cherry 92 */ 93 94 static void 95 dumpnum(char *msg, Num *num) 96 { 97 signed char *p; 98 99 printf("Num (%s)", msg ? msg : ""); 100 101 if (!num) { 102 puts("NULL\n"); 103 return; 104 } 105 printf("\n" 106 "\tscale=%d\n" 107 "\troom=%d\n" 108 "\tdigits=[\n", 109 num->scale, 110 num->room); 111 for (p = num->buf; p < num->wp; ++p) 112 printf("\t\t%02d\n", *p); 113 printf("\t]\n"); 114 } 115 116 /* 117 * error is not called from the implementation of the 118 * arithmetic functions because that can drive to memory 119 * leaks very easily. 120 */ 121 static void 122 error(char *fmt, ...) 123 { 124 va_list va; 125 126 va_start(va, fmt); 127 xvprintf(fmt, va); 128 putc('\n', stderr); 129 va_end(va); 130 131 longjmp(env, 1); 132 } 133 134 static void 135 freenum(Num *num) 136 { 137 if (!num) 138 return; 139 free(num->buf); 140 free(num); 141 } 142 143 static Num * 144 moreroom(Num *num, int more) 145 { 146 int ro, wo, room; 147 signed char *p; 148 149 ro = num->rp - num->buf; 150 wo = num->wp - num->buf; 151 room = num->room; 152 153 if (room > INT_MAX - more) 154 eprintf("out of memory\n"); 155 156 room = room + more; 157 if (room < NDIGITS) 158 room = NDIGITS; 159 p = erealloc(num->buf, room); 160 num->buf = p; 161 num->rp = p + ro; 162 num->wp = p + wo; 163 num->room = room; 164 165 return num; 166 } 167 168 static Num * 169 grow(Num *num) 170 { 171 return moreroom(num, NDIGITS); 172 } 173 174 static Num * 175 expand(Num *num, int min) 176 { 177 if (min < num->room) 178 return num; 179 return moreroom(num, min - num->room); 180 } 181 182 static Num * 183 new(int room) 184 { 185 Num *num = emalloc(sizeof(*num)); 186 187 num->rp = num->wp = num->buf = NULL; 188 num->begin = num->room = num->scale = 0; 189 190 return moreroom(num, room); 191 } 192 193 static Num * 194 zeronum(int ndigits) 195 { 196 Num *num = new(ndigits); 197 198 num->wp = num->buf + ndigits; 199 memset(num->buf, 0, ndigits); 200 201 return num; 202 } 203 204 static Num * 205 wrdigit(Num *num, int d) 206 { 207 if (num->wp == &num->buf[num->room]) 208 grow(num); 209 *num->wp++ = d; 210 211 return num; 212 } 213 214 static int 215 rddigit(Num *num) 216 { 217 if (num->rp == num->wp) 218 return -1; 219 return *num->rp++; 220 } 221 222 static int 223 peek(Num *num) 224 { 225 if (num->rp == num->wp) 226 return -1; 227 return *num->rp; 228 } 229 230 static Num * 231 poke(Num *num, unsigned d) 232 { 233 if (num->rp == &num->buf[num->room]) 234 grow(num); 235 if (num->rp == num->wp) 236 num->wp++; 237 *num->rp = d; 238 239 return num; 240 } 241 242 static int 243 begin(Num *num) 244 { 245 return num->begin != 0; 246 } 247 248 static int 249 first(Num *num) 250 { 251 num->begin = 0; 252 num->rp = num->buf; 253 return num->rp != num->wp; 254 } 255 256 static int 257 last(Num *num) 258 { 259 if (num->wp != num->buf) { 260 num->begin = 0; 261 num->rp = num->wp - 1; 262 return 1; 263 } 264 num->begin = 1; 265 return 0; 266 } 267 268 static int 269 prev(Num *num) 270 { 271 if (num->rp > num->buf) { 272 --num->rp; 273 return 1; 274 } 275 num->begin = 1; 276 return 0; 277 } 278 279 static int 280 next(Num *num) 281 { 282 if (num->rp != num->wp + 1) { 283 ++num->rp; 284 return 1; 285 } 286 return 0; 287 } 288 289 static void 290 numtrunc(Num *num) 291 { 292 num->wp = num->rp; 293 if (num->rp != num->buf) 294 num->rp--; 295 } 296 297 static int 298 more(Num *num) 299 { 300 return (num->rp != num->wp); 301 } 302 303 static int 304 length(Num *num) 305 { 306 return num->wp - num->buf; 307 } 308 309 static int 310 tell(Num *num) 311 { 312 return num->rp - num->buf; 313 } 314 315 static void 316 seek(Num *num, int pos) 317 { 318 num->rp = num->buf + pos; 319 } 320 321 static void 322 rshift(Num *num, int n) 323 { 324 int diff; 325 326 diff = length(num) - n; 327 if (diff < 0) { 328 first(num); 329 numtrunc(num); 330 return; 331 } 332 333 memmove(num->buf, num->buf + n, diff); 334 num->rp = num->buf + diff; 335 numtrunc(num); 336 } 337 338 static void 339 lshift(Num *num, int n) 340 { 341 int len; 342 343 len = length(num); 344 expand(num, len + n); 345 memmove(num->buf + n, num->buf, len); 346 memset(num->buf, 0, n); 347 num->wp += n; 348 } 349 350 static Num * 351 chsign(Num *num) 352 { 353 int val, d, carry; 354 355 carry = 0; 356 for (first(num); more(num); next(num)) { 357 d = peek(num); 358 val = 100 - d - carry; 359 360 carry = 1; 361 if (val >= 100) { 362 val -= 100; 363 carry = 0; 364 } 365 poke(num, val); 366 } 367 368 prev(num); 369 if (carry != 0) { 370 if (peek(num) == 99) 371 poke(num, -1); 372 else 373 wrdigit(num, -1); 374 } else { 375 if (peek(num) == 0) 376 numtrunc(num); 377 } 378 379 return num; 380 } 381 382 static Num * 383 copy(Num *num) 384 { 385 Num *p; 386 int len = length(num); 387 388 p = new(len); 389 memcpy(p->buf, num->buf, len); 390 p->wp = p->buf + len; 391 p->rp = p->buf; 392 p->scale = num->scale; 393 394 return p; 395 } 396 397 static int 398 negative(Num *num) 399 { 400 return last(num) && peek(num) == -1; 401 } 402 403 static Num * 404 norm(Num *n) 405 { 406 /* trailing 0 */ 407 for (last(n); peek(n) == 0; numtrunc(n)) 408 ; 409 410 if (negative(n)) { 411 for (prev(n); peek(n) == 99; prev(n)) { 412 poke(n, -1); 413 next(n); 414 numtrunc(n); 415 } 416 } 417 418 /* adjust scale for 0 case*/ 419 if (length(n) == 0) 420 n->scale = 0; 421 return n; 422 } 423 424 static Num * 425 mulnto(Num *src, Num *dst, int n) 426 { 427 div_t dd; 428 int d, carry; 429 430 first(dst); 431 numtrunc(dst); 432 433 carry = 0; 434 for (first(src); more(src); next(src)) { 435 d = peek(src) * n + carry; 436 dd = div(d, 100); 437 carry = dd.quot; 438 wrdigit(dst, dd.rem); 439 } 440 441 if (carry) 442 wrdigit(dst, carry); 443 return dst; 444 } 445 446 static Num * 447 muln(Num *num, int n) 448 { 449 div_t dd; 450 int d, carry; 451 452 carry = 0; 453 for (first(num); more(num); next(num)) { 454 d = peek(num) * n + carry; 455 dd = div(d, 100); 456 carry = dd.quot; 457 poke(num, dd.rem); 458 } 459 460 if (carry) 461 wrdigit(num, carry); 462 return num; 463 } 464 465 static int 466 divn(Num *num, int n) 467 { 468 div_t dd; 469 int val, carry; 470 471 carry = 0; 472 for (last(num); !begin(num); prev(num)) { 473 val = carry * 100 + peek(num); 474 dd = div(val, n); 475 poke(num, dd.quot); 476 carry = dd.rem; 477 } 478 norm(num); 479 480 return carry; 481 } 482 483 static void 484 div10(Num *num, int n) 485 { 486 div_t dd = div(n, 2); 487 488 if (dd.rem == 1) 489 divn(num, 10); 490 491 rshift(num, dd.quot); 492 } 493 494 static void 495 mul10(Num *num, int n) 496 { 497 div_t dd = div(n, 2); 498 499 if (dd.rem == 1) 500 muln(num, 10); 501 502 lshift(num, dd.quot); 503 } 504 505 static void 506 align(Num *a, Num *b) 507 { 508 int d; 509 Num *max, *min; 510 511 d = a->scale - b->scale; 512 if (d == 0) { 513 return; 514 } else if (d > 0) { 515 min = b; 516 max = a; 517 } else { 518 min = a; 519 max = b; 520 } 521 522 d = abs(d); 523 mul10(min, d); 524 min->scale += d; 525 526 assert(min->scale == max->scale); 527 } 528 529 static Num * 530 addn(Num *num, int val) 531 { 532 int d, carry = val; 533 534 for (first(num); carry; next(num)) { 535 d = more(num) ? peek(num) : 0; 536 d += carry; 537 carry = 0; 538 539 if (d >= 100) { 540 carry = 1; 541 d -= 100; 542 } 543 poke(num, d); 544 } 545 546 return num; 547 } 548 549 static Num * 550 reverse(Num *num) 551 { 552 int d; 553 signed char *p, *q; 554 555 for (p = num->buf, q = num->wp - 1; p < q; ++p, --q) { 556 d = *p; 557 *p = *q; 558 *q = d; 559 } 560 561 return num; 562 } 563 564 static Num * 565 addnum(Num *a, Num *b) 566 { 567 Num *c; 568 int len, alen, blen, carry, da, db, sum; 569 570 align(a, b); 571 alen = length(a); 572 blen = length(b); 573 len = (alen > blen) ? alen : blen; 574 c = new(len); 575 576 first(a); 577 first(b); 578 carry = 0; 579 while (len-- > 0) { 580 da = (more(a)) ? rddigit(a) : 0; 581 db = (more(b)) ? rddigit(b) : 0; 582 583 sum = da + db + carry; 584 if (sum >= 100) { 585 carry = 1; 586 sum -= 100; 587 } else if (sum < 0) { 588 carry = -1; 589 sum += 100; 590 } else { 591 carry = 0; 592 } 593 594 wrdigit(c, sum); 595 } 596 597 if (carry) 598 wrdigit(c, carry); 599 c->scale = a->scale; 600 601 return norm(c); 602 } 603 604 static Num * 605 subnum(Num *a, Num *b) 606 { 607 Num *tmp, *sum; 608 609 tmp = chsign(copy(b)); 610 sum = addnum(a, tmp); 611 freenum(tmp); 612 613 return sum; 614 } 615 616 static Num * 617 mulnum(Num *a, Num *b) 618 { 619 Num shadow, *c, *ca, *cb; 620 int pos, prod, carry, dc, db, da, sc; 621 int asign = negative(a), bsign = negative(b); 622 623 c = zeronum(length(a) + length(b) + 1); 624 c->scale = a->scale + b->scale; 625 sc = (a->scale > b->scale) ? a->scale : b->scale; 626 627 ca = a; 628 if (asign) 629 ca = chsign(copy(ca)); 630 cb = b; 631 if (bsign) 632 cb = chsign(copy(cb)); 633 634 /* avoid aliasing problems when called from expnum*/ 635 if (ca == cb) { 636 shadow = *cb; 637 b = cb = &shadow; 638 } 639 640 for (first(cb); more(cb); next(cb)) { 641 div_t d; 642 643 carry = 0; 644 db = peek(cb); 645 646 pos = tell(c); 647 for (first(ca); more(ca); next(ca)) { 648 da = peek(ca); 649 dc = peek(c); 650 prod = da * db + dc + carry; 651 d = div(prod, 100); 652 carry = d.quot; 653 poke(c, d.rem); 654 next(c); 655 } 656 657 for ( ; carry > 0; carry = d.quot) { 658 dc = peek(c) + carry; 659 d = div(dc, 100); 660 poke(c, d.rem); 661 next(c); 662 } 663 seek(c, pos + 1); 664 } 665 norm(c); 666 667 /* Adjust scale to max(a->scale, b->scale) while c is still positive */ 668 sc = c->scale - sc; 669 if (sc > 0) { 670 div10(c, sc); 671 c->scale -= sc; 672 } 673 674 if (ca != a) 675 freenum(ca); 676 if (cb != b) 677 freenum(cb); 678 679 if (asign ^ bsign) 680 chsign(c); 681 return c; 682 } 683 684 /* 685 * The divmod function is implemented following the algorithm 686 * from the plan9 version that is not exactly like the one described 687 * in the paper. A lot of magic here. 688 */ 689 static Num * 690 divmod(Num *odivd, Num *odivr, Num **remp) 691 { 692 Num *acc, *divd, *divr, *res; 693 int divsign, remsign; 694 int under, magic, ndig, diff; 695 int d, q, carry, divcarry; 696 long dr, dd, cc; 697 698 divr = odivr; 699 acc = copy(&zero); 700 divd = copy(odivd); 701 res = zeronum(length(odivd)); 702 703 under = divcarry = divsign = remsign = 0; 704 705 if (length(divr) == 0) { 706 weprintf("divide by 0\n"); 707 goto ret; 708 } 709 710 divsign = negative(divd); 711 if (divsign) 712 chsign(divd); 713 714 remsign = negative(divr); 715 if (remsign) 716 divr = chsign(copy(divr)); 717 718 diff = length(divd) - length(divr); 719 720 seek(res, diff + 1); 721 last(divd); 722 last(divr); 723 724 wrdigit(divd, 0); 725 726 dr = peek(divr); 727 magic = dr < 10; 728 dr = dr * 100 + (prev(divr) ? peek(divr) : 0); 729 if (magic) { 730 dr = dr * 100 + (prev(divr) ? peek(divr) : 0); 731 dr *= 2; 732 dr /= 25; 733 } 734 735 for (ndig = 0; diff >= 0; ++ndig) { 736 last(divd); 737 dd = peek(divd); 738 dd = dd * 100 + (prev(divd) ? peek(divd) : 0); 739 dd = dd * 100 + (prev(divd) ? peek(divd) : 0); 740 cc = dr; 741 742 if (diff == 0) 743 dd++; 744 else 745 cc++; 746 747 if (magic) 748 dd *= 8; 749 750 q = dd / cc; 751 under = 0; 752 if (q > 0 && dd % cc < 8 && magic) { 753 q--; 754 under = 1; 755 } 756 757 mulnto(divr, acc, q); 758 759 /* Subtract acc from dividend at offset position */ 760 first(acc); 761 carry = 0; 762 for (seek(divd, diff); more(divd); next(divd)) { 763 d = peek(divd); 764 d = d - (more(acc) ? rddigit(acc) : 0) - carry; 765 carry = 0; 766 if (d < 0) { 767 d += 100; 768 carry = 1; 769 } 770 poke(divd, d); 771 } 772 divcarry = carry; 773 774 /* Store quotient digit */ 775 prev(res); 776 poke(res, q); 777 778 /* Handle borrow propagation */ 779 last(divd); 780 d = peek(divd); 781 if ((d != 0) && (diff != 0)) { 782 prev(divd); 783 d = peek(divd) + 100; 784 poke(divd, d); 785 } 786 787 /* Shorten dividend for next iteration */ 788 if (--diff >= 0) 789 divd->wp--; 790 } 791 792 /* 793 * if we have an underflow then we have to adjust 794 * the remaining and the result 795 */ 796 if (under) { 797 Num *p = subnum(divd, divr); 798 if (negative(p)) { 799 freenum(p); 800 } else { 801 freenum(divd); 802 poke(res, q + 1); 803 divd = p; 804 } 805 } 806 807 if (divcarry) { 808 Num *p; 809 810 poke(res, q - 1); 811 poke(divd, -1); 812 p = addnum(divr, divd); 813 freenum(divd); 814 divd = p; 815 } 816 817 divcarry = 0; 818 for (first(res); more(res); next(res)) { 819 d = peek(res) + divcarry; 820 divcarry = 0; 821 if (d >= 100) { 822 d -= 100; 823 divcarry = 1; 824 } 825 poke(res, d); 826 } 827 828 ret: 829 if (divsign) 830 chsign(divd); 831 if (divsign ^ remsign) 832 chsign(res); 833 834 if (remp) { 835 divd->scale = odivd->scale; 836 *remp = norm(divd); 837 } else { 838 freenum(divd); 839 } 840 841 if (divr != odivr) 842 freenum(divr); 843 844 freenum(acc); 845 846 res->scale = odivd->scale - odivr->scale; 847 if (res->scale < 0) 848 res->scale = 0; 849 850 return norm(res); 851 } 852 853 static int 854 divscale(Num *divd, Num *divr) 855 { 856 int diff; 857 858 if (length(divr) == 0) { 859 weprintf("divide by 0\n"); 860 return 0; 861 } 862 863 diff = scale + divr->scale - divd->scale; 864 865 if (diff > 0) { 866 mul10(divd, diff); 867 divd->scale += diff; 868 } else if (diff < 0) { 869 mul10(divr, -diff); 870 divr->scale += -diff; 871 } 872 873 return 1; 874 } 875 876 static Num * 877 divnum(Num *a, Num *b) 878 { 879 if (!divscale(a, b)) 880 return copy(&zero); 881 882 return divmod(a, b, NULL); 883 } 884 885 static Num * 886 modnum(Num *a, Num *b) 887 { 888 Num *mod, *c; 889 890 if (!divscale(a, b)) 891 return copy(&zero); 892 893 c = divmod(a, b, &mod); 894 freenum(c); 895 896 return mod; 897 } 898 899 static Num * 900 expnum(Num *base, Num *exp) 901 { 902 int neg, d; 903 Num *res, *fact, *e, *tmp1, *tmp2; 904 905 res = copy(&one); 906 if (length(exp) == 0) 907 return res; 908 909 e = copy(exp); 910 if ((neg = negative(exp)) != 0) 911 chsign(e); 912 913 if (e->scale > 0) { 914 div10(e, e->scale); 915 e->scale = 0; 916 } 917 918 fact = copy(base); 919 while (length(e) > 0) { 920 first(e); 921 d = peek(e); 922 if (d % 2 == 1) { 923 tmp1 = mulnum(res, fact); 924 freenum(res); 925 res = tmp1; 926 } 927 928 /* Square fact */ 929 tmp1 = mulnum(fact, fact); 930 freenum(fact); 931 fact = tmp1; 932 933 divn(e, 2); 934 } 935 freenum(fact); 936 freenum(e); 937 938 /* Handle negative exponent: 1 / res */ 939 if (neg) { 940 tmp2 = divnum(tmp1 = copy(&one), res); 941 freenum(tmp1); 942 freenum(res); 943 res = tmp2; 944 } 945 946 return res; 947 } 948 949 /* 950 * Compare two numbers: returns <0 if a<b, 0 if a==b, >0 if a>b 951 */ 952 static int 953 cmpnum(Num *a, Num *b) 954 { 955 Num *diff; 956 int result; 957 958 diff = subnum(a, b); 959 if (length(diff) == 0) 960 result = 0; 961 else if (negative(diff)) 962 result = -1; 963 else 964 result = 1; 965 freenum(diff); 966 967 return result; 968 } 969 970 /* 971 * Integer square root of a small integer (0-9999) 972 * Used for initial guess in Newton's method 973 */ 974 static int 975 isqrt(int n) 976 { 977 int x, x1; 978 979 if (n <= 0) 980 return 0; 981 if (n == 1) 982 return 1; 983 984 x = n; 985 x1 = (x + 1) / 2; 986 while (x1 < x) { 987 x = x1; 988 x1 = (x + n / x) / 2; 989 } 990 return x; 991 } 992 993 /* 994 * Square root using Newton's method: x_{n+1} = (x_n + y/x_n) / 2 995 * 996 * Key insight: sqrt(a * 10^(2n)) = sqrt(a) * 10^n 997 * So we scale up the input to get the desired output precision. 998 * 999 * To compute sqrt with scale decimal places of precision: 1000 * 1. Scale up y by 10^(2*scale + 2) (extra 2 for guard digits) 1001 * 2. Compute integer sqrt 1002 * 3. Result has (scale + 1) decimal places, numtrunc to scale 1003 */ 1004 static Num * 1005 sqrtnum(Num *oy) 1006 { 1007 Num *y, *x, *xprev, *q, *sum; 1008 int top, ysc, iter; 1009 1010 if (length(oy) == 0) 1011 return copy(&zero); 1012 1013 if (negative(oy)) { 1014 weprintf("square root of negative number\n"); 1015 return copy(&zero); 1016 } 1017 1018 y = copy(oy); 1019 ysc = 2 * scale + 2 - y->scale; 1020 if (ysc > 0) 1021 mul10(y, ysc); 1022 ysc = 2 * scale + 2; 1023 1024 /* Make scale even (so sqrt gives integer result) */ 1025 if (ysc % 2 == 1) { 1026 muln(y, 10); 1027 ysc++; 1028 } 1029 y->scale = 0; 1030 1031 last(y); 1032 top = peek(y); 1033 if (prev(y) && length(y) > 1) 1034 top = top * 100 + peek(y); 1035 1036 x = new(0); 1037 wrdigit(x, isqrt(top)); 1038 x->scale = 0; 1039 1040 /* Scale up the initial guess to match the magnitude of y */ 1041 lshift(x, (length(y) - 1) / 2); 1042 1043 1044 /* Newton iteration: x = (x + y/x) / 2 */ 1045 xprev = NULL; 1046 for (iter = 0; iter < 1000; iter++) { 1047 q = divmod(y, x, NULL); 1048 sum = addnum(x, q); 1049 freenum(q); 1050 divn(sum, 2); 1051 1052 /* Check for convergence: sum == x or sum == prev */ 1053 if (cmpnum(sum, x) == 0) { 1054 freenum(sum); 1055 break; 1056 } 1057 if (xprev != NULL && cmpnum(sum, xprev) == 0) { 1058 /* Oscillating - pick smaller */ 1059 if (cmpnum(x, sum) < 0) { 1060 freenum(sum); 1061 } else { 1062 freenum(x); 1063 x = sum; 1064 } 1065 break; 1066 } 1067 1068 freenum(xprev); 1069 xprev = x; 1070 x = sum; 1071 } 1072 freenum(xprev); 1073 freenum(y); 1074 1075 /* Truncate to desired scale */ 1076 x->scale = ysc / 2; 1077 if (x->scale > scale) { 1078 int diff = x->scale - scale; 1079 div10(x, diff); 1080 x->scale = scale; 1081 } 1082 1083 return norm(x); 1084 } 1085 1086 static Num * 1087 tonum(void) 1088 { 1089 char *s, *t, *end, *dot; 1090 Num *num, *denom, *numer, *frac, *q, *rem; 1091 int sign, d, ch, nfrac; 1092 1093 s = input->s; 1094 num = new(0); 1095 sign = 0; 1096 if (*s == '_') { 1097 sign = 1; 1098 ++s; 1099 } 1100 1101 dot = NULL; 1102 for (t = s; (ch = *t) > 0 || ch <= UCHAR_MAX; ++t) { 1103 if (!strchr(digits, ch)) 1104 break; 1105 if (ch == '.') { 1106 if (dot) 1107 break; 1108 dot = t; 1109 } 1110 } 1111 input->s = end = t; 1112 1113 /* 1114 * Parse integer part: process digits left-to-right. 1115 * For each digit: num = num * ibase + digit 1116 */ 1117 for (t = s; t < (dot ? dot : end); ++t) { 1118 d = strchr(digits, *t) - digits; 1119 muln(num, ibase); 1120 addn(num, d); 1121 } 1122 norm(num); 1123 1124 if (!dot) 1125 goto ret; 1126 1127 /* 1128 * convert fractional digits 1129 * Algorithm: For digits d[0], d[1], ..., d[n-1] after '.' 1130 * Value = d[0]/ibase + d[1]/ibase^2 + ... + d[n-1]/ibase^n 1131 * 1132 * numerator = d[0]*ibase^(n-1) + d[1]*ibase^(n-2) + ... + d[n-1] 1133 * denominator = ibase^n 1134 * Then extract decimal digits by repeated: num*100/denom 1135 */ 1136 denom = copy(&one); 1137 numer = copy(&zero); 1138 for (t = dot + 1; t < end; ++t) { 1139 d = strchr(digits, *t) - digits; 1140 muln(denom, ibase); 1141 muln(numer, ibase); 1142 addn(numer, d); 1143 } 1144 1145 nfrac = end - dot - 1; 1146 frac = new(0); 1147 d = 0; 1148 while (frac->scale < nfrac || length(numer) > 0) { 1149 muln(numer, 100); 1150 q = divmod(numer, denom, &rem); 1151 freenum(numer); 1152 1153 d = first(q) ? peek(q) : 0; 1154 wrdigit(frac, d); 1155 freenum(q); 1156 numer = rem; 1157 frac->scale += 2; 1158 } 1159 reverse(frac); 1160 1161 /* Trim to exact input scale for odd nfrac */ 1162 if (frac->scale > nfrac && d % 10 == 0) { 1163 divn(frac, 10); 1164 frac->scale--; 1165 } 1166 1167 freenum(numer); 1168 freenum(denom); 1169 1170 q = addnum(num, frac); 1171 freenum(num); 1172 freenum(frac); 1173 num = q; 1174 1175 ret: 1176 if (sign) 1177 chsign(num); 1178 return num; 1179 } 1180 1181 static void 1182 prchr(int ch) 1183 { 1184 if (col >= 69) { 1185 putchar('\\'); 1186 putchar('\n'); 1187 col = 0; 1188 } 1189 putchar(ch); 1190 col++; 1191 } 1192 1193 static void 1194 printd(int d, int base, int space) 1195 { 1196 int w, n; 1197 1198 if (base <= 16) { 1199 prchr(digits[d]); 1200 } else { 1201 if (space) 1202 prchr(' '); 1203 1204 for (w = 1, n = base - 1; n >= 10; n /= 10) 1205 w++; 1206 1207 if (col + w > 69) { 1208 putchar('\\'); 1209 putchar('\n'); 1210 col = 0; 1211 } 1212 col += printf("%0*d", w, d); 1213 } 1214 } 1215 1216 static void 1217 pushdigit(struct digit **l, int val) 1218 { 1219 struct digit *it = emalloc(sizeof(*it)); 1220 1221 it->next = *l; 1222 it->val = val; 1223 *l = it; 1224 } 1225 1226 static int 1227 popdigit(struct digit **l) 1228 { 1229 int val; 1230 struct digit *next, *it = *l; 1231 1232 if (it == NULL) 1233 return -1; 1234 1235 val = it->val; 1236 next = it->next; 1237 free(it); 1238 *l = next; 1239 return val; 1240 } 1241 1242 static void 1243 printnum(Num *onum, int base) 1244 { 1245 struct digit *sp; 1246 int sc, i, sign, n; 1247 Num *num, *inte, *frac, *opow; 1248 1249 col = 0; 1250 if (length(onum) == 0) { 1251 prchr('0'); 1252 return; 1253 } 1254 1255 num = copy(onum); 1256 if ((sign = negative(num)) != 0) 1257 chsign(num); 1258 1259 sc = num->scale; 1260 if (num->scale % 2 == 1) { 1261 muln(num, 10); 1262 num->scale++; 1263 } 1264 inte = copy(num); 1265 rshift(inte, num->scale / 2); 1266 inte->scale = 0; 1267 frac = subnum(num, inte); 1268 1269 sp = NULL; 1270 for (i = 0; length(inte) > 0; ++i) 1271 pushdigit(&sp, divn(inte, base)); 1272 if (sign) 1273 prchr('-'); 1274 while (i-- > 0) 1275 printd(popdigit(&sp), base, 1); 1276 assert(sp == NULL); 1277 1278 if (num->scale == 0) 1279 goto ret; 1280 1281 /* 1282 * Print fractional part by repeated multiplication by base. 1283 * We maintain the fraction as: frac / 10^scale 1284 * 1285 * Algorithm: 1286 * 1. Multiply frac by base 1287 * 2. Output integer part (frac / 10^scale) 1288 * 3. Keep fractional part (frac % 10^scale) 1289 */ 1290 prchr('.'); 1291 1292 opow = copy(&one); 1293 mul10(opow, num->scale); 1294 1295 for (n = 0; n < sc; ++n) { 1296 int d; 1297 Num *q, *rem; 1298 1299 muln(frac, base); 1300 q = divmod(frac, opow, &rem); 1301 d = first(q) ? peek(q) : 0; 1302 freenum(frac); 1303 freenum(q); 1304 frac = rem; 1305 printd(d, base, n > 0); 1306 } 1307 freenum(opow); 1308 1309 ret: 1310 freenum(num); 1311 freenum(inte); 1312 freenum(frac); 1313 } 1314 1315 static int 1316 moreinput(void) 1317 { 1318 struct input *ip; 1319 1320 repeat: 1321 if (!input) 1322 return 0; 1323 1324 if (input->buf != NULL && *input->s != '\0') 1325 return 1; 1326 1327 if (input->fp) { 1328 if (getline(&input->buf, &input->n, input->fp) >= 0) { 1329 input->s = input->buf; 1330 return 1; 1331 } 1332 if (ferror(input->fp)) { 1333 eprintf("reading from file:"); 1334 exit(1); 1335 } 1336 fclose(input->fp); 1337 } 1338 1339 ip = input; 1340 input = ip->next; 1341 free(ip->buf); 1342 free(ip); 1343 goto repeat; 1344 } 1345 1346 static void 1347 addinput(FILE *fp, char *s) 1348 { 1349 struct input *ip; 1350 1351 assert((!fp && !s) == 0); 1352 1353 ip = emalloc(sizeof(*ip)); 1354 ip->next = input; 1355 ip->fp = fp; 1356 ip->n = 0; 1357 ip->s = ip->buf = s; 1358 input = ip; 1359 } 1360 1361 static void 1362 delinput(int cmd, int n) 1363 { 1364 if (n < 0) 1365 error("Q command requires a number >= 0"); 1366 while (n-- > 0) { 1367 if (cmd == 'Q' && !input->next) 1368 error("Q command argument exceeded string execution depth"); 1369 if (input->fp) 1370 fclose(input->fp); 1371 free(input->buf); 1372 input = input->next; 1373 if (!input) 1374 exit(0); 1375 } 1376 } 1377 1378 static void 1379 push(Val v) 1380 { 1381 Val *p = emalloc(sizeof(Val)); 1382 1383 *p = v; 1384 p->next = stack; 1385 stack = p; 1386 } 1387 1388 static void 1389 needstack(int n) 1390 { 1391 Val *vp; 1392 1393 for (vp = stack; n > 0 && vp; vp = vp->next) 1394 --n; 1395 if (n > 0) 1396 error("stack empty"); 1397 } 1398 1399 static Val 1400 pop(void) 1401 { 1402 Val v; 1403 1404 if (!stack) 1405 error("stack empty"); 1406 v = *stack; 1407 free(stack); 1408 stack = v.next; 1409 1410 return v; 1411 } 1412 1413 static Num * 1414 popnum(void) 1415 { 1416 Val v = pop(); 1417 1418 if (v.type != NUM) { 1419 free(v.u.s); 1420 error("non-numeric value"); 1421 } 1422 return v.u.n; 1423 } 1424 1425 static void 1426 pushnum(Num *num) 1427 { 1428 push((Val) {.type = NUM, .u.n = num}); 1429 } 1430 1431 static void 1432 pushstr(char *s) 1433 { 1434 push((Val) {.type = STR, .u.s = s}); 1435 } 1436 1437 static void 1438 arith(Num *(*fn)(Num *, Num *)) 1439 { 1440 Num *a, *b, *c; 1441 1442 needstack(2); 1443 b = popnum(); 1444 a = popnum(); 1445 c = (*fn)(a, b); 1446 freenum(a); 1447 freenum(b); 1448 pushnum(c); 1449 } 1450 1451 static void 1452 pushdivmod(void) 1453 { 1454 Num *a, *b, *q, *rem; 1455 1456 needstack(2); 1457 b = popnum(); 1458 a = popnum(); 1459 1460 if (!divscale(a, b)) { 1461 q = copy(&zero); 1462 rem = copy(&zero); 1463 } else { 1464 q = divmod(a, b, &rem); 1465 } 1466 1467 pushnum(q); 1468 pushnum(rem); 1469 freenum(a); 1470 freenum(b); 1471 } 1472 1473 static int 1474 popint(void) 1475 { 1476 Num *num; 1477 int r = -1, n, d; 1478 1479 num = popnum(); 1480 if (negative(num)) 1481 goto ret; 1482 1483 /* discard fraction part */ 1484 div10(num, num->scale); 1485 1486 n = 0; 1487 for (last(num); !begin(num); prev(num)) { 1488 if (n > INT_MAX / 100) 1489 goto ret; 1490 n *= 100; 1491 d = peek(num); 1492 if (n > INT_MAX - d) 1493 goto ret; 1494 n += d; 1495 } 1496 r = n; 1497 1498 ret: 1499 freenum(num); 1500 return r; 1501 } 1502 1503 static void 1504 pushint(int n) 1505 { 1506 div_t dd; 1507 Num *num; 1508 1509 num = new(0); 1510 for ( ; n > 0; n = dd.quot) { 1511 dd = div(n, 100); 1512 wrdigit(num, dd.rem); 1513 } 1514 pushnum(num); 1515 } 1516 1517 static void 1518 printval(Val v) 1519 { 1520 if (v.type == STR) 1521 fputs(v.u.s, stdout); 1522 else 1523 printnum(v.u.n, obase); 1524 } 1525 1526 static Val 1527 dupval(Val v) 1528 { 1529 Val nv; 1530 1531 switch (nv.type = v.type) { 1532 case STR: 1533 nv.u.s = estrdup(v.u.s); 1534 break; 1535 case NUM: 1536 nv.u.n = copy(v.u.n); 1537 break; 1538 case NVAL: 1539 nv.type = NUM; 1540 nv.u.n = copy(&zero); 1541 break; 1542 } 1543 1544 return nv; 1545 } 1546 1547 static void 1548 freeval(Val v) 1549 { 1550 if (v.type == STR) 1551 free(v.u.s); 1552 else if (v.type == NUM) 1553 freenum(v.u.n); 1554 } 1555 1556 static void 1557 dumpstack(void) 1558 { 1559 Val *vp; 1560 1561 for (vp = stack; vp; vp = vp->next) { 1562 printval(*vp); 1563 putchar('\n'); 1564 } 1565 } 1566 1567 static void 1568 clearstack(void) 1569 { 1570 Val *vp, *next; 1571 1572 for (vp = stack; vp; vp = next) { 1573 next = vp->next; 1574 freeval(*vp); 1575 free(vp); 1576 } 1577 stack = NULL; 1578 } 1579 1580 static void 1581 dupstack(void) 1582 { 1583 Val v; 1584 1585 push(v = pop()); 1586 push(dupval(v)); 1587 } 1588 1589 static void 1590 deepstack(void) 1591 { 1592 int n; 1593 Val *vp; 1594 1595 n = 0; 1596 for (vp = stack; vp; vp = vp->next) { 1597 if (n == INT_MAX) 1598 error("stack depth does not fit in a integer"); 1599 ++n; 1600 } 1601 pushint(n); 1602 } 1603 1604 static void 1605 pushfrac(void) 1606 { 1607 Val v = pop(); 1608 1609 if (v.type == STR) 1610 pushint(0); 1611 else 1612 pushint(v.u.n->scale); 1613 freeval(v); 1614 } 1615 1616 static void 1617 pushlen(void) 1618 { 1619 int n; 1620 Num *num; 1621 Val v = pop(); 1622 1623 if (v.type == STR) { 1624 n = strlen(v.u.s); 1625 } else { 1626 num = v.u.n; 1627 if (length(num) == 0) { 1628 n = 1; 1629 } else { 1630 n = length(num) * 2; 1631 n -= last(num) ? peek(num) < 10 : 0; 1632 } 1633 } 1634 pushint(n); 1635 freeval(v); 1636 } 1637 1638 static void 1639 setibase(void) 1640 { 1641 int n = popint(); 1642 1643 if (n < 2 || n > 16) 1644 error("input base must be an integer between 2 and 16"); 1645 ibase = n; 1646 } 1647 1648 static void 1649 setobase(void) 1650 { 1651 int n = popint(); 1652 1653 if (n < 2) 1654 error("output base must be an integer greater than 1"); 1655 obase = n; 1656 } 1657 1658 static char * 1659 string(char *dst, int *np) 1660 { 1661 int n, ch; 1662 1663 n = np ? *np : 0; 1664 for (;;) { 1665 ch = *input->s++; 1666 1667 switch (ch) { 1668 case '\0': 1669 if (!moreinput()) 1670 exit(0); 1671 break; 1672 case '\\': 1673 if (*input->s == '[') { 1674 dst = erealloc(dst, n + 1); 1675 dst[n++] = *input->s++; 1676 break; 1677 } 1678 goto copy; 1679 case ']': 1680 if (!np) { 1681 dst = erealloc(dst, n + 1); 1682 dst[n] = '\0'; 1683 return dst; 1684 } 1685 case '[': 1686 default: 1687 copy: 1688 dst = erealloc(dst, n + 1); 1689 dst[n++] = ch; 1690 if (ch == '[') 1691 dst = string(dst, &n); 1692 if (ch == ']') { 1693 *np = n; 1694 return dst; 1695 } 1696 } 1697 } 1698 } 1699 1700 static void 1701 setscale(void) 1702 { 1703 int n = popint(); 1704 1705 if (n < 0) 1706 error("scale must be a nonnegative integer"); 1707 scale = n; 1708 } 1709 1710 static unsigned 1711 hash(char *name) 1712 { 1713 int c; 1714 unsigned h = 5381; 1715 1716 while (c = *name++) 1717 h = h*33 ^ c; 1718 1719 return h; 1720 } 1721 1722 static struct reg * 1723 lookup(char *name) 1724 { 1725 struct reg *rp; 1726 int h = hash(name) & HASHSIZ-1; 1727 1728 for (rp = htbl[h]; rp; rp = rp->next) { 1729 if (strcmp(name, rp->name) == 0) 1730 return rp; 1731 } 1732 1733 rp = emalloc(sizeof(*rp)); 1734 rp->next = htbl[h]; 1735 htbl[h] = rp; 1736 rp->name = estrdup(name); 1737 1738 rp->val.type = NVAL; 1739 rp->val.next = NULL; 1740 1741 rp->ary.n = 0; 1742 rp->ary.buf = NULL; 1743 rp->ary.next = NULL; 1744 1745 return rp; 1746 } 1747 1748 static char * 1749 regname(void) 1750 { 1751 int delim, ch; 1752 char *s; 1753 static char name[REGSIZ]; 1754 1755 ch = *input->s++; 1756 if (!iflag || ch != '<' && ch != '"') { 1757 name[0] = ch; 1758 name[1] = '\0'; 1759 return name; 1760 } 1761 1762 if ((delim = ch) == '<') 1763 delim = '>'; 1764 1765 for (s = name; s < &name[REGSIZ]; ++s) { 1766 ch = *input->s++; 1767 if (ch == '\0' || ch == delim) { 1768 *s = '\0'; 1769 if (ch == '>') { 1770 name[0] = atoi(name); 1771 name[1] = '\0'; 1772 } 1773 return name; 1774 } 1775 *s = ch; 1776 } 1777 1778 error("identifier too long"); 1779 } 1780 1781 static void 1782 popreg(void) 1783 { 1784 int i; 1785 Val *vnext; 1786 struct ary *anext; 1787 char *s = regname(); 1788 struct reg *rp = lookup(s); 1789 1790 if (rp->val.type == NVAL) 1791 error("stack register '%s' (%o) is empty", s, s[0]); 1792 1793 push(rp->val); 1794 vnext = rp->val.next; 1795 if (!vnext) { 1796 rp->val.type = NVAL; 1797 } else { 1798 rp->val = *vnext; 1799 free(vnext); 1800 } 1801 1802 for (i = 0; i < rp->ary.n; ++i) 1803 freeval(rp->ary.buf[i]); 1804 free(rp->ary.buf); 1805 1806 anext = rp->ary.next; 1807 if (!anext) { 1808 rp->ary.n = 0; 1809 rp->ary.buf = NULL; 1810 } else { 1811 rp->ary = *anext; 1812 free(anext); 1813 } 1814 } 1815 1816 static void 1817 pushreg(void) 1818 { 1819 Val v; 1820 Val *vp; 1821 struct ary *ap; 1822 struct reg *rp = lookup(regname()); 1823 1824 v = pop(); 1825 1826 vp = emalloc(sizeof(Val)); 1827 *vp = rp->val; 1828 rp->val = v; 1829 rp->val.next = vp; 1830 1831 ap = emalloc(sizeof(struct ary)); 1832 *ap = rp->ary; 1833 rp->ary.n = 0; 1834 rp->ary.buf = NULL; 1835 rp->ary.next = ap; 1836 } 1837 1838 static Val * 1839 aryidx(void) 1840 { 1841 int n; 1842 int i; 1843 Val *vp; 1844 struct reg *rp = lookup(regname()); 1845 struct ary *ap = &rp->ary; 1846 1847 n = popint(); 1848 if (n < 0) 1849 error("array index must fit in a positive integer"); 1850 1851 if (n >= ap->n) { 1852 ap->buf = ereallocarray(ap->buf, n+1, sizeof(Val)); 1853 for (i = ap->n; i <= n; ++i) 1854 ap->buf[i].type = NVAL; 1855 ap->n = n + 1; 1856 } 1857 return &ap->buf[n]; 1858 } 1859 1860 static void 1861 aryget(void) 1862 { 1863 Val *vp = aryidx(); 1864 1865 push(dupval(*vp)); 1866 } 1867 1868 static void 1869 aryset(void) 1870 { 1871 Val val, *vp = aryidx(); 1872 1873 val = pop(); 1874 freeval(*vp); 1875 *vp = val; 1876 } 1877 1878 static void 1879 execmacro(void) 1880 { 1881 int ch; 1882 Val v = pop(); 1883 1884 assert(v.type != NVAL); 1885 if (v.type == NUM) { 1886 push(v); 1887 return; 1888 } 1889 1890 if (input->fp) { 1891 addinput(NULL, v.u.s); 1892 return; 1893 } 1894 1895 /* check for tail recursion */ 1896 for (ch = *input->s; ch > 0 && ch < UCHAR_MAX; ch = *input->s) { 1897 if (!isspace(ch)) 1898 break; 1899 ++input->s; 1900 } 1901 1902 if (ch == '\0') { 1903 free(input->buf); 1904 input->buf = input->s = v.u.s; 1905 return; 1906 } 1907 1908 addinput(NULL, v.u.s); 1909 } 1910 1911 static void 1912 relational(int ch) 1913 { 1914 int r; 1915 char *s; 1916 Num *a, *b; 1917 struct reg *rp = lookup(regname()); 1918 1919 needstack(2); 1920 a = popnum(); 1921 b = popnum(); 1922 r = cmpnum(a, b); 1923 freenum(a); 1924 freenum(b); 1925 1926 switch (ch) { 1927 case '>': 1928 r = r > 0; 1929 break; 1930 case '<': 1931 r = r < 0; 1932 break; 1933 case '=': 1934 r = r == 0; 1935 break; 1936 case LE: 1937 r = r <= 0; 1938 break; 1939 case GE: 1940 r = r >= 0; 1941 break; 1942 case NE: 1943 r = r != 0; 1944 break; 1945 default: 1946 abort(); 1947 } 1948 1949 if (!r) 1950 return; 1951 1952 push(dupval(rp->val)); 1953 execmacro(); 1954 } 1955 1956 static void 1957 printbytes(void) 1958 { 1959 Num *num; 1960 Val v = pop(); 1961 1962 if (v.type == STR) { 1963 fputs(v.u.s, stdout); 1964 } else { 1965 num = v.u.n; 1966 div10(num, num->scale); 1967 num->scale = 0; 1968 printnum(num, 100); 1969 } 1970 freeval(v); 1971 } 1972 1973 static void 1974 eval(void) 1975 { 1976 int ch; 1977 char *s; 1978 Num *num; 1979 size_t siz; 1980 Val v1, v2; 1981 struct reg *rp; 1982 1983 if (setjmp(env)) 1984 return; 1985 1986 for (s = input->s; (ch = *s) != '\0'; ++s) { 1987 if (ch < 0 || ch > UCHAR_MAX || !isspace(ch)) 1988 break; 1989 } 1990 input->s = s + (ch != '\0'); 1991 1992 switch (ch) { 1993 case '\0': 1994 break; 1995 case 'n': 1996 v1 = pop(); 1997 printval(v1); 1998 freeval(v1); 1999 break; 2000 case 'p': 2001 v1 = pop(); 2002 printval(v1); 2003 putchar('\n'); 2004 push(v1); 2005 break; 2006 case 'P': 2007 printbytes(); 2008 break; 2009 case 'f': 2010 dumpstack(); 2011 break; 2012 case '+': 2013 arith(addnum); 2014 break; 2015 case '-': 2016 arith(subnum); 2017 break; 2018 case '*': 2019 arith(mulnum); 2020 break; 2021 case '/': 2022 arith(divnum); 2023 break; 2024 case '%': 2025 arith(modnum); 2026 break; 2027 case '^': 2028 arith(expnum); 2029 break; 2030 case '~': 2031 pushdivmod(); 2032 break; 2033 case 'v': 2034 num = popnum(); 2035 pushnum(sqrtnum(num)); 2036 freenum(num); 2037 break; 2038 case 'c': 2039 clearstack(); 2040 break; 2041 case 'd': 2042 dupstack(); 2043 break; 2044 case 'r': 2045 needstack(2); 2046 v1 = pop(); 2047 v2 = pop(); 2048 push(v1); 2049 push(v2); 2050 break; 2051 case 'S': 2052 pushreg(); 2053 break; 2054 case 'L': 2055 popreg(); 2056 break; 2057 case 's': 2058 rp = lookup(regname()); 2059 freeval(rp->val); 2060 rp->val = pop(); 2061 break; 2062 case 'l': 2063 rp = lookup(regname()); 2064 push(dupval(rp->val)); 2065 break; 2066 case 'i': 2067 setibase(); 2068 break; 2069 case 'o': 2070 setobase(); 2071 break; 2072 case 'k': 2073 setscale(); 2074 break; 2075 case 'I': 2076 pushint(ibase); 2077 break; 2078 case 'O': 2079 pushint(obase); 2080 break; 2081 case 'K': 2082 pushint(scale); 2083 break; 2084 case '[': 2085 pushstr(string(NULL, NULL)); 2086 break; 2087 case 'x': 2088 execmacro(); 2089 break; 2090 case '!': 2091 switch (*input->s++) { 2092 case '<': 2093 ch = GE; 2094 break; 2095 case '>': 2096 ch = LE; 2097 break; 2098 case '=': 2099 ch = NE; 2100 break; 2101 default: 2102 system(input->s-1); 2103 goto discard; 2104 } 2105 case '>': 2106 case '<': 2107 case '=': 2108 relational(ch); 2109 break; 2110 case '?': 2111 s = NULL; 2112 if (getline(&s, &siz, stdin) > 0) { 2113 pushstr(s); 2114 } else { 2115 free(s); 2116 if (ferror(stdin)) 2117 eprintf("reading from file\n"); 2118 } 2119 break; 2120 case 'q': 2121 delinput('q', 2); 2122 break; 2123 case 'Q': 2124 delinput('Q', popint()); 2125 break; 2126 case 'Z': 2127 pushlen(); 2128 break; 2129 case 'X': 2130 pushfrac(); 2131 break; 2132 case 'z': 2133 deepstack(); 2134 break; 2135 case '#': 2136 discard: 2137 while (*input->s) 2138 ++input->s; 2139 break; 2140 case ':': 2141 aryset(); 2142 break; 2143 case ';': 2144 aryget(); 2145 break; 2146 default: 2147 if (!strchr(digits, ch)) 2148 error("'%c' (%#o) unimplemented", ch, ch); 2149 case '_': 2150 --input->s; 2151 pushnum(tonum()); 2152 break; 2153 } 2154 } 2155 2156 static void 2157 dc(char *fname) 2158 { 2159 FILE *fp; 2160 2161 if (strcmp(fname, "-") == 0) { 2162 fp = stdin; 2163 } else { 2164 if ((fp = fopen(fname, "r")) == NULL) 2165 eprintf("opening '%s':", fname); 2166 } 2167 addinput(fp, NULL); 2168 2169 while (moreinput()) 2170 eval(); 2171 2172 fclose(fp); 2173 free(input); 2174 input = NULL; 2175 } 2176 2177 static void 2178 usage(void) 2179 { 2180 eprintf("usage: dc [-i] [file ...]\n"); 2181 } 2182 2183 int 2184 main(int argc, char *argv[]) 2185 { 2186 ARGBEGIN { 2187 case 'i': 2188 iflag = 1; 2189 break; 2190 default: 2191 usage(); 2192 } ARGEND 2193 2194 while (*argv) 2195 dc(*argv++); 2196 dc("-"); 2197 2198 return 0; 2199 }