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