1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 
31 /*	from OpenSolaris "n5.c	1.10	05/06/08 SMI"	*/
32 
33 /*
34  * Portions Copyright (c) 2005 Gunnar Ritter, Freiburg i. Br., Germany
35  *
36  * Sccsid @(#)n5.c	1.130 (gritter) 10/23/09
37  */
38 
39 /*
40  * Changes Copyright (c) 2014, 2015 Carsten Kunze <carsten.kunze at arcor.de>
41  */
42 
43 /*
44  * University Copyright- Copyright (c) 1982, 1986, 1988
45  * The Regents of the University of California
46  * All Rights Reserved
47  *
48  * University Acknowledgment- Portions of this document are derived from
49  * software developed by the University of California, Berkeley, and its
50  * contributors.
51  */
52 
53 #include <sys/types.h>
54 #include <sys/stat.h>
55 #include <fcntl.h>
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <ctype.h>
59 #include <limits.h>
60 #if defined (EUC)
61 #include <stddef.h>
62 #include <wchar.h>
63 #endif	/* EUC */
64 #include <string.h>
65 #include <unistd.h>
66 #include "tdef.h"
67 #include "ext.h"
68 #ifdef	NROFF
69 #include "tw.h"
70 #endif
71 #include "pt.h"
72 
73 /*
74  * troff5.c
75  *
76  * misc processing requests
77  */
78 
79 void
casead(void)80 casead(void)
81 {
82 	register int i;
83 
84 	ad = 1;
85 	/*leave admod alone*/
86 	if (skip(0))
87 		return;
88 	pa = 0;
89 loop:
90 	switch (i = cbits(getch())) {
91 	case 'r':	/*right adj, left ragged*/
92 		admod = 2;
93 		break;
94 	case 'l':	/*left adj, right ragged*/
95 		admod = ad = 0;	/*same as casena*/
96 		break;
97 	case 'c':	/*centered adj*/
98 		admod = 1;
99 		break;
100 	case 'b':
101 	case 'n':
102 		admod = 0;
103 		break;
104 	case '0':
105 	case '2':
106 	case '4':
107 		ad = 0;
108 	case '1':
109 	case '3':
110 	case '5':
111 		admod = (i - '0') / 2;
112 		break;
113 	case 'p':
114 	case '7':
115 		if (xflag) {
116 			pa = 1;
117 			admod = 0;
118 			goto loop;
119 		}
120 	}
121 }
122 
123 
124 void
casena(void)125 casena(void)
126 {
127 	ad = 0;
128 }
129 
130 
131 void
casefi(void)132 casefi(void)
133 {
134 	tbreak();
135 	fi++;
136 	pendnf = 0;
137 }
138 
139 
140 void
casenf(void)141 casenf(void)
142 {
143 	tbreak();
144 	fi = 0;
145 }
146 
147 
148 void
casepadj(void)149 casepadj(void)
150 {
151 	int	n;
152 
153 	if (skip(0))
154 		padj = 1;
155 	else {
156 		n = hatoi();
157 		if (!nonumb)
158 			padj = n;
159 	}
160 }
161 
162 
163 void
casers(void)164 casers(void)
165 {
166 	dip->nls = 0;
167 }
168 
169 
170 void
casens(void)171 casens(void)
172 {
173 	dip->nls++;
174 }
175 
176 
177 void
casespreadwarn(void)178 casespreadwarn(void)
179 {
180 	if (skip(0))
181 		spreadwarn = !spreadwarn;
182 	else {
183 		dfact = EM;
184 		spreadlimit = inumb(&spreadlimit);
185 		spreadwarn = 1;
186 	}
187 }
188 
189 
190 int
chget(int c)191 chget(int c)
192 {
193 	tchar i = 0;
194 
195 	charf++;
196 	if (skip(0) || ismot(i = getch()) || cbits(i) == ' ' || cbits(i) == '\n') {
197 		ch = i;
198 		return(c);
199 	} else
200 		return(cbits(i));
201 }
202 
203 
204 void
casecc(void)205 casecc(void)
206 {
207 	cc = chget('.');
208 }
209 
210 
211 void
casec2(void)212 casec2(void)
213 {
214 	c2 = chget('\'');
215 }
216 
217 
218 void
casehc(void)219 casehc(void)
220 {
221 	ohc = chget(OHC);
222 }
223 
224 
225 void
casetc(void)226 casetc(void)
227 {
228 	tabc = chget(0);
229 }
230 
231 
232 void
caselc(void)233 caselc(void)
234 {
235 	dotc = chget(0);
236 }
237 
238 
239 void
casehy(void)240 casehy(void)
241 {
242 	register int i;
243 
244 	hyf = 1;
245 	if (skip(0))
246 		return;
247 	noscale++;
248 	i = hatoi();
249 	noscale = 0;
250 	if (nonumb)
251 		return;
252 	hyf = max(i, 0);
253 }
254 
255 
256 void
casenh(void)257 casenh(void)
258 {
259 	hyf = 0;
260 }
261 
262 
263 void
casehlm(void)264 casehlm(void)
265 {
266 	int	i;
267 
268 	if (!skip(0)) {
269 		noscale++;
270 		i = hatoi();
271 		noscale = 0;
272 		if (!nonumb)
273 			hlm = i;
274 	} else
275 		hlm = -1;
276 }
277 
278 void
casehcode(void)279 casehcode(void)
280 {
281 	tchar	c, d;
282 	int	k;
283 
284 	lgf++;
285 	if (skip(1))
286 		return;
287 	do {
288 		c = getch();
289 		if (skip(1))
290 			break;
291 		d = getch();
292 		if (c && d && !ismot(c) && !ismot(d)) {
293 			if ((k = cbits(c)) >= nhcode) {
294 				hcode = realloc(hcode, (k+1) * sizeof *hcode);
295 				memset(&hcode[nhcode], 0,
296 					(k+1-nhcode) * sizeof *hcode);
297 				nhcode = k+1;
298 			}
299 			hcode[k] = cbits(d);
300 		}
301 	} while (!skip(0));
302 }
303 
304 void
caseshc(void)305 caseshc(void)
306 {
307 	shc = skip(0) ? 0 : getch();
308 }
309 
310 void
casehylen(void)311 casehylen(void)
312 {
313 	int	n;
314 
315 	if (skip(0))
316 		hylen = 5;
317 	else {
318 		n = hatoi();
319 		if (!nonumb)
320 			hylen = n;
321 	}
322 }
323 
324 void
casehypp(void)325 casehypp(void)
326 {
327 	float	t;
328 
329 	if (skip(0))
330 		hypp = hypp2 = hypp3 = 0;
331 	else {
332 		t = atop();
333 		if (!nonumb)
334 			hypp = t;
335 		if (skip(0))
336 			hypp2 = hypp3 = 0;
337 		else {
338 			t = atop();
339 			if (!nonumb)
340 				hypp2 = t;
341 			if (skip(0))
342 				hypp3 = 0;
343 			else {
344 				t = atop();
345 				if (!nonumb)
346 					hypp3 = t;
347 			}
348 		}
349 	}
350 }
351 
352 static void
chkin(int indent,int linelength,const char * note)353 chkin(int indent, int linelength, const char *note)
354 {
355 	if (indent > linelength - INCH / 10) {
356 		if (warn & WARN_RANGE)
357 			errprint("excess of %sindent", note);
358 	}
359 }
360 
361 void
casepshape(void)362 casepshape(void)
363 {
364 	int	i, l;
365 	int	lastin = in, lastll = ll;
366 
367 	pshapes = 0;
368 	if (skip(0)) {
369 		pshapes = 0;
370 		return;
371 	}
372 	do {
373 		i = max(hnumb(&lastin), 0);
374 		if (nonumb)
375 			break;
376 		if (skip(0))
377 			l = ll;
378 		else {
379 			l = max(hnumb(&lastll), INCH / 10);
380 			if (nonumb)
381 				break;
382 		}
383 		if (pshapes >= pgsize)
384 			growpgsize();
385 		chkin(i, l, "");
386 		pgin[pshapes] = i;
387 		pgll[pshapes] = l;
388 		pshapes++;
389 		lastin = i;
390 		lastll = l;
391 	} while (!skip(0));
392 }
393 
394 void
caselpfx(void)395 caselpfx(void)
396 {
397 	int	n;
398 	tchar	c;
399 
400 	if (skip(0)) {
401 		free(lpfx);
402 		lpfx = NULL;
403 		nlpfx = 0;
404 	} else {
405 		for (n = 0; ; n++) {
406 			if (n+1 >= nlpfx) {
407 				nlpfx += 10;
408 				lpfx = realloc(lpfx, nlpfx * sizeof *lpfx);
409 			}
410 			c = getch();
411 			if (nlflg)
412 				break;
413 			if (n == 0 && cbits(c) == '"')
414 				continue;
415 			lpfx[n] = c;
416 		}
417 		lpfx[n] = 0;
418 	}
419 }
420 
421 int
max(int aa,int bb)422 max(int aa, int bb)
423 {
424 	if (aa > bb)
425 		return(aa);
426 	else
427 		return(bb);
428 }
429 
430 int
min(int aa,int bb)431 min(int aa, int bb)
432 {
433 	if (aa < bb)
434 		return(aa);
435 	else
436 		return(bb);
437 }
438 
439 
440 static void
cerj(int dorj)441 cerj(int dorj)
442 {
443 	register int i;
444 
445 	noscale++;
446 	skip(0);
447 	i = max(hatoi(), 0);
448 	if (nonumb)
449 		i = 1;
450 	tbreak();
451 	if (dorj) {
452 		rj = i;
453 		ce = 0;
454 	} else {
455 		ce = i;
456 		rj = 0;
457 	}
458 	noscale = 0;
459 }
460 
461 
462 void
casece(void)463 casece(void)
464 {
465 	cerj(0);
466 }
467 
468 
469 void
caserj(void)470 caserj(void)
471 {
472 	if (xflag)
473 		cerj(1);
474 }
475 
476 
477 static void
_brnl(int p)478 _brnl(int p)
479 {
480 	int	n;
481 
482 	noscale++;
483 	if (skip(0))
484 		n = INT_MAX;
485 	else {
486 		n = hatoi();
487 		if (nonumb || n < 0)
488 			n = p ? brpnl : brpnl;
489 	}
490 	noscale--;
491 	tbreak();
492 	if (p) {
493 		brpnl = n;
494 		brnl = 0;
495 	} else {
496 		brnl = n;
497 		brpnl = 0;
498 	}
499 }
500 
501 
502 void
casebrnl(void)503 casebrnl(void)
504 {
505 	_brnl(0);
506 }
507 
508 
509 void
casebrpnl(void)510 casebrpnl(void)
511 {
512 	_brnl(1);
513 }
514 
515 
516 void
casein(void)517 casein(void)
518 {
519 	register int i;
520 
521 	if ((pa || padj) && pglines == 0 && pgchars)
522 		tbreak();
523 	if (skip(0))
524 		i = in1;
525 	else
526 		i = max(hnumb(&in), 0);
527 	tbreak();
528 	in1 = in;
529 	in = i;
530 	chkin(in, ll, "");
531 	if (!nc && !pgwords) {
532 		un = in;
533 		setnel();
534 	} else if (pgwords) {
535 		pgflags[pgwords] |= PG_NEWIN;
536 		pgwdin[pgwords] = in;
537 	}
538 }
539 
540 
541 void
casell(void)542 casell(void)
543 {
544 	register int i;
545 
546 	if (skip(0))
547 		i = ll1;
548 	else
549 		i = max(hnumb(&ll), INCH / 10);
550 	ll1 = ll;
551 	ll = i;
552 	chkin(in, ll, "");
553 	setnel();
554 	if (pgwords) {
555 		pgflags[pgwords] |= PG_NEWLL;
556 		pgwdll[pgwords] = ll;
557 	}
558 }
559 
560 
561 void
caselt(void)562 caselt(void)
563 {
564 	register int i;
565 
566 	if (skip(0))
567 		i = lt1;
568 	else
569 		i = max(hnumb(&lt), 0);
570 	lt1 = lt;
571 	lt = i;
572 }
573 
574 
575 void
caseti(void)576 caseti(void)
577 {
578 	register int i;
579 
580 	if (skip(1))
581 		return;
582 	if ((pa || padj) && pglines == 0 && pgchars)
583 		tbreak();
584 	i = max(hnumb(&in), 0);
585 	tbreak();
586 	un1 = i;
587 	chkin(i, ll, "temporary ");
588 	setnel();
589 }
590 
591 
592 void
casels(void)593 casels(void)
594 {
595 	register int i;
596 
597 	noscale++;
598 	if (skip(0))
599 		i = ls1;
600 	else
601 		i = max(inumb(&ls), 1);
602 	ls1 = ls;
603 	ls = i;
604 	noscale = 0;
605 }
606 
607 
608 void
casepo(void)609 casepo(void)
610 {
611 	register int i;
612 
613 	if (skip(0))
614 		i = po1;
615 	else
616 		i = max(hnumb(&po), 0);
617 	po1 = po;
618 	po = i;
619 #ifndef NROFF
620 	if (!ascii)
621 		esc += po - po1;
622 #endif
623 }
624 
625 
626 void
casepl(void)627 casepl(void)
628 {
629 	register int i;
630 
631 	skip(0);
632 	if ((i = vnumb(&pl)) == 0)
633 		pl = defaultpl ? defaultpl : 11 * INCH; /*11in*/
634 	else
635 		pl = i;
636 	if (numtab[NL].val > pl) {
637 		numtab[NL].val = pl;
638 		prwatchn(&numtab[NL]);
639 	}
640 }
641 
642 
643 static void
chkt(struct d * dp,int n)644 chkt(struct d *dp, int n)
645 {
646 	if (n <= 0 && dp != d)
647 		if (warn & WARN_RANGE)
648 			errprint("trap at %d not effective in diversion", n);
649 }
650 
651 
652 static void
_casewh(struct d * dp)653 _casewh(struct d *dp)
654 {
655 	register int i, j, k;
656 
657 	lgf++;
658 	skip(1);
659 	i = vnumb((int *)0);
660 	if (nonumb)
661 		return;
662 	skip(0);
663 	j = getrq(1);
664 	if ((k = findn(dp, i)) != NTRAP) {
665 		dp->mlist[k] = j;
666 		return;
667 	}
668 	for (k = 0; k < NTRAP; k++)
669 		if (dp->mlist[k] == 0)
670 			break;
671 	if (k == NTRAP) {
672 		flusho();
673 		errprint("cannot plant trap.");
674 		return;
675 	}
676 	dp->mlist[k] = j;
677 	dp->nlist[k] = i;
678 	chkt(dp, i);
679 }
680 
681 
682 void
casewh(void)683 casewh(void)
684 {
685 	_casewh(d);
686 }
687 
688 
689 void
casedwh(void)690 casedwh(void)
691 {
692 	_casewh(dip);
693 }
694 
695 
696 static void
_casech(struct d * dp)697 _casech(struct d *dp)
698 {
699 	register int i, j, k;
700 
701 	lgf++;
702 	skip(1);
703 	if (!(j = getrq(0)))
704 		return;
705 	else  {
706 		for (k = 0; k < NTRAP; k++)
707 			if (dp->mlist[k] == j)
708 				break;
709 	}
710 	if (k == NTRAP)
711 		return;
712 	skip(0);
713 	i = vnumb((int *)0);
714 	if (nonumb)
715 		dp->mlist[k] = 0;
716 	dp->nlist[k] = i;
717 	chkt(dp, i);
718 }
719 
720 
721 void
casech(void)722 casech(void)
723 {
724 	_casech(d);
725 }
726 
727 
728 void
casedch(void)729 casedch(void)
730 {
731 	_casech(dip);
732 }
733 
734 
735 void
casevpt(void)736 casevpt(void)
737 {
738 	if (skip(1))
739 		return;
740 	vpt = hatoi() != 0;
741 }
742 
743 
744 tchar
setolt(void)745 setolt(void)
746 {
747 	storerq(getsn(1));
748 	return mkxfunc(OLT, 0);
749 }
750 
751 
752 int
findn(struct d * dp,int i)753 findn(struct d *dp, int i)
754 {
755 	register int k;
756 
757 	for (k = 0; k < NTRAP; k++)
758 		if ((dp->nlist[k] == i) && (dp->mlist[k] != 0))
759 			break;
760 	return(k);
761 }
762 
763 
764 void
casepn(void)765 casepn(void)
766 {
767 	register int i;
768 
769 	skip(1);
770 	noscale++;
771 	i = max(inumb(&numtab[PN].val), 0);
772 	prwatchn(&numtab[PN]);
773 	noscale = 0;
774 	if (!nonumb) {
775 		npn = i;
776 		npnflg++;
777 	}
778 }
779 
780 
781 void
casebp(void)782 casebp(void)
783 {
784 	register int i;
785 	register struct s *savframe;
786 
787 	if (dip != d)
788 		return;
789 	savframe = frame;
790 	if (skip(0))
791 		i = -1;
792 	else {
793 		if ((i = inumb(&numtab[PN].val)) < 0)
794 			i = 0;
795 		if (nonumb)
796 			i = -1;
797 	}
798 	tbreak();
799 	if (i >= 0) {
800 		npn = i;
801 		npnflg++;
802 	} else if (dip->nls && donef < 1)
803 		return;
804 	eject(savframe);
805 }
806 
807 
808 static void
tmtmcwr(int ab,int tmc,int wr,int ep,int tmm)809 tmtmcwr(int ab, int tmc, int wr, int ep, int tmm)
810 {
811 	const char tmtab[] = {
812 		'a',000,000,000,000,000,000,000,
813 		000,000,000,000,000,000,000,000,
814 		'{','}','&',000,'%','c','e',' ',
815 		'!',000,000,000,000,000,000,'~',
816 		000
817 	};
818 	struct contab	*cp;
819 	register int i, j;
820 	tchar	c;
821 	char	tmbuf[NTM];
822 	filep	savip = ip;
823 	int	discard = 0;
824 
825 	lgf++;
826 	if (tmm) {
827 		if (skip(1) || (i = getrq(0)) == 0)
828 			return;
829 		if ((cp = findmn(i)) == NULL || !cp->mx) {
830 			nosuch(i);
831 			return;
832 		}
833 		savip = ip;
834 		ip = (filep)cp->mx;
835 		app++;
836 		copyf++;
837 	} else {
838 		copyf++;
839 		if (skip(0) && ab)
840 			errprint("User Abort");
841 	}
842 loop:	for (i = 0; i < NTM - 5 - mb_cur_max; ) {
843 		if (tmm) {
844 			if ((c = rbf()) == 0) {
845 				ip = savip;
846 				tmm = 0;
847 				app--;
848 				break;
849 			}
850 		} else
851 			c = getch();
852 		if (discard) {
853 			discard--;
854 			continue;
855 		}
856 		if (c == '\n') {
857 			tmbuf[i++] = '\n';
858 			break;
859 		}
860 	c:	j = cbits(c);
861 		if (iscopy(c)) {
862 			int	n;
863 			if ((n = wctomb(&tmbuf[i], j)) > 0) {
864 				i += n;
865 				continue;
866 			}
867 		}
868 		if (xflag == 0) {
869 			tmbuf[i++] = c;
870 			continue;
871 		}
872 		if (ismot(c))
873 			continue;
874 		tmbuf[i++] = '\\';
875 		if (c == (OHC|BLBIT))
876 			j = ':';
877 		else if (istrans(c))
878 			j = ')';
879 		else if (j >= 0 && j < sizeof tmtab && tmtab[j])
880 			j = tmtab[j];
881 		else if (j == ACUTE)
882 			j = '\'';
883 		else if (j == GRAVE)
884 			j = '`';
885 		else if (j == UNDERLINE)
886 			j = '_';
887 		else if (j == MINUS)
888 			j = '-';
889 		else {
890 			i--;
891 			if (c == WORDSP)
892 				j = ' ';
893 			else if (j == WORDSP)
894 				continue;
895 			else if (j == FLSS) {
896 				discard++;
897 				continue;
898 			}
899 		}
900 		if (j == XFUNC)
901 			switch (fbits(c)) {
902 			case CHAR:
903 				c = charout[sbits(c)].ch;
904 				goto c;
905 			default:
906 				continue;
907 			}
908 		tmbuf[i++] = j;
909 	}
910 	if (i == NTM - 2)
911 		tmbuf[i++] = '\n';
912 	if (tmc)
913 		i--;
914 	tmbuf[i] = 0;
915 	if (ab)	/* truncate output */
916 		obufp = obuf;	/* should be a function in n2.c */
917 	if (ep) {
918 		flusho();
919 		errprint("%s", tmbuf);
920 	} else if (wr < 0) {
921 		flusho();
922 		fprintf(stderr, "%s", tmbuf);
923 	} else if (i)
924 		write(wr, tmbuf, i);
925 	if (tmm)
926 		goto loop;
927 	copyf--;
928 	lgf--;
929 }
930 
931 void
casetm(int ab)932 casetm(int ab)
933 {
934 	tmtmcwr(ab, 0, -1, 0, 0);
935 }
936 
937 void
casetmc(void)938 casetmc(void)
939 {
940 	tmtmcwr(0, 1, -1, 0, 0);
941 }
942 
943 void
caseerrprint(void)944 caseerrprint(void)
945 {
946 	tmtmcwr(0, 1, -1, 1, 0);
947 }
948 
949 static struct stream {
950 	char	*name;
951 	int	fd;
952 } *streams;
953 static int	nstreams;
954 
955 static void
open1(int flags)956 open1(int flags)
957 {
958 	int	ns = nstreams;
959 
960 	lgf++;
961 	if (skip(1) || !getname() || skip(1))
962 		return;
963 	streams = realloc(streams, sizeof *streams * ++nstreams);
964 	streams[ns].name = malloc(NS);
965 	n_strcpy(streams[ns].name, nextf, NS);
966 	getname();
967 	if ((streams[ns].fd = open(nextf, flags, 0666)) < 0) {
968 		errprint("can't open file %s", nextf);
969 		done(02);
970 	}
971 }
972 
973 void
caseopen(void)974 caseopen(void)
975 {
976 	open1(O_WRONLY|O_CREAT|O_TRUNC);
977 }
978 
979 void
caseopena(void)980 caseopena(void)
981 {
982 	open1(O_WRONLY|O_CREAT|O_APPEND);
983 }
984 
985 static int
getstream(const char * name)986 getstream(const char *name)
987 {
988 	int	i;
989 
990 	for (i = 0; i < nstreams; i++)
991 		if (strcmp(streams[i].name, name) == 0)
992 			return i;
993 	errprint("no such stream %s", name);
994 	return -1;
995 }
996 
997 static void
write1(int writec,int writem)998 write1(int writec, int writem)
999 {
1000 	int	i;
1001 
1002 	lgf++;
1003 	if (skip(1) || !getname())
1004 		return;
1005 	if ((i = getstream(nextf)) < 0)
1006 		return;
1007 	tmtmcwr(0, writec, streams[i].fd, 0, writem);
1008 }
1009 
1010 void
casewrite(void)1011 casewrite(void)
1012 {
1013 	write1(0, 0);
1014 }
1015 
1016 void
casewritec(void)1017 casewritec(void)
1018 {
1019 	write1(1, 0);
1020 }
1021 
1022 void
casewritem(void)1023 casewritem(void)
1024 {
1025 	write1(0, 1);
1026 }
1027 
1028 void
caseclose(void)1029 caseclose(void)
1030 {
1031 	int	i;
1032 
1033 	lgf++;
1034 	if (skip(1) || !getname())
1035 		return;
1036 	if ((i = getstream(nextf)) < 0)
1037 		return;
1038 	free(streams[i].name);
1039 	memmove(&streams[i], &streams[i+1], (nstreams-i-1) * sizeof *streams);
1040 	nstreams--;
1041 }
1042 
1043 
1044 void
casesp(int a)1045 casesp(int a)
1046 {
1047 	register int i, j, savlss;
1048 
1049 	tbreak();
1050 	if (dip->nls || trap)
1051 		return;
1052 	i = findt1();
1053 	if (!a) {
1054 		skip(0);
1055 		j = vnumb((int *)0);
1056 		if (nonumb)
1057 			j = lss;
1058 	} else
1059 		j = a;
1060 	if (j == 0)
1061 		return;
1062 	if (i < j)
1063 		j = i;
1064 	savlss = lss;
1065 	if (dip != d)
1066 		i = dip->dnl;
1067 	else
1068 		i = numtab[NL].val;
1069 	if ((i + j) < 0)
1070 		j = -i;
1071 	lss = j;
1072 	newline(0);
1073 	lss = savlss;
1074 }
1075 
1076 
1077 void
casebrp(void)1078 casebrp(void)
1079 {
1080 	if (nc || pgchars) {
1081 		spread = 2;
1082 		flushi();
1083 		if (pgchars)
1084 			tbreak();
1085 		else {
1086 			pendt++;
1087 			text();
1088 		}
1089 	} else
1090 		tbreak();
1091 }
1092 
1093 
1094 void
caseblm(void)1095 caseblm(void)
1096 {
1097 	if (!skip(0))
1098 		blmac = getrq(1);
1099 	else
1100 		blmac = 0;
1101 }
1102 
1103 void
caselsm(void)1104 caselsm(void)
1105 {
1106 	if (!skip(0))
1107 		lsmac = getrq(1);
1108 	else
1109 		lsmac = 0;
1110 }
1111 
1112 void
casert(void)1113 casert(void)
1114 {
1115 	register int a, *p;
1116 
1117 	skip(0);
1118 	if (dip != d)
1119 		p = &dip->dnl;
1120 	else
1121 		p = &numtab[NL].val;
1122 	a = vnumb(p);
1123 	if (nonumb)
1124 		a = dip->mkline;
1125 	if ((a < 0) || (a >= *p))
1126 		return;
1127 	nb++;
1128 	casesp(a - *p);
1129 }
1130 
1131 
1132 void
caseem(void)1133 caseem(void)
1134 {
1135 	lgf++;
1136 	skip(1);
1137 	em = getrq(1);
1138 }
1139 
1140 
1141 void
casefl(void)1142 casefl(void)
1143 {
1144 	tbreak();
1145 	flusho();
1146 }
1147 
1148 
1149 static struct evnames {
1150 	int	number;
1151 	char	*name;
1152 } *evnames;
1153 static struct env	*evp;
1154 static int	*evlist;
1155 static int	evi;
1156 static int	evlsz;
1157 static int	Nev = NEV;
1158 
1159 static struct env *
findev(int * number,char * name)1160 findev(int *number, char *name)
1161 {
1162 	int	i;
1163 
1164 	if (*number < 0)
1165 		return &evp[-1 - (*number)];
1166 	else if (name) {
1167 		for (i = 0; i < Nev-NEV; i++)
1168 			if (evnames[i].name != NULL &&
1169 					strcmp(evnames[i].name, name) == 0) {
1170 				*number = -1 - i;
1171 				return &evp[i];
1172 			}
1173 		*number = -1 - i;
1174 		return NULL;
1175 	} else if (*number >= NEV) {
1176 		for (i = 0; i < Nev-NEV; i++)
1177 			if (evnames[i].name == NULL &&
1178 					evnames[i].number == *number)
1179 				return &evp[i];
1180 		*number = -1 - i;
1181 		return NULL;
1182 	} else {
1183 		extern tchar *corebuf;
1184 		return &((struct env *)corebuf)[*number];
1185 	}
1186 }
1187 
1188 static int
getev(int * nxevp,char ** namep)1189 getev(int *nxevp, char **namep)
1190 {
1191 	char	*name = NULL;
1192 	int nxev = 0;
1193 	int	c;
1194 	int	i = 0, sz = 0, valid = 1;
1195 
1196 	*namep = NULL;
1197 	*nxevp = 0;
1198 	if (skip(0))
1199 		return 0;
1200 	c = cbits(ch);
1201 	if (xflag == 0 || isdigit(c) || c == '(') {
1202 		noscale++;
1203 		nxev = hatoi();
1204 		noscale = 0;
1205 		if (nonumb) {
1206 			flushi();
1207 			return 0;
1208 		}
1209 	} else {
1210 		do {
1211 			c = rgetach();
1212 			if (i >= sz)
1213 				name = realloc(name, (sz += 8) * sizeof *name);
1214 			name[i++] = c;
1215 		} while (c);
1216 		if (*name == 0) {
1217 			free(name);
1218 			name = NULL;
1219 			valid = 0;
1220 		}
1221 	}
1222 	flushi();
1223 	*namep = name;
1224 	*nxevp = nxev;
1225 	return valid;
1226 }
1227 
1228 void
caseev(void)1229 caseev(void)
1230 {
1231 	char	*name;
1232 	int nxev;
1233 	struct env	*np, *op;
1234 
1235 	if (getev(&nxev, &name) == 0) {
1236 		if (evi == 0)
1237 			return;
1238 		nxev =  evlist[--evi];
1239 		goto e1;
1240 	}
1241 	if (xflag == 0 && ((nxev >= NEV) || (nxev < 0) || (evi >= EVLSZ)))
1242 		goto cannot;
1243 	if (evi >= evlsz) {
1244 		evlsz = evi + 1;
1245 		if ((evlist = realloc(evlist, evlsz * sizeof *evlist)) == NULL)
1246 			goto cannot;
1247 	}
1248 	if ((name && findev(&nxev, name) == NULL) || nxev >= Nev) {
1249 		if ((evp = realloc(evp, (Nev-NEV+1) * sizeof *evp)) == NULL ||
1250 				(evnames = realloc(evnames,
1251 				   (Nev-NEV+1) * sizeof *evnames)) == NULL)
1252 			goto cannot;
1253 		evnames[Nev-NEV].number = nxev;
1254 		evnames[Nev-NEV].name = name;
1255 		evp[Nev-NEV] = initenv;
1256 		Nev++;
1257 	}
1258 	if (name == NULL && nxev < 0) {
1259 		flusho();
1260 	cannot:	errprint("cannot do ev.");
1261 		if (error)
1262 			done2(040);
1263 		else
1264 			edone(040);
1265 		return;
1266 	}
1267 	evlist[evi++] = ev;
1268 e1:
1269 	if (ev == nxev)
1270 		return;
1271 	if ((np = findev(&nxev, name)) == NULL ||
1272 			(op = findev(&ev, NULL)) == NULL)
1273 		goto cannot;
1274 	*op = env;
1275 	env = *np;
1276 	ev = nxev;
1277 	if (evname == NULL) {
1278 		if (name)
1279 			evname = name;
1280 		else {
1281 			size_t l = 20;
1282 			evname = malloc(l);
1283 			roff_sprintf(evname, l, "%d", ev);
1284 		}
1285 	}
1286 }
1287 
1288 void
caseevc(void)1289 caseevc(void)
1290 {
1291 	char	*name;
1292 	int	nxev;
1293 	struct env	*ep;
1294 
1295 	if (getev(&nxev, &name) == 0 || (ep = findev(&nxev, name)) == NULL)
1296 		return;
1297 	relsev(&env);
1298 	evc(&env, ep);
1299 }
1300 
1301 void
evc(struct env * dp,struct env * sp)1302 evc(struct env *dp, struct env *sp)
1303 {
1304 	if (dp != sp) {
1305 		char *name;
1306 		name = dp->_evname;
1307 		memcpy(dp, sp, sizeof *dp);
1308 		dp->_evname = name;
1309 	}
1310 	if (sp->_hcode) {
1311 		dp->_hcode = malloc(dp->_nhcode * sizeof *dp->_hcode);
1312 		memcpy(dp->_hcode, sp->_hcode, dp->_nhcode *
1313 		    sizeof *dp->_hcode);
1314 	}
1315 	if (sp->_lpfx) {
1316 		dp->_lpfx = malloc(dp->_nlpfx * sizeof *dp->_lpfx);
1317 		memcpy(dp->_lpfx, sp->_lpfx, dp->_nlpfx * sizeof *dp->_lpfx);
1318 	}
1319 	dp->_pendnf = 0;
1320 	dp->_pendw = 0;
1321 	dp->_pendt = 0;
1322 	dp->_wch = 0;
1323 	dp->_wne = 0;
1324 	dp->_wsp = 0;
1325 	dp->_wdstart = 0;
1326 	dp->_wdend = 0;
1327 	dp->_lnsize = 0;
1328 	dp->_line = NULL;
1329 	dp->_linep = NULL;
1330 	dp->_wdsize = 0;
1331 	dp->_word = 0;
1332 	dp->_wdpenal = 0;
1333 	dp->_wordp = 0;
1334 	dp->_spflg = 0;
1335 	dp->_seflg = 0;
1336 	dp->_ce = 0;
1337 	dp->_rj = 0;
1338 	dp->_pgsize = 0;
1339 	dp->_pgcsize = 0;
1340 	dp->_pgssize = 0;
1341 	dp->_pglines = 0;
1342 	dp->_pgwords = 0;
1343 	dp->_pgchars = 0;
1344 	dp->_pgspacs = 0;
1345 	dp->_para = NULL;
1346 	dp->_parsp = NULL;
1347 	dp->_pgwordp = NULL;
1348 	dp->_pgspacp = NULL;
1349 	dp->_pgwordw = NULL;
1350 	dp->_pghyphw = NULL;
1351 	dp->_pgadspc = NULL;
1352 	dp->_pglsphc = NULL;
1353 	dp->_pgopt = NULL;
1354 	dp->_pgspacw = NULL;
1355 	dp->_pglgsc = NULL;
1356 	dp->_pglgec = NULL;
1357 	dp->_pglgsw = NULL;
1358 	dp->_pglgew = NULL;
1359 	dp->_pglgsh = NULL;
1360 	dp->_pglgeh = NULL;
1361 	dp->_pgin = NULL;
1362 	dp->_pgll = NULL;
1363 	dp->_pgwdin = NULL;
1364 	dp->_pgwdll = NULL;
1365 	dp->_pgflags = NULL;
1366 	dp->_pglno = NULL;
1367 	dp->_pgpenal = NULL;
1368 	dp->_inlevp = NULL;
1369 	if (dp->_brnl < INT_MAX)
1370 		dp->_brnl = 0;
1371 	if (dp->_brpnl < INT_MAX)
1372 		dp->_brpnl = 0;
1373 	dp->_nn = 0;
1374 	dp->_ndf = 0;
1375 	dp->_nms = 0;
1376 	dp->_ni = 0;
1377 	dp->_ul = 0;
1378 	dp->_cu = 0;
1379 	dp->_it = 0;
1380 	dp->_itc = 0;
1381 	dp->_itmac = 0;
1382 	dp->_nc = 0;
1383 	dp->_un = 0;
1384 	dp->_un1 = -1;
1385 	dp->_nwd = 0;
1386 	dp->_hyoff = 0;
1387 	dp->_nb = 0;
1388 	dp->_spread = 0;
1389 	dp->_lnmod = 0;
1390 	dp->_hlc = 0;
1391 	dp->_cht = 0;
1392 	dp->_cdp = 0;
1393 	dp->_maxcht = 0;
1394 	dp->_maxcdp = 0;
1395 	setnel();
1396 }
1397 
1398 void
evcline(struct env * dp,struct env * sp)1399 evcline(struct env *dp, struct env *sp)
1400 {
1401 	if (dp == sp)
1402 		return;
1403 #ifndef	NROFF
1404 	dp->_lspnc = sp->_lspnc;
1405 	dp->_lsplow = sp->_lsplow;
1406 	dp->_lsphigh = sp->_lsphigh;
1407 	dp->_lspcur = sp->_lspcur;
1408 	dp->_lsplast = sp->_lsplast;
1409 	dp->_lshwid = sp->_lshwid;
1410 	dp->_lshlow = sp->_lshlow;
1411 	dp->_lshhigh = sp->_lshhigh;
1412 	dp->_lshcur = sp->_lshcur;
1413 #endif
1414 	dp->_fldcnt = sp->_fldcnt;
1415 	dp->_hyoff = sp->_hyoff;
1416 	dp->_hlc = sp->_hlc;
1417 	dp->_nel = sp->_nel;
1418 	dp->_adflg = sp->_adflg;
1419 	dp->_adspc = sp->_adspc;
1420 	dp->_wne = sp->_wne;
1421 	dp->_wsp = sp->_wsp;
1422 	dp->_ne = sp->_ne;
1423 	dp->_nc = sp->_nc;
1424 	dp->_nwd = sp->_nwd;
1425 	dp->_un = sp->_un;
1426 	dp->_wch = sp->_wch;
1427 	dp->_rhang = sp->_rhang;
1428 	dp->_cht = sp->_cht;
1429 	dp->_cdp = sp->_cdp;
1430 	dp->_maxcht = sp->_maxcht;
1431 	dp->_maxcdp = sp->_maxcdp;
1432 	if (icf == 0)
1433 		dp->_ic = sp->_ic;
1434 	memcpy(dp->_hyptr, sp->_hyptr, NHYP * sizeof *sp->_hyptr);
1435 	dp->_line = malloc((dp->_lnsize = sp->_lnsize) * sizeof *dp->_line);
1436 	memcpy(dp->_line, sp->_line, sp->_lnsize * sizeof *sp->_line);
1437 	dp->_word = malloc((dp->_wdsize = sp->_wdsize) * sizeof *dp->_word);
1438 	memcpy(dp->_word, sp->_word, sp->_wdsize * sizeof *sp->_word);
1439 	dp->_wdpenal = malloc((dp->_wdsize = sp->_wdsize) *
1440 			sizeof *dp->_wdpenal);
1441 	memcpy(dp->_wdpenal, sp->_wdpenal, sp->_wdsize * sizeof *sp->_wdpenal);
1442 	dp->_linep = sp->_linep + (dp->_line - sp->_line);
1443 	dp->_wordp = sp->_wordp + (dp->_word - sp->_word);
1444 	dp->_wdend = sp->_wdend + (dp->_word - sp->_word);
1445 	dp->_wdstart = sp->_wdstart + (dp->_word - sp->_word);
1446 	dp->_para = malloc((dp->_pgcsize = sp->_pgcsize) * sizeof *dp->_para);
1447 	memcpy(dp->_para, sp->_para, dp->_pgcsize * sizeof *sp->_para);
1448 	dp->_parsp = malloc((dp->_pgssize = sp->_pgssize) * sizeof *dp->_parsp);
1449 	memcpy(dp->_parsp, sp->_parsp, dp->_pgssize * sizeof *sp->_parsp);
1450 	dp->_pgsize = sp->_pgsize;
1451 	dp->_pgwordp = malloc(dp->_pgsize * sizeof *dp->_pgwordp);
1452 	memcpy(dp->_pgwordp, sp->_pgwordp, dp->_pgsize * sizeof *dp->_pgwordp);
1453 	dp->_pgwordw = malloc(dp->_pgsize * sizeof *dp->_pgwordw);
1454 	memcpy(dp->_pgwordw, sp->_pgwordw, dp->_pgsize * sizeof *dp->_pgwordw);
1455 	dp->_pghyphw = malloc(dp->_pgsize * sizeof *dp->_pghyphw);
1456 	memcpy(dp->_pghyphw, sp->_pghyphw, dp->_pgsize * sizeof *dp->_pghyphw);
1457 	dp->_pgadspc = malloc(dp->_pgsize * sizeof *dp->_pgadspc);
1458 	memcpy(dp->_pgadspc, sp->_pgadspc, dp->_pgsize * sizeof *dp->_pgadspc);
1459 	dp->_pglsphc = malloc(dp->_pgsize * sizeof *dp->_pglsphc);
1460 	memcpy(dp->_pglsphc, sp->_pglsphc, dp->_pgsize * sizeof *dp->_pglsphc);
1461 	dp->_pgopt = malloc(dp->_pgsize * sizeof *dp->_pgopt);
1462 	memcpy(dp->_pgopt, sp->_pgopt, dp->_pgsize * sizeof *dp->_pgopt);
1463 	dp->_pgspacw = malloc(dp->_pgsize * sizeof *dp->_pgspacw);
1464 	memcpy(dp->_pgspacw, sp->_pgspacw, dp->_pgsize * sizeof *dp->_pgspacw);
1465 	dp->_pgspacp = malloc(dp->_pgsize * sizeof *dp->_pgspacp);
1466 	memcpy(dp->_pgspacp, sp->_pgspacp, dp->_pgsize * sizeof *dp->_pgspacp);
1467 	dp->_pglgsc = malloc(dp->_pgsize * sizeof *dp->_pglgsc);
1468 	memcpy(dp->_pglgsc, sp->_pglgsc, dp->_pgsize * sizeof *dp->_pglgsc);
1469 	dp->_pglgec = malloc(dp->_pgsize * sizeof *dp->_pglgec);
1470 	memcpy(dp->_pglgec, sp->_pglgec, dp->_pgsize * sizeof *dp->_pglgec);
1471 	dp->_pglgsw = malloc(dp->_pgsize * sizeof *dp->_pglgsw);
1472 	memcpy(dp->_pglgsw, sp->_pglgsw, dp->_pgsize * sizeof *dp->_pglgsw);
1473 	dp->_pglgew = malloc(dp->_pgsize * sizeof *dp->_pglgew);
1474 	memcpy(dp->_pglgew, sp->_pglgew, dp->_pgsize * sizeof *dp->_pglgew);
1475 	dp->_pglgsh = malloc(dp->_pgsize * sizeof *dp->_pglgsh);
1476 	memcpy(dp->_pglgsh, sp->_pglgsh, dp->_pgsize * sizeof *dp->_pglgsh);
1477 	dp->_pglgeh = malloc(dp->_pgsize * sizeof *dp->_pglgeh);
1478 	memcpy(dp->_pglgeh, sp->_pglgeh, dp->_pgsize * sizeof *dp->_pglgeh);
1479 	dp->_pgin = malloc(dp->_pgsize * sizeof *dp->_pgin);
1480 	memcpy(dp->_pgin, sp->_pgin, dp->_pgsize * sizeof *dp->_pgin);
1481 	dp->_pgll = malloc(dp->_pgsize * sizeof *dp->_pgll);
1482 	memcpy(dp->_pgll, sp->_pgll, dp->_pgsize * sizeof *dp->_pgll);
1483 	dp->_pgwdin = malloc(dp->_pgsize * sizeof *dp->_pgwdin);
1484 	memcpy(dp->_pgwdin, sp->_pgwdin, dp->_pgsize * sizeof *dp->_pgwdin);
1485 	dp->_pgwdll = malloc(dp->_pgsize * sizeof *dp->_pgwdll);
1486 	memcpy(dp->_pgwdll, sp->_pgwdll, dp->_pgsize * sizeof *dp->_pgwdll);
1487 	dp->_pgflags = malloc(dp->_pgsize * sizeof *dp->_pgflags);
1488 	memcpy(dp->_pgflags, sp->_pgflags, dp->_pgsize * sizeof *dp->_pgflags);
1489 	dp->_pglno = malloc(dp->_pgsize * sizeof *dp->_pglno);
1490 	memcpy(dp->_pglno, sp->_pglno, dp->_pgsize * sizeof *dp->_pglno);
1491 	dp->_pgpenal = malloc(dp->_pgsize * sizeof *dp->_pgpenal);
1492 	memcpy(dp->_pgpenal, sp->_pgpenal, dp->_pgsize * sizeof *dp->_pgpenal);
1493 	dp->_inlevp = malloc(dp->_ainlev * sizeof *dp->_inlevp);
1494 	memcpy(dp->_inlevp, sp->_inlevp, dp->_ninlev * sizeof *dp->_inlevp);
1495 	dp->_pgwords = sp->_pgwords;
1496 	dp->_pgchars = sp->_pgchars;
1497 	dp->_pgspacs = sp->_pgspacs;
1498 	dp->_pglines = sp->_pglines;
1499 }
1500 
1501 void
relsev(struct env * ep)1502 relsev(struct env *ep)
1503 {
1504 	free(ep->_hcode);
1505 	ep->_hcode = NULL;
1506 	ep->_nhcode = 0;
1507 	free(ep->_line);
1508 	ep->_line = NULL;
1509 	ep->_lnsize = 0;
1510 	free(ep->_word);
1511 	ep->_word = NULL;
1512 	free(ep->_wdpenal);
1513 	ep->_wdpenal = NULL;
1514 	ep->_wdsize = 0;
1515 	free(ep->_para);
1516 	ep->_para = NULL;
1517 	ep->_pgcsize = 0;
1518 	free(ep->_pgwordp);
1519 	ep->_pgwordp = NULL;
1520 	free(ep->_pgwordw);
1521 	ep->_pgwordw = NULL;
1522 	free(ep->_pghyphw);
1523 	ep->_pghyphw = NULL;
1524 	free(ep->_pgadspc);
1525 	ep->_pgadspc = NULL;
1526 	free(ep->_pglsphc);
1527 	ep->_pglsphc = NULL;
1528 	free(ep->_pgopt);
1529 	ep->_pgopt = NULL;
1530 	free(ep->_pgspacw);
1531 	ep->_pgspacw = NULL;
1532 	free(ep->_pgspacp);
1533 	ep->_pgspacp = NULL;
1534 	free(ep->_pglgsc);
1535 	ep->_pglgsc = NULL;
1536 	free(ep->_pglgec);
1537 	ep->_pglgec = NULL;
1538 	free(ep->_pglgsw);
1539 	ep->_pglgsw = NULL;
1540 	free(ep->_pglgew);
1541 	ep->_pglgew = NULL;
1542 	free(ep->_pglgsh);
1543 	ep->_pglgsh = NULL;
1544 	free(ep->_pglgeh);
1545 	ep->_pglgeh = NULL;
1546 	free(ep->_pgin);
1547 	ep->_pgin = NULL;
1548 	free(ep->_pgll);
1549 	ep->_pgll = NULL;
1550 	free(ep->_pgwdin);
1551 	ep->_pgwdin = NULL;
1552 	free(ep->_pgwdll);
1553 	ep->_pgwdll = NULL;
1554 	free(ep->_pgflags);
1555 	ep->_pgflags = NULL;
1556 	free(ep->_pglno);
1557 	ep->_pglno = NULL;
1558 	free(ep->_pgpenal);
1559 	ep->_pgpenal = NULL;
1560 	ep->_pgsize = 0;
1561 	free(ep->_inlevp);
1562 	ep->_inlevp = NULL;
1563 	ep->_ninlev = 0;
1564 	ep->_ainlev = 0;
1565 }
1566 
1567 void
caseel(void)1568 caseel(void)
1569 {
1570 	caseif(2);
1571 }
1572 
1573 void
caseie(void)1574 caseie(void)
1575 {
1576 	caseif(1);
1577 }
1578 
1579 int	tryglf;
1580 
1581 void
caseif(int x)1582 caseif(int x)
1583 {
1584 	extern int falsef;
1585 	register int notflag, true;
1586 	tchar i, j;
1587 	enum warn w = warn;
1588 	int	flt = 0;
1589 	static int el;
1590 
1591 	if (x == 3)
1592 		goto i2;
1593 	if (x == 2) {
1594 		notflag = 0;
1595 		true = el;
1596 		el = 0;
1597 		goto i1;
1598 	}
1599 	true = 0;
1600 	skip(1);
1601 	if ((cbits(i = getch())) == '!') {
1602 		notflag = 1;
1603 		if (xflag == 0)
1604 			/*EMPTY*/;
1605 		else if ((cbits(i = getch())) == 'f')
1606 			flt = 1;
1607 		else
1608 			ch = i;
1609 	} else if (xflag && cbits(i) == 'f') {
1610 		flt = 1;
1611 		notflag = 0;
1612 	} else {
1613 		notflag = 0;
1614 		ch = i;
1615 	}
1616 	if (flt)
1617 		i = atof0() > 0;
1618 	else
1619 		i = (int)atoi0();
1620 	if (!nonumb) {
1621 		if (i > 0)
1622 			true++;
1623 		goto i1;
1624 	}
1625 	i = getch();
1626 	switch (cbits(i)) {
1627 	case 'e':
1628 		if (!(numtab[PN].val & 01))
1629 			true++;
1630 		break;
1631 	case 'o':
1632 		if (numtab[PN].val & 01)
1633 			true++;
1634 		break;
1635 #ifdef NROFF
1636 	case 'n':
1637 		true++;
1638 	case 't':
1639 #endif
1640 #ifndef NROFF
1641 	case 't':
1642 		true++;
1643 	case 'n':
1644 #endif
1645 		break;
1646 	case 'c':
1647 		if (xflag == 0)
1648 			goto dfl;
1649 		warn &= ~WARN_CHAR;
1650 		tryglf++;
1651 		if (!skip(1)) {
1652 			j = getch();
1653 			true = !ismot(j) && cbits(j) && cbits(j) != ' ';
1654 		}
1655 		tryglf--;
1656 		warn = w;
1657 		break;
1658 	case 'r':
1659 	case 'd':
1660 		if (xflag == 0)
1661 			goto dfl;
1662 		warn &= ~(WARN_MAC|WARN_SPACE|WARN_REG);
1663 		if (!skip(1)) {
1664 			j = getrq(2);
1665 			true = (cbits(i) == 'r' ?
1666 					usedr(j) != NULL : findmn(j) != NULL);
1667 		}
1668 		warn = w;
1669 		break;
1670 	case 'F':
1671 		if (xflag == 0)
1672 			goto dfl;
1673 		if (!skip(1)) {
1674 			j = getrq(3);
1675 			true = findft(j, 0) != -1;
1676 		}
1677 		break;
1678 	case 'v':
1679 		/* break; */
1680 	case ' ':
1681 		break;
1682 	default:
1683 	dfl:	true = cmpstr(i);
1684 	}
1685 i1:
1686 	true ^= notflag;
1687 	if (x == 1) {
1688 		el = !true;
1689 	}
1690 	if (true) {
1691 		if (frame->loopf & LOOP_EVAL) {
1692 			if (nonumb)
1693 				goto i3;
1694 			frame->loopf &= ~LOOP_EVAL;
1695 			frame->loopf |= LOOP_NEXT;
1696 		}
1697 i2:
1698 		noschr = 0;
1699 		bol = 1;
1700 		while ((cbits(i = getch())) == ' ')
1701 			;
1702 		bol = 0;
1703 		if (cbits(i) == LEFT)
1704 			goto i2;
1705 		ch = i;
1706 		nflush++;
1707 	} else {
1708 i3:
1709 		if (frame->loopf & LOOP_EVAL)
1710 			frame->loopf = LOOP_FREE;
1711 		copyf++;
1712 		falsef++;
1713 		eatblk(0);
1714 		copyf--;
1715 		falsef--;
1716 	}
1717 }
1718 
1719 void
casenop(void)1720 casenop(void)
1721 {
1722 	caseif(3);
1723 }
1724 
1725 void
casechomp(void)1726 casechomp(void) {
1727 	chomp = 1;
1728 	caseif(3);
1729 }
1730 
1731 void
casereturn(void)1732 casereturn(void)
1733 {
1734 	flushi();
1735 	nflush++;
1736 	while (frame->loopf) {
1737 		frame->loopf = LOOP_FREE;
1738 		popi();
1739 	}
1740 	popi();
1741 }
1742 
1743 void
casewhile(void)1744 casewhile(void)
1745 {
1746 	tchar	c;
1747 	int	k, level;
1748 	filep	newip;
1749 
1750 	if (dip != d)
1751 		wbfl();
1752 	if ((nextb = alloc()) == 0) {
1753 		errprint("out of space");
1754 		edone(04);
1755 		return;
1756 	}
1757 	newip = offset = nextb;
1758 	wbf(mkxfunc(CC, 0));
1759 	wbf(XFUNC);	/* caseif */
1760 	wbf(' ');
1761 	copyf++, clonef++;
1762 	level = 0;
1763 	do {
1764 		nlflg = 0;
1765 		k = cbits(c = getch());
1766 		switch (k) {
1767 		case LEFT:
1768 			level++;
1769 			break;
1770 		case RIGHT:
1771 			level--;
1772 			break;
1773 		}
1774 		wbf(c);
1775 	} while (!nlflg || level > 0);
1776 	if (level < 0 && warn & WARN_DELIM)
1777 		errprint("%d excess delimiter(s)", -level);
1778 	wbt(0);
1779 	copyf--, clonef--;
1780 	pushi(newip, LOOP, 0);
1781 	offset = dip->op;
1782 }
1783 
1784 void
casebreak(void)1785 casebreak(void)
1786 {
1787 	casecontinue(1);
1788 }
1789 
1790 void
casecontinue(int _break)1791 casecontinue(int _break)
1792 {
1793 	int	i, j;
1794 	struct s	*s;
1795 
1796 	noscale++;
1797 	if (skip(0) || (i = hatoi()) <= 0 || nonumb)
1798 		i = 1;
1799 	noscale--;
1800 	j = 0;
1801 	for (s = frame; s != stk; s = s->pframe)
1802 		if (s->loopf && ++j >= i)
1803 			break;
1804 	if (j != i) {
1805 		if (i == 1) {
1806 			if (warn & WARN_RANGE)
1807 				errprint("%s outside loop", macname(lastrq));
1808 			return;
1809 		}
1810 		if (warn & WARN_RANGE)
1811 			errprint("%s: breaking out of %d current loop "
1812 					"levels but %d requested",
1813 				macname(lastrq), j, i);
1814 		_break = 1;
1815 		i = j;
1816 	}
1817 	flushi();
1818 	nflush++;
1819 	while (i > 1 || (_break && i > 0)) {
1820 		if (frame->loopf) {
1821 			frame->loopf = LOOP_FREE;
1822 			i--;
1823 		}
1824 		popi();
1825 	}
1826 	if (i == 1) {
1827 		while (frame->loopf == 0)
1828 			popi();
1829 		popi();
1830 	}
1831 }
1832 
1833 void
eatblk(int inblk)1834 eatblk(int inblk)
1835 {	register int cnt, i;
1836 	tchar	ii;
1837 
1838 	cnt = 0;
1839 	do {
1840 		if (ch)	{
1841 			i = cbits(ii = ch);
1842 			ch = 0;
1843 		} else
1844 			i = cbits(ii = getch0());
1845 		if (i == ESC)
1846 			cnt++;
1847 		else {
1848 			if (cnt == 1)
1849 				switch (i) {
1850 				case '{':  i = LEFT; break;
1851 				case '}':  i = RIGHT; break;
1852 				case '\n': i = 'x'; break;
1853 				}
1854 			cnt = 0;
1855 		}
1856 		if (i == LEFT) eatblk(1);
1857 	} while ((!inblk && (i != '\n')) || (inblk && (i != RIGHT)));
1858 	if (i == '\n') {
1859 		nlflg++;
1860 		tailflg = istail(ii);
1861 	}
1862 }
1863 
1864 
1865 int
cmpstr(tchar c)1866 cmpstr(tchar c)
1867 {
1868 	register int j, delim;
1869 	register tchar i;
1870 	register int val;
1871 	int savapts, savapts1, savfont, savfont1, savpts, savpts1;
1872 	tchar string[1280];
1873 	register tchar *sp;
1874 
1875 	if (ismot(c))
1876 		return(0);
1877 	argdelim = delim = cbits(c);
1878 	savapts = apts;
1879 	savapts1 = apts1;
1880 	savfont = font;
1881 	savfont1 = font1;
1882 	savpts = pts;
1883 	savpts1 = pts1;
1884 	sp = string;
1885 	while ((j = cbits(i = getch()))!=delim && j!='\n' && sp<&string[1280-1])
1886 		*sp++ = i;
1887 	if (j != delim)
1888 		nodelim(delim);
1889 	if (sp >= string + 1280) {
1890 		errprint("too-long string compare.");
1891 		edone(0100);
1892 	}
1893 	if (nlflg) {
1894 		val = sp==string;
1895 		goto rtn;
1896 	}
1897 	*sp++ = 0;
1898 	apts = savapts;
1899 	apts1 = savapts1;
1900 	font = savfont;
1901 	font1 = savfont1;
1902 	pts = savpts;
1903 	pts1 = savpts1;
1904 	mchbits();
1905 	val = 1;
1906 	sp = string;
1907 	while ((j = cbits(i = getch())) != delim && j != '\n') {
1908 		if (*sp != i) {
1909 			eat(delim);
1910 			val = 0;
1911 			goto rtn;
1912 		}
1913 		sp++;
1914 	}
1915 	if (j != delim)
1916 		nodelim(delim);
1917 	if (*sp)
1918 		val = 0;
1919 rtn:
1920 	apts = savapts;
1921 	apts1 = savapts1;
1922 	font = savfont;
1923 	font1 = savfont1;
1924 	pts = savpts;
1925 	pts1 = savpts1;
1926 	mchbits();
1927 	argdelim = 0;
1928 	return(val);
1929 }
1930 
1931 
1932 void
caserd(void)1933 caserd(void)
1934 {
1935 
1936 	lgf++;
1937 	skip(0);
1938 	getname();
1939 	if (!iflg) {
1940 		if (quiet) {
1941 #ifdef	NROFF
1942 			echo_off();
1943 			flusho();
1944 #endif	/* NROFF */
1945 			fprintf(stderr, "\007"); /*bell*/
1946 		} else {
1947 			if (nextf[0]) {
1948 				fprintf(stderr, "%s:", nextf);
1949 			} else {
1950 				fprintf(stderr, "\007"); /*bell*/
1951 			}
1952 		}
1953 	}
1954 	collect();
1955 	tty++;
1956 	pushi(-1, PAIR('r','d'), 0);
1957 }
1958 
1959 
1960 int
rdtty(void)1961 rdtty(void)
1962 {
1963 	char	onechar;
1964 #if defined (EUC)
1965 	int	i, n;
1966 
1967 loop:
1968 #endif /* EUC */
1969 
1970 	onechar = 0;
1971 	if (read(0, &onechar, 1) == 1) {
1972 		if (onechar == '\n')
1973 			tty++;
1974 		else
1975 			tty = 1;
1976 #if !defined (EUC)
1977 		if (tty != 3)
1978 			return(onechar);
1979 #else	/* EUC */
1980 		if (tty != 3) {
1981 			if (!multi_locale)
1982 				return(onechar);
1983 			i = onechar & 0377;
1984 			*mbbuf1p++ = i;
1985 			*mbbuf1p = 0;
1986 			if ((*mbbuf1&~(wchar_t)0177) == 0) {
1987 				twc = 0;
1988 				mbbuf1p = mbbuf1;
1989 			}
1990 			else if ((n = mbtowc(&twc, mbbuf1, mb_cur_max)) <= 0) {
1991 				if (mbbuf1p >= mbbuf1 + mb_cur_max) {
1992 					illseq(-1, mbbuf1, mbbuf1p-mbbuf1);
1993 					twc = 0;
1994 					mbbuf1p = mbbuf1;
1995 					*mbbuf1p = 0;
1996 					i &= 0177;
1997 				} else {
1998 					goto loop;
1999 				}
2000 			} else {
2001 				i = twc | COPYBIT;
2002 				twc = 0;
2003 				mbbuf1p = mbbuf1;
2004 			}
2005 			return(i);
2006 		}
2007 #endif /* EUC */
2008 	}
2009 	popi();
2010 	tty = 0;
2011 #ifdef	NROFF
2012 	if (quiet)
2013 		echo_on();
2014 #endif	/* NROFF */
2015 	return(0);
2016 }
2017 
2018 
2019 void
caseec(void)2020 caseec(void)
2021 {
2022 	eschar = chget('\\');
2023 }
2024 
2025 
2026 void
caseeo(void)2027 caseeo(void)
2028 {
2029 	eschar = 0;
2030 }
2031 
2032 
2033 void
caseecs(void)2034 caseecs(void)
2035 {
2036 	ecs = eschar;
2037 }
2038 
2039 
2040 void
caseecr(void)2041 caseecr(void)
2042 {
2043 	eschar = ecs;
2044 }
2045 
2046 
2047 void
caseta(void)2048 caseta(void)
2049 {
2050 	int	T[NTAB];
2051 	register int i, j, n = 0;
2052 
2053 	tabtab[0] = nonumb = 0;
2054 	Tflg = 1;
2055 	for (i = 0; ((i < (NTAB - 1)) && !nonumb); i++) {
2056 		if (skip(0))
2057 			break;
2058 		tabtab[i] = max(hnumb(&tabtab[max(i-1,0)]), 0) & TABMASK;
2059 		if (nonumb && cbits(ch) == 'T') {
2060 			ch = 0;
2061 			nonumb = 0;
2062 			Tflg = 0;
2063 			goto T;
2064 		}
2065 		if (!nonumb)
2066 			switch (cbits(ch)) {
2067 			case 'C':
2068 				tabtab[i] |= CTAB;
2069 				break;
2070 			case 'R':
2071 				tabtab[i] |= RTAB;
2072 				break;
2073 			default: /*includes L*/
2074 				break;
2075 			}
2076 		nonumb = ch = 0;
2077 	}
2078 	Tflg = 0;
2079 	tabtab[i] = 0;
2080 	return;
2081 T:
2082 	for (j = 0; j < NTAB - 1 && !nonumb; j++) {
2083 		if (skip(0))
2084 			break;
2085 		T[j] = hatoi() & TABMASK;
2086 		if (!nonumb)
2087 			switch (cbits(ch)) {
2088 			case 'C':
2089 				T[j] |= CTAB;
2090 				break;
2091 			case 'R':
2092 				T[j] |= RTAB;
2093 				break;
2094 			default:
2095 				break;
2096 			}
2097 		nonumb = ch = 0;
2098 	}
2099 	T[j] = 0;
2100 	while (i < NTAB - 1) {
2101 		if (T[j] == 0) {
2102 			j = 0;
2103 			n = (i ? tabtab[i-1] : 0) & TABMASK;
2104 		}
2105 		tabtab[i++] = (n + (T[j] & TABMASK)) | (T[j] & ~TABMASK);
2106 		j++;
2107 	}
2108 	tabtab[i] = 0;
2109 }
2110 
2111 
2112 void
casene(void)2113 casene(void)
2114 {
2115 	register int i, j;
2116 
2117 	skip(0);
2118 	i = vnumb((int *)0);
2119 	if (nonumb)
2120 		i = lss;
2121 	if (i > (j = findt1())) {
2122 		i = lss;
2123 		lss = j;
2124 		dip->nls = 0;
2125 		newline(0);
2126 		lss = i;
2127 	}
2128 }
2129 
2130 
2131 void
casetr(int flag)2132 casetr(int flag)
2133 {
2134 	register int i, j;
2135 	tchar k;
2136 
2137 	lgf++;
2138 	tryglf++;
2139 	skip(1);
2140 	if (!ch && cbits(getch()) == '\n')
2141 		goto r;
2142 	while ((i = cbits(k=getch())) != '\n') {
2143 		if (ismot(k))
2144 			goto r;
2145 		if (ismot(k = getch()))
2146 			goto r;
2147 		if ((j = cbits(k)) == '\n')
2148 			j = ' ';
2149 		trtab[i] = j;
2150 		if (flag & 1)
2151 			trintab[j] = i;
2152 		else
2153 			trintab[j] = 0;
2154 		if (flag & 2)
2155 			trnttab[i] = i;
2156 		else
2157 			trnttab[i] = j;
2158 	}
2159 r:
2160 	tryglf--;
2161 }
2162 
2163 
2164 void
casetrin(void)2165 casetrin(void)
2166 {
2167 	casetr(1);
2168 }
2169 
2170 
2171 void
casetrnt(void)2172 casetrnt(void)
2173 {
2174 	casetr(2);
2175 }
2176 
2177 
2178 void
casecu(void)2179 casecu(void)
2180 {
2181 	cu++;
2182 	caseul();
2183 }
2184 
2185 
2186 void
caseul(void)2187 caseul(void)
2188 {
2189 	register int i;
2190 
2191 	noscale++;
2192 	if (skip(0))
2193 		i = 1;
2194 	else
2195 		i = hatoi();
2196 	if (ul && (i == 0)) {
2197 		font = sfont;
2198 		ul = cu = 0;
2199 	}
2200 	if (i) {
2201 		if (!ul) {
2202 			sfont = font;
2203 			font = ulfont;
2204 		}
2205 		ul = i;
2206 	}
2207 	noscale = 0;
2208 	mchbits();
2209 }
2210 
2211 
2212 void
caseuf(void)2213 caseuf(void)
2214 {
2215 	register int i, j;
2216 	extern int findft(int, int);
2217 
2218 	if (skip(0) || !(i = getrq(2)) || i == 'S' || (j = findft(i, 1))  == -1)
2219 		ulfont = ULFONT; /*default underline position*/
2220 	else
2221 		ulfont = j;
2222 #ifdef NROFF
2223 	if (ulfont == FT)
2224 		ulfont = ULFONT;
2225 #endif
2226 }
2227 
2228 
2229 void
caseit(int cflag)2230 caseit(int cflag)
2231 {
2232 	register int i;
2233 
2234 	lgf++;
2235 	it = itc = itmac = 0;
2236 	noscale++;
2237 	skip(0);
2238 	i = hatoi();
2239 	skip(0);
2240 	if (!nonumb && (itmac = getrq(1))) {
2241 		it = i;
2242 		itc = cflag;
2243 	}
2244 	noscale = 0;
2245 }
2246 
2247 
2248 void
caseitc(void)2249 caseitc(void)
2250 {
2251 	caseit(1);
2252 }
2253 
2254 
2255 void
casemc(void)2256 casemc(void)
2257 {
2258 	register int i;
2259 
2260 	if (icf > 1)
2261 		ic = 0;
2262 	icf = 0;
2263 	if (skip(0))
2264 		return;
2265 	ic = getch();
2266 	icf = 1;
2267 	skip(0);
2268 	i = max(hnumb((int *)0), 0);
2269 	if (!nonumb)
2270 		ics = i;
2271 }
2272 
2273 
2274 static void
propchar(int * tp)2275 propchar(int *tp)
2276 {
2277 	int	c, *tpp;
2278 	tchar	i;
2279 
2280 	if (skip(0)) {
2281 		*tp = IMP;
2282 		return;
2283 	}
2284 	tpp = tp;
2285 	do {
2286 		while (!ismot(c = cbits(i = getch())) &&
2287 				c != ' ' && c != '\n')
2288 			if (tpp < &tp[NSENT])
2289 				*tpp++ = c;
2290 	} while (!skip(0));
2291 }
2292 
2293 void
casesentchar(void)2294 casesentchar(void)
2295 {
2296 	propchar(sentch);
2297 }
2298 
2299 void
casetranschar(void)2300 casetranschar(void)
2301 {
2302 	propchar(transch);
2303 }
2304 
2305 void
casebreakchar(void)2306 casebreakchar(void)
2307 {
2308 	propchar(breakch);
2309 }
2310 
2311 void
casenhychar(void)2312 casenhychar(void)
2313 {
2314 	propchar(nhych);
2315 }
2316 
2317 void
caseconnectchar(void)2318 caseconnectchar(void)
2319 {
2320 	propchar(connectch);
2321 }
2322 
2323 void
casemk(void)2324 casemk(void)
2325 {
2326 	register int i, j;
2327 	struct numtab	*np;
2328 
2329 	if (dip != d)
2330 		j = dip->dnl;
2331 	else
2332 		j = numtab[NL].val;
2333 	if (skip(0)) {
2334 		dip->mkline = j;
2335 		return;
2336 	}
2337 	if ((i = getrq(1)) == 0)
2338 		return;
2339 	np = findr(i);
2340 	np->val = j;
2341 	prwatchn(np);
2342 }
2343 
2344 
2345 void
casesv(void)2346 casesv(void)
2347 {
2348 	register int i;
2349 
2350 	skip(0);
2351 	if ((i = vnumb((int *)0)) < 0)
2352 		return;
2353 	if (nonumb)
2354 		i = 1;
2355 	sv += i;
2356 	caseos();
2357 }
2358 
2359 
2360 void
caseos(void)2361 caseos(void)
2362 {
2363 	register int savlss;
2364 
2365 	if (sv <= findt1()) {
2366 		savlss = lss;
2367 		lss = sv;
2368 		newline(0);
2369 		lss = savlss;
2370 		sv = 0;
2371 	}
2372 }
2373 
2374 
2375 void
casenm(void)2376 casenm(void)
2377 {
2378 	register int i;
2379 
2380 	lnmod = nn = 0;
2381 	if (skip(0))
2382 		return;
2383 	lnmod++;
2384 	noscale++;
2385 	i = inumb(&numtab[LN].val);
2386 	if (!nonumb)
2387 		numtab[LN].val = max(i, 0);
2388 	prwatchn(&numtab[LN]);
2389 	getnm(&ndf, 1);
2390 	getnm(&nms, 0);
2391 	getnm(&ni, 0);
2392 	noscale = 0;
2393 	nmbits = chbits;
2394 }
2395 
2396 
2397 void
getnm(int * p,int min)2398 getnm(int *p, int min)
2399 {
2400 	register int i;
2401 
2402 	eat(' ');
2403 	if (skip(0))
2404 		return;
2405 	i = atoi0();
2406 	if (nonumb)
2407 		return;
2408 	*p = max(i, min);
2409 }
2410 
2411 
2412 void
casenn(void)2413 casenn(void)
2414 {
2415 	noscale++;
2416 	skip(0);
2417 	nn = max(hatoi(), 1);
2418 	noscale = 0;
2419 }
2420 
2421 
2422 void
caseab(void)2423 caseab(void)
2424 {
2425 	casetm(1);
2426 	done3(0);
2427 }
2428 
2429 
2430 #ifdef	NROFF
2431 /*
2432  * The following routines are concerned with setting terminal options.
2433  *	The manner of doing this differs between research/Berkeley systems
2434  *	and UNIX System V systems (i.e. DOCUMENTER'S WORKBENCH)
2435  *	The distinction is controlled by the #define'd variable USG,
2436  *	which must be set by System V users.
2437  */
2438 
2439 
2440 #ifdef	USG
2441 #include <termios.h>
2442 #define	ECHO_USG (ECHO | ECHOE | ECHOK | ECHONL)
2443 struct termios	ttys;
2444 #else
2445 #include <sgtty.h>
2446 struct	sgttyb	ttys[2];
2447 #endif	/* USG */
2448 
2449 int	ttysave[2] = {-1, -1};
2450 
2451 void
save_tty(void)2452 save_tty(void)			/*save any tty settings that may be changed*/
2453 {
2454 
2455 #ifdef	USG
2456 	if (tcgetattr(0, &ttys) >= 0)
2457 		ttysave[0] = ttys.c_lflag;
2458 #else
2459 	if (gtty(0, &ttys[0]) >= 0)
2460 		ttysave[0] = ttys[0].sg_flags;
2461 	if (gtty(1, &ttys[1]) >= 0)
2462 		ttysave[1] = ttys[1].sg_flags;
2463 #endif	/* USG */
2464 
2465 }
2466 
2467 
2468 void
restore_tty(void)2469 restore_tty (void)			/*restore tty settings from beginning*/
2470 {
2471 
2472 	if (ttysave[0] != -1) {
2473 #ifdef	USG
2474 		ttys.c_lflag = ttysave[0];
2475 		tcsetattr(0, TCSADRAIN, &ttys);
2476 #else
2477 		ttys[0].sg_flags = ttysave[0];
2478 		stty(0, &ttys[0]);
2479 	}
2480 	if (ttysave[1] != -1) {
2481 		ttys[1].sg_flags = ttysave[1];
2482 		stty(1, &ttys[1]);
2483 #endif	/* USG */
2484 	}
2485 }
2486 
2487 
2488 void
set_tty(void)2489 set_tty (void)			/*this replaces the use of bset and breset*/
2490 {
2491 
2492 #ifndef	USG			/*for research/BSD only, reset CRMOD*/
2493 	if (ttysave[1] == -1)
2494 		save_tty();
2495 	if (ttysave[1] != -1) {
2496 		ttys[1].sg_flags &= ~CRMOD;
2497 		stty(1, &ttys[1]);
2498 	}
2499 #endif	/* USG */
2500 
2501 }
2502 
2503 
2504 void
echo_off(void)2505 echo_off (void)			/*turn off ECHO for .rd in "-q" mode*/
2506 {
2507 	if (ttysave[0] == -1)
2508 		return;
2509 
2510 #ifdef	USG
2511 	ttys.c_lflag &= ~ECHO_USG;
2512 	tcsetattr(0, TCSADRAIN, &ttys);
2513 #else
2514 	ttys[0].sg_flags &= ~ECHO;
2515 	stty(0, &ttys[0]);
2516 #endif	/* USG */
2517 
2518 }
2519 
2520 
2521 void
echo_on(void)2522 echo_on (void)			/*restore ECHO after .rd in "-q" mode*/
2523 {
2524 	if (ttysave[0] == -1)
2525 		return;
2526 
2527 #ifdef	USG
2528 	ttys.c_lflag |= ECHO_USG;
2529 	tcsetattr(0, TCSADRAIN, &ttys);
2530 #else
2531 	ttys[0].sg_flags |= ECHO;
2532 	stty(0, &ttys[0]);
2533 #endif	/* USG */
2534 
2535 }
2536 #endif	/* NROFF */
2537