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);