1 #include <ctype.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <sys/time.h>
5 #include "tdef.h"
6 extern
7 #include "d.h"
8 extern
9 #include "v.h"
10 #ifdef NROFF
11 extern
12 #include "tw.h"
13 #endif
14 #include "s.h"
15 #include <setjmp.h>
16 jmp_buf sjbuf;
17 #include	<sgtty.h>
18 /*
19 troff1.c
20 
21 consume options, initialization, main loop,
22 input routines, escape function calling
23 */
24 
25 #include "ext.h"
26 
27 char	*sprintf();
28 char	*getenv();
29 tchar	inchar[LNSIZE], *pinchar = inchar;	/* XXX */
30 filep ipl[NSO];
31 long	offl[NSO];
32 long	ioff;
33 char	*ttyp;
34 extern struct contab {
35 	int	rq;
36 	union {
37 		int	(*f)();
38 		unsigned	mx;
39 	} x;
40 } contab[NM];
41 
42 main(argc, argv)
43 int	argc;
44 char	**argv;
45 {
46 	register char	*p, *q;
47 	register j;
48 	tchar i;
49 	extern catch(), kcatch();
50 	int	oargc;
51 	char	**oargv;
52 
53 	signal(SIGHUP, catch);
54 	if (signal(SIGINT, catch) == SIG_IGN) {
55 		signal(SIGHUP, SIG_IGN);
56 		signal(SIGINT, SIG_IGN);
57 		signal(SIGQUIT, SIG_IGN);
58 	}
59 	signal(SIGPIPE, catch);
60 	signal(SIGTERM, kcatch);
61 	oargc = argc;
62 	oargv = argv;
63 	if (p = getenv("PRINTER")) strcpy(devname, p);
64 	if (p = getenv("TYPESETTER")) strcpy(devname, p);
65 	for (nfi = 0, p = nextf; *p; p++) nfi++;
66 	init0();
67 options:
68 	while (--argc > 0 && (++argv)[0][0] == '-')
69 		switch (argv[0][1]) {
70 
71 		case 'F':	/* switch font tables from default */
72 			if (argv[0][2] != '\0') {
73 				strcpy(termtab, &argv[0][2]);
74 				strcpy(fontfile, &argv[0][2]);
75 			} else {
76 				argv++; argc--;
77 				strcpy(termtab, argv[0]);
78 				strcpy(fontfile, argv[0]);
79 			}
80 			continue;
81 		case 0:
82 			goto start;
83 		case 'i':
84 			stdi++;
85 			continue;
86 		case 'q':
87 			quiet++;
88 			if (gtty(0, &ttys) >= 0)
89 				ttysave = ttys.sg_flags;
90 			continue;
91 		case 'n':
92 			npn = ctoi(&argv[0][2]);
93 			continue;
94 		case 'u':	/* set emboldening amount */
95 			bdtab[3] = ctoi(&argv[0][2]);
96 			if (bdtab[3] < 0 || bdtab[3] > 50)
97 				bdtab[3] = 0;
98 			continue;
99 		case 's':
100 			if (!(stop = ctoi(&argv[0][2])))
101 				stop++;
102 			continue;
103 		case 'r':
104 			eibuf = sprintf(ibuf+strlen(ibuf), ".nr %c %s\n",
105 				argv[0][2], &argv[0][3]);
106 			continue;
107 		case 'm':
108 			p = &nextf[nfi];
109 			q = &argv[0][2];
110 			while ((*p++ = *q++) != 0)
111 				;
112 			mflg++;
113 			continue;
114 		case 'o':
115 			getpn(&argv[0][2]);
116 			continue;
117 #ifdef NROFF
118 		case 'h':
119 			hflg++;
120 			continue;
121 		case 'z':
122 			no_out++;
123 			continue;
124 		case 'e':
125 			eqflg++;
126 			continue;
127 		case 'T':
128 			strcat(termtab, &argv[0][2]);
129 			dotT++;
130 			continue;
131 #endif
132 #ifndef NROFF
133 		case 'P':
134 		case 'T':
135 			strcpy(devname, &argv[0][2]);
136 			dotT++;
137 			continue;
138 		case 'z':
139 			no_out++;
140 		case 'a':
141 			ascii = 1;
142 			nofeed++;
143 		case 't':
144 			ptid = 1;
145 			continue;
146 		case 'f':
147 			nofeed++;
148 			continue;
149 #endif
150 		default:
151 			fprintf(stderr, "troff: unknown option %s\n", argv[0]);
152 			done(02);
153 		}
154 
155 start:
156 	init1(oargv[0][0]);
157 	argp = argv;
158 	rargc = argc;
159 	init2();
160 	setjmp(sjbuf);
161 loop:
162 	copyf = lgf = nb = nflush = nlflg = 0;
163 	if (ip && rbf0(ip) == 0 && ejf && frame->pframe <= ejl) {
164 		nflush++;
165 		trap = 0;
166 		eject((struct s *)0);
167 		goto loop;
168 	}
169 	i = getch();
170 	if (pendt)
171 		goto lt;
172 	if ((j = cbits(i)) == XPAR) {
173 		copyf++;
174 		tflg++;
175 		while (cbits(i) != '\n')
176 			pchar(i = getch());
177 		tflg = 0;
178 		copyf--;
179 		goto loop;
180 	}
181 	if (j == cc || j == c2) {
182 		if (j == c2)
183 			nb++;
184 		copyf++;
185 		while ((j = cbits(i = getch())) == ' ' || j == '\t')
186 			;
187 		ch = i;
188 		copyf--;
189 		control(getrq(), 1);
190 		flushi();
191 		goto loop;
192 	}
193 lt:
194 	ch = i;
195 	text();
196 	goto loop;
197 }
198 
199 
200 catch()
201 {
202 	done3(01);
203 }
204 
205 
206 kcatch()
207 {
208 	signal(SIGTERM, SIG_IGN);
209 	done3(01);
210 }
211 
212 
213 init0()
214 {
215 	eibuf = ibufp = ibuf;
216 	ibuf[0] = 0;
217 	v.nl = -1;
218 }
219 
220 
221 init1(a)
222 char	a;
223 {
224 	register char	*p;
225 	char	*mktemp();
226 	register i;
227 
228 	p = mktemp("/usr/tmp/trtmpXXXXX");
229 	if (a == 'a')
230 		p = &p[9];
231 	if ((close(creat(p, 0600))) < 0) {
232 		fprintf(stderr, "troff: cannot create temp file.\n");
233 		exit(-1);
234 	}
235 	ibf = open(p, 2);
236 	unlkp = p;
237 	for (i = NTRTAB; --i; )
238 		trtab[i] = i;
239 	trtab[UNPAD] = ' ';
240 }
241 
242 
243 init2()
244 {
245 	register i, j;
246 	register char *p;
247 	tchar *t;
248 	extern int	block;
249 	extern char	*setbrk();
250 	extern char	*ttyname();
251 
252 	ttyod = 2;
253 	if ((ttyp=ttyname(j=0)) != 0 || (ttyp=ttyname(j=1)) != 0 || (ttyp=ttyname(j=2)) != 0)
254 		;
255 	else
256 		ttyp = "notty";
257 	iflg = j;
258 	if (ascii)
259 		mesg(0);
260 	obufp = obuf;
261 	ptinit();
262 	mchbits();
263 	cvtime();
264 	v.pid = getpid();
265 	olinep = oline;
266 	ioff = 0;
267 	v.hp = init = 0;
268 	pinchar = inchar;	/* XXX */
269 	v.nl = -1;
270 	nfo = 0;
271 	ifile = 0;
272 	copyf = raw = 0;
273 	level = 0;
274 	eibuf = sprintf(ibuf+strlen(ibuf), ".ds .T %s\n", devname);
275 	for (p=ibuf, t=cbuf; *t++ = *p++; )
276 		;
277 	cp = cbuf;
278 	eibuf = ibuf;
279 	ibufp = ibuf;
280 	nx = mflg;
281 	frame = stk = (struct s *)setbrk(DELTA);
282 	dip = &d[0];
283 	nxf = frame + 1;
284 	for (i = NEV; i--; )
285 		write(ibf, (char *) & block, EVS);
286 }
287 
288 
289 cvtime()
290 {
291 	long	tt;
292 	struct tm	*date;
293 	extern struct tm	*localtime();
294 
295 	time(&tt);
296 	date = localtime(&tt);
297 	v.dy = date->tm_mday;
298 	v.dw = date->tm_wday + 1;
299 	v.yr = date->tm_year;
300 	v.mo = date->tm_mon + 1;
301 }
302 
303 
304 ctoi(s)
305 	register char *s;
306 {
307 	register n;
308 
309 	while (*s == ' ')
310 		s++;
311 	n = 0;
312 	while (isdigit(*s))
313 		n = 10 * n + *s++ - '0';
314 	return n;
315 }
316 
317 
318 mesg(f)
319 int	f;
320 {
321 	static int	mode;
322 
323 	if (!f) {
324 		stat(ttyp, cbuf);
325 		mode = ((struct stat *)(cbuf))->st_mode;
326 		chmod(ttyp, mode & ~0122);	/* turn off writing for others */
327 	} else {
328 		chmod(ttyp, mode);
329 	}
330 }
331 
332 
333 /*
334  * Scaled down version of C Library printf.
335  * Only %s %u %d (==%u) %o %c %x %D are recognized.
336  */
337 #define	putchar(n)	(*pfbp++ = (n))	/* NO CHECKING! */
338 
339 static char	pfbuf[NTM];
340 static char	*pfbp = pfbuf;
341 int	stderr	 = 2;	/* NOT stdio value */
342 
343 /* VARARGS */
344 fprintf(fd, fmt, x1)
345 int	fd;
346 char	*fmt;
347 unsigned	x1;
348 {
349 	register c;
350 	register unsigned int	*adx;
351 	char	*s;
352 	register i;
353 
354 	pfbp = pfbuf;
355 	adx = &x1;
356 loop:
357 	while ((c = *fmt++) != '%') {
358 		if (c == '\0') {
359 			if (fd == stderr)
360 				write(stderr, pfbuf, pfbp - pfbuf);
361 			else {
362 				*pfbp = 0;
363 				pfbp = pfbuf;
364 				while (*pfbp) {
365 					*obufp++ = *pfbp++;
366 					if (obufp >= &obuf[OBUFSZ])
367 						flusho();
368 				}
369 			}
370 			return;
371 		}
372 		putchar(c);
373 	}
374 	c = *fmt++;
375 	if (c == 'd') {
376 		i = *adx;
377 		if (i < 0) {
378 			putchar('-');
379 			i = -i;
380 		}
381 		printn((long)i, 10);
382 	} else if (c == 'u' || c == 'o' || c == 'x')
383 		printn((long)*adx, c == 'o' ? 8 : (c == 'x' ? 16 : 10));
384 	else if (c == 'c') {
385 		if (c > 0177 || c < 040)
386 			putchar('\\');
387 		putchar(*adx & 0177);
388 	} else if (c == 's') {
389 		s = (char *) * adx;
390 		while (c = *s++)
391 			putchar(c);
392 	} else if (c == 'D') {
393 		printn(*(long *)adx, 10);
394 		adx += (sizeof(long) / sizeof(int)) - 1;
395 	} else if (c == 'O') {
396 		printn(*(long *)adx, 8);
397 		adx += (sizeof(long) / sizeof(int)) - 1;
398 	}
399 	adx++;
400 	goto loop;
401 }
402 
403 
404 /*
405  * Print an unsigned integer in base b.
406  */
407 static printn(n, b)
408 long	n;
409 {
410 	register long	a;
411 
412 	if (n < 0) {	/* shouldn't happen */
413 		putchar('-');
414 		n = -n;
415 	}
416 	if (a = n / b)
417 		printn(a, b);
418 	putchar("0123456789ABCDEF"[(int)(n%b)]);
419 }
420 
421 /* scaled down version of library sprintf */
422 /* same limits as fprintf */
423 /* returns pointer to \0 that ends the string */
424 
425 /* VARARGS */
426 char *sprintf(str, fmt, x1)
427 	char	*str;
428 	char	*fmt;
429 	unsigned	x1;
430 {
431 	register c;
432 	char *sprintn();
433 	register unsigned int	*adx;
434 	char	*s;
435 	register i;
436 
437 	adx = &x1;
438 loop:
439 	while ((c = *fmt++) != '%') {
440 		if (c == '\0') {
441 			*str = 0;
442 			return str;
443 		}
444 		*str++ = c;
445 	}
446 	c = *fmt++;
447 	if (c == 'd') {
448 		i = *adx;
449 		if (i < 0) {
450 			*str++ = '-';
451 			i = -i;
452 		}
453 		str = sprintn(str, (long)i, 10);
454 	} else if (c == 'u' || c == 'o' || c == 'x')
455 		str = sprintn(str, (long)*adx, c == 'o' ? 8 : (c == 'x' ? 16 : 10));
456 	else if (c == 'c') {
457 		if (c > 0177 || c < 040)
458 			*str++ = '\\';
459 		*str++ = *adx & 0177;
460 	} else if (c == 's') {
461 		s = (char *) * adx;
462 		while (c = *s++)
463 			*str++ = c;
464 	} else if (c == 'D') {
465 		str = sprintn(str, *(long *)adx, 10);
466 		adx += (sizeof(long) / sizeof(int)) - 1;
467 	} else if (c == 'O') {
468 		str = sprintn(str, *(long *)adx, 8);
469 		adx += (sizeof(long) / sizeof(int)) - 1;
470 	}
471 	adx++;
472 	goto loop;
473 }
474 
475 /*
476  * Print an unsigned integer in base b.
477  */
478 static char *sprintn(s, n, b)
479 	register char *s;
480 	register long n;
481 {
482 	register long	a;
483 
484 	if (n < 0) {	/* shouldn't happen */
485 		*s++ = '-';
486 		n = -n;
487 	}
488 	if (a = n / b)
489 		s = sprintn(s, a, b);
490 	*s++ = "0123456789ABCDEF"[(int)(n%b)];
491 	return s;
492 }
493 
494 
495 control(a, b)
496 register int	a, b;
497 {
498 	register int	j;
499 
500 	if (a == 0 || (j = findmn(a)) == -1)
501 		return(0);
502 	if (contab[j].rq & MMASK) {
503 		nxf->nargs = 0;
504 		if (b)
505 			collect();
506 		flushi();
507 		return(pushi((filep)contab[j].x.mx));
508 	} else if (b)
509 		return((*contab[j].x.f)(0));
510 	else
511 		return(0);
512 }
513 
514 
515 getrq()
516 {
517 	register i, j;
518 
519 	if (((i = getach()) == 0) || ((j = getach()) == 0))
520 		goto rtn;
521 	i = PAIR(i, j);
522 rtn:
523 	return(i);
524 }
525 
526 
527 tchar getch()
528 {
529 	register int	k;
530 	tchar i, j;
531 	tchar setht(), setslant();
532 
533 	level++;
534 g0:
535 	if (ch) {
536 		if (cbits(i = ch) == '\n')
537 			nlflg++;
538 		ch = 0;
539 		level--;
540 		return(i);
541 	}
542 
543 	if (nlflg) {
544 		level--;
545 		return('\n');
546 	}
547 
548 	if ((k = cbits(i = getch0())) != ESC) {
549 		if (ismot(i))
550 			goto g2;
551 		if (k == FLSS) {
552 			copyf++;
553 			raw++;
554 			i = getch0();
555 			if (!fi)
556 				flss = i;
557 			copyf--;
558 			raw--;
559 			goto g0;
560 		}
561 		if (k == RPT) {
562 			setrpt();
563 			goto g0;
564 		}
565 		if (!copyf) {
566 			if (k == 'f' && lg && !lgf) {
567 				i = getlg(i);
568 				goto g2;
569 			}
570 			if (k == fc || k == tabch || k == ldrch) {
571 				if ((i = setfield(k)) == 0)
572 					goto g0;
573 				else
574 					goto g2;
575 			}
576 			if (k == '\b') {
577 				i = makem(-width(' ' | chbits));
578 				goto g2;
579 			}
580 		}
581 		goto g2;
582 	}
583 	k = cbits(j = getch0());
584 	if (ismot(j)) {
585 		i = j;
586 		goto g2;
587 	}
588 	switch (k) {
589 
590 	case '\n':	/* concealed newline */
591 		goto g0;
592 	case 'n':	/* number register */
593 		setn();
594 		goto g0;
595 	case '*':	/* string indicator */
596 		setstr();
597 		goto g0;
598 	case '$':	/* argument indicator */
599 		seta();
600 		goto g0;
601 	case '{':	/* LEFT */
602 		i = LEFT;
603 		goto gx;
604 	case '}':	/* RIGHT */
605 		i = RIGHT;
606 		goto gx;
607 	case '"':	/* comment */
608 		while (cbits(i = getch0()) != '\n')
609 			;
610 		goto g2;
611 	case ESC:	/* double backslash */
612 		i = eschar;
613 		goto gx;
614 	case 'e':	/* printable version of current eschar */
615 		i = PRESC;
616 		goto gx;
617 	case ' ':	/* unpaddable space */
618 		i = UNPAD;
619 		goto gx;
620 	case '|':	/* narrow space */
621 		i = NARSP;
622 		goto gx;
623 	case '^':	/* half of narrow space */
624 		i = HNARSP;
625 		goto gx;
626 	case '\'':	/* \(aa */
627 		i = ACUTE;
628 		goto gx;
629 	case '`':	/* \(ga */
630 		i = GRAVE;
631 		goto gx;
632 	case '_':	/* \(ul */
633 		i = UNDERLINE;
634 		goto gx;
635 	case '-':	/* current font minus */
636 		i = MINUS;
637 		goto gx;
638 	case '&':	/* filler */
639 		i = FILLER;
640 		goto gx;
641 	case 'c':	/* to be continued */
642 		i = CONT;
643 		goto gx;
644 	case '!':	/* transparent indicator */
645 		i = XPAR;
646 		goto gx;
647 	case 't':	/* tab */
648 		i = '\t';
649 		goto g2;
650 	case 'a':	/* leader (SOH) */
651 		i = LEADER;
652 		goto g2;
653 	case '%':	/* ohc */
654 		i = OHC;
655 		goto g2;
656 	case 'g':	/* return format of a number register */
657 		setaf();
658 		goto g0;
659 	case '.':	/* . */
660 		i = '.';
661 gx:
662 		setsfbits(i, sfbits(j));
663 		goto g2;
664 	}
665 	if (!copyf)
666 		switch (k) {
667 
668 		case 'p':	/* spread */
669 			spread++;
670 			goto g0;
671 		case '(':	/* special char name */
672 			if ((i = setch()) == 0)
673 				goto g0;
674 			break;
675 		case 's':	/* size indicator */
676 			setps();
677 			goto g0;
678 		case 'H':	/* character height */
679 			i = setht();
680 			break;
681 		case 'S':	/* slant */
682 			i = setslant();
683 			break;
684 		case 'f':	/* font indicator */
685 			setfont(0);
686 			goto g0;
687 		case 'w':	/* width function */
688 			setwd();
689 			goto g0;
690 		case 'v':	/* vert mot */
691 			if (i = vmot())
692 				break;
693 			goto g0;
694 		case 'h': 	/* horiz mot */
695 			if (i = hmot())
696 				break;
697 			goto g0;
698 		case 'z':	/* zero with char */
699 			i = setz();
700 			break;
701 		case 'l':	/* hor line */
702 			setline();
703 			goto g0;
704 		case 'L':	/* vert line */
705 			setvline();
706 			goto g0;
707 		case 'D':	/* drawing function */
708 			setdraw();
709 			goto g0;
710 		case 'b':	/* bracket */
711 			setbra();
712 			goto g0;
713 		case 'o':	/* overstrike */
714 			setov();
715 			goto g0;
716 		case 'k':	/* mark hor place */
717 			if ((k = findr(getsn())) != -1) {
718 				vlist[k] = v.hp = sumhp();
719 			}
720 			goto g0;
721 		case '0':	/* number space */
722 			i = makem(width('0' | chbits));
723 			break;
724 		case 'x':	/* extra line space */
725 			if (i = xlss())
726 				break;
727 			goto g0;
728 		case 'u':	/* half em up */
729 		case 'r':	/* full em up */
730 		case 'd':	/* half em down */
731 			i = sethl(k);
732 			break;
733 		default:
734 			i = j;
735 		}
736 	else {
737 		ch0 = j;
738 		i = eschar;
739 	}
740 g2:
741 	if (cbits(i) == '\n') {
742 		nlflg++;
743 		v.hp = 0;
744 		pinchar = inchar;	/* XXX */
745 		if (ip == 0)
746 			v.cd++;	/* current input line number in this file */
747 	}
748 	if (!--level) {
749 		if (pinchar >= inchar + LNSIZE) {	/* XXX */
750 			inchar[0] = makem(sumhp());
751 			pinchar = &inchar[1];
752 		}
753 		*pinchar++ = i;	/* XXX */
754 	}
755 	return(i);
756 }
757 
758 
759 char	ifilt[32] = {
760 	0, 001, 002, 003, 0, 005, 006, 007, 010, 011, 012};
761 
762 
763 sumhp()	/* XXX - add up values in inchar */
764 {
765 	register int n;
766 	register tchar *p;
767 
768 	n = 0;
769 	for (p = inchar; p < pinchar; p++)
770 		n += width(*p);
771 	return(n);
772 }
773 
774 
775 tchar getch0()
776 {
777 	register int	j;
778 	tchar i;
779 
780 	if (ch0) {
781 		i = ch0;
782 		ch0 = 0;
783 		return(i);
784 	}
785 	if (nchar) {
786 		nchar--;
787 		return(rchar);
788 	}
789 
790 again:
791 	if (cp) {
792 		if ((i = *cp++) == 0) {
793 			cp = 0;
794 			goto again;
795 		}
796 	} else if (ap) {
797 		if ((i = *ap++) == 0) {
798 			ap = 0;
799 			goto again;
800 		}
801 	} else if (ip) {
802 		if (ip == -1)
803 			i = rdtty();
804 		else
805 			i = rbf();
806 	} else {
807 		if (donef)
808 			done(0);
809 		if (nx || ibufp >= eibuf) {
810 			if (nfo)
811 				goto g1;
812 g0:
813 			if (nextfile()) {
814 				if (ip)
815 					goto again;
816 				if (ibufp < eibuf)
817 					goto g2;
818 			}
819 g1:
820 			nx = 0;
821 			if ((j = read(ifile, ibuf, IBUFSZ)) <= 0)
822 				goto g0;
823 			ibufp = ibuf;
824 			eibuf = ibuf + j;
825 			if (ip)
826 				goto again;
827 		}
828 g2:
829 		i = *ibufp++ & 0177;
830 		ioff++;
831 		if (i >= 040)
832 			goto g4;
833 		else
834 			i = ifilt[i];
835 	}
836 	if (raw)
837 		return(i);
838 	if ((j = cbits(i)) == IMP)
839 		goto again;
840 	if ((i == 0) && !init)
841 		goto again;
842 g4:
843 	if (copyf == 0 && (i & ~BMASK) == 0 && !iscontrol(cbits(i)))
844 		i |= chbits;
845 	if (cbits(i) == eschar)
846 		setcbits(i, ESC);
847 	return(i);
848 }
849 
850 
851 nextfile()
852 {
853 	register char	*p;
854 
855 n0:
856 	if (ifile)
857 		close(ifile);
858 	if (nx) {
859 		p = nextf;
860 		if (*p != 0)
861 			goto n1;
862 	}
863 	if (ifi > 0) {
864 		if (popf())
865 			goto n0; /* popf error */
866 		return(1); /* popf ok */
867 	}
868 	if (rargc-- <= 0) {
869 		goto n2;
870 	}
871 	p = (argp++)[0];
872 n1:
873 	if ((p[0] == '-') && (p[1] == 0)) {
874 		ifile = 0;
875 	} else if ((ifile = open(p, 0)) < 0) {
876 		fprintf(stderr, "troff: cannot open %s\n", p);
877 		nfo -= mflg;
878 		done(02);
879 	}
880 	nfo++;
881 	v.cd = 0;
882 	ioff = 0;
883 	return(0);
884 n2:
885 	if ((nfo -= mflg) && !stdi)
886 		done(0);
887 	nfo++;
888 	v.cd = ifile = stdi = mflg = 0;
889 	ioff = 0;
890 	return(0);
891 }
892 
893 
894 popf()
895 {
896 	register i;
897 	register char	*p, *q;
898 	extern char	*ttyname();
899 
900 	ioff = offl[--ifi];
901 	ip = ipl[ifi];
902 	if ((ifile = ifl[ifi]) == 0) {
903 		p = xbuf;
904 		q = ibuf;
905 		ibufp = xbufp;
906 		eibuf = xeibuf;
907 		while (q < eibuf)
908 			*q++ = *p++;
909 		return(0);
910 	}
911 	if ((lseek(ifile, (long)(ioff & ~(IBUFSZ - 1)), 0) < 0) || ((i = read(ifile, ibuf, IBUFSZ)) < 0))
912 		return(1);
913 	eibuf = ibuf + i;
914 	ibufp = ibuf;
915 	if (ttyname(ifile) == 0)
916 		if ((ibufp = ibuf + (int)(ioff & (IBUFSZ - 1))) >= eibuf)
917 			return(1);
918 	return(0);
919 }
920 
921 
922 flushi()
923 {
924 	if (nflush)
925 		return;
926 	ch = 0;
927 	if (cbits(ch0) == '\n')
928 		nlflg++;
929 	ch0 = 0;
930 	copyf++;
931 	while (!nlflg) {
932 		if (donef && (frame == stk))
933 			break;
934 		getch();
935 	}
936 	copyf--;
937 	v.hp = 0;
938 	pinchar = inchar;	/* XXX */
939 }
940 
941 
942 getach()
943 {
944 	tchar i;
945 	register j;
946 
947 	lgf++;
948 	j = cbits(i = getch());
949 	if (ismot(i) || j == ' ' || j == '\n' || j & 0200) {
950 		ch = i;
951 		j = 0;
952 	}
953 	lgf--;
954 	return(j & 0177);
955 }
956 
957 
958 casenx()
959 {
960 	lgf++;
961 	skip();
962 	getname();
963 	nx++;
964 	nextfile();
965 	nlflg++;
966 	ip = 0;
967 	ap = 0;
968 	nchar = pendt = 0;
969 	frame = stk;
970 	nxf = frame + 1;
971 }
972 
973 
974 getname()
975 {
976 	register int	j, k;
977 	tchar i;
978 
979 	lgf++;
980 	for (k = 0; k < (NS - 1); k++) {
981 		if (((j = cbits(i = getch())) <= ' ') || (j > 0176))
982 			break;
983 		nextf[k] = j;
984 	}
985 	nextf[k] = 0;
986 	ch = i;
987 	lgf--;
988 	return(nextf[0]);
989 }
990 
991 
992 caseso()
993 {
994 	register i;
995 	register char	*p, *q;
996 
997 	lgf++;
998 	nextf[0] = 0;
999 	if (skip() || !getname() || ((i = open(nextf, 0)) < 0) || (ifi >= NSO)) {
1000 		fprintf(stderr, "troff: can't open file %s\n", nextf);
1001 		done(02);
1002 	}
1003 	flushi();
1004 	ifl[ifi] = ifile;
1005 	ifile = i;
1006 	offl[ifi] = ioff;
1007 	ioff = 0;
1008 	ipl[ifi] = ip;
1009 	ip = 0;
1010 	nx++;
1011 	nflush++;
1012 	if (!ifl[ifi++]) {
1013 		p = ibuf;
1014 		q = xbuf;
1015 		xbufp = ibufp;
1016 		xeibuf = eibuf;
1017 		while (p < eibuf)
1018 			*q++ = *p++;
1019 	}
1020 }
1021 
1022 
1023 casecf()
1024 {	/* copy file without change */
1025 #ifndef NROFF
1026 	int	fd, n;
1027 	char	buf[512];
1028 	extern int	un, hpos, esc, po;
1029 
1030 	nextf[0] = 0;
1031 	if (skip() || !getname() || (fd = open(nextf, 0)) < 0) {
1032 		fprintf(stderr, "troff: can't open file %s\n", nextf);
1033 		done(02);
1034 	}
1035 	tbreak();
1036 	/* make it into a clean state, be sure that everything is out */
1037 	hpos = po;
1038 	esc = un;
1039 	ptesc();
1040 	ptlead();
1041 	ptps();
1042 	ptfont();
1043 	flusho();
1044 	while ((n = read(fd, buf, 512)) > 0)
1045 		write(ptid, buf, n);
1046 	close(fd);
1047 #endif
1048 }
1049 
1050 
1051 casesy()
1052 {	/* call system */
1053 	char	sybuf[NTM];
1054 	int	i;
1055 
1056 	lgf++;
1057 	copyf++;
1058 	skip();
1059 	for (i = 0; i < NTM - 2; i++)
1060 		if ((sybuf[i] = getch()) == '\n')
1061 			break;
1062 	sybuf[i] = 0;
1063 	system(sybuf);
1064 	copyf--;
1065 }
1066 
1067 
1068 getpn(a)
1069 	register char *a;
1070 {
1071 	register int n, neg;
1072 
1073 	if (*a == 0)
1074 		return;
1075 	neg = 0;
1076 	for ( ; *a; a++)
1077 		switch (*a) {
1078 		case '+':
1079 		case ',':
1080 			continue;
1081 		case '-':
1082 			neg = 1;
1083 			continue;
1084 		default:
1085 			n = 0;
1086 			if (isdigit(*a)) {
1087 				do
1088 					n = 10 * n + *a++ - '0';
1089 				while (isdigit(*a));
1090 				a--;
1091 			} else
1092 				n = 9999;
1093 			*pnp++ = neg ? -n : n;
1094 			neg = 0;
1095 			if (pnp >= &pnlist[NPN-2]) {
1096 				fprintf(stderr, "troff: too many page numbers\n");
1097 				done3(-3);
1098 			}
1099 		}
1100 	if (neg)
1101 		*pnp++ = -9999;
1102 	*pnp = -32767;
1103 	print = 0;
1104 	pnp = pnlist;
1105 	if (*pnp != -32767)
1106 		chkpn();
1107 }
1108 
1109 
1110 setrpt()
1111 {
1112 	tchar i, j;
1113 
1114 	copyf++;
1115 	raw++;
1116 	i = getch0();
1117 	copyf--;
1118 	raw--;
1119 	if (i < 0 || cbits(j = getch0()) == RPT)
1120 		return;
1121 	rchar = j;
1122 	nchar = i & BMASK;
1123 }
1124