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(&lt),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