blob: c65898cec0f5528cc29e8b773d23bd7bbc9d6377 [file] [log] [blame]
/*
* n1.c
*
* consume options, initialization, main loop,
* input routines, escape function calling
*/
#include <u.h>
#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;
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;
int
main(int argc, char *argv[])
{
char *p;
int j;
Tchar i;
char buf[100];
ifile = stdin; /* gcc */
ptid = stdout;
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--;
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)
{
time_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;
}
/*g2: */
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;
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(unsharp(p), "r")) == NULL) {
ERROR "cannot open file %s", p WARN;
nfo -= mflg;
done(02);
} else
strcpy(cfname[ifi],p);
nfo++;
return(0);
}
int
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.
*/
int
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;
}
int
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 = 0;
lgf++;
nextf[0] = 0;
if (skip() || !getname() || (fp = fopen(unsharp(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(unsharp(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((uchar)*a)) {
do
n = 10 * n + *a++ - '0';
while (isdigit((uchar)*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 ((long) i < 0 || cbits(j = getch0()) == RPT)
return;
while (i > 0 && pbp < &pbbuf[NC-3]) {
i--;
*pbp++ = j;
}
}