1 #include <ctype.h> 2 #include "tdef.h" 3 extern 4 #include "d.h" 5 extern 6 #include "v.h" 7 #ifdef NROFF 8 extern 9 #include "tw.h" 10 #endif 11 #include "s.h" 12 /* 13 troff4.c 14 15 number registers, conversion, arithmetic 16 */ 17 18 #include <sgtty.h> 19 #include "ext.h" 20 21 int regcnt = NNAMES; 22 int falsef = 0; /* on if inside false branch of if */ 23 24 setn() 25 { 26 register i, j; 27 tchar ii; 28 int f; 29 30 f = nform = 0; 31 lgf++; /* don't catch ligatures */ 32 if ((i = cbits(ii = getch())) == '+') 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 = v.cd; 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 = v.nl; 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 = width(*(pinchar-1)); /* XXX */ 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 cbuf[0] = i & BMASK; 132 cbuf[1] = (i >> BYTE) & BMASK; 133 cbuf[2] = 0; 134 cp = cbuf; 135 return; 136 case 'b': 137 i = bdtab[font]; 138 break; 139 140 default: 141 goto s0; 142 } 143 else { 144 s0: 145 if ((j = findr(i)) == -1) 146 i = 0; 147 else { 148 i = (vlist[j] = (vlist[j] + inc[j] * f)); 149 nform = fmt[j]; 150 } 151 } 152 setn1(i); 153 cp = cbuf; 154 } 155 156 157 setn1(i) 158 int i; 159 { 160 extern int wrc(); 161 162 cp = cbuf; 163 nrbits = 0; 164 fnumb(i, wrc); 165 *cp = 0; 166 cp = cbuf; 167 } 168 169 170 findr(i) 171 register int i; 172 { 173 register j; 174 register int *p; 175 176 if (i == 0) 177 return(-1); 178 for (p = r; p < &r[NN]; p++) { 179 if (i == *p) 180 break; 181 } 182 if (p != &r[NN]) 183 return(p - r); 184 for (p = r; p < &r[NN]; p++) { 185 if (*p == 0) { 186 *p = i; 187 regcnt++; 188 break; 189 } 190 } 191 if (p == &r[NN]) { 192 fprintf(stderr, "troff: too many number registers (%d).\n", NN); 193 done2(04); 194 } 195 return(p - r); 196 } 197 198 usedr(i) /* returns -1 if nr i has never been used */ 199 register int i; 200 { 201 register j; 202 register int *p; 203 204 if (i == 0) 205 return(-1); 206 for (p = r; p < &r[NN]; p++) { 207 if (i == *p) 208 break; 209 } 210 if (p != &r[NN]) 211 return(p - r); 212 else 213 return -1; 214 } 215 216 217 fnumb(i, f) 218 int i, (*f)(); 219 { 220 register j; 221 222 j = 0; 223 if (i < 0) { 224 j = (*f)('-' | nrbits); 225 i = -i; 226 } 227 switch (nform) { 228 default: 229 case '1': 230 case 0: 231 return(decml(i, f) + j); 232 case 'i': 233 case 'I': 234 return(roman(i, f) + j); 235 case 'a': 236 case 'A': 237 return(abc(i, f) + j); 238 } 239 } 240 241 242 decml(i, f) 243 int i, (*f)(); 244 { 245 register j, k; 246 247 k = 0; 248 nform--; 249 if ((j = i / 10) || (nform > 0)) 250 k = decml(j, f); 251 return(k + (*f)((i % 10 + '0') | nrbits)); 252 } 253 254 255 roman(i, f) 256 int i, (*f)(); 257 { 258 259 if (!i) 260 return((*f)('0' | nrbits)); 261 if (nform == 'i') 262 return(roman0(i, f, "ixcmz", "vldw")); 263 else 264 return(roman0(i, f, "IXCMZ", "VLDW")); 265 } 266 267 268 roman0(i, f, onesp, fivesp) 269 int i, (*f)(); 270 char *onesp, *fivesp; 271 { 272 register q, rem, k; 273 274 k = 0; 275 if (!i) 276 return(0); 277 k = roman0(i / 10, f, onesp + 1, fivesp + 1); 278 q = (i = i % 10) / 5; 279 rem = i % 5; 280 if (rem == 4) { 281 k += (*f)(*onesp | nrbits); 282 if (q) 283 i = *(onesp + 1); 284 else 285 i = *fivesp; 286 return(k += (*f)(i | nrbits)); 287 } 288 if (q) 289 k += (*f)(*fivesp | nrbits); 290 while (--rem >= 0) 291 k += (*f)(*onesp | nrbits); 292 return(k); 293 } 294 295 296 abc(i, f) 297 int i, (*f)(); 298 { 299 if (!i) 300 return((*f)('0' | nrbits)); 301 else 302 return(abc0(i - 1, f)); 303 } 304 305 306 abc0(i, f) 307 int i, (*f)(); 308 { 309 register j, k; 310 311 k = 0; 312 if (j = i / 26) 313 k = abc0(j - 1, f); 314 return(k + (*f)((i % 26 + nform) | nrbits)); 315 } 316 317 318 wrc(i) 319 tchar i; 320 { 321 if (cp >= &cbuf[NC]) 322 return(0); 323 *cp++ = i; 324 return(1); 325 } 326 327 328 long atoi0() 329 { 330 register c, k, cnt; 331 tchar ii; 332 long i, acc; 333 extern long ckph(); 334 335 i = 0; 336 acc = 0; 337 nonumb = 0; 338 cnt = -1; 339 a0: 340 cnt++; 341 ii = getch(); 342 c = cbits(ii); 343 switch (c) { 344 default: 345 ch = ii; 346 if (cnt) 347 break; 348 case '+': 349 i = ckph(); 350 if (nonumb) 351 break; 352 acc += i; 353 goto a0; 354 case '-': 355 i = ckph(); 356 if (nonumb) 357 break; 358 acc -= i; 359 goto a0; 360 case '*': 361 i = ckph(); 362 if (nonumb) 363 break; 364 acc *= i; 365 goto a0; 366 case '/': 367 i = ckph(); 368 if (nonumb) 369 break; 370 if (i == 0) { 371 flusho(); 372 fprintf(stderr, "troff: divide by zero.\n"); 373 acc = 0; 374 } else 375 acc /= i; 376 goto a0; 377 case '%': 378 i = ckph(); 379 if (nonumb) 380 break; 381 acc %= i; 382 goto a0; 383 case '&': /*and*/ 384 i = ckph(); 385 if (nonumb) 386 break; 387 if ((acc > 0) && (i > 0)) 388 acc = 1; 389 else 390 acc = 0; 391 goto a0; 392 case ':': /*or*/ 393 i = ckph(); 394 if (nonumb) 395 break; 396 if ((acc > 0) || (i > 0)) 397 acc = 1; 398 else 399 acc = 0; 400 goto a0; 401 case '=': 402 if (cbits(ii = getch()) != '=') 403 ch = ii; 404 i = ckph(); 405 if (nonumb) { 406 acc = 0; 407 break; 408 } 409 if (i == acc) 410 acc = 1; 411 else 412 acc = 0; 413 goto a0; 414 case '>': 415 k = 0; 416 if (cbits(ii = getch()) == '=') 417 k++; 418 else 419 ch = ii; 420 i = ckph(); 421 if (nonumb) { 422 acc = 0; 423 break; 424 } 425 if (acc > (i - k)) 426 acc = 1; 427 else 428 acc = 0; 429 goto a0; 430 case '<': 431 k = 0; 432 if (cbits(ii = getch()) == '=') 433 k++; 434 else 435 ch = ii; 436 i = ckph(); 437 if (nonumb) { 438 acc = 0; 439 break; 440 } 441 if (acc < (i + k)) 442 acc = 1; 443 else 444 acc = 0; 445 goto a0; 446 case ')': 447 break; 448 case '(': 449 acc = atoi0(); 450 goto a0; 451 } 452 return(acc); 453 } 454 455 456 long ckph() 457 { 458 tchar i; 459 long j; 460 extern long atoi0(); 461 extern long atoi1(); 462 463 if (cbits(i = getch()) == '(') 464 j = atoi0(); 465 else { 466 ch = i; 467 j = atoi1(); 468 } 469 return(j); 470 } 471 472 473 long atoi1() 474 { 475 register i, j, digits; 476 tchar ii; 477 long acc; 478 int neg, abs, field; 479 480 neg = abs = field = digits = 0; 481 acc = 0; 482 a0: 483 ii = getch(); 484 i = cbits(ii); 485 switch (i) { 486 default: 487 ch = ii; 488 break; 489 case '+': 490 goto a0; 491 case '-': 492 neg = 1; 493 goto a0; 494 case '|': 495 abs = 1 + neg; 496 neg = 0; 497 goto a0; 498 } 499 a1: 500 while (((j = (cbits(ii = getch())) - '0') >= 0) && (j <= 9)) { 501 field++; 502 digits++; 503 acc = 10 * acc + j; 504 } 505 if (cbits(ii) == '.') { 506 field++; 507 digits = 0; 508 goto a1; 509 } 510 ch = ii; 511 if (!field) 512 goto a2; 513 ii = getch(); 514 switch (i = cbits(ii)) { 515 case 'u': 516 i = j = 1; /* should this be related to HOR?? */ 517 break; 518 case 'v': /*VSs - vert spacing*/ 519 j = lss; 520 i = 1; 521 break; 522 case 'm': /*Ems*/ 523 j = EM; 524 i = 1; 525 break; 526 case 'n': /*Ens*/ 527 j = EM; 528 #ifndef NROFF 529 i = 2; 530 #endif 531 #ifdef NROFF 532 i = 1; /*Same as Ems in NROFF*/ 533 #endif 534 break; 535 case 'p': /*Points*/ 536 j = INCH; 537 i = 72; 538 break; 539 case 'i': /*Inches*/ 540 j = INCH; 541 i = 1; 542 break; 543 case 'c': /*Centimeters*/ 544 /* if INCH is too big, this will overflow */ 545 j = INCH * 50; 546 i = 127; 547 break; 548 case 'P': /*Picas*/ 549 j = INCH; 550 i = 6; 551 break; 552 default: 553 j = dfact; 554 ch = ii; 555 i = dfactd; 556 } 557 if (neg) 558 acc = -acc; 559 if (!noscale) { 560 acc = (acc * j) / i; 561 } 562 if ((field != digits) && (digits > 0)) 563 while (digits--) 564 acc /= 10; 565 if (abs) { 566 if (dip != d) 567 j = dip->dnl; 568 else 569 j = v.nl; 570 if (!vflag) { 571 j = v.hp = sumhp(); /* XXX */ 572 } 573 if (abs == 2) 574 j = -j; 575 acc -= j; 576 } 577 a2: 578 nonumb = !field; 579 return(acc); 580 } 581 582 583 caserr() 584 { 585 register i, j; 586 587 lgf++; 588 while (!skip() && (i = getrq()) ) { 589 for (j = NNAMES; j < NN; j++) { /*NNAMES predefined names*/ 590 if (i == r[j]) 591 break; 592 } 593 if (j != NN) { 594 r[j] = vlist[j] = inc[j] = fmt[j] = 0; 595 regcnt--; 596 } 597 } 598 } 599 600 601 casenr() 602 { 603 register i, j; 604 605 lgf++; 606 skip(); 607 if ((i = findr(getrq())) == -1) 608 goto rtn; 609 skip(); 610 j = inumb(&vlist[i]); 611 if (nonumb) 612 goto rtn; 613 vlist[i] = j; 614 skip(); 615 j = atoi(); 616 if (nonumb) 617 goto rtn; 618 inc[i] = j; 619 rtn: 620 return; 621 } 622 623 624 caseaf() 625 { 626 register i, k; 627 tchar j; 628 629 lgf++; 630 if (skip() || !(i = getrq()) || skip()) 631 return; 632 k = 0; 633 j = getch(); 634 if (!isalpha(cbits(j))) { 635 ch = j; 636 while ((j = cbits(getch())) >= '0' && j <= '9') 637 k++; 638 } 639 if (!k) 640 k = j; 641 fmt[findr(i)] = k & BMASK; 642 } 643 644 setaf() /* return format of number register */ 645 { 646 register int i, j; 647 648 i = usedr(getsn()); 649 if (i == -1) 650 return; 651 cp = cbuf; 652 if (fmt[i] > 20) /* it was probably a, A, i or I */ 653 *cp++ = fmt[i]; 654 else 655 for (j = (fmt[i] ? fmt[i] : 1); j; j--) 656 *cp++ = '0'; 657 *cp = 0; 658 cp = cbuf; 659 } 660 661 662 vnumb(i) 663 int *i; 664 { 665 vflag++; 666 dfact = lss; 667 res = VERT; 668 return(inumb(i)); 669 } 670 671 672 hnumb(i) 673 int *i; 674 { 675 dfact = EM; 676 res = HOR; 677 return(inumb(i)); 678 } 679 680 681 inumb(n) 682 int *n; 683 { 684 register i, j, f; 685 tchar ii; 686 687 f = 0; 688 if (n) { 689 if ((j = cbits(ii = getch())) == '+') 690 f = 1; 691 else if (j == '-') 692 f = -1; 693 else 694 ch = ii; 695 } 696 i = atoi(); 697 if (n && f) 698 i = *n + f * i; 699 i = quant(i, res); 700 vflag = 0; 701 res = dfactd = dfact = 1; 702 if (nonumb) 703 i = 0; 704 return(i); 705 } 706 707 708 quant(n, m) 709 int n, m; 710 { 711 register i, neg; 712 713 neg = 0; 714 if (n < 0) { 715 neg++; 716 n = -n; 717 } 718 /* better as i = ((n + (m/2))/m)*m */ 719 i = n / m; 720 if ((n - m * i) > (m / 2)) 721 i += 1; 722 i *= m; 723 if (neg) 724 i = -i; 725 return(i); 726 } 727 728 729