aboutsummaryrefslogtreecommitdiffstats
path: root/filter
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2023-10-05 14:26:22 +0200
committerOndrej Zajicek <santiago@crfreenet.org>2023-10-05 14:26:22 +0200
commitde09fda5dcef16bf50663f7ffb56074e6ad20b5a (patch)
tree3651f3e12d621e6f0196e7ffbaee885e56a676e9 /filter
parentabae806efdf6ac5f919c93057dd8df1faff1058c (diff)
downloadbird-de09fda5dcef16bf50663f7ffb56074e6ad20b5a.tar.gz
Filter: Fix scope handling in for loops
Changes in scope implementation broke scope handling in for loops. The term in for loops is supposed to be parsed in the parent scope.
Diffstat (limited to 'filter')
-rw-r--r--filter/config.Y5
-rw-r--r--filter/test.conf57
2 files changed, 61 insertions, 1 deletions
diff --git a/filter/config.Y b/filter/config.Y
index 3cd8e3e4..f3ed2dc5 100644
--- a/filter/config.Y
+++ b/filter/config.Y
@@ -20,6 +20,7 @@ static inline u32 pair_a(u32 p) { return p >> 16; }
static inline u32 pair_b(u32 p) { return p & 0xFFFF; }
static struct symbol *this_function;
+static struct sym_scope *this_for_scope;
static struct f_method_scope {
struct f_inst *object;
@@ -993,7 +994,9 @@ cmd:
new_config->current_scope->slots += 2;
} for_var IN
/* Parse term in the parent scope */
- { new_config->current_scope->active = 0; } term { new_config->current_scope->active = 1; }
+ { this_for_scope = new_config->current_scope; new_config->current_scope = this_for_scope->next; }
+ term
+ { new_config->current_scope = this_for_scope; this_for_scope = NULL; }
DO cmd {
cf_pop_block_scope(new_config);
$$ = f_for_cycle($3, $6, $9);
diff --git a/filter/test.conf b/filter/test.conf
index 22b4984a..f9289189 100644
--- a/filter/test.conf
+++ b/filter/test.conf
@@ -1939,6 +1939,63 @@ bt_test_suite(t_if_else, "Testing if-else statement");
/*
+ * Test for-in statement
+ * ---------------------
+ */
+
+function t_for_in()
+{
+ bgppath p = +empty+.prepend(5).prepend(4).prepend(3).prepend(2).prepend(1);
+ bgppath q = +empty+.prepend(30).prepend(20).prepend(10);
+ int a;
+
+ # basic for loop
+ a = 0;
+ for int i in p do {
+ a = 2 * a + i;
+ }
+ bt_assert(a = 57);
+
+ # basic for loop, no braces
+ a = 0;
+ for int i in p do a = 2 * a + i;
+ bt_assert(a = 57);
+
+ # for loop with empty body
+ a = 0;
+ for int i in p do { }
+ bt_assert(a = 0);
+
+ # for loop over empty path
+ a = 0;
+ for int i in +empty+ do a = 1;
+ bt_assert(a = 0);
+
+ # for loop with var name shadowing
+ a = 0;
+ for int p in p do {
+ a = 2 * a + p;
+ }
+ bt_assert(a = 57);
+
+ # nested for loops
+ a = 0;
+ int n = 1;
+ for int i in p do {
+ for int j in q do {
+ a = a + i * j * n;
+ n = n + 1;
+ }
+ }
+ bt_assert(a = 9300);
+}
+
+bt_test_suite(t_for_in, "Testing for-in statement");
+
+
+
+
+/*
* Unused functions -- testing only parsing
* ----------------------------------------
*/