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 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23 /* All Rights Reserved */ 24 25 26 /* 27 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 #include <stdio.h> 34 #include <signal.h> 35 #include <errno.h> 36 #include <sys/stat.h> 37 #include <sys/types.h> 38 #include <limits.h> 39 #include "dc.h" 40 #include <locale.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 int 63 ctoint(c) 64 #if __STDC__ 65 char c; 66 #else 67 unsigned char c; 68 #endif 69 { 70 int i; 71 72 if (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 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() 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 div(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() { 935 struct blk *dd, *dr, *r; 936 int c; 937 938 dr = pop(); 939 EMPTYS; 940 dd = pop(); 941 EMPTYSR(dr); 942 fsfile(dd); 943 skd = sunputc(dd); 944 fsfile(dr); 945 skr = sunputc(dr); 946 if (sfbeg(dr) == 1 || (sfbeg(dr) == 0 && sbackc(dr) == 0)) { 947 sputc(dr, skr); 948 pushp(dr); 949 printf(gettext("divide by 0\n")); 950 return (1); 951 } 952 if (sfbeg(dd) == 1 || (sfbeg(dd) == 0 && sbackc(dd) == 0)) { 953 #ifdef XPG6 954 sputc(dd, k); 955 #else 956 sputc(dd, skd); 957 #endif 958 pushp(dd); 959 return (1); 960 } 961 c = k-skd+skr; 962 if (c < 0) 963 r = removr(dd, -c); 964 else { 965 r = add0(dd, c); 966 irem = 0; 967 } 968 arg1 = r; 969 arg2 = dr; 970 savk = k; 971 return (0); 972 } 973 974 struct blk * 975 removr(struct blk *p, int n) 976 { 977 int nn, neg; 978 struct blk *q, *s, *r; 979 fsfile(p); 980 neg = sbackc(p); 981 if (neg < 0) 982 chsign(p); 983 rewind(p); 984 nn = (n + 1) / 2; 985 q = salloc(nn); 986 while (n > 1) { 987 sputc(q, sgetc(p)); 988 n -= 2; 989 } 990 r = salloc(2); 991 while (sfeof(p) == 0) 992 sputc(r, sgetc(p)); 993 release(p); 994 if (n == 1) { 995 s = div(r, tenptr); 996 release(r); 997 rewind(rem); 998 if (sfeof(rem) == 0) 999 sputc(q, sgetc(rem)); 1000 release(rem); 1001 if (neg < 0) { 1002 chsign(s); 1003 chsign(q); 1004 irem = q; 1005 return (s); 1006 } 1007 irem = q; 1008 return (s); 1009 } 1010 if (neg < 0) { 1011 chsign(r); 1012 chsign(q); 1013 irem = q; 1014 return (r); 1015 } 1016 irem = q; 1017 return (r); 1018 } 1019 1020 struct blk * 1021 sqrt(struct blk *p) 1022 { 1023 struct blk *r, *q, *s, *t; 1024 int c, n, nn; 1025 1026 n = length(p); 1027 fsfile(p); 1028 c = sbackc(p); 1029 if ((n & 1) != 1) 1030 c = c * 100 + (sfbeg(p) ? 0 : sbackc(p)); 1031 n = (n + 1) >> 1; 1032 r = salloc(n); 1033 zero(r); 1034 seekc(r, n); 1035 nn = 1; 1036 while ((c -= nn) >= 0) 1037 nn += 2; 1038 c = (nn + 1) >> 1; 1039 fsfile(r); 1040 sbackc(r); 1041 if (c >= 100) { 1042 c -= 100; 1043 salterc(r, c); 1044 sputc(r, 1); 1045 } else 1046 salterc(r, c); 1047 for (; ; ) { 1048 q = div(p, r); 1049 s = add(q, r); 1050 release(q); 1051 release(rem); 1052 q = div(s, sqtemp); 1053 release(s); 1054 release(rem); 1055 s = copy(r, length(r)); 1056 chsign(s); 1057 t = add(s, q); 1058 release(s); 1059 fsfile(t); 1060 nn = sfbeg(t) ? 0 : sbackc(t); 1061 if (nn >= 0) 1062 break; 1063 release(r); 1064 release(t); 1065 r = q; 1066 } 1067 release(t); 1068 release(q); 1069 release(p); 1070 return (r); 1071 } 1072 1073 struct blk * 1074 exp(struct blk *base, struct blk *ex) 1075 { 1076 struct blk *r, *e, *p, *e1, *t, *cp; 1077 int temp, c, n; 1078 r = salloc(1); 1079 sputc(r, 1); 1080 p = copy(base, length(base)); 1081 e = copy(ex, length(ex)); 1082 fsfile(e); 1083 if (sfbeg(e) != 0) 1084 goto edone; 1085 temp = 0; 1086 c = sbackc(e); 1087 if (c < 0) { 1088 temp++; 1089 chsign(e); 1090 } 1091 while (length(e) != 0) { 1092 e1 = div(e, sqtemp); 1093 release(e); 1094 e = e1; 1095 n = length(rem); 1096 release(rem); 1097 if (n != 0) { 1098 e1 = mult(p, r); 1099 release(r); 1100 r = e1; 1101 } 1102 t = copy(p, length(p)); 1103 cp = mult(p, t); 1104 release(p); 1105 release(t); 1106 p = cp; 1107 } 1108 if (temp != 0) { 1109 if ((c = length(base)) == 0) { 1110 goto edone; 1111 } 1112 if (c > 1) 1113 create(r); 1114 else { 1115 rewind(base); 1116 if ((c = sgetc(base)) <= 1) { 1117 create(r); 1118 sputc(r, c); 1119 } else 1120 create(r); 1121 } 1122 } 1123 edone: 1124 release(p); 1125 release(e); 1126 return (r); 1127 } 1128 1129 void 1130 init(int argc, char **argv) 1131 { 1132 struct sym *sp; 1133 char *dcmalloc(); 1134 struct stat tsb; 1135 1136 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 1137 signal(SIGINT, onintr); 1138 setbuf(stdout, (char *)NULL); 1139 svargc = --argc; 1140 svargv = argv; 1141 while (svargc > 0 && svargv[1][0] == '-') { 1142 switch (svargv[1][1]) { 1143 default: 1144 dbg = 1; 1145 } 1146 svargc--; 1147 svargv++; 1148 } 1149 1150 ifile = 1; 1151 1152 if (svargc <= 0) 1153 curfile = stdin; 1154 else { 1155 if (stat(svargv[1], &tsb) < 0) { 1156 printf(gettext("Cannot stat %s: "), svargv[1]); 1157 perror(""); 1158 exit(1); 1159 } 1160 1161 if (S_ISREG(tsb.st_mode)) { 1162 if ((curfile = fopen(svargv[1], "r")) == NULL) { 1163 printf(gettext("can't open file %s\n"), \ 1164 svargv[1]); 1165 exit(1); 1166 } 1167 } else { 1168 printf(gettext("invalid file type: %s\n"), \ 1169 svargv[1]); 1170 exit(1); 1171 } 1172 } 1173 1174 dummy = dcmalloc(0); 1175 scalptr = salloc(1); 1176 sputc(scalptr, 0); 1177 basptr = salloc(1); 1178 sputc(basptr, 10); 1179 obase = 10; 1180 log10 = log2(10L); 1181 1182 /* 1183 * POSIX.2 1184 * default line length is 70 characters including newline 1185 */ 1186 ll = 70; 1187 fw = 1; 1188 fw1 = 0; 1189 tenptr = salloc(1); 1190 sputc(tenptr, 10); 1191 obase = 10; 1192 inbas = salloc(1); 1193 sputc(inbas, 10); 1194 sqtemp = salloc(1); 1195 sputc(sqtemp, 2); 1196 chptr = salloc(0); 1197 strptr = salloc(0); 1198 divxyz = salloc(0); 1199 stkbeg = stkptr = &stack[0]; 1200 stkend = &stack[STKSZ]; 1201 stkerr = 0; 1202 readptr = &readstk[0]; 1203 k = 0; 1204 sp = sptr = &symlst[0]; 1205 while (sptr < &symlst[TBLSZ]) { 1206 sptr->next = ++sp; 1207 sptr++; 1208 } 1209 sptr->next = 0; 1210 sfree = &symlst[0]; 1211 } 1212 1213 void 1214 onintr(int sig) 1215 { 1216 1217 signal(sig, onintr); 1218 while (readptr != &readstk[0]) { 1219 if (*readptr != 0) 1220 release(*readptr); 1221 readptr--; 1222 } 1223 curfile = stdin; 1224 commnds(); 1225 } 1226 1227 void 1228 pushp(struct blk *p) 1229 { 1230 if (stkptr == stkend) 1231 printf(gettext("out of stack space\n")); 1232 else { 1233 stkerr = 0; 1234 *++stkptr = p; 1235 } 1236 } 1237 1238 struct blk * 1239 pop() { 1240 if (stkptr == stack) { 1241 stkerr = 1; 1242 return (0); 1243 } 1244 return (*stkptr--); 1245 } 1246 1247 struct blk * 1248 readin() { 1249 struct blk *p, *q; 1250 int dp, dpct; 1251 int c; 1252 1253 dp = dpct = 0; 1254 p = salloc(0); 1255 for (; ; ) { 1256 c = readc(); 1257 switch (c) { 1258 case '.': 1259 if (dp != 0) 1260 goto gotnum; 1261 dp++; 1262 continue; 1263 case '\\': 1264 readc(); 1265 continue; 1266 default: 1267 if (c >= 'A' && c <= 'F') 1268 c = c - 'A' + 10; 1269 else 1270 if (c >= '0' && c <= '9') 1271 c -= '0'; 1272 else 1273 goto gotnum; 1274 if (dp != 0) { 1275 if (dpct >= 99) 1276 continue; 1277 dpct++; 1278 } 1279 create(chptr); 1280 if (c != 0) 1281 sputc(chptr, c); 1282 q = mult(p, inbas); 1283 release(p); 1284 p = add(chptr, q); 1285 release(q); 1286 } 1287 } 1288 gotnum: 1289 unreadc(c); 1290 if (dp == 0) { 1291 sputc(p, 0); 1292 return (p); 1293 } else { 1294 /* if not base 10, then scale fractional input to precision */ 1295 if (((int)*(inbas->beg)) != 10) { 1296 while (dpct < k) { 1297 create(chptr); 1298 q = mult(p, inbas); 1299 release(p); 1300 p = add(chptr, q); 1301 release(q); 1302 dpct++; 1303 } 1304 } 1305 q = scale(p, dpct); 1306 return (q); 1307 } 1308 } 1309 1310 /* 1311 * returns pointer to struct with ct 0's & p 1312 */ 1313 struct blk * 1314 add0(struct blk *p, int ct) 1315 { 1316 struct blk *q, *t; 1317 1318 q = salloc(length(p) + (ct + 1) / 2); 1319 while (ct > 1) { 1320 sputc(q, 0); 1321 ct -= 2; 1322 } 1323 rewind(p); 1324 while (sfeof(p) == 0) { 1325 sputc(q, sgetc(p)); 1326 } 1327 release(p); 1328 if (ct == 1) { 1329 t = mult(tenptr, q); 1330 release(q); 1331 return (t); 1332 } 1333 return (q); 1334 } 1335 1336 struct blk * 1337 mult(struct blk *p, struct blk *q) 1338 { 1339 struct blk *mp, *mq, *mr; 1340 int sign, offset, carry; 1341 int cq, cp, mt, mcr; 1342 1343 offset = sign = 0; 1344 fsfile(p); 1345 mp = p; 1346 if (sfbeg(p) == 0) { 1347 if (sbackc(p) < 0) { 1348 mp = copy(p, length(p)); 1349 chsign(mp); 1350 sign = ~sign; 1351 } 1352 } 1353 fsfile(q); 1354 mq = q; 1355 if (sfbeg(q) == 0) { 1356 if (sbackc(q) < 0) { 1357 mq = copy(q, length(q)); 1358 chsign(mq); 1359 sign = ~sign; 1360 } 1361 } 1362 mr = salloc(length(mp) + length(mq)); 1363 zero(mr); 1364 rewind(mq); 1365 while (sfeof(mq) == 0) { 1366 cq = sgetc(mq); 1367 rewind(mp); 1368 rewind(mr); 1369 mr->rd += offset; 1370 carry = 0; 1371 while (sfeof(mp) == 0) { 1372 cp = sgetc(mp); 1373 mcr = sfeof(mr) ? 0 : slookc(mr); 1374 mt = cp*cq + carry + mcr; 1375 carry = mt / 100; 1376 salterc(mr, mt % 100); 1377 } 1378 offset++; 1379 if (carry != 0) { 1380 mcr = sfeof(mr) ? 0 : slookc(mr); 1381 salterc(mr, mcr + carry); 1382 } 1383 } 1384 if (sign < 0) { 1385 chsign(mr); 1386 } 1387 if (mp != p) 1388 release(mp); 1389 if (mq != q) 1390 release(mq); 1391 return (mr); 1392 } 1393 1394 void 1395 chsign(struct blk *p) 1396 { 1397 int carry; 1398 char ct; 1399 1400 carry = 0; 1401 rewind(p); 1402 while (sfeof(p) == 0) { 1403 ct = 100 - slookc(p) - carry; 1404 carry = 1; 1405 if (ct >= 100) { 1406 ct -= 100; 1407 carry = 0; 1408 } 1409 salterc(p, ct); 1410 } 1411 if (carry != 0) { 1412 sputc(p, -1); 1413 fsfile(p); 1414 sbackc(p); 1415 ct = sbackc(p); 1416 if (ct == 99) { 1417 truncate(p); 1418 sputc(p, -1); 1419 } 1420 } else { 1421 fsfile(p); 1422 ct = sbackc(p); 1423 if (ct == 0) 1424 truncate(p); 1425 } 1426 } 1427 1428 char 1429 readc() { 1430 loop: 1431 if ((readptr != &readstk[0]) && (*readptr != 0)) { 1432 if (sfeof(*readptr) == 0) 1433 return (lastchar = sgetc(*readptr)); 1434 release(*readptr); 1435 readptr--; 1436 goto loop; 1437 } 1438 lastchar = getc(curfile); 1439 if (lastchar != EOF) 1440 return (lastchar); 1441 if (readptr != &readptr[0]) { 1442 readptr--; 1443 if (*readptr == 0) 1444 curfile = stdin; 1445 goto loop; 1446 } 1447 if (curfile != stdin) { 1448 fclose(curfile); 1449 curfile = stdin; 1450 goto loop; 1451 } 1452 exit(0); 1453 } 1454 1455 void 1456 unreadc(char c) 1457 { 1458 1459 if ((readptr != &readstk[0]) && (*readptr != 0)) { 1460 sungetc(*readptr, c); 1461 } else 1462 ungetc(c, curfile); 1463 } 1464 1465 void 1466 binop(char c) 1467 { 1468 struct blk *r; 1469 1470 switch (c) { 1471 case '+': 1472 r = add(arg1, arg2); 1473 break; 1474 case '*': 1475 r = mult(arg1, arg2); 1476 break; 1477 case '/': 1478 r = div(arg1, arg2); 1479 break; 1480 } 1481 release(arg1); 1482 release(arg2); 1483 sputc(r, savk); 1484 pushp(r); 1485 } 1486 1487 void 1488 print(struct blk *hptr) 1489 { 1490 struct blk *p, *q, *dec; 1491 int sc; /* scale */ 1492 int dig, dout, ct; 1493 1494 rewind(hptr); 1495 while (sfeof(hptr) == 0) { 1496 if (sgetc(hptr) > 99) { 1497 rewind(hptr); 1498 while (sfeof(hptr) == 0) { 1499 printf("%c", sgetc(hptr)); 1500 } 1501 printf("\n"); 1502 return; 1503 } 1504 } 1505 fsfile(hptr); 1506 sc = sbackc(hptr); /* read scale off end of blk */ 1507 if (sfbeg(hptr) != 0) { 1508 printf("0\n"); 1509 return; 1510 } 1511 count = ll; 1512 p = copy(hptr, length(hptr)); 1513 sunputc(p); 1514 fsfile(p); 1515 if (sbackc(p) < 0) { 1516 chsign(p); 1517 OUTC('-'); 1518 } 1519 if ((obase == 0) || (obase == -1)) { 1520 oneot(p, sc, 'd'); 1521 return; 1522 } 1523 if (obase == 1) { 1524 oneot(p, sc, '1'); 1525 return; 1526 } 1527 if (obase == 10) { 1528 tenot(p, sc); 1529 return; 1530 } 1531 create(strptr); 1532 dig = log10 * sc; 1533 dout = ((dig / 10) + dig) / logo; 1534 dec = getdec(p, sc); 1535 p = removc(p, sc); 1536 while (length(p) != 0) { 1537 q = div(p, basptr); 1538 release(p); 1539 p = q; 1540 (*outdit)(rem, 0); 1541 if (obase > 16) 1542 sputc(strptr, ' '); 1543 } 1544 release(p); 1545 fsfile(strptr); 1546 while (sfbeg(strptr) == 0) 1547 OUTC(sbackc(strptr)); 1548 if (sc == 0) { 1549 release(dec); 1550 printf("\n"); 1551 return; 1552 } 1553 create(strptr); 1554 OUTC('.'); 1555 ct = 0; 1556 do { 1557 if (ct != 0 && obase > 16) 1558 sputc(strptr, ' '); 1559 q = mult(basptr, dec); 1560 release(dec); 1561 dec = getdec(q, sc); 1562 p = removc(q, sc); 1563 (*outdit)(p, 1); 1564 } while (++ct < dout); 1565 release(dec); 1566 rewind(strptr); 1567 while (sfeof(strptr) == 0) 1568 OUTC(sgetc(strptr)); 1569 printf("\n"); 1570 } 1571 1572 struct blk * 1573 getdec(struct blk *p, int sc) 1574 { 1575 int cc; 1576 struct blk *q, *t, *s; 1577 1578 rewind(p); 1579 if (length(p) * 2 < sc) { 1580 q = copy(p, length(p)); 1581 return (q); 1582 } 1583 q = salloc(length(p)); 1584 while (sc >= 1) { 1585 sputc(q, sgetc(p)); 1586 sc -= 2; 1587 } 1588 if (sc != 0) { 1589 t = mult(q, tenptr); 1590 s = salloc(cc = length(q)); 1591 release(q); 1592 rewind(t); 1593 while (cc-- > 0) 1594 sputc(s, sgetc(t)); 1595 sputc(s, 0); 1596 release(t); 1597 t = div(s, tenptr); 1598 release(s); 1599 release(rem); 1600 return (t); 1601 } 1602 return (q); 1603 } 1604 1605 void 1606 tenot(struct blk *p, int sc) 1607 { 1608 int c, f; 1609 1610 fsfile(p); 1611 1612 f = 0; 1613 1614 /* 1615 * at this point, the number is stored as base 100 (two decimal 1616 * digits per char) stuck in a buf (character array) backwards. 1617 * sc indicates the scaling factor. 1618 */ 1619 1620 while ((sfbeg(p) == 0) && ((p->rd-p->beg-1)*2 >= sc)) { 1621 /* 1622 * get numbers from the buf until we are the beginning of 1623 * the buf (i.e., there are no more numbers) or the numbers 1624 * remaining fall within the scaled (to the right of the 1625 * decimal point) portion. 1626 */ 1627 c = sbackc(p); 1628 1629 /* 1630 * POSIX.2 1631 * as we output digits, we have to watch the line length (ll) 1632 * which should include a '\' and a newline. 1633 */ 1634 if (c < 10) { 1635 /* 1636 * if the number is less than 10, we need to output 1637 * a space-holding '0' (unless this is the first time 1638 * through). 1639 */ 1640 if (f == 1) { 1641 CHECKEND; 1642 printf("0"); 1643 count--; 1644 } 1645 1646 CHECKEND; 1647 printf("%d", c); 1648 count--; 1649 } else { 1650 CHECKEND; 1651 printf("%d", c / 10); 1652 count--; 1653 1654 CHECKEND; 1655 printf("%d", c % 10); 1656 count--; 1657 } 1658 f = 1; 1659 } 1660 1661 if (sc == 0) { 1662 /* 1663 * no scaling factor, so we must have exited loop because we 1664 * ran out of numbers. 1665 */ 1666 printf("\n"); 1667 release(p); 1668 return; 1669 } 1670 1671 if ((p->rd - p->beg) * 2 > sc) { 1672 c = sbackc(p); 1673 1674 CHECKEND; 1675 printf("%d", c / 10); 1676 count--; 1677 1678 CHECKEND; 1679 printf("."); 1680 count--; 1681 1682 CHECKEND; 1683 printf("%d", c % 10); 1684 count--; 1685 1686 sc--; 1687 } else { 1688 CHECKEND; 1689 printf("."); 1690 count--; 1691 } 1692 1693 if (sc > (p->rd - p->beg) * 2) { 1694 while (sc > (p->rd - p->beg) * 2) { 1695 CHECKEND; 1696 printf("0"); 1697 count--; 1698 1699 sc--; 1700 } 1701 } 1702 1703 /* now go through the scaled portion of the number */ 1704 while (sc > 1) { 1705 c = sbackc(p); 1706 if (c < 10) { 1707 CHECKEND; 1708 printf("0"); 1709 count--; 1710 1711 CHECKEND; 1712 printf("%d", c); 1713 count--; 1714 } else { 1715 CHECKEND; 1716 printf("%d", c / 10); 1717 count--; 1718 1719 CHECKEND; 1720 printf("%d", c % 10); 1721 count--; 1722 } 1723 sc -= 2; 1724 } 1725 1726 if (sc == 1) { /* just in case the scaling factor was odd */ 1727 CHECKEND; 1728 printf("%d", sbackc(p) / 10); 1729 } 1730 1731 printf("\n"); 1732 release(p); 1733 } 1734 1735 void 1736 oneot(struct blk *p, int sc, char ch) 1737 { 1738 struct blk *q; 1739 1740 q = removc(p, sc); 1741 create(strptr); 1742 sputc(strptr, -1); 1743 while (length(q) > 0) { 1744 p = add(strptr, q); 1745 release(q); 1746 q = p; 1747 OUTC(ch); 1748 } 1749 release(q); 1750 printf("\n"); 1751 } 1752 1753 void 1754 hexot(struct blk *p, int flg) 1755 { 1756 int c; 1757 1758 rewind(p); 1759 if (sfeof(p) != 0) { 1760 sputc(strptr, '0'); 1761 release(p); 1762 return; 1763 } 1764 c = sgetc(p); 1765 release(p); 1766 if (c >= 16) { 1767 printf(gettext("hex digit > 16")); 1768 return; 1769 } 1770 sputc(strptr, c < 10 ? c + '0' : c - 10 + 'A'); 1771 } 1772 1773 void 1774 bigot(struct blk *p, int flg) 1775 { 1776 struct blk *t, *q; 1777 int l; 1778 int neg; 1779 1780 if (flg == 1) 1781 t = salloc(0); 1782 else { 1783 t = strptr; 1784 l = length(strptr) + fw - 1; 1785 } 1786 neg = 0; 1787 if (length(p) != 0) { 1788 fsfile(p); 1789 if (sbackc(p) < 0) { 1790 neg = 1; 1791 chsign(p); 1792 } 1793 while (length(p) != 0) { 1794 q = div(p, tenptr); 1795 release(p); 1796 p = q; 1797 rewind(rem); 1798 sputc(t, sfeof(rem) ? '0' : sgetc(rem) + '0'); 1799 release(rem); 1800 } 1801 } 1802 release(p); 1803 if (flg == 1) { 1804 l = fw1 - length(t); 1805 if (neg != 0) { 1806 l--; 1807 sputc(strptr, '-'); 1808 } 1809 fsfile(t); 1810 while (l-- > 0) 1811 sputc(strptr, '0'); 1812 while (sfbeg(t) == 0) 1813 sputc(strptr, sbackc(t)); 1814 release(t); 1815 } else { 1816 l -= length(strptr); 1817 while (l-- > 0) 1818 sputc(strptr, '0'); 1819 if (neg != 0) { 1820 sunputc(strptr); 1821 sputc(strptr, '-'); 1822 } 1823 } 1824 } 1825 1826 struct blk * 1827 add(struct blk *a1, struct blk *a2) 1828 { 1829 struct blk *p; 1830 int carry, n; 1831 int size; 1832 int c, n1, n2; 1833 1834 size = length(a1) > length(a2) ? length(a1) : length(a2); 1835 p = salloc(size); 1836 rewind(a1); 1837 rewind(a2); 1838 carry = 0; 1839 while (--size >= 0) { 1840 n1 = sfeof(a1) ? 0 : sgetc(a1); 1841 n2 = sfeof(a2) ? 0 : sgetc(a2); 1842 n = n1 + n2 + carry; 1843 if (n >= 100) { 1844 carry = 1; 1845 n -= 100; 1846 } else 1847 if (n < 0) { 1848 carry = -1; 1849 n += 100; 1850 } else 1851 carry = 0; 1852 sputc(p, n); 1853 } 1854 if (carry != 0) 1855 sputc(p, carry); 1856 fsfile(p); 1857 if (sfbeg(p) == 0) { 1858 while (sfbeg(p) == 0 && (c = sbackc(p)) == 0); 1859 if (c != 0) 1860 salterc(p, c); 1861 truncate(p); 1862 } 1863 fsfile(p); 1864 if (sfbeg(p) == 0 && sbackc(p) == -1) { 1865 while ((c = sbackc(p)) == 99) { 1866 if (c == EOF) 1867 break; 1868 } 1869 sgetc(p); 1870 salterc(p, -1); 1871 truncate(p); 1872 } 1873 return (p); 1874 } 1875 1876 int 1877 eqk() { 1878 struct blk *p, *q; 1879 int skp, skq; 1880 1881 p = pop(); 1882 EMPTYS; 1883 q = pop(); 1884 EMPTYSR(p); 1885 skp = sunputc(p); 1886 skq = sunputc(q); 1887 if (skp == skq) { 1888 arg1 = p; 1889 arg2 = q; 1890 savk = skp; 1891 return (0); 1892 } else 1893 if (skp < skq) { 1894 savk = skq; 1895 p = add0(p, skq - skp); 1896 } else { 1897 savk = skp; 1898 q = add0(q, skp - skq); 1899 } 1900 arg1 = p; 1901 arg2 = q; 1902 return (0); 1903 } 1904 1905 struct blk * 1906 removc(struct blk *p, int n) 1907 { 1908 struct blk *q, *r; 1909 1910 rewind(p); 1911 while (n > 1) { 1912 sgetc(p); 1913 n -= 2; 1914 } 1915 q = salloc(2); 1916 while (sfeof(p) == 0) 1917 sputc(q, sgetc(p)); 1918 if (n == 1) { 1919 r = div(q, tenptr); 1920 release(q); 1921 release(rem); 1922 q = r; 1923 } 1924 release(p); 1925 return (q); 1926 } 1927 1928 struct blk * 1929 scalint(struct blk *p) 1930 { 1931 int n; 1932 1933 n = sunputc(p); 1934 p = removc(p, n); 1935 return (p); 1936 } 1937 1938 struct blk * 1939 scale(struct blk *p, int n) 1940 { 1941 struct blk *q, *s, *t; 1942 1943 t = add0(p, n); 1944 q = salloc(1); 1945 sputc(q, n); 1946 s = exp(inbas, q); 1947 release(q); 1948 q = div(t, s); 1949 release(t); 1950 release(s); 1951 release(rem); 1952 sputc(q, n); 1953 return (q); 1954 } 1955 1956 int 1957 subt() { 1958 arg1 = pop(); 1959 EMPTYS; 1960 savk = sunputc(arg1); 1961 chsign(arg1); 1962 sputc(arg1, savk); 1963 pushp(arg1); 1964 if (eqk() != 0) 1965 return (1); 1966 binop('+'); 1967 return (0); 1968 } 1969 1970 int 1971 command() { 1972 int c; 1973 char line[100], *sl; 1974 void (*savint)(); 1975 pid_t pid, rpid; 1976 int retcode; 1977 1978 switch (c = readc()) { 1979 case '<': 1980 return (cond(NL)); 1981 case '>': 1982 return (cond(NG)); 1983 case '=': 1984 return (cond(NE)); 1985 default: 1986 sl = line; 1987 *sl++ = c; 1988 while ((c = readc()) != '\n') 1989 *sl++ = c; 1990 *sl = 0; 1991 if ((pid = fork()) == (pid_t)0) { 1992 execl("/usr/bin/sh", "sh", "-c", line, 0); 1993 exit(0100); 1994 } 1995 savint = signal(SIGINT, SIG_IGN); 1996 while ((rpid = wait(&retcode)) != pid && rpid != (pid_t)-1); 1997 signal(SIGINT, savint); 1998 printf(gettext("!\n")); 1999 return (0); 2000 } 2001 } 2002 2003 int 2004 cond(char c) 2005 { 2006 struct blk *p; 2007 int cc; 2008 2009 if (subt() != 0) 2010 return (1); 2011 p = pop(); 2012 sunputc(p); 2013 if (length(p) == 0) { 2014 release(p); 2015 if (c == '<' || c == '>' || c == NE) { 2016 readc(); 2017 return (0); 2018 } 2019 load(); 2020 return (1); 2021 } else { 2022 if (c == '=') { 2023 release(p); 2024 readc(); 2025 return (0); 2026 } 2027 } 2028 if (c == NE) { 2029 release(p); 2030 load(); 2031 return (1); 2032 } 2033 fsfile(p); 2034 cc = sbackc(p); 2035 release(p); 2036 if ((cc < 0 && (c == '<' || c == NG)) || 2037 (cc > 0) && (c == '>' || c == NL)) { 2038 readc(); 2039 return (0); 2040 } 2041 load(); 2042 return (1); 2043 } 2044 2045 void 2046 load() { 2047 int c; 2048 struct blk *p, *q, *t, *s; 2049 2050 c = readc() & 0377; 2051 sptr = stable[c]; 2052 if (sptr != 0) { 2053 p = sptr->val; 2054 if (c >= ARRAYST) { 2055 q = salloc(length(p)); 2056 rewind(p); 2057 while (sfeof(p) == 0) { 2058 s = getwd(p); 2059 if (s == 0) 2060 putwd(q, (struct blk *)NULL); 2061 else { 2062 t = copy(s, length(s)); 2063 putwd(q, t); 2064 } 2065 } 2066 pushp(q); 2067 } else { 2068 q = copy(p, length(p)); 2069 pushp(q); 2070 } 2071 } else { 2072 q = salloc(1); 2073 if (c <= LASTFUN) { 2074 printf(gettext 2075 ("function %c undefined\n"), c + 'a' - 1); 2076 sputc(q, 'c'); 2077 sputc(q, '0'); 2078 sputc(q, ' '); 2079 sputc(q, '1'); 2080 sputc(q, 'Q'); 2081 } else 2082 sputc(q, 0); 2083 pushp(q); 2084 } 2085 } 2086 2087 int 2088 log2(long n) 2089 { 2090 int i; 2091 2092 if (n == 0) 2093 return (0); 2094 i = 31; 2095 if (n < 0) 2096 return (i); 2097 while ((n = n << 1) > 0) 2098 i--; 2099 return (--i); 2100 } 2101 2102 struct blk * 2103 salloc(int size) 2104 { 2105 struct blk *hdr; 2106 char *ptr; 2107 char *dcmalloc(); 2108 all++; 2109 lall++; 2110 if (all - rel > active) 2111 active = all - rel; 2112 nbytes += size; 2113 lbytes += size; 2114 if (nbytes > maxsize) 2115 maxsize = nbytes; 2116 if (size > longest) 2117 longest = size; 2118 ptr = dcmalloc((unsigned)size); 2119 if (ptr == 0) { 2120 garbage("salloc"); 2121 if ((ptr = dcmalloc((unsigned)size)) == 0) 2122 ospace("salloc"); 2123 } 2124 if ((hdr = hfree) == 0) 2125 hdr = morehd(); 2126 hfree = (struct blk *)hdr->rd; 2127 hdr->rd = hdr->wt = hdr->beg = ptr; 2128 hdr->last = ptr + size; 2129 return (hdr); 2130 } 2131 2132 struct blk * 2133 morehd() { 2134 struct blk *h, *kk; 2135 char *dcmalloc(); 2136 2137 headmor++; 2138 nbytes += HEADSZ; 2139 hfree = h = (struct blk *)dcmalloc(HEADSZ); 2140 if (hfree == 0) { 2141 garbage("morehd"); 2142 if ((hfree = h = (struct blk *)dcmalloc(HEADSZ)) == 0) 2143 ospace("headers"); 2144 } 2145 kk = h; 2146 while (h < hfree + (HEADSZ/BLK)) 2147 (h++)->rd = (char *)++kk; 2148 (--h)->rd = 0; 2149 return (hfree); 2150 } 2151 2152 struct blk * 2153 copy(struct blk *hptr, int size) 2154 { 2155 struct blk *hdr; 2156 unsigned sz; 2157 char *ptr; 2158 2159 all++; 2160 lall++; 2161 lcopy++; 2162 nbytes += size; 2163 lbytes += size; 2164 if (size > longest) 2165 longest = size; 2166 if (size > maxsize) 2167 maxsize = size; 2168 sz = length(hptr); 2169 ptr = nalloc(hptr->beg, (unsigned)size); 2170 if (ptr == 0) { 2171 garbage("copy"); 2172 if ((ptr = nalloc(hptr->beg, (unsigned)size)) == NULL) { 2173 printf(gettext("copy size %d\n"), size); 2174 ospace("copy"); 2175 } 2176 } 2177 if ((hdr = hfree) == 0) 2178 hdr = morehd(); 2179 hfree = (struct blk *)hdr->rd; 2180 hdr->rd = hdr->beg = ptr; 2181 hdr->last = ptr + size; 2182 hdr->wt = ptr + sz; 2183 ptr = hdr->wt; 2184 while (ptr < hdr->last) 2185 *ptr++ = '\0'; 2186 return (hdr); 2187 } 2188 2189 void 2190 sdump(char *s1, struct blk *hptr) 2191 { 2192 char *p; 2193 2194 if (hptr) { 2195 printf("%s %o rd %o wt %o beg %o last %o\n", s1, hptr, 2196 hptr->rd, hptr->wt, hptr->beg, hptr->last); 2197 p = hptr->beg; 2198 while (p < hptr->wt) 2199 printf("%d ", *p++); 2200 printf("\n"); 2201 } else 2202 printf("%s %o\n", s1, hptr); 2203 } 2204 2205 void 2206 seekc(struct blk *hptr, int n) 2207 { 2208 char *nn, *p; 2209 2210 nn = hptr->beg + n; 2211 if (nn > hptr->last) { 2212 nbytes += nn - hptr->last; 2213 if (nbytes > maxsize) 2214 maxsize = nbytes; 2215 lbytes += nn - hptr->last; 2216 if (n > longest) 2217 longest = n; 2218 p = realloc(hptr->beg, (unsigned)n); 2219 if (p == 0) { 2220 hptr->beg = realloc(hptr->beg, 2221 (unsigned)(hptr->last - hptr->beg)); 2222 garbage("seekc"); 2223 if ((p = realloc(hptr->beg, (unsigned)n)) == 0) 2224 ospace("seekc"); 2225 } 2226 hptr->beg = p; 2227 hptr->wt = hptr->last = hptr->rd = p + n; 2228 return; 2229 } 2230 hptr->rd = nn; 2231 if (nn > hptr->wt) 2232 hptr->wt = nn; 2233 } 2234 2235 void 2236 salterwd(struct wblk *hptr, struct blk *n) 2237 { 2238 if (hptr->rdw == hptr->lastw) 2239 more((struct blk *)hptr); 2240 *hptr->rdw++ = n; 2241 if (hptr->rdw > hptr->wtw) 2242 hptr->wtw = hptr->rdw; 2243 } 2244 2245 void 2246 more(struct blk *hptr) 2247 { 2248 unsigned size; 2249 char *p; 2250 2251 if ((size = (hptr->last - hptr->beg) * 2) == 0) 2252 size = 1; 2253 nbytes += size / 2; 2254 if (nbytes > maxsize) 2255 maxsize = nbytes; 2256 if (size > longest) 2257 longest = size; 2258 lbytes += size / 2; 2259 lmore++; 2260 p = realloc(hptr->beg, (unsigned)size); 2261 if (p == 0) { 2262 hptr->beg = realloc(hptr->beg, 2263 (unsigned)(hptr->last - hptr->beg)); 2264 garbage("more"); 2265 if ((p = realloc(hptr->beg, size)) == 0) 2266 ospace("more"); 2267 } 2268 hptr->rd = hptr->rd - hptr->beg + p; 2269 hptr->wt = hptr->wt - hptr->beg + p; 2270 hptr->beg = p; 2271 hptr->last = p + size; 2272 } 2273 2274 void 2275 ospace(char *s) 2276 { 2277 printf(gettext("out of space: %s\n"), s); 2278 printf(gettext("all %ld rel %ld headmor %ld\n"), all, rel, headmor); 2279 printf(gettext("nbytes %ld\n"), nbytes); 2280 sdump("stk", *stkptr); 2281 abort(); 2282 } 2283 2284 #define G1 gettext("array %o elt %d odd\n") 2285 #define G2 gettext("tmps %o p %o\n") 2286 void 2287 garbage(char *s) 2288 { 2289 int i; 2290 struct blk *p, *q; 2291 struct sym *tmps; 2292 int ct; 2293 2294 printf(gettext("got to garbage %s\n"), s); 2295 for (i = 0; i < TBLSZ; i++) { 2296 tmps = stable[i]; 2297 if (tmps != 0) { 2298 if (i < ARRAYST) { 2299 do { 2300 p = tmps->val; 2301 if (((int)p->beg & 01) != 0) { 2302 printf(gettext( 2303 "string %o\n"), i); 2304 sdump("odd beg", p); 2305 } 2306 redef(p); 2307 tmps = tmps->next; 2308 } while (tmps != 0); 2309 continue; 2310 } else { 2311 do { 2312 p = tmps->val; 2313 rewind(p); 2314 ct = 0; 2315 while ((q = getwd(p)) != NULL) { 2316 ct++; 2317 if (q != 0) { 2318 if (((int)q->beg & 01) 2319 != 0) { 2320 printf(G1, 2321 i - ARRAYST, 2322 ct); 2323 printf(G2, 2324 tmps, p); 2325 sdump("elt", q); 2326 } 2327 redef(q); 2328 } 2329 } 2330 tmps = tmps->next; 2331 } while (tmps != 0); 2332 } 2333 } 2334 } 2335 } 2336 2337 void 2338 redef(struct blk *p) 2339 { 2340 int offset; 2341 char *newp; 2342 char *dcmalloc(); 2343 2344 if ((int)p->beg & 01) { 2345 printf(gettext("odd ptr %o hdr %o\n"), p->beg, p); 2346 ospace("redef-bad"); 2347 } 2348 free(dummy); 2349 dummy = dcmalloc(0); 2350 if (dummy == NULL) 2351 ospace("dummy"); 2352 newp = realloc(p->beg, (unsigned)(p->last - p->beg)); 2353 if (newp == NULL) 2354 ospace("redef"); 2355 offset = newp - p->beg; 2356 p->beg = newp; 2357 p->rd += offset; 2358 p->wt += offset; 2359 p->last += offset; 2360 } 2361 2362 void 2363 release(struct blk *p) 2364 { 2365 rel++; 2366 lrel++; 2367 nbytes -= p->last - p->beg; 2368 p->rd = (char *)hfree; 2369 hfree = p; 2370 free(p->beg); 2371 p->beg = NULL; 2372 } 2373 2374 struct blk * 2375 getwd(struct blk *p) 2376 { 2377 struct wblk *wp; 2378 2379 wp = (struct wblk *)p; 2380 if (wp->rdw == wp->wtw) 2381 return (NULL); 2382 return (*wp->rdw++); 2383 } 2384 2385 void 2386 putwd(struct blk *p, struct blk *c) 2387 { 2388 struct wblk *wp; 2389 2390 wp = (struct wblk *)p; 2391 if (wp->wtw == wp->lastw) 2392 more(p); 2393 *wp->wtw++ = c; 2394 } 2395 2396 struct blk * 2397 lookwd(struct blk *p) 2398 { 2399 struct wblk *wp; 2400 2401 wp = (struct wblk *)p; 2402 if (wp->rdw == wp->wtw) 2403 return (NULL); 2404 return (*wp->rdw); 2405 } 2406 2407 char * 2408 nalloc(char *p, unsigned int nbytes) 2409 { 2410 char *dcmalloc(); 2411 char *q, *r; 2412 q = r = dcmalloc(nbytes); 2413 if (q == 0) 2414 return (0); 2415 while (nbytes--) 2416 *q++ = *p++; 2417 return (r); 2418 } 2419 2420 char * 2421 dcmalloc(int size) 2422 { 2423 return (malloc(size ? size : 1)); 2424 } 2425