Introduction
Introduction Statistics Contact Development Disclaimer Help
n5.c - 9base - revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log
Files
Refs
README
LICENSE
---
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…
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) …
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(&lt), 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"…
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 st…
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+…
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[…
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)) ==…
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 …
1129 {
1130 }
1131
1132
1133 void restore_tty(void) /*restore tty settings fro…
1134 {
1135 }
1136
1137
1138 void set_tty(void)
1139 {
1140 }
1141
1142
1143 void echo_off(void) /*turn off ECHO for .rd in "-…
1144 {
1145 }
1146
1147
1148 void echo_on(void) /*restore ECHO after .rd in "-…
1149 {
1150 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.