| #include "a.h" |
| |
| /* |
| * 16. Conditional acceptance of input. |
| * |
| * conditions are |
| * c - condition letter (o, e, t, n) |
| * !c - not c |
| * N - N>0 |
| * !N - N <= 0 |
| * 'a'b' - if a==b |
| * !'a'b' - if a!=b |
| * |
| * \{xxx\} can be used for newline in bodies |
| * |
| * .if .ie .el |
| * |
| */ |
| |
| int iftrue[20]; |
| int niftrue; |
| |
| void |
| startbody(void) |
| { |
| int c; |
| |
| while((c = getrune()) == ' ' || c == '\t') |
| ; |
| ungetrune(c); |
| } |
| |
| void |
| skipbody(void) |
| { |
| int c, cc, nbrace; |
| |
| nbrace = 0; |
| for(cc=0; (c = getrune()) >= 0; cc=c){ |
| if(c == '\n' && nbrace <= 0) |
| break; |
| if(cc == '\\' && c == '{') |
| nbrace++; |
| if(cc == '\\' && c == '}') |
| nbrace--; |
| } |
| } |
| |
| int |
| ifeval(void) |
| { |
| int c, cc, neg, nc; |
| Rune line[MaxLine], *p, *e, *q; |
| Rune *a; |
| |
| while((c = getnext()) == ' ' || c == '\t') |
| ; |
| neg = 0; |
| while(c == '!'){ |
| neg = !neg; |
| c = getnext(); |
| } |
| |
| if('0' <= c && c <= '9'){ |
| ungetnext(c); |
| a = copyarg(); |
| c = (eval(a)>0) ^ neg; |
| free(a); |
| return c; |
| } |
| |
| switch(c){ |
| case ' ': |
| case '\n': |
| ungetnext(c); |
| return !neg; |
| case 'o': /* odd page */ |
| case 't': /* troff */ |
| case 'h': /* htmlroff */ |
| while((c = getrune()) != ' ' && c != '\t' && c != '\n' && c >= 0) |
| ; |
| return 1 ^ neg; |
| case 'n': /* nroff */ |
| case 'e': /* even page */ |
| while((c = getnext()) != ' ' && c != '\t' && c != '\n' && c >= 0) |
| ; |
| return 0 ^ neg; |
| } |
| |
| /* string comparison 'string1'string2' */ |
| p = line; |
| e = p+nelem(line); |
| nc = 0; |
| q = nil; |
| while((cc=getnext()) >= 0 && cc != '\n' && p<e){ |
| if(cc == c){ |
| if(++nc == 2) |
| break; |
| q = p; |
| } |
| *p++ = cc; |
| } |
| if(cc != c){ |
| ungetnext(cc); |
| return 0; |
| } |
| if(nc < 2){ |
| return 0; |
| } |
| *p = 0; |
| return (q-line == p-(q+1) |
| && memcmp(line, q+1, (q-line)*sizeof(Rune))==0) ^ neg; |
| } |
| |
| void |
| r_if(Rune *name) |
| { |
| int n; |
| |
| n = ifeval(); |
| if(runestrcmp(name, L("ie")) == 0){ |
| if(niftrue >= nelem(iftrue)) |
| sysfatal("%Cie overflow", dot); |
| iftrue[niftrue++] = n; |
| } |
| if(n) |
| startbody(); |
| else |
| skipbody(); |
| } |
| |
| void |
| r_el(Rune *name) |
| { |
| USED(name); |
| |
| if(niftrue <= 0){ |
| warn("%Cel underflow", dot); |
| return; |
| } |
| if(iftrue[--niftrue]) |
| skipbody(); |
| else |
| startbody(); |
| } |
| |
| void |
| t16init(void) |
| { |
| addraw(L("if"), r_if); |
| addraw(L("ie"), r_if); |
| addraw(L("el"), r_el); |
| |
| addesc('{', e_nop, HtmlMode|ArgMode); |
| addesc('}', e_nop, HtmlMode|ArgMode); |
| } |