157 lines
2.2 KiB
C
157 lines
2.2 KiB
C
#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);
|
|
}
|