filter not_too_far
-int var;
{
+ int var;
if defined( rip_metric ) then
var = rip_metric;
else {
@@ -1290,9 +1290,9 @@ local variables. Recursion is not allowed. Function definitions look like this:
function name ()
-int local_variable;
{
- local_variable = 5;
+ int local_variable;
+ int another_variable = 5;
}
function with_parameters (int parameter)
@@ -1301,16 +1301,19 @@ function with_parameters (int parameter)
}
-Unlike in C, variables are declared after the name(); with_parameters(5); . Function may return
-values using the return command. Returning a value exits
-from current function (this is similar to C).
+Like in C programming language, variables are declared inside function body,
+either at the beginning, or mixed with other statements. Declarations may
+contain initialization. You can also declare variables in nested blocks, such
+variables have scope restricted to such block. There is a deprecated syntax to
+declare variables after the name(); with_parameters(5); . Function
+may return values using the return command. Returning a
+value exits from current function (this is similar to C).
-Filters are defined in a way similar to functions except they can't have
+
Filters are defined in a way similar to functions except they cannot have
explicit parameters. They get a route table entry as an implicit parameter, it
is also passed automatically to any functions called. The filter must terminate
-with either A nice trick to debug filters is to use show route filter
@@ -1680,7 +1683,8 @@ prefix and an ASN as arguments.
Control structures
diff --git a/filter/config.Y b/filter/config.Y
index 15b77761..f256aace 100644
--- a/filter/config.Y
+++ b/filter/config.Y
@@ -22,6 +22,36 @@ static inline u32 pair_b(u32 p) { return p & 0xFFFF; }
#define f_generate_complex(fi_code, da, arg) \
f_new_inst(FI_EA_SET, f_new_inst(fi_code, f_new_inst(FI_EA_GET, da), arg), da)
+static int
+f_new_var(struct sym_scope *s)
+{
+ /*
+ * - A variable is an offset on vstack from vbase.
+ * - Vbase is set on filter start / function call.
+ * - Scopes contain anonymous scopes (blocks) inside filter/function scope
+ * - Each scope knows number of vars in that scope
+ * - Offset is therefore a sum of 'slots' up to named scope
+ * - New variables are added on top of vstk, so intermediate values cannot
+ * be there during FI_VAR_INIT. I.e. no 'var' inside 'term'.
+ * - Also, each f_line must always have its scope, otherwise a variable may
+ * be defined but not initialized if relevant f_line is not executed.
+ */
+
+ int offset = s->slots++;
+
+ while (!s->name)
+ {
+ s = s->next;
+ ASSERT(s);
+ offset += s->slots;
+ }
+
+ if (offset >= 0xff)
+ cf_error("Too many variables, at most 255 allowed");
+
+ return offset;
+}
+
/*
* Sets and their items are during parsing handled as lists, linked
* through left ptr. The first item in a list also contains a pointer
@@ -262,7 +292,7 @@ assert_assign(struct f_lval *lval, struct f_inst *expr, const char *start, const
checker = f_new_inst(FI_EQ, expr, getter);
setter->next = checker;
-
+
return assert_done(setter, start, end);
}
@@ -273,6 +303,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
INT, BOOL, IP, TYPE, PREFIX, RD, PAIR, QUAD, EC, LC,
SET, STRING, BGPMASK, BGPPATH, CLIST, ECLIST, LCLIST,
IF, THEN, ELSE, CASE,
+ FOR, IN, DO,
TRUE, FALSE, RT, RO, UNKNOWN, GENERIC,
FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, DEST, IFNAME, IFINDEX, WEIGHT, GW_MPLS,
PREFERENCE,
@@ -292,21 +323,23 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
%nonassoc ELSE
%type