commit e72e360a1a5a74d85a721b8405790593b033277b from: rsc date: Fri Dec 30 15:56:36 2005 UTC forgot this commit - 3f6a501b4d661acb8dba53d8a857e963aad2fe6b commit + e72e360a1a5a74d85a721b8405790593b033277b blob - /dev/null blob + d34bfc7c47b0c0cccb4ce5396a73f363a9922f75 (mode 755) --- /dev/null +++ src/cmd/ip/snoopy/filter.y @@ -0,0 +1,107 @@ +%{ +#include +#include +#include +#include "dat.h" + +char *yylp; /* next character to be lex'd */ +char *yybuffer; +char *yyend; /* end of buffer to be parsed */ +%} + +%term LOR +%term LAND +%term WORD +%right '!' +%left '|' +%left '&' +%left LOR +%left LAND +%start filter +%% + +filter : expr + { filter = $$; } + ; +expr : WORD + { $$ = $1; } + | WORD '=' WORD + { $2->l = $1; $2->r = $3; $$ = $2; } + | WORD '(' expr ')' + { $1->l = $3; free($2); free($4); $$ = $1; } + | '(' expr ')' + { free($1); free($3); $$ = $2; } + | expr LOR expr + { $2->l = $1; $2->r = $3; $$ = $2; } + | expr LAND expr + { $2->l = $1; $2->r = $3; $$ = $2; } + | '!' expr + { $1->l = $2; $$ = $1; } + ; +%% + +/* + * Initialize the parsing. Done once for each header field. + */ +void +yyinit(char *p) +{ + yylp = p; +} + +int +yylex(void) +{ + char *p; + int c; + + if(yylp == nil || *yylp == 0) + return 0; + while(isspace(*yylp)) + yylp++; + + yylval = newfilter(); + + p = strpbrk(yylp, "!|&()= "); + if(p == 0){ + yylval->op = WORD; + yylval->s = strdup(yylp); + if(yylval->s == nil) + sysfatal("parsing filter: %r"); + yylp = nil; + return WORD; + } + c = *p; + if(p != yylp){ + yylval->op = WORD; + *p = 0; + yylval->s = strdup(yylp); + if(yylval->s == nil) + sysfatal("parsing filter: %r"); + *p = c; + yylp = p; + return WORD; + } + + yylp++; + if(*yylp == c) + switch(c){ + case '&': + c = LAND; + yylp++; + break; + case '|': + c = LOR; + yylp++; + break; + } + yylval->op = c; + return c; +} + +void +yyerror(char *e) +{ + USED(e); + sysfatal("error parsing filter"); +}