/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #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; voidstartbody(void){ int c; while((c = getrune()) == ' ' || c == '\t') ; ungetrune(c);} voidskipbody(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--; }} intifeval(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;} voidr_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();} voidr_el(Rune *name){ USED(name); if(niftrue <= 0){ warn("%Cel underflow", dot); return; } if(iftrue[--niftrue]) skipbody(); else startbody();} voidt16init(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);}
/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
#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);
}