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