n5.c (14292B)
1 /* 2 * troff5.c 3 * 4 * misc processing requests 5 */ 6 7 #include "tdef.h" 8 #include "fns.h" 9 #include "ext.h" 10 11 int iflist[NIF]; 12 int ifx; 13 int ifnum = 0; /* trying numeric expression for .if or .ie condition */ 14 15 void casead(void) 16 { 17 int i; 18 19 ad = 1; 20 /* leave admod alone */ 21 if (skip()) 22 return; 23 switch (i = cbits(getch())) { 24 case 'r': /* right adj, left ragged */ 25 admod = 2; 26 break; 27 case 'l': /* left adj, right ragged */ 28 admod = ad = 0; /* same as casena */ 29 break; 30 case 'c': /*centered adj*/ 31 admod = 1; 32 break; 33 case 'b': 34 case 'n': 35 admod = 0; 36 break; 37 case '0': 38 case '2': 39 case '4': 40 ad = 0; 41 case '1': 42 case '3': 43 case '5': 44 admod = (i - '0') / 2; 45 } 46 } 47 48 49 void casena(void) 50 { 51 ad = 0; 52 } 53 54 55 void casefi(void) 56 { 57 tbreak(); 58 fi = 1; 59 pendnf = 0; 60 } 61 62 63 void casenf(void) 64 { 65 tbreak(); 66 fi = 0; 67 } 68 69 70 void casers(void) 71 { 72 dip->nls = 0; 73 } 74 75 76 void casens(void) 77 { 78 dip->nls++; 79 } 80 81 int 82 chget(int c) 83 { 84 Tchar i; 85 86 i = 0; 87 if (skip() || ismot(i = getch()) || cbits(i) == ' ' || cbits(i) == '\n') { 88 ch = i; 89 return(c); 90 } else 91 return cbits(i); /* was (i & BYTEMASK) */ 92 } 93 94 95 void casecc(void) 96 { 97 cc = chget('.'); 98 } 99 100 101 void casec2(void) 102 { 103 c2 = chget('\''); 104 } 105 106 107 void casehc(void) 108 { 109 ohc = chget(OHC); 110 } 111 112 113 void casetc(void) 114 { 115 tabc = chget(0); 116 } 117 118 119 void caselc(void) 120 { 121 dotc = chget(0); 122 } 123 124 125 void casehy(void) 126 { 127 int i; 128 129 hyf = 1; 130 if (skip()) 131 return; 132 noscale++; 133 i = atoi0(); 134 noscale = 0; 135 if (nonumb) 136 return; 137 hyf = max(i, 0); 138 } 139 140 141 void casenh(void) 142 { 143 hyf = 0; 144 } 145 146 int 147 max(int aa, int bb) 148 { 149 if (aa > bb) 150 return(aa); 151 else 152 return(bb); 153 } 154 155 156 void casece(void) 157 { 158 int i; 159 160 noscale++; 161 skip(); 162 i = max(atoi0(), 0); 163 if (nonumb) 164 i = 1; 165 tbreak(); 166 ce = i; 167 noscale = 0; 168 } 169 170 171 void casein(void) 172 { 173 int i; 174 175 if (skip()) 176 i = in1; 177 else { 178 i = max(hnumb(&in), 0); 179 if (nonumb) 180 i = in1; 181 } 182 tbreak(); 183 in1 = in; 184 in = i; 185 if (!nc) { 186 un = in; 187 setnel(); 188 } 189 } 190 191 192 void casell(void) 193 { 194 int i; 195 196 if (skip()) 197 i = ll1; 198 else { 199 i = max(hnumb(&ll), INCH / 10); 200 if (nonumb) 201 i = ll1; 202 } 203 ll1 = ll; 204 ll = i; 205 setnel(); 206 } 207 208 209 void caselt(void) 210 { 211 int i; 212 213 if (skip()) 214 i = lt1; 215 else { 216 i = max(hnumb(<), 0); 217 if (nonumb) 218 i = lt1; 219 } 220 lt1 = lt; 221 lt = i; 222 } 223 224 225 void caseti(void) 226 { 227 int i; 228 229 if (skip()) 230 return; 231 i = max(hnumb(&in), 0); 232 tbreak(); 233 un1 = i; 234 setnel(); 235 } 236 237 238 void casels(void) 239 { 240 int i; 241 242 noscale++; 243 if (skip()) 244 i = ls1; 245 else { 246 i = max(inumb(&ls), 1); 247 if (nonumb) 248 i = ls1; 249 } 250 ls1 = ls; 251 ls = i; 252 noscale = 0; 253 } 254 255 256 void casepo(void) 257 { 258 int i; 259 260 if (skip()) 261 i = po1; 262 else { 263 i = max(hnumb(&po), 0); 264 if (nonumb) 265 i = po1; 266 } 267 po1 = po; 268 po = i; 269 if (TROFF & !ascii) 270 esc += po - po1; 271 } 272 273 274 void casepl(void) 275 { 276 int i; 277 278 skip(); 279 if ((i = vnumb(&pl)) == 0) 280 pl = 11 * INCH; /*11in*/ 281 else 282 pl = i; 283 if (numtabp[NL].val > pl) 284 numtabp[NL].val = pl; 285 } 286 287 288 void casewh(void) 289 { 290 int i, j, k; 291 292 lgf++; 293 skip(); 294 i = vnumb((int *)0); 295 if (nonumb) 296 return; 297 skip(); 298 j = getrq(); 299 if ((k = findn(i)) != NTRAP) { 300 mlist[k] = j; 301 return; 302 } 303 for (k = 0; k < NTRAP; k++) 304 if (mlist[k] == 0) 305 break; 306 if (k == NTRAP) { 307 flusho(); 308 ERROR "cannot plant trap." WARN; 309 return; 310 } 311 mlist[k] = j; 312 nlist[k] = i; 313 } 314 315 316 void casech(void) 317 { 318 int i, j, k; 319 320 lgf++; 321 skip(); 322 if (!(j = getrq())) 323 return; 324 else 325 for (k = 0; k < NTRAP; k++) 326 if (mlist[k] == j) 327 break; 328 if (k == NTRAP) 329 return; 330 skip(); 331 i = vnumb((int *)0); 332 if (nonumb) 333 mlist[k] = 0; 334 nlist[k] = i; 335 } 336 337 int 338 findn(int i) 339 { 340 int k; 341 342 for (k = 0; k < NTRAP; k++) 343 if ((nlist[k] == i) && (mlist[k] != 0)) 344 break; 345 return(k); 346 } 347 348 349 void casepn(void) 350 { 351 int i; 352 353 skip(); 354 noscale++; 355 i = max(inumb(&numtabp[PN].val), 0); 356 noscale = 0; 357 if (!nonumb) { 358 npn = i; 359 npnflg++; 360 } 361 } 362 363 364 void casebp(void) 365 { 366 int i; 367 Stack *savframe; 368 369 if (dip != d) 370 return; 371 savframe = frame; 372 skip(); 373 if ((i = inumb(&numtabp[PN].val)) < 0) 374 i = 0; 375 tbreak(); 376 if (!nonumb) { 377 npn = i; 378 npnflg++; 379 } else if (dip->nls) 380 return; 381 eject(savframe); 382 } 383 384 void casetm(void) 385 { 386 casetm1(0, stderr); 387 } 388 389 390 void casefm(void) 391 { 392 static struct fcache { 393 char *name; 394 FILE *fp; 395 } fcache[15]; 396 int i; 397 398 if ( skip() || !getname()) { 399 ERROR "fm: missing filename" WARN; 400 return; 401 } 402 403 for (i = 0; i < 15 && fcache[i].fp != NULL; i++) { 404 if (strcmp(nextf, fcache[i].name) == 0) 405 break; 406 } 407 if (i >= 15) { 408 ERROR "fm: too many streams" WARN; 409 return; 410 } 411 if (fcache[i].fp == NULL) { 412 if( (fcache[i].fp = fopen(unsharp(nextf), "w")) == NULL) { 413 ERROR "fm: cannot open %s", nextf WARN; 414 return; 415 } 416 fcache[i].name = strdupl(nextf); 417 } 418 casetm1(0, fcache[i].fp); 419 } 420 421 void casetm1(int ab, FILE *out) 422 { 423 int i, j, c; 424 char *p; 425 char tmbuf[NTM]; 426 427 lgf++; 428 copyf++; 429 if (ab) { 430 if (skip()) 431 ERROR "User Abort" WARN; 432 else { 433 extern int error; 434 int savtrac = trace; 435 i = trace = 0; 436 noscale++; 437 i = inumb(&trace); 438 noscale--; 439 if (i) { 440 error = i; 441 if (nlflg || skip()) 442 ERROR "User Abort, exit code %d", i WARN; 443 } 444 trace = savtrac; 445 } 446 } else 447 skip(); 448 for (i = 0; i < NTM - 2; ) { 449 if ((c = cbits(getch())) == '\n' || c == RIGHT) 450 break; 451 else if (c == MINUS) { /* special pleading for strange encodings */ 452 tmbuf[i++] = '\\'; 453 tmbuf[i++] = '-'; 454 } else if (c == PRESC) { 455 tmbuf[i++] = '\\'; 456 tmbuf[i++] = 'e'; 457 } else if (c == FILLER) { 458 tmbuf[i++] = '\\'; 459 tmbuf[i++] = '&'; 460 } else if (c == UNPAD) { 461 tmbuf[i++] = '\\'; 462 tmbuf[i++] = ' '; 463 } else if (c == OHC) { 464 tmbuf[i++] = '\\'; 465 tmbuf[i++] = '%'; 466 } else if (c >= ALPHABET) { 467 p = chname(c); 468 switch (*p) { 469 case MBchar: 470 strcpy(&tmbuf[i], p+1); 471 break; 472 case Number: 473 sprintf(&tmbuf[i], "\\N'%s'", p+1); 474 break; 475 case Troffchar: 476 if ((j = strlen(p+1)) == 2) 477 sprintf(&tmbuf[i], "\\(%s", p+1); 478 else 479 sprintf(&tmbuf[i], "\\C'%s'", p+1); 480 break; 481 default: 482 sprintf(&tmbuf[i]," %s? ", p); 483 break; 484 } 485 j = strlen(&tmbuf[i]); 486 i += j; 487 } else 488 tmbuf[i++] = c; 489 } 490 tmbuf[i] = 0; 491 if (ab) /* truncate output */ 492 obufp = obuf; /* should be a function in n2.c */ 493 flusho(); 494 if (i) 495 fprintf(out, "%s\n", tmbuf); 496 fflush(out); 497 copyf--; 498 lgf--; 499 } 500 501 502 void casesp(void) 503 { 504 casesp1(0); 505 } 506 507 void casesp1(int a) 508 { 509 int i, j, savlss; 510 511 tbreak(); 512 if (dip->nls || trap) 513 return; 514 i = findt1(); 515 if (!a) { 516 skip(); 517 j = vnumb((int *)0); 518 if (nonumb) 519 j = lss; 520 } else 521 j = a; 522 if (j == 0) 523 return; 524 if (i < j) 525 j = i; 526 savlss = lss; 527 if (dip != d) 528 i = dip->dnl; 529 else 530 i = numtabp[NL].val; 531 if ((i + j) < 0) 532 j = -i; 533 lss = j; 534 newline(0); 535 lss = savlss; 536 } 537 538 539 void casert(void) 540 { 541 int a, *p; 542 543 skip(); 544 if (dip != d) 545 p = &dip->dnl; 546 else 547 p = &numtabp[NL].val; 548 a = vnumb(p); 549 if (nonumb) 550 a = dip->mkline; 551 if ((a < 0) || (a >= *p)) 552 return; 553 nb++; 554 casesp1(a - *p); 555 } 556 557 558 void caseem(void) 559 { 560 lgf++; 561 skip(); 562 em = getrq(); 563 } 564 565 566 void casefl(void) 567 { 568 tbreak(); 569 if (!ascii) 570 ptflush(); 571 flusho(); 572 } 573 574 575 void caseev(void) 576 { 577 int nxev; 578 579 if (skip()) { 580 e0: 581 if (evi == 0) 582 return; 583 nxev = evlist[--evi]; 584 goto e1; 585 } 586 noscale++; 587 nxev = atoi0(); 588 noscale = 0; 589 if (nonumb) 590 goto e0; 591 flushi(); 592 if (nxev >= NEV || nxev < 0 || evi >= EVLSZ) { 593 flusho(); 594 ERROR "cannot do .ev %d", nxev WARN; 595 if (error) 596 done2(040); 597 else 598 edone(040); 599 return; 600 } 601 evlist[evi++] = ev; 602 e1: 603 if (ev == nxev) 604 return; 605 ev = nxev; 606 envp = &env[ev]; 607 } 608 609 void envcopy(Env *e1, Env *e2) /* copy env e2 to e1 */ 610 { 611 *e1 = *e2; /* rumor hath that this fails on some machines */ 612 } 613 614 615 void caseel(void) 616 { 617 if (--ifx < 0) { 618 ifx = 0; 619 iflist[0] = 0; 620 } 621 caseif1(2); 622 } 623 624 625 void caseie(void) 626 { 627 if (ifx >= NIF) { 628 ERROR "if-else overflow." WARN; 629 ifx = 0; 630 edone(040); 631 } 632 caseif1(1); 633 ifx++; 634 } 635 636 637 void caseif(void) 638 { 639 caseif1(0); 640 } 641 642 void caseif1(int x) 643 { 644 extern int falsef; 645 int notflag, true; 646 Tchar i; 647 648 if (x == 2) { 649 notflag = 0; 650 true = iflist[ifx]; 651 goto i1; 652 } 653 true = 0; 654 skip(); 655 if ((cbits(i = getch())) == '!') { 656 notflag = 1; 657 } else { 658 notflag = 0; 659 ch = i; 660 } 661 ifnum++; 662 i = atoi0(); 663 ifnum = 0; 664 if (!nonumb) { 665 if (i > 0) 666 true++; 667 goto i1; 668 } 669 i = getch(); 670 switch (cbits(i)) { 671 case 'e': 672 if (!(numtabp[PN].val & 01)) 673 true++; 674 break; 675 case 'o': 676 if (numtabp[PN].val & 01) 677 true++; 678 break; 679 case 'n': 680 if (NROFF) 681 true++; 682 break; 683 case 't': 684 if (TROFF) 685 true++; 686 break; 687 case ' ': 688 break; 689 default: 690 true = cmpstr(i); 691 } 692 i1: 693 true ^= notflag; 694 if (x == 1) 695 iflist[ifx] = !true; 696 if (true) { 697 i2: 698 while ((cbits(i = getch())) == ' ') 699 ; 700 if (cbits(i) == LEFT) 701 goto i2; 702 ch = i; 703 nflush++; 704 } else { 705 if (!nlflg) { 706 copyf++; 707 falsef++; 708 eatblk(0); 709 copyf--; 710 falsef--; 711 } 712 } 713 } 714 715 void eatblk(int inblk) 716 { 717 int cnt, i; 718 719 cnt = 0; 720 do { 721 if (ch) { 722 i = cbits(ch); 723 ch = 0; 724 } else 725 i = cbits(getch0()); 726 if (i == ESC) 727 cnt++; 728 else { 729 if (cnt == 1) 730 switch (i) { 731 case '{': i = LEFT; break; 732 case '}': i = RIGHT; break; 733 case '\n': i = 'x'; break; 734 } 735 cnt = 0; 736 } 737 if (i == LEFT) eatblk(1); 738 } while ((!inblk && (i != '\n')) || (inblk && (i != RIGHT))); 739 if (i == '\n') { 740 nlflg++; 741 if (ip == 0) 742 numtabp[CD].val++; 743 } 744 } 745 746 int 747 cmpstr(Tchar c) 748 { 749 int j, delim; 750 Tchar i; 751 int val; 752 int savapts, savapts1, savfont, savfont1, savpts, savpts1; 753 Tchar string[1280]; 754 Tchar *sp; 755 756 if (ismot(c)) 757 return(0); 758 delim = cbits(c); 759 savapts = apts; 760 savapts1 = apts1; 761 savfont = font; 762 savfont1 = font1; 763 savpts = pts; 764 savpts1 = pts1; 765 sp = string; 766 while ((j = cbits(i = getch()))!=delim && j!='\n' && sp<&string[1280-1]) 767 *sp++ = i; 768 if (sp >= string + 1280) { 769 ERROR "too-long string compare." WARN; 770 edone(0100); 771 } 772 if (nlflg) { 773 val = sp==string; 774 goto rtn; 775 } 776 *sp = 0; 777 apts = savapts; 778 apts1 = savapts1; 779 font = savfont; 780 font1 = savfont1; 781 pts = savpts; 782 pts1 = savpts1; 783 mchbits(); 784 val = 1; 785 sp = string; 786 while ((j = cbits(i = getch())) != delim && j != '\n') { 787 if (*sp != i) { 788 eat(delim); 789 val = 0; 790 goto rtn; 791 } 792 sp++; 793 } 794 if (*sp) 795 val = 0; 796 rtn: 797 apts = savapts; 798 apts1 = savapts1; 799 font = savfont; 800 font1 = savfont1; 801 pts = savpts; 802 pts1 = savpts1; 803 mchbits(); 804 return(val); 805 } 806 807 808 void caserd(void) 809 { 810 811 lgf++; 812 skip(); 813 getname(); 814 if (!iflg) { 815 if (quiet) { 816 if (NROFF) { 817 echo_off(); 818 flusho(); 819 } 820 fprintf(stderr, "\007"); /*bell*/ 821 } else { 822 if (nextf[0]) { 823 fprintf(stderr, "%s:", nextf); 824 } else { 825 fprintf(stderr, "\007"); /*bell*/ 826 } 827 } 828 } 829 collect(); 830 tty++; 831 pushi(RD_OFFSET, PAIR('r','d')); 832 } 833 834 int 835 rdtty(void) 836 { 837 char onechar; 838 839 onechar = 0; 840 if (read(0, &onechar, 1) == 1) { 841 if (onechar == '\n') 842 tty++; 843 else 844 tty = 1; 845 if (tty != 3) 846 return(onechar); 847 } 848 tty = 0; 849 if (NROFF && quiet) 850 echo_on(); 851 return(0); 852 } 853 854 855 void caseec(void) 856 { 857 eschar = chget('\\'); 858 } 859 860 861 void caseeo(void) 862 { 863 eschar = 0; 864 } 865 866 867 void caseta(void) 868 { 869 int i, j, k; 870 871 tabtab[0] = nonumb = 0; 872 for (i = 0; ((i < (NTAB - 1)) && !nonumb); i++) { 873 if (skip()) 874 break; 875 k = tabtab[max(i-1, 0)] & TABMASK; 876 if ((j = max(hnumb(&k), 0)) > TABMASK) { 877 ERROR "Tab too far away" WARN; 878 j = TABMASK; 879 } 880 tabtab[i] = j & TABMASK; 881 if (!nonumb) 882 switch (cbits(ch)) { 883 case 'C': 884 tabtab[i] |= CTAB; 885 break; 886 case 'R': 887 tabtab[i] |= RTAB; 888 break; 889 default: /*includes L*/ 890 break; 891 } 892 nonumb = ch = 0; 893 } 894 if (!skip()) 895 ERROR "Too many tab stops" WARN; 896 tabtab[i] = 0; 897 } 898 899 900 void casene(void) 901 { 902 int i, j; 903 904 skip(); 905 i = vnumb((int *)0); 906 if (nonumb) 907 i = lss; 908 if (dip == d && numtabp[NL].val == -1) { 909 newline(1); 910 return; 911 } 912 if (i > (j = findt1())) { 913 i = lss; 914 lss = j; 915 dip->nls = 0; 916 newline(0); 917 lss = i; 918 } 919 } 920 921 922 void casetr(void) 923 { 924 int i, j; 925 Tchar k; 926 927 lgf++; 928 skip(); 929 while ((i = cbits(k=getch())) != '\n') { 930 if (ismot(k)) 931 return; 932 if (ismot(k = getch())) 933 return; 934 if ((j = cbits(k)) == '\n') 935 j = ' '; 936 trtab[i] = j; 937 } 938 } 939 940 941 void casecu(void) 942 { 943 cu++; 944 caseul(); 945 } 946 947 948 void caseul(void) 949 { 950 int i; 951 952 noscale++; 953 skip(); 954 i = max(atoi0(), 0); 955 if (nonumb) 956 i = 1; 957 if (ul && (i == 0)) { 958 font = sfont; 959 ul = cu = 0; 960 } 961 if (i) { 962 if (!ul) { 963 sfont = font; 964 font = ulfont; 965 } 966 ul = i; 967 } 968 noscale = 0; 969 mchbits(); 970 } 971 972 973 void caseuf(void) 974 { 975 int i, j; 976 977 if (skip() || !(i = getrq()) || i == 'S' || (j = findft(i)) == -1) 978 ulfont = ULFONT; /*default underline position*/ 979 else 980 ulfont = j; 981 if (NROFF && ulfont == FT) 982 ulfont = ULFONT; 983 } 984 985 986 void caseit(void) 987 { 988 int i; 989 990 lgf++; 991 it = itmac = 0; 992 noscale++; 993 skip(); 994 i = atoi0(); 995 skip(); 996 if (!nonumb && (itmac = getrq())) 997 it = i; 998 noscale = 0; 999 } 1000 1001 1002 void casemc(void) 1003 { 1004 int i; 1005 1006 if (icf > 1) 1007 ic = 0; 1008 icf = 0; 1009 if (skip()) 1010 return; 1011 ic = getch(); 1012 icf = 1; 1013 skip(); 1014 i = max(hnumb((int *)0), 0); 1015 if (!nonumb) 1016 ics = i; 1017 } 1018 1019 1020 void casemk(void) 1021 { 1022 int i, j; 1023 1024 if (dip != d) 1025 j = dip->dnl; 1026 else 1027 j = numtabp[NL].val; 1028 if (skip()) { 1029 dip->mkline = j; 1030 return; 1031 } 1032 if ((i = getrq()) == 0) 1033 return; 1034 numtabp[findr(i)].val = j; 1035 } 1036 1037 1038 void casesv(void) 1039 { 1040 int i; 1041 1042 skip(); 1043 if ((i = vnumb((int *)0)) < 0) 1044 return; 1045 if (nonumb) 1046 i = 1; 1047 sv += i; 1048 caseos(); 1049 } 1050 1051 1052 void caseos(void) 1053 { 1054 int savlss; 1055 1056 if (sv <= findt1()) { 1057 savlss = lss; 1058 lss = sv; 1059 newline(0); 1060 lss = savlss; 1061 sv = 0; 1062 } 1063 } 1064 1065 1066 void casenm(void) 1067 { 1068 int i; 1069 1070 lnmod = nn = 0; 1071 if (skip()) 1072 return; 1073 lnmod++; 1074 noscale++; 1075 i = inumb(&numtabp[LN].val); 1076 if (!nonumb) 1077 numtabp[LN].val = max(i, 0); 1078 getnm(&ndf, 1); 1079 getnm(&nms, 0); 1080 getnm(&ni, 0); 1081 getnm(&nmwid, 3); /* really kludgy! */ 1082 noscale = 0; 1083 nmbits = chbits; 1084 } 1085 1086 /* 1087 * .nm relies on the fact that illegal args are skipped; don't warn 1088 * for illegality of these 1089 */ 1090 void getnm(int *p, int min) 1091 { 1092 int i; 1093 int savtr = trace; 1094 1095 eat(' '); 1096 if (skip()) 1097 return; 1098 trace = 0; 1099 i = atoi0(); 1100 if (nonumb) 1101 return; 1102 *p = max(i, min); 1103 trace = savtr; 1104 } 1105 1106 1107 void casenn(void) 1108 { 1109 noscale++; 1110 skip(); 1111 nn = max(atoi0(), 1); 1112 noscale = 0; 1113 } 1114 1115 1116 void caseab(void) 1117 { 1118 casetm1(1, stderr); 1119 done3(0); 1120 } 1121 1122 1123 /* nroff terminal handling has been pretty well excised */ 1124 /* as part of the merge with troff. these are ghostly remnants, */ 1125 /* called, but doing nothing. restore them at your peril. */ 1126 1127 1128 void save_tty(void) /*save any tty settings that may be changed*/ 1129 { 1130 } 1131 1132 1133 void restore_tty(void) /*restore tty settings from beginning*/ 1134 { 1135 } 1136 1137 1138 void set_tty(void) 1139 { 1140 } 1141 1142 1143 void echo_off(void) /*turn off ECHO for .rd in "-q" mode*/ 1144 { 1145 } 1146 1147 1148 void echo_on(void) /*restore ECHO after .rd in "-q" mode*/ 1149 { 1150 }