PERFORCE change 166943 for review
Tatsiana Elavaya
tsel at FreeBSD.org
Sun Aug 2 20:16:41 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=166943
Change 166943 by tsel at tsel_mz on 2009/08/02 20:16:15
Add regression tests
Use call operator @ to refer to other condition sets/rulesets
Implement shell-like variables
Support escaped strings
Add id and str tokens (also containing line number)
Use cmd list to store rule actions
Affected files ...
.. //depot/projects/soc2009/tsel_ipfw/libexec/ipfw.hll/Makefile#2 edit
.. //depot/projects/soc2009/tsel_ipfw/libexec/ipfw.hll/ipfw.hll.c#2 edit
.. //depot/projects/soc2009/tsel_ipfw/libexec/ipfw.hll/ipfw.hll.h#2 edit
.. //depot/projects/soc2009/tsel_ipfw/libexec/ipfw.hll/parse.y#2 edit
.. //depot/projects/soc2009/tsel_ipfw/libexec/ipfw.hll/test/Makefile#1 add
.. //depot/projects/soc2009/tsel_ipfw/libexec/ipfw.hll/test/test0#1 add
.. //depot/projects/soc2009/tsel_ipfw/libexec/ipfw.hll/test/test0.output#1 add
.. //depot/projects/soc2009/tsel_ipfw/libexec/ipfw.hll/test/test1#1 add
.. //depot/projects/soc2009/tsel_ipfw/libexec/ipfw.hll/test/test1.err#1 add
.. //depot/projects/soc2009/tsel_ipfw/libexec/ipfw.hll/test/test2#1 add
.. //depot/projects/soc2009/tsel_ipfw/libexec/ipfw.hll/test/test2.err#1 add
.. //depot/projects/soc2009/tsel_ipfw/libexec/ipfw.hll/test/test3#1 add
.. //depot/projects/soc2009/tsel_ipfw/libexec/ipfw.hll/test/test3.output#1 add
.. //depot/projects/soc2009/tsel_ipfw/libexec/ipfw.hll/test/test4#1 add
.. //depot/projects/soc2009/tsel_ipfw/libexec/ipfw.hll/token.l#2 edit
Differences ...
==== //depot/projects/soc2009/tsel_ipfw/libexec/ipfw.hll/Makefile#2 (text+ko) ====
@@ -13,4 +13,7 @@
DEBUG_FLAGS+= -g
+.PHONY: test
+test:
+ make -C ${.CURDIR}/test test
.include <bsd.prog.mk>
==== //depot/projects/soc2009/tsel_ipfw/libexec/ipfw.hll/ipfw.hll.c#2 (text+ko) ====
@@ -133,7 +133,7 @@
}
trace_entry_init(&t_rule, rule, trace_rule, t->flags);
trace(stack, t, &t_rule);
- rule = TAILQ_NEXT(rule, ruleset_entries);
+ rule = TAILQ_NEXT(rule, rule_entries);
t->data = rule;
if (rule == NULL) {
return (0);
@@ -146,19 +146,21 @@
{
struct trace_entry t_cond;
struct rule *rule = t->arg;
+ struct cmd *cmd;
int flags = t->flags;
if (flags & TRACE_ACTIONS) {
- if (1 || rule->action_ruleset) {
+ if (0 || rule->action_ruleset) {
#if 0
tnext = trace(stack, tnext, rule->action_ruleset, trace_ruleset, TRACE_ACTIONS);
#endif
} else {
- trace_push_cmd(stack, rule->action);
- if (rule->action_arg)
- trace_push_cmd(stack, rule->action_arg);
+ TAILQ_FOREACH(cmd, &rule->actions, cmd_entries) {
+ trace_push_cmd(stack, cmd->cmd);
+ }
}
}
+
if (flags & TRACE_CONDS) {
trace_entry_init(&t_cond, rule->cond, trace_cond, TRACE_CONDS);
trace(stack, t, &t_cond);
@@ -186,7 +188,7 @@
}
trace_entry_init(&t_cond, cond, trace_cond, TRACE_CONDS);
trace(stack, t, &t_cond);
- t->data = TAILQ_NEXT(cond, condset_entries);
+ t->data = TAILQ_NEXT(cond, cond_entries);
if (t->data == NULL) {
return (0);
}
@@ -211,7 +213,7 @@
while (cmd) {
if (cmd->cmd_condset) {
trace_entry_init(&t_condset, cmd->cmd_condset, trace_condset, TRACE_CONDS);
- cmd = TAILQ_NEXT(cmd, cond_entries);
+ cmd = TAILQ_NEXT(cmd, cmd_entries);
if (cmd != NULL) {
trace_entry_init(&t_next, cond, trace_cond, TRACE_CONDS);
t_next.data = cmd;
@@ -226,7 +228,7 @@
break;
}
trace_push_cmd(stack, cmd->cmd);
- cmd = TAILQ_NEXT(cmd, cond_entries);
+ cmd = TAILQ_NEXT(cmd, cmd_entries);
}
return (0);
}
==== //depot/projects/soc2009/tsel_ipfw/libexec/ipfw.hll/ipfw.hll.h#2 (text+ko) ====
@@ -29,36 +29,37 @@
#define DPRINTF(fmt, ...) fprintf(stderr, "%s: " fmt, __func__, ## __VA_ARGS__)
struct ruleset {
- TAILQ_ENTRY(ruleset) rulesets_entries;
+ TAILQ_ENTRY(ruleset) ruleset_entries;
TAILQ_HEAD(, rule) rules;
char *name;
+ int count;
int lineno;
};
struct rule {
- TAILQ_ENTRY(rule) ruleset_entries;
+ TAILQ_ENTRY(rule) rule_entries;
+ TAILQ_HEAD(, cmd) actions;
+ struct ruleset *action_ruleset;
struct cond *cond;
- char *action;
- char *action_arg;
- struct ruleset *action_ruleset;
int lineno;
};
struct condset {
- TAILQ_ENTRY(condset) condsets_entries;
+ TAILQ_ENTRY(condset) condset_entries;
TAILQ_HEAD(, cond) conds;
char *name;
+ int count;
int lineno;
};
struct cond {
- TAILQ_ENTRY(cond) condset_entries;
+ TAILQ_ENTRY(cond) cond_entries;
TAILQ_HEAD(, cmd) cmds;
int lineno;
};
struct cmd {
- TAILQ_ENTRY(cmd) cond_entries;
+ TAILQ_ENTRY(cmd) cmd_entries;
char *cmd;
struct condset *cmd_condset;
int lineno;
==== //depot/projects/soc2009/tsel_ipfw/libexec/ipfw.hll/parse.y#2 (text+ko) ====
@@ -32,12 +32,20 @@
#include "ipfw.hll.h"
+struct var {
+ TAILQ_ENTRY(var) vars_entries;
+ char *name;
+ char *value;
+ int lineno;
+};
+
extern char *yytext;
extern int yyline;
extern int yylex();
static TAILQ_HEAD(, ruleset) rulesets = TAILQ_HEAD_INITIALIZER(rulesets);
static TAILQ_HEAD(, condset) condsets = TAILQ_HEAD_INITIALIZER(condsets);
+static TAILQ_HEAD(, var) vars = TAILQ_HEAD_INITIALIZER(vars);
static int
valid_name(char *name)
@@ -54,7 +62,7 @@
}
static struct ruleset *
-ruleset_alloc()
+ruleset_alloc(void)
{
struct ruleset *r;
@@ -69,7 +77,7 @@
{
struct ruleset *r;
- TAILQ_FOREACH(r, &rulesets, rulesets_entries) {
+ TAILQ_FOREACH(r, &rulesets, ruleset_entries) {
if (strcmp(r->name, name) == 0)
return (r);
}
@@ -81,28 +89,27 @@
{
struct ruleset *dup;
- if (!valid_name(ruleset->name))
- errx(EX_DATAERR, "line %d: invalid ruleset name '%s'",
- ruleset->lineno, ruleset->name);
dup = ruleset_lookup(ruleset->name);
if (dup != NULL)
errx(EX_DATAERR, "line %d: ruleset '%s' is already defined at line %d",
ruleset->lineno, ruleset->name, dup->lineno);
- TAILQ_INSERT_TAIL(&rulesets, ruleset, rulesets_entries);
+ TAILQ_INSERT_TAIL(&rulesets, ruleset, ruleset_entries);
+ ruleset->count++;
}
static struct rule *
-rule_alloc()
+rule_alloc(void)
{
struct rule *r;
r = safe_calloc(sizeof(struct rule));
+ TAILQ_INIT(&r->actions);
r->lineno = yyline;
return (r);
}
static struct condset *
-condset_alloc()
+condset_alloc(void)
{
struct condset *r;
@@ -117,7 +124,7 @@
{
struct condset *r;
- TAILQ_FOREACH(r, &condsets, condsets_entries) {
+ TAILQ_FOREACH(r, &condsets, condset_entries) {
if (strcmp(r->name, name) == 0)
return (r);
}
@@ -129,18 +136,16 @@
{
struct condset *dup;
- if (!valid_name(condset->name))
- errx(EX_DATAERR, "line %d: invalid condition name '%s'",
- condset->lineno, condset->name);
dup = condset_lookup(condset->name);
if (dup != NULL)
errx(EX_DATAERR, "line %d: condition '%s' is already defined at line %d",
condset->lineno, condset->name, dup->lineno);
- TAILQ_INSERT_TAIL(&condsets, condset, condsets_entries);
+ TAILQ_INSERT_TAIL(&condsets, condset, condset_entries);
+ condset->count++;
}
static struct cond *
-cond_alloc()
+cond_alloc(void)
{
struct cond *r;
@@ -151,7 +156,7 @@
}
static struct cmd *
-cmd_alloc()
+cmd_alloc(void)
{
struct cmd *r;
@@ -160,39 +165,81 @@
return (r);
}
+static struct var *
+var_alloc(void)
+{
+ struct var *r;
+
+ r = safe_calloc(sizeof(struct var));
+ r->lineno = yyline;
+ return (r);
+}
+
+static struct var *
+var_lookup(char *name)
+{
+ struct var *r;
+
+ TAILQ_FOREACH(r, &vars, vars_entries) {
+ if (strcmp(r->name, name) == 0)
+ return (r);
+ }
+ return (NULL);
+}
+
+static void
+var_insert(struct var *var)
+{
+ struct var *dup;
+
+ dup = var_lookup(var->name);
+ if (dup != NULL)
+ errx(EX_DATAERR, "line %d: variable '%s' is already defined at line %d",
+ var->lineno, var->name, dup->lineno);
+ TAILQ_INSERT_TAIL(&vars, var, vars_entries);
+}
+
%}
%union {
- char *str;
+ struct {
+ char *s;
+ int lineno;
+ } str;
+ struct cmd *cmd;
struct cond *cond;
struct condset *condset;
struct rule *rule;
struct ruleset *ruleset;
+ struct var *var;
};
%token<str> STR
%token<str> ACTION
%token DEFINE
%token RULESET
+%token SET
+%token CALL
%token SEMICOLON
%token IF
%token THEN
%token BLOCK_BEGIN
%token BLOCK_END
-%type<condset> define_cond cond_body cond_list cond_tail
-%type<cond> cond cmd_list
+%type<condset> define_cond cond_body cond_list
+%type<cond> cond cond_cmd_list
%type<ruleset> define_ruleset rule_body rule_list
-%type<rule> rule rule_tail rule_action
-%type<str> rule_action_arg
+%type<rule> rule rule_tail rule_action rule_action_list
+%type<cmd> cond_cmd cond_tail
+%type<str> id str
+%type<var> define_var
%start begin
%%
begin
- :
- | define_list rule_list
+ : define_list rule_list
{
if ($2 == NULL)
errx(EX_DATAERR, "line %d: top level ruleset is empty", yyline);
@@ -207,26 +254,37 @@
define_block
: SEMICOLON
+ | define_var
| define_cond
| define_ruleset
;
+define_var
+ : id SET str SEMICOLON
+ {
+ $$ = var_alloc();
+ $$->lineno = $1.lineno;
+ $$->name = $1.s;
+ $$->value = $3.s;
+ var_insert($$);
+ }
+
define_cond
- : DEFINE STR cond_body SEMICOLON
+ : DEFINE id cond_body SEMICOLON
{
- DPRINTF("define cond: %s; bode=%p\n", $2, $3);
$$ = $3;
- $$->name = $2;
+ $$->lineno = $2.lineno;
+ $$->name = $2.s;
condsets_insert($$);
}
;
define_ruleset
- : RULESET STR rule_body SEMICOLON
+ : RULESET id rule_body SEMICOLON
{
- DPRINTF("define rule: %s; body=%p\n", $2, $3);
$$ = $3;
- $$->name = $2;
+ $$->lineno = $2.lineno;
+ $$->name = $2.s;
rulesets_insert($$);
}
;
@@ -244,17 +302,13 @@
{ $$ = NULL; }
| cond_list cond cond_tail SEMICOLON
{
- struct cmd *cmd;
-
if ($2 != NULL) {
if ($1 == NULL)
$1 = condset_alloc();
if ($3 != NULL) {
- cmd = cmd_alloc();
- cmd->cmd_condset = $3;
- TAILQ_INSERT_TAIL(&$2->cmds, cmd, cond_entries);
+ TAILQ_INSERT_TAIL(&$2->cmds, $3, cmd_entries);
}
- TAILQ_INSERT_TAIL(&$1->conds, $2, condset_entries);
+ TAILQ_INSERT_TAIL(&$1->conds, $2, cond_entries);
}
$$ = $1;
}
@@ -268,7 +322,7 @@
if ($2 != NULL) {
if ($1 == NULL)
$1 = ruleset_alloc();
- TAILQ_INSERT_TAIL(&$1->rules, $2, ruleset_entries);
+ TAILQ_INSERT_TAIL(&$1->rules, $2, rule_entries);
}
$$ = $1;
}
@@ -277,7 +331,7 @@
cond
:
{ $$ = NULL; }
- | IF cmd_list
+ | IF cond_cmd_list
{ $$ = $2; }
;
@@ -285,7 +339,10 @@
:
{ $$ = NULL; }
| cond_body
- { $$ = $1; }
+ {
+ $$ = cmd_alloc();
+ $$->cmd_condset = $1;
+ }
;
rule
@@ -312,59 +369,147 @@
;
rule_action
- : ACTION rule_action_arg
+ : CALL id
{
$$ = rule_alloc();
- $$->action = $1;
- $$->action_arg = $2;
- DPRINTF("rule action=%s action_arg=%s\n", $$->action, $$->action_arg);
+ $$->lineno = $2.lineno;
+ $$->action_ruleset = ruleset_lookup($2.s);
+ if ($$->action_ruleset == NULL)
+ errx(EX_DATAERR, "line %d: ruleset not found: %s", $$->lineno, $2.s);
}
- | STR
+ | rule_action_list
{
+ $$ = $1;
+ }
+ ;
+
+rule_action_list
+ : ACTION
+ {
+ struct cmd *cmd;
+
$$ = rule_alloc();
- $$->action_ruleset = ruleset_lookup($1);
- if ($$->action_ruleset == NULL)
- errx(EX_DATAERR, "line %d: ruleset not found: %s", yyline, $1);
+ $$->lineno = $1.lineno;
+ cmd = cmd_alloc();
+ cmd->lineno = $1.lineno;
+ cmd->cmd = $1.s;
+ TAILQ_INSERT_TAIL(&$$->actions, cmd, cmd_entries);
+ }
+ | rule_action_list ACTION
+ {
+ struct cmd *cmd;
+
+ cmd = cmd_alloc();
+ cmd->lineno = $2.lineno;
+ cmd->cmd = $2.s;
+ TAILQ_INSERT_TAIL(&$1->actions, cmd, cmd_entries);
+ $$ = $1;
}
- ;
+ | rule_action_list str
+ {
+ struct cmd *cmd;
-rule_action_arg
- :
- { $$ = NULL; }
- | STR
- { $$ = $1; }
+ cmd = cmd_alloc();
+ cmd->lineno = $2.lineno;
+ cmd->cmd = $2.s;
+ TAILQ_INSERT_TAIL(&$1->actions, cmd, cmd_entries);
+ $$ = $1;
+ }
;
-cmd_list
+cond_cmd_list
: { $$ = NULL; }
- | cmd_list STR
+ | cond_cmd_list cond_cmd
{
- struct cmd *cmd;
- struct condset *cmd_condset;
-
if ($1 == NULL) {
$1 = cond_alloc();
}
- cmd_condset = condset_lookup($2);
- cmd = cmd_alloc();
- if (cmd_condset != NULL)
- cmd->cmd_condset = cmd_condset;
- else
- cmd->cmd = $2;
- TAILQ_INSERT_TAIL(&$1->cmds, cmd, cond_entries);
+ TAILQ_INSERT_TAIL(&$1->cmds, $2, cmd_entries);
+ $$ = $1;
+ }
+ ;
+
+cond_cmd
+ : CALL id
+ {
+ $$ = cmd_alloc();
+ $$->lineno = $2.lineno;
+ $$->cmd_condset = condset_lookup($2.s);
+ if ($$->cmd_condset == NULL)
+ errx(EX_DATAERR, "line %d: condition set not found: %s", $$->lineno, $2.s);
+ }
+ | str
+ {
+ $$ = cmd_alloc();
+ $$->lineno = $1.lineno;
+ $$->cmd = $1.s;
+ }
+ ;
+
+id
+ : STR
+ {
+ if (!valid_name($1.s))
+ errx(EX_DATAERR, "line %d: invalid name '%s'", $1.lineno, $1.s);
$$ = $1;
}
;
+str
+ : STR
+ {
+ struct var *var;
+ char *p, *s, *sn, *v;
+ int l;
+
+ s = $1.s;
+ while ((p = strchr(s, '$')) != NULL) {
+ v = p + 2;
+ if (p[1] != '{' || (p = strchr(v, '}')) == NULL) {
+ errx(EX_DATAERR,
+ "line %d: syntax error: variable expansion failed", yyline);
+ } else {
+ *p = '\0';
+ var = var_lookup(v);
+ *p = '}';
+ if (var == NULL)
+ errx(EX_DATAERR, "line %d: variable not found: %s", yyline, v);
+ l = (v - s - 2) + strlen(var->value) + strlen(p + 1) + 1;
+ sn = safe_calloc(l);
+ memcpy(sn, s, v - s - 2);
+ strlcat(sn, var->value, l);
+ strlcat(sn, p + 1, l);
+ s = sn;
+ }
+ }
+/*
+ if (strchr(s, ' ') != NULL || strchr(s, '"') != NULL) {
+ sn = safe_calloc(strlen(s) * 2 + 3);
+ p = sn;
+ *(p++) = '"';
+ for (; *s; s++, p++) {
+ if (*s == '"')
+ *(p++) = '\\';
+ *p = *s;
+ }
+ *(p++) = '"';
+ s = sn;
+ }
+*/
+ $$.s = s;
+ $$.lineno = $1.lineno;
+ }
+ ;
+
%%
void yyerror(char *s)
{
if (yytext)
- warnx("line %d: '%s': %s", yyline, yytext, s);
+ errx(EX_DATAERR, "line %d: '%s': %s", yyline, yytext, s);
else
- warnx("line %d: %s", yyline, s);
+ errx(EX_DATAERR, "line %d: %s", yyline, s);
}
==== //depot/projects/soc2009/tsel_ipfw/libexec/ipfw.hll/token.l#2 (text+ko) ====
@@ -68,7 +68,7 @@
%}
-STR [-A-Za-z0-9,._&/!()]+
+STR [-A-Za-z0-9,._&/!()${}]+
%%
@@ -80,6 +80,8 @@
[ \t]+ ;
";" { return SEMICOLON; }
+"@" { return CALL; }
+"=" { return SET; }
"if" { return IF; }
"cond" { return IF; }
"then" { return THEN; }
@@ -98,10 +100,26 @@
return BLOCK_END;
}
+\"(\\\"|[^"])*\"|\'(\\\'|[^'])*\' {
+ char *s, *d;
+
+ yylval.str.lineno = yyline;
+ yylval.str.s = strdup(yytext + 1);
+ yylval.str.s[strlen(yylval.str.s) - 1] = '\0';
+ for (s = yylval.str.s, d = s; *s; s++, d++) {
+ if (s[0] == '\\' && (s[1] == '\'' || s[1] == '"'))
+ s++;
+ if (s != d)
+ *d = *s;
+ }
+ *d = '\0';
+ return STR;
+ }
{STR} {
int i;
- yylval.str = strdup(yytext);
+ yylval.str.lineno = yyline;
+ yylval.str.s = strdup(yytext);
for (i = 0; rule_actions[i].s != NULL; i++) {
if (strcmp(yytext, rule_actions[i].s) == 0)
return ACTION;
More information about the p4-projects
mailing list