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