| ---
n5.c (14292B)
---
1 /*
2 * troff5.c
3 *
4 * misc processing requests
5 */
6
7 #include "tdef.h"
8 #include "fns.h"
9 #include "ext.h"
10
11 int iflist[NIF];
12 int ifx;
13 int ifnum = 0; /* trying numeric expression for .if or .ie condition */
14
15 void casead(void)
16 {
17 int i;
18
19 ad = 1;
20 /* leave admod alone */
21 if (skip())
22 return;
23 switch (i = cbits(getch())) {
24 case 'r': /* right adj, left ragged */
25 admod = 2;
26 break;
27 case 'l': /* left adj, right ragged */
28 admod = ad = 0; /* same as casena */
29 break;
30 case 'c': /*centered adj*/
31 admod = 1;
32 break;
33 case 'b':
34 case 'n':
35 admod = 0;
36 break;
37 case '0':
38 case '2':
39 case '4':
40 ad = 0;
41 case '1':
42 case '3':
43 case '5':
44 admod = (i - '0') / 2;
45 }
46 }
47
48
49 void casena(void)
50 {
51 ad = 0;
52 }
53
54
55 void casefi(void)
56 {
57 tbreak();
58 fi = 1;
59 pendnf = 0;
60 }
61
62
63 void casenf(void)
64 {
65 tbreak();
66 fi = 0;
67 }
68
69
70 void casers(void)
71 {
72 dip->nls = 0;
73 }
74
75
76 void casens(void)
77 {
78 dip->nls++;
79 }
80
81 int
82 chget(int c)
83 {
84 Tchar i;
85
86 i = 0;
87 if (skip() || ismot(i = getch()) || cbits(i) == ' ' || cbits(i) == '\n') {
88 ch = i;
89 return(c);
90 } else
91 return cbits(i); /* was (i & BYTEMASK) */
92 }
93
94
95 void casecc(void)
96 {
97 cc = chget('.');
98 }
99
100
101 void casec2(void)
102 {
103 c2 = chget('\'');
104 }
105
106
107 void casehc(void)
108 {
109 ohc = chget(OHC);
110 }
111
112
113 void casetc(void)
114 {
115 tabc = chget(0);
116 }
117
118
119 void caselc(void)
120 {
121 dotc = chget(0);
122 }
123
124
125 void casehy(void)
126 {
127 int i;
128
129 hyf = 1;
130 if (skip())
131 return;
132 noscale++;
133 i = atoi0();
134 noscale = 0;
135 if (nonumb)
136 return;
137 hyf = max(i, 0);
138 }
139
140
141 void casenh(void)
142 {
143 hyf = 0;
144 }
145
146 int
147 max(int aa, int bb)
148 {
149 if (aa > bb)
150 return(aa);
151 else
152 return(bb);
153 }
154
155
156 void casece(void)
157 {
158 int i;
159
160 noscale++;
161 skip();
162 i = max(atoi0(), 0);
163 if (nonumb)
164 i = 1;
165 tbreak();
166 ce = i;
167 noscale = 0;
168 }
169
170
171 void casein(void)
172 {
173 int i;
174
175 if (skip())
176 i = in1;
177 else {
178 i = max(hnumb(&in), 0);
179 if (nonumb)
180 i = in1;
181 }
182 tbreak();
183 in1 = in;
184 in = i;
185 if (!nc) {
186 un = in;
187 setnel();
188 }
189 }
190
191
192 void casell(void)
193 {
194 int i;
195
196 if (skip())
197 i = ll1;
198 else {
199 i = max(hnumb(&ll), INCH / 10);
200 if (nonumb)
201 i = ll1;
202 }
203 ll1 = ll;
204 ll = i;
205 setnel();
206 }
207
208
209 void caselt(void)
210 {
211 int i;
212
213 if (skip())
214 i = lt1;
215 else {
216 i = max(hnumb(<), 0);
217 if (nonumb)
218 i = lt1;
219 }
220 lt1 = lt;
221 lt = i;
222 }
223
224
225 void caseti(void)
226 {
227 int i;
228
229 if (skip())
230 return;
231 i = max(hnumb(&in), 0);
232 tbreak();
233 un1 = i;
234 setnel();
235 }
236
237
238 void casels(void)
239 {
240 int i;
241
242 noscale++;
243 if (skip())
244 i = ls1;
245 else {
246 i = max(inumb(&ls), 1);
247 if (nonumb)
248 i = ls1;
249 }
250 ls1 = ls;
251 ls = i;
252 noscale = 0;
253 }
254
255
256 void casepo(void)
257 {
258 int i;
259
260 if (skip())
261 i = po1;
262 else {
263 i = max(hnumb(&po), 0);
264 if (nonumb)
265 i = po1;
266 }
267 po1 = po;
268 po = i;
269 if (TROFF & !ascii)
270 esc += po - po1;
271 }
272
273
274 void casepl(void)
275 {
276 int i;
277
278 skip();
279 if ((i = vnumb(&pl)) == 0)
280 pl = 11 * INCH; /*11in*/
281 else
282 pl = i;
283 if (numtabp[NL].val > pl)
284 numtabp[NL].val = pl;
285 }
286
287
288 void casewh(void)
289 {
290 int i, j, k;
291
292 lgf++;
293 skip();
294 i = vnumb((int *)0);
295 if (nonumb)
296 return;
297 skip();
298 j = getrq();
299 if ((k = findn(i)) != NTRAP) {
300 mlist[k] = j;
301 return;
302 }
303 for (k = 0; k < NTRAP; k++)
304 if (mlist[k] == 0)
305 break;
306 if (k == NTRAP) {
307 flusho();
308 ERROR "cannot plant trap." WARN;
309 return;
310 }
311 mlist[k] = j;
312 nlist[k] = i;
313 }
314
315
316 void casech(void)
317 {
318 int i, j, k;
319
320 lgf++;
321 skip();
322 if (!(j = getrq()))
323 return;
324 else
325 for (k = 0; k < NTRAP; k++)
326 if (mlist[k] == j)
327 break;
328 if (k == NTRAP)
329 return;
330 skip();
331 i = vnumb((int *)0);
332 if (nonumb)
333 mlist[k] = 0;
334 nlist[k] = i;
335 }
336
337 int
338 findn(int i)
339 {
340 int k;
341
342 for (k = 0; k < NTRAP; k++)
343 if ((nlist[k] == i) && (mlist[k] != 0))
344 break;
345 return(k);
346 }
347
348
349 void casepn(void)
350 {
351 int i;
352
353 skip();
354 noscale++;
355 i = max(inumb(&numtabp[PN].val), 0);
356 noscale = 0;
357 if (!nonumb) {
358 npn = i;
359 npnflg++;
360 }
361 }
362
363
364 void casebp(void)
365 {
366 int i;
367 Stack *savframe;
368
369 if (dip != d)
370 return;
371 savframe = frame;
372 skip();
373 if ((i = inumb(&numtabp[PN].val)) < 0)
374 i = 0;
375 tbreak();
376 if (!nonumb) {
377 npn = i;
378 npnflg++;
379 } else if (dip->nls)
380 return;
381 eject(savframe);
382 }
383
384 void casetm(void)
385 {
386 casetm1(0, stderr);
387 }
388
389
390 void casefm(void)
391 {
392 static struct fcache {
393 char *name;
394 FILE *fp;
395 } fcache[15];
396 int i;
397
398 if ( skip() || !getname()) {
399 ERROR "fm: missing filename" WARN;
400 return;
401 }
402
403 for (i = 0; i < 15 && fcache[i].fp != NULL; i++) {
404 if (strcmp(nextf, fcache[i].name) == 0)
405 break;
406 }
407 if (i >= 15) {
408 ERROR "fm: too many streams" WARN;
409 return;
410 }
411 if (fcache[i].fp == NULL) {
412 if( (fcache[i].fp = fopen(unsharp(nextf), "w")) == NULL) {
413 ERROR "fm: cannot open %s", nextf WARN;
414 return;
415 }
416 fcache[i].name = strdupl(nextf);
417 }
418 casetm1(0, fcache[i].fp);
419 }
420
421 void casetm1(int ab, FILE *out)
422 {
423 int i, j, c;
424 char *p;
425 char tmbuf[NTM];
426
427 lgf++;
428 copyf++;
429 if (ab) {
430 if (skip())
431 ERROR "User Abort" WARN;
432 else {
433 extern int error;
434 int savtrac = trace;
435 i = trace = 0;
436 noscale++;
437 i = inumb(&trace);
438 noscale--;
439 if (i) {
440 error = i;
441 if (nlflg || skip())
442 ERROR "User Abort, exit code %d", i WARN;
443 }
444 trace = savtrac;
445 }
446 } else
447 skip();
448 for (i = 0; i < NTM - 2; ) {
449 if ((c = cbits(getch())) == '\n' || c == RIGHT)
450 break;
451 else if (c == MINUS) { /* special pleading for strange encodings */
452 tmbuf[i++] = '\\';
453 tmbuf[i++] = '-';
454 } else if (c == PRESC) {
455 tmbuf[i++] = '\\';
456 tmbuf[i++] = 'e';
457 } else if (c == FILLER) {
458 tmbuf[i++] = '\\';
459 tmbuf[i++] = '&';
460 } else if (c == UNPAD) {
461 tmbuf[i++] = '\\';
462 tmbuf[i++] = ' ';
463 } else if (c == OHC) {
464 tmbuf[i++] = '\\';
465 tmbuf[i++] = '%';
466 } else if (c >= ALPHABET) {
467 p = chname(c);
468 switch (*p) {
469 case MBchar:
470 strcpy(&tmbuf[i], p+1);
471 break;
472 case Number:
473 sprintf(&tmbuf[i], "\\N'%s'", p+1);
474 break;
475 case Troffchar:
476 if ((j = strlen(p+1)) == 2)
477 sprintf(&tmbuf[i], "\\(%s", p+1);
478 else
479 sprintf(&tmbuf[i], "\\C'%s'", p+1);
480 break;
481 default:
482 sprintf(&tmbuf[i]," %s? ", p);
483 break;
484 }
485 j = strlen(&tmbuf[i]);
486 i += j;
487 } else
488 tmbuf[i++] = c;
489 }
490 tmbuf[i] = 0;
491 if (ab) /* truncate output */
492 obufp = obuf; /* should be a function in n2.c */
493 flusho();
494 if (i)
495 fprintf(out, "%s\n", tmbuf);
496 fflush(out);
497 copyf--;
498 lgf--;
499 }
500
501
502 void casesp(void)
503 {
504 casesp1(0);
505 }
506
507 void casesp1(int a)
508 {
509 int i, j, savlss;
510
511 tbreak();
512 if (dip->nls || trap)
513 return;
514 i = findt1();
515 if (!a) {
516 skip();
517 j = vnumb((int *)0);
518 if (nonumb)
519 j = lss;
520 } else
521 j = a;
522 if (j == 0)
523 return;
524 if (i < j)
525 j = i;
526 savlss = lss;
527 if (dip != d)
528 i = dip->dnl;
529 else
530 i = numtabp[NL].val;
531 if ((i + j) < 0)
532 j = -i;
533 lss = j;
534 newline(0);
535 lss = savlss;
536 }
537
538
539 void casert(void)
540 {
541 int a, *p;
542
543 skip();
544 if (dip != d)
545 p = &dip->dnl;
546 else
547 p = &numtabp[NL].val;
548 a = vnumb(p);
549 if (nonumb)
550 a = dip->mkline;
551 if ((a < 0) || (a >= *p))
552 return;
553 nb++;
554 casesp1(a - *p);
555 }
556
557
558 void caseem(void)
559 {
560 lgf++;
561 skip();
562 em = getrq();
563 }
564
565
566 void casefl(void)
567 {
568 tbreak();
569 if (!ascii)
570 ptflush();
571 flusho();
572 }
573
574
575 void caseev(void)
576 {
577 int nxev;
578
579 if (skip()) {
580 e0:
581 if (evi == 0)
582 return;
583 nxev = evlist[--evi];
584 goto e1;
585 }
586 noscale++;
587 nxev = atoi0();
588 noscale = 0;
589 if (nonumb)
590 goto e0;
591 flushi();
592 if (nxev >= NEV || nxev < 0 || evi >= EVLSZ) {
593 flusho();
594 ERROR "cannot do .ev %d", nxev WARN;
595 if (error)
596 done2(040);
597 else
598 edone(040);
599 return;
600 }
601 evlist[evi++] = ev;
602 e1:
603 if (ev == nxev)
604 return;
605 ev = nxev;
606 envp = &env[ev];
607 }
608
609 void envcopy(Env *e1, Env *e2) /* copy env e2 to e1 */
610 {
611 *e1 = *e2; /* rumor hath that this fails on some machines */
612 }
613
614
615 void caseel(void)
616 {
617 if (--ifx < 0) {
618 ifx = 0;
619 iflist[0] = 0;
620 }
621 caseif1(2);
622 }
623
624
625 void caseie(void)
626 {
627 if (ifx >= NIF) {
628 ERROR "if-else overflow." WARN;
629 ifx = 0;
630 edone(040);
631 }
632 caseif1(1);
633 ifx++;
634 }
635
636
637 void caseif(void)
638 {
639 caseif1(0);
640 }
641
642 void caseif1(int x)
643 {
644 extern int falsef;
645 int notflag, true;
646 Tchar i;
647
648 if (x == 2) {
649 notflag = 0;
650 true = iflist[ifx];
651 goto i1;
652 }
653 true = 0;
654 skip();
655 if ((cbits(i = getch())) == '!') {
656 notflag = 1;
657 } else {
658 notflag = 0;
659 ch = i;
660 }
661 ifnum++;
662 i = atoi0();
663 ifnum = 0;
664 if (!nonumb) {
665 if (i > 0)
666 true++;
667 goto i1;
668 }
669 i = getch();
670 switch (cbits(i)) {
671 case 'e':
672 if (!(numtabp[PN].val & 01))
673 true++;
674 break;
675 case 'o':
676 if (numtabp[PN].val & 01)
677 true++;
678 break;
679 case 'n':
680 if (NROFF)
681 true++;
682 break;
683 case 't':
684 if (TROFF)
685 true++;
686 break;
687 case ' ':
688 break;
689 default:
690 true = cmpstr(i);
691 }
692 i1:
693 true ^= notflag;
694 if (x == 1)
695 iflist[ifx] = !true;
696 if (true) {
697 i2:
698 while ((cbits(i = getch())) == ' ')
699 ;
700 if (cbits(i) == LEFT)
701 goto i2;
702 ch = i;
703 nflush++;
704 } else {
705 if (!nlflg) {
706 copyf++;
707 falsef++;
708 eatblk(0);
709 copyf--;
710 falsef--;
711 }
712 }
713 }
714
715 void eatblk(int inblk)
716 {
717 int cnt, i;
718
719 cnt = 0;
720 do {
721 if (ch) {
722 i = cbits(ch);
723 ch = 0;
724 } else
725 i = cbits(getch0());
726 if (i == ESC)
727 cnt++;
728 else {
729 if (cnt == 1)
730 switch (i) {
731 case '{': i = LEFT; break;
732 case '}': i = RIGHT; break;
733 case '\n': i = 'x'; break;
734 }
735 cnt = 0;
736 }
737 if (i == LEFT) eatblk(1);
738 } while ((!inblk && (i != '\n')) || (inblk && (i != RIGHT)));
739 if (i == '\n') {
740 nlflg++;
741 if (ip == 0)
742 numtabp[CD].val++;
743 }
744 }
745
746 int
747 cmpstr(Tchar c)
748 {
749 int j, delim;
750 Tchar i;
751 int val;
752 int savapts, savapts1, savfont, savfont1, savpts, savpts1;
753 Tchar string[1280];
754 Tchar *sp;
755
756 if (ismot(c))
757 return(0);
758 delim = cbits(c);
759 savapts = apts;
760 savapts1 = apts1;
761 savfont = font;
762 savfont1 = font1;
763 savpts = pts;
764 savpts1 = pts1;
765 sp = string;
766 while ((j = cbits(i = getch()))!=delim && j!='\n' && sp<&string[1280-1])
767 *sp++ = i;
768 if (sp >= string + 1280) {
769 ERROR "too-long string compare." WARN;
770 edone(0100);
771 }
772 if (nlflg) {
773 val = sp==string;
774 goto rtn;
775 }
776 *sp = 0;
777 apts = savapts;
778 apts1 = savapts1;
779 font = savfont;
780 font1 = savfont1;
781 pts = savpts;
782 pts1 = savpts1;
783 mchbits();
784 val = 1;
785 sp = string;
786 while ((j = cbits(i = getch())) != delim && j != '\n') {
787 if (*sp != i) {
788 eat(delim);
789 val = 0;
790 goto rtn;
791 }
792 sp++;
793 }
794 if (*sp)
795 val = 0;
796 rtn:
797 apts = savapts;
798 apts1 = savapts1;
799 font = savfont;
800 font1 = savfont1;
801 pts = savpts;
802 pts1 = savpts1;
803 mchbits();
804 return(val);
805 }
806
807
808 void caserd(void)
809 {
810
811 lgf++;
812 skip();
813 getname();
814 if (!iflg) {
815 if (quiet) {
816 if (NROFF) {
817 echo_off();
818 flusho();
819 }
820 fprintf(stderr, "\007"); /*bell*/
821 } else {
822 if (nextf[0]) {
823 fprintf(stderr, "%s:", nextf);
824 } else {
825 fprintf(stderr, "\007"); /*bell*/
826 }
827 }
828 }
829 collect();
830 tty++;
831 pushi(RD_OFFSET, PAIR('r','d'));
832 }
833
834 int
835 rdtty(void)
836 {
837 char onechar;
838
839 onechar = 0;
840 if (read(0, &onechar, 1) == 1) {
841 if (onechar == '\n')
842 tty++;
843 else
844 tty = 1;
845 if (tty != 3)
846 return(onechar);
847 }
848 tty = 0;
849 if (NROFF && quiet)
850 echo_on();
851 return(0);
852 }
853
854
855 void caseec(void)
856 {
857 eschar = chget('\\');
858 }
859
860
861 void caseeo(void)
862 {
863 eschar = 0;
864 }
865
866
867 void caseta(void)
868 {
869 int i, j, k;
870
871 tabtab[0] = nonumb = 0;
872 for (i = 0; ((i < (NTAB - 1)) && !nonumb); i++) {
873 if (skip())
874 break;
875 k = tabtab[max(i-1, 0)] & TABMASK;
876 if ((j = max(hnumb(&k), 0)) > TABMASK) {
877 ERROR "Tab too far away" WARN;
878 j = TABMASK;
879 }
880 tabtab[i] = j & TABMASK;
881 if (!nonumb)
882 switch (cbits(ch)) {
883 case 'C':
884 tabtab[i] |= CTAB;
885 break;
886 case 'R':
887 tabtab[i] |= RTAB;
888 break;
889 default: /*includes L*/
890 break;
891 }
892 nonumb = ch = 0;
893 }
894 if (!skip())
895 ERROR "Too many tab stops" WARN;
896 tabtab[i] = 0;
897 }
898
899
900 void casene(void)
901 {
902 int i, j;
903
904 skip();
905 i = vnumb((int *)0);
906 if (nonumb)
907 i = lss;
908 if (dip == d && numtabp[NL].val == -1) {
909 newline(1);
910 return;
911 }
912 if (i > (j = findt1())) {
913 i = lss;
914 lss = j;
915 dip->nls = 0;
916 newline(0);
917 lss = i;
918 }
919 }
920
921
922 void casetr(void)
923 {
924 int i, j;
925 Tchar k;
926
927 lgf++;
928 skip();
929 while ((i = cbits(k=getch())) != '\n') {
930 if (ismot(k))
931 return;
932 if (ismot(k = getch()))
933 return;
934 if ((j = cbits(k)) == '\n')
935 j = ' ';
936 trtab[i] = j;
937 }
938 }
939
940
941 void casecu(void)
942 {
943 cu++;
944 caseul();
945 }
946
947
948 void caseul(void)
949 {
950 int i;
951
952 noscale++;
953 skip();
954 i = max(atoi0(), 0);
955 if (nonumb)
956 i = 1;
957 if (ul && (i == 0)) {
958 font = sfont;
959 ul = cu = 0;
960 }
961 if (i) {
962 if (!ul) {
963 sfont = font;
964 font = ulfont;
965 }
966 ul = i;
967 }
968 noscale = 0;
969 mchbits();
970 }
971
972
973 void caseuf(void)
974 {
975 int i, j;
976
977 if (skip() || !(i = getrq()) || i == 'S' || (j = findft(i)) == -1)
978 ulfont = ULFONT; /*default underline position*/
979 else
980 ulfont = j;
981 if (NROFF && ulfont == FT)
982 ulfont = ULFONT;
983 }
984
985
986 void caseit(void)
987 {
988 int i;
989
990 lgf++;
991 it = itmac = 0;
992 noscale++;
993 skip();
994 i = atoi0();
995 skip();
996 if (!nonumb && (itmac = getrq()))
997 it = i;
998 noscale = 0;
999 }
1000
1001
1002 void casemc(void)
1003 {
1004 int i;
1005
1006 if (icf > 1)
1007 ic = 0;
1008 icf = 0;
1009 if (skip())
1010 return;
1011 ic = getch();
1012 icf = 1;
1013 skip();
1014 i = max(hnumb((int *)0), 0);
1015 if (!nonumb)
1016 ics = i;
1017 }
1018
1019
1020 void casemk(void)
1021 {
1022 int i, j;
1023
1024 if (dip != d)
1025 j = dip->dnl;
1026 else
1027 j = numtabp[NL].val;
1028 if (skip()) {
1029 dip->mkline = j;
1030 return;
1031 }
1032 if ((i = getrq()) == 0)
1033 return;
1034 numtabp[findr(i)].val = j;
1035 }
1036
1037
1038 void casesv(void)
1039 {
1040 int i;
1041
1042 skip();
1043 if ((i = vnumb((int *)0)) < 0)
1044 return;
1045 if (nonumb)
1046 i = 1;
1047 sv += i;
1048 caseos();
1049 }
1050
1051
1052 void caseos(void)
1053 {
1054 int savlss;
1055
1056 if (sv <= findt1()) {
1057 savlss = lss;
1058 lss = sv;
1059 newline(0);
1060 lss = savlss;
1061 sv = 0;
1062 }
1063 }
1064
1065
1066 void casenm(void)
1067 {
1068 int i;
1069
1070 lnmod = nn = 0;
1071 if (skip())
1072 return;
1073 lnmod++;
1074 noscale++;
1075 i = inumb(&numtabp[LN].val);
1076 if (!nonumb)
1077 numtabp[LN].val = max(i, 0);
1078 getnm(&ndf, 1);
1079 getnm(&nms, 0);
1080 getnm(&ni, 0);
1081 getnm(&nmwid, 3); /* really kludgy! */
1082 noscale = 0;
1083 nmbits = chbits;
1084 }
1085
1086 /*
1087 * .nm relies on the fact that illegal args are skipped; don't warn
1088 * for illegality of these
1089 */
1090 void getnm(int *p, int min)
1091 {
1092 int i;
1093 int savtr = trace;
1094
1095 eat(' ');
1096 if (skip())
1097 return;
1098 trace = 0;
1099 i = atoi0();
1100 if (nonumb)
1101 return;
1102 *p = max(i, min);
1103 trace = savtr;
1104 }
1105
1106
1107 void casenn(void)
1108 {
1109 noscale++;
1110 skip();
1111 nn = max(atoi0(), 1);
1112 noscale = 0;
1113 }
1114
1115
1116 void caseab(void)
1117 {
1118 casetm1(1, stderr);
1119 done3(0);
1120 }
1121
1122
1123 /* nroff terminal handling has been pretty well excised */
1124 /* as part of the merge with troff. these are ghostly remnants, */
1125 /* called, but doing nothing. restore them at your peril. */
1126
1127
1128 void save_tty(void) /*save any tty settings that may be changed*/
1129 {
1130 }
1131
1132
1133 void restore_tty(void) /*restore tty settings from beginning*/
1134 {
1135 }
1136
1137
1138 void set_tty(void)
1139 {
1140 }
1141
1142
1143 void echo_off(void) /*turn off ECHO for .rd in "-q" mode*/
1144 {
1145 }
1146
1147
1148 void echo_on(void) /*restore ECHO after .rd in "-q" mode*/
1149 {
1150 } |