From owner-p4-projects@FreeBSD.ORG Sun Aug 2 20:16:40 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 3936A1065673; Sun, 2 Aug 2009 20:16:40 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id EA79F106566C for ; Sun, 2 Aug 2009 20:16:39 +0000 (UTC) (envelope-from tsel@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id D73158FC16 for ; Sun, 2 Aug 2009 20:16:39 +0000 (UTC) (envelope-from tsel@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n72KGds8079825 for ; Sun, 2 Aug 2009 20:16:39 GMT (envelope-from tsel@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n72KGd65079823 for perforce@freebsd.org; Sun, 2 Aug 2009 20:16:39 GMT (envelope-from tsel@FreeBSD.org) Date: Sun, 2 Aug 2009 20:16:39 GMT Message-Id: <200908022016.n72KGd65079823@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to tsel@FreeBSD.org using -f From: Tatsiana Elavaya To: Perforce Change Reviews Cc: Subject: PERFORCE change 166943 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 02 Aug 2009 20:16:41 -0000 http://perforce.freebsd.org/chv.cgi?CH=166943 Change 166943 by tsel@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 ==== //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 %token ACTION %token DEFINE %token RULESET +%token SET +%token CALL %token SEMICOLON %token IF %token THEN %token BLOCK_BEGIN %token BLOCK_END -%type define_cond cond_body cond_list cond_tail -%type cond cmd_list +%type define_cond cond_body cond_list +%type cond cond_cmd_list %type define_ruleset rule_body rule_list -%type rule rule_tail rule_action -%type rule_action_arg +%type rule rule_tail rule_action rule_action_list +%type cond_cmd cond_tail +%type id str +%type 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;