summaryrefslogtreecommitdiff
path: root/filter
diff options
context:
space:
mode:
Diffstat (limited to 'filter')
-rw-r--r--filter/config.Y2
-rw-r--r--filter/filter.c38
-rw-r--r--filter/test.conf2
3 files changed, 31 insertions, 11 deletions
diff --git a/filter/config.Y b/filter/config.Y
index e635f609..80e74286 100644
--- a/filter/config.Y
+++ b/filter/config.Y
@@ -566,6 +566,7 @@ term:
| PREPEND '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('A','p'); $$->a1.p = $3; $$->a2.p = $5; }
| ADD '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'a'; }
| DELETE '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'd'; }
+ | FILTER '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'f'; }
/* | term '.' LEN { $$->code = P('P','l'); } */
@@ -706,6 +707,7 @@ cmd:
| rtadot dynamic_attr '.' PREPEND '(' term ')' ';' { $$ = f_generate_complex( P('A','p'), 'x', $2, $6 ); }
| rtadot dynamic_attr '.' ADD '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'a', $2, $6 ); }
| rtadot dynamic_attr '.' DELETE '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'd', $2, $6 ); }
+ | rtadot dynamic_attr '.' FILTER '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'f', $2, $6 ); }
;
CF_END
diff --git a/filter/filter.c b/filter/filter.c
index b8044293..913bd086 100644
--- a/filter/filter.c
+++ b/filter/filter.c
@@ -279,7 +279,7 @@ clist_match_set(struct adata *clist, struct f_tree *set)
}
static struct adata *
-clist_del_matching(struct linpool *pool, struct adata *clist, struct f_tree *set)
+clist_filter(struct linpool *pool, struct adata *clist, struct f_tree *set, int pos)
{
if (!clist)
return NULL;
@@ -294,7 +294,7 @@ clist_del_matching(struct linpool *pool, struct adata *clist, struct f_tree *set
while (l < end) {
v.val.i = *l++;
- if (!find_tree(set, v))
+ if (pos == !!find_tree(set, v)) /* pos && find_tree || !pos && !find_tree */
*k++ = v.val.i;
}
@@ -945,7 +945,7 @@ interpret(struct f_inst *what)
runtime("Can't add/delete to non-clist");
struct f_val dummy;
- u16 op = what->aux;
+ int arg_set = 0;
i = 0;
if ((v2.type == T_PAIR) || (v2.type == T_QUAD))
@@ -955,17 +955,35 @@ interpret(struct f_inst *what)
else if (v2.type == T_IP)
i = ipa_to_u32(v2.val.px.ip);
#endif
- else if ((v2.type == T_SET) && (op == 'd') && clist_set_type(v2.val.t, &dummy))
- op = 'D';
+ else if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy))
+ arg_set = 1;
else
runtime("Can't add/delete non-pair");
res.type = T_CLIST;
- switch (op) {
- case 'a': res.val.ad = int_set_add(f_pool, v1.val.ad, i); break;
- case 'd': res.val.ad = int_set_del(f_pool, v1.val.ad, i); break;
- case 'D': res.val.ad = clist_del_matching(f_pool, v1.val.ad, v2.val.t); break;
- default: bug("unknown Ca operation");
+ switch (what->aux)
+ {
+ case 'a':
+ if (arg_set)
+ runtime("Can't add set");
+ res.val.ad = int_set_add(f_pool, v1.val.ad, i);
+ break;
+
+ case 'd':
+ if (!arg_set)
+ res.val.ad = int_set_del(f_pool, v1.val.ad, i);
+ else
+ res.val.ad = clist_filter(f_pool, v1.val.ad, v2.val.t, 0);
+ break;
+
+ case 'f':
+ if (!arg_set)
+ runtime("Can't filter pair");
+ res.val.ad = clist_filter(f_pool, v1.val.ad, v2.val.t, 1);
+ break;
+
+ default:
+ bug("unknown Ca operation");
}
break;
diff --git a/filter/test.conf b/filter/test.conf
index dbb3a4ea..ca8e26f5 100644
--- a/filter/test.conf
+++ b/filter/test.conf
@@ -97,7 +97,7 @@ clist l;
l = add( l, (one,one) );
l = delete( l, [(5,1),(6,one),(one,1)] );
l = delete( l, [(5,one),(6,one)] );
- l = delete( l, [(2,*)] );
+ l = filter( l, [(1,*)] );
print "Community list (1,2) ", l;
print "Should be false: ", (2,3) ~ l, " ", l ~ [(2,*)], " ", l ~ [(one,3..6)];
print "Should be always true: ", l ~ [(*,*)];