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