Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 2 Aug 2009 20:16:39 GMT
From:      Tatsiana Elavaya <tsel@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 166943 for review
Message-ID:  <200908022016.n72KGd65079823@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <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;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200908022016.n72KGd65079823>