aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/troff/n5.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/troff/n5.c')
-rw-r--r--src/cmd/troff/n5.c1149
1 files changed, 1149 insertions, 0 deletions
diff --git a/src/cmd/troff/n5.c b/src/cmd/troff/n5.c
new file mode 100644
index 00000000..c2801e47
--- /dev/null
+++ b/src/cmd/troff/n5.c
@@ -0,0 +1,1149 @@
+/*
+ * troff5.c
+ *
+ * misc processing requests
+ */
+
+#include "tdef.h"
+#include "fns.h"
+#include "ext.h"
+
+int iflist[NIF];
+int ifx;
+int ifnum = 0; /* trying numeric expression for .if or .ie condition */
+
+void casead(void)
+{
+ int i;
+
+ ad = 1;
+ /* leave admod alone */
+ if (skip())
+ return;
+ switch (i = cbits(getch())) {
+ case 'r': /* right adj, left ragged */
+ admod = 2;
+ break;
+ case 'l': /* left adj, right ragged */
+ admod = ad = 0; /* same as casena */
+ break;
+ case 'c': /*centered adj*/
+ admod = 1;
+ break;
+ case 'b':
+ case 'n':
+ admod = 0;
+ break;
+ case '0':
+ case '2':
+ case '4':
+ ad = 0;
+ case '1':
+ case '3':
+ case '5':
+ admod = (i - '0') / 2;
+ }
+}
+
+
+void casena(void)
+{
+ ad = 0;
+}
+
+
+void casefi(void)
+{
+ tbreak();
+ fi = 1;
+ pendnf = 0;
+}
+
+
+void casenf(void)
+{
+ tbreak();
+ fi = 0;
+}
+
+
+void casers(void)
+{
+ dip->nls = 0;
+}
+
+
+void casens(void)
+{
+ dip->nls++;
+}
+
+
+chget(int c)
+{
+ Tchar i;
+
+ if (skip() || ismot(i = getch()) || cbits(i) == ' ' || cbits(i) == '\n') {
+ ch = i;
+ return(c);
+ } else
+ return cbits(i); /* was (i & BYTEMASK) */
+}
+
+
+void casecc(void)
+{
+ cc = chget('.');
+}
+
+
+void casec2(void)
+{
+ c2 = chget('\'');
+}
+
+
+void casehc(void)
+{
+ ohc = chget(OHC);
+}
+
+
+void casetc(void)
+{
+ tabc = chget(0);
+}
+
+
+void caselc(void)
+{
+ dotc = chget(0);
+}
+
+
+void casehy(void)
+{
+ int i;
+
+ hyf = 1;
+ if (skip())
+ return;
+ noscale++;
+ i = atoi0();
+ noscale = 0;
+ if (nonumb)
+ return;
+ hyf = max(i, 0);
+}
+
+
+void casenh(void)
+{
+ hyf = 0;
+}
+
+
+max(int aa, int bb)
+{
+ if (aa > bb)
+ return(aa);
+ else
+ return(bb);
+}
+
+
+void casece(void)
+{
+ int i;
+
+ noscale++;
+ skip();
+ i = max(atoi0(), 0);
+ if (nonumb)
+ i = 1;
+ tbreak();
+ ce = i;
+ noscale = 0;
+}
+
+
+void casein(void)
+{
+ int i;
+
+ if (skip())
+ i = in1;
+ else {
+ i = max(hnumb(&in), 0);
+ if (nonumb)
+ i = in1;
+ }
+ tbreak();
+ in1 = in;
+ in = i;
+ if (!nc) {
+ un = in;
+ setnel();
+ }
+}
+
+
+void casell(void)
+{
+ int i;
+
+ if (skip())
+ i = ll1;
+ else {
+ i = max(hnumb(&ll), INCH / 10);
+ if (nonumb)
+ i = ll1;
+ }
+ ll1 = ll;
+ ll = i;
+ setnel();
+}
+
+
+void caselt(void)
+{
+ int i;
+
+ if (skip())
+ i = lt1;
+ else {
+ i = max(hnumb(&lt), 0);
+ if (nonumb)
+ i = lt1;
+ }
+ lt1 = lt;
+ lt = i;
+}
+
+
+void caseti(void)
+{
+ int i;
+
+ if (skip())
+ return;
+ i = max(hnumb(&in), 0);
+ tbreak();
+ un1 = i;
+ setnel();
+}
+
+
+void casels(void)
+{
+ int i;
+
+ noscale++;
+ if (skip())
+ i = ls1;
+ else {
+ i = max(inumb(&ls), 1);
+ if (nonumb)
+ i = ls1;
+ }
+ ls1 = ls;
+ ls = i;
+ noscale = 0;
+}
+
+
+void casepo(void)
+{
+ int i;
+
+ if (skip())
+ i = po1;
+ else {
+ i = max(hnumb(&po), 0);
+ if (nonumb)
+ i = po1;
+ }
+ po1 = po;
+ po = i;
+ if (TROFF & !ascii)
+ esc += po - po1;
+}
+
+
+void casepl(void)
+{
+ int i;
+
+ skip();
+ if ((i = vnumb(&pl)) == 0)
+ pl = 11 * INCH; /*11in*/
+ else
+ pl = i;
+ if (numtabp[NL].val > pl)
+ numtabp[NL].val = pl;
+}
+
+
+void casewh(void)
+{
+ int i, j, k;
+
+ lgf++;
+ skip();
+ i = vnumb((int *)0);
+ if (nonumb)
+ return;
+ skip();
+ j = getrq();
+ if ((k = findn(i)) != NTRAP) {
+ mlist[k] = j;
+ return;
+ }
+ for (k = 0; k < NTRAP; k++)
+ if (mlist[k] == 0)
+ break;
+ if (k == NTRAP) {
+ flusho();
+ ERROR "cannot plant trap." WARN;
+ return;
+ }
+ mlist[k] = j;
+ nlist[k] = i;
+}
+
+
+void casech(void)
+{
+ int i, j, k;
+
+ lgf++;
+ skip();
+ if (!(j = getrq()))
+ return;
+ else
+ for (k = 0; k < NTRAP; k++)
+ if (mlist[k] == j)
+ break;
+ if (k == NTRAP)
+ return;
+ skip();
+ i = vnumb((int *)0);
+ if (nonumb)
+ mlist[k] = 0;
+ nlist[k] = i;
+}
+
+
+findn(int i)
+{
+ int k;
+
+ for (k = 0; k < NTRAP; k++)
+ if ((nlist[k] == i) && (mlist[k] != 0))
+ break;
+ return(k);
+}
+
+
+void casepn(void)
+{
+ int i;
+
+ skip();
+ noscale++;
+ i = max(inumb(&numtabp[PN].val), 0);
+ noscale = 0;
+ if (!nonumb) {
+ npn = i;
+ npnflg++;
+ }
+}
+
+
+void casebp(void)
+{
+ int i;
+ Stack *savframe;
+
+ if (dip != d)
+ return;
+ savframe = frame;
+ skip();
+ if ((i = inumb(&numtabp[PN].val)) < 0)
+ i = 0;
+ tbreak();
+ if (!nonumb) {
+ npn = i;
+ npnflg++;
+ } else if (dip->nls)
+ return;
+ eject(savframe);
+}
+
+void casetm(void)
+{
+ casetm1(0, stderr);
+}
+
+
+void casefm(void)
+{
+ static struct fcache {
+ char *name;
+ FILE *fp;
+ } fcache[15];
+ int i;
+
+ if ( skip() || !getname()) {
+ ERROR "fm: missing filename" WARN;
+ return;
+ }
+
+ for (i = 0; i < 15 && fcache[i].fp != NULL; i++) {
+ if (strcmp(nextf, fcache[i].name) == 0)
+ break;
+ }
+ if (i >= 15) {
+ ERROR "fm: too many streams" WARN;
+ return;
+ }
+ if (fcache[i].fp == NULL) {
+ if( (fcache[i].fp = fopen(unsharp(nextf), "w")) == NULL) {
+ ERROR "fm: cannot open %s", nextf WARN;
+ return;
+ }
+ fcache[i].name = strdupl(nextf);
+ }
+ casetm1(0, fcache[i].fp);
+}
+
+void casetm1(int ab, FILE *out)
+{
+ int i, j, c;
+ char *p;
+ char tmbuf[NTM];
+
+ lgf++;
+ copyf++;
+ if (ab) {
+ if (skip())
+ ERROR "User Abort" WARN;
+ else {
+ extern int error;
+ int savtrac = trace;
+ i = trace = 0;
+ noscale++;
+ i = inumb(&trace);
+ noscale--;
+ if (i) {
+ error = i;
+ if (nlflg || skip())
+ ERROR "User Abort, exit code %d", i WARN;
+ }
+ trace = savtrac;
+ }
+ } else
+ skip();
+ for (i = 0; i < NTM - 2; ) {
+ if ((c = cbits(getch())) == '\n' || c == RIGHT)
+ break;
+ else if (c == MINUS) { /* special pleading for strange encodings */
+ tmbuf[i++] = '\\';
+ tmbuf[i++] = '-';
+ } else if (c == PRESC) {
+ tmbuf[i++] = '\\';
+ tmbuf[i++] = 'e';
+ } else if (c == FILLER) {
+ tmbuf[i++] = '\\';
+ tmbuf[i++] = '&';
+ } else if (c == UNPAD) {
+ tmbuf[i++] = '\\';
+ tmbuf[i++] = ' ';
+ } else if (c == OHC) {
+ tmbuf[i++] = '\\';
+ tmbuf[i++] = '%';
+ } else if (c >= ALPHABET) {
+ p = chname(c);
+ switch (*p) {
+ case MBchar:
+ sprintf(&tmbuf[i], p+1);
+ break;
+ case Number:
+ sprintf(&tmbuf[i], "\\N'%s'", p+1);
+ break;
+ case Troffchar:
+ if ((j = strlen(p+1)) == 2)
+ sprintf(&tmbuf[i], "\\(%s", p+1);
+ else
+ sprintf(&tmbuf[i], "\\C'%s'", p+1);
+ break;
+ default:
+ sprintf(&tmbuf[i]," %s? ", p);
+ break;
+ }
+ j = strlen(&tmbuf[i]);
+ i += j;
+ } else
+ tmbuf[i++] = c;
+ }
+ tmbuf[i] = 0;
+ if (ab) /* truncate output */
+ obufp = obuf; /* should be a function in n2.c */
+ flusho();
+ if (i)
+ fprintf(out, "%s\n", tmbuf);
+ fflush(out);
+ copyf--;
+ lgf--;
+}
+
+
+void casesp(void)
+{
+ casesp1(0);
+}
+
+void casesp1(int a)
+{
+ int i, j, savlss;
+
+ tbreak();
+ if (dip->nls || trap)
+ return;
+ i = findt1();
+ if (!a) {
+ skip();
+ j = vnumb((int *)0);
+ if (nonumb)
+ j = lss;
+ } else
+ j = a;
+ if (j == 0)
+ return;
+ if (i < j)
+ j = i;
+ savlss = lss;
+ if (dip != d)
+ i = dip->dnl;
+ else
+ i = numtabp[NL].val;
+ if ((i + j) < 0)
+ j = -i;
+ lss = j;
+ newline(0);
+ lss = savlss;
+}
+
+
+void casert(void)
+{
+ int a, *p;
+
+ skip();
+ if (dip != d)
+ p = &dip->dnl;
+ else
+ p = &numtabp[NL].val;
+ a = vnumb(p);
+ if (nonumb)
+ a = dip->mkline;
+ if ((a < 0) || (a >= *p))
+ return;
+ nb++;
+ casesp1(a - *p);
+}
+
+
+void caseem(void)
+{
+ lgf++;
+ skip();
+ em = getrq();
+}
+
+
+void casefl(void)
+{
+ tbreak();
+ if (!ascii)
+ ptflush();
+ flusho();
+}
+
+
+void caseev(void)
+{
+ int nxev;
+
+ if (skip()) {
+e0:
+ if (evi == 0)
+ return;
+ nxev = evlist[--evi];
+ goto e1;
+ }
+ noscale++;
+ nxev = atoi0();
+ noscale = 0;
+ if (nonumb)
+ goto e0;
+ flushi();
+ if (nxev >= NEV || nxev < 0 || evi >= EVLSZ) {
+ flusho();
+ ERROR "cannot do .ev %d", nxev WARN;
+ if (error)
+ done2(040);
+ else
+ edone(040);
+ return;
+ }
+ evlist[evi++] = ev;
+e1:
+ if (ev == nxev)
+ return;
+ ev = nxev;
+ envp = &env[ev];
+}
+
+void envcopy(Env *e1, Env *e2) /* copy env e2 to e1 */
+{
+ *e1 = *e2; /* rumor hath that this fails on some machines */
+}
+
+
+void caseel(void)
+{
+ if (--ifx < 0) {
+ ifx = 0;
+ iflist[0] = 0;
+ }
+ caseif1(2);
+}
+
+
+void caseie(void)
+{
+ if (ifx >= NIF) {
+ ERROR "if-else overflow." WARN;
+ ifx = 0;
+ edone(040);
+ }
+ caseif1(1);
+ ifx++;
+}
+
+
+void caseif(void)
+{
+ caseif1(0);
+}
+
+void caseif1(int x)
+{
+ extern int falsef;
+ int notflag, true;
+ Tchar i;
+
+ if (x == 2) {
+ notflag = 0;
+ true = iflist[ifx];
+ goto i1;
+ }
+ true = 0;
+ skip();
+ if ((cbits(i = getch())) == '!') {
+ notflag = 1;
+ } else {
+ notflag = 0;
+ ch = i;
+ }
+ ifnum++;
+ i = atoi0();
+ ifnum = 0;
+ if (!nonumb) {
+ if (i > 0)
+ true++;
+ goto i1;
+ }
+ i = getch();
+ switch (cbits(i)) {
+ case 'e':
+ if (!(numtabp[PN].val & 01))
+ true++;
+ break;
+ case 'o':
+ if (numtabp[PN].val & 01)
+ true++;
+ break;
+ case 'n':
+ if (NROFF)
+ true++;
+ break;
+ case 't':
+ if (TROFF)
+ true++;
+ break;
+ case ' ':
+ break;
+ default:
+ true = cmpstr(i);
+ }
+i1:
+ true ^= notflag;
+ if (x == 1)
+ iflist[ifx] = !true;
+ if (true) {
+i2:
+ while ((cbits(i = getch())) == ' ')
+ ;
+ if (cbits(i) == LEFT)
+ goto i2;
+ ch = i;
+ nflush++;
+ } else {
+ if (!nlflg) {
+ copyf++;
+ falsef++;
+ eatblk(0);
+ copyf--;
+ falsef--;
+ }
+ }
+}
+
+void eatblk(int inblk)
+{
+ int cnt, i;
+
+ cnt = 0;
+ do {
+ if (ch) {
+ i = cbits(ch);
+ ch = 0;
+ } else
+ i = cbits(getch0());
+ if (i == ESC)
+ cnt++;
+ else {
+ if (cnt == 1)
+ switch (i) {
+ case '{': i = LEFT; break;
+ case '}': i = RIGHT; break;
+ case '\n': i = 'x'; break;
+ }
+ cnt = 0;
+ }
+ if (i == LEFT) eatblk(1);
+ } while ((!inblk && (i != '\n')) || (inblk && (i != RIGHT)));
+ if (i == '\n') {
+ nlflg++;
+ if (ip == 0)
+ numtabp[CD].val++;
+ }
+}
+
+
+cmpstr(Tchar c)
+{
+ int j, delim;
+ Tchar i;
+ int val;
+ int savapts, savapts1, savfont, savfont1, savpts, savpts1;
+ Tchar string[1280];
+ Tchar *sp;
+
+ if (ismot(c))
+ return(0);
+ delim = cbits(c);
+ savapts = apts;
+ savapts1 = apts1;
+ savfont = font;
+ savfont1 = font1;
+ savpts = pts;
+ savpts1 = pts1;
+ sp = string;
+ while ((j = cbits(i = getch()))!=delim && j!='\n' && sp<&string[1280-1])
+ *sp++ = i;
+ if (sp >= string + 1280) {
+ ERROR "too-long string compare." WARN;
+ edone(0100);
+ }
+ if (nlflg) {
+ val = sp==string;
+ goto rtn;
+ }
+ *sp = 0;
+ apts = savapts;
+ apts1 = savapts1;
+ font = savfont;
+ font1 = savfont1;
+ pts = savpts;
+ pts1 = savpts1;
+ mchbits();
+ val = 1;
+ sp = string;
+ while ((j = cbits(i = getch())) != delim && j != '\n') {
+ if (*sp != i) {
+ eat(delim);
+ val = 0;
+ goto rtn;
+ }
+ sp++;
+ }
+ if (*sp)
+ val = 0;
+rtn:
+ apts = savapts;
+ apts1 = savapts1;
+ font = savfont;
+ font1 = savfont1;
+ pts = savpts;
+ pts1 = savpts1;
+ mchbits();
+ return(val);
+}
+
+
+void caserd(void)
+{
+
+ lgf++;
+ skip();
+ getname();
+ if (!iflg) {
+ if (quiet) {
+ if (NROFF) {
+ echo_off();
+ flusho();
+ }
+ fprintf(stderr, "\007"); /*bell*/
+ } else {
+ if (nextf[0]) {
+ fprintf(stderr, "%s:", nextf);
+ } else {
+ fprintf(stderr, "\007"); /*bell*/
+ }
+ }
+ }
+ collect();
+ tty++;
+ pushi(RD_OFFSET, PAIR('r','d'));
+}
+
+
+rdtty(void)
+{
+ char onechar;
+
+ onechar = 0;
+ if (read(0, &onechar, 1) == 1) {
+ if (onechar == '\n')
+ tty++;
+ else
+ tty = 1;
+ if (tty != 3)
+ return(onechar);
+ }
+ tty = 0;
+ if (NROFF && quiet)
+ echo_on();
+ return(0);
+}
+
+
+void caseec(void)
+{
+ eschar = chget('\\');
+}
+
+
+void caseeo(void)
+{
+ eschar = 0;
+}
+
+
+void caseta(void)
+{
+ int i, j, k;
+
+ tabtab[0] = nonumb = 0;
+ for (i = 0; ((i < (NTAB - 1)) && !nonumb); i++) {
+ if (skip())
+ break;
+ k = tabtab[max(i-1, 0)] & TABMASK;
+ if ((j = max(hnumb(&k), 0)) > TABMASK) {
+ ERROR "Tab too far away" WARN;
+ j = TABMASK;
+ }
+ tabtab[i] = j & TABMASK;
+ if (!nonumb)
+ switch (cbits(ch)) {
+ case 'C':
+ tabtab[i] |= CTAB;
+ break;
+ case 'R':
+ tabtab[i] |= RTAB;
+ break;
+ default: /*includes L*/
+ break;
+ }
+ nonumb = ch = 0;
+ }
+ if (!skip())
+ ERROR "Too many tab stops" WARN;
+ tabtab[i] = 0;
+}
+
+
+void casene(void)
+{
+ int i, j;
+
+ skip();
+ i = vnumb((int *)0);
+ if (nonumb)
+ i = lss;
+ if (dip == d && numtabp[NL].val == -1) {
+ newline(1);
+ return;
+ }
+ if (i > (j = findt1())) {
+ i = lss;
+ lss = j;
+ dip->nls = 0;
+ newline(0);
+ lss = i;
+ }
+}
+
+
+void casetr(void)
+{
+ int i, j;
+ Tchar k;
+
+ lgf++;
+ skip();
+ while ((i = cbits(k=getch())) != '\n') {
+ if (ismot(k))
+ return;
+ if (ismot(k = getch()))
+ return;
+ if ((j = cbits(k)) == '\n')
+ j = ' ';
+ trtab[i] = j;
+ }
+}
+
+
+void casecu(void)
+{
+ cu++;
+ caseul();
+}
+
+
+void caseul(void)
+{
+ int i;
+
+ noscale++;
+ skip();
+ i = max(atoi0(), 0);
+ if (nonumb)
+ i = 1;
+ if (ul && (i == 0)) {
+ font = sfont;
+ ul = cu = 0;
+ }
+ if (i) {
+ if (!ul) {
+ sfont = font;
+ font = ulfont;
+ }
+ ul = i;
+ }
+ noscale = 0;
+ mchbits();
+}
+
+
+void caseuf(void)
+{
+ int i, j;
+
+ if (skip() || !(i = getrq()) || i == 'S' || (j = findft(i)) == -1)
+ ulfont = ULFONT; /*default underline position*/
+ else
+ ulfont = j;
+ if (NROFF && ulfont == FT)
+ ulfont = ULFONT;
+}
+
+
+void caseit(void)
+{
+ int i;
+
+ lgf++;
+ it = itmac = 0;
+ noscale++;
+ skip();
+ i = atoi0();
+ skip();
+ if (!nonumb && (itmac = getrq()))
+ it = i;
+ noscale = 0;
+}
+
+
+void casemc(void)
+{
+ int i;
+
+ if (icf > 1)
+ ic = 0;
+ icf = 0;
+ if (skip())
+ return;
+ ic = getch();
+ icf = 1;
+ skip();
+ i = max(hnumb((int *)0), 0);
+ if (!nonumb)
+ ics = i;
+}
+
+
+void casemk(void)
+{
+ int i, j;
+
+ if (dip != d)
+ j = dip->dnl;
+ else
+ j = numtabp[NL].val;
+ if (skip()) {
+ dip->mkline = j;
+ return;
+ }
+ if ((i = getrq()) == 0)
+ return;
+ numtabp[findr(i)].val = j;
+}
+
+
+void casesv(void)
+{
+ int i;
+
+ skip();
+ if ((i = vnumb((int *)0)) < 0)
+ return;
+ if (nonumb)
+ i = 1;
+ sv += i;
+ caseos();
+}
+
+
+void caseos(void)
+{
+ int savlss;
+
+ if (sv <= findt1()) {
+ savlss = lss;
+ lss = sv;
+ newline(0);
+ lss = savlss;
+ sv = 0;
+ }
+}
+
+
+void casenm(void)
+{
+ int i;
+
+ lnmod = nn = 0;
+ if (skip())
+ return;
+ lnmod++;
+ noscale++;
+ i = inumb(&numtabp[LN].val);
+ if (!nonumb)
+ numtabp[LN].val = max(i, 0);
+ getnm(&ndf, 1);
+ getnm(&nms, 0);
+ getnm(&ni, 0);
+ getnm(&nmwid, 3); /* really kludgy! */
+ noscale = 0;
+ nmbits = chbits;
+}
+
+/*
+ * .nm relies on the fact that illegal args are skipped; don't warn
+ * for illegality of these
+ */
+void getnm(int *p, int min)
+{
+ int i;
+ int savtr = trace;
+
+ eat(' ');
+ if (skip())
+ return;
+ trace = 0;
+ i = atoi0();
+ if (nonumb)
+ return;
+ *p = max(i, min);
+ trace = savtr;
+}
+
+
+void casenn(void)
+{
+ noscale++;
+ skip();
+ nn = max(atoi0(), 1);
+ noscale = 0;
+}
+
+
+void caseab(void)
+{
+ casetm1(1, stderr);
+ done3(0);
+}
+
+
+/* nroff terminal handling has been pretty well excised */
+/* as part of the merge with troff. these are ghostly remnants, */
+/* called, but doing nothing. restore them at your peril. */
+
+
+void save_tty(void) /*save any tty settings that may be changed*/
+{
+}
+
+
+void restore_tty(void) /*restore tty settings from beginning*/
+{
+}
+
+
+void set_tty(void)
+{
+}
+
+
+void echo_off(void) /*turn off ECHO for .rd in "-q" mode*/
+{
+}
+
+
+void echo_on(void) /*restore ECHO after .rd in "-q" mode*/
+{
+}