master xplshn/aruu / cmd / extra / dc.c
   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}