1 /* $MirOS: src/usr.bin/oldroff/nroff/n1.c,v 1.9 2006/11/04 03:02:53 tg Exp $ */
2
3 /*-
4 * Copyright (c) 2002, 2003, 2004, 2005, 2006
5 * Thorsten Glaser <tg@mirbsd.de>
6 *
7 * Licensee is hereby permitted to deal in this work without restric-
8 * tion, including unlimited rights to use, publicly perform, modify,
9 * merge, distribute, sell, give away or sublicence, provided all co-
10 * pyright notices above, these terms and the disclaimer are retained
11 * in all redistributions or reproduced in accompanying documentation
12 * or other materials provided with binary redistributions.
13 *
14 * Advertising materials mentioning features or use of this work must
15 * display the following acknowledgement:
16 * This product includes material provided by Thorsten Glaser.
17 *
18 * Licensor offers the work "AS IS" and WITHOUT WARRANTY of any kind,
19 * express, or implied, to the maximum extent permitted by applicable
20 * law, without malicious intent or gross negligence; in no event may
21 * licensor, an author or contributor be held liable for any indirect
22 * or other damage, or direct damage except proven a consequence of a
23 * direct error of said person and intended use of this work, loss or
24 * other issues arising in any way out of its use, even if advised of
25 * the possibility of such damage or existence of a defect.
26 */
27
28 /*-
29 * Copyright (c) 1979, 1980, 1981, 1986, 1988, 1990, 1991, 1992
30 * The Regents of the University of California.
31 * Copyright (C) Caldera International Inc. 2001-2002.
32 * All rights reserved.
33 *
34 * Redistribution and use in source and binary forms,
35 * with or without modification, are permitted provided
36 * that the following conditions are met:
37 *
38 * Redistributions of source code and documentation must retain
39 * the above copyright notice, this list of conditions and the
40 * following disclaimer. Redistributions in binary form must
41 * reproduce the above copyright notice, this list of conditions
42 * and the following disclaimer in the documentation and/or other
43 * materials provided with the distribution.
44 *
45 * All advertising materials mentioning features or use of this
46 * software must display the following acknowledgement:
47 * This product includes software developed or owned by
48 * Caldera International, Inc.
49 *
50 * Neither the name of Caldera International, Inc. nor the names
51 * of other contributors may be used to endorse or promote products
52 * derived from this software without specific prior written permission.
53 *
54 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
55 * INTERNATIONAL, INC. AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
56 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
57 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
58 * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE
59 * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR
60 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
61 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
62 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
63 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
64 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
65 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
66 */
67
68 #include "tdef.h"
69 #include "pathnames.h"
70 #include <sys/types.h>
71 #include <sys/stat.h>
72 #include <stdlib.h>
73 #include <time.h>
74 #include <unistd.h>
75 extern
76 #include "d.h"
77 extern
78 #include "v.h"
79 #ifdef NROFF
80 extern
81 #include "tw.h"
82 #endif
83 #include "sdef.h"
84 #include <setjmp.h>
85 jmp_buf sjbuf;
86 #include <termios.h>
87
88 __COPYRIGHT("Copyright (c) 2006 The MirOS Project.\n\
89 Copyright (c) 1991 The Regents of the University of California.\n\
90 All rights reserved.\n");
91 __SCCSID("@(#)n1.c 4.13 (Berkeley) 4/18/91");
92 __RCSID("$MirOS: src/usr.bin/oldroff/nroff/n1.c,v 1.9 2006/11/04 03:02:53 tg Exp $");
93
94 /*
95 troff1.c
96
97 consume options, initialization, main loop,
98 input routines, escape function calling
99 */
100
101 int inchar[LNSIZE], *pinchar = inchar; /* XXX */
102 extern struct s *frame, *stk, *nxf;
103 extern struct s *ejl, *litlev;
104 extern filep ip;
105 extern filep offset;
106 extern filep nextb;
107
108
109 extern int stdi;
110 extern int waitf;
111 extern int nofeed;
112 extern int quiet;
113 extern int ptid;
114 extern int ascii;
115 extern int npn;
116 extern int xflg;
117 extern int stop;
118 extern char ibuf[IBUFSZ];
119 extern char xbuf[IBUFSZ];
120 extern char *ibufp;
121 extern char *xbufp;
122 extern char *eibuf;
123 extern char *xeibuf;
124 extern int *cp;
125 extern int *vlist;
126 extern int nx;
127 extern int mflg;
128 extern int ch;
129 extern int pto;
130 extern int pfrom;
131 extern int cps;
132 extern int chbits;
133 extern int ibf;
134 extern int ttyod;
135 extern struct termios ttys;
136 extern int iflg;
137 extern int init;
138 extern int rargc;
139 extern char **argp;
140 extern char trtab[256];
141 extern int lgf;
142 extern int copyf;
143 extern int eschar;
144 extern int ch0;
145 extern int cwidth;
146 extern int nlflg;
147 extern int *ap;
148 extern int donef;
149 extern int nflush;
150 extern int nchar;
151 extern int rchar;
152 extern int nfo;
153 extern int ifile;
154 extern int fc;
155 extern int padc;
156 extern int tabc;
157 extern int dotc;
158 extern int raw;
159 extern int tabtab[NTAB];
160 extern char nextf[];
161 extern int nfi;
162 #ifdef NROFF
163 extern char termtab[];
164 extern int tti;
165 #endif
166 extern int ifl[NSO];
167 extern int ifi;
168 extern int pendt;
169 extern int flss;
170 extern int fi;
171 extern int lg;
172 extern char ptname[];
173 extern int print;
174 extern int nonumb;
175 extern int pnlist[];
176 extern int *pnp;
177 extern int nb;
178 extern int trap;
179 extern int tflg;
180 extern int ejf;
181 extern int lit;
182 extern int cc;
183 extern int c2;
184 extern int spread;
185 extern int gflag;
186 extern int oline[];
187 extern int *olinep;
188 extern int dpn;
189 extern int noscale;
190 extern char *unlkp;
191 extern int pts;
192 extern int level;
193 extern int ttysave;
194 extern struct termios ttysavespace;
195 extern int tdelim;
196 extern int dotT;
197 extern int tabch, ldrch;
198 extern int eqflg;
199 extern int spflg;
200 extern no_out;
201 extern int hflg;
202 #ifndef NROFF
203 extern char codetab[];
204 extern int spbits;
205 #endif
206 extern int xxx;
207 extern char *__progname;
208 int stopmesg;
209 filep ipl[NSO];
210 long offl[NSO];
211 long ioff;
212 char *ttyp;
213 extern struct contab {
214 int rq;
215 union {
216 int (*f)();
217 unsigned mx;
218 }x;
219 }contab[NM];
220 int ms[] = {31,28,31,30,31,30,31,31,30,31,30,31};
221 #ifndef NROFF
222 int acctf;
223 #endif
224 int groffmode = 0;
225
main(argc,argv)226 main(argc,argv)
227 int argc;
228 char **argv;
229 {
230 char *p, *q;
231 register i, j;
232 extern void catch(), fpecatch(), kcatch();
233
234 signal(SIGHUP,catch);
235 if(signal(SIGINT,catch) == SIG_IGN){
236 signal(SIGHUP,SIG_IGN);
237 signal(SIGINT,SIG_IGN);
238 signal(SIGQUIT,SIG_IGN);
239 }
240 signal(SIGFPE,fpecatch);
241 signal(SIGPIPE,catch);
242 signal(SIGTERM,kcatch);
243 init1(argv[0][0]);
244 options:
245 while(--argc > 0 && (++argv)[0][0]=='-')
246 switch(argv[0][1]){
247
248 case 0:
249 goto start;
250 case 'i':
251 stdi++;
252 continue;
253 case 'q':
254 quiet++;
255 if(tcgetattr(0, &ttys) >= 0) {
256 ttysavespace = ttys;
257 ttysave = 1;
258 }
259 continue;
260 case 'n':
261 npn = cnum(&argv[0][2]);
262 continue;
263 case 'p':
264 xflg = 0;
265 cps = cnum(&argv[0][2]);
266 continue;
267 case 'S':
268 stopmesg++;
269 continue;
270 case 's':
271 if(!(stop = cnum(&argv[0][2])))stop++;
272 continue;
273 case 'r':
274 vlist[findr(argv[0][2])] = cnum(&argv[0][3]);
275 continue;
276 case 'm':
277 p = &nextf[nfi];
278 q = &argv[0][2];
279 while((*p++ = *q++) != 0);
280 if (access(nextf, 4) < 0) {
281 char local[NS];
282
283 strlcpy(local, _PATH_LOCAL_TMAC, NS);
284 strlcat(local, &argv[0][2], NS);
285 if (access(local, 4) == 0)
286 strlcpy(nextf, local, NS);
287 }
288 mflg++;
289 continue;
290 case 'o':
291 getpn(&argv[0][2]);
292 continue;
293 #ifdef NROFF
294 case 'h':
295 hflg++;
296 continue;
297 case 'z':
298 no_out++;
299 continue;
300 case 'e':
301 eqflg++;
302 continue;
303 case 'B':
304 spflg = -1;
305 continue;
306 case 'T':
307 p = &termtab[tti];
308 q = &argv[0][2];
309 if(!((*q) & 0177))continue;
310 while((*p++ = *q++) != 0);
311 dotT++;
312 continue;
313 case 'c':
314 groffmode = 1;
315 continue;
316 #endif
317 #ifndef NROFF
318 case 'z':
319 no_out++;
320 case 'a':
321 ascii = 1;
322 nofeed++;
323 case 't':
324 ptid = 1;
325 continue;
326 case 'w':
327 waitf = 1;
328 continue;
329 case 'f':
330 nofeed++;
331 continue;
332 case 'x':
333 xflg = 0;
334 continue;
335 case 'b':
336 if(open(ptname,1) < 0)prstr("Busy.\n");
337 else prstr("Available.\n");
338 done3(0);
339 case 'g':
340 stop = ptid = gflag = 1;
341 dpn = 0;
342 continue;
343 case 'F':
344 {
345 extern char *fontfile;
346 fontfile = &argv[0][2];
347 }
348 continue;
349 #endif
350 default:
351 pto = cnum(&argv[0][1]);
352 continue;
353 }
354
355 if(argv[0][0] == '+'){
356 pfrom = cnum(&argv[0][1]);
357 print = 0;
358 if(argc > 0)goto options;
359 }
360
361 start:
362 argp = argv;
363 rargc = argc;
364 init2();
365 setjmp(sjbuf);
366 loop:
367 copyf = lgf = nb = nflush = nlflg = 0;
368 if(ip && (rbf0(ip)==0) && ejf && (frame->pframe <= ejl)){
369 nflush++;
370 trap = 0;
371 eject((struct s *)0);
372 goto loop;
373 }
374 i = getch();
375 if(pendt)goto lt;
376 if(lit && (frame <= litlev)){
377 lit--;
378 goto lt;
379 }
380 if((j = (i & CMASK)) == XPAR){
381 copyf++;
382 tflg++;
383 for(;(i & CMASK) != '\n';)pchar(i = getch());
384 tflg = 0;
385 copyf--;
386 goto loop;
387 }
388 if((j == cc) || (j == c2)){
389 if(j == c2)nb++;
390 copyf++;
391 while(((j=((i=getch()) & CMASK)) == ' ') ||
392 (j == '\t'));
393 ch = i;
394 copyf--;
395 control(getrq(),1);
396 flushi();
397 goto loop;
398 }
399 lt:
400 ch = i;
401 text();
402 goto loop;
403 }
404 void
catch()405 catch(){
406 /*
407 prstr("Interrupt\n");
408 */
409 done3(01);
410 }
411 void
fpecatch()412 fpecatch(){
413 prstrfl("Floating Exception.\n");
414 signal(SIGFPE,fpecatch);
415 }
416 void
kcatch()417 kcatch(){
418 signal(SIGTERM,SIG_IGN);
419 done3(01);
420 }
421 #ifndef NROFF
acctg()422 acctg() {
423 static char *acct_file = _PATH_TRACCT;
424 acctf = open(acct_file,1);
425 setuid(getuid());
426 }
427 #endif
init1(a)428 init1(a)
429 char a;
430 {
431 char *mktemp();
432 static char tempname[] = "/tmp/taXXXXX";
433 register i;
434 register char *p = tempname;
435
436 #ifndef NROFF
437 acctg();/*open troff actg file while mode 4755*/
438 #endif
439 #ifdef UNSAFE
440 p = mktemp(tempname);
441 if(a == 'a')p = &p[5];
442 if((close(creat(p, 0600))) < 0){
443 prstr("Cannot create temp file.\n");
444 exit(-1);
445 }
446 ibf = open(p, 2);
447 #else
448 ibf = mkstemp(tempname);
449 #endif
450 for(i=256; --i;)trtab[i]=i;
451 trtab[UNPAD] = ' ';
452 mchbits();
453 if(a != 'a')unlkp = p;
454 }
init2()455 init2()
456 {
457 register i,j;
458 extern int block;
459 extern char *setbrk();
460
461 ttyod = 2;
462 if (((ttyp = ttyname(1)) != NULL) && ascii)
463 mesg(0);
464 iflg = isatty(0) ? 0 : 1;
465 if(ascii)mesg(0);
466
467 if((!ptid) && (!waitf)){
468 if((ptid = open(ptname,1)) < 0){
469 prstr("Typesetter busy.\n");
470 done3(-2);
471 }
472 }
473 ptinit();
474 for(i=NEV; i--;)write(ibf, (char *)&block, EVS*sizeof(int));
475 olinep = oline;
476 ibufp = eibuf = ibuf;
477 v.hp = init = 0;
478 pinchar = inchar; /* XXX */
479 ioff = 0;
480 v.nl = -1;
481 cvtime();
482 frame = stk = (struct s *)setbrk(DELTA);
483 dip = &d[0];
484 nxf = frame + 1;
485 nx = mflg;
486 }
cvtime()487 cvtime()
488 {
489 extern time_t time();
490 time_t t;
491 register struct tm *tmp;
492
493 t = time((time_t *)0);
494 tmp = localtime(&t);
495 v.dy = tmp->tm_mday;
496 v.dw = tmp->tm_wday + 1;
497 v.yr = tmp->tm_year;
498 v.mo = tmp->tm_mon + 1;
499 }
cnum(a)500 cnum(a)
501 char *a;
502 {
503 register i;
504
505 ibufp = a;
506 eibuf = (char *) MAXPTR;
507 i = nr_atoi();
508 ch = 0;
509 return(i);
510 }
mesg(f)511 mesg(f)
512 int f;
513 {
514 struct stat cb;
515 static int mode = -1;
516
517 if (!f) {
518 stat(ttyp,&cb);
519 mode = (cb.st_mode);
520 chmod(ttyp,mode & ~022);
521 } else if (mode != -1)
522 chmod(ttyp,mode);
523 }
prstrfl(s)524 prstrfl(s)
525 char *s;
526 {
527 flusho();
528 prstr(s);
529 }
prstr(s)530 prstr(s)
531 char *s;
532 {
533 register i;
534 register char *j;
535
536 j = s;
537 for(i=0;*s;i++)s++;
538 write(ttyod,j,i);
539 }
control(a,b)540 control(a,b)
541 int a,b;
542 {
543 register i,j;
544 extern filep boff();
545
546 i = a;
547 if((i == 0) || ((j = findmn(i)) == -1))return(0);
548 if(contab[j].rq & MMASK){
549 nxf->nargs = 0;
550 if(b)collect();
551 flushi();
552 return(pushi(((filep)contab[j].x.mx)<<BLKBITS));
553 }else{
554 if(!b)return(0);
555 return((*contab[j].x.f)(0));
556 }
557 }
558
getrq()559 getrq(){
560 register i,j;
561
562 if(((i=getach()) == 0) ||
563 ((j=getach()) == 0))goto rtn;
564 i = PAIR(i,j);
565 rtn:
566 return(i);
567 }
getch()568 getch(){
569 register int i, j, k;
570
571 level++;
572 g0:
573 if(ch){
574 if(((i = ch) & CMASK) == '\n')nlflg++;
575 ch = 0;
576 level--;
577 return(i);
578 }
579
580 if(nlflg){
581 level--;
582 return('\n');
583 }
584
585 if((k = (i = getch0()) & CMASK) != ESC){
586 if(i & MOT)goto g2;
587 if(k == FLSS){
588 copyf++; raw++;
589 i = getch0();
590 if(!fi)flss = i;
591 copyf--; raw--;
592 goto g0;
593 }
594 if(k == RPT){
595 setrpt();
596 goto g0;
597 }
598 if(!copyf){
599 if((k == 'f') && lg && !lgf){
600 i = getlg(i);
601 goto g2;
602 }
603 if((k == fc) || (k == tabch) || (k == ldrch)){
604 if((i=setfield(k)) == 0)goto g0; else goto g2;
605 }
606 if(k == 010){
607 i = makem(-width(' ' | chbits));
608 goto g2;
609 }
610 }
611 goto g2;
612 }
613 k = (j = getch0()) & CMASK;
614 if(j & MOT){
615 i = j;
616 goto g2;
617 }
618 /*
619 if(k == tdelim){
620 i = TDELIM;
621 tdelim = IMP;
622 goto g2;
623 }
624 */
625 switch(k){
626
627 case '\n': /*concealed newline*/
628 goto g0;
629 case 'n': /*number register*/
630 setn();
631 goto g0;
632 case '*': /*string indicator*/
633 setstr();
634 goto g0;
635 case '$': /*argument indicator*/
636 seta();
637 goto g0;
638 case '{': /*LEFT*/
639 i = LEFT;
640 goto gx;
641 case '}': /*RIGHT*/
642 i = RIGHT;
643 goto gx;
644 case '"': /*comment*/
645 while(((i=getch0()) & CMASK ) != '\n');
646 goto g2;
647 case ESC: /*double backslash*/
648 i = eschar;
649 goto gx;
650 case 'e': /*printable version of current eschar*/
651 i = PRESC;
652 goto gx;
653 case ' ': /*unpaddable space*/
654 i = UNPAD;
655 goto gx;
656 case '|': /*narrow space*/
657 i = NARSP;
658 goto gx;
659 case '^': /*half of narrow space*/
660 i = HNSP;
661 goto gx;
662 case '\'': /*\(aa*/
663 i = 0222;
664 goto gx;
665 case '`': /*\(ga*/
666 i = 0223;
667 goto gx;
668 case '_': /*\(ul*/
669 i = 0224;
670 goto gx;
671 case '-': /*current font minus*/
672 i = 0210;
673 goto gx;
674 case '&': /*filler*/
675 i = FILLER;
676 goto gx;
677 case 'c': /*to be continued*/
678 i = CONT;
679 goto gx;
680 case ':': /*lem's char*/
681 i = COLON;
682 goto gx;
683 case '!': /*transparent indicator*/
684 i = XPAR;
685 goto gx;
686 case 't': /*tab*/
687 i = '\t';
688 goto g2;
689 case 'a': /*leader (SOH)*/
690 i = LEADER;
691 goto g2;
692 case '%': /*ohc*/
693 i = OHC;
694 goto g2;
695 case '.': /*.*/
696 i = '.';
697 gx:
698 i = (j & ~CMASK) | i;
699 goto g2;
700 }
701 if(!copyf)
702 switch(k){
703
704 case 'p': /*spread*/
705 spread++;
706 goto g0;
707 case '(': /*special char name*/
708 if((i=setch()) == 0)goto g0;
709 break;
710 case 's': /*size indicator*/
711 setps();
712 goto g0;
713 case 'f': /*font indicator*/
714 setfont(0);
715 goto g0;
716 case 'w': /*width function*/
717 setwd();
718 goto g0;
719 case 'v': /*vert mot*/
720 if(i = vmot())break;
721 goto g0;
722 case 'h': /*horiz mot*/
723 if(i = hmot())break;
724 goto g0;
725 case 'z': /*zero with char*/
726 i = setz();
727 break;
728 case 'l': /*hor line*/
729 setline();
730 goto g0;
731 case 'L': /*vert line*/
732 setvline();
733 goto g0;
734 case 'b': /*bracket*/
735 setbra();
736 goto g0;
737 case 'o': /*overstrike*/
738 setov();
739 goto g0;
740 case 'k': /*mark hor place*/
741 if((i=findr(getsn())) == -1)goto g0;
742 vlist[i] = v.hp = sumhp(); /* XXX */
743 goto g0;
744 case 'j': /*mark output hor place*/
745 if(!(i=getach()))goto g0;
746 i = (i<<BYTE) | JREG;
747 break;
748 case '0': /*number space*/
749 i = makem(width('0' | chbits));
750 break;
751 case 'x': /*extra line space*/
752 if(i = xlss())break;
753 goto g0;
754 case 'u': /*half em up*/
755 case 'r': /*full em up*/
756 case 'd': /*half em down*/
757 i = sethl(k);
758 break;
759 default:
760 i = j;
761 }
762 else{
763 ch0 = j;
764 i = eschar;
765 }
766 g2:
767 if((i & CMASK) == '\n'){
768 nlflg++;
769 v.hp = 0;
770 pinchar = inchar; /* XXX */
771 if(ip == 0)v.cd++;
772 }
773 if(!--level){
774 /* j = width(i); */
775 /* v.hp += j; */
776 /* cwidth = j; */
777 if (pinchar >= inchar + LNSIZE) { /* XXX */
778 inchar[0] = makem(sumhp());
779 pinchar = &inchar[1];
780 }
781 *pinchar++ = i; /* XXX */
782 }
783 return(i);
784 }
785
sumhp()786 sumhp() /* XXX - add up widths in inchar array */
787 {
788 register int n;
789 register int *p;
790
791 n = 0;
792 for (p = inchar; p < pinchar; p++)
793 n += width(*p);
794 return(n);
795 }
796 char ifilt[32] = {0,001,002,003,0,005,006,007,010,011,012};
getch0()797 getch0(){
798 register int i, j;
799
800 if(ch0){i=ch0; ch0=0; return(i);}
801 if(nchar){nchar--; return(rchar);}
802
803 again:
804 if(cp){
805 if((i = *cp++) == 0){
806 cp = 0;
807 goto again;
808 }
809 }else if(ap){
810 if((i = *ap++) == 0){
811 ap = 0;
812 goto again;
813 }
814 }else if(ip){
815 if(ip == -1)i = rdtty();
816 else i = rbf();
817 }else{
818 if(donef)done(0);
819 if(nx || ((ibufp >= eibuf) && (eibuf != (char *) MAXPTR))){
820 if(nfo)goto g1;
821 g0:
822 if(nextfile()){
823 if(ip)goto again;
824 if(ibufp < eibuf)goto g2;
825 }
826 g1:
827 nx = 0;
828 if((j=read(ifile,ibuf,IBUFSZ)) <= 0)goto g0;
829 ibufp = ibuf;
830 eibuf = ibuf + j;
831 if(ip)goto again;
832 }
833 g2:
834 i = *ibufp++ & 0177;
835 ioff++;
836 if(i >= 040)goto g4; else i = ifilt[i];
837 }
838 if(raw)return(i);
839 if((j = i & CMASK) == IMP)goto again;
840 if((i == 0) && !init)goto again;
841 g4:
842 if((copyf == 0) && ((i & ~BMASK) == 0) && ((i & CMASK) < 0370))
843 #ifndef NROFF
844 if(spbits && (i>31) && ((codetab[i-32] & 0200))) i |= spbits;
845 else
846 #endif
847 i |= chbits;
848 if((i & CMASK) == eschar)i = (i & ~CMASK) | ESC;
849 return(i);
850 }
nextfile()851 nextfile(){
852 register char *p;
853
854 n0:
855 if(ifile)close(ifile);
856 if(nx){
857 p = nextf;
858 if(*p != 0)goto n1;
859 }
860 if(ifi > 0){
861 if(popf())goto n0; /*popf error*/
862 return(1); /*popf ok*/
863 }
864 if(rargc-- <= 0)goto n2;
865 p = (argp++)[0];
866 n1:
867 if((p[0] == '-') && (p[1] == 0)){
868 ifile = 0;
869 }else if((ifile=open(p,0)) < 0){
870 prstr("Cannot open ");
871 prstr(p);
872 prstr("\n");
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)done(0);
882 nfo++;
883 v.cd = ifile = stdi = mflg = 0;
884 ioff = 0;
885 return(0);
886 }
popf()887 popf(){
888 register i;
889 register char *p, *q;
890
891 ioff = offl[--ifi];
892 ip = ipl[ifi];
893 if((ifile = ifl[ifi]) == 0){
894 p = xbuf;
895 q = ibuf;
896 ibufp = xbufp;
897 eibuf = xeibuf;
898 while(q < eibuf)*q++ = *p++;
899 return(0);
900 }
901 if((lseek(ifile,(long)(ioff & ~(IBUFSZ-1)),0) < 0) ||
902 ((i = read(ifile,ibuf,IBUFSZ)) < 0))return(1);
903 eibuf = ibuf + i;
904 ibufp = ibuf;
905 if(ttyname(ifile) == (char *)0)
906 if((ibufp = ibuf + (int)(ioff & (IBUFSZ-1))) >= eibuf)return(1);
907 return(0);
908 }
flushi()909 flushi(){
910 if(nflush)return;
911 ch = 0;
912 if((ch0 & CMASK) == '\n')nlflg++;
913 ch0 = 0;
914 copyf++;
915 while(!nlflg){
916 if(donef && (frame == stk))break;
917 getch();
918 }
919 copyf--;
920 v.hp = 0;
921 pinchar = inchar; /* XXX */
922 }
getach()923 getach(){
924 register i;
925
926 lgf++;
927 if(((i = getch()) & MOT) ||
928 ((i&CMASK) == ' ') ||
929 ((i&CMASK) == '\n')||
930 (i & 0200)){
931 ch = i;
932 i = 0;
933 }
934 lgf--;
935 return(i & 0177);
936 }
casenx()937 casenx(){
938 lgf++;
939 skip();
940 getname();
941 nx++;
942 nextfile();
943 nlflg++;
944 ip = 0;
945 ap = 0;
946 nchar = pendt = 0;
947 frame = stk;
948 nxf = frame + 1;
949 }
getname()950 getname(){
951 register int i, j, k;
952
953 lgf++;
954 for(k=0; k < (NS-1); k++){
955 if(((j=(i=getch()) & CMASK) <= ' ') ||
956 (j > 0176))break;
957 nextf[k] = j;
958 }
959 nextf[k] = 0;
960 ch = i;
961 lgf--;
962 return(nextf[0]);
963 }
caseso()964 caseso(){
965 register i;
966 register char *p, *q;
967
968 lgf++;
969 nextf[0] = 0;
970 if(skip() || !getname() || ((i=open(nextf,0)) <0) || (ifi >= NSO)) {
971 prstr("can't open file ");
972 prstr(nextf);
973 prstr("\n");
974 done(02);
975 }
976 flushi();
977 ifl[ifi] = ifile;
978 ifile = i;
979 offl[ifi] = ioff;
980 ioff = 0;
981 ipl[ifi] = ip;
982 ip = 0;
983 nx++;
984 nflush++;
985 if(!ifl[ifi++]){
986 p = ibuf;
987 q = xbuf;
988 xbufp = ibufp;
989 xeibuf = eibuf;
990 while(p < eibuf)*q++ = *p++;
991 }
992 }
993
casecf()994 casecf(){ /* copy file without change */
995 int fd, i, n;
996 char buf[OBUFSZ];
997
998 flusho();
999 lgf++;
1000 nextf[0] = 0;
1001 if(skip() || !getname() || ((fd=open(nextf,0)) <0) || (ifi >= NSO)) {
1002 prstr("can't open file ");
1003 prstr(nextf);
1004 prstr("\n");
1005 done(02);
1006 }
1007 while ((n = read(fd, buf, OBUFSZ)) > 0)
1008 for (i = 0; i < n; i++)
1009 oput(buf[i]);
1010 flusho();
1011 close(fd);
1012 }
getpn(a)1013 getpn(a)
1014 char *a;
1015 {
1016 register i, neg;
1017 long atoi1();
1018
1019 if((*a & 0177) == 0)return;
1020 neg = 0;
1021 ibufp = a;
1022 eibuf = (char *) MAXPTR;
1023 noscale++;
1024 while((i = getch() & CMASK) != 0)switch(i){
1025 case '+':
1026 case ',':
1027 continue;
1028 case '-':
1029 neg = MOT;
1030 goto d2;
1031 default:
1032 ch = i;
1033 d2:
1034 i = atoi1();
1035 if(nonumb)goto fini;
1036 else{
1037 *pnp++ = i | neg;
1038 neg = 0;
1039 if(pnp >= &pnlist[NPN-2]){
1040 prstr("Too many page numbers\n");
1041 done3(-3);
1042 }
1043 }
1044 }
1045 fini:
1046 if(neg)*pnp++ = -2;
1047 *pnp = -1;
1048 ch = noscale = print = 0;
1049 pnp = pnlist;
1050 if(*pnp != -1)chkpn();
1051 }
setrpt()1052 setrpt(){
1053 register i, j;
1054
1055 copyf++;raw++;
1056 i = getch0();
1057 copyf--;raw--;
1058 if((i < 0) ||
1059 (((j = getch0()) & CMASK) == RPT))return;
1060 rchar = j;
1061 nchar = i & BMASK;
1062 }
1063