1 #include "a.h"
2
3 /*
4 * 16. Conditional acceptance of input.
5 *
6 * conditions are
7 * c - condition letter (o, e, t, n)
8 * !c - not c
9 * N - N>0
10 * !N - N <= 0
11 * 'a'b' - if a==b
12 * !'a'b' - if a!=b
13 *
14 * \{xxx\} can be used for newline in bodies
15 *
16 * .if .ie .el
17 *
18 */
19
20 int iftrue[20];
21 int niftrue;
22
23 void
startbody(void)24 startbody(void)
25 {
26 int c;
27
28 while((c = getrune()) == ' ' || c == '\t')
29 ;
30 ungetrune(c);
31 }
32
33 void
skipbody(void)34 skipbody(void)
35 {
36 int c, cc, nbrace;
37
38 nbrace = 0;
39 for(cc=0; (c = getrune()) >= 0; cc=c){
40 if(c == '\n' && nbrace <= 0)
41 break;
42 if(cc == '\\' && c == '{')
43 nbrace++;
44 if(cc == '\\' && c == '}')
45 nbrace--;
46 }
47 }
48
49 int
ifeval(void)50 ifeval(void)
51 {
52 int c, cc, neg, nc;
53 Rune line[MaxLine], *p, *e, *q;
54 Rune *a;
55
56 while((c = getnext()) == ' ' || c == '\t')
57 ;
58 neg = 0;
59 while(c == '!'){
60 neg = !neg;
61 c = getnext();
62 }
63
64 if('0' <= c && c <= '9'){
65 ungetnext(c);
66 a = copyarg();
67 c = (eval(a)>0) ^ neg;
68 free(a);
69 return c;
70 }
71
72 switch(c){
73 case ' ':
74 case '\n':
75 ungetnext(c);
76 return !neg;
77 case 'o': /* odd page */
78 case 't': /* troff */
79 case 'h': /* htmlroff */
80 while((c = getrune()) != ' ' && c != '\t' && c != '\n' && c >= 0)
81 ;
82 return 1 ^ neg;
83 case 'n': /* nroff */
84 case 'e': /* even page */
85 while((c = getnext()) != ' ' && c != '\t' && c != '\n' && c >= 0)
86 ;
87 return 0 ^ neg;
88 }
89
90 /* string comparison 'string1'string2' */
91 p = line;
92 e = p+nelem(line);
93 nc = 0;
94 q = nil;
95 while((cc=getnext()) >= 0 && cc != '\n' && p<e){
96 if(cc == c){
97 if(++nc == 2)
98 break;
99 q = p;
100 }
101 *p++ = cc;
102 }
103 if(cc != c){
104 ungetnext(cc);
105 return 0;
106 }
107 if(nc < 2){
108 return 0;
109 }
110 *p = 0;
111 return (q-line == p-(q+1)
112 && memcmp(line, q+1, (q-line)*sizeof(Rune))==0) ^ neg;
113 }
114
115 void
r_if(Rune * name)116 r_if(Rune *name)
117 {
118 int n;
119
120 n = ifeval();
121 if(runestrcmp(name, L("ie")) == 0){
122 if(niftrue >= nelem(iftrue))
123 sysfatal("%Cie overflow", dot);
124 iftrue[niftrue++] = n;
125 }
126 if(n)
127 startbody();
128 else
129 skipbody();
130 }
131
132 void
r_el(Rune * name)133 r_el(Rune *name)
134 {
135 USED(name);
136
137 if(niftrue <= 0){
138 warn("%Cel underflow", dot);
139 return;
140 }
141 if(iftrue[--niftrue])
142 skipbody();
143 else
144 startbody();
145 }
146
147 void
t16init(void)148 t16init(void)
149 {
150 addraw(L("if"), r_if);
151 addraw(L("ie"), r_if);
152 addraw(L("el"), r_el);
153
154 addesc('{', e_nop, HtmlMode|ArgMode);
155 addesc('}', e_nop, HtmlMode|ArgMode);
156 }
157