t16.c (2261B)
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 24 startbody(void) 25 { 26 int c; 27 28 while((c = getrune()) == ' ' || c == '\t') 29 ; 30 ungetrune(c); 31 } 32 33 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 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 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 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 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 }