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