Blob
1 /*2 * troff5.c3 *4 * misc processing requests5 */7 #include "tdef.h"8 #include "fns.h"9 #include "ext.h"11 int iflist[NIF];12 int ifx;13 int ifnum = 0; /* trying numeric expression for .if or .ie condition */15 void casead(void)16 {17 int i;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 }49 void casena(void)50 {51 ad = 0;52 }55 void casefi(void)56 {57 tbreak();58 fi = 1;59 pendnf = 0;60 }63 void casenf(void)64 {65 tbreak();66 fi = 0;67 }70 void casers(void)71 {72 dip->nls = 0;73 }76 void casens(void)77 {78 dip->nls++;79 }81 int82 chget(int c)83 {84 Tchar i;86 i = 0;87 if (skip() || ismot(i = getch()) || cbits(i) == ' ' || cbits(i) == '\n') {88 ch = i;89 return(c);90 } else91 return cbits(i); /* was (i & BYTEMASK) */92 }95 void casecc(void)96 {97 cc = chget('.');98 }101 void casec2(void)102 {103 c2 = chget('\'');104 }107 void casehc(void)108 {109 ohc = chget(OHC);110 }113 void casetc(void)114 {115 tabc = chget(0);116 }119 void caselc(void)120 {121 dotc = chget(0);122 }125 void casehy(void)126 {127 int i;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 }141 void casenh(void)142 {143 hyf = 0;144 }146 int147 max(int aa, int bb)148 {149 if (aa > bb)150 return(aa);151 else152 return(bb);153 }156 void casece(void)157 {158 int i;160 noscale++;161 skip();162 i = max(atoi0(), 0);163 if (nonumb)164 i = 1;165 tbreak();166 ce = i;167 noscale = 0;168 }171 void casein(void)172 {173 int i;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 }192 void casell(void)193 {194 int i;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 }209 void caselt(void)210 {211 int i;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 }225 void caseti(void)226 {227 int i;229 if (skip())230 return;231 i = max(hnumb(&in), 0);232 tbreak();233 un1 = i;234 setnel();235 }238 void casels(void)239 {240 int i;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 }256 void casepo(void)257 {258 int i;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 }274 void casepl(void)275 {276 int i;278 skip();279 if ((i = vnumb(&pl)) == 0)280 pl = 11 * INCH; /*11in*/281 else282 pl = i;283 if (numtabp[NL].val > pl)284 numtabp[NL].val = pl;285 }288 void casewh(void)289 {290 int i, j, k;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 }316 void casech(void)317 {318 int i, j, k;320 lgf++;321 skip();322 if (!(j = getrq()))323 return;324 else325 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 }337 int338 findn(int i)339 {340 int k;342 for (k = 0; k < NTRAP; k++)343 if ((nlist[k] == i) && (mlist[k] != 0))344 break;345 return(k);346 }349 void casepn(void)350 {351 int i;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 }364 void casebp(void)365 {366 int i;367 Stack *savframe;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 }384 void casetm(void)385 {386 casetm1(0, stderr);387 }390 void casefm(void)391 {392 static struct fcache {393 char *name;394 FILE *fp;395 } fcache[15];396 int i;398 if ( skip() || !getname()) {399 ERROR "fm: missing filename" WARN;400 return;401 }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 }421 void casetm1(int ab, FILE *out)422 {423 int i, j, c;424 char *p;425 char tmbuf[NTM];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 } else447 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 sprintf(&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 else479 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 } else488 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 }502 void casesp(void)503 {504 casesp1(0);505 }507 void casesp1(int a)508 {509 int i, j, savlss;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 } else521 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 else530 i = numtabp[NL].val;531 if ((i + j) < 0)532 j = -i;533 lss = j;534 newline(0);535 lss = savlss;536 }539 void casert(void)540 {541 int a, *p;543 skip();544 if (dip != d)545 p = &dip->dnl;546 else547 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 }558 void caseem(void)559 {560 lgf++;561 skip();562 em = getrq();563 }566 void casefl(void)567 {568 tbreak();569 if (!ascii)570 ptflush();571 flusho();572 }575 void caseev(void)576 {577 int nxev;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 else598 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 }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 }615 void caseel(void)616 {617 if (--ifx < 0) {618 ifx = 0;619 iflist[0] = 0;620 }621 caseif1(2);622 }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 }637 void caseif(void)638 {639 caseif1(0);640 }642 void caseif1(int x)643 {644 extern int falsef;645 int notflag, true;646 Tchar i;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 }715 void eatblk(int inblk)716 {717 int cnt, i;719 cnt = 0;720 do {721 if (ch) {722 i = cbits(ch);723 ch = 0;724 } else725 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 }746 int747 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;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 }808 void caserd(void)809 {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 }834 int835 rdtty(void)836 {837 char onechar;839 onechar = 0;840 if (read(0, &onechar, 1) == 1) {841 if (onechar == '\n')842 tty++;843 else844 tty = 1;845 if (tty != 3)846 return(onechar);847 }848 tty = 0;849 if (NROFF && quiet)850 echo_on();851 return(0);852 }855 void caseec(void)856 {857 eschar = chget('\\');858 }861 void caseeo(void)862 {863 eschar = 0;864 }867 void caseta(void)868 {869 int i, j, k;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 }900 void casene(void)901 {902 int i, j;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 }922 void casetr(void)923 {924 int i, j;925 Tchar k;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 }941 void casecu(void)942 {943 cu++;944 caseul();945 }948 void caseul(void)949 {950 int i;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 }973 void caseuf(void)974 {975 int i, j;977 if (skip() || !(i = getrq()) || i == 'S' || (j = findft(i)) == -1)978 ulfont = ULFONT; /*default underline position*/979 else980 ulfont = j;981 if (NROFF && ulfont == FT)982 ulfont = ULFONT;983 }986 void caseit(void)987 {988 int i;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 }1002 void casemc(void)1003 {1004 int i;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 }1020 void casemk(void)1021 {1022 int i, j;1024 if (dip != d)1025 j = dip->dnl;1026 else1027 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 }1038 void casesv(void)1039 {1040 int i;1042 skip();1043 if ((i = vnumb((int *)0)) < 0)1044 return;1045 if (nonumb)1046 i = 1;1047 sv += i;1048 caseos();1049 }1052 void caseos(void)1053 {1054 int savlss;1056 if (sv <= findt1()) {1057 savlss = lss;1058 lss = sv;1059 newline(0);1060 lss = savlss;1061 sv = 0;1062 }1063 }1066 void casenm(void)1067 {1068 int i;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 }1086 /*1087 * .nm relies on the fact that illegal args are skipped; don't warn1088 * for illegality of these1089 */1090 void getnm(int *p, int min)1091 {1092 int i;1093 int savtr = trace;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 }1107 void casenn(void)1108 {1109 noscale++;1110 skip();1111 nn = max(atoi0(), 1);1112 noscale = 0;1113 }1116 void caseab(void)1117 {1118 casetm1(1, stderr);1119 done3(0);1120 }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. */1128 void save_tty(void) /*save any tty settings that may be changed*/1129 {1130 }1133 void restore_tty(void) /*restore tty settings from beginning*/1134 {1135 }1138 void set_tty(void)1139 {1140 }1143 void echo_off(void) /*turn off ECHO for .rd in "-q" mode*/1144 {1145 }1148 void echo_on(void) /*restore ECHO after .rd in "-q" mode*/1149 {1150 }