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