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