summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikael Magnusson <mikma@users.sourceforge.net>2023-11-25 23:43:36 +0100
committerMikael Magnusson <mikma@users.sourceforge.net>2023-11-25 23:43:36 +0100
commit3f0b72910882bd6cbb02302f198a4ab70f0b2927 (patch)
treec0aa7fdb309b1d29cef0d3fa2ae0148e393e149e
parent5a53dfd4254838e58303ebb8de2054988f23044c (diff)
parentde09fda5dcef16bf50663f7ffb56074e6ad20b5a (diff)
Merge commit 'de09fda5' into wireguard-next-tmp7-1
-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 608a8895..11b1a7f1 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;
@@ -1137,7 +1138,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
* ----------------------------------------
*/