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