summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikael Magnusson <mikma@users.sourceforge.net>2023-11-25 22:12:46 +0100
committerMikael Magnusson <mikma@users.sourceforge.net>2023-11-25 23:20:03 +0100
commitedda1365c032c79f5d00cc558a2a0601f61175d9 (patch)
tree614dd78038aaa74d560e55729e9ae5a9bb683b70
parent278f4c9f5a449c4f52398a0b82aabb7b3e4d01ce (diff)
parentcc1099a04169b768cb4803686ee20423a6d3fede (diff)
Merge commit 'cc1099a0' into wireguard-next-tmp7-1
-rw-r--r--conf/cf-lex.l2
-rw-r--r--filter/config.Y27
-rw-r--r--filter/data.h2
-rw-r--r--filter/decl.m442
-rw-r--r--filter/f-inst.c271
-rw-r--r--filter/f-inst.h2
-rw-r--r--filter/f-util.c40
7 files changed, 249 insertions, 137 deletions
diff --git a/conf/cf-lex.l b/conf/cf-lex.l
index 0357f9ac..24923f7d 100644
--- a/conf/cf-lex.l
+++ b/conf/cf-lex.l
@@ -744,7 +744,7 @@ cf_lex_symbol(const char *data)
return ENUM;
}
case SYM_METHOD:
- return sym->method->arg_num ? CF_SYM_METHOD_ARGS : CF_SYM_METHOD_BARE;
+ return (sym->method->arg_num > 1) ? CF_SYM_METHOD_ARGS : CF_SYM_METHOD_BARE;
case SYM_VOID:
return CF_SYM_UNDEFINED;
default:
diff --git a/filter/config.Y b/filter/config.Y
index dae05d90..7fa15dec 100644
--- a/filter/config.Y
+++ b/filter/config.Y
@@ -1017,12 +1017,12 @@ static_attr:
term_dot_method: term '.' { f_method_call_start($1); } method_name_cont { f_method_call_end(); $$ = $4; };
method_name_cont:
CF_SYM_METHOD_BARE {
- $$ = $1->method->new_inst(FM.object, NULL);
+ $$ = f_dispatch_method($1, FM.object, NULL);
}
| CF_SYM_METHOD_ARGS {
f_method_call_args();
} '(' var_list ')' {
- $$ = $1->method->new_inst(FM.object, $4);
+ $$ = f_dispatch_method($1, FM.object, $4);
}
;
@@ -1063,32 +1063,15 @@ term:
| '-' '-' '-' '-' EMPTY '-' '-' '-' '-' { $$ = f_const_empty(T_TLVLIST); }
| PREPEND '(' term ',' term ')' { $$ = f_new_inst(FI_PATH_PREPEND, $3, $5); }
| ADD '(' term ',' term ')' {
- switch ($3->type) {
- case T_CLIST: $$ = f_new_inst(FI_CLIST_ADD, $3, $5); break;
- case T_ECLIST: $$ = f_new_inst(FI_ECLIST_ADD, $3, $5); break;
- case T_LCLIST: $$ = f_new_inst(FI_LCLIST_ADD, $3, $5); break;
- default: cf_error("Can't add to type %s", f_type_name($3->type));
- }
+ $$ = f_dispatch_method_x("add", $3->type, $3, $5);
cf_warn("add(x,y) function is deprecated, please use x.add(y)");
}
| DELETE '(' term ',' term ')' {
- switch ($3->type) {
- case T_PATH: $$ = f_new_inst(FI_PATH_DEL, $3, $5); break;
- case T_CLIST: $$ = f_new_inst(FI_CLIST_DEL, $3, $5); break;
- case T_ECLIST: $$ = f_new_inst(FI_ECLIST_DEL, $3, $5); break;
- case T_LCLIST: $$ = f_new_inst(FI_LCLIST_DEL, $3, $5); break;
- default: cf_error("Can't delete from type %s", f_type_name($3->type));
- }
+ $$ = f_dispatch_method_x("delete", $3->type, $3, $5);
cf_warn("delete(x,y) function is deprecated, please use x.delete(y)");
}
| FILTER '(' term ',' term ')' {
- switch ($3->type) {
- case T_PATH: $$ = f_new_inst(FI_PATH_FILTER, $3, $5); break;
- case T_CLIST: $$ = f_new_inst(FI_CLIST_FILTER, $3, $5); break;
- case T_ECLIST: $$ = f_new_inst(FI_ECLIST_FILTER, $3, $5); break;
- case T_LCLIST: $$ = f_new_inst(FI_LCLIST_FILTER, $3, $5); break;
- default: cf_error("Can't filter type %s", f_type_name($3->type));
- }
+ $$ = f_dispatch_method_x("filter", $3->type, $3, $5);
cf_warn("filter(x,y) function is deprecated, please use x.filter(y)");
}
diff --git a/filter/data.h b/filter/data.h
index 158e2c04..3fa762d0 100644
--- a/filter/data.h
+++ b/filter/data.h
@@ -70,7 +70,9 @@ enum f_type {
struct f_method {
struct symbol *sym;
struct f_inst *(*new_inst)(struct f_inst *obj, struct f_inst *args);
+ const struct f_method *next;
uint arg_num;
+ enum f_type args_type[];
};
/* Filter value; size of this affects filter memory consumption */
diff --git a/filter/decl.m4 b/filter/decl.m4
index 8c02a1f9..a31b69a9 100644
--- a/filter/decl.m4
+++ b/filter/decl.m4
@@ -53,6 +53,7 @@ m4_define(FID_NEW_ATTRIBUTES, `m4_divert(110)')
m4_define(FID_NEW_BODY, `m4_divert(103)')
m4_define(FID_NEW_METHOD, `m4_divert(111)')
m4_define(FID_METHOD_CALL, `m4_divert(112)')
+m4_define(FID_TYPE_SIGNATURE, `m4_divert(113)')
m4_define(FID_DUMP_BODY, `m4_divert(104)m4_define([[FID_DUMP_BODY_EXISTS]])')
m4_define(FID_LINEARIZE_BODY, `m4_divert(105)')
m4_define(FID_SAME_BODY, `m4_divert(106)')
@@ -125,7 +126,7 @@ FID_IFCONST([[
constargs = 0;
]])
} while (child$1 = child$1->next);
-m4_define([[INST_METHOD_NUM_ARGS]],m4_eval($1-1))m4_dnl
+m4_define([[INST_METHOD_NUM_ARGS]],$1)m4_dnl
m4_ifelse($1,1,,[[FID_NEW_METHOD()m4_dnl
struct f_inst *arg$1 = args;
if (args == NULL) cf_error("Not enough arguments"); /* INST_NAME */
@@ -183,6 +184,8 @@ m4_define(ARG_TYPE, `ARG_TYPE_STATIC($1,$2) ARG_TYPE_DYNAMIC($1,$2)')
m4_define(ARG_TYPE_STATIC, `m4_dnl
m4_ifelse($1,1,[[m4_define([[INST_METHOD_OBJECT_TYPE]],$2)]],)m4_dnl
+FID_TYPE_SIGNATURE()m4_dnl
+ method->args_type[m4_eval($1-1)] = $2;
FID_NEW_BODY()m4_dnl
if (f$1->type && (f$1->type != ($2)) && !f_const_promotion(f$1, ($2)))
cf_error("Argument $1 of %s must be of type %s, got type %s",
@@ -230,7 +233,7 @@ FID_NEW_ARGS()m4_dnl
, struct f_inst * f$1
FID_NEW_BODY()m4_dnl
whati->f$1 = f$1;
-m4_define([[INST_METHOD_NUM_ARGS]],m4_eval($1-1))m4_dnl
+m4_define([[INST_METHOD_NUM_ARGS]],$1)m4_dnl
FID_NEW_METHOD()m4_dnl
struct f_inst *arg$1 = args;
if (args == NULL) cf_error("Not enough arguments"); /* INST_NAME */
@@ -421,17 +424,11 @@ m4_undivert(112)
FID_METHOD_SCOPE_INIT()m4_dnl
[INST_METHOD_OBJECT_TYPE] = {},
FID_METHOD_REGISTER()m4_dnl
- sym = cf_new_symbol(&f_type_method_scopes[INST_METHOD_OBJECT_TYPE],
- global_root_scope_pool, global_root_scope_linpool,
- INST_METHOD_NAME);
- sym->class = SYM_METHOD;
- sym->method = method = lp_allocz(global_root_scope_linpool, sizeof(struct f_method));
-
- *method = (struct f_method) {
- .sym = sym,
- .new_inst = f_new_method_]]INST_NAME()[[,
- .arg_num = INST_METHOD_NUM_ARGS,
- };
+ method = lp_allocz(global_root_scope_linpool, sizeof(struct f_method) + INST_METHOD_NUM_ARGS * sizeof(enum f_type));
+ method->new_inst = f_new_method_]]INST_NAME()[[;
+ method->arg_num = INST_METHOD_NUM_ARGS;
+m4_undivert(113)
+ f_register_method(INST_METHOD_OBJECT_TYPE, INST_METHOD_NAME, method);
]])m4_dnl
@@ -658,10 +655,27 @@ struct sym_scope *f_type_method_scope(enum f_type t)
return (t < ARRAY_SIZE(f_type_method_scopes)) ? &f_type_method_scopes[t] : NULL;
}
+static void
+f_register_method(enum f_type t, const byte *name, struct f_method *dsc)
+{
+ struct sym_scope *scope = &f_type_method_scopes[t];
+ struct symbol *sym = cf_find_symbol_scope(scope, name);
+
+ if (!sym)
+ {
+ sym = cf_new_symbol(scope, global_root_scope_pool, global_root_scope_linpool, name);
+ sym->class = SYM_METHOD;
+ }
+
+ dsc->sym = sym;
+ dsc->next = sym->method;
+ sym->method = dsc;
+}
+
void f_type_methods_register(void)
{
- struct symbol *sym;
struct f_method *method;
+
FID_WR_PUT(13)
for (uint i = 0; i < ARRAY_SIZE(f_type_method_scopes); i++)
diff --git a/filter/f-inst.c b/filter/f-inst.c
index 0f9d3fb8..5196d289 100644
--- a/filter/f-inst.c
+++ b/filter/f-inst.c
@@ -1271,7 +1271,8 @@
RESULT(T_PATH, ad, [[ as_path_prepend(fpool, v1.val.ad, v2.val.i) ]]);
}
- INST(FI_CLIST_ADD, 2, 1) { /* (Extended) Community list add */
+ /* Community list add */
+ INST(FI_CLIST_ADD, 2, 1) {
ARG(1, T_CLIST);
ARG_ANY(2);
METHOD_CONSTRUCTOR("add");
@@ -1289,60 +1290,73 @@
runtime("Can't add non-pair");
}
- INST(FI_ECLIST_ADD, 2, 1) {
+ INST(FI_ECLIST_ADD_EC, 2, 1) {
ARG(1, T_ECLIST);
- ARG_ANY(2);
+ ARG(2, T_EC);
METHOD_CONSTRUCTOR("add");
- /* v2.val is either EC or EC-set */
- if ((v2.type == T_SET) && eclist_set_type(v2.val.t))
- runtime("Can't add set");
- else if (v2.type == T_ECLIST)
- RESULT(T_ECLIST, ad, [[ ec_set_union(fpool, v1.val.ad, v2.val.ad) ]]);
- else if (v2.type != T_EC)
- runtime("Can't add non-ec");
- else
- RESULT(T_ECLIST, ad, [[ ec_set_add(fpool, v1.val.ad, v2.val.ec) ]]);
+ RESULT(T_ECLIST, ad, [[ ec_set_add(fpool, v1.val.ad, v2.val.ec) ]]);
+ }
+
+ INST(FI_ECLIST_ADD_ECLIST, 2, 1) {
+ ARG(1, T_ECLIST);
+ ARG(2, T_ECLIST);
+ METHOD_CONSTRUCTOR("add");
+ RESULT(T_ECLIST, ad, [[ ec_set_union(fpool, v1.val.ad, v2.val.ad) ]]);
}
- INST(FI_LCLIST_ADD, 2, 1) {
+ INST(FI_LCLIST_ADD_LC, 2, 1) {
ARG(1, T_LCLIST);
- ARG_ANY(2);
+ ARG(2, T_LC);
METHOD_CONSTRUCTOR("add");
- /* v2.val is either LC or LC-set */
- if ((v2.type == T_SET) && lclist_set_type(v2.val.t))
- runtime("Can't add set");
- else if (v2.type == T_LCLIST)
- RESULT(T_LCLIST, ad, [[ lc_set_union(fpool, v1.val.ad, v2.val.ad) ]]);
- else if (v2.type != T_LC)
- runtime("Can't add non-lc");
- else
- RESULT(T_LCLIST, ad, [[ lc_set_add(fpool, v1.val.ad, v2.val.lc) ]]);
+ RESULT(T_LCLIST, ad, [[ lc_set_add(fpool, v1.val.ad, v2.val.lc) ]]);
}
- INST(FI_TLVLIST_ADD, 2, 1) {
+ INST(FI_LCLIST_ADD_LCLIST, 2, 1) {
+ ARG(1, T_LCLIST);
+ ARG(2, T_LCLIST);
+ METHOD_CONSTRUCTOR("add");
+ RESULT(T_LCLIST, ad, [[ lc_set_union(fpool, v1.val.ad, v2.val.ad) ]]);
+ }
+
+ INST(FI_TLVLIST_ADD_SET, 2, 1) {
ARG(1, T_TLVLIST);
- ARG_ANY(2);
+ ARG(2, T_SET);
METHOD_CONSTRUCTOR("add");
- /* v2.val is either TLV or TLV-set */
- if ((v2.type == T_SET) && subtlv_set_type(v2.val.t))
- RESULT(T_TLVLIST, tl, [[ tlv_set_add(fpool, v1.val.tl, tlv_alloc(fpool, v2.val.t)) ]]);
- else if (v2.type == T_TLVLIST)
- RESULT(T_TLVLIST, tl, [[ tlv_set_union(fpool, v1.val.tl, v2.val.tl) ]]);
- else
- runtime("Can't add non-tlv");
+
+ if (!subtlv_set_type(v2.val.t))
+ runtime("Can't add non-tlv");
+
+ RESULT(T_TLVLIST, tl, [[ tlv_set_add(fpool, v1.val.tl, tlv_alloc(fpool, v2.val.t)) ]]);
+ }
+
+ INST(FI_TLVLIST_ADD_TLVLIST, 2, 1) {
+ ARG(1, T_TLVLIST);
+ ARG(2, T_TLVLIST);
+ METHOD_CONSTRUCTOR("add");
+
+ RESULT(T_TLVLIST, tl, [[ tlv_set_union(fpool, v1.val.tl, v2.val.tl) ]]);
}
- INST(FI_PATH_DEL, 2, 1) { /* Path delete */
+ INST(FI_PATH_DELETE_INT, 2, 1) {
ARG(1, T_PATH);
- ARG_ANY(2);
+ ARG(2, T_INT);
METHOD_CONSTRUCTOR("delete");
- if ((v2.type == T_SET) && path_set_type(v2.val.t) || (v2.type == T_INT))
- RESULT(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, &v2, 0) ]]);
- else
- runtime("Can't delete non-integer (set)");
+ RESULT(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, &v2, 0) ]]);
+ }
+
+ INST(FI_PATH_DELETE_SET, 2, 1) {
+ ARG(1, T_PATH);
+ ARG(2, T_SET);
+ METHOD_CONSTRUCTOR("delete");
+
+ if (!path_set_type(v2.val.t))
+ runtime("Mismatched set type");
+
+ RESULT(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, &v2, 0) ]]);
}
- INST(FI_CLIST_DEL, 2, 1) { /* (Extended) Community list add or delete */
+ /* Community list delete */
+ INST(FI_CLIST_DELETE, 2, 1) {
ARG(1, T_CLIST);
ARG_ANY(2);
METHOD_CONSTRUCTOR("delete");
@@ -1360,102 +1374,161 @@
runtime("Can't delete non-pair");
}
- INST(FI_ECLIST_DEL, 2, 1) { /* (Extended) Community list add or delete */
+ INST(FI_ECLIST_DELETE_EC, 2, 1) {
ARG(1, T_ECLIST);
- ARG_ANY(2);
+ ARG(2, T_EC);
METHOD_CONSTRUCTOR("delete");
- /* v2.val is either EC or EC-set */
- if ((v2.type == T_SET) && eclist_set_type(v2.val.t) || (v2.type == T_ECLIST))
- RESULT(T_ECLIST, ad, [[ eclist_filter(fpool, v1.val.ad, &v2, 0) ]]);
- else if (v2.type != T_EC)
- runtime("Can't delete non-ec");
- else
- RESULT(T_ECLIST, ad, [[ ec_set_del(fpool, v1.val.ad, v2.val.ec) ]]);
+ RESULT(T_ECLIST, ad, [[ ec_set_del(fpool, v1.val.ad, v2.val.ec) ]]);
+ }
+
+ INST(FI_ECLIST_DELETE_ECLIST, 2, 1) {
+ ARG(1, T_ECLIST);
+ ARG(2, T_ECLIST);
+ METHOD_CONSTRUCTOR("delete");
+ RESULT(T_ECLIST, ad, [[ eclist_filter(fpool, v1.val.ad, &v2, 0) ]]);
}
- INST(FI_LCLIST_DEL, 2, 1) { /* (Extended) Community list add or delete */
+ INST(FI_ECLIST_DELETE_SET, 2, 1) {
+ ARG(1, T_ECLIST);
+ ARG(2, T_SET);
+ METHOD_CONSTRUCTOR("delete");
+
+ if (!eclist_set_type(v2.val.t))
+ runtime("Mismatched set type");
+
+ RESULT(T_ECLIST, ad, [[ eclist_filter(fpool, v1.val.ad, &v2, 0) ]]);
+ }
+
+ INST(FI_LCLIST_DELETE_LC, 2, 1) {
ARG(1, T_LCLIST);
- ARG_ANY(2);
+ ARG(2, T_LC);
METHOD_CONSTRUCTOR("delete");
- /* v2.val is either LC or LC-set */
- if ((v2.type == T_SET) && lclist_set_type(v2.val.t) || (v2.type == T_LCLIST))
- RESULT(T_LCLIST, ad, [[ lclist_filter(fpool, v1.val.ad, &v2, 0) ]]);
- else if (v2.type != T_LC)
- runtime("Can't delete non-lc");
- else
- RESULT(T_LCLIST, ad, [[ lc_set_del(fpool, v1.val.ad, v2.val.lc) ]]);
+ RESULT(T_LCLIST, ad, [[ lc_set_del(fpool, v1.val.ad, v2.val.lc) ]]);
+ }
+
+ INST(FI_LCLIST_DELETE_LCLIST, 2, 1) {
+ ARG(1, T_LCLIST);
+ ARG(2, T_LCLIST);
+ METHOD_CONSTRUCTOR("delete");
+ RESULT(T_LCLIST, ad, [[ lclist_filter(fpool, v1.val.ad, &v2, 0) ]]);
}
- INST(FI_TLVLIST_DEL, 2, 1) { /* (Extended) Community list add or delete */
+ INST(FI_LCLIST_DELETE_SET, 2, 1) {
+ ARG(1, T_LCLIST);
+ ARG(2, T_SET);
+ METHOD_CONSTRUCTOR("delete");
+
+ if (!lclist_set_type(v2.val.t))
+ runtime("Mismatched set type");
+
+ RESULT(T_LCLIST, ad, [[ lclist_filter(fpool, v1.val.ad, &v2, 0) ]]);
+ }
+
+ INST(FI_TLVLIST_DEL_SET, 2, 1) {
ARG(1, T_TLVLIST);
- ARG_ANY(2);
+ ARG(2, T_SET);
METHOD_CONSTRUCTOR("delete");
#if 0
/* v2.val is sub-TLV-set */
- if ((v2.type == T_SET) && subtlv_set_type(v2.val.t))
- RESULT(T_TLVLIST, tl, [[ tlvlist_filter(fpool, v1.val.tl, &v2, 0) ]]);
- else
+ if (!subtlv_set_type(v2.val.t))
+ runtime("Mismatched set type");
+
+ RESULT(T_TLVLIST, tl, [[ tlvlist_filter(fpool, v1.val.tl, &v2, 0) ]]);
+#else
+ runtime("Can't delete TLVLIST");
#endif
- runtime("Can't delete non-sub-TLV-set");
}
- INST(FI_PATH_FILTER, 2, 1) { /* (Extended) Community list add or delete */
+ INST(FI_PATH_FILTER_SET, 2, 1) {
ARG(1, T_PATH);
- ARG_ANY(2);
+ ARG(2, T_SET);
METHOD_CONSTRUCTOR("filter");
- if ((v2.type == T_SET) && path_set_type(v2.val.t))
- RESULT(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, &v2, 1) ]]);
- else
- runtime("Can't filter integer");
- }
+ if (!path_set_type(v2.val.t))
+ runtime("Mismatched set type");
- INST(FI_CLIST_FILTER, 2, 1) {
+ RESULT(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, &v2, 1) ]]);
+ }
+
+ INST(FI_CLIST_FILTER_CLIST, 2, 1) {
ARG(1, T_CLIST);
- ARG_ANY(2);
+ ARG(2, T_CLIST);
METHOD_CONSTRUCTOR("filter");
- /* Community (or cluster) list */
- struct f_val dummy;
+ RESULT(T_CLIST, ad, [[ clist_filter(fpool, v1.val.ad, &v2, 1) ]]);
+ }
- if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy) || (v2.type == T_CLIST))
- RESULT(T_CLIST, ad, [[ clist_filter(fpool, v1.val.ad, &v2, 1) ]]);
- else
- runtime("Can't filter pair");
+ INST(FI_CLIST_FILTER_SET, 2, 1) {
+ ARG(1, T_CLIST);
+ ARG(2, T_SET);
+ METHOD_CONSTRUCTOR("filter");
+
+ if (!clist_set_type(v2.val.t, &(struct f_val){}))
+ runtime("Mismatched set type");
+
+ RESULT(T_CLIST, ad, [[ clist_filter(fpool, v1.val.ad, &v2, 1) ]]);
}
- INST(FI_ECLIST_FILTER, 2, 1) {
+ INST(FI_ECLIST_FILTER_ECLIST, 2, 1) {
ARG(1, T_ECLIST);
- ARG_ANY(2);
+ ARG(2, T_ECLIST);
METHOD_CONSTRUCTOR("filter");
- /* v2.val is either EC or EC-set */
- if ((v2.type == T_SET) && eclist_set_type(v2.val.t) || (v2.type == T_ECLIST))
- RESULT(T_ECLIST, ad, [[ eclist_filter(fpool, v1.val.ad, &v2, 1) ]]);
- else
- runtime("Can't filter ec");
+ RESULT(T_ECLIST, ad, [[ eclist_filter(fpool, v1.val.ad, &v2, 1) ]]);
}
- INST(FI_LCLIST_FILTER, 2, 1) {
+ INST(FI_ECLIST_FILTER_SET, 2, 1) {
+ ARG(1, T_ECLIST);
+ ARG(2, T_SET);
+ METHOD_CONSTRUCTOR("filter");
+
+ if (!eclist_set_type(v2.val.t))
+ runtime("Mismatched set type");
+
+ RESULT(T_ECLIST, ad, [[ eclist_filter(fpool, v1.val.ad, &v2, 1) ]]);
+ }
+
+ INST(FI_LCLIST_FILTER_LCLIST, 2, 1) {
ARG(1, T_LCLIST);
- ARG_ANY(2);
+ ARG(2, T_LCLIST);
METHOD_CONSTRUCTOR("filter");
- /* v2.val is either LC or LC-set */
- if ((v2.type == T_SET) && lclist_set_type(v2.val.t) || (v2.type == T_LCLIST))
- RESULT(T_LCLIST, ad, [[ lclist_filter(fpool, v1.val.ad, &v2, 1) ]]);
- else
- runtime("Can't filter lc");
+ RESULT(T_LCLIST, ad, [[ lclist_filter(fpool, v1.val.ad, &v2, 1) ]]);
}
- INST(FI_TLVLIST_FILTER, 2, 1) {
+ INST(FI_LCLIST_FILTER_SET, 2, 1) {
+ ARG(1, T_LCLIST);
+ ARG(2, T_SET);
+ METHOD_CONSTRUCTOR("filter");
+
+ if (!lclist_set_type(v2.val.t))
+ runtime("Mismatched set type");
+
+ RESULT(T_LCLIST, ad, [[ lclist_filter(fpool, v1.val.ad, &v2, 1) ]]);
+ }
+
+ INST(FI_TLVLIST_FILTER_SET, 2, 1) {
ARG(1, T_TLVLIST);
- ARG_ANY(2);
+ ARG(2, T_SET);
METHOD_CONSTRUCTOR("filter");
+
#if 0
- /* v2.val is either TLV or sub-TLV-set */
- if ((v2.type == T_SET) && subtlv_set_type(v2.val.t) || (v2.type == T_TLVLIST))
- RESULT(T_TLVLIST, tl, [[ tlvlist_filter(fpool, v1.val.tl, &v2, 1) ]]);
- else
+ if (!subtlv_set_type(v2.val.t))
+ runtime("Mismatched set type");
+
+ RESULT(T_TLVLIST, tl, [[ tlvlist_filter(fpool, v1.val.tl, &v2, 1) ]]);
+#else
+ runtime("Can't filter tlv");
+#endif
+ }
+
+ INST(FI_TLVLIST_FILTER_TLVLIST, 2, 1) {
+ ARG(1, T_TLVLIST);
+ ARG(2, T_TLVLIST);
+ METHOD_CONSTRUCTOR("filter");
+
+#if 0
+ RESULT(T_TLVLIST, tl, [[ tlvlist_filter(fpool, v1.val.tl, &v2, 1) ]]);
+#else
+ runtime("Can't filter tlv");
#endif
- runtime("Can't filter tlv");
}
INST(FI_ROA_CHECK_IMPLICIT, 0, 1) { /* ROA Check */
diff --git a/filter/f-inst.h b/filter/f-inst.h
index 8c304de5..f5dfcd20 100644
--- a/filter/f-inst.h
+++ b/filter/f-inst.h
@@ -96,6 +96,8 @@ void f_add_lines(const struct f_line_item *what, struct filter_iterator *fit);
struct filter *f_new_where(struct f_inst *);
+struct f_inst *f_dispatch_method(struct symbol *sym, struct f_inst *obj, struct f_inst *args);
+struct f_inst *f_dispatch_method_x(const char *name, enum f_type t, struct f_inst *obj, struct f_inst *args);
struct f_inst *f_for_cycle(struct symbol *var, struct f_inst *term, struct f_inst *block);
struct f_inst *f_print(struct f_inst *vars, int flush, enum filter_return fret);
diff --git a/filter/f-util.c b/filter/f-util.c
index 98b7d1a8..7ce3f9c8 100644
--- a/filter/f-util.c
+++ b/filter/f-util.c
@@ -30,7 +30,8 @@ filter_name(const struct filter *filter)
return filter->sym->name;
}
-struct filter *f_new_where(struct f_inst *where)
+struct filter *
+f_new_where(struct f_inst *where)
{
struct f_inst *cond = f_new_inst(FI_CONDITION, where,
f_new_inst(FI_DIE, F_ACCEPT),
@@ -41,6 +42,43 @@ struct filter *f_new_where(struct f_inst *where)
return f;
}
+static inline int
+f_match_signature(const struct f_method *dsc, struct f_inst *args)
+{
+ uint i;
+
+ for (i = 1; args && (i < dsc->arg_num); args = args->next, i++)
+ if (dsc->args_type[i] && (args->type != dsc->args_type[i]))
+ return 0;
+
+ return !args && !(i < dsc->arg_num);
+}
+
+struct f_inst *
+f_dispatch_method(struct symbol *sym, struct f_inst *obj, struct f_inst *args)
+{
+ /* Note! We should revert args */
+
+ for (const struct f_method *dsc = sym->method; dsc; dsc = dsc->next)
+ if (f_match_signature(dsc, args))
+ return dsc->new_inst(obj, args);
+
+ cf_error("Cannot dispatch method '%s'", sym->name);
+}
+
+struct f_inst *
+f_dispatch_method_x(const char *name, enum f_type t, struct f_inst *obj, struct f_inst *args)
+{
+ struct sym_scope *scope = f_type_method_scope(t);
+ struct symbol *sym = cf_find_symbol_scope(scope, name);
+
+ if (!sym)
+ cf_error("Cannot dispatch method '%s'", name);
+
+ return f_dispatch_method(sym, obj, args);
+}
+
+
struct f_inst *
f_for_cycle(struct symbol *var, struct f_inst *term, struct f_inst *block)
{