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 /* 31 * University Copyright- Copyright (c) 1982, 1986, 1988 32 * The Regents of the University of California 33 * All Rights Reserved 34 * 35 * University Acknowledgment- Portions of this document are derived from 36 * software developed by the University of California, Berkeley, and its 37 * contributors. 38 */ 39 40 #include <ctype.h> 41 #include "tdef.h" 42 #ifdef NROFF 43 #include "tw.h" 44 #endif 45 #include "ext.h" 46 /* 47 * troff4.c 48 * 49 * number registers, conversion, arithmetic 50 */ 51 52 53 int regcnt = NNAMES; 54 int falsef = 0; /* on if inside false branch of if */ 55 #define NHASH(i) ((i>>6)^i)&0177 56 struct numtab *nhash[128]; /* 128 == the 0177 on line above */ 57 58 int 59 setn() 60 { 61 int i, j; 62 tchar ii; 63 int f; 64 65 f = nform = 0; 66 if ((i = cbits(ii = getach())) == '+') 67 f = 1; 68 else if (i == '-') 69 f = -1; 70 else 71 ch = ii; 72 if (falsef) 73 f = 0; 74 if ((i = getsn()) == 0) 75 return (0); 76 if ((i & 0177) == '.') 77 switch (i >> BYTE) { 78 case 's': 79 i = pts; 80 break; 81 case 'v': 82 i = lss; 83 break; 84 case 'f': 85 i = font; 86 break; 87 case 'p': 88 i = pl; 89 break; 90 case 't': 91 i = findt1(); 92 break; 93 case 'o': 94 i = po; 95 break; 96 case 'l': 97 i = ll; 98 break; 99 case 'i': 100 i = in; 101 break; 102 case '$': 103 i = frame->nargs; 104 break; 105 case 'A': 106 i = ascii; 107 break; 108 case 'c': 109 i = numtab[CD].val; 110 break; 111 case 'n': 112 i = lastl; 113 break; 114 case 'a': 115 i = ralss; 116 break; 117 case 'h': 118 i = dip->hnl; 119 break; 120 case 'd': 121 if (dip != d) 122 i = dip->dnl; 123 else 124 i = numtab[NL].val; 125 break; 126 case 'u': 127 i = fi; 128 break; 129 case 'j': 130 i = ad + 2 * admod; 131 break; 132 case 'w': 133 i = widthp; 134 break; 135 case 'x': 136 i = nel; 137 break; 138 case 'y': 139 i = un; 140 break; 141 case 'T': 142 i = dotT; 143 break; /*-Tterm used in nroff*/ 144 case 'V': 145 i = VERT; 146 break; 147 case 'H': 148 i = HOR; 149 break; 150 case 'k': 151 i = ne; 152 break; 153 case 'P': 154 i = print; 155 break; 156 case 'L': 157 i = ls; 158 break; 159 case 'R': 160 i = NN - regcnt; 161 break; 162 case 'z': 163 i = dip->curd; 164 *pbp++ = (i >> BYTE) & BYTEMASK; 165 *pbp++ = i & BYTEMASK; 166 return (0); 167 case 'b': 168 i = bdtab[font]; 169 break; 170 case 'F': 171 cpushback(cfname[ifi]); 172 return (0); 173 174 default: 175 goto s0; 176 } 177 else { 178 s0: 179 if ((j = findr(i)) == -1) 180 i = 0; 181 else { 182 i = numtab[j].val = (numtab[j].val+numtab[j].inc*f); 183 nform = numtab[j].fmt; 184 } 185 } 186 setn1(i, nform, (tchar) 0); 187 188 return (0); 189 } 190 191 tchar numbuf[17]; 192 tchar *numbufp; 193 194 int 195 wrc(i) 196 tchar i; 197 { 198 if (numbufp >= &numbuf[16]) 199 return(0); 200 *numbufp++ = i; 201 return(1); 202 } 203 204 205 206 /* insert into input number i, in format form, with size-font bits bits */ 207 int 208 setn1(i, form, bits) 209 int i; 210 tchar bits; 211 { 212 extern int wrc(); 213 214 numbufp = numbuf; 215 nrbits = bits; 216 nform = form; 217 fnumb(i, wrc); 218 *numbufp = 0; 219 pushback(numbuf); 220 221 return (0); 222 } 223 224 225 int 226 nrehash() 227 { 228 struct numtab *p; 229 int i; 230 231 for (i=0; i<128; i++) 232 nhash[i] = 0; 233 for (p=numtab; p < &numtab[NN]; p++) 234 p->link = 0; 235 for (p=numtab; p < &numtab[NN]; p++) { 236 if (p->r == 0) 237 continue; 238 i = NHASH(p->r); 239 p->link = nhash[i]; 240 nhash[i] = p; 241 } 242 243 return (0); 244 } 245 246 int 247 nunhash(rp) 248 struct numtab *rp; 249 { 250 struct numtab *p; 251 struct numtab **lp; 252 253 if (rp->r == 0) 254 return (0); 255 lp = &nhash[NHASH(rp->r)]; 256 p = *lp; 257 while (p) { 258 if (p == rp) { 259 *lp = p->link; 260 p->link = 0; 261 return (0); 262 } 263 lp = &p->link; 264 p = p->link; 265 } 266 return (0); 267 } 268 269 int 270 findr(i) 271 int i; 272 { 273 struct numtab *p; 274 int h = NHASH(i); 275 276 if (i == 0) 277 return(-1); 278 for (p = nhash[h]; p; p = p->link) 279 if (i == p->r) 280 return(p - numtab); 281 for (p = numtab; p < &numtab[NN]; p++) { 282 if (p->r == 0) { 283 p->r = i; 284 p->link = nhash[h]; 285 nhash[h] = p; 286 regcnt++; 287 return(p - numtab); 288 } 289 } 290 errprint(gettext("too many number registers (%d)."), NN); 291 done2(04); 292 /* NOTREACHED */ 293 294 return (0); 295 } 296 297 int 298 usedr(i) /* returns -1 if nr i has never been used */ 299 int i; 300 { 301 struct numtab *p; 302 303 if (i == 0) 304 return(-1); 305 for (p = nhash[NHASH(i)]; p; p = p->link) 306 if (i == p->r) 307 return(p - numtab); 308 return -1; 309 } 310 311 312 int 313 fnumb(i, f) 314 int i, (*f)(); 315 { 316 int j; 317 318 j = 0; 319 if (i < 0) { 320 j = (*f)('-' | nrbits); 321 i = -i; 322 } 323 switch (nform) { 324 default: 325 case '1': 326 case 0: 327 return decml(i, f) + j; 328 break; 329 case 'i': 330 case 'I': 331 return roman(i, f) + j; 332 break; 333 case 'a': 334 case 'A': 335 return abc(i, f) + j; 336 break; 337 } 338 339 return (0); 340 } 341 342 343 int 344 decml(i, f) 345 int i, (*f)(); 346 { 347 int j, k; 348 349 k = 0; 350 nform--; 351 if ((j = i / 10) || (nform > 0)) 352 k = decml(j, f); 353 return(k + (*f)((i % 10 + '0') | nrbits)); 354 } 355 356 357 int 358 roman(i, f) 359 int i, (*f)(); 360 { 361 362 if (!i) 363 return((*f)('0' | nrbits)); 364 if (nform == 'i') 365 return(roman0(i, f, "ixcmz", "vldw")); 366 else 367 return(roman0(i, f, "IXCMZ", "VLDW")); 368 } 369 370 371 int 372 roman0(i, f, onesp, fivesp) 373 int i, (*f)(); 374 char *onesp, *fivesp; 375 { 376 int q, rem, k; 377 378 k = 0; 379 if (!i) 380 return(0); 381 k = roman0(i / 10, f, onesp + 1, fivesp + 1); 382 q = (i = i % 10) / 5; 383 rem = i % 5; 384 if (rem == 4) { 385 k += (*f)(*onesp | nrbits); 386 if (q) 387 i = *(onesp + 1); 388 else 389 i = *fivesp; 390 return(k += (*f)(i | nrbits)); 391 } 392 if (q) 393 k += (*f)(*fivesp | nrbits); 394 while (--rem >= 0) 395 k += (*f)(*onesp | nrbits); 396 return(k); 397 } 398 399 400 int 401 abc(i, f) 402 int i, (*f)(); 403 { 404 if (!i) 405 return((*f)('0' | nrbits)); 406 else 407 return(abc0(i - 1, f)); 408 } 409 410 411 int 412 abc0(i, f) 413 int i, (*f)(); 414 { 415 int j, k; 416 417 k = 0; 418 if (j = i / 26) 419 k = abc0(j - 1, f); 420 return(k + (*f)((i % 26 + nform) | nrbits)); 421 } 422 423 long atoi0() 424 { 425 int c, k, cnt; 426 tchar ii; 427 long i, acc; 428 extern long ckph(); 429 430 i = 0; 431 acc = 0; 432 nonumb = 0; 433 cnt = -1; 434 a0: 435 cnt++; 436 ii = getch(); 437 c = cbits(ii); 438 switch (c) { 439 default: 440 ch = ii; 441 if (cnt) 442 break; 443 case '+': 444 i = ckph(); 445 if (nonumb) 446 break; 447 acc += i; 448 goto a0; 449 case '-': 450 i = ckph(); 451 if (nonumb) 452 break; 453 acc -= i; 454 goto a0; 455 case '*': 456 i = ckph(); 457 if (nonumb) 458 break; 459 acc *= i; 460 goto a0; 461 case '/': 462 i = ckph(); 463 if (nonumb) 464 break; 465 if (i == 0) { 466 flusho(); 467 errprint(gettext("divide by zero.")); 468 acc = 0; 469 } else 470 acc /= i; 471 goto a0; 472 case '%': 473 i = ckph(); 474 if (nonumb) 475 break; 476 acc %= i; 477 goto a0; 478 case '&': /*and*/ 479 i = ckph(); 480 if (nonumb) 481 break; 482 if ((acc > 0) && (i > 0)) 483 acc = 1; 484 else 485 acc = 0; 486 goto a0; 487 case ':': /*or*/ 488 i = ckph(); 489 if (nonumb) 490 break; 491 if ((acc > 0) || (i > 0)) 492 acc = 1; 493 else 494 acc = 0; 495 goto a0; 496 case '=': 497 if (cbits(ii = getch()) != '=') 498 ch = ii; 499 i = ckph(); 500 if (nonumb) { 501 acc = 0; 502 break; 503 } 504 if (i == acc) 505 acc = 1; 506 else 507 acc = 0; 508 goto a0; 509 case '>': 510 k = 0; 511 if (cbits(ii = getch()) == '=') 512 k++; 513 else 514 ch = ii; 515 i = ckph(); 516 if (nonumb) { 517 acc = 0; 518 break; 519 } 520 if (acc > (i - k)) 521 acc = 1; 522 else 523 acc = 0; 524 goto a0; 525 case '<': 526 k = 0; 527 if (cbits(ii = getch()) == '=') 528 k++; 529 else 530 ch = ii; 531 i = ckph(); 532 if (nonumb) { 533 acc = 0; 534 break; 535 } 536 if (acc < (i + k)) 537 acc = 1; 538 else 539 acc = 0; 540 goto a0; 541 case ')': 542 break; 543 case '(': 544 acc = atoi0(); 545 goto a0; 546 } 547 return(acc); 548 } 549 550 551 long ckph() 552 { 553 tchar i; 554 long j; 555 extern long atoi0(); 556 extern long atoi1(); 557 558 if (cbits(i = getch()) == '(') 559 j = atoi0(); 560 else { 561 j = atoi1(i); 562 } 563 return(j); 564 } 565 566 567 long atoi1(ii) 568 tchar ii; 569 { 570 int i, j, digits; 571 long acc; 572 int neg, abs, field; 573 574 neg = abs = field = digits = 0; 575 acc = 0; 576 for (;;) { 577 i = cbits(ii); 578 switch (i) { 579 default: 580 break; 581 case '+': 582 ii = getch(); 583 continue; 584 case '-': 585 neg = 1; 586 ii = getch(); 587 continue; 588 case '|': 589 abs = 1 + neg; 590 neg = 0; 591 ii = getch(); 592 continue; 593 } 594 break; 595 } 596 a1: 597 while (i >= '0' && i <= '9') { 598 field++; 599 digits++; 600 acc = 10 * acc + i - '0'; 601 ii = getch(); 602 i = cbits(ii); 603 } 604 if (i == '.') { 605 field++; 606 digits = 0; 607 ii = getch(); 608 i = cbits(ii); 609 goto a1; 610 } 611 if (!field) { 612 ch = ii; 613 goto a2; 614 } 615 switch (i) { 616 case 'u': 617 i = j = 1; /* should this be related to HOR?? */ 618 break; 619 case 'v': /*VSs - vert spacing*/ 620 j = lss; 621 i = 1; 622 break; 623 case 'm': /*Ems*/ 624 j = EM; 625 i = 1; 626 break; 627 case 'n': /*Ens*/ 628 j = EM; 629 #ifndef NROFF 630 i = 2; 631 #endif 632 #ifdef NROFF 633 i = 1; /*Same as Ems in NROFF*/ 634 #endif 635 break; 636 case 'p': /*Points*/ 637 j = INCH; 638 i = 72; 639 break; 640 case 'i': /*Inches*/ 641 j = INCH; 642 i = 1; 643 break; 644 case 'c': /*Centimeters*/ 645 /* if INCH is too big, this will overflow */ 646 j = INCH * 50; 647 i = 127; 648 break; 649 case 'P': /*Picas*/ 650 j = INCH; 651 i = 6; 652 break; 653 default: 654 j = dfact; 655 ch = ii; 656 i = dfactd; 657 } 658 if (neg) 659 acc = -acc; 660 if (!noscale) { 661 acc = (acc * j) / i; 662 } 663 if ((field != digits) && (digits > 0)) 664 while (digits--) 665 acc /= 10; 666 if (abs) { 667 if (dip != d) 668 j = dip->dnl; 669 else 670 j = numtab[NL].val; 671 if (!vflag) { 672 j = numtab[HP].val; 673 } 674 if (abs == 2) 675 j = -j; 676 acc -= j; 677 } 678 a2: 679 nonumb = !field; 680 return(acc); 681 } 682 683 684 int 685 caserr() 686 { 687 int i, j; 688 struct numtab *p; 689 690 lgf++; 691 while (!skip() && (i = getrq()) ) { 692 j = usedr(i); 693 if (j < 0) 694 continue; 695 p = &numtab[j]; 696 nunhash(p); 697 p->r = p->val = p->inc = p->fmt = 0; 698 regcnt--; 699 } 700 701 return (0); 702 } 703 704 705 int 706 casenr() 707 { 708 int i, j; 709 710 lgf++; 711 skip(); 712 if ((i = findr(getrq())) == -1) 713 goto rtn; 714 skip(); 715 j = inumb(&numtab[i].val); 716 if (nonumb) 717 goto rtn; 718 numtab[i].val = j; 719 skip(); 720 j = atoi(); 721 if (nonumb) 722 goto rtn; 723 numtab[i].inc = j; 724 rtn: 725 return (0); 726 } 727 728 729 int 730 caseaf() 731 { 732 int i, k; 733 tchar j, jj; 734 735 lgf++; 736 if (skip() || !(i = getrq()) || skip()) 737 return (0); 738 k = 0; 739 j = getch(); 740 if (!ischar(jj = cbits(j)) || !isalpha(jj)) { 741 ch = j; 742 while ((j = cbits(getch())) >= '0' && j <= '9') 743 k++; 744 } 745 if (!k) 746 k = j; 747 numtab[findr(i)].fmt = k & BYTEMASK; 748 749 return (0); 750 } 751 752 int 753 setaf() /* return format of number register */ 754 { 755 int i, j; 756 757 i = usedr(getsn()); 758 if (i == -1) 759 return (0); 760 if (numtab[i].fmt > 20) /* it was probably a, A, i or I */ 761 *pbp++ = numtab[i].fmt; 762 else 763 for (j = (numtab[i].fmt ? numtab[i].fmt : 1); j; j--) 764 *pbp++ = '0'; 765 766 return (0); 767 } 768 769 770 int 771 vnumb(i) 772 int *i; 773 { 774 vflag++; 775 dfact = lss; 776 res = VERT; 777 return(inumb(i)); 778 } 779 780 781 int 782 hnumb(i) 783 int *i; 784 { 785 dfact = EM; 786 res = HOR; 787 return(inumb(i)); 788 } 789 790 791 int 792 inumb(n) 793 int *n; 794 { 795 int i, j, f; 796 tchar ii; 797 798 f = 0; 799 if (n) { 800 if ((j = cbits(ii = getch())) == '+') 801 f = 1; 802 else if (j == '-') 803 f = -1; 804 else 805 ch = ii; 806 } 807 i = atoi(); 808 if (n && f) 809 i = *n + f * i; 810 i = quant(i, res); 811 vflag = 0; 812 res = dfactd = dfact = 1; 813 if (nonumb) 814 i = 0; 815 return(i); 816 } 817 818 819 int 820 quant(n, m) 821 int n, m; 822 { 823 int i, neg; 824 825 neg = 0; 826 if (n < 0) { 827 neg++; 828 n = -n; 829 } 830 /* better as i = ((n + (m/2))/m)*m */ 831 i = n / m; 832 if ((n - m * i) > (m / 2)) 833 i += 1; 834 i *= m; 835 if (neg) 836 i = -i; 837 return(i); 838 } 839 840 841