1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 #include <stdio.h> 31 #include <signal.h> 32 #include <errno.h> 33 #include <sys/stat.h> 34 #include <sys/types.h> 35 #include <limits.h> 36 #include "dc.h" 37 #include <locale.h> 38 #include <stdlib.h> 39 40 #define LASTFUN 026 41 long longest = 0, maxsize = 0, active = 0; 42 int lall = 0, lrel = 0, lcopy = 0, lmore = 0, lbytes = 0; 43 44 /* 45 * Routine to handle sign extension of characters on systems that do not 46 * do automatic sign extension. This should be portable to all 2's and 1's 47 * complement systems that do or do not provide automatic sign 48 * extension. If the system provides automatic sign extension or the 49 * value of 'c' is positive, ctoint() will always return quickly, 50 * otherwise ctoint() will search for the negative value by attempting 51 * to wrap 'c' to 0. The number of increments needed to get to 0 is the 52 * negative value. 53 * 54 * Note: This assummes that the representation of values stored in chars 55 * is sequential and allowed to wrap, and that values < 128 are 56 * positive. While this is true on 1's and 2's complement machines, it 57 * may vary on less common architectures. 58 */ 59 60 #if __STDC__ 61 int 62 ctoint(char c) 63 #else 64 int 65 ctoint(unsigned char c) 66 #endif 67 { 68 int i; 69 70 if ((unsigned char)c <= SCHAR_MAX) 71 return ((int)c); /* Normal promotion will work */ 72 for (i = 0; c++; i--); /* Scan for negative value */ 73 return (i); 74 } 75 76 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 77 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't. */ 78 #endif 79 80 void commnds(void) __NORETURN; 81 82 int 83 main(int argc, char **argv) 84 { 85 (void) setlocale(LC_ALL, ""); 86 (void) textdomain(TEXT_DOMAIN); 87 88 init(argc, argv); 89 commnds(); 90 /* NOTREACHED */ 91 } 92 93 void 94 commnds(void) 95 { 96 int c; 97 struct blk *p, *q; 98 long l; 99 int sign; 100 struct blk **ptr, *s, *t; 101 struct sym *sp; 102 int sk, sk1, sk2; 103 int n, d; 104 int scalev; /* scaling value for converting blks to integers */ 105 106 for (; ; ) { 107 if (((c = readc()) >= '0' && c <= '9') || 108 (c >= 'A' && c <= 'F') || c == '.') { 109 unreadc(c); 110 p = readin(); 111 pushp(p); 112 continue; 113 } 114 switch (c) { 115 case ' ': 116 case '\n': 117 case 0377: 118 case EOF: 119 continue; 120 case 'Y': 121 sdump("stk", *stkptr); 122 printf(gettext 123 ("all %ld rel %ld headmor %ld\n"), all, rel, 124 headmor); 125 printf(gettext("nbytes %ld\n"), nbytes); 126 printf(gettext 127 ("longest %ld active %ld maxsize %ld\n"), longest, 128 active, maxsize); 129 printf(gettext 130 ("new all %d rel %d copy %d more %d lbytes %d\n"), 131 lall, lrel, lcopy, lmore, lbytes); 132 lall = lrel = lcopy = lmore = lbytes = 0; 133 continue; 134 case '_': 135 p = readin(); 136 savk = sunputc(p); 137 chsign(p); 138 sputc(p, savk); 139 pushp(p); 140 continue; 141 case '-': 142 subt(); 143 continue; 144 case '+': 145 if (eqk() != 0) 146 continue; 147 binop('+'); 148 continue; 149 case '*': 150 arg1 = pop(); 151 EMPTY; 152 arg2 = pop(); 153 EMPTYR(arg1); 154 sk1 = sunputc(arg1); 155 sk2 = sunputc(arg2); 156 binop('*'); 157 p = pop(); 158 sunputc(p); 159 savk = n = sk1 + sk2; 160 if (n > k && n > sk1 && n > sk2) { 161 sk = sk1; 162 if (sk < sk2) 163 sk = sk2; 164 if (sk < k) 165 sk = k; 166 p = removc(p, n - sk); 167 savk = sk; 168 } 169 sputc(p, savk); 170 pushp(p); 171 continue; 172 case '/': 173 casediv: 174 if (dscale() != 0) 175 continue; 176 binop('/'); 177 if (irem != 0) 178 release(irem); 179 release(rem); 180 continue; 181 case '%': 182 if (dscale() != 0) 183 continue; 184 binop('/'); 185 p = pop(); 186 release(p); 187 if (irem == 0) { 188 sputc(rem, skr + k); 189 pushp(rem); 190 continue; 191 } 192 p = add0(rem, skd - (skr + k)); 193 q = add(p, irem); 194 release(p); 195 release(irem); 196 sputc(q, skd); 197 pushp(q); 198 continue; 199 case 'v': 200 p = pop(); 201 EMPTY; 202 savk = sunputc(p); 203 if (length(p) == 0) { 204 sputc(p, savk); 205 pushp(p); 206 continue; 207 } 208 if ((c = sbackc(p)) < 0) { 209 error(gettext("sqrt of neg number\n")); 210 } 211 if (k < savk) 212 n = savk; 213 else { 214 n = k * 2 - savk; 215 savk = k; 216 } 217 arg1 = add0(p, n); 218 arg2 = sqrt(arg1); 219 sputc(arg2, savk); 220 pushp(arg2); 221 continue; 222 case '^': 223 neg = 0; 224 arg1 = pop(); 225 EMPTY; 226 if (sunputc(arg1) != 0) 227 error(gettext("exp not an integer\n")); 228 arg2 = pop(); 229 EMPTYR(arg1); 230 if (sfbeg(arg1) == 0 && sbackc(arg1) < 0) { 231 neg++; 232 chsign(arg1); 233 } 234 if (length(arg1) >= 3) 235 error(gettext("exp too big\n")); 236 savk = sunputc(arg2); 237 p = exp(arg2, arg1); 238 release(arg2); 239 rewind(arg1); 240 c = sgetc(arg1); 241 if (c == EOF) 242 c = 0; 243 else if (sfeof(arg1) == 0) 244 c = sgetc(arg1) * 100 + c; 245 d = c * savk; 246 release(arg1); 247 if (k >= savk) 248 n = k; 249 else 250 n = savk; 251 if (n < d) { 252 q = removc(p, d - n); 253 sputc(q, n); 254 pushp(q); 255 } else { 256 sputc(p, d); 257 pushp(p); 258 } 259 if (neg == 0) 260 continue; 261 p = pop(); 262 q = salloc(2); 263 sputc(q, 1); 264 sputc(q, 0); 265 pushp(q); 266 pushp(p); 267 goto casediv; 268 case 'z': 269 p = salloc(2); 270 n = stkptr - stkbeg; 271 if (n >= 100) { 272 sputc(p, n / 100); 273 n %= 100; 274 } 275 sputc(p, n); 276 sputc(p, 0); 277 pushp(p); 278 continue; 279 case 'Z': 280 p = pop(); 281 EMPTY; 282 n = (length(p) - 1) << 1; 283 fsfile(p); 284 sbackc(p); 285 if (sfbeg(p) == 0) { 286 if ((c = sbackc(p)) < 0) { 287 n -= 2; 288 if (sfbeg(p) == 1) 289 n += 1; 290 else { 291 if ((c = sbackc(p)) == 0) 292 n += 1; 293 else if (c > 90) 294 n -= 1; 295 } 296 } else 297 if (c < 10) 298 n -= 1; 299 } 300 release(p); 301 q = salloc(1); 302 if (n >= 100) { 303 sputc(q, n%100); 304 n /= 100; 305 } 306 sputc(q, n); 307 sputc(q, 0); 308 pushp(q); 309 continue; 310 case 'i': 311 p = pop(); 312 EMPTY; 313 p = scalint(p); 314 315 /* 316 * POSIX.2 317 * input base must be between 2 and 16 318 */ 319 n = length(p); 320 q = copy(p, n); 321 fsfile(q); 322 c = sbackc(q); 323 if (sfbeg(q) == 0) 324 error(gettext("input base is too large\n")); 325 if (c < 2) 326 error(gettext("input base is too small\n")); 327 if (c > 16) 328 error(gettext("input base is too large\n")); 329 release(q); 330 331 release(inbas); 332 inbas = p; 333 continue; 334 case 'I': 335 p = copy(inbas, length(inbas) + 1); 336 sputc(p, 0); 337 pushp(p); 338 continue; 339 case 'o': 340 p = pop(); 341 EMPTY; 342 p = scalint(p); 343 sign = 0; 344 n = length(p); 345 q = copy(p, n); 346 fsfile(q); 347 l = c = sbackc(q); 348 if (n != 1) { 349 if (c < 0) { 350 sign = 1; 351 chsign(q); 352 n = length(q); 353 fsfile(q); 354 l = c = sbackc(q); 355 } 356 if (n != 1) { 357 while (sfbeg(q) == 0) 358 l = l * 100 + sbackc(q); 359 } 360 } 361 362 /* 363 * POSIX.2 364 * Check that output base is less than or equal 365 * BC_BASE_MAX. 366 */ 367 if (l > BC_BASE_MAX) 368 error(gettext("output base is too large\n")); 369 370 logo = log2(l); 371 obase = l; 372 release(basptr); 373 if (sign == 1) 374 obase = -l; 375 basptr = p; 376 outdit = bigot; 377 if (n == 1 && sign == 0) { 378 if (c <= 16) { 379 outdit = hexot; 380 fw = 1; 381 fw1 = 0; 382 383 /* 384 * POSIX.2 385 * Line length is 70 characters, 386 * including newline. 387 */ 388 ll = 70; 389 release(q); 390 continue; 391 } 392 } 393 n = 0; 394 if (sign == 1) 395 n++; 396 p = salloc(1); 397 sputc(p, -1); 398 t = add(p, q); 399 n += length(t) * 2; 400 fsfile(t); 401 if ((c = sbackc(t)) > 9) 402 n++; 403 release(t); 404 release(q); 405 release(p); 406 fw = n; 407 fw1 = n-1; 408 409 /* 410 * POSIX.2 411 * Line length is 70 characters including newline 412 */ 413 ll = 70; 414 if (fw >= ll) 415 continue; 416 ll = (70 / fw) * fw; 417 continue; 418 case 'O': 419 p = copy(basptr, length(basptr) + 1); 420 sputc(p, 0); 421 pushp(p); 422 continue; 423 case '[': 424 n = 0; 425 p = salloc(0); 426 for (; ; ) { 427 if ((c = readc()) == ']') { 428 if (n == 0) 429 break; 430 n--; 431 } 432 sputc(p, c); 433 if (c == '[') 434 n++; 435 } 436 pushp(p); 437 continue; 438 case 'k': 439 p = pop(); 440 EMPTY; 441 p = scalint(p); 442 443 /* 444 * POSIX.2 445 * Make sure scaling factor is between 0 and 446 * BC_SCALE_MAX. Copy p to q and figure the 447 * scaling factor. 448 */ 449 n = length(p); 450 q = copy(p, n); 451 fsfile(q); 452 c = 0; 453 if ((sfbeg(q) == 0) && ((c = sbackc(q)) < 0)) 454 error(gettext("invalid scale factor\n")); 455 456 scalev = 1; 457 while (c < BC_SCALE_MAX && sfbeg(q) == 0) 458 c = (c * (scalev *= 100)) + sbackc(q); 459 460 if (c > BC_SCALE_MAX) 461 error(gettext("scale factor is too large\n")); 462 release(q); 463 464 rewind(p); 465 k = sfeof(p) ? 0 : sgetc(p); 466 release(scalptr); 467 scalptr = p; 468 continue; 469 470 case 'K': 471 p = copy(scalptr, length(scalptr) + 1); 472 sputc(p, 0); 473 pushp(p); 474 continue; 475 case 'X': 476 p = pop(); 477 EMPTY; 478 fsfile(p); 479 n = sbackc(p); 480 release(p); 481 p = salloc(2); 482 sputc(p, n); 483 sputc(p, 0); 484 pushp(p); 485 continue; 486 case 'Q': 487 p = pop(); 488 EMPTY; 489 if (length(p) > 2) { 490 error("Q?\n"); 491 } 492 rewind(p); 493 if ((c = sgetc(p)) < 0) { 494 error(gettext("neg Q\n")); 495 } 496 release(p); 497 while (c-- > 0) { 498 if (readptr == &readstk[0]) { 499 error("readstk?\n"); 500 } 501 if (*readptr != 0) 502 release(*readptr); 503 readptr--; 504 } 505 continue; 506 case 'q': 507 if (readptr <= &readstk[1]) 508 exit(0); 509 if (*readptr != 0) 510 release(*readptr); 511 readptr--; 512 if (*readptr != 0) 513 release(*readptr); 514 readptr--; 515 continue; 516 case 'f': 517 if (stkptr == &stack[0]) 518 printf(gettext("empty stack\n")); 519 else { 520 for (ptr = stkptr; ptr > &stack[0]; ) { 521 print(*ptr--); 522 } 523 } 524 continue; 525 case 'p': 526 if (stkptr == &stack[0]) 527 printf(gettext("empty stack\n")); 528 else { 529 print(*stkptr); 530 } 531 continue; 532 case 'P': 533 p = pop(); 534 EMPTY; 535 sputc(p, 0); 536 printf("%s", p->beg); 537 release(p); 538 continue; 539 case 'd': 540 if (stkptr == &stack[0]) { 541 printf(gettext("empty stack\n")); 542 continue; 543 } 544 q = *stkptr; 545 n = length(q); 546 p = copy(*stkptr, n); 547 pushp(p); 548 continue; 549 case 'c': 550 while (stkerr == 0) { 551 p = pop(); 552 if (stkerr == 0) 553 release(p); 554 } 555 continue; 556 case 'S': 557 if (stkptr == &stack[0]) { 558 error(gettext("save: args\n")); 559 } 560 c = readc() & 0377; 561 sptr = stable[c]; 562 sp = stable[c] = sfree; 563 sfree = sfree->next; 564 if (sfree == 0) 565 goto sempty; 566 sp->next = sptr; 567 p = pop(); 568 EMPTY; 569 if (c >= ARRAYST) { 570 q = copy(p, length(p) + PTRSZ); 571 for (n = 0; n < PTRSZ; n++) { 572 sputc(q, 0); 573 } 574 release(p); 575 p = q; 576 } 577 sp->val = p; 578 continue; 579 sempty: 580 error(gettext("symbol table overflow\n")); 581 case 's': 582 if (stkptr == &stack[0]) { 583 error(gettext("save:args\n")); 584 } 585 c = readc() & 0377; 586 sptr = stable[c]; 587 if (sptr != 0) { 588 p = sptr->val; 589 if (c >= ARRAYST) { 590 rewind(p); 591 while (sfeof(p) == 0) 592 release(getwd(p)); 593 } 594 release(p); 595 } else { 596 sptr = stable[c] = sfree; 597 sfree = sfree->next; 598 if (sfree == 0) 599 goto sempty; 600 sptr->next = 0; 601 } 602 p = pop(); 603 sptr->val = p; 604 continue; 605 case 'l': 606 load(); 607 continue; 608 case 'L': 609 c = readc() & 0377; 610 sptr = stable[c]; 611 if (sptr == 0) { 612 error("L?\n"); 613 } 614 stable[c] = sptr->next; 615 sptr->next = sfree; 616 sfree = sptr; 617 p = sptr->val; 618 if (c >= ARRAYST) { 619 rewind(p); 620 while (sfeof(p) == 0) { 621 q = getwd(p); 622 if (q != 0) 623 release(q); 624 } 625 } 626 pushp(p); 627 continue; 628 case ':': 629 p = pop(); 630 EMPTY; 631 q = scalint(p); 632 fsfile(q); 633 634 /* 635 * POSIX.2 636 * Make sure index is between 0 and BC_DIM_MAX-1 637 */ 638 c = 0; 639 if ((sfbeg(q) == 0) && ((c = sbackc(q)) < 0)) 640 error(gettext("invalid index\n")); 641 scalev = 1; 642 while (c < BC_DIM_MAX && sfbeg(q) == 0) 643 c = (c * (scalev *= 100)) + sbackc(q); 644 645 if (c >= BC_DIM_MAX) 646 error(gettext("index is too large\n")); 647 648 release(q); 649 n = readc() & 0377; 650 sptr = stable[n]; 651 if (sptr == 0) { 652 sptr = stable[n] = sfree; 653 sfree = sfree->next; 654 if (sfree == 0) 655 goto sempty; 656 sptr->next = 0; 657 p = salloc((c + PTRSZ) * PTRSZ); 658 zero(p); 659 } else { 660 p = sptr->val; 661 if (length(p) - PTRSZ < c * PTRSZ) { 662 q = copy(p, (c + PTRSZ) * PTRSZ); 663 release(p); 664 p = q; 665 } 666 } 667 seekc(p, c * PTRSZ); 668 q = lookwd(p); 669 if (q != NULL) 670 release(q); 671 s = pop(); 672 EMPTY; 673 salterwd((struct wblk *)p, s); 674 sptr->val = p; 675 continue; 676 677 case ';': 678 p = pop(); 679 EMPTY; 680 q = scalint(p); 681 fsfile(q); 682 683 /* 684 * POSIX.2 685 * Make sure index is between 0 and BC_DIM_MAX-1 686 */ 687 c = 0; 688 if ((sfbeg(q) == 0) && ((c = sbackc(q)) < 0)) 689 error(gettext("invalid index\n")); 690 scalev = 1; 691 while (c < BC_DIM_MAX && sfbeg(q) == 0) 692 c = (c * (scalev *= 100)) + sbackc(q); 693 694 if (c >= BC_DIM_MAX) 695 error(gettext("index is too large\n")); 696 697 release(q); 698 n = readc() & 0377; 699 sptr = stable[n]; 700 if (sptr != 0) { 701 p = sptr->val; 702 if (length(p) - PTRSZ >= c * PTRSZ) { 703 seekc(p, c * PTRSZ); 704 s = getwd(p); 705 if (s != 0) { 706 q = copy(s, length(s)); 707 pushp(q); 708 continue; 709 } 710 } 711 } 712 q = salloc(1); /* uninitializd array elt prints as 0 */ 713 sputc(q, 0); 714 pushp(q); 715 continue; 716 case 'x': 717 execute: 718 p = pop(); 719 EMPTY; 720 if ((readptr != &readstk[0]) && (*readptr != 0)) { 721 if ((*readptr)->rd == (*readptr)->wt) 722 release(*readptr); 723 else { 724 if (readptr++ == &readstk[RDSKSZ]) { 725 error(gettext 726 ("nesting depth\n")); 727 } 728 } 729 } else 730 readptr++; 731 *readptr = p; 732 if (p != 0) 733 rewind(p); 734 else { 735 if ((c = readc()) != '\n') 736 unreadc(c); 737 } 738 continue; 739 case '?': 740 if (++readptr == &readstk[RDSKSZ]) { 741 error(gettext("nesting depth\n")); 742 } 743 *readptr = 0; 744 fsave = curfile; 745 curfile = stdin; 746 while ((c = readc()) == '!') 747 command(); 748 p = salloc(0); 749 sputc(p, c); 750 while ((c = readc()) != '\n') { 751 sputc(p, c); 752 if (c == '\\') 753 sputc(p, readc()); 754 } 755 curfile = fsave; 756 *readptr = p; 757 continue; 758 case '!': 759 if (command() == 1) 760 goto execute; 761 continue; 762 case '<': 763 case '>': 764 case '=': 765 if (cond(c) == 1) 766 goto execute; 767 continue; 768 default: 769 printf(gettext("%o is unimplemented\n"), c); 770 } 771 } 772 } 773 774 struct blk * 775 dcdiv(struct blk *ddivd, struct blk *ddivr) 776 { 777 int divsign, remsign, offset, divcarry; 778 int carry, dig, magic, d, dd, under; 779 long c, td, cc; 780 struct blk *ps, *px; 781 struct blk *p, *divd, *divr; 782 783 rem = 0; 784 p = salloc(0); 785 if (length(ddivr) == 0) { 786 pushp(ddivr); 787 printf(gettext("divide by 0\n")); 788 return (p); 789 } 790 divsign = remsign = 0; 791 divr = ddivr; 792 fsfile(divr); 793 if (sbackc(divr) == -1) { 794 divr = copy(ddivr, length(ddivr)); 795 chsign(divr); 796 divsign = ~divsign; 797 } 798 divd = copy(ddivd, length(ddivd)); 799 fsfile(divd); 800 if (sfbeg(divd) == 0 && sbackc(divd) == -1) { 801 chsign(divd); 802 divsign = ~divsign; 803 remsign = ~remsign; 804 } 805 offset = length(divd) - length(divr); 806 if (offset < 0) 807 goto ddone; 808 seekc(p, offset + 1); 809 sputc(divd, 0); 810 magic = 0; 811 fsfile(divr); 812 c = sbackc(divr); 813 if (c < 10) 814 magic++; 815 c = c * 100 + (sfbeg(divr)?0:sbackc(divr)); 816 if (magic > 0) { 817 c = (c * 100 +(sfbeg(divr)?0:sbackc(divr)))*2; 818 c /= 25; 819 } 820 while (offset >= 0) { 821 fsfile(divd); 822 td = sbackc(divd) * 100; 823 dd = sfbeg(divd)?0:sbackc(divd); 824 td = (td + dd) * 100; 825 dd = sfbeg(divd)?0:sbackc(divd); 826 td = td + dd; 827 cc = c; 828 if (offset == 0) 829 td++; 830 else 831 cc++; 832 if (magic != 0) 833 td = td<<3; 834 dig = td/cc; 835 under = 0; 836 if (td%cc < 8 && dig > 0 && magic) { 837 dig--; 838 under = 1; 839 } 840 rewind(divr); 841 rewind(divxyz); 842 carry = 0; 843 while (sfeof(divr) == 0) { 844 d = sgetc(divr) * dig + carry; 845 carry = d / 100; 846 salterc(divxyz, d % 100); 847 } 848 salterc(divxyz, carry); 849 rewind(divxyz); 850 seekc(divd, offset); 851 carry = 0; 852 while (sfeof(divd) == 0) { 853 d = slookc(divd); 854 d = d - (sfeof(divxyz) ? 0 : sgetc(divxyz)) - carry; 855 carry = 0; 856 if (d < 0) { 857 d += 100; 858 carry = 1; 859 } 860 salterc(divd, d); 861 } 862 divcarry = carry; 863 sbackc(p); 864 salterc(p, dig); 865 sbackc(p); 866 fsfile(divd); 867 d = sbackc(divd); 868 if ((d != 0) && /* !divcarry */ (offset != 0)) { 869 d = sbackc(divd) + 100; 870 salterc(divd, d); 871 } 872 if (--offset >= 0) { 873 divd->wt--; 874 } 875 } 876 if (under) { /* undershot last - adjust */ 877 px = copy(divr, length(divr)); /* 11/88 don't corrupt ddivr */ 878 chsign(px); 879 ps = add(px, divd); 880 fsfile(ps); 881 if (length(ps) > 0 && sbackc(ps) < 0) { 882 release(ps); /* only adjust in really undershot */ 883 } else { 884 release(divd); 885 salterc(p, dig + 1); 886 divd = ps; 887 } 888 } 889 if (divcarry != 0) { 890 salterc(p, dig - 1); 891 salterc(divd, -1); 892 ps = add(divr, divd); 893 release(divd); 894 divd = ps; 895 } 896 897 rewind(p); 898 divcarry = 0; 899 while (sfeof(p) == 0) { 900 d = slookc(p) + divcarry; 901 divcarry = 0; 902 if (d >= 100) { 903 d -= 100; 904 divcarry = 1; 905 } 906 salterc(p, d); 907 } 908 if (divcarry != 0) 909 salterc(p, divcarry); 910 fsfile(p); 911 while (sfbeg(p) == 0) { 912 if (sbackc(p) == 0) 913 truncate(p); 914 else break; 915 } 916 if (divsign < 0) 917 chsign(p); 918 fsfile(divd); 919 while (sfbeg(divd) == 0) { 920 if (sbackc(divd) == 0) 921 truncate(divd); 922 else break; 923 } 924 ddone: 925 if (remsign < 0) 926 chsign(divd); 927 if (divr != ddivr) 928 release(divr); 929 rem = divd; 930 return (p); 931 } 932 933 int 934 dscale(void) 935 { 936 struct blk *dd, *dr, *r; 937 int c; 938 939 dr = pop(); 940 EMPTYS; 941 dd = pop(); 942 EMPTYSR(dr); 943 fsfile(dd); 944 skd = sunputc(dd); 945 fsfile(dr); 946 skr = sunputc(dr); 947 if (sfbeg(dr) == 1 || (sfbeg(dr) == 0 && sbackc(dr) == 0)) { 948 sputc(dr, skr); 949 pushp(dr); 950 printf(gettext("divide by 0\n")); 951 return (1); 952 } 953 if (sfbeg(dd) == 1 || (sfbeg(dd) == 0 && sbackc(dd) == 0)) { 954 #ifdef XPG6 955 sputc(dd, k); 956 #else 957 sputc(dd, skd); 958 #endif 959 pushp(dd); 960 return (1); 961 } 962 c = k-skd+skr; 963 if (c < 0) 964 r = removr(dd, -c); 965 else { 966 r = add0(dd, c); 967 irem = 0; 968 } 969 arg1 = r; 970 arg2 = dr; 971 savk = k; 972 return (0); 973 } 974 975 struct blk * 976 removr(struct blk *p, int n) 977 { 978 int nn, neg; 979 struct blk *q, *s, *r; 980 fsfile(p); 981 neg = sbackc(p); 982 if (neg < 0) 983 chsign(p); 984 rewind(p); 985 nn = (n + 1) / 2; 986 q = salloc(nn); 987 while (n > 1) { 988 sputc(q, sgetc(p)); 989 n -= 2; 990 } 991 r = salloc(2); 992 while (sfeof(p) == 0) 993 sputc(r, sgetc(p)); 994 release(p); 995 if (n == 1) { 996 s = dcdiv(r, tenptr); 997 release(r); 998 rewind(rem); 999 if (sfeof(rem) == 0) 1000 sputc(q, sgetc(rem)); 1001 release(rem); 1002 if (neg < 0) { 1003 chsign(s); 1004 chsign(q); 1005 irem = q; 1006 return (s); 1007 } 1008 irem = q; 1009 return (s); 1010 } 1011 if (neg < 0) { 1012 chsign(r); 1013 chsign(q); 1014 irem = q; 1015 return (r); 1016 } 1017 irem = q; 1018 return (r); 1019 } 1020 1021 struct blk * 1022 sqrt(struct blk *p) 1023 { 1024 struct blk *r, *q, *s, *t; 1025 int c, n, nn; 1026 1027 n = length(p); 1028 fsfile(p); 1029 c = sbackc(p); 1030 if ((n & 1) != 1) 1031 c = c * 100 + (sfbeg(p) ? 0 : sbackc(p)); 1032 n = (n + 1) >> 1; 1033 r = salloc(n); 1034 zero(r); 1035 seekc(r, n); 1036 nn = 1; 1037 while ((c -= nn) >= 0) 1038 nn += 2; 1039 c = (nn + 1) >> 1; 1040 fsfile(r); 1041 sbackc(r); 1042 if (c >= 100) { 1043 c -= 100; 1044 salterc(r, c); 1045 sputc(r, 1); 1046 } else 1047 salterc(r, c); 1048 for (; ; ) { 1049 q = dcdiv(p, r); 1050 s = add(q, r); 1051 release(q); 1052 release(rem); 1053 q = dcdiv(s, sqtemp); 1054 release(s); 1055 release(rem); 1056 s = copy(r, length(r)); 1057 chsign(s); 1058 t = add(s, q); 1059 release(s); 1060 fsfile(t); 1061 nn = sfbeg(t) ? 0 : sbackc(t); 1062 if (nn >= 0) 1063 break; 1064 release(r); 1065 release(t); 1066 r = q; 1067 } 1068 release(t); 1069 release(q); 1070 release(p); 1071 return (r); 1072 } 1073 1074 struct blk * 1075 exp(struct blk *base, struct blk *ex) 1076 { 1077 struct blk *r, *e, *p, *e1, *t, *cp; 1078 int temp, c, n; 1079 r = salloc(1); 1080 sputc(r, 1); 1081 p = copy(base, length(base)); 1082 e = copy(ex, length(ex)); 1083 fsfile(e); 1084 if (sfbeg(e) != 0) 1085 goto edone; 1086 temp = 0; 1087 c = sbackc(e); 1088 if (c < 0) { 1089 temp++; 1090 chsign(e); 1091 } 1092 while (length(e) != 0) { 1093 e1 = dcdiv(e, sqtemp); 1094 release(e); 1095 e = e1; 1096 n = length(rem); 1097 release(rem); 1098 if (n != 0) { 1099 e1 = mult(p, r); 1100 release(r); 1101 r = e1; 1102 } 1103 t = copy(p, length(p)); 1104 cp = mult(p, t); 1105 release(p); 1106 release(t); 1107 p = cp; 1108 } 1109 if (temp != 0) { 1110 if ((c = length(base)) == 0) { 1111 goto edone; 1112 } 1113 if (c > 1) 1114 create(r); 1115 else { 1116 rewind(base); 1117 if ((c = sgetc(base)) <= 1) { 1118 create(r); 1119 sputc(r, c); 1120 } else 1121 create(r); 1122 } 1123 } 1124 edone: 1125 release(p); 1126 release(e); 1127 return (r); 1128 } 1129 1130 void 1131 init(int argc, char **argv) 1132 { 1133 struct sym *sp; 1134 char *dcmalloc(); 1135 struct stat tsb; 1136 1137 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 1138 signal(SIGINT, onintr); 1139 setbuf(stdout, (char *)NULL); 1140 svargc = --argc; 1141 svargv = argv; 1142 while (svargc > 0 && svargv[1][0] == '-') { 1143 switch (svargv[1][1]) { 1144 default: 1145 dbg = 1; 1146 } 1147 svargc--; 1148 svargv++; 1149 } 1150 1151 ifile = 1; 1152 1153 if (svargc <= 0) 1154 curfile = stdin; 1155 else { 1156 if (stat(svargv[1], &tsb) < 0) { 1157 printf(gettext("Cannot stat %s: "), svargv[1]); 1158 perror(""); 1159 exit(1); 1160 } 1161 1162 if (S_ISREG(tsb.st_mode)) { 1163 if ((curfile = fopen(svargv[1], "r")) == NULL) { 1164 printf(gettext("can't open file %s\n"), \ 1165 svargv[1]); 1166 exit(1); 1167 } 1168 } else { 1169 printf(gettext("invalid file type: %s\n"), \ 1170 svargv[1]); 1171 exit(1); 1172 } 1173 } 1174 1175 dummy = dcmalloc(0); 1176 scalptr = salloc(1); 1177 sputc(scalptr, 0); 1178 basptr = salloc(1); 1179 sputc(basptr, 10); 1180 obase = 10; 1181 log10 = log2(10L); 1182 1183 /* 1184 * POSIX.2 1185 * default line length is 70 characters including newline 1186 */ 1187 ll = 70; 1188 fw = 1; 1189 fw1 = 0; 1190 tenptr = salloc(1); 1191 sputc(tenptr, 10); 1192 obase = 10; 1193 inbas = salloc(1); 1194 sputc(inbas, 10); 1195 sqtemp = salloc(1); 1196 sputc(sqtemp, 2); 1197 chptr = salloc(0); 1198 strptr = salloc(0); 1199 divxyz = salloc(0); 1200 stkbeg = stkptr = &stack[0]; 1201 stkend = &stack[STKSZ]; 1202 stkerr = 0; 1203 readptr = &readstk[0]; 1204 k = 0; 1205 sp = sptr = &symlst[0]; 1206 while (sptr < &symlst[TBLSZ]) { 1207 sptr->next = ++sp; 1208 sptr++; 1209 } 1210 sptr->next = 0; 1211 sfree = &symlst[0]; 1212 } 1213 1214 void 1215 onintr(int sig) 1216 { 1217 1218 signal(sig, onintr); 1219 while (readptr != &readstk[0]) { 1220 if (*readptr != 0) 1221 release(*readptr); 1222 readptr--; 1223 } 1224 curfile = stdin; 1225 commnds(); 1226 } 1227 1228 void 1229 pushp(struct blk *p) 1230 { 1231 if (stkptr == stkend) 1232 printf(gettext("out of stack space\n")); 1233 else { 1234 stkerr = 0; 1235 *++stkptr = p; 1236 } 1237 } 1238 1239 struct blk * 1240 pop(void) 1241 { 1242 if (stkptr == stack) { 1243 stkerr = 1; 1244 return (0); 1245 } 1246 return (*stkptr--); 1247 } 1248 1249 struct blk * 1250 readin(void) 1251 { 1252 struct blk *p, *q; 1253 int dp, dpct; 1254 int c; 1255 1256 dp = dpct = 0; 1257 p = salloc(0); 1258 for (; ; ) { 1259 c = readc(); 1260 switch (c) { 1261 case '.': 1262 if (dp != 0) 1263 goto gotnum; 1264 dp++; 1265 continue; 1266 case '\\': 1267 readc(); 1268 continue; 1269 default: 1270 if (c >= 'A' && c <= 'F') 1271 c = c - 'A' + 10; 1272 else 1273 if (c >= '0' && c <= '9') 1274 c -= '0'; 1275 else 1276 goto gotnum; 1277 if (dp != 0) { 1278 if (dpct >= 99) 1279 continue; 1280 dpct++; 1281 } 1282 create(chptr); 1283 if (c != 0) 1284 sputc(chptr, c); 1285 q = mult(p, inbas); 1286 release(p); 1287 p = add(chptr, q); 1288 release(q); 1289 } 1290 } 1291 gotnum: 1292 unreadc(c); 1293 if (dp == 0) { 1294 sputc(p, 0); 1295 return (p); 1296 } else { 1297 /* if not base 10, then scale fractional input to precision */ 1298 if (((int)*(inbas->beg)) != 10) { 1299 while (dpct < k) { 1300 create(chptr); 1301 q = mult(p, inbas); 1302 release(p); 1303 p = add(chptr, q); 1304 release(q); 1305 dpct++; 1306 } 1307 } 1308 q = scale(p, dpct); 1309 return (q); 1310 } 1311 } 1312 1313 /* 1314 * returns pointer to struct with ct 0's & p 1315 */ 1316 struct blk * 1317 add0(struct blk *p, int ct) 1318 { 1319 struct blk *q, *t; 1320 1321 q = salloc(length(p) + (ct + 1) / 2); 1322 while (ct > 1) { 1323 sputc(q, 0); 1324 ct -= 2; 1325 } 1326 rewind(p); 1327 while (sfeof(p) == 0) { 1328 sputc(q, sgetc(p)); 1329 } 1330 release(p); 1331 if (ct == 1) { 1332 t = mult(tenptr, q); 1333 release(q); 1334 return (t); 1335 } 1336 return (q); 1337 } 1338 1339 struct blk * 1340 mult(struct blk *p, struct blk *q) 1341 { 1342 struct blk *mp, *mq, *mr; 1343 int sign, offset, carry; 1344 int cq, cp, mt, mcr; 1345 1346 offset = sign = 0; 1347 fsfile(p); 1348 mp = p; 1349 if (sfbeg(p) == 0) { 1350 if (sbackc(p) < 0) { 1351 mp = copy(p, length(p)); 1352 chsign(mp); 1353 sign = ~sign; 1354 } 1355 } 1356 fsfile(q); 1357 mq = q; 1358 if (sfbeg(q) == 0) { 1359 if (sbackc(q) < 0) { 1360 mq = copy(q, length(q)); 1361 chsign(mq); 1362 sign = ~sign; 1363 } 1364 } 1365 mr = salloc(length(mp) + length(mq)); 1366 zero(mr); 1367 rewind(mq); 1368 while (sfeof(mq) == 0) { 1369 cq = sgetc(mq); 1370 rewind(mp); 1371 rewind(mr); 1372 mr->rd += offset; 1373 carry = 0; 1374 while (sfeof(mp) == 0) { 1375 cp = sgetc(mp); 1376 mcr = sfeof(mr) ? 0 : slookc(mr); 1377 mt = cp*cq + carry + mcr; 1378 carry = mt / 100; 1379 salterc(mr, mt % 100); 1380 } 1381 offset++; 1382 if (carry != 0) { 1383 mcr = sfeof(mr) ? 0 : slookc(mr); 1384 salterc(mr, mcr + carry); 1385 } 1386 } 1387 if (sign < 0) { 1388 chsign(mr); 1389 } 1390 if (mp != p) 1391 release(mp); 1392 if (mq != q) 1393 release(mq); 1394 return (mr); 1395 } 1396 1397 void 1398 chsign(struct blk *p) 1399 { 1400 int carry; 1401 char ct; 1402 1403 carry = 0; 1404 rewind(p); 1405 while (sfeof(p) == 0) { 1406 ct = 100 - slookc(p) - carry; 1407 carry = 1; 1408 if (ct >= 100) { 1409 ct -= 100; 1410 carry = 0; 1411 } 1412 salterc(p, ct); 1413 } 1414 if (carry != 0) { 1415 sputc(p, -1); 1416 fsfile(p); 1417 sbackc(p); 1418 ct = sbackc(p); 1419 if (ct == 99) { 1420 truncate(p); 1421 sputc(p, -1); 1422 } 1423 } else { 1424 fsfile(p); 1425 ct = sbackc(p); 1426 if (ct == 0) 1427 truncate(p); 1428 } 1429 } 1430 1431 char 1432 readc(void) 1433 { 1434 loop: 1435 if ((readptr != &readstk[0]) && (*readptr != 0)) { 1436 if (sfeof(*readptr) == 0) 1437 return (lastchar = sgetc(*readptr)); 1438 release(*readptr); 1439 readptr--; 1440 goto loop; 1441 } 1442 lastchar = getc(curfile); 1443 if (lastchar != EOF) 1444 return (lastchar); 1445 if (readptr != &readptr[0]) { 1446 readptr--; 1447 if (*readptr == 0) 1448 curfile = stdin; 1449 goto loop; 1450 } 1451 if (curfile != stdin) { 1452 fclose(curfile); 1453 curfile = stdin; 1454 goto loop; 1455 } 1456 exit(0); 1457 } 1458 1459 void 1460 unreadc(char c) 1461 { 1462 1463 if ((readptr != &readstk[0]) && (*readptr != 0)) { 1464 sungetc(*readptr, c); 1465 } else 1466 ungetc(c, curfile); 1467 } 1468 1469 void 1470 binop(char c) 1471 { 1472 struct blk *r; 1473 1474 switch (c) { 1475 case '+': 1476 r = add(arg1, arg2); 1477 break; 1478 case '*': 1479 r = mult(arg1, arg2); 1480 break; 1481 case '/': 1482 r = dcdiv(arg1, arg2); 1483 break; 1484 } 1485 release(arg1); 1486 release(arg2); 1487 sputc(r, savk); 1488 pushp(r); 1489 } 1490 1491 void 1492 print(struct blk *hptr) 1493 { 1494 struct blk *p, *q, *dec; 1495 int sc; /* scale */ 1496 int dig, dout, ct; 1497 1498 rewind(hptr); 1499 while (sfeof(hptr) == 0) { 1500 if (sgetc(hptr) > 99) { 1501 rewind(hptr); 1502 while (sfeof(hptr) == 0) { 1503 printf("%c", sgetc(hptr)); 1504 } 1505 printf("\n"); 1506 return; 1507 } 1508 } 1509 fsfile(hptr); 1510 sc = sbackc(hptr); /* read scale off end of blk */ 1511 if (sfbeg(hptr) != 0) { 1512 printf("0\n"); 1513 return; 1514 } 1515 count = ll; 1516 p = copy(hptr, length(hptr)); 1517 sunputc(p); 1518 fsfile(p); 1519 if (sbackc(p) < 0) { 1520 chsign(p); 1521 OUTC('-'); 1522 } 1523 if ((obase == 0) || (obase == -1)) { 1524 oneot(p, sc, 'd'); 1525 return; 1526 } 1527 if (obase == 1) { 1528 oneot(p, sc, '1'); 1529 return; 1530 } 1531 if (obase == 10) { 1532 tenot(p, sc); 1533 return; 1534 } 1535 create(strptr); 1536 dig = log10 * sc; 1537 dout = ((dig / 10) + dig) / logo; 1538 dec = getdec(p, sc); 1539 p = removc(p, sc); 1540 while (length(p) != 0) { 1541 q = dcdiv(p, basptr); 1542 release(p); 1543 p = q; 1544 (*outdit)(rem, 0); 1545 if (obase > 16) 1546 sputc(strptr, ' '); 1547 } 1548 release(p); 1549 fsfile(strptr); 1550 while (sfbeg(strptr) == 0) 1551 OUTC(sbackc(strptr)); 1552 if (sc == 0) { 1553 release(dec); 1554 printf("\n"); 1555 return; 1556 } 1557 create(strptr); 1558 OUTC('.'); 1559 ct = 0; 1560 do { 1561 if (ct != 0 && obase > 16) 1562 sputc(strptr, ' '); 1563 q = mult(basptr, dec); 1564 release(dec); 1565 dec = getdec(q, sc); 1566 p = removc(q, sc); 1567 (*outdit)(p, 1); 1568 } while (++ct < dout); 1569 release(dec); 1570 rewind(strptr); 1571 while (sfeof(strptr) == 0) 1572 OUTC(sgetc(strptr)); 1573 printf("\n"); 1574 } 1575 1576 struct blk * 1577 getdec(struct blk *p, int sc) 1578 { 1579 int cc; 1580 struct blk *q, *t, *s; 1581 1582 rewind(p); 1583 if (length(p) * 2 < sc) { 1584 q = copy(p, length(p)); 1585 return (q); 1586 } 1587 q = salloc(length(p)); 1588 while (sc >= 1) { 1589 sputc(q, sgetc(p)); 1590 sc -= 2; 1591 } 1592 if (sc != 0) { 1593 t = mult(q, tenptr); 1594 s = salloc(cc = length(q)); 1595 release(q); 1596 rewind(t); 1597 while (cc-- > 0) 1598 sputc(s, sgetc(t)); 1599 sputc(s, 0); 1600 release(t); 1601 t = dcdiv(s, tenptr); 1602 release(s); 1603 release(rem); 1604 return (t); 1605 } 1606 return (q); 1607 } 1608 1609 void 1610 tenot(struct blk *p, int sc) 1611 { 1612 int c, f; 1613 1614 fsfile(p); 1615 1616 f = 0; 1617 1618 /* 1619 * at this point, the number is stored as base 100 (two decimal 1620 * digits per char) stuck in a buf (character array) backwards. 1621 * sc indicates the scaling factor. 1622 */ 1623 1624 while ((sfbeg(p) == 0) && ((p->rd-p->beg-1)*2 >= sc)) { 1625 /* 1626 * get numbers from the buf until we are the beginning of 1627 * the buf (i.e., there are no more numbers) or the numbers 1628 * remaining fall within the scaled (to the right of the 1629 * decimal point) portion. 1630 */ 1631 c = sbackc(p); 1632 1633 /* 1634 * POSIX.2 1635 * as we output digits, we have to watch the line length (ll) 1636 * which should include a '\' and a newline. 1637 */ 1638 if (c < 10) { 1639 /* 1640 * if the number is less than 10, we need to output 1641 * a space-holding '0' (unless this is the first time 1642 * through). 1643 */ 1644 if (f == 1) { 1645 CHECKEND; 1646 printf("0"); 1647 count--; 1648 } 1649 1650 CHECKEND; 1651 printf("%d", c); 1652 count--; 1653 } else { 1654 CHECKEND; 1655 printf("%d", c / 10); 1656 count--; 1657 1658 CHECKEND; 1659 printf("%d", c % 10); 1660 count--; 1661 } 1662 f = 1; 1663 } 1664 1665 if (sc == 0) { 1666 /* 1667 * no scaling factor, so we must have exited loop because we 1668 * ran out of numbers. 1669 */ 1670 printf("\n"); 1671 release(p); 1672 return; 1673 } 1674 1675 if ((p->rd - p->beg) * 2 > sc) { 1676 c = sbackc(p); 1677 1678 CHECKEND; 1679 printf("%d", c / 10); 1680 count--; 1681 1682 CHECKEND; 1683 printf("."); 1684 count--; 1685 1686 CHECKEND; 1687 printf("%d", c % 10); 1688 count--; 1689 1690 sc--; 1691 } else { 1692 CHECKEND; 1693 printf("."); 1694 count--; 1695 } 1696 1697 if (sc > (p->rd - p->beg) * 2) { 1698 while (sc > (p->rd - p->beg) * 2) { 1699 CHECKEND; 1700 printf("0"); 1701 count--; 1702 1703 sc--; 1704 } 1705 } 1706 1707 /* now go through the scaled portion of the number */ 1708 while (sc > 1) { 1709 c = sbackc(p); 1710 if (c < 10) { 1711 CHECKEND; 1712 printf("0"); 1713 count--; 1714 1715 CHECKEND; 1716 printf("%d", c); 1717 count--; 1718 } else { 1719 CHECKEND; 1720 printf("%d", c / 10); 1721 count--; 1722 1723 CHECKEND; 1724 printf("%d", c % 10); 1725 count--; 1726 } 1727 sc -= 2; 1728 } 1729 1730 if (sc == 1) { /* just in case the scaling factor was odd */ 1731 CHECKEND; 1732 printf("%d", sbackc(p) / 10); 1733 } 1734 1735 printf("\n"); 1736 release(p); 1737 } 1738 1739 void 1740 oneot(struct blk *p, int sc, char ch) 1741 { 1742 struct blk *q; 1743 1744 q = removc(p, sc); 1745 create(strptr); 1746 sputc(strptr, -1); 1747 while (length(q) > 0) { 1748 p = add(strptr, q); 1749 release(q); 1750 q = p; 1751 OUTC(ch); 1752 } 1753 release(q); 1754 printf("\n"); 1755 } 1756 1757 void 1758 hexot(struct blk *p, int flg) 1759 { 1760 int c; 1761 1762 rewind(p); 1763 if (sfeof(p) != 0) { 1764 sputc(strptr, '0'); 1765 release(p); 1766 return; 1767 } 1768 c = sgetc(p); 1769 release(p); 1770 if (c >= 16) { 1771 printf(gettext("hex digit > 16")); 1772 return; 1773 } 1774 sputc(strptr, c < 10 ? c + '0' : c - 10 + 'A'); 1775 } 1776 1777 void 1778 bigot(struct blk *p, int flg) 1779 { 1780 struct blk *t, *q; 1781 int l; 1782 int neg; 1783 1784 if (flg == 1) 1785 t = salloc(0); 1786 else { 1787 t = strptr; 1788 l = length(strptr) + fw - 1; 1789 } 1790 neg = 0; 1791 if (length(p) != 0) { 1792 fsfile(p); 1793 if (sbackc(p) < 0) { 1794 neg = 1; 1795 chsign(p); 1796 } 1797 while (length(p) != 0) { 1798 q = dcdiv(p, tenptr); 1799 release(p); 1800 p = q; 1801 rewind(rem); 1802 sputc(t, sfeof(rem) ? '0' : sgetc(rem) + '0'); 1803 release(rem); 1804 } 1805 } 1806 release(p); 1807 if (flg == 1) { 1808 l = fw1 - length(t); 1809 if (neg != 0) { 1810 l--; 1811 sputc(strptr, '-'); 1812 } 1813 fsfile(t); 1814 while (l-- > 0) 1815 sputc(strptr, '0'); 1816 while (sfbeg(t) == 0) 1817 sputc(strptr, sbackc(t)); 1818 release(t); 1819 } else { 1820 l -= length(strptr); 1821 while (l-- > 0) 1822 sputc(strptr, '0'); 1823 if (neg != 0) { 1824 sunputc(strptr); 1825 sputc(strptr, '-'); 1826 } 1827 } 1828 } 1829 1830 struct blk * 1831 add(struct blk *a1, struct blk *a2) 1832 { 1833 struct blk *p; 1834 int carry, n; 1835 int size; 1836 int c, n1, n2; 1837 1838 size = length(a1) > length(a2) ? length(a1) : length(a2); 1839 p = salloc(size); 1840 rewind(a1); 1841 rewind(a2); 1842 carry = 0; 1843 while (--size >= 0) { 1844 n1 = sfeof(a1) ? 0 : sgetc(a1); 1845 n2 = sfeof(a2) ? 0 : sgetc(a2); 1846 n = n1 + n2 + carry; 1847 if (n >= 100) { 1848 carry = 1; 1849 n -= 100; 1850 } else 1851 if (n < 0) { 1852 carry = -1; 1853 n += 100; 1854 } else 1855 carry = 0; 1856 sputc(p, n); 1857 } 1858 if (carry != 0) 1859 sputc(p, carry); 1860 fsfile(p); 1861 if (sfbeg(p) == 0) { 1862 while (sfbeg(p) == 0 && (c = sbackc(p)) == 0); 1863 if (c != 0) 1864 salterc(p, c); 1865 truncate(p); 1866 } 1867 fsfile(p); 1868 if (sfbeg(p) == 0 && sbackc(p) == -1) { 1869 while ((c = sbackc(p)) == 99) { 1870 if (c == EOF) 1871 break; 1872 } 1873 sgetc(p); 1874 salterc(p, -1); 1875 truncate(p); 1876 } 1877 return (p); 1878 } 1879 1880 int 1881 eqk(void) { 1882 struct blk *p, *q; 1883 int skp, skq; 1884 1885 p = pop(); 1886 EMPTYS; 1887 q = pop(); 1888 EMPTYSR(p); 1889 skp = sunputc(p); 1890 skq = sunputc(q); 1891 if (skp == skq) { 1892 arg1 = p; 1893 arg2 = q; 1894 savk = skp; 1895 return (0); 1896 } else 1897 if (skp < skq) { 1898 savk = skq; 1899 p = add0(p, skq - skp); 1900 } else { 1901 savk = skp; 1902 q = add0(q, skp - skq); 1903 } 1904 arg1 = p; 1905 arg2 = q; 1906 return (0); 1907 } 1908 1909 struct blk * 1910 removc(struct blk *p, int n) 1911 { 1912 struct blk *q, *r; 1913 1914 rewind(p); 1915 while (n > 1) { 1916 sgetc(p); 1917 n -= 2; 1918 } 1919 q = salloc(2); 1920 while (sfeof(p) == 0) 1921 sputc(q, sgetc(p)); 1922 if (n == 1) { 1923 r = dcdiv(q, tenptr); 1924 release(q); 1925 release(rem); 1926 q = r; 1927 } 1928 release(p); 1929 return (q); 1930 } 1931 1932 struct blk * 1933 scalint(struct blk *p) 1934 { 1935 int n; 1936 1937 n = sunputc(p); 1938 p = removc(p, n); 1939 return (p); 1940 } 1941 1942 struct blk * 1943 scale(struct blk *p, int n) 1944 { 1945 struct blk *q, *s, *t; 1946 1947 t = add0(p, n); 1948 q = salloc(1); 1949 sputc(q, n); 1950 s = exp(inbas, q); 1951 release(q); 1952 q = dcdiv(t, s); 1953 release(t); 1954 release(s); 1955 release(rem); 1956 sputc(q, n); 1957 return (q); 1958 } 1959 1960 int 1961 subt(void) 1962 { 1963 arg1 = pop(); 1964 EMPTYS; 1965 savk = sunputc(arg1); 1966 chsign(arg1); 1967 sputc(arg1, savk); 1968 pushp(arg1); 1969 if (eqk() != 0) 1970 return (1); 1971 binop('+'); 1972 return (0); 1973 } 1974 1975 int 1976 command(void) 1977 { 1978 int c; 1979 char line[100], *sl; 1980 void (*savint)(); 1981 pid_t pid, rpid; 1982 int retcode; 1983 1984 switch (c = readc()) { 1985 case '<': 1986 return (cond(NL)); 1987 case '>': 1988 return (cond(NG)); 1989 case '=': 1990 return (cond(NE)); 1991 default: 1992 sl = line; 1993 *sl++ = c; 1994 while ((c = readc()) != '\n') 1995 *sl++ = c; 1996 *sl = 0; 1997 if ((pid = fork()) == (pid_t)0) { 1998 execl("/usr/bin/sh", "sh", "-c", line, 0); 1999 exit(0100); 2000 } 2001 savint = signal(SIGINT, SIG_IGN); 2002 while ((rpid = wait(&retcode)) != pid && rpid != (pid_t)-1); 2003 signal(SIGINT, savint); 2004 printf(gettext("!\n")); 2005 return (0); 2006 } 2007 } 2008 2009 int 2010 cond(char c) 2011 { 2012 struct blk *p; 2013 int cc; 2014 2015 if (subt() != 0) 2016 return (1); 2017 p = pop(); 2018 sunputc(p); 2019 if (length(p) == 0) { 2020 release(p); 2021 if (c == '<' || c == '>' || c == NE) { 2022 readc(); 2023 return (0); 2024 } 2025 load(); 2026 return (1); 2027 } else { 2028 if (c == '=') { 2029 release(p); 2030 readc(); 2031 return (0); 2032 } 2033 } 2034 if (c == NE) { 2035 release(p); 2036 load(); 2037 return (1); 2038 } 2039 fsfile(p); 2040 cc = sbackc(p); 2041 release(p); 2042 if ((cc < 0 && (c == '<' || c == NG)) || 2043 (cc > 0) && (c == '>' || c == NL)) { 2044 readc(); 2045 return (0); 2046 } 2047 load(); 2048 return (1); 2049 } 2050 2051 void 2052 load(void) 2053 { 2054 int c; 2055 struct blk *p, *q, *t, *s; 2056 2057 c = readc() & 0377; 2058 sptr = stable[c]; 2059 if (sptr != 0) { 2060 p = sptr->val; 2061 if (c >= ARRAYST) { 2062 q = salloc(length(p)); 2063 rewind(p); 2064 while (sfeof(p) == 0) { 2065 s = getwd(p); 2066 if (s == 0) 2067 putwd(q, (struct blk *)NULL); 2068 else { 2069 t = copy(s, length(s)); 2070 putwd(q, t); 2071 } 2072 } 2073 pushp(q); 2074 } else { 2075 q = copy(p, length(p)); 2076 pushp(q); 2077 } 2078 } else { 2079 q = salloc(1); 2080 if (c <= LASTFUN) { 2081 printf(gettext 2082 ("function %c undefined\n"), c + 'a' - 1); 2083 sputc(q, 'c'); 2084 sputc(q, '0'); 2085 sputc(q, ' '); 2086 sputc(q, '1'); 2087 sputc(q, 'Q'); 2088 } else 2089 sputc(q, 0); 2090 pushp(q); 2091 } 2092 } 2093 2094 int 2095 log2(long n) 2096 { 2097 int i; 2098 2099 if (n == 0) 2100 return (0); 2101 i = 31; 2102 if (n < 0) 2103 return (i); 2104 while ((n = n << 1) > 0) 2105 i--; 2106 return (--i); 2107 } 2108 2109 struct blk * 2110 salloc(int size) 2111 { 2112 struct blk *hdr; 2113 char *ptr; 2114 char *dcmalloc(); 2115 all++; 2116 lall++; 2117 if (all - rel > active) 2118 active = all - rel; 2119 nbytes += size; 2120 lbytes += size; 2121 if (nbytes > maxsize) 2122 maxsize = nbytes; 2123 if (size > longest) 2124 longest = size; 2125 ptr = dcmalloc((unsigned)size); 2126 if (ptr == 0) { 2127 garbage("salloc"); 2128 if ((ptr = dcmalloc((unsigned)size)) == 0) 2129 ospace("salloc"); 2130 } 2131 if ((hdr = hfree) == 0) 2132 hdr = morehd(); 2133 hfree = (struct blk *)hdr->rd; 2134 hdr->rd = hdr->wt = hdr->beg = ptr; 2135 hdr->last = ptr + size; 2136 return (hdr); 2137 } 2138 2139 struct blk * 2140 morehd(void) 2141 { 2142 struct blk *h, *kk; 2143 char *dcmalloc(); 2144 2145 headmor++; 2146 nbytes += HEADSZ; 2147 hfree = h = (struct blk *)dcmalloc(HEADSZ); 2148 if (hfree == 0) { 2149 garbage("morehd"); 2150 if ((hfree = h = (struct blk *)dcmalloc(HEADSZ)) == 0) 2151 ospace("headers"); 2152 } 2153 kk = h; 2154 while (h < hfree + (HEADSZ/BLK)) 2155 (h++)->rd = (char *)++kk; 2156 (--h)->rd = 0; 2157 return (hfree); 2158 } 2159 2160 struct blk * 2161 copy(struct blk *hptr, int size) 2162 { 2163 struct blk *hdr; 2164 unsigned sz; 2165 char *ptr; 2166 2167 all++; 2168 lall++; 2169 lcopy++; 2170 nbytes += size; 2171 lbytes += size; 2172 if (size > longest) 2173 longest = size; 2174 if (size > maxsize) 2175 maxsize = size; 2176 sz = length(hptr); 2177 ptr = nalloc(hptr->beg, (unsigned)size); 2178 if (ptr == 0) { 2179 garbage("copy"); 2180 if ((ptr = nalloc(hptr->beg, (unsigned)size)) == NULL) { 2181 printf(gettext("copy size %d\n"), size); 2182 ospace("copy"); 2183 } 2184 } 2185 if ((hdr = hfree) == 0) 2186 hdr = morehd(); 2187 hfree = (struct blk *)hdr->rd; 2188 hdr->rd = hdr->beg = ptr; 2189 hdr->last = ptr + size; 2190 hdr->wt = ptr + sz; 2191 ptr = hdr->wt; 2192 while (ptr < hdr->last) 2193 *ptr++ = '\0'; 2194 return (hdr); 2195 } 2196 2197 void 2198 sdump(char *s1, struct blk *hptr) 2199 { 2200 char *p; 2201 2202 if (hptr) { 2203 printf("%s %o rd %o wt %o beg %o last %o\n", s1, hptr, 2204 hptr->rd, hptr->wt, hptr->beg, hptr->last); 2205 p = hptr->beg; 2206 while (p < hptr->wt) 2207 printf("%d ", *p++); 2208 printf("\n"); 2209 } else 2210 printf("%s %o\n", s1, hptr); 2211 } 2212 2213 void 2214 seekc(struct blk *hptr, int n) 2215 { 2216 char *nn, *p; 2217 2218 nn = hptr->beg + n; 2219 if (nn > hptr->last) { 2220 nbytes += nn - hptr->last; 2221 if (nbytes > maxsize) 2222 maxsize = nbytes; 2223 lbytes += nn - hptr->last; 2224 if (n > longest) 2225 longest = n; 2226 p = realloc(hptr->beg, (unsigned)n); 2227 if (p == 0) { 2228 hptr->beg = realloc(hptr->beg, 2229 (unsigned)(hptr->last - hptr->beg)); 2230 garbage("seekc"); 2231 if ((p = realloc(hptr->beg, (unsigned)n)) == 0) 2232 ospace("seekc"); 2233 } 2234 hptr->beg = p; 2235 hptr->wt = hptr->last = hptr->rd = p + n; 2236 return; 2237 } 2238 hptr->rd = nn; 2239 if (nn > hptr->wt) 2240 hptr->wt = nn; 2241 } 2242 2243 void 2244 salterwd(struct wblk *hptr, struct blk *n) 2245 { 2246 if (hptr->rdw == hptr->lastw) 2247 more((struct blk *)hptr); 2248 *hptr->rdw++ = n; 2249 if (hptr->rdw > hptr->wtw) 2250 hptr->wtw = hptr->rdw; 2251 } 2252 2253 void 2254 more(struct blk *hptr) 2255 { 2256 unsigned size; 2257 char *p; 2258 2259 if ((size = (hptr->last - hptr->beg) * 2) == 0) 2260 size = 1; 2261 nbytes += size / 2; 2262 if (nbytes > maxsize) 2263 maxsize = nbytes; 2264 if (size > longest) 2265 longest = size; 2266 lbytes += size / 2; 2267 lmore++; 2268 p = realloc(hptr->beg, (unsigned)size); 2269 if (p == 0) { 2270 hptr->beg = realloc(hptr->beg, 2271 (unsigned)(hptr->last - hptr->beg)); 2272 garbage("more"); 2273 if ((p = realloc(hptr->beg, size)) == 0) 2274 ospace("more"); 2275 } 2276 hptr->rd = hptr->rd - hptr->beg + p; 2277 hptr->wt = hptr->wt - hptr->beg + p; 2278 hptr->beg = p; 2279 hptr->last = p + size; 2280 } 2281 2282 void 2283 ospace(char *s) 2284 { 2285 printf(gettext("out of space: %s\n"), s); 2286 printf(gettext("all %ld rel %ld headmor %ld\n"), all, rel, headmor); 2287 printf(gettext("nbytes %ld\n"), nbytes); 2288 sdump("stk", *stkptr); 2289 abort(); 2290 } 2291 2292 #define G1 gettext("array %o elt %d odd\n") 2293 #define G2 gettext("tmps %o p %o\n") 2294 void 2295 garbage(char *s) 2296 { 2297 int i; 2298 struct blk *p, *q; 2299 struct sym *tmps; 2300 int ct; 2301 2302 printf(gettext("got to garbage %s\n"), s); 2303 for (i = 0; i < TBLSZ; i++) { 2304 tmps = stable[i]; 2305 if (tmps != 0) { 2306 if (i < ARRAYST) { 2307 do { 2308 p = tmps->val; 2309 if (((int)p->beg & 01) != 0) { 2310 printf(gettext( 2311 "string %o\n"), i); 2312 sdump("odd beg", p); 2313 } 2314 redef(p); 2315 tmps = tmps->next; 2316 } while (tmps != 0); 2317 continue; 2318 } else { 2319 do { 2320 p = tmps->val; 2321 rewind(p); 2322 ct = 0; 2323 while ((q = getwd(p)) != NULL) { 2324 ct++; 2325 if (q != 0) { 2326 if (((int)q->beg & 01) 2327 != 0) { 2328 printf(G1, 2329 i - ARRAYST, 2330 ct); 2331 printf(G2, 2332 tmps, p); 2333 sdump("elt", q); 2334 } 2335 redef(q); 2336 } 2337 } 2338 tmps = tmps->next; 2339 } while (tmps != 0); 2340 } 2341 } 2342 } 2343 } 2344 2345 void 2346 redef(struct blk *p) 2347 { 2348 int offset; 2349 char *newp; 2350 char *dcmalloc(); 2351 2352 if ((int)p->beg & 01) { 2353 printf(gettext("odd ptr %o hdr %o\n"), p->beg, p); 2354 ospace("redef-bad"); 2355 } 2356 free(dummy); 2357 dummy = dcmalloc(0); 2358 if (dummy == NULL) 2359 ospace("dummy"); 2360 newp = realloc(p->beg, (unsigned)(p->last - p->beg)); 2361 if (newp == NULL) 2362 ospace("redef"); 2363 offset = newp - p->beg; 2364 p->beg = newp; 2365 p->rd += offset; 2366 p->wt += offset; 2367 p->last += offset; 2368 } 2369 2370 void 2371 release(struct blk *p) 2372 { 2373 rel++; 2374 lrel++; 2375 nbytes -= p->last - p->beg; 2376 p->rd = (char *)hfree; 2377 hfree = p; 2378 free(p->beg); 2379 p->beg = NULL; 2380 } 2381 2382 struct blk * 2383 getwd(struct blk *p) 2384 { 2385 struct wblk *wp; 2386 2387 wp = (struct wblk *)p; 2388 if (wp->rdw == wp->wtw) 2389 return (NULL); 2390 return (*wp->rdw++); 2391 } 2392 2393 void 2394 putwd(struct blk *p, struct blk *c) 2395 { 2396 struct wblk *wp; 2397 2398 wp = (struct wblk *)p; 2399 if (wp->wtw == wp->lastw) 2400 more(p); 2401 *wp->wtw++ = c; 2402 } 2403 2404 struct blk * 2405 lookwd(struct blk *p) 2406 { 2407 struct wblk *wp; 2408 2409 wp = (struct wblk *)p; 2410 if (wp->rdw == wp->wtw) 2411 return (NULL); 2412 return (*wp->rdw); 2413 } 2414 2415 char * 2416 nalloc(char *p, unsigned int nbytes) 2417 { 2418 char *dcmalloc(); 2419 char *q, *r; 2420 q = r = dcmalloc(nbytes); 2421 if (q == 0) 2422 return (0); 2423 while (nbytes--) 2424 *q++ = *p++; 2425 return (r); 2426 } 2427 2428 char * 2429 dcmalloc(int size) 2430 { 2431 return (malloc(size ? size : 1)); 2432 } 2433