xref: /original-bsd/old/roff/common_source/n1.c (revision 823023b8)
1 #ifndef lint
2 static char sccsid[] = "@(#)n1.c	4.9 07/22/88";
3 #endif lint
4 
5 #include "tdef.h"
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <time.h>
9 extern
10 #include "d.h"
11 extern
12 #include "v.h"
13 #ifdef NROFF
14 extern
15 #include "tw.h"
16 #endif
17 #include "sdef.h"
18 #include <setjmp.h>
19 jmp_buf sjbuf;
20 #include	<sgtty.h>
21 /*
22 troff1.c
23 
24 consume options, initialization, main loop,
25 input routines, escape function calling
26 */
27 
28 int	inchar[LNSIZE], *pinchar = inchar;	/* XXX */
29 extern struct s *frame, *stk, *nxf;
30 extern struct s *ejl, *litlev;
31 extern filep ip;
32 extern filep offset;
33 extern filep nextb;
34 
35 
36 extern int stdi;
37 extern int waitf;
38 extern int nofeed;
39 extern int quiet;
40 extern int ptid;
41 extern int ascii;
42 extern int npn;
43 extern int xflg;
44 extern int stop;
45 extern char ibuf[IBUFSZ];
46 extern char xbuf[IBUFSZ];
47 extern char *ibufp;
48 extern char *xbufp;
49 extern char *eibuf;
50 extern char *xeibuf;
51 extern int cbuf[NC];
52 extern int *cp;
53 extern int *vlist;
54 extern int nx;
55 extern int mflg;
56 extern int ch;
57 extern int pto;
58 extern int pfrom;
59 extern int cps;
60 extern int chbits;
61 extern int ibf;
62 extern int ttyod;
63 extern struct sgttyb ttys;
64 extern int iflg;
65 extern int init;
66 extern int rargc;
67 extern char **argp;
68 extern char trtab[256];
69 extern int lgf;
70 extern int copyf;
71 extern int eschar;
72 extern int ch0;
73 extern int cwidth;
74 extern int nlflg;
75 extern int *ap;
76 extern int donef;
77 extern int nflush;
78 extern int nchar;
79 extern int rchar;
80 extern int nfo;
81 extern int ifile;
82 extern int fc;
83 extern int padc;
84 extern int tabc;
85 extern int dotc;
86 extern int raw;
87 extern int tabtab[NTAB];
88 extern char nextf[];
89 extern int nfi;
90 #ifdef NROFF
91 extern char termtab[];
92 extern int tti;
93 #endif
94 extern int ifl[NSO];
95 extern int ifi;
96 extern int pendt;
97 extern int flss;
98 extern int fi;
99 extern int lg;
100 extern char ptname[];
101 extern int print;
102 extern int nonumb;
103 extern int pnlist[];
104 extern int *pnp;
105 extern int nb;
106 extern int trap;
107 extern int tflg;
108 extern int ejf;
109 extern int lit;
110 extern int cc;
111 extern int c2;
112 extern int spread;
113 extern int gflag;
114 extern int oline[];
115 extern int *olinep;
116 extern int dpn;
117 extern int noscale;
118 extern char *unlkp;
119 extern int pts;
120 extern int level;
121 extern int ttysave;
122 extern int tdelim;
123 extern int dotT;
124 extern int tabch, ldrch;
125 extern int eqflg;
126 extern no_out;
127 extern int hflg;
128 #ifndef NROFF
129 extern char codetab[];
130 extern int spbits;
131 #endif
132 extern int xxx;
133 int stopmesg;
134 filep ipl[NSO];
135 long offl[NSO];
136 long ioff;
137 char *ttyp;
138 extern struct contab {
139 	int rq;
140 	union {
141 		int (*f)();
142 		unsigned mx;
143 	}x;
144 }contab[NM];
145 int ms[] = {31,28,31,30,31,30,31,31,30,31,30,31};
146 #ifndef NROFF
147 int acctf;
148 #endif
149 
150 main(argc,argv)
151 int argc;
152 char **argv;
153 {
154 	char *p, *q;
155 	register i, j;
156 	extern catch(), fpecatch(), kcatch();
157 
158 	signal(SIGHUP,catch);
159 	if(signal(SIGINT,catch) == SIG_IGN){
160 		signal(SIGHUP,SIG_IGN);
161 		signal(SIGINT,SIG_IGN);
162 		signal(SIGQUIT,SIG_IGN);
163 	}
164 	signal(SIGFPE,fpecatch);
165 	signal(SIGPIPE,catch);
166 	signal(SIGTERM,kcatch);
167 	init1(argv[0][0]);
168 options:
169 	while(--argc > 0 && (++argv)[0][0]=='-')
170 		switch(argv[0][1]){
171 
172 		case 0:
173 			goto start;
174 		case 'i':
175 			stdi++;
176 			continue;
177 		case 'q':
178 			quiet++;
179 			if(gtty(0, &ttys) >= 0)
180 				ttysave = ttys.sg_flags;
181 			continue;
182 		case 'n':
183 			npn = cnum(&argv[0][2]);
184 			continue;
185 		case 'p':
186 			xflg = 0;
187 			cps = cnum(&argv[0][2]);
188 			continue;
189 		case 'S':
190 			stopmesg++;
191 			continue;
192 		case 's':
193 			if(!(stop = cnum(&argv[0][2])))stop++;
194 			continue;
195 		case 'r':
196 			vlist[findr(argv[0][2])] = cnum(&argv[0][3]);
197 			continue;
198 		case 'm':
199 			p = &nextf[nfi];
200 			q = &argv[0][2];
201 			while((*p++ = *q++) != 0);
202 			if (access(nextf, 4) < 0) {
203 char *local = "/usr/local/lib/tmac/tmac.\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
204 				strcat(local, &argv[0][2]);
205 				if (access(local, 4) == 0)
206 					strcpy(nextf, local);
207 			}
208 			mflg++;
209 			continue;
210 		case 'o':
211 			getpn(&argv[0][2]);
212 			continue;
213 #ifdef NROFF
214 		case 'h':
215 			hflg++;
216 			continue;
217 		case 'z':
218 			no_out++;
219 			continue;
220 		case 'e':
221 			eqflg++;
222 			continue;
223 		case 'T':
224 			p = &termtab[tti];
225 			q = &argv[0][2];
226 			if(!((*q) & 0177))continue;
227 			while((*p++ = *q++) != 0);
228 			dotT++;
229 			continue;
230 #endif
231 #ifndef NROFF
232 		case 'z':
233 			no_out++;
234 		case 'a':
235 			ascii = 1;
236 			nofeed++;
237 		case 't':
238 			ptid = 1;
239 			continue;
240 		case 'w':
241 			waitf = 1;
242 			continue;
243 		case 'f':
244 			nofeed++;
245 			continue;
246 		case 'x':
247 			xflg = 0;
248 			continue;
249 		case 'b':
250 			if(open(ptname,1) < 0)prstr("Busy.\n");
251 			else prstr("Available.\n");
252 			done3(0);
253 		case 'g':
254 			stop = ptid = gflag = 1;
255 			dpn = 0;
256 			continue;
257 		case 'F':
258 			{
259 			  extern char *fontfile;
260 			  fontfile = &argv[0][2];
261 			}
262 			continue;
263 #endif
264 		default:
265 			pto = cnum(&argv[0][1]);
266 			continue;
267 		}
268 
269 	if(argv[0][0] == '+'){
270 		pfrom = cnum(&argv[0][1]);
271 		print = 0;
272 		if(argc > 0)goto options;
273 	}
274 
275 start:
276 	argp = argv;
277 	rargc = argc;
278 	init2();
279 	setjmp(sjbuf);
280 loop:
281 	copyf = lgf = nb = nflush = nlflg = 0;
282 	if(ip && (rbf0(ip)==0) && ejf && (frame->pframe <= ejl)){
283 		nflush++;
284 		trap = 0;
285 		eject((struct s *)0);
286 		goto loop;
287 	}
288 	i = getch();
289 	if(pendt)goto lt;
290 	if(lit && (frame <= litlev)){
291 		lit--;
292 		goto lt;
293 	}
294 	if((j = (i & CMASK)) == XPAR){
295 		copyf++;
296 		tflg++;
297 		for(;(i & CMASK) != '\n';)pchar(i = getch());
298 		tflg = 0;
299 		copyf--;
300 		goto loop;
301 	}
302 	if((j == cc) || (j == c2)){
303 		if(j == c2)nb++;
304 		copyf++;
305 		while(((j=((i=getch()) & CMASK)) == ' ') ||
306 			(j == '\t'));
307 		ch = i;
308 		copyf--;
309 		control(getrq(),1);
310 		flushi();
311 		goto loop;
312 	}
313 lt:
314 	ch = i;
315 	text();
316 	goto loop;
317 }
318 catch(){
319 /*
320 	prstr("Interrupt\n");
321 */
322 	done3(01);
323 }
324 fpecatch(){
325 	prstrfl("Floating Exception.\n");
326 	signal(SIGFPE,fpecatch);
327 }
328 kcatch(){
329 	signal(SIGTERM,SIG_IGN);
330 	done3(01);
331 }
332 #ifndef NROFF
333 acctg() {
334 	static char *acct_file = "/usr/adm/tracct";
335 	acctf = open(acct_file,1);
336 	setuid(getuid());
337 }
338 #endif
339 init1(a)
340 char a;
341 {
342 	register char *p;
343 	char *mktemp();
344 	static char tempname[] = "/tmp/taXXXXX";
345 	register i;
346 
347 #ifndef NROFF
348 	acctg();/*open troff actg file while mode 4755*/
349 #endif
350 	p = mktemp(tempname);
351 	if(a == 'a')p = &p[5];
352 	if((close(creat(p, 0600))) < 0){
353 		prstr("Cannot create temp file.\n");
354 		exit(-1);
355 	}
356 	ibf = open(p, 2);
357 	for(i=256; --i;)trtab[i]=i;
358 	trtab[UNPAD] = ' ';
359 	mchbits();
360 	if(a != 'a')unlkp = p;
361 }
362 init2()
363 {
364 	register i,j;
365 	extern int block;
366 	extern char *setbrk();
367 	extern char *ttyname();
368 
369 	ttyod = 2;
370 	if(((ttyp=ttyname(j=0)) != (char *)0) ||
371 	   ((ttyp=ttyname(j=1)) != (char *)0) ||
372 	   ((ttyp=ttyname(j=2)) != (char *)0)
373 	  );else ttyp = "notty";
374 	iflg = j;
375 	if(ascii)mesg(0);
376 
377 	if((!ptid) && (!waitf)){
378 		if((ptid = open(ptname,1)) < 0){
379 			prstr("Typesetter busy.\n");
380 			done3(-2);
381 		}
382 	}
383 	ptinit();
384 	for(i=NEV; i--;)write(ibf, (char *)&block, EVS*sizeof(int));
385 	olinep = oline;
386 	ibufp = eibuf = ibuf;
387 	v.hp = init = 0;
388 	pinchar = inchar;	/* XXX */
389 	ioff = 0;
390 	v.nl = -1;
391 	cvtime();
392 	frame = stk = (struct s *)setbrk(DELTA);
393 	dip = &d[0];
394 	nxf = frame + 1;
395 	nx = mflg;
396 }
397 cvtime()
398 {
399 	extern time_t time();
400 	time_t t;
401 	register struct tm *tmp;
402 
403 	t = time((time_t *)0);
404 	tmp = localtime(&t);
405 	v.dy = tmp->tm_mday;
406 	v.dw = tmp->tm_wday + 1;
407 	v.yr = tmp->tm_year;
408 	v.mo = tmp->tm_mon + 1;
409 }
410 cnum(a)
411 char *a;
412 {
413 	register i;
414 
415 	ibufp = a;
416 	eibuf = (char *) MAXPTR;
417 	i = atoi();
418 	ch = 0;
419 	return(i);
420 }
421 mesg(f)
422 int f;
423 {
424 	static int mode;
425 
426 	if (ttyp==0)
427 		return;
428 	if(!f){
429 		stat(ttyp,cbuf);
430 		mode = ((struct stat *)(cbuf))->st_mode;
431 		chmod(ttyp,mode & ~022);
432 	}else{
433 		chmod(ttyp,mode);
434 	}
435 }
436 prstrfl(s)
437 char *s;
438 {
439 	flusho();
440 	prstr(s);
441 }
442 prstr(s)
443 char *s;
444 {
445 	register i;
446 	register char *j;
447 
448 	j = s;
449 	for(i=0;*s;i++)s++;
450 	write(ttyod,j,i);
451 }
452 control(a,b)
453 int a,b;
454 {
455 	register i,j;
456 	extern filep boff();
457 
458 	i = a;
459 	if((i == 0) || ((j = findmn(i)) == -1))return(0);
460 	if(contab[j].rq & MMASK){
461 		nxf->nargs = 0;
462 		if(b)collect();
463 		flushi();
464 		return(pushi(((filep)contab[j].x.mx)<<BLKBITS));
465 	}else{
466 		if(!b)return(0);
467 		return((*contab[j].x.f)(0));
468 	}
469 }
470 
471 getrq(){
472 	register i,j;
473 
474 	if(((i=getach()) == 0) ||
475 	   ((j=getach()) == 0))goto rtn;
476 	i = PAIR(i,j);
477 rtn:
478 	return(i);
479 }
480 getch(){
481 	register int i, j, k;
482 
483 	level++;
484 g0:
485 	if(ch){
486 		if(((i = ch) & CMASK) == '\n')nlflg++;
487 		ch = 0;
488 		level--;
489 		return(i);
490 	}
491 
492 	if(nlflg){
493 		level--;
494 		return('\n');
495 	}
496 
497 	if((k = (i = getch0()) & CMASK) != ESC){
498 		if(i & MOT)goto g2;
499 		if(k == FLSS){
500 			copyf++; raw++;
501 			i = getch0();
502 			if(!fi)flss = i;
503 			copyf--; raw--;
504 			goto g0;
505 		}
506 		if(k == RPT){
507 			setrpt();
508 			goto g0;
509 		}
510 		if(!copyf){
511 			if((k == 'f') && lg && !lgf){
512 				i = getlg(i);
513 				goto g2;
514 			}
515 			if((k == fc) || (k == tabch) || (k == ldrch)){
516 				if((i=setfield(k)) == 0)goto g0; else goto g2;
517 			}
518 			if(k == 010){
519 				i = makem(-width(' ' | chbits));
520 				goto g2;
521 			}
522 		}
523 		goto g2;
524 	}
525 	k = (j = getch0()) & CMASK;
526 	if(j & MOT){
527 		i = j;
528 		goto g2;
529 	}
530 /*
531 	if(k == tdelim){
532 		i = TDELIM;
533 		tdelim = IMP;
534 		goto g2;
535 	}
536 */
537 	switch(k){
538 
539 		case '\n':	/*concealed newline*/
540 			goto g0;
541 		case 'n':	/*number register*/
542 			setn();
543 			goto g0;
544 		case '*':	/*string indicator*/
545 			setstr();
546 			goto g0;
547 		case '$':	/*argument indicator*/
548 			seta();
549 			goto g0;
550 		case '{':	/*LEFT*/
551 			i = LEFT;
552 			goto gx;
553 		case '}':	/*RIGHT*/
554 			i = RIGHT;
555 			goto gx;
556 		case '"':	/*comment*/
557 			while(((i=getch0()) & CMASK ) != '\n');
558 			goto g2;
559 		case ESC:	/*double backslash*/
560 			i = eschar;
561 			goto gx;
562 		case 'e':	/*printable version of current eschar*/
563 			i = PRESC;
564 			goto gx;
565 		case ' ':	/*unpaddable space*/
566 			i = UNPAD;
567 			goto gx;
568 		case '|':	/*narrow space*/
569 			i = NARSP;
570 			goto gx;
571 		case '^':	/*half of narrow space*/
572 			i = HNSP;
573 			goto gx;
574 		case '\'':	/*\(aa*/
575 			i = 0222;
576 			goto gx;
577 		case '`':	/*\(ga*/
578 			i = 0223;
579 			goto gx;
580 		case '_':	/*\(ul*/
581 			i = 0224;
582 			goto gx;
583 		case '-':	/*current font minus*/
584 			i = 0210;
585 			goto gx;
586 		case '&':	/*filler*/
587 			i = FILLER;
588 			goto gx;
589 		case 'c':	/*to be continued*/
590 			i = CONT;
591 			goto gx;
592 		case ':':	/*lem's char*/
593 			i = COLON;
594 			goto gx;
595 		case '!':	/*transparent indicator*/
596 			i = XPAR;
597 			goto gx;
598 		case 't':	/*tab*/
599 			i = '\t';
600 			goto g2;
601 		case 'a':	/*leader (SOH)*/
602 			i = LEADER;
603 			goto g2;
604 		case '%':	/*ohc*/
605 			i = OHC;
606 			goto g2;
607 		case '.':	/*.*/
608 			i = '.';
609 		gx:
610 			i = (j & ~CMASK) | i;
611 			goto g2;
612 	}
613 	if(!copyf)
614 		switch(k){
615 
616 			case 'p':	/*spread*/
617 				spread++;
618 				goto g0;
619 			case '(':	/*special char name*/
620 				if((i=setch()) == 0)goto g0;
621 				break;
622 			case 's':	/*size indicator*/
623 				setps();
624 				goto g0;
625 			case 'f':	/*font indicator*/
626 				setfont(0);
627 				goto g0;
628 			case 'w':	/*width function*/
629 				setwd();
630 				goto g0;
631 			case 'v':	/*vert mot*/
632 				if(i = vmot())break;
633 				goto g0;
634 			case 'h': 	/*horiz mot*/
635 				if(i = hmot())break;
636 				goto g0;
637 			case 'z':	/*zero with char*/
638 				i = setz();
639 				break;
640 			case 'l':	/*hor line*/
641 				setline();
642 				goto g0;
643 			case 'L':	/*vert line*/
644 				setvline();
645 				goto g0;
646 			case 'b':	/*bracket*/
647 				setbra();
648 				goto g0;
649 			case 'o':	/*overstrike*/
650 				setov();
651 				goto g0;
652 			case 'k':	/*mark hor place*/
653 				if((i=findr(getsn())) == -1)goto g0;
654 				vlist[i] = v.hp = sumhp();	/* XXX */
655 				goto g0;
656 			case 'j':	/*mark output hor place*/
657 				if(!(i=getach()))goto g0;
658 				i = (i<<BYTE) | JREG;
659 				break;
660 			case '0':	/*number space*/
661 				i = makem(width('0' | chbits));
662 				break;
663 			case 'x':	/*extra line space*/
664 				if(i = xlss())break;
665 				goto g0;
666 			case 'u':	/*half em up*/
667 			case 'r':	/*full em up*/
668 			case 'd':	/*half em down*/
669 				i = sethl(k);
670 				break;
671 			default:
672 				i = j;
673 		}
674 	else{
675 		ch0 = j;
676 		i = eschar;
677 	}
678 g2:
679 	if((i & CMASK) == '\n'){
680 		nlflg++;
681 		v.hp = 0;
682 		pinchar = inchar;	/* XXX */
683 		if(ip == 0)v.cd++;
684 	}
685 	if(!--level){
686 		/* j = width(i); */
687 		/* v.hp += j; */
688 		/* cwidth = j; */
689 		if (pinchar >= inchar + LNSIZE) {	/* XXX */
690 			inchar[0] = makem(sumhp());
691 			pinchar = &inchar[1];
692 		}
693 		*pinchar++ = i;	/* XXX */
694 	}
695 	return(i);
696 }
697 
698 sumhp()	/* XXX - add up widths in inchar array */
699 {
700 	register int n;
701 	register int *p;
702 
703 	n = 0;
704 	for (p = inchar; p < pinchar; p++)
705 		n += width(*p);
706 	return(n);
707 }
708 char ifilt[32] = {0,001,002,003,0,005,006,007,010,011,012};
709 getch0(){
710 	register int i, j;
711 
712 	if(ch0){i=ch0; ch0=0; return(i);}
713 	if(nchar){nchar--; return(rchar);}
714 
715 again:
716 	if(cp){
717 		if((i = *cp++) == 0){
718 			cp = 0;
719 			goto again;
720 		}
721 	}else if(ap){
722 		if((i = *ap++) == 0){
723 			ap = 0;
724 			goto again;
725 		}
726 	}else if(ip){
727 		if(ip == -1)i = rdtty();
728 		else i = rbf();
729 	}else{
730 		if(donef)done(0);
731 		if(nx || ((ibufp >= eibuf) && (eibuf != (char *) MAXPTR))){
732 			if(nfo)goto g1;
733 		g0:
734 			if(nextfile()){
735 				if(ip)goto again;
736 				if(ibufp < eibuf)goto g2;
737 			}
738 		g1:
739 			nx = 0;
740 			if((j=read(ifile,ibuf,IBUFSZ)) <= 0)goto g0;
741 			ibufp = ibuf;
742 			eibuf = ibuf + j;
743 			if(ip)goto again;
744 		}
745 	g2:
746 		i = *ibufp++ & 0177;
747 		ioff++;
748 		if(i >= 040)goto g4; else i = ifilt[i];
749 	}
750 	if(raw)return(i);
751 	if((j = i & CMASK) == IMP)goto again;
752 	if((i == 0) && !init)goto again;
753 g4:
754 	if((copyf == 0) && ((i & ~BMASK) == 0) && ((i & CMASK) < 0370))
755 #ifndef NROFF
756 		if(spbits && (i>31) && ((codetab[i-32] & 0200))) i |= spbits;
757 		else
758 #endif
759 		i |= chbits;
760 	if((i & CMASK) == eschar)i = (i & ~CMASK) | ESC;
761 	return(i);
762 }
763 nextfile(){
764 	register char *p;
765 
766 n0:
767 	if(ifile)close(ifile);
768 	if(nx){
769 		p = nextf;
770 		if(*p != 0)goto n1;
771 	}
772 	if(ifi > 0){
773 		if(popf())goto n0; /*popf error*/
774 		return(1); /*popf ok*/
775 	}
776 	if(rargc-- <= 0)goto n2;
777 	p = (argp++)[0];
778 n1:
779 	if((p[0] == '-') && (p[1] == 0)){
780 		ifile = 0;
781 	}else if((ifile=open(p,0)) < 0){
782 		prstr("Cannot open ");
783 		prstr(p);
784 		prstr("\n");
785 		nfo -= mflg;
786 		done(02);
787 	}
788 	nfo++;
789 	v.cd = 0;
790 	ioff = 0;
791 	return(0);
792 n2:
793 	if((nfo -= mflg) && !stdi)done(0);
794 	nfo++;
795 	v.cd = ifile =  stdi = mflg = 0;
796 	ioff = 0;
797 	return(0);
798 }
799 popf(){
800 	register i;
801 	register char *p, *q;
802 	extern char *ttyname();
803 
804 	ioff = offl[--ifi];
805 	ip = ipl[ifi];
806 	if((ifile = ifl[ifi]) == 0){
807 		p = xbuf;
808 		q = ibuf;
809 		ibufp = xbufp;
810 		eibuf = xeibuf;
811 		while(q < eibuf)*q++ = *p++;
812 		return(0);
813 	}
814 	if((lseek(ifile,(long)(ioff & ~(IBUFSZ-1)),0) < 0) ||
815 	   ((i = read(ifile,ibuf,IBUFSZ)) < 0))return(1);
816 	eibuf = ibuf + i;
817 	ibufp = ibuf;
818 	if(ttyname(ifile) == (char *)0)
819 		if((ibufp = ibuf + (int)(ioff & (IBUFSZ-1)))  >= eibuf)return(1);
820 	return(0);
821 }
822 flushi(){
823 	if(nflush)return;
824 	ch = 0;
825 	if((ch0 & CMASK) == '\n')nlflg++;
826 	ch0 = 0;
827 	copyf++;
828 	while(!nlflg){
829 		if(donef && (frame == stk))break;
830 		getch();
831 	}
832 	copyf--;
833 	v.hp = 0;
834 	pinchar = inchar;	/* XXX */
835 }
836 getach(){
837 	register i;
838 
839 	lgf++;
840 	if(((i = getch()) & MOT) ||
841 	    ((i&CMASK) == ' ') ||
842 	    ((i&CMASK) == '\n')||
843 	    (i & 0200)){
844 			ch = i;
845 			i = 0;
846 	}
847 	lgf--;
848 	return(i & 0177);
849 }
850 casenx(){
851 	lgf++;
852 	skip();
853 	getname();
854 	nx++;
855 	nextfile();
856 	nlflg++;
857 	ip = 0;
858 	ap = 0;
859 	nchar = pendt = 0;
860 	frame = stk;
861 	nxf = frame + 1;
862 }
863 getname(){
864 	register int i, j, k;
865 
866 	lgf++;
867 	for(k=0; k < (NS-1); k++){
868 		if(((j=(i=getch()) & CMASK) <= ' ') ||
869 			(j > 0176))break;
870 		nextf[k] = j;
871 	}
872 	nextf[k] = 0;
873 	ch = i;
874 	lgf--;
875 	return(nextf[0]);
876 }
877 caseso(){
878 	register i;
879 	register char *p, *q;
880 
881 	lgf++;
882 	nextf[0] = 0;
883 	if(skip() || !getname() || ((i=open(nextf,0)) <0) || (ifi >= NSO)) {
884 		prstr("can't open file ");
885 		prstr(nextf);
886 		prstr("\n");
887 		done(02);
888 	}
889 	flushi();
890 	ifl[ifi] = ifile;
891 	ifile = i;
892 	offl[ifi] = ioff;
893 	ioff = 0;
894 	ipl[ifi] = ip;
895 	ip = 0;
896 	nx++;
897 	nflush++;
898 	if(!ifl[ifi++]){
899 		p = ibuf;
900 		q = xbuf;
901 		xbufp = ibufp;
902 		xeibuf = eibuf;
903 		while(p < eibuf)*q++ = *p++;
904 	}
905 }
906 
907 casecf(){	/* copy file without change */
908 	int fd, i, n;
909 	char buf[OBUFSZ];
910 
911 	flusho();
912 	lgf++;
913 	nextf[0] = 0;
914 	if(skip() || !getname() || ((fd=open(nextf,0)) <0) || (ifi >= NSO)) {
915 		prstr("can't open file ");
916 		prstr(nextf);
917 		prstr("\n");
918 		done(02);
919 	}
920 	while ((n = read(fd, buf, OBUFSZ)) > 0)
921 		for (i = 0; i < n; i++)
922 			oput(buf[i]);
923 	flusho();
924 	close(fd);
925 }
926 getpn(a)
927 char *a;
928 {
929 	register i, neg;
930 	long atoi1();
931 
932 	if((*a & 0177) == 0)return;
933 	neg = 0;
934 	ibufp = a;
935 	eibuf = (char *) MAXPTR;
936 	noscale++;
937 	while((i = getch() & CMASK) != 0)switch(i){
938 		case '+':
939 		case ',':
940 			continue;
941 		case '-':
942 			neg = MOT;
943 			goto d2;
944 		default:
945 			ch = i;
946 		d2:
947 			i = atoi1();
948 			if(nonumb)goto fini;
949 			else{
950 				*pnp++ = i | neg;
951 				neg = 0;
952 				if(pnp >= &pnlist[NPN-2]){
953 					prstr("Too many page numbers\n");
954 					done3(-3);
955 				}
956 			}
957 		}
958 fini:
959 	if(neg)*pnp++ = -2;
960 	*pnp = -1;
961 	ch = noscale = print = 0;
962 	pnp = pnlist;
963 	if(*pnp != -1)chkpn();
964 }
965 setrpt(){
966 	register i, j;
967 
968 	copyf++;raw++;
969 	i = getch0();
970 	copyf--;raw--;
971 	if((i < 0) ||
972 	   (((j = getch0()) & CMASK) == RPT))return;
973 	rchar = j;
974 	nchar = i & BMASK;
975 }
976