|  | #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); | 
|  | } |