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