123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- /*
- * n1.c
- *
- * consume options, initialization, main loop,
- * input routines, escape function calling
- */
- #include "tdef.h"
- #include "fns.h"
- #include "ext.h"
- #include "dwbinit.h"
- #include <setjmp.h>
- #include <time.h>
- char *Version = "March 11, 1994";
- #ifndef DWBVERSION
- #define DWBVERSION "???"
- #endif
- char *DWBfontdir = FONTDIR;
- char *DWBntermdir = NTERMDIR;
- char *DWBalthyphens = ALTHYPHENS;
- char *DWBhomedir = "";
- dwbinit dwbpaths[] = {
- &DWBfontdir, NULL, 0,
- &DWBntermdir, NULL, 0,
- &DWBalthyphens, NULL, 0,
- &DWBhomedir, NULL, 0,
- NULL, nextf, NS,
- NULL, NULL, 0
- };
- int TROFF = 1; /* assume we started in troff... */
- jmp_buf sjbuf;
- Offset ipl[NSO];
- static FILE *ifile = stdin;
- static FILE *ifl[NSO]; /* open input file pointers */
- char cfname[NSO+1][NS] = { "stdin" }; /* file name stack */
- int cfline[NSO]; /* input line count stack */
- char *progname; /* program name (troff or nroff) */
- int trace = 0; /* tracing mode: default off */
- int trace1 = 0;
- main(int argc, char *argv[])
- {
- char *p;
- int j;
- Tchar i;
- char buf[100];
- buf[0] = '\0'; /* make sure it's empty (silly 3b2) */
- progname = argv[0];
- if ((p = strrchr(progname, '/')) == NULL)
- p = progname;
- else
- p++;
- DWBinit(progname, dwbpaths);
- if (strcmp(p, "nroff") == 0)
- TROFF = 0;
- #ifdef UNICODE
- alphabet = 128; /* unicode for plan 9 */
- #endif /*UNICODE*/
- mnspace();
- nnspace();
- mrehash();
- nrehash();
- numtabp[NL].val = -1;
- while (--argc > 0 && (++argv)[0][0] == '-')
- switch (argv[0][1]) {
- case 'N': /* ought to be used first... */
- TROFF = 0;
- break;
- case 'd':
- fprintf(stderr, "troff/nroff version %s\n", Version);
- break;
- case 'F': /* switch font tables from default */
- if (argv[0][2] != '\0') {
- strcpy(termtab, &argv[0][2]);
- strcpy(fontdir, &argv[0][2]);
- } else {
- argv++; argc--;
- strcpy(termtab, argv[0]);
- strcpy(fontdir, argv[0]);
- }
- break;
- case 0:
- goto start;
- case 'i':
- stdi++;
- break;
- case 'n':
- npn = atoi(&argv[0][2]);
- break;
- case 'u': /* set emboldening amount */
- bdtab[3] = atoi(&argv[0][2]);
- if (bdtab[3] < 0 || bdtab[3] > 50)
- bdtab[3] = 0;
- break;
- case 's':
- if (!(stop = atoi(&argv[0][2])))
- stop++;
- break;
- case 'r':
- sprintf(buf + strlen(buf), ".nr %c %s\n",
- argv[0][2], &argv[0][3]);
- /* not yet cpushback(buf);*/
- /* dotnr(&argv[0][2], &argv[0][3]); */
- break;
- case 'm':
- if (mflg++ >= NMF) {
- ERROR "Too many macro packages: %s", argv[0] WARN;
- break;
- }
- strcpy(mfiles[nmfi], nextf);
- strcat(mfiles[nmfi++], &argv[0][2]);
- break;
- case 'o':
- getpn(&argv[0][2]);
- break;
- case 'T':
- strcpy(devname, &argv[0][2]);
- dotT++;
- break;
- case 'a':
- ascii = 1;
- break;
- case 'h':
- hflg++;
- break;
- case 'e':
- eqflg++;
- break;
- case 'q':
- quiet++;
- save_tty();
- break;
- case 'V':
- fprintf(stdout, "%croff: DWB %s\n",
- TROFF ? 't' : 'n', DWBVERSION);
- exit(0);
- case 't':
- if (argv[0][2] != '\0')
- trace = trace1 = argv[0][2];
- break; /* for the sake of compatibility */
- default:
- ERROR "unknown option %s", argv[0] WARN;
- done(02);
- }
- start:
- /*
- * cpushback maintains a LIFO, so push pack the -r arguments
- * in reverse order to maintain a FIFO in case someone did -rC1 -rC3
- */
- if (buf[0]) {
- char *p = buf;
- while(*p++)
- ;
- while(p > buf) {
- while(strncmp(p, ".nr", 3) != 0)
- p--;
- cpushback(p);
- *p-- = '\0';
- }
- }
- argp = argv;
- rargc = argc;
- nmfi = 0;
- init2();
- setjmp(sjbuf);
- loop:
- copyf = lgf = nb = nflush = nlflg = 0;
- if (ip && rbf0(ip) == 0 && ejf && frame->pframe <= ejl && dip == d) {
- nflush++;
- trap = 0;
- eject((Stack *)0);
- goto loop;
- }
- i = getch();
- if (pendt)
- goto Lt;
- if ((j = cbits(i)) == XPAR) {
- copyf++;
- tflg++;
- while (cbits(i) != '\n')
- pchar(i = getch());
- tflg = 0;
- copyf--; /* pointless */
- goto loop;
- }
- if (j == cc || j == c2) {
- if (j == c2)
- nb++;
- copyf++;
- while ((j = cbits(i = getch())) == ' ' || j == '\t')
- ;
- ch = i;
- copyf--;
- control(getrq(), 1);
- flushi();
- goto loop;
- }
- Lt:
- ch = i;
- text();
- if (nlflg)
- numtabp[HP].val = 0;
- goto loop;
- }
- void init2(void)
- {
- int i;
- char buf[100];
- for (i = NTRTAB; --i; )
- trtab[i] = i;
- trtab[UNPAD] = ' ';
- iflg = 0;
- obufp = obuf;
- if (TROFF)
- t_ptinit();
- else
- n_ptinit();
- mchbits();
- cvtime();
- numtabp[PID].val = getpid();
- numtabp[HP].val = init = 0;
- numtabp[NL].val = -1;
- nfo = 0;
- copyf = raw = 0;
- sprintf(buf, ".ds .T %s\n", devname);
- cpushback(buf);
- sprintf(buf, ".ds .P %s\n", DWBhomedir);
- cpushback(buf);
- numtabp[CD].val = -1; /* compensation */
- nx = mflg;
- frame = stk = (Stack *)setbrk(STACKSIZE);
- dip = &d[0];
- nxf = frame + 1;
- for (i = 1; i < NEV; i++) /* propagate the environment */
- envcopy(&env[i], &env[0]);
- for (i = 0; i < NEV; i++) {
- if ((env[i]._word._bufp = (Tchar *)calloc(WDSIZE, sizeof(Tchar))) == NULL) {
- ERROR "not enough room for word buffers" WARN;
- done2(1);
- }
- env[i]._word._size = WDSIZE;
- if ((env[i]._line._bufp = (Tchar *)calloc(LNSIZE, sizeof(Tchar))) == NULL) {
- ERROR "not enough room for line buffers" WARN;
- done2(1);
- }
- env[i]._line._size = LNSIZE;
- }
- if ((oline = (Tchar *)calloc(OLNSIZE, sizeof(Tchar))) == NULL) {
- ERROR "not enough room for line buffers" WARN;
- done2(1);
- }
- olinep = oline;
- olnsize = OLNSIZE;
- blockinit();
- }
- void cvtime(void)
- {
- int32_t tt;
- struct tm *ltime;
- time(&tt);
- ltime = localtime(&tt);
- numtabp[YR].val = ltime->tm_year % 100;
- numtabp[YR].fmt = 2;
- numtabp[MO].val = ltime->tm_mon + 1; /* troff uses 1..12 */
- numtabp[DY].val = ltime->tm_mday;
- numtabp[DW].val = ltime->tm_wday + 1; /* troff uses 1..7 */
- }
- char errbuf[200];
- void errprint(void) /* error message printer */
- {
- int savecd = numtabp[CD].val;
- if (!nlflg)
- numtabp[CD].val++;
- fprintf(stderr, "%s: ", progname);
- fputs(errbuf, stderr);
- if (cfname[ifi][0])
- fprintf(stderr, "; %s:%d", cfname[ifi], numtabp[CD].val);
- fputs("\n", stderr);
- if (cfname[ifi][0])
- stackdump();
- numtabp[CD].val = savecd;
- }
- int control(int a, int b)
- {
- int j, k;
- extern Contab *contabp;
- numerr.type = RQERR;
- numerr.req = a;
- if (a == 0 || (j = findmn(a)) == -1)
- return(0);
- if (contabp[j].f == 0) {
- if (trace & TRMAC)
- fprintf(stderr, "invoke macro %s\n", unpair(a));
- if (dip != d)
- for (k = dilev; k; k--)
- if (d[k].curd == a) {
- ERROR "diversion %s invokes itself during diversion",
- unpair(a) WARN;
- edone(0100);
- }
- nxf->nargs = 0;
- if (b)
- collect();
- flushi();
- return pushi(contabp[j].mx, a); /* BUG??? all that matters is 0/!0 */
- }
- if (b) {
- if (trace & TRREQ)
- fprintf(stderr, "invoke request %s\n", unpair(a));
- (*contabp[j].f)();
- }
- return(0);
- }
- void casept(void)
- {
- int i;
- noscale++;
- if (skip())
- i = trace1;
- else {
- i = max(inumb(&trace), 0);
- if (nonumb)
- i = trace1;
- }
- trace1 = trace;
- trace = i;
- noscale = 0;
- }
- int getrq(void)
- {
- int i, j;
- if ((i = getach()) == 0 || (j = getach()) == 0)
- goto rtn;
- i = PAIR(i, j);
- rtn:
- return(i);
- }
- /*
- * table encodes some special characters, to speed up tests
- * in getch, viz FLSS, RPT, f, \b, \n, fc, tabch, ldrch
- */
- char gchtab[NCHARS] = {
- 000,004,000,000,010,000,000,000, /* fc, ldr */
- 001,002,001,000,001,000,000,000, /* \b, tab, nl, RPT */
- 000,000,000,000,000,000,000,000,
- 000,001,000,001,000,000,000,000, /* FLSS, ESC */
- 000,000,000,000,000,000,000,000,
- 000,000,000,000,000,000,000,000,
- 000,000,000,000,000,000,000,000,
- 000,000,000,000,000,000,000,000,
- 000,000,000,000,000,000,000,000,
- 000,000,000,000,000,000,000,000,
- 000,000,000,000,000,000,000,000,
- 000,000,000,000,000,000,000,000,
- 000,000,000,000,000,000,001,000, /* f */
- 000,000,000,000,000,000,000,000,
- 000,000,000,000,000,000,000,000,
- 000,000,000,000,000,000,000,000,
- };
- int realcbits(Tchar c) /* return character bits, or MOTCH if motion */
- {
- if (ismot(c))
- return MOTCH;
- else
- return c & 0xFFFF;
- }
- Tchar getch(void)
- {
- int k;
- Tchar i, j;
- g0:
- if (ch) {
- i = ch;
- if (cbits(i) == '\n')
- nlflg++;
- ch = 0;
- return(i);
- }
- if (nlflg)
- return('\n');
- i = getch0();
- if (ismot(i))
- return(i);
- k = cbits(i);
- if (k >= sizeof(gchtab)/sizeof(gchtab[0]) || gchtab[k] == 0) /* nothing special */
- return(i);
- if (k != ESC) {
- if (k == '\n') {
- nlflg++;
- if (ip == 0)
- numtabp[CD].val++; /* line number */
- return(k);
- }
- if (k == FLSS) {
- copyf++;
- raw++;
- i = getch0();
- if (!fi)
- flss = i;
- copyf--;
- raw--;
- goto g0;
- }
- if (k == RPT) {
- setrpt();
- goto g0;
- }
- if (!copyf) {
- if (k == 'f' && lg && !lgf) {
- i = getlg(i);
- return(i);
- }
- if (k == fc || k == tabch || k == ldrch) {
- if ((i = setfield(k)) == 0)
- goto g0;
- else
- return(i);
- }
- if (k == '\b') {
- i = makem(-width(' ' | chbits));
- return(i);
- }
- }
- return(i);
- }
- k = cbits(j = getch0());
- if (ismot(j))
- return(j);
- switch (k) {
- case 'n': /* number register */
- setn();
- goto g0;
- case '$': /* argument indicator */
- seta();
- goto g0;
- case '*': /* string indicator */
- setstr();
- goto g0;
- case '{': /* LEFT */
- i = LEFT;
- goto gx;
- case '}': /* RIGHT */
- i = RIGHT;
- goto gx;
- case '"': /* comment */
- while (cbits(i = getch0()) != '\n')
- ;
- if (ip == 0)
- numtabp[CD].val++; /* line number */
- nlflg++;
- return(i);
- /* experiment: put it here instead of copy mode */
- case '(': /* special char name \(xx */
- case 'C': /* \C'...' */
- if ((i = setch(k)) == 0)
- goto g0;
- goto gx;
- case ESC: /* double backslash */
- i = eschar;
- goto gx;
- case 'e': /* printable version of current eschar */
- i = PRESC;
- goto gx;
- case '\n': /* concealed newline */
- numtabp[CD].val++;
- goto g0;
- case ' ': /* unpaddable space */
- i = UNPAD;
- goto gx;
- case '\'': /* \(aa */
- i = ACUTE;
- goto gx;
- case '`': /* \(ga */
- i = GRAVE;
- goto gx;
- case '_': /* \(ul */
- i = UNDERLINE;
- goto gx;
- case '-': /* current font minus */
- i = MINUS;
- goto gx;
- case '&': /* filler */
- i = FILLER;
- goto gx;
- case 'c': /* to be continued */
- i = CONT;
- goto gx;
- case '!': /* transparent indicator */
- i = XPAR;
- goto gx;
- case 't': /* tab */
- i = '\t';
- return(i);
- case 'a': /* leader (SOH) */
- /* old: *pbp++ = LEADER; goto g0; */
- i = LEADER;
- return i;
- case '%': /* ohc */
- i = OHC;
- return(i);
- case 'g': /* return format of a number register */
- setaf(); /* should this really be in copy mode??? */
- goto g0;
- case '.': /* . */
- i = '.';
- gx:
- setsfbits(i, sfbits(j));
- return(i);
- }
- if (copyf) {
- *pbp++ = j;
- return(eschar);
- }
- switch (k) {
- case 'f': /* font indicator */
- setfont(0);
- goto g0;
- case 's': /* size indicator */
- setps();
- goto g0;
- case 'v': /* vert mot */
- numerr.type = numerr.escarg = 0; numerr.esc = k;
- if (i = vmot()) {
- return(i);
- }
- goto g0;
- case 'h': /* horiz mot */
- numerr.type = numerr.escarg = 0; numerr.esc = k;
- if (i = hmot())
- return(i);
- goto g0;
- case '|': /* narrow space */
- if (NROFF)
- goto g0;
- return(makem((int)(EM)/6));
- case '^': /* half narrow space */
- if (NROFF)
- goto g0;
- return(makem((int)(EM)/12));
- case 'w': /* width function */
- setwd();
- goto g0;
- case 'p': /* spread */
- spread++;
- goto g0;
- case 'N': /* absolute character number */
- numerr.type = numerr.escarg = 0; numerr.esc = k;
- if ((i = setabs()) == 0)
- goto g0;
- return i;
- case 'H': /* character height */
- numerr.type = numerr.escarg = 0; numerr.esc = k;
- return(setht());
- case 'S': /* slant */
- numerr.type = numerr.escarg = 0; numerr.esc = k;
- return(setslant());
- case 'z': /* zero with char */
- return(setz());
- case 'l': /* hor line */
- numerr.type = numerr.escarg = 0; numerr.esc = k;
- setline();
- goto g0;
- case 'L': /* vert line */
- numerr.type = numerr.escarg = 0; numerr.esc = k;
- setvline();
- goto g0;
- case 'D': /* drawing function */
- numerr.type = numerr.escarg = 0; numerr.esc = k;
- setdraw();
- goto g0;
- case 'X': /* \X'...' for copy through */
- setxon();
- goto g0;
- case 'b': /* bracket */
- setbra();
- goto g0;
- case 'o': /* overstrike */
- setov();
- goto g0;
- case 'k': /* mark hor place */
- if ((k = findr(getsn())) != -1) {
- numtabp[k].val = numtabp[HP].val;
- }
- goto g0;
- case '0': /* number space */
- return(makem(width('0' | chbits)));
- case 'x': /* extra line space */
- numerr.type = numerr.escarg = 0; numerr.esc = k;
- if (i = xlss())
- return(i);
- goto g0;
- case 'u': /* half em up */
- case 'r': /* full em up */
- case 'd': /* half em down */
- return(sethl(k));
- default:
- return(j);
- }
- /* NOTREACHED */
- }
- void setxon(void) /* \X'...' for copy through */
- {
- Tchar xbuf[NC];
- Tchar *i;
- Tchar c;
- int delim, k;
- if (ismot(c = getch()))
- return;
- delim = cbits(c);
- i = xbuf;
- *i++ = XON | chbits;
- while ((k = cbits(c = getch())) != delim && k != '\n' && i < xbuf+NC-1) {
- if (k == ' ')
- setcbits(c, WORDSP);
- *i++ = c | ZBIT;
- }
- *i++ = XOFF | chbits;
- *i = 0;
- pushback(xbuf);
- }
- char ifilt[32] = { 0, 001, 002, 003, 0, 005, 006, 007, 010, 011, 012 };
- Tchar getch0(void)
- {
- Tchar i;
- again:
- if (pbp > lastpbp)
- i = *--pbp;
- else if (ip) {
- /* i = rbf(); */
- i = rbf0(ip);
- if (i == 0)
- i = rbf();
- else {
- ++ip;
- if (pastend(ip)) {
- --ip;
- rbf();
- }
- }
- } else {
- if (donef || ndone)
- done(0);
- if (nx || 1) { /* BUG: was ibufp >= eibuf, so EOF test is wrong */
- if (nfo < 0)
- ERROR "in getch0, nfo = %d", nfo WARN;
- if (nfo == 0) {
- g0:
- if (nextfile()) {
- if (ip)
- goto again;
- }
- }
- nx = 0;
- #ifdef UNICODE
- if (MB_CUR_MAX > 1)
- i = get1ch(ifile);
- else
- #endif /*UNICODE*/
- i = getc(ifile);
- if (i == EOF)
- goto g0;
- if (ip)
- goto again;
- }
- if (i >= 040) /* zapped: && i < 0177 */
- goto g4;
- i = ifilt[i];
- }
- if (cbits(i) == IMP && !raw)
- goto again;
- if (i == 0 && !init && !raw) { /* zapped: || i == 0177 */
- goto again;
- }
- g4:
- if (ismot(i))
- return i;
- if (copyf == 0 && sfbits(i) == 0)
- i |= chbits;
- if (cbits(i) == eschar && !raw)
- setcbits(i, ESC);
- return(i);
- }
- #ifdef UNICODE
- Tchar get1ch(FILE *fp) /* get one "character" from input, figure out what alphabet */
- {
- wchar_t wc;
- char buf[100], *p;
- int i, n, c;
- n = c = 0;
- for (i = 0, p = buf; i < MB_CUR_MAX; i++) {
- if ((c = getc(fp)) == EOF)
- return c;
- *p++ = c;
- if ((n = mbtowc(&wc, buf, p-buf)) >= 0)
- break;
- }
- if (n == 1) /* real ascii, presumably */
- return wc;
- if (n == 0)
- return p[-1]; /* illegal, but what else to do? */
- if (c == EOF)
- return EOF;
- *p = 0;
- return chadd(buf, MBchar, Install); /* add name even if haven't seen it */
- }
- #endif /*UNICODE*/
- void pushback(Tchar *b)
- {
- Tchar *ob = b;
- while (*b++)
- ;
- b--;
- while (b > ob && pbp < &pbbuf[NC-3])
- *pbp++ = *--b;
- if (pbp >= &pbbuf[NC-3]) {
- ERROR "pushback overflow" WARN;
- done(2);
- }
- }
- void cpushback(char *b)
- {
- char *ob = b;
- while (*b++)
- ;
- b--;
- while (b > ob && pbp < &pbbuf[NC-3])
- *pbp++ = *--b;
- if (pbp >= &pbbuf[NC-3]) {
- ERROR "cpushback overflow" WARN;
- done(2);
- }
- }
- int nextfile(void)
- {
- char *p;
- n0:
- if (ifile != stdin)
- fclose(ifile);
- if (ifi > 0 && !nx) {
- if (popf())
- goto n0; /* popf error */
- return(1); /* popf ok */
- }
- if (nx || nmfi < mflg) {
- p = mfiles[nmfi++];
- if (*p != 0)
- goto n1;
- }
- if (rargc-- <= 0) {
- if ((nfo -= mflg) && !stdi) {
- done(0);
- }
- nfo++;
- numtabp[CD].val = stdi = mflg = 0;
- ifile = stdin;
- strcpy(cfname[ifi], "stdin");
- return(0);
- }
- p = (argp++)[0];
- if (rargc >= 0)
- cfname[ifi][0] = 0;
- n1:
- numtabp[CD].val = 0;
- if (p[0] == '-' && p[1] == 0) {
- ifile = stdin;
- strcpy(cfname[ifi], "stdin");
- } else if ((ifile = fopen(p, "r")) == NULL) {
- ERROR "cannot open file %s", p WARN;
- nfo -= mflg;
- done(02);
- } else
- strcpy(cfname[ifi],p);
- nfo++;
- return(0);
- }
- popf(void)
- {
- --ifi;
- if (ifi < 0) {
- ERROR "popf went negative" WARN;
- return 1;
- }
- numtabp[CD].val = cfline[ifi]; /* restore line counter */
- ip = ipl[ifi]; /* input pointer */
- ifile = ifl[ifi]; /* input FILE * */
- return(0);
- }
- void flushi(void)
- {
- if (nflush)
- return;
- ch = 0;
- copyf++;
- while (!nlflg) {
- if (donef && frame == stk)
- break;
- getch();
- }
- copyf--;
- }
- /*
- * return 16-bit, ascii/alphabetic character, ignore chars with more bits,
- * (internal names), spaces and special cookies (below 040).
- * Leave STX ETX ENQ ACK and BELL in to maintain compatibility with v7 troff.
- */
- getach(void)
- {
- Tchar i;
- int j;
- lgf++;
- j = cbits(i = getch());
- if (ismot(i)
- || j > SHORTMASK
- || (j <= 040 && j != 002 /*STX*/
- && j != 003 /*ETX*/
- && j != 005 /*ENQ*/
- && j != 006 /*ACK*/
- && j != 007)) { /*BELL*/
- ch = i;
- j = 0;
- }
- lgf--;
- return j;
- }
- void casenx(void)
- {
- lgf++;
- skip();
- getname();
- nx++;
- if (nmfi > 0)
- nmfi--;
- strcpy(mfiles[nmfi], nextf);
- nextfile();
- nlflg++;
- ip = 0;
- pendt = 0;
- frame = stk;
- nxf = frame + 1;
- }
- getname(void)
- {
- int j, k;
- lgf++;
- for (k = 0; k < NS - 1; k++) {
- j = getach();
- if (!j)
- break;
- nextf[k] = j;
- }
- nextf[k] = 0;
- lgf--;
- return(nextf[0]);
- }
- void caseso(void)
- {
- FILE *fp;
- lgf++;
- nextf[0] = 0;
- fp = NULL;
- if (skip() || !getname() || (fp = fopen(nextf, "r")) == NULL || ifi >= NSO) {
- ERROR "can't open file %s", nextf WARN;
- done(02);
- }
- strcpy(cfname[ifi+1], nextf);
- cfline[ifi] = numtabp[CD].val; /*hold line counter*/
- numtabp[CD].val = 0;
- flushi();
- ifl[ifi] = ifile;
- ifile = fp;
- ipl[ifi] = ip;
- ip = 0;
- nx++;
- nflush++;
- ifi++;
- }
- void caself(void) /* set line number and file */
- {
- int n;
- if (skip())
- return;
- n = atoi0();
- if (!nonumb)
- cfline[ifi] = numtabp[CD].val = n - 1;
- if (!skip())
- if (getname()) { /* eats '\n' ? */
- strcpy(cfname[ifi], nextf);
- if (!nonumb)
- numtabp[CD].val--;
- }
- }
- void cpout(FILE *fin, char *token)
- {
- int n;
- char buf[1024];
- if (token) { /* BUG: There should be no NULL bytes in input */
- char *newl = buf;
- while ((fgets(buf, sizeof buf, fin)) != NULL) {
- if (newl) {
- numtabp[CD].val++; /* line number */
- if (strcmp(token, buf) == 0)
- return;
- }
- newl = strchr(buf, '\n');
- fputs(buf, ptid);
- }
- } else {
- while ((n = fread(buf, sizeof *buf, sizeof buf, fin)) > 0)
- fwrite(buf, n, 1, ptid);
- fclose(fin);
- }
- }
- void casecf(void)
- { /* copy file without change */
- FILE *fd;
- char *eof, *p;
- extern int hpos, esc, po;
- /* this may not make much sense in nroff... */
- lgf++;
- nextf[0] = 0;
- if (!skip() && getname()) {
- if (strncmp("<<", nextf, 2) != 0) {
- if ((fd = fopen(nextf, "r")) == NULL) {
- ERROR "can't open file %s", nextf WARN;
- done(02);
- }
- eof = (char *) NULL;
- } else { /* current file */
- if (pbp > lastpbp || ip) {
- ERROR "casecf: not reading from file" WARN;
- done(02);
- }
- eof = &nextf[2];
- if (!*eof) {
- ERROR "casecf: missing end of input token" WARN;
- done(02);
- }
- p = eof;
- while(*++p)
- ;
- *p++ = '\n';
- *p = 0;
- fd = ifile;
- }
- } else {
- ERROR "casecf: no argument" WARN;
- lgf--;
- return;
- }
- lgf--;
- /* make it into a clean state, be sure that everything is out */
- tbreak();
- hpos = po;
- esc = 0;
- ptesc(); /* to left margin */
- esc = un;
- ptesc();
- ptlead();
- ptps();
- ptfont();
- flusho();
- cpout(fd, eof);
- ptps();
- ptfont();
- }
- void getline(char *s, int n) /* get rest of input line into s */
- {
- int i;
- lgf++;
- copyf++;
- skip();
- for (i = 0; i < n-1; i++)
- if ((s[i] = cbits(getch())) == '\n' || s[i] == RIGHT)
- break;
- s[i] = 0;
- copyf--;
- lgf--;
- }
- void casesy(void) /* call system */
- {
- char sybuf[NTM];
- getline(sybuf, NTM);
- system(sybuf);
- }
- void getpn(char *a)
- {
- int n, neg;
- if (*a == 0)
- return;
- neg = 0;
- for ( ; *a; a++)
- switch (*a) {
- case '+':
- case ',':
- continue;
- case '-':
- neg = 1;
- continue;
- default:
- n = 0;
- if (isdigit(*a)) {
- do
- n = 10 * n + *a++ - '0';
- while (isdigit(*a));
- a--;
- } else
- n = 9999;
- *pnp++ = neg ? -n : n;
- neg = 0;
- if (pnp >= &pnlist[NPN-2]) {
- ERROR "too many page numbers" WARN;
- done3(-3);
- }
- }
- if (neg)
- *pnp++ = -9999;
- *pnp = -INT_MAX;
- print = 0;
- pnp = pnlist;
- if (*pnp != -INT_MAX)
- chkpn();
- }
- void setrpt(void)
- {
- Tchar i, j;
- copyf++;
- raw++;
- i = getch0();
- copyf--;
- raw--;
- if ((int32_t) i < 0 || cbits(j = getch0()) == RPT)
- return;
- while (i > 0 && pbp < &pbbuf[NC-3]) {
- i--;
- *pbp++ = j;
- }
- }
|