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