1 /* $MirOS: src/usr.bin/oldroff/nroff/n1.c,v 1.9 2006/11/04 03:02:53 tg Exp $ */
2 
3 /*-
4  * Copyright (c) 2002, 2003, 2004, 2005, 2006
5  *	Thorsten Glaser <tg@mirbsd.de>
6  *
7  * Licensee is hereby permitted to deal in this work without restric-
8  * tion, including unlimited rights to use, publicly perform, modify,
9  * merge, distribute, sell, give away or sublicence, provided all co-
10  * pyright notices above, these terms and the disclaimer are retained
11  * in all redistributions or reproduced in accompanying documentation
12  * or other materials provided with binary redistributions.
13  *
14  * Advertising materials mentioning features or use of this work must
15  * display the following acknowledgement:
16  *	This product includes material provided by Thorsten Glaser.
17  *
18  * Licensor offers the work "AS IS" and WITHOUT WARRANTY of any kind,
19  * express, or implied, to the maximum extent permitted by applicable
20  * law, without malicious intent or gross negligence; in no event may
21  * licensor, an author or contributor be held liable for any indirect
22  * or other damage, or direct damage except proven a consequence of a
23  * direct error of said person and intended use of this work, loss or
24  * other issues arising in any way out of its use, even if advised of
25  * the possibility of such damage or existence of a defect.
26  */
27 
28 /*-
29  * Copyright (c) 1979, 1980, 1981, 1986, 1988, 1990, 1991, 1992
30  *     The Regents of the University of California.
31  * Copyright (C) Caldera International Inc.  2001-2002.
32  * All rights reserved.
33  *
34  * Redistribution and use in source and binary forms,
35  * with or without modification, are permitted provided
36  * that the following conditions are met:
37  *
38  * Redistributions of source code and documentation must retain
39  * the above copyright notice, this list of conditions and the
40  * following disclaimer.  Redistributions in binary form must
41  * reproduce the above copyright notice, this list of conditions
42  * and the following disclaimer in the documentation and/or other
43  * materials provided with the distribution.
44  *
45  * All advertising materials mentioning features or use of this
46  * software must display the following acknowledgement:
47  *   This product includes software developed or owned by
48  *   Caldera International, Inc.
49  *
50  * Neither the name of Caldera International, Inc. nor the names
51  * of other contributors may be used to endorse or promote products
52  * derived from this software without specific prior written permission.
53  *
54  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
55  * INTERNATIONAL, INC. AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
56  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
57  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
58  * ARE DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE
59  * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR
60  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
61  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
62  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
63  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
64  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
65  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
66  */
67 
68 #include "tdef.h"
69 #include "pathnames.h"
70 #include <sys/types.h>
71 #include <sys/stat.h>
72 #include <stdlib.h>
73 #include <time.h>
74 #include <unistd.h>
75 extern
76 #include "d.h"
77 extern
78 #include "v.h"
79 #ifdef NROFF
80 extern
81 #include "tw.h"
82 #endif
83 #include "sdef.h"
84 #include <setjmp.h>
85 jmp_buf sjbuf;
86 #include <termios.h>
87 
88 __COPYRIGHT("Copyright (c) 2006 The MirOS Project.\n\
89  Copyright (c) 1991 The Regents of the University of California.\n\
90  All rights reserved.\n");
91 __SCCSID("@(#)n1.c	4.13 (Berkeley) 4/18/91");
92 __RCSID("$MirOS: src/usr.bin/oldroff/nroff/n1.c,v 1.9 2006/11/04 03:02:53 tg Exp $");
93 
94 /*
95 troff1.c
96 
97 consume options, initialization, main loop,
98 input routines, escape function calling
99 */
100 
101 int	inchar[LNSIZE], *pinchar = inchar;	/* XXX */
102 extern struct s *frame, *stk, *nxf;
103 extern struct s *ejl, *litlev;
104 extern filep ip;
105 extern filep offset;
106 extern filep nextb;
107 
108 
109 extern int stdi;
110 extern int waitf;
111 extern int nofeed;
112 extern int quiet;
113 extern int ptid;
114 extern int ascii;
115 extern int npn;
116 extern int xflg;
117 extern int stop;
118 extern char ibuf[IBUFSZ];
119 extern char xbuf[IBUFSZ];
120 extern char *ibufp;
121 extern char *xbufp;
122 extern char *eibuf;
123 extern char *xeibuf;
124 extern int *cp;
125 extern int *vlist;
126 extern int nx;
127 extern int mflg;
128 extern int ch;
129 extern int pto;
130 extern int pfrom;
131 extern int cps;
132 extern int chbits;
133 extern int ibf;
134 extern int ttyod;
135 extern struct termios ttys;
136 extern int iflg;
137 extern int init;
138 extern int rargc;
139 extern char **argp;
140 extern char trtab[256];
141 extern int lgf;
142 extern int copyf;
143 extern int eschar;
144 extern int ch0;
145 extern int cwidth;
146 extern int nlflg;
147 extern int *ap;
148 extern int donef;
149 extern int nflush;
150 extern int nchar;
151 extern int rchar;
152 extern int nfo;
153 extern int ifile;
154 extern int fc;
155 extern int padc;
156 extern int tabc;
157 extern int dotc;
158 extern int raw;
159 extern int tabtab[NTAB];
160 extern char nextf[];
161 extern int nfi;
162 #ifdef NROFF
163 extern char termtab[];
164 extern int tti;
165 #endif
166 extern int ifl[NSO];
167 extern int ifi;
168 extern int pendt;
169 extern int flss;
170 extern int fi;
171 extern int lg;
172 extern char ptname[];
173 extern int print;
174 extern int nonumb;
175 extern int pnlist[];
176 extern int *pnp;
177 extern int nb;
178 extern int trap;
179 extern int tflg;
180 extern int ejf;
181 extern int lit;
182 extern int cc;
183 extern int c2;
184 extern int spread;
185 extern int gflag;
186 extern int oline[];
187 extern int *olinep;
188 extern int dpn;
189 extern int noscale;
190 extern char *unlkp;
191 extern int pts;
192 extern int level;
193 extern int ttysave;
194 extern struct termios ttysavespace;
195 extern int tdelim;
196 extern int dotT;
197 extern int tabch, ldrch;
198 extern int eqflg;
199 extern int spflg;
200 extern no_out;
201 extern int hflg;
202 #ifndef NROFF
203 extern char codetab[];
204 extern int spbits;
205 #endif
206 extern int xxx;
207 extern char *__progname;
208 int stopmesg;
209 filep ipl[NSO];
210 long offl[NSO];
211 long ioff;
212 char *ttyp;
213 extern struct contab {
214 	int rq;
215 	union {
216 		int (*f)();
217 		unsigned mx;
218 	}x;
219 }contab[NM];
220 int ms[] = {31,28,31,30,31,30,31,31,30,31,30,31};
221 #ifndef NROFF
222 int acctf;
223 #endif
224 int groffmode = 0;
225 
main(argc,argv)226 main(argc,argv)
227 int argc;
228 char **argv;
229 {
230 	char *p, *q;
231 	register i, j;
232 	extern void catch(), fpecatch(), kcatch();
233 
234 	signal(SIGHUP,catch);
235 	if(signal(SIGINT,catch) == SIG_IGN){
236 		signal(SIGHUP,SIG_IGN);
237 		signal(SIGINT,SIG_IGN);
238 		signal(SIGQUIT,SIG_IGN);
239 	}
240 	signal(SIGFPE,fpecatch);
241 	signal(SIGPIPE,catch);
242 	signal(SIGTERM,kcatch);
243 	init1(argv[0][0]);
244 options:
245 	while(--argc > 0 && (++argv)[0][0]=='-')
246 		switch(argv[0][1]){
247 
248 		case 0:
249 			goto start;
250 		case 'i':
251 			stdi++;
252 			continue;
253 		case 'q':
254 			quiet++;
255 			if(tcgetattr(0, &ttys) >= 0) {
256 				ttysavespace = ttys;
257 				ttysave = 1;
258 			}
259 			continue;
260 		case 'n':
261 			npn = cnum(&argv[0][2]);
262 			continue;
263 		case 'p':
264 			xflg = 0;
265 			cps = cnum(&argv[0][2]);
266 			continue;
267 		case 'S':
268 			stopmesg++;
269 			continue;
270 		case 's':
271 			if(!(stop = cnum(&argv[0][2])))stop++;
272 			continue;
273 		case 'r':
274 			vlist[findr(argv[0][2])] = cnum(&argv[0][3]);
275 			continue;
276 		case 'm':
277 			p = &nextf[nfi];
278 			q = &argv[0][2];
279 			while((*p++ = *q++) != 0);
280 			if (access(nextf, 4) < 0) {
281 				char local[NS];
282 
283 				strlcpy(local, _PATH_LOCAL_TMAC, NS);
284 				strlcat(local, &argv[0][2], NS);
285 				if (access(local, 4) == 0)
286 					strlcpy(nextf, local, NS);
287 			}
288 			mflg++;
289 			continue;
290 		case 'o':
291 			getpn(&argv[0][2]);
292 			continue;
293 #ifdef NROFF
294 		case 'h':
295 			hflg++;
296 			continue;
297 		case 'z':
298 			no_out++;
299 			continue;
300 		case 'e':
301 			eqflg++;
302 			continue;
303 		case 'B':
304 			spflg = -1;
305 			continue;
306 		case 'T':
307 			p = &termtab[tti];
308 			q = &argv[0][2];
309 			if(!((*q) & 0177))continue;
310 			while((*p++ = *q++) != 0);
311 			dotT++;
312 			continue;
313 		case 'c':
314 			groffmode = 1;
315 			continue;
316 #endif
317 #ifndef NROFF
318 		case 'z':
319 			no_out++;
320 		case 'a':
321 			ascii = 1;
322 			nofeed++;
323 		case 't':
324 			ptid = 1;
325 			continue;
326 		case 'w':
327 			waitf = 1;
328 			continue;
329 		case 'f':
330 			nofeed++;
331 			continue;
332 		case 'x':
333 			xflg = 0;
334 			continue;
335 		case 'b':
336 			if(open(ptname,1) < 0)prstr("Busy.\n");
337 			else prstr("Available.\n");
338 			done3(0);
339 		case 'g':
340 			stop = ptid = gflag = 1;
341 			dpn = 0;
342 			continue;
343 		case 'F':
344 			{
345 			  extern char *fontfile;
346 			  fontfile = &argv[0][2];
347 			}
348 			continue;
349 #endif
350 		default:
351 			pto = cnum(&argv[0][1]);
352 			continue;
353 		}
354 
355 	if(argv[0][0] == '+'){
356 		pfrom = cnum(&argv[0][1]);
357 		print = 0;
358 		if(argc > 0)goto options;
359 	}
360 
361 start:
362 	argp = argv;
363 	rargc = argc;
364 	init2();
365 	setjmp(sjbuf);
366 loop:
367 	copyf = lgf = nb = nflush = nlflg = 0;
368 	if(ip && (rbf0(ip)==0) && ejf && (frame->pframe <= ejl)){
369 		nflush++;
370 		trap = 0;
371 		eject((struct s *)0);
372 		goto loop;
373 	}
374 	i = getch();
375 	if(pendt)goto lt;
376 	if(lit && (frame <= litlev)){
377 		lit--;
378 		goto lt;
379 	}
380 	if((j = (i & CMASK)) == XPAR){
381 		copyf++;
382 		tflg++;
383 		for(;(i & CMASK) != '\n';)pchar(i = getch());
384 		tflg = 0;
385 		copyf--;
386 		goto loop;
387 	}
388 	if((j == cc) || (j == c2)){
389 		if(j == c2)nb++;
390 		copyf++;
391 		while(((j=((i=getch()) & CMASK)) == ' ') ||
392 			(j == '\t'));
393 		ch = i;
394 		copyf--;
395 		control(getrq(),1);
396 		flushi();
397 		goto loop;
398 	}
399 lt:
400 	ch = i;
401 	text();
402 	goto loop;
403 }
404 void
catch()405 catch(){
406 /*
407 	prstr("Interrupt\n");
408 */
409 	done3(01);
410 }
411 void
fpecatch()412 fpecatch(){
413 	prstrfl("Floating Exception.\n");
414 	signal(SIGFPE,fpecatch);
415 }
416 void
kcatch()417 kcatch(){
418 	signal(SIGTERM,SIG_IGN);
419 	done3(01);
420 }
421 #ifndef NROFF
acctg()422 acctg() {
423 	static char *acct_file = _PATH_TRACCT;
424 	acctf = open(acct_file,1);
425 	setuid(getuid());
426 }
427 #endif
init1(a)428 init1(a)
429 char a;
430 {
431 	char *mktemp();
432 	static char tempname[] = "/tmp/taXXXXX";
433 	register i;
434 	register char *p = tempname;
435 
436 #ifndef NROFF
437 	acctg();/*open troff actg file while mode 4755*/
438 #endif
439 #ifdef UNSAFE
440 	p = mktemp(tempname);
441 	if(a == 'a')p = &p[5];
442 	if((close(creat(p, 0600))) < 0){
443 		prstr("Cannot create temp file.\n");
444 		exit(-1);
445 	}
446 	ibf = open(p, 2);
447 #else
448 	ibf = mkstemp(tempname);
449 #endif
450 	for(i=256; --i;)trtab[i]=i;
451 	trtab[UNPAD] = ' ';
452 	mchbits();
453 	if(a != 'a')unlkp = p;
454 }
init2()455 init2()
456 {
457 	register i,j;
458 	extern int block;
459 	extern char *setbrk();
460 
461 	ttyod = 2;
462 	if (((ttyp = ttyname(1)) != NULL) && ascii)
463 		mesg(0);
464 	iflg = isatty(0) ? 0 : 1;
465 	if(ascii)mesg(0);
466 
467 	if((!ptid) && (!waitf)){
468 		if((ptid = open(ptname,1)) < 0){
469 			prstr("Typesetter busy.\n");
470 			done3(-2);
471 		}
472 	}
473 	ptinit();
474 	for(i=NEV; i--;)write(ibf, (char *)&block, EVS*sizeof(int));
475 	olinep = oline;
476 	ibufp = eibuf = ibuf;
477 	v.hp = init = 0;
478 	pinchar = inchar;	/* XXX */
479 	ioff = 0;
480 	v.nl = -1;
481 	cvtime();
482 	frame = stk = (struct s *)setbrk(DELTA);
483 	dip = &d[0];
484 	nxf = frame + 1;
485 	nx = mflg;
486 }
cvtime()487 cvtime()
488 {
489 	extern time_t time();
490 	time_t t;
491 	register struct tm *tmp;
492 
493 	t = time((time_t *)0);
494 	tmp = localtime(&t);
495 	v.dy = tmp->tm_mday;
496 	v.dw = tmp->tm_wday + 1;
497 	v.yr = tmp->tm_year;
498 	v.mo = tmp->tm_mon + 1;
499 }
cnum(a)500 cnum(a)
501 char *a;
502 {
503 	register i;
504 
505 	ibufp = a;
506 	eibuf = (char *) MAXPTR;
507 	i = nr_atoi();
508 	ch = 0;
509 	return(i);
510 }
mesg(f)511 mesg(f)
512 int f;
513 {
514 	struct stat cb;
515 	static int mode = -1;
516 
517 	if (!f) {
518 		stat(ttyp,&cb);
519 		mode = (cb.st_mode);
520 		chmod(ttyp,mode & ~022);
521 	} else if (mode != -1)
522 		chmod(ttyp,mode);
523 }
prstrfl(s)524 prstrfl(s)
525 char *s;
526 {
527 	flusho();
528 	prstr(s);
529 }
prstr(s)530 prstr(s)
531 char *s;
532 {
533 	register i;
534 	register char *j;
535 
536 	j = s;
537 	for(i=0;*s;i++)s++;
538 	write(ttyod,j,i);
539 }
control(a,b)540 control(a,b)
541 int a,b;
542 {
543 	register i,j;
544 	extern filep boff();
545 
546 	i = a;
547 	if((i == 0) || ((j = findmn(i)) == -1))return(0);
548 	if(contab[j].rq & MMASK){
549 		nxf->nargs = 0;
550 		if(b)collect();
551 		flushi();
552 		return(pushi(((filep)contab[j].x.mx)<<BLKBITS));
553 	}else{
554 		if(!b)return(0);
555 		return((*contab[j].x.f)(0));
556 	}
557 }
558 
getrq()559 getrq(){
560 	register i,j;
561 
562 	if(((i=getach()) == 0) ||
563 	   ((j=getach()) == 0))goto rtn;
564 	i = PAIR(i,j);
565 rtn:
566 	return(i);
567 }
getch()568 getch(){
569 	register int i, j, k;
570 
571 	level++;
572 g0:
573 	if(ch){
574 		if(((i = ch) & CMASK) == '\n')nlflg++;
575 		ch = 0;
576 		level--;
577 		return(i);
578 	}
579 
580 	if(nlflg){
581 		level--;
582 		return('\n');
583 	}
584 
585 	if((k = (i = getch0()) & CMASK) != ESC){
586 		if(i & MOT)goto g2;
587 		if(k == FLSS){
588 			copyf++; raw++;
589 			i = getch0();
590 			if(!fi)flss = i;
591 			copyf--; raw--;
592 			goto g0;
593 		}
594 		if(k == RPT){
595 			setrpt();
596 			goto g0;
597 		}
598 		if(!copyf){
599 			if((k == 'f') && lg && !lgf){
600 				i = getlg(i);
601 				goto g2;
602 			}
603 			if((k == fc) || (k == tabch) || (k == ldrch)){
604 				if((i=setfield(k)) == 0)goto g0; else goto g2;
605 			}
606 			if(k == 010){
607 				i = makem(-width(' ' | chbits));
608 				goto g2;
609 			}
610 		}
611 		goto g2;
612 	}
613 	k = (j = getch0()) & CMASK;
614 	if(j & MOT){
615 		i = j;
616 		goto g2;
617 	}
618 /*
619 	if(k == tdelim){
620 		i = TDELIM;
621 		tdelim = IMP;
622 		goto g2;
623 	}
624 */
625 	switch(k){
626 
627 		case '\n':	/*concealed newline*/
628 			goto g0;
629 		case 'n':	/*number register*/
630 			setn();
631 			goto g0;
632 		case '*':	/*string indicator*/
633 			setstr();
634 			goto g0;
635 		case '$':	/*argument indicator*/
636 			seta();
637 			goto g0;
638 		case '{':	/*LEFT*/
639 			i = LEFT;
640 			goto gx;
641 		case '}':	/*RIGHT*/
642 			i = RIGHT;
643 			goto gx;
644 		case '"':	/*comment*/
645 			while(((i=getch0()) & CMASK ) != '\n');
646 			goto g2;
647 		case ESC:	/*double backslash*/
648 			i = eschar;
649 			goto gx;
650 		case 'e':	/*printable version of current eschar*/
651 			i = PRESC;
652 			goto gx;
653 		case ' ':	/*unpaddable space*/
654 			i = UNPAD;
655 			goto gx;
656 		case '|':	/*narrow space*/
657 			i = NARSP;
658 			goto gx;
659 		case '^':	/*half of narrow space*/
660 			i = HNSP;
661 			goto gx;
662 		case '\'':	/*\(aa*/
663 			i = 0222;
664 			goto gx;
665 		case '`':	/*\(ga*/
666 			i = 0223;
667 			goto gx;
668 		case '_':	/*\(ul*/
669 			i = 0224;
670 			goto gx;
671 		case '-':	/*current font minus*/
672 			i = 0210;
673 			goto gx;
674 		case '&':	/*filler*/
675 			i = FILLER;
676 			goto gx;
677 		case 'c':	/*to be continued*/
678 			i = CONT;
679 			goto gx;
680 		case ':':	/*lem's char*/
681 			i = COLON;
682 			goto gx;
683 		case '!':	/*transparent indicator*/
684 			i = XPAR;
685 			goto gx;
686 		case 't':	/*tab*/
687 			i = '\t';
688 			goto g2;
689 		case 'a':	/*leader (SOH)*/
690 			i = LEADER;
691 			goto g2;
692 		case '%':	/*ohc*/
693 			i = OHC;
694 			goto g2;
695 		case '.':	/*.*/
696 			i = '.';
697 		gx:
698 			i = (j & ~CMASK) | i;
699 			goto g2;
700 	}
701 	if(!copyf)
702 		switch(k){
703 
704 			case 'p':	/*spread*/
705 				spread++;
706 				goto g0;
707 			case '(':	/*special char name*/
708 				if((i=setch()) == 0)goto g0;
709 				break;
710 			case 's':	/*size indicator*/
711 				setps();
712 				goto g0;
713 			case 'f':	/*font indicator*/
714 				setfont(0);
715 				goto g0;
716 			case 'w':	/*width function*/
717 				setwd();
718 				goto g0;
719 			case 'v':	/*vert mot*/
720 				if(i = vmot())break;
721 				goto g0;
722 			case 'h': 	/*horiz mot*/
723 				if(i = hmot())break;
724 				goto g0;
725 			case 'z':	/*zero with char*/
726 				i = setz();
727 				break;
728 			case 'l':	/*hor line*/
729 				setline();
730 				goto g0;
731 			case 'L':	/*vert line*/
732 				setvline();
733 				goto g0;
734 			case 'b':	/*bracket*/
735 				setbra();
736 				goto g0;
737 			case 'o':	/*overstrike*/
738 				setov();
739 				goto g0;
740 			case 'k':	/*mark hor place*/
741 				if((i=findr(getsn())) == -1)goto g0;
742 				vlist[i] = v.hp = sumhp();	/* XXX */
743 				goto g0;
744 			case 'j':	/*mark output hor place*/
745 				if(!(i=getach()))goto g0;
746 				i = (i<<BYTE) | JREG;
747 				break;
748 			case '0':	/*number space*/
749 				i = makem(width('0' | chbits));
750 				break;
751 			case 'x':	/*extra line space*/
752 				if(i = xlss())break;
753 				goto g0;
754 			case 'u':	/*half em up*/
755 			case 'r':	/*full em up*/
756 			case 'd':	/*half em down*/
757 				i = sethl(k);
758 				break;
759 			default:
760 				i = j;
761 		}
762 	else{
763 		ch0 = j;
764 		i = eschar;
765 	}
766 g2:
767 	if((i & CMASK) == '\n'){
768 		nlflg++;
769 		v.hp = 0;
770 		pinchar = inchar;	/* XXX */
771 		if(ip == 0)v.cd++;
772 	}
773 	if(!--level){
774 		/* j = width(i); */
775 		/* v.hp += j; */
776 		/* cwidth = j; */
777 		if (pinchar >= inchar + LNSIZE) {	/* XXX */
778 			inchar[0] = makem(sumhp());
779 			pinchar = &inchar[1];
780 		}
781 		*pinchar++ = i;	/* XXX */
782 	}
783 	return(i);
784 }
785 
sumhp()786 sumhp()	/* XXX - add up widths in inchar array */
787 {
788 	register int n;
789 	register int *p;
790 
791 	n = 0;
792 	for (p = inchar; p < pinchar; p++)
793 		n += width(*p);
794 	return(n);
795 }
796 char ifilt[32] = {0,001,002,003,0,005,006,007,010,011,012};
getch0()797 getch0(){
798 	register int i, j;
799 
800 	if(ch0){i=ch0; ch0=0; return(i);}
801 	if(nchar){nchar--; return(rchar);}
802 
803 again:
804 	if(cp){
805 		if((i = *cp++) == 0){
806 			cp = 0;
807 			goto again;
808 		}
809 	}else if(ap){
810 		if((i = *ap++) == 0){
811 			ap = 0;
812 			goto again;
813 		}
814 	}else if(ip){
815 		if(ip == -1)i = rdtty();
816 		else i = rbf();
817 	}else{
818 		if(donef)done(0);
819 		if(nx || ((ibufp >= eibuf) && (eibuf != (char *) MAXPTR))){
820 			if(nfo)goto g1;
821 		g0:
822 			if(nextfile()){
823 				if(ip)goto again;
824 				if(ibufp < eibuf)goto g2;
825 			}
826 		g1:
827 			nx = 0;
828 			if((j=read(ifile,ibuf,IBUFSZ)) <= 0)goto g0;
829 			ibufp = ibuf;
830 			eibuf = ibuf + j;
831 			if(ip)goto again;
832 		}
833 	g2:
834 		i = *ibufp++ & 0177;
835 		ioff++;
836 		if(i >= 040)goto g4; else i = ifilt[i];
837 	}
838 	if(raw)return(i);
839 	if((j = i & CMASK) == IMP)goto again;
840 	if((i == 0) && !init)goto again;
841 g4:
842 	if((copyf == 0) && ((i & ~BMASK) == 0) && ((i & CMASK) < 0370))
843 #ifndef NROFF
844 		if(spbits && (i>31) && ((codetab[i-32] & 0200))) i |= spbits;
845 		else
846 #endif
847 		i |= chbits;
848 	if((i & CMASK) == eschar)i = (i & ~CMASK) | ESC;
849 	return(i);
850 }
nextfile()851 nextfile(){
852 	register char *p;
853 
854 n0:
855 	if(ifile)close(ifile);
856 	if(nx){
857 		p = nextf;
858 		if(*p != 0)goto n1;
859 	}
860 	if(ifi > 0){
861 		if(popf())goto n0; /*popf error*/
862 		return(1); /*popf ok*/
863 	}
864 	if(rargc-- <= 0)goto n2;
865 	p = (argp++)[0];
866 n1:
867 	if((p[0] == '-') && (p[1] == 0)){
868 		ifile = 0;
869 	}else if((ifile=open(p,0)) < 0){
870 		prstr("Cannot open ");
871 		prstr(p);
872 		prstr("\n");
873 		nfo -= mflg;
874 		done(02);
875 	}
876 	nfo++;
877 	v.cd = 0;
878 	ioff = 0;
879 	return(0);
880 n2:
881 	if((nfo -= mflg) && !stdi)done(0);
882 	nfo++;
883 	v.cd = ifile =  stdi = mflg = 0;
884 	ioff = 0;
885 	return(0);
886 }
popf()887 popf(){
888 	register i;
889 	register char *p, *q;
890 
891 	ioff = offl[--ifi];
892 	ip = ipl[ifi];
893 	if((ifile = ifl[ifi]) == 0){
894 		p = xbuf;
895 		q = ibuf;
896 		ibufp = xbufp;
897 		eibuf = xeibuf;
898 		while(q < eibuf)*q++ = *p++;
899 		return(0);
900 	}
901 	if((lseek(ifile,(long)(ioff & ~(IBUFSZ-1)),0) < 0) ||
902 	   ((i = read(ifile,ibuf,IBUFSZ)) < 0))return(1);
903 	eibuf = ibuf + i;
904 	ibufp = ibuf;
905 	if(ttyname(ifile) == (char *)0)
906 		if((ibufp = ibuf + (int)(ioff & (IBUFSZ-1)))  >= eibuf)return(1);
907 	return(0);
908 }
flushi()909 flushi(){
910 	if(nflush)return;
911 	ch = 0;
912 	if((ch0 & CMASK) == '\n')nlflg++;
913 	ch0 = 0;
914 	copyf++;
915 	while(!nlflg){
916 		if(donef && (frame == stk))break;
917 		getch();
918 	}
919 	copyf--;
920 	v.hp = 0;
921 	pinchar = inchar;	/* XXX */
922 }
getach()923 getach(){
924 	register i;
925 
926 	lgf++;
927 	if(((i = getch()) & MOT) ||
928 	    ((i&CMASK) == ' ') ||
929 	    ((i&CMASK) == '\n')||
930 	    (i & 0200)){
931 			ch = i;
932 			i = 0;
933 	}
934 	lgf--;
935 	return(i & 0177);
936 }
casenx()937 casenx(){
938 	lgf++;
939 	skip();
940 	getname();
941 	nx++;
942 	nextfile();
943 	nlflg++;
944 	ip = 0;
945 	ap = 0;
946 	nchar = pendt = 0;
947 	frame = stk;
948 	nxf = frame + 1;
949 }
getname()950 getname(){
951 	register int i, j, k;
952 
953 	lgf++;
954 	for(k=0; k < (NS-1); k++){
955 		if(((j=(i=getch()) & CMASK) <= ' ') ||
956 			(j > 0176))break;
957 		nextf[k] = j;
958 	}
959 	nextf[k] = 0;
960 	ch = i;
961 	lgf--;
962 	return(nextf[0]);
963 }
caseso()964 caseso(){
965 	register i;
966 	register char *p, *q;
967 
968 	lgf++;
969 	nextf[0] = 0;
970 	if(skip() || !getname() || ((i=open(nextf,0)) <0) || (ifi >= NSO)) {
971 		prstr("can't open file ");
972 		prstr(nextf);
973 		prstr("\n");
974 		done(02);
975 	}
976 	flushi();
977 	ifl[ifi] = ifile;
978 	ifile = i;
979 	offl[ifi] = ioff;
980 	ioff = 0;
981 	ipl[ifi] = ip;
982 	ip = 0;
983 	nx++;
984 	nflush++;
985 	if(!ifl[ifi++]){
986 		p = ibuf;
987 		q = xbuf;
988 		xbufp = ibufp;
989 		xeibuf = eibuf;
990 		while(p < eibuf)*q++ = *p++;
991 	}
992 }
993 
casecf()994 casecf(){	/* copy file without change */
995 	int fd, i, n;
996 	char buf[OBUFSZ];
997 
998 	flusho();
999 	lgf++;
1000 	nextf[0] = 0;
1001 	if(skip() || !getname() || ((fd=open(nextf,0)) <0) || (ifi >= NSO)) {
1002 		prstr("can't open file ");
1003 		prstr(nextf);
1004 		prstr("\n");
1005 		done(02);
1006 	}
1007 	while ((n = read(fd, buf, OBUFSZ)) > 0)
1008 		for (i = 0; i < n; i++)
1009 			oput(buf[i]);
1010 	flusho();
1011 	close(fd);
1012 }
getpn(a)1013 getpn(a)
1014 char *a;
1015 {
1016 	register i, neg;
1017 	long atoi1();
1018 
1019 	if((*a & 0177) == 0)return;
1020 	neg = 0;
1021 	ibufp = a;
1022 	eibuf = (char *) MAXPTR;
1023 	noscale++;
1024 	while((i = getch() & CMASK) != 0)switch(i){
1025 		case '+':
1026 		case ',':
1027 			continue;
1028 		case '-':
1029 			neg = MOT;
1030 			goto d2;
1031 		default:
1032 			ch = i;
1033 		d2:
1034 			i = atoi1();
1035 			if(nonumb)goto fini;
1036 			else{
1037 				*pnp++ = i | neg;
1038 				neg = 0;
1039 				if(pnp >= &pnlist[NPN-2]){
1040 					prstr("Too many page numbers\n");
1041 					done3(-3);
1042 				}
1043 			}
1044 		}
1045 fini:
1046 	if(neg)*pnp++ = -2;
1047 	*pnp = -1;
1048 	ch = noscale = print = 0;
1049 	pnp = pnlist;
1050 	if(*pnp != -1)chkpn();
1051 }
setrpt()1052 setrpt(){
1053 	register i, j;
1054 
1055 	copyf++;raw++;
1056 	i = getch0();
1057 	copyf--;raw--;
1058 	if((i < 0) ||
1059 	   (((j = getch0()) & CMASK) == RPT))return;
1060 	rchar = j;
1061 	nchar = i & BMASK;
1062 }
1063