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