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