Currently isn't possible to determine if clist or eclist defined (using defined() always return true for extended attributes of clist and eclist type, as they are special cased in P('e','s') instruction in interpret() function) or even known number of entries in these list. One of the way to determine if extended attribute of such type is empty is compare it to appropriate predefined constant: "- EMPTY -" for clist type, and "-- EMPTY --" for eclist type. However these constants, among with "+ EMPTY +" for bgppath type are intended for internal use and testing purposes and never documented. Add C.len operator just like for bgppath type to get number of elements in lists. Thats also enables to check if list is empty by checking if number of elements is zero. --- doc/bird.sgml | 2 ++ filter/filter.c | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/bird.sgml b/doc/bird.sgml index f43eb4b..050acf3 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -1077,6 +1077,8 @@ incompatible with each other (that is to prevent you from shooting in the foot). no literals of this type. There are three special operators on clists: + <cf><m/C/.len</cf> returns the length of clist <m/C/. + <cf>add(<m/C/,<m/P/)</cf> adds pair (or quad) <m/P/ to clist <m/C/ and returns the result. If item <m/P/ is already in clist <m/C/, it does nothing. <m/P/ may also be a clist, diff --git a/filter/filter.c b/filter/filter.c index 7e91c71..8164ead 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -1065,7 +1065,9 @@ interpret(struct f_inst *what) switch(v1.type) { case T_PREFIX: res.val.i = v1.val.px.len; break; case T_PATH: res.val.i = as_path_getlen(v1.val.ad); break; - default: runtime( "Prefix or path expected" ); + case T_CLIST: res.val.i = v1.val.ad->length / 4; break; + case T_ECLIST: res.val.i = v1.val.ad->length / 8; break; + default: runtime( "Prefix, path, clist or eclist expected" ); } break; case P('c','p'): /* Convert prefix to ... */ -- 1.7.10.4