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(int i, int form, tchar bits) 209 { 210 extern int wrc(); 211 212 numbufp = numbuf; 213 nrbits = bits; 214 nform = form; 215 fnumb(i, wrc); 216 *numbufp = 0; 217 pushback(numbuf); 218 219 return (0); 220 } 221 222 223 int 224 nrehash() 225 { 226 struct numtab *p; 227 int i; 228 229 for (i=0; i<128; i++) 230 nhash[i] = 0; 231 for (p=numtab; p < &numtab[NN]; p++) 232 p->link = 0; 233 for (p=numtab; p < &numtab[NN]; p++) { 234 if (p->r == 0) 235 continue; 236 i = NHASH(p->r); 237 p->link = nhash[i]; 238 nhash[i] = p; 239 } 240 241 return (0); 242 } 243 244 int 245 nunhash(rp) 246 struct numtab *rp; 247 { 248 struct numtab *p; 249 struct numtab **lp; 250 251 if (rp->r == 0) 252 return (0); 253 lp = &nhash[NHASH(rp->r)]; 254 p = *lp; 255 while (p) { 256 if (p == rp) { 257 *lp = p->link; 258 p->link = 0; 259 return (0); 260 } 261 lp = &p->link; 262 p = p->link; 263 } 264 return (0); 265 } 266 267 int 268 findr(i) 269 int i; 270 { 271 struct numtab *p; 272 int h = NHASH(i); 273 274 if (i == 0) 275 return(-1); 276 for (p = nhash[h]; p; p = p->link) 277 if (i == p->r) 278 return(p - numtab); 279 for (p = numtab; p < &numtab[NN]; p++) { 280 if (p->r == 0) { 281 p->r = i; 282 p->link = nhash[h]; 283 nhash[h] = p; 284 regcnt++; 285 return(p - numtab); 286 } 287 } 288 errprint(gettext("too many number registers (%d)."), NN); 289 done2(04); 290 /* NOTREACHED */ 291 292 return (0); 293 } 294 295 int 296 usedr(i) /* returns -1 if nr i has never been used */ 297 int i; 298 { 299 struct numtab *p; 300 301 if (i == 0) 302 return(-1); 303 for (p = nhash[NHASH(i)]; p; p = p->link) 304 if (i == p->r) 305 return(p - numtab); 306 return -1; 307 } 308 309 310 int 311 fnumb(i, f) 312 int i, (*f)(); 313 { 314 int j; 315 316 j = 0; 317 if (i < 0) { 318 j = (*f)('-' | nrbits); 319 i = -i; 320 } 321 switch (nform) { 322 default: 323 case '1': 324 case 0: 325 return decml(i, f) + j; 326 break; 327 case 'i': 328 case 'I': 329 return roman(i, f) + j; 330 break; 331 case 'a': 332 case 'A': 333 return abc(i, f) + j; 334 break; 335 } 336 337 return (0); 338 } 339 340 341 int 342 decml(i, f) 343 int i, (*f)(); 344 { 345 int j, k; 346 347 k = 0; 348 nform--; 349 if ((j = i / 10) || (nform > 0)) 350 k = decml(j, f); 351 return(k + (*f)((i % 10 + '0') | nrbits)); 352 } 353 354 355 int 356 roman(i, f) 357 int i, (*f)(); 358 { 359 360 if (!i) 361 return((*f)('0' | nrbits)); 362 if (nform == 'i') 363 return(roman0(i, f, "ixcmz", "vldw")); 364 else 365 return(roman0(i, f, "IXCMZ", "VLDW")); 366 } 367 368 369 int 370 roman0(i, f, onesp, fivesp) 371 int i, (*f)(); 372 char *onesp, *fivesp; 373 { 374 int q, rem, k; 375 376 k = 0; 377 if (!i) 378 return(0); 379 k = roman0(i / 10, f, onesp + 1, fivesp + 1); 380 q = (i = i % 10) / 5; 381 rem = i % 5; 382 if (rem == 4) { 383 k += (*f)(*onesp | nrbits); 384 if (q) 385 i = *(onesp + 1); 386 else 387 i = *fivesp; 388 return(k += (*f)(i | nrbits)); 389 } 390 if (q) 391 k += (*f)(*fivesp | nrbits); 392 while (--rem >= 0) 393 k += (*f)(*onesp | nrbits); 394 return(k); 395 } 396 397 398 int 399 abc(i, f) 400 int i, (*f)(); 401 { 402 if (!i) 403 return((*f)('0' | nrbits)); 404 else 405 return(abc0(i - 1, f)); 406 } 407 408 409 int 410 abc0(i, f) 411 int i, (*f)(); 412 { 413 int j, k; 414 415 k = 0; 416 if (j = i / 26) 417 k = abc0(j - 1, f); 418 return(k + (*f)((i % 26 + nform) | nrbits)); 419 } 420 421 long atoi0() 422 { 423 int c, k, cnt; 424 tchar ii; 425 long i, acc; 426 extern long ckph(); 427 428 i = 0; 429 acc = 0; 430 nonumb = 0; 431 cnt = -1; 432 a0: 433 cnt++; 434 ii = getch(); 435 c = cbits(ii); 436 switch (c) { 437 default: 438 ch = ii; 439 if (cnt) 440 break; 441 case '+': 442 i = ckph(); 443 if (nonumb) 444 break; 445 acc += i; 446 goto a0; 447 case '-': 448 i = ckph(); 449 if (nonumb) 450 break; 451 acc -= i; 452 goto a0; 453 case '*': 454 i = ckph(); 455 if (nonumb) 456 break; 457 acc *= i; 458 goto a0; 459 case '/': 460 i = ckph(); 461 if (nonumb) 462 break; 463 if (i == 0) { 464 flusho(); 465 errprint(gettext("divide by zero.")); 466 acc = 0; 467 } else 468 acc /= i; 469 goto a0; 470 case '%': 471 i = ckph(); 472 if (nonumb) 473 break; 474 acc %= i; 475 goto a0; 476 case '&': /*and*/ 477 i = ckph(); 478 if (nonumb) 479 break; 480 if ((acc > 0) && (i > 0)) 481 acc = 1; 482 else 483 acc = 0; 484 goto a0; 485 case ':': /*or*/ 486 i = ckph(); 487 if (nonumb) 488 break; 489 if ((acc > 0) || (i > 0)) 490 acc = 1; 491 else 492 acc = 0; 493 goto a0; 494 case '=': 495 if (cbits(ii = getch()) != '=') 496 ch = ii; 497 i = ckph(); 498 if (nonumb) { 499 acc = 0; 500 break; 501 } 502 if (i == acc) 503 acc = 1; 504 else 505 acc = 0; 506 goto a0; 507 case '>': 508 k = 0; 509 if (cbits(ii = getch()) == '=') 510 k++; 511 else 512 ch = ii; 513 i = ckph(); 514 if (nonumb) { 515 acc = 0; 516 break; 517 } 518 if (acc > (i - k)) 519 acc = 1; 520 else 521 acc = 0; 522 goto a0; 523 case '<': 524 k = 0; 525 if (cbits(ii = getch()) == '=') 526 k++; 527 else 528 ch = ii; 529 i = ckph(); 530 if (nonumb) { 531 acc = 0; 532 break; 533 } 534 if (acc < (i + k)) 535 acc = 1; 536 else 537 acc = 0; 538 goto a0; 539 case ')': 540 break; 541 case '(': 542 acc = atoi0(); 543 goto a0; 544 } 545 return(acc); 546 } 547 548 549 long ckph() 550 { 551 tchar i; 552 long j; 553 extern long atoi0(); 554 extern long atoi1(); 555 556 if (cbits(i = getch()) == '(') 557 j = atoi0(); 558 else { 559 j = atoi1(i); 560 } 561 return(j); 562 } 563 564 565 long atoi1(ii) 566 tchar ii; 567 { 568 int i, j, digits; 569 long acc; 570 int neg, abs, field; 571 572 neg = abs = field = digits = 0; 573 acc = 0; 574 for (;;) { 575 i = cbits(ii); 576 switch (i) { 577 default: 578 break; 579 case '+': 580 ii = getch(); 581 continue; 582 case '-': 583 neg = 1; 584 ii = getch(); 585 continue; 586 case '|': 587 abs = 1 + neg; 588 neg = 0; 589 ii = getch(); 590 continue; 591 } 592 break; 593 } 594 a1: 595 while (i >= '0' && i <= '9') { 596 field++; 597 digits++; 598 acc = 10 * acc + i - '0'; 599 ii = getch(); 600 i = cbits(ii); 601 } 602 if (i == '.') { 603 field++; 604 digits = 0; 605 ii = getch(); 606 i = cbits(ii); 607 goto a1; 608 } 609 if (!field) { 610 ch = ii; 611 goto a2; 612 } 613 switch (i) { 614 case 'u': 615 i = j = 1; /* should this be related to HOR?? */ 616 break; 617 case 'v': /*VSs - vert spacing*/ 618 j = lss; 619 i = 1; 620 break; 621 case 'm': /*Ems*/ 622 j = EM; 623 i = 1; 624 break; 625 case 'n': /*Ens*/ 626 j = EM; 627 #ifndef NROFF 628 i = 2; 629 #endif 630 #ifdef NROFF 631 i = 1; /*Same as Ems in NROFF*/ 632 #endif 633 break; 634 case 'p': /*Points*/ 635 j = INCH; 636 i = 72; 637 break; 638 case 'i': /*Inches*/ 639 j = INCH; 640 i = 1; 641 break; 642 case 'c': /*Centimeters*/ 643 /* if INCH is too big, this will overflow */ 644 j = INCH * 50; 645 i = 127; 646 break; 647 case 'P': /*Picas*/ 648 j = INCH; 649 i = 6; 650 break; 651 default: 652 j = dfact; 653 ch = ii; 654 i = dfactd; 655 } 656 if (neg) 657 acc = -acc; 658 if (!noscale) { 659 acc = (acc * j) / i; 660 } 661 if ((field != digits) && (digits > 0)) 662 while (digits--) 663 acc /= 10; 664 if (abs) { 665 if (dip != d) 666 j = dip->dnl; 667 else 668 j = numtab[NL].val; 669 if (!vflag) { 670 j = numtab[HP].val; 671 } 672 if (abs == 2) 673 j = -j; 674 acc -= j; 675 } 676 a2: 677 nonumb = !field; 678 return(acc); 679 } 680 681 682 int 683 caserr() 684 { 685 int i, j; 686 struct numtab *p; 687 688 lgf++; 689 while (!skip() && (i = getrq()) ) { 690 j = usedr(i); 691 if (j < 0) 692 continue; 693 p = &numtab[j]; 694 nunhash(p); 695 p->r = p->val = p->inc = p->fmt = 0; 696 regcnt--; 697 } 698 699 return (0); 700 } 701 702 703 int 704 casenr() 705 { 706 int i, j; 707 708 lgf++; 709 skip(); 710 if ((i = findr(getrq())) == -1) 711 goto rtn; 712 skip(); 713 j = inumb(&numtab[i].val); 714 if (nonumb) 715 goto rtn; 716 numtab[i].val = j; 717 skip(); 718 j = atoi(); 719 if (nonumb) 720 goto rtn; 721 numtab[i].inc = j; 722 rtn: 723 return (0); 724 } 725 726 727 int 728 caseaf() 729 { 730 int i, k; 731 tchar j, jj; 732 733 lgf++; 734 if (skip() || !(i = getrq()) || skip()) 735 return (0); 736 k = 0; 737 j = getch(); 738 if (!ischar(jj = cbits(j)) || !isalpha(jj)) { 739 ch = j; 740 while ((j = cbits(getch())) >= '0' && j <= '9') 741 k++; 742 } 743 if (!k) 744 k = j; 745 numtab[findr(i)].fmt = k & BYTEMASK; 746 747 return (0); 748 } 749 750 int 751 setaf() /* return format of number register */ 752 { 753 int i, j; 754 755 i = usedr(getsn()); 756 if (i == -1) 757 return (0); 758 if (numtab[i].fmt > 20) /* it was probably a, A, i or I */ 759 *pbp++ = numtab[i].fmt; 760 else 761 for (j = (numtab[i].fmt ? numtab[i].fmt : 1); j; j--) 762 *pbp++ = '0'; 763 764 return (0); 765 } 766 767 768 int 769 vnumb(i) 770 int *i; 771 { 772 vflag++; 773 dfact = lss; 774 res = VERT; 775 return(inumb(i)); 776 } 777 778 779 int 780 hnumb(i) 781 int *i; 782 { 783 dfact = EM; 784 res = HOR; 785 return(inumb(i)); 786 } 787 788 789 int 790 inumb(n) 791 int *n; 792 { 793 int i, j, f; 794 tchar ii; 795 796 f = 0; 797 if (n) { 798 if ((j = cbits(ii = getch())) == '+') 799 f = 1; 800 else if (j == '-') 801 f = -1; 802 else 803 ch = ii; 804 } 805 i = atoi(); 806 if (n && f) 807 i = *n + f * i; 808 i = quant(i, res); 809 vflag = 0; 810 res = dfactd = dfact = 1; 811 if (nonumb) 812 i = 0; 813 return(i); 814 } 815 816 817 int 818 quant(n, m) 819 int n, m; 820 { 821 int i, neg; 822 823 neg = 0; 824 if (n < 0) { 825 neg++; 826 n = -n; 827 } 828 /* better as i = ((n + (m/2))/m)*m */ 829 i = n / m; 830 if ((n - m * i) > (m / 2)) 831 i += 1; 832 i *= m; 833 if (neg) 834 i = -i; 835 return(i); 836 } 837 838 839