1 /*-
2 * Copyright (c) 1979, 1980, 1981, 1986, 1988, 1990, 1991, 1992
3 * The Regents of the University of California.
4 * Copyright (C) Caldera International Inc. 2001-2002.
5 * Copyright (c) 2003, 2004, 2005, 2014
6 * Thorsten "mirabilos" Glaser <tg@mirbsd.org>
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms,
10 * with or without modification, are permitted provided
11 * that the following conditions are met:
12 *
13 * Redistributions of source code and documentation must retain
14 * the above copyright notice, this list of conditions and the
15 * following disclaimer. Redistributions in binary form must
16 * reproduce the above copyright notice, this list of conditions
17 * and the following disclaimer in the documentation and/or other
18 * materials provided with the distribution.
19 *
20 * All advertising materials mentioning features or use of this
21 * software must display the following acknowledgement:
22 * This product includes software developed or owned by
23 * Caldera International, Inc.
24 *
25 * Neither the name of Caldera International, Inc. nor the names
26 * of other contributors may be used to endorse or promote products
27 * derived from this software without specific prior written permission.
28 *
29 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
30 * INTERNATIONAL, INC. AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
31 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE
34 * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR
35 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
36 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
37 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
38 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
39 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
40 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 */
42
43 #include <sys/cdefs.h>
44 __SCCSID("@(#)n5.c 4.4 (Berkeley) 5/2/91");
45 __RCSID("$MirOS: src/usr.bin/oldroff/nroff/n5.c,v 1.7 2014/07/20 16:34:20 tg Exp $");
46
47 #include "tdef.h"
48 #include <termios.h>
49 extern
50 #include "d.h"
51 extern
52 #include "v.h"
53 #include "sdef.h"
54
55 /*
56 troff5.c
57
58 misc processing requests
59 */
60
61 extern int inchar[LNSIZE], *pinchar; /* XXX */
62 extern struct s *frame;
63 extern struct s *litlev;
64 extern filep ip;
65 extern filep offset;
66
67 extern int ascii;
68 extern int nonumb;
69 extern int admod;
70 extern int ad;
71 extern int fi;
72 extern int cc;
73 extern int c2;
74 extern int ohc;
75 extern int tabc;
76 extern int dotc;
77 extern int pendnf;
78 extern int hyf;
79 extern int ce;
80 extern int po;
81 extern int po1;
82 extern int nc;
83 extern int in;
84 extern int un;
85 extern int un1;
86 extern int in1;
87 extern int ll;
88 extern int ll1;
89 extern int lt;
90 extern int lt1;
91 extern int nlistx[NTRAP];
92 extern int mlist[NTRAP];
93 extern int lgf;
94 extern int pl;
95 extern int npn;
96 extern int npnflg;
97 extern int copyf;
98 extern char nextf[];
99 extern int trap;
100 extern int lss;
101 extern int em;
102 extern int evlist[EVLSZ];
103 extern int evi;
104 extern int ibf;
105 extern int ev;
106 extern int ch;
107 extern int nflush;
108 extern int tty;
109 extern struct termios ttys;
110 extern int quiet;
111 extern int iflg;
112 extern int eschar;
113 extern int lit;
114 extern int ls;
115 extern int ls1;
116 extern int tabtab[];
117 extern char trtab[];
118 extern int ul;
119 extern int cu;
120 extern int sfont;
121 extern int font;
122 extern int fontlab[];
123 extern int it;
124 extern int itmac;
125 extern int noscale;
126 extern int ic;
127 extern int icf;
128 extern int ics;
129 extern int *vlist;
130 extern int sv;
131 extern int esc;
132 extern int nn;
133 extern int nms;
134 extern int ndf;
135 extern int lnmod;
136 extern int ni;
137 extern int lnsize;
138 extern int nb;
139 extern int nlflg;
140 extern int apts, apts1, pts, pts1, font, font1;
141 extern int ulfont;
142 extern int ulbit;
143 extern int error;
144 extern int nmbits;
145 extern int chbits;
146 extern int tdelim;
147 extern int xxx;
148 extern int ecskip;
149 int iflist[NIF];
150 int ifx;
151
casead()152 casead(){
153 register i;
154
155 ad = 1;
156 /*leave admod alone*/
157 if(skip())return;
158 switch(i = getch() & CMASK){
159 case 'r': /*right adj, left ragged*/
160 admod = 2;
161 break;
162 case 'l': /*left adj, right ragged*/
163 admod = ad = 0; /*same as casena*/
164 break;
165 case 'c': /*centered adj*/
166 admod = 1;
167 break;
168 case 'b': case 'n':
169 admod = 0;
170 break;
171 case '0': case '2': case '4':
172 ad = 0;
173 case '1': case '3': case '5':
174 admod = (i - '0')/2;
175 }
176 }
casena()177 casena(){
178 ad = 0;
179 }
casefi()180 casefi(){
181 tbreak();
182 fi++;
183 pendnf = 0;
184 lnsize = LNSIZE;
185 }
casenf()186 casenf(){
187 tbreak();
188 fi = 0;
189 /* can't do while oline is only LNSIZE
190 lnsize = LNSIZE + WDSIZE;
191 */
192 }
casers()193 casers(){
194 dip->nls = 0;
195 }
casens()196 casens(){
197 dip->nls++;
198 }
chget(c)199 chget(c)
200 int c;
201 {
202 register i;
203
204 if(skip() ||
205 ((i = getch()) & MOT) ||
206 ((i&CMASK) == ' ') ||
207 ((i&CMASK) == '\n')){
208 ch = i;
209 return(c);
210 }else return(i & BMASK);
211 }
casecc()212 casecc(){
213 cc = chget('.');
214 }
casec2()215 casec2(){
216 c2 = chget('\'');
217 }
casehc()218 casehc(){
219 ohc = chget(OHC);
220 }
casetc()221 casetc(){
222 tabc = chget(0);
223 }
caselc()224 caselc(){
225 dotc = chget(0);
226 }
casehy()227 casehy(){
228 register i;
229
230 hyf = 1;
231 if(skip())return;
232 noscale++;
233 i = nr_atoi();
234 noscale = 0;
235 if(nonumb)return;
236 hyf = max(i,0);
237 }
casenh()238 casenh(){
239 hyf = 0;
240 }
max(aa,bb)241 max(aa,bb)
242 int aa,bb;
243 {
244 if(aa>bb)return(aa);
245 else return(bb);
246 }
casece()247 casece(){
248 register i;
249
250 noscale++;
251 skip();
252 i = max(nr_atoi(),0);
253 if(nonumb)i = 1;
254 tbreak();
255 ce = i;
256 noscale = 0;
257 }
casein()258 casein(){
259 register i;
260
261 if(skip())i = in1;
262 else i = max(hnumb(&in),0);
263 tbreak();
264 in1 = in;
265 in = i;
266 if(!nc){
267 un = in;
268 setnel();
269 }
270 }
casell()271 casell(){
272 register i;
273
274 if(skip())i = ll1;
275 else i = max(hnumb(&ll),INCH/10);
276 ll1 = ll;
277 ll = i;
278 setnel();
279 }
caselt()280 caselt(){
281 register i;
282
283 if(skip())i = lt1;
284 else i = max(hnumb(<),0);
285 lt1 = lt;
286 lt = i;
287 }
caseti()288 caseti(){
289 register i;
290
291 if(skip())return;
292 i = max(hnumb(&in),0);
293 tbreak();
294 un1 = i;
295 setnel();
296 }
casels()297 casels(){
298 register i;
299
300 noscale++;
301 if(skip())i = ls1;
302 else i = max(inumb(&ls),1);
303 ls1 = ls;
304 ls = i;
305 noscale = 0;
306 }
casepo()307 casepo(){
308 register i;
309
310 if(skip())i = po1;
311 else i = max(hnumb(&po),0);
312 po1 = po;
313 po = i;
314 #ifndef NROFF
315 if(!ascii)esc += po - po1;
316 #endif
317 }
casepl()318 casepl(){
319 register i;
320
321 skip();
322 if((i = vnumb(&pl)) == 0)pl = 11 * INCH; /*11in*/
323 else pl = i;
324 if(v.nl > pl)v.nl = pl;
325 }
casewh()326 casewh(){
327 register i, j, k;
328
329 lgf++;
330 skip();
331 i = vnumb((int *)0);
332 if(nonumb)return;
333 skip();
334 j = getrq();
335 if((k=findn(i)) != NTRAP){
336 mlist[k] = j;
337 return;
338 }
339 for(k=0; k<NTRAP; k++)if(mlist[k] == 0)break;
340 if(k == NTRAP){
341 prstrfl("Cannot plant trap.\n");
342 return;
343 }
344 mlist[k] = j;
345 nlistx[k] = i;
346 }
casech()347 casech(){
348 register i, j, k;
349
350 lgf++;
351 skip();
352 if(!(j=getrq()))return;
353 else for(k=0; k<NTRAP; k++)if(mlist[k] == j)break;
354 if(k == NTRAP)return;
355 skip();
356 i = vnumb((int *)0);
357 if(nonumb)mlist[k] = 0;
358 nlistx[k] = i;
359 }
findn(i)360 findn(i)
361 int i;
362 {
363 register k;
364
365 for(k=0; k<NTRAP; k++)
366 if((nlistx[k] == i) && (mlist[k] != 0))break;
367 return(k);
368 }
casepn()369 casepn(){
370 register i;
371
372 skip();
373 noscale++;
374 i = max(inumb(&v.pn),0);
375 noscale = 0;
376 if(!nonumb){
377 npn = i;
378 npnflg++;
379 }
380 }
casebp()381 casebp(){
382 register i;
383 register struct s *savframe;
384
385 if(dip != d)return;
386 savframe = frame;
387 skip();
388 if((i = inumb(&v.pn)) < 0)i = 0;
389 tbreak();
390 if(!nonumb){
391 npn = i;
392 npnflg++;
393 }else if(dip->nls)return;
394 eject(savframe);
395 }
casetm(x)396 casetm(x) int x;{
397 register i, ch;
398 char tmbuf[NTM];
399
400 lgf++;
401 copyf++;
402 if(skip() && x)prstrfl("User Abort.");
403 for (i = 0; i < NTM - 2; )
404 if ((tmbuf[i++] = ch = getch()) == '\n')
405 break;
406 else if (ch == UNPAD)
407 tmbuf[i-1] = ' ';
408 if(i == NTM-2)tmbuf[i++] = '\n';
409 tmbuf[i] = 0;
410 prstrfl(tmbuf);
411 copyf--;
412 }
casesp(a)413 casesp(a)
414 int a;
415 {
416 register i, j, savlss;
417
418 tbreak();
419 if(dip->nls || trap)return;
420 i = findt1();
421 if(!a){
422 skip();
423 j = vnumb((int *)0);
424 if(nonumb)j = lss;
425 }else j = a;
426 if(j == 0)return;
427 if(i < j)j = i;
428 savlss = lss;
429 if(dip != d)i = dip->dnl; else i = v.nl;
430 if((i + j) < 0)j = -i;
431 lss = j;
432 newline(0);
433 lss = savlss;
434 }
casert()435 casert(){
436 register a, *p;
437
438 skip();
439 if(dip != d)p = &dip->dnl; else p = &v.nl;
440 a = vnumb(p);
441 if(nonumb)a = dip->mkline;
442 if((a < 0) || (a >= *p))return;
443 nb++;
444 casesp(a - *p);
445 }
caseem()446 caseem(){
447 lgf++;
448 skip();
449 em = getrq();
450 }
casefl()451 casefl(){
452 tbreak();
453 flusho();
454 }
caseev()455 caseev(){
456 register nxev;
457 extern int block;
458
459 if(skip()){
460 e0:
461 if(evi == 0)return;
462 nxev = evlist[--evi];
463 goto e1;
464 }
465 noscale++;
466 nxev = nr_atoi();
467 noscale = 0;
468 if(nonumb)goto e0;
469 flushi();
470 if((nxev >= NEV) || (nxev < 0) || (evi >= EVLSZ)){
471 prstrfl("Cannot do ev.\n");
472 if(error)done2(040);else edone(040);
473 return;
474 }
475 evlist[evi++] = ev;
476 e1:
477 if(ev == nxev)return;
478 lseek(ibf, (long)(ev*EVS*sizeof(int)), 0);
479 write(ibf,(char *)&block, EVS*sizeof(int));
480 lseek(ibf, (long)(nxev*EVS*sizeof(int)), 0);
481 read(ibf,(char *)&block, EVS*sizeof(int));
482 ev = nxev;
483 }
caseel()484 caseel(){
485 if(--ifx < 0){
486 ifx = 0;
487 iflist[0] = 0;
488 }
489 caseif(2);
490 }
caseie()491 caseie(){
492 if(ifx >= NIF){
493 prstr("if-else overflow.\n");
494 ifx = 0;
495 edone(040);
496 }
497 caseif(1);
498 ifx++;
499 }
caseif(x)500 caseif(x)
501 int x;
502 {
503 register i, notflag, true;
504
505 if(x == 2){
506 notflag = 0;
507 true = iflist[ifx];
508 goto i1;
509 }
510 true = 0;
511 skip();
512 if(((i = getch()) & CMASK) == '!'){
513 notflag = 1;
514 }else{
515 notflag = 0;
516 ch = i;
517 }
518 i = nr_atoi();
519 if(!nonumb){
520 if(i > 0)true++;
521 goto i1;
522 }
523 switch((i = getch()) & CMASK){
524 case 'e':
525 if(!(v.pn & 01))true++;
526 break;
527 case 'o':
528 if(v.pn & 01)true++;
529 break;
530 #ifdef NROFF
531 case 'n':
532 true++;
533 case 't':
534 #endif
535 #ifndef NROFF
536 case 't':
537 true++;
538 case 'n':
539 #endif
540 case ' ':
541 break;
542 default:
543 true = cmpstr(i);
544 }
545 i1:
546 true ^= notflag;
547 if(x == 1)iflist[ifx] = !true;
548 if(true){
549 i2:
550 do{
551 v.hp = 0;
552 pinchar = inchar; /* XXX */
553 }
554 while(((i = getch()) & CMASK) == ' ');
555 if((i & CMASK) == LEFT)goto i2;
556 ch = i;
557 nflush++;
558 }else{
559 copyf++; ecskip++;
560 if(eat(LEFT) == LEFT){
561 while(eatblk(RIGHT,LEFT) != RIGHT)nlflg = 0;
562 }
563 copyf--; ecskip--;
564 }
565 }
eatblk(right,left)566 eatblk(right,left)
567 int right,left;
568 {
569 register i;
570
571 e0:
572 while(((i = getch() & CMASK) != right) &&
573 (i != left) &&
574 (i != '\n'));
575 if(i == left){
576 while((i=eatblk(right,left)) != right)nlflg = 0;
577 goto e0;
578 }
579 return(i);
580 }
cmpstr(delim)581 cmpstr(delim)
582 int delim;
583 {
584 register i, j;
585 register filep p;
586 extern filep alloc();
587 extern filep incoff();
588 filep begin;
589 int cnt, k;
590 int savapts, savapts1, savfont, savfont1,
591 savpts, savpts1;
592
593 if(delim & MOT)return(0);
594 delim &= CMASK;
595 if(dip != d)wbfl();
596 if((offset = begin = alloc()) == (filep)0)return(0);
597 cnt = 0;
598 v.hp = 0;
599 pinchar = inchar; /* XXX */
600 savapts = apts;
601 savapts1 = apts1;
602 savfont = font;
603 savfont1 = font1;
604 savpts = pts;
605 savpts1 = pts1;
606 while(((j = (i=getch()) & CMASK) != delim) && (j != '\n')){
607 wbf(i);
608 cnt++;
609 }
610 wbt(0);
611 k = !cnt;
612 if(nlflg)goto rtn;
613 p = begin;
614 apts = savapts;
615 apts1 = savapts1;
616 font = savfont;
617 font1 = savfont1;
618 pts = savpts;
619 pts1 = savpts1;
620 mchbits();
621 v.hp = 0;
622 pinchar = inchar; /* XXX */
623 while(((j = (i=getch()) & CMASK) != delim) && (j != '\n')){
624 if(rbf0(p) != i){
625 eat(delim);
626 k = 0;
627 break;
628 }
629 p = incoff(p);
630 k = !(--cnt);
631 }
632 rtn:
633 apts = savapts;
634 apts1 = savapts1;
635 font = savfont;
636 font1 = savfont1;
637 pts = savpts;
638 pts1 = savpts1;
639 mchbits();
640 offset = dip->op;
641 ffree(begin);
642 return(k);
643 }
caserd()644 caserd(){
645
646 lgf++;
647 skip();
648 getname();
649 if(!iflg){
650 if(quiet){
651 ttys.c_lflag &= ~ECHO;
652 tcsetattr(0, TCSAFLUSH, &ttys);
653 prstrfl(""); /*bell*/
654 }else{
655 if(nextf[0]){
656 prstr(nextf);
657 prstr(":");
658 }else{
659 prstr(""); /*bell*/
660 }
661 }
662 }
663 collect();
664 tty++;
665 pushi((filep)-1);
666 }
rdtty()667 rdtty(){
668 char onechar;
669
670 onechar = 0;
671 if(read(0, &onechar, 1) == 1){
672 if(onechar == '\n')tty++;
673 else tty = 1;
674 if(tty != 3)return(onechar);
675 }
676 popi();
677 tty = 0;
678 if(quiet){
679 ttys.c_lflag |= ECHO;
680 tcsetattr(0, TCSAFLUSH, &ttys);
681 }
682 return(0);
683 }
caseec()684 caseec(){
685 eschar = chget('\\');
686 }
caseeo()687 caseeo(){
688 eschar = 0;
689 }
caseli()690 caseli(){
691
692 skip();
693 lit = max(inumb((int *)0),1);
694 litlev = frame;
695 if((dip == d) && (v.nl == -1))newline(1);
696 }
caseta()697 caseta(){
698 register i;
699
700 tabtab[0] = nonumb = 0;
701 for(i=0; ((i < (NTAB-1)) && !nonumb); i++){
702 if(skip())break;
703 tabtab[i] = tabtab[max(i-1,0)] & TMASK;
704 tabtab[i] = max(hnumb(&tabtab[i]),0) & TMASK;
705 if(!nonumb) switch(ch & CMASK){
706 case 'C':
707 tabtab[i] |= CTAB;
708 break;
709 case 'R':
710 tabtab[i] |= RTAB;
711 break;
712 default: /*includes L*/
713 break;
714 }
715 nonumb = ch = 0;
716 }
717 tabtab[i] = 0;
718 }
casene()719 casene(){
720 register i, j;
721
722 skip();
723 i = vnumb((int *)0);
724 if(nonumb)i = lss;
725 if(i > (j = findt1())){
726 i = lss;
727 lss = j;
728 dip->nls = 0;
729 newline(0);
730 lss = i;
731 }
732 }
casetr()733 casetr(){
734 register i, j;
735
736 lgf++;
737 skip();
738 while((i = getch() & CMASK) != '\n'){
739 if((i & MOT) || ((j = getch()) & MOT))return;
740 if((j &= CMASK) == '\n')j = ' ';
741 trtab[i] = j;
742 }
743 }
casecu()744 casecu(){
745 cu++;
746 caseul();
747 }
caseul()748 caseul(){
749 register i;
750
751 noscale++;
752 if(skip())i = 1;
753 else i = nr_atoi();
754 if(ul && (i == 0)){
755 font = sfont;
756 ul = cu = 0;
757 }
758 if(i){
759 if(!ul){
760 sfont = font;
761 font = ulfont;
762 }
763 ul = i;
764 }
765 noscale = 0;
766 mchbits();
767 }
caseuf()768 caseuf(){
769 register i, j;
770
771 if(skip() || !(i = getrq()) || (i == 'S') ||
772 ((j = find(i,fontlab)) == -1))
773 ulfont = 1; /*default position 2*/
774 else ulfont = j;
775 #ifdef NROFF
776 if(ulfont == 0)ulfont = 1;
777 #endif
778 ulbit = ulfont<<9;
779 }
caseit()780 caseit(){
781 register i;
782
783 lgf++;
784 it = itmac = 0;
785 noscale++;
786 skip();
787 i = nr_atoi();
788 skip();
789 if(!nonumb && (itmac = getrq()))it = i;
790 noscale = 0;
791 }
casemc()792 casemc(){
793 register i;
794
795 if(icf > 1)ic = 0;
796 icf = 0;
797 if(skip())return;
798 ic = getch();
799 icf = 1;
800 skip();
801 i = max(hnumb((int *)0),0);
802 if(!nonumb)ics = i;
803 }
casemk()804 casemk(){
805 register i, j;
806
807 if(dip != d)j = dip->dnl; else j = v.nl;
808 if(skip()){
809 dip->mkline = j;
810 return;
811 }
812 if((i = getrq()) == 0)return;
813 vlist[findr(i)] = j;
814 }
casesv()815 casesv(){
816 register i;
817
818 skip();
819 if((i = vnumb((int *)0)) < 0)return;
820 if(nonumb)i = 1;
821 sv += i;
822 caseos();
823 }
caseos()824 caseos(){
825 register savlss;
826
827 if(sv <= findt1()){
828 savlss = lss;
829 lss = sv;
830 newline(0);
831 lss = savlss;
832 sv = 0;
833 }
834 }
casenm()835 casenm(){
836 register i;
837
838 lnmod = nn = 0;
839 if(skip())return;
840 lnmod++;
841 noscale++;
842 i = inumb(&v.ln);
843 if(!nonumb)v.ln = max(i,0);
844 getnm(&ndf,1);
845 getnm(&nms,0);
846 getnm(&ni,0);
847 noscale = 0;
848 nmbits = chbits;
849 }
getnm(p,min)850 getnm(p,min)
851 int *p, min;
852 {
853 register i;
854
855 eat(' ');
856 if(skip())return;
857 i = nr_atoi();
858 if(nonumb)return;
859 *p = max(i,min);
860 }
casenn()861 casenn(){
862 noscale++;
863 skip();
864 nn = max(nr_atoi(),1);
865 noscale = 0;
866 }
caseab()867 caseab(){
868 dummy();
869 casetm(1);
870 done2(0);
871 }
872