]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Filter: refactoring of instruction constructors
authorMaria Matejka <mq@ucw.cz>
Mon, 21 Jan 2019 08:17:54 +0000 (09:17 +0100)
committerMaria Matejka <mq@ucw.cz>
Wed, 20 Feb 2019 21:30:54 +0000 (22:30 +0100)
18 files changed:
conf/conf.h
conf/confbase.Y
filter/Makefile
filter/config.Y
filter/dump.m4
filter/f-inst.c
filter/f-inst.h [new file with mode: 0644]
filter/f-util.c
filter/filter.c
filter/filter.h
filter/interpret.m4
filter/line-size.m4
filter/new.m4 [new file with mode: 0644]
filter/postfixify.m4
filter/same.m4
filter/struct.m4 [new file with mode: 0644]
nest/attrs.h
proto/static/config.Y

index 427569fd94bb485b923a435df99659554d388c7b..6138ccecdb90c6fa9b63aed24463ec304af71193 100644 (file)
@@ -107,7 +107,7 @@ struct symbol {
   struct sym_scope *scope;
   int class;
   int aux;
-  void *aux2;
+  uint aux2;
   void *def;
   char name[1];
 };
index 492ecd08cd7716a02976340f9d3e2345210b0325..13f6aadeade8b403b222b704c702aab2ad36ae4a 100644 (file)
@@ -49,6 +49,10 @@ CF_DECLS
   struct rtable_config *r;
   struct channel_config *cc;
   struct f_inst *x;
+  struct f_inst *xp[2];
+  struct { struct f_inst *inst; uint count; } xc;
+  enum filter_return fret;
+  enum ec_subtype ecs;
   struct f_dynamic_attr fda;
   struct f_static_attr fsa;
   struct filter *f;
index c74ba2f3873fb5bb8796698c803d7380c1706198..15f2c3d0610f9cd58d74bb693c698c6260c481b3 100644 (file)
@@ -1,4 +1,4 @@
-src := filter.c f-util.c tree.c trie.c
+src := filter.c f-util.c tree.c trie.c f-inst-new.c
 obj := $(src-o-files)
 $(all-daemon)
 $(cf-local)
@@ -17,10 +17,16 @@ $(o)f-inst-interpret.c: $(s)interpret.m4 $(s)f-inst.c $(objdir)/.dir-stamp
 $(o)f-inst-same.c: $(s)same.m4 $(s)f-inst.c $(objdir)/.dir-stamp
        $(M4) $(M4FLAGS_FILTERS) -P $^ >$@
 
+$(o)f-inst-struct.h: $(s)struct.m4 $(s)f-inst.c $(objdir)/.dir-stamp
+       $(M4) $(M4FLAGS_FILTERS) -P $^ >$@
+
+$(o)f-inst-new.c: $(s)new.m4 $(s)f-inst.c $(objdir)/.dir-stamp
+       $(M4) $(M4FLAGS_FILTERS) -P $^ >$@
+
 $(o)f-inst-dump.c: $(s)dump.m4 $(s)f-inst.c $(objdir)/.dir-stamp
        $(M4) $(M4FLAGS_FILTERS) -P $^ >$@
 
-$(o)filter.o: $(o)f-inst-interpret.c $(o)f-inst-line-size.c $(o)f-inst-postfixify.c $(o)f-inst-same.c $(o)f-inst-dump.c
+$(o)filter.o: $(o)f-inst-interpret.c $(o)f-inst-line-size.c $(o)f-inst-postfixify.c $(o)f-inst-same.c $(o)f-inst-dump.c $(o)f-inst-struct.h
 
 tests_src := tree_test.c filter_test.c trie_test.c
 tests_targets := $(tests_targets) $(tests-target-files)
index a79b158228b5a2fa2bfad196d235c12451a0deb9..607f534eb8e1baac755f6c7b5ac1ce9dc983dd4a 100644 (file)
@@ -16,6 +16,8 @@ static inline u32 pair(u32 a, u32 b) { return (a << 16) | b; }
 static inline u32 pair_a(u32 p) { return p >> 16; }
 static inline u32 pair_b(u32 p) { return p & 0xFFFF; }
 
+#define f_generate_complex(fi_code, da, arg) \
+  f_new_inst(FI_EA_SET, da, f_new_inst(fi_code, f_new_inst(FI_EA_GET, da), arg))
 
 /*
  * Sets and their items are during parsing handled as lists, linked
@@ -158,30 +160,29 @@ f_new_lc_item(u32 f1, u32 t1, u32 f2, u32 t2, u32 f3, u32 t3)
 static inline struct f_inst *
 f_generate_empty(struct f_dynamic_attr dyn)
 {
-  struct f_inst *e = f_new_inst(FI_CONSTANT);
+  struct f_val empty;
 
   switch (dyn.type & EAF_TYPE_MASK) {
     case EAF_TYPE_AS_PATH:
-      e->val = f_const_empty_path;
+      empty = f_const_empty_path;
       break;
     case EAF_TYPE_INT_SET:
-      e->val = f_const_empty_clist;
+      empty = f_const_empty_clist;
       break;
     case EAF_TYPE_EC_SET:
-      e->val = f_const_empty_eclist;
+      empty = f_const_empty_eclist;
       break;
     case EAF_TYPE_LC_SET:
-      e->val = f_const_empty_lclist;
+      empty = f_const_empty_lclist;
       break;
     default:
       cf_error("Can't empty that attribute");
   }
 
-  struct f_inst *s = f_new_inst_da(FI_EA_SET, dyn);
-  s->a[0].p = e;
-  return s;
+  return f_new_inst(FI_EA_SET, dyn, f_new_inst(FI_CONSTANT, empty));
 }
 
+#if 0
 
 static inline struct f_inst *
 f_generate_dpair(struct f_inst *t1, struct f_inst *t2)
@@ -332,6 +333,8 @@ f_generate_path_mask(struct f_inst *t)
   return pmc;
 }
 
+#endif
+
 /*
  * Remove all new lines and doubled whitespaces
  * and convert all tabulators to spaces
@@ -380,21 +383,10 @@ assert_copy_expr(const char *start, size_t len)
 static struct f_inst *
 assert_done(struct f_inst *expr, const char *start, const char *end)
 {
-  struct f_inst *i;
-  i = f_new_inst(FI_ASSERT);
-  i->a[0].p = expr;
-
-  if (end >= start)
-  {
-    i->a[1].p = assert_copy_expr(start, end - start + 1);
-  }
-  else
-  {
-    /* this is a break of lexer buffer */
-    i->a[1].p = "???";
-  }
-
-  return i;
+  return f_new_inst(FI_ASSERT, expr,
+    (end >= start) ?
+      assert_copy_expr(start, end - start + 1)
+    : "???");
 }
 
 CF_DECLS
@@ -420,17 +412,20 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
 %nonassoc THEN
 %nonassoc ELSE
 
-%type <x> term block cmds cmds_int cmd function_body constant constructor print_one print_list var_list var_listn function_call symbol bgp_path_expr bgp_path bgp_path_tail
+%type <xc> function_params declsn
+%type <xp> cmds_int function_body
+%type <x> term block cmd cmds constant constructor print_one print_list var_list var_listn function_call symbol bgp_path_expr bgp_path bgp_path_tail one_decl decls
 %type <fda> dynamic_attr
 %type <fsa> static_attr
 %type <f> filter filter_body where_filter
-%type <i> type break_command ec_kind
+%type <i> type
+%type <ecs> ec_kind
+%type <fret> break_command 
 %type <i32> cnum
 %type <e> pair_item ec_item lc_item set_item switch_item set_items switch_items switch_body
 %type <trie> fprefix_set
 %type <v> set_atom switch_atom fipa
 %type <px> fprefix
-%type <s> decls declsn one_decl function_params
 %type <t> get_cf_position
 
 CF_GRAMMAR
@@ -515,8 +510,7 @@ one_decl:
      val->type = T_VOID;
      $2 = cf_define_symbol($2, SYM_VARIABLE | $1, val);
      DBG( "New variable %s type %x\n", $2->name, $1 );
-     $2->aux2 = NULL;
-     $$=$2;
+     $$ = f_new_inst(FI_SET, NULL, $2);
    }
  ;
 
@@ -524,24 +518,29 @@ one_decl:
 decls: /* EMPTY */ { $$ = NULL; }
  | one_decl ';' decls {
      $$ = $1;
-     $$->aux2 = $3;
+     f_inst_next($$, $3);
    }
  ;
 
-/* Declarations that have no ';' at the end. */
-declsn: one_decl { $$ = $1; }
+/* Declarations that have no ';' at the end. Beware; these are reversed. */
+declsn: one_decl { $$.inst = $1; $$.count = 1; }
  | one_decl ';' declsn {
-     $$ = $1;
-     $$->aux2 = $3;
+     $$ = $3;
+     $$.count++;
+     f_inst_next($$.inst, $1);
    }
  ;
 
 filter_body:
    function_body {
-     struct filter *f = cfg_alloc(sizeof(struct filter));
-     f->name = NULL;
-     f->root = f_postfixify($1);
-     $$ = f;
+     $$ = cfg_alloc(sizeof(struct filter));
+     $$->name = NULL;
+     if ($1[0]) {
+       const struct f_inst *inst[2] = { $1[0], $1[1] };
+       $$->root = f_postfixify_concat(inst, 2);
+     }
+     else
+       $$->root = f_postfixify($1[1]);
    }
  ;
 
@@ -556,42 +555,19 @@ filter:
 where_filter:
    WHERE term {
      /* Construct 'IF term THEN { ACCEPT; } ELSE { REJECT; }' */
-     struct filter *f = cfg_alloc(sizeof(struct filter));
-     struct f_inst acc = {
-       .fi_code = FI_PRINT_AND_DIE,
-       .a = { { .p = NULL }, { .i = F_ACCEPT } },
-       .lineno = ifs->lino,
-     };
-     struct f_inst rej = {
-       .fi_code = FI_PRINT_AND_DIE,
-       .a = { { .p = NULL }, { .i = F_REJECT } },
-       .lineno = ifs->lino,
-     };
-     struct f_inst i = {
-       .fi_code = FI_CONDITION,
-       .a = { { .p = $2 }, { .p = &acc }, { .p = &rej } },
-       .lineno = ifs->lino,
-     };
-     f->name = NULL;
-     f->root = f_postfixify(&i);
-     $$ = f;
+     $$ = f_new_where($2);
    }
  ;
 
 function_params:
-   '(' declsn ')' { DBG( "Have function parameters\n" ); $$=$2; }
- | '(' ')' { $$=NULL; }
+   '(' declsn ')' { $$ = $2; }
+ | '(' ')' { $$.inst = NULL; $$.count = 0; }
  ;
 
 function_body:
    decls '{' cmds '}' {
-     if ($1) {
-       /* Prepend instruction to clear local variables */
-       $$ = f_new_inst(FI_CLEAR_LOCAL_VARS);
-       $$->a[0].p = $1;
-       $$->next = $3;
-     } else
-       $$ = $3;
+     $$[0] = $1 ? f_clear_local_vars($1) : NULL;
+     $$[1] = $3;
    }
  ;
 
@@ -601,10 +577,26 @@ function_def:
      $2 = cf_define_symbol($2, SYM_FUNCTION, NULL);
      cf_push_scope($2);
    } function_params function_body {
-     struct f_inst *vc = f_new_inst(FI_CONSTANT);
-     vc->val = (struct f_val) { .type = T_VOID };
-     $2->def = f_postfixify_concat($5, vc, NULL);
-     $2->aux2 = $4;
+     const struct f_inst *catlist[4];
+     uint count = 0;
+
+     /* Argument setters */
+     if ($4.inst)
+       catlist[count++] = $4.inst;
+
+     /* Local var clearers */
+     if ($5[0])
+       catlist[count++] = $5[0];
+
+     /* Return void if no return is needed */
+     catlist[count++] = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_VOID });
+
+     /* Function body itself */
+     if ($5[1])
+       catlist[count++] = $5[1];
+
+     $2->def = f_postfixify_concat(catlist, count);
+     $2->aux2 = $4.count;
      DBG("Hmm, we've got one function here - %s\n", $2->name);
      cf_pop_scope();
    }
@@ -612,15 +604,12 @@ function_def:
 
 /* Programs */
 
-/* Hack: $$ of cmds_int is the last node.
-   $$->next of cmds_int is temporary used for the first node */
-
 cmds: /* EMPTY */ { $$ = NULL; }
- | cmds_int { $$ = $1->next; $1->next = NULL; }
+ | cmds_int { $$ = $1[0]; }
  ;
 
-cmds_int: cmd { $$ = $1; $1->next = $1; }
- | cmds_int cmd { $$ = $2; $2->next = $1->next ; $1->next = $2; }
+cmds_int: cmd { $$[0] = $$[1] = $1; }
+ | cmds_int cmd { $$[1] = $2; f_inst_next($1[1], $2); $$[0] = $1[0]; }
  ;
 
 block:
@@ -784,37 +773,36 @@ bgp_path:
  ;
 
 bgp_path_tail:
-   NUM bgp_path_tail           { $$ = f_new_inst(FI_CONSTANT); $$->next = $2; $$->val = (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .asn = $1, .kind = PM_ASN, }, }; }
- | NUM DDOT NUM bgp_path_tail  { $$ = f_new_inst(FI_CONSTANT); $$->next = $4; $$->val = (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .from = $1, .to = $3, .kind = PM_ASN_RANGE }, }; }
- | '*' bgp_path_tail           { $$ = f_new_inst(FI_CONSTANT); $$->next = $2; $$->val = (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .kind = PM_ASTERISK }, }; }
- | '?' bgp_path_tail           { $$ = f_new_inst(FI_CONSTANT); $$->next = $2; $$->val = (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .kind = PM_QUESTION }, }; }
- | bgp_path_expr bgp_path_tail { $$ = $1; $$->next = $2; }
+   NUM bgp_path_tail           { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .asn = $1, .kind = PM_ASN, }, }); f_inst_next($$, $2);  }
+ | NUM DDOT NUM bgp_path_tail  { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .from = $1, .to = $3, .kind = PM_ASN_RANGE }, }); f_inst_next($$, $4); }
+ | '*' bgp_path_tail           { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .kind = PM_ASTERISK }, }); f_inst_next($$, $2); }
+ | '?' bgp_path_tail           { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .kind = PM_QUESTION }, }); f_inst_next($$, $2); }
+ | bgp_path_expr bgp_path_tail { $$ = $1; f_inst_next($$, $2); }
  |                             { $$ = NULL; }
  ;
 
 constant:
-   NUM    { $$ = f_new_inst(FI_CONSTANT); $$->val = (struct f_val) { .type = T_INT, .val.i = $1, }; }
- | TRUE   { $$ = f_new_inst(FI_CONSTANT); $$->val = (struct f_val) { .type = T_BOOL, .val.i = 1, }; }
- | FALSE  { $$ = f_new_inst(FI_CONSTANT); $$->val = (struct f_val) { .type = T_BOOL, .val.i = 0, }; }
- | TEXT   { $$ = f_new_inst(FI_CONSTANT); $$->val = (struct f_val) { .type = T_STRING, .val.s = $1, }; }
- | fipa          { $$ = f_new_inst(FI_CONSTANT); $$->val = $1; }
- | VPN_RD { $$ = f_new_inst(FI_CONSTANT); $$->val = (struct f_val) { .type = T_RD, .val.ec = $1, }; }
- | net_   { $$ = f_new_inst(FI_CONSTANT); $$->val = (struct f_val) { .type = T_NET, .val.net = $1, }; }
+   NUM    { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_INT, .val.i = $1, }); }
+ | TRUE   { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_BOOL, .val.i = 1, }); }
+ | FALSE  { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_BOOL, .val.i = 0, }); }
+ | TEXT   { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_STRING, .val.s = $1, }); }
+ | fipa          { $$ = f_new_inst(FI_CONSTANT, $1); }
+ | VPN_RD { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_RD, .val.ec = $1, }); }
+ | net_   { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_NET, .val.net = $1, }); }
  | '[' set_items ']' {
      DBG( "We've got a set here..." );
-     $$ = f_new_inst(FI_CONSTANT);
-     $$->val = (struct f_val) { .type = T_SET, .val.t = build_tree($2), };
+     $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_SET, .val.t = build_tree($2), });
      DBG( "ook\n" );
  }
- | '[' fprefix_set ']' { $$ = f_new_inst(FI_CONSTANT); $$->val = (struct f_val) { .type = T_PREFIX_SET, .val.ti = $2, }; }
- | ENUM          { $$ = f_new_inst(FI_CONSTANT); $$->val = (struct f_val) { .type = $1 >> 16, .val.i = $1 & 0xffff, }; }
+ | '[' fprefix_set ']' { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PREFIX_SET, .val.ti = $2, }); }
+ | ENUM          { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = $1 >> 16, .val.i = $1 & 0xffff, }); }
  ;
 
 constructor:
-   '(' term ',' term ')' { $$ = f_generate_dpair($2, $4); }
- | '(' ec_kind ',' term ',' term ')' { $$ = f_generate_ec($2, $4, $6); }
- | '(' term ',' term ',' term ')' { $$ = f_generate_lc($2, $4, $6); }
- | bgp_path { $$ = f_generate_path_mask($1); }
+   '(' term ',' term ')' { $$ = f_new_inst(FI_PAIR_CONSTRUCT, $2, $4); }
+ | '(' ec_kind ',' term ',' term ')' { $$ = f_new_inst(FI_EC_CONSTRUCT, $4, $6, $2); }
+ | '(' term ',' term ',' term ')' { $$ = f_new_inst(FI_LC_CONSTRUCT, $2, $4, $6); }
+ | bgp_path { $$ = f_new_inst(FI_PATHMASK_CONSTRUCT, $1, 0); }
  ;
 
 
@@ -823,23 +811,7 @@ rtadot: /* EMPTY, we are not permitted RTA. prefix */
 
 function_call:
    SYM '(' var_list ')' {
-     struct symbol *sym;
-     struct f_inst *inst = $3;
-     if ($1->class != SYM_FUNCTION)
-       cf_error("You can't call something which is not a function. Really.");
-     DBG("You are calling function %s\n", $1->name);
-     $$ = f_new_inst(FI_CALL);
-     $$->a[0].p = inst;
-     $$->a[1].p = $1->def;
-     sym = $1->aux2;
-     while (sym || inst) {
-       if (!sym || !inst)
-        cf_error("Wrong number of arguments for function %s.", $1->name);
-       DBG( "You should pass parameter called %s\n", sym->name);
-       inst->a[0].p = sym;
-       sym = sym->aux2;
-       inst = inst->next;
-     }
+     $$ = f_new_inst(FI_CALL, $1, $3);
    }
  ;
 
@@ -847,15 +819,13 @@ symbol:
    SYM {
      switch ($1->class & 0xffff) {
        case SYM_CONSTANT_RANGE:
-         $$ = f_new_inst(FI_CONSTANT_INDIRECT);
-         $$->a[0].p = $1;
+         $$ = f_new_inst(FI_CONSTANT_INDIRECT, $1->def);
         break;
        case SYM_VARIABLE_RANGE:
-         $$ = f_new_inst(FI_VARIABLE);
-         $$->a[0].p = $1;
+         $$ = f_new_inst(FI_VARIABLE, $1);
         break;
        case SYM_ATTRIBUTE:
-         $$ = f_new_inst_da(FI_EA_GET, *((struct f_dynamic_attr *) $1->def));
+         $$ = f_new_inst(FI_EA_GET, *((struct f_dynamic_attr *) $1->def));
         break;
        default:
          cf_error("%s: variable expected.", $1->name);
@@ -876,22 +846,22 @@ static_attr:
 
 term:
    '(' term ')'                { $$ = $2; }
- | term '+' term       { $$ = f_new_inst(FI_ADD);      $$->a[0].p = $1; $$->a[1].p = $3; }
- | term '-' term       { $$ = f_new_inst(FI_SUBTRACT); $$->a[0].p = $1; $$->a[1].p = $3; }
- | term '*' term       { $$ = f_new_inst(FI_MULTIPLY); $$->a[0].p = $1; $$->a[1].p = $3; }
- | term '/' term       { $$ = f_new_inst(FI_DIVIDE);   $$->a[0].p = $1; $$->a[1].p = $3; }
- | term AND term       { $$ = f_new_inst(FI_AND);      $$->a[0].p = $1; $$->a[1].p = $3; }
- | term OR  term       { $$ = f_new_inst(FI_OR);       $$->a[0].p = $1; $$->a[1].p = $3; }
- | term '=' term       { $$ = f_new_inst(FI_EQ);       $$->a[0].p = $1; $$->a[1].p = $3; }
- | term NEQ term       { $$ = f_new_inst(FI_NEQ);      $$->a[0].p = $1; $$->a[1].p = $3; }
- | term '<' term       { $$ = f_new_inst(FI_LT);       $$->a[0].p = $1; $$->a[1].p = $3; }
- | term LEQ term       { $$ = f_new_inst(FI_LTE);      $$->a[0].p = $1; $$->a[1].p = $3; }
- | term '>' term       { $$ = f_new_inst(FI_LT);       $$->a[0].p = $3; $$->a[1].p = $1; }
- | term GEQ term       { $$ = f_new_inst(FI_LTE);      $$->a[0].p = $3; $$->a[1].p = $1; }
- | term '~' term       { $$ = f_new_inst(FI_MATCH);    $$->a[0].p = $1; $$->a[1].p = $3; }
- | term NMA term       { $$ = f_new_inst(FI_NOT_MATCH);$$->a[0].p = $1; $$->a[1].p = $3; }
- | '!' term            { $$ = f_new_inst(FI_NOT);      $$->a[0].p = $2; }
- | DEFINED '(' term ')' { $$ = f_new_inst(FI_DEFINED); $$->a[0].p = $3; }
+ | term '+' term       { $$ = f_new_inst(FI_ADD, $1, $3); }
+ | term '-' term       { $$ = f_new_inst(FI_SUBTRACT, $1, $3); }
+ | term '*' term       { $$ = f_new_inst(FI_MULTIPLY, $1, $3); }
+ | term '/' term       { $$ = f_new_inst(FI_DIVIDE, $1, $3); }
+ | term AND term       { $$ = f_new_inst(FI_AND, $1, $3); }
+ | term OR  term       { $$ = f_new_inst(FI_OR, $1, $3); }
+ | term '=' term       { $$ = f_new_inst(FI_EQ, $1, $3); }
+ | term NEQ term       { $$ = f_new_inst(FI_NEQ, $1, $3); }
+ | term '<' term       { $$ = f_new_inst(FI_LT, $1, $3); }
+ | term LEQ term       { $$ = f_new_inst(FI_LTE, $1, $3); }
+ | term '>' term       { $$ = f_new_inst(FI_LT, $3, $1); }
+ | term GEQ term       { $$ = f_new_inst(FI_LTE, $3, $1); }
+ | term '~' term       { $$ = f_new_inst(FI_MATCH, $1, $3); }
+ | term NMA term       { $$ = f_new_inst(FI_NOT_MATCH, $1, $3); }
+ | '!' term            { $$ = f_new_inst(FI_NOT, $2); }
+ | DEFINED '(' term ')' { $$ = f_new_inst(FI_DEFINED, $3); }
 
  | symbol   { $$ = $1; }
  | constant { $$ = $1; }
@@ -899,22 +869,22 @@ term:
 
  | PREFERENCE { $$ = f_new_inst(FI_PREF_GET); }
 
- | rtadot static_attr { $$ = f_new_inst_sa(FI_RTA_GET, $2); }
+ | rtadot static_attr { $$ = f_new_inst(FI_RTA_GET, $2); }
 
- | rtadot dynamic_attr { $$ = f_new_inst_da(FI_EA_GET, $2); }
+ | rtadot dynamic_attr { $$ = f_new_inst(FI_EA_GET, $2); }
 
- | term '.' IS_V4 { $$ = f_new_inst(FI_IS_V4); $$->a[0].p = $1; }
- | term '.' TYPE { $$ = f_new_inst(FI_TYPE); $$->a[0].p = $1; }
- | term '.' IP { $$ = f_new_inst(FI_IP); $$->a[0].p = $1; $$->aux = T_IP; }
- | term '.' RD { $$ = f_new_inst(FI_ROUTE_DISTINGUISHER); $$->a[0].p = $1; $$->aux = T_RD; }
- | term '.' LEN { $$ = f_new_inst(FI_LENGTH); $$->a[0].p = $1; }
- | term '.' MAXLEN { $$ = f_new_inst(FI_ROA_MAXLEN); $$->a[0].p = $1; }
- | term '.' ASN { $$ = f_new_inst(FI_ROA_ASN); $$->a[0].p = $1; }
- | term '.' SRC { $$ = f_new_inst(FI_SADR_SRC); $$->a[0].p = $1; }
- | term '.' MASK '(' term ')' { $$ = f_new_inst(FI_IP_MASK); $$->a[0].p = $1; $$->a[1].p = $5; }
- | term '.' FIRST { $$ = f_new_inst(FI_AS_PATH_FIRST); $$->a[0].p = $1; }
- | term '.' LAST  { $$ = f_new_inst(FI_AS_PATH_LAST); $$->a[0].p = $1; }
- | term '.' LAST_NONAGGREGATED  { $$ = f_new_inst(FI_AS_PATH_LAST_NAG); $$->a[0].p = $1; }
+ | term '.' IS_V4 { $$ = f_new_inst(FI_IS_V4, $1); }
+ | term '.' TYPE { $$ = f_new_inst(FI_TYPE, $1); }
+ | term '.' IP { $$ = f_new_inst(FI_IP, $1); }
+ | term '.' RD { $$ = f_new_inst(FI_ROUTE_DISTINGUISHER, $1); }
+ | term '.' LEN { $$ = f_new_inst(FI_LENGTH, $1); }
+ | term '.' MAXLEN { $$ = f_new_inst(FI_ROA_MAXLEN, $1); }
+ | term '.' ASN { $$ = f_new_inst(FI_ROA_ASN, $1); }
+ | term '.' SRC { $$ = f_new_inst(FI_SADR_SRC, $1); }
+ | term '.' MASK '(' term ')' { $$ = f_new_inst(FI_IP_MASK, $1, $5); }
+ | term '.' FIRST { $$ = f_new_inst(FI_AS_PATH_FIRST, $1); }
+ | term '.' LAST  { $$ = f_new_inst(FI_AS_PATH_LAST, $1); }
+ | term '.' LAST_NONAGGREGATED  { $$ = f_new_inst(FI_AS_PATH_LAST_NAG, $1); }
 
 /* Communities */
 /* This causes one shift/reduce conflict
@@ -924,19 +894,19 @@ term:
  | rtadot dynamic_attr '.' RESET{ }
 */
 
- | '+' EMPTY '+' { $$ = f_new_inst(FI_CONSTANT); $$->val = f_const_empty_path; }
- | '-' EMPTY '-' { $$ = f_new_inst(FI_CONSTANT); $$->val = f_const_empty_clist; }
- | '-' '-' EMPTY '-' '-' { $$ = f_new_inst(FI_CONSTANT); $$->val = f_const_empty_eclist; }
- | '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_new_inst(FI_CONSTANT); $$->val = f_const_empty_lclist; }
- | PREPEND '(' term ',' term ')' { $$ = f_new_inst(FI_PATH_PREPEND); $$->a[0].p = $3; $$->a[1].p = $5; }
- | ADD '(' term ',' term ')' { $$ = f_new_inst(FI_CLIST_ADD); $$->a[0].p = $3; $$->a[1].p = $5; }
- | DELETE '(' term ',' term ')' { $$ = f_new_inst(FI_CLIST_DEL); $$->a[0].p = $3; $$->a[1].p = $5; }
- | FILTER '(' term ',' term ')' { $$ = f_new_inst(FI_CLIST_FILTER); $$->a[0].p = $3; $$->a[1].p = $5; }
+ | '+' EMPTY '+' { $$ = f_new_inst(FI_CONSTANT, f_const_empty_path); }
+ | '-' EMPTY '-' { $$ = f_new_inst(FI_CONSTANT, f_const_empty_clist); }
+ | '-' '-' EMPTY '-' '-' { $$ = f_new_inst(FI_CONSTANT, f_const_empty_eclist); }
+ | '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_new_inst(FI_CONSTANT, f_const_empty_lclist); }
+ | PREPEND '(' term ',' term ')' { $$ = f_new_inst(FI_PATH_PREPEND, $3, $5); }
+ | ADD '(' term ',' term ')' { $$ = f_new_inst(FI_CLIST_ADD, $3, $5); }
+ | DELETE '(' term ',' term ')' { $$ = f_new_inst(FI_CLIST_DEL, $3, $5); }
+ | FILTER '(' term ',' term ')' { $$ = f_new_inst(FI_CLIST_FILTER, $3, $5); }
 
- | ROA_CHECK '(' rtable ')' { $$ = f_new_inst(FI_ROA_CHECK_IMPLICIT); $$->a[0].rtc = $3; }
- | ROA_CHECK '(' rtable ',' term ',' term ')' { $$ = f_new_inst(FI_ROA_CHECK_EXPLICIT); $$->a[2].rtc = $3; $$->a[0].p = $5; $$->a[1].p = $7; }
+ | ROA_CHECK '(' rtable ')' { $$ = f_new_inst(FI_ROA_CHECK_IMPLICIT, $3); }
+ | ROA_CHECK '(' rtable ',' term ',' term ')' { $$ = f_new_inst(FI_ROA_CHECK_EXPLICIT, $5, $7, $3); }
 
- | FORMAT '(' term ')' {  $$ = f_new_inst(FI_FORMAT); $$->a[0].p = $3; }
+ | FORMAT '(' term ')' {  $$ = f_new_inst(FI_FORMAT, $3); }
 
 /* | term '.' LEN { $$->code = P('P','l'); } */
 
@@ -953,30 +923,25 @@ break_command:
  ;
 
 print_one:
-   term { $$ = f_new_inst(FI_PRINT); $$->a[0].p = $1; $$->a[1].p = NULL; }
+   term { $$ = f_new_inst(FI_PRINT, $1); }
  ;
 
 print_list: /* EMPTY */ { $$ = NULL; }
  | print_one { $$ = $1; }
  | print_one ',' print_list {
      if ($1) {
-       $1->next = $3;
+       f_inst_next($1, $3);
        $$ = $1;
      } else $$ = $3;
    }
  ;
 
 var_listn: term {
-     $$ = f_new_inst(FI_SET);
-     $$->a[0].p = NULL;
-     $$->a[1].p = $1;
-     $$->next = NULL;
+     $$ = $1;
    }
  | term ',' var_listn {
-     $$ = f_new_inst(FI_SET);
-     $$->a[0].p = NULL;
-     $$->a[1].p = $1;
-     $$->next = $3;
+     $$ = $1;
+     f_inst_next($$, $3);
    }
  ;
 
@@ -986,58 +951,42 @@ var_list: /* EMPTY */ { $$ = NULL; }
 
 cmd:
    IF term THEN block {
-     $$ = f_new_inst(FI_CONDITION);
-     $$->a[0].p = $2;
-     $$->a[1].p = $4;
+     $$ = f_new_inst(FI_CONDITION, $2, $4, NULL);
    }
  | IF term THEN block ELSE block {
-     $$ = f_new_inst(FI_CONDITION);
-     $$->a[0].p = $2;
-     $$->a[1].p = $4;
-     $$->a[2].p = $6;
+     $$ = f_new_inst(FI_CONDITION, $2, $4, $6);
    }
  | SYM '=' term ';' {
      DBG( "Ook, we'll set value\n" );
      if ($1->class == SYM_ATTRIBUTE) {
-       $$ = f_new_inst_da(FI_EA_SET, *((struct f_dynamic_attr *) $1->def));
-       $$->a[0].p = $3;
+       $$ = f_new_inst(FI_EA_SET, *((struct f_dynamic_attr *) $1->def), $3);
      } else if (($1->class & ~T_MASK) == SYM_VARIABLE) {
-       $$ = f_new_inst(FI_SET);
-       $$->a[0].p = $1;
-       $$->a[1].p = $3;
+       $$ = f_new_inst(FI_SET, $3, $1);
      } else
        cf_error( "Symbol `%s' is read-only.", $1->name );
    }
  | RETURN term ';' {
      DBG( "Ook, we'll return the value\n" );
-     $$ = f_new_inst(FI_RETURN);
-     $$->a[0].p = $2;
+     $$ = f_new_inst(FI_RETURN, $2);
    }
  | rtadot dynamic_attr '=' term ';' {
-     $$ = f_new_inst_da(FI_EA_SET, $2);
-     $$->a[0].p = $4;
+     $$ = f_new_inst(FI_EA_SET, $2, $4);
    }
  | rtadot static_attr '=' term ';' {
-     $$ = f_new_inst_sa(FI_RTA_SET, $2);
-     if ($$->sa.readonly)
+     if ($2.readonly)
        cf_error( "This static attribute is read-only.");
-     $$->a[0].p = $4;
+     $$ = f_new_inst(FI_RTA_SET, $2, $4);
    }
  | PREFERENCE '=' term ';' {
-     $$ = f_new_inst(FI_PREF_SET);
-     $$->a[0].p = $3;
+     $$ = f_new_inst(FI_PREF_SET, $3);
    }
  | UNSET '(' rtadot dynamic_attr ')' ';' {
-     $$ = f_new_inst_da(FI_EA_SET, $4);
-     $$->aux = EAF_TYPE_UNDEF | EAF_TEMP;
-     $$->a[0].p = NULL;
+     $$ = f_new_inst(FI_EA_UNSET, $4);
    }
- | break_command print_list ';' { $$ = f_new_inst(FI_PRINT_AND_DIE); $$->a[0].p = $2; $$->a[1].i = $1; }
- | function_call ';' { $$ = f_new_inst(FI_DROP_RESULT); $$->a[0].p = $1; } 
+ | break_command print_list ';' { $$ = f_new_inst(FI_PRINT_AND_DIE, $2, $1); }
+ | function_call ';' { $$ = f_new_inst(FI_DROP_RESULT, $1); } 
  | CASE term '{' switch_body '}' {
-      $$ = f_new_inst(FI_SWITCH);
-      $$->a[0].p = $2;
-      $$->a[1].p = build_tree( $4 );
+      $$ = f_new_inst(FI_SWITCH, $2, build_tree($4));
    }
 
  | rtadot dynamic_attr '.' EMPTY ';' { $$ = f_generate_empty($2); }
index 913a76526193846e1f94193da1b936f0d2c38c13..cb8e5c5fe40000a4b9672374dd80fa726a1f6e7c 100644 (file)
@@ -17,9 +17,9 @@ m4_divert(-1)')
 m4_define(LINEP, `LINE($@)')
 m4_define(SYMBOL, `m4_divert(1)debug("%ssymbol %s\n", INDENT, item->sym->name);
 m4_divert(-1)')
-m4_define(VALI, `m4_divert(1)debug("%svalue %s\n", INDENT, val_dump(item->vp));
+m4_define(VALI, `m4_divert(1)debug("%svalue %s\n", INDENT, val_dump(&item->val));
 m4_divert(-1)')
-m4_define(VALI, `m4_divert(1)debug("%svalue %s\n", INDENT, val_dump(item->vp));
+m4_define(VAR, `m4_divert(1)debug("%svar %s: value %s\n", INDENT, item->sym->name, val_dump(item->vp));
 m4_divert(-1)')
 m4_define(FRET, `m4_divert(1)debug("%sfilter return value %d\n", INDENT, item->fret);
 m4_divert(-1)')
index 02c884096475a9540d192b47979cc4992b46353b..ae2b528966e545d441bda134a10e75b774de5518 100644 (file)
   INST(FI_PATHMASK_CONSTRUCT, 0, 1) {
     ARG_ANY(1);
     COUNT(2);
+
+    NEW([[]], [[
+       uint len = 0;
+       uint dyn = 0;
+       for (const struct f_inst *tt = f1; tt; tt = tt->next, len++)
+         if (tt->fi_code != FI_CONSTANT)
+           dyn++;
+
+       WHAT().count = len;
+       ]]);
+
     if (vstk.cnt < what->count) /* TODO: make this check systematic */
       runtime("Construction of BGP path mask from %u elements must have at least that number of elements", what->count);
 
     RESULT_OK;
   }
   INST(FI_VARIABLE, 0, 1) {
-    VALP(1); // res = * ((struct f_val *) what->a[0].p);
-    SAME([[if (strcmp(f1->sym->name, f2->sym->name)) return 0; ]]);
+    VAR;
     RESULT_OK;
   }
   INST(FI_CONSTANT_INDIRECT, 0, 1) {
-    VALP(1);
-    SAME([[if (!val_same(f1->vp, f2->vp)) return 0; ]]);
+    VALP;
     RESULT_OK;
   }
   INST(FI_PRINT, 1, 0) {
   }
   INST(FI_PRINT_AND_DIE, 0, 0) {
     POSTFIXIFY([[
-       if (what->a[0].p) {
-         pos = postfixify(dest, what->a[0].p, pos);
-         dest->items[pos].flags |= FIF_PRINTED;
-       }
+      {
+       uint opos = pos;
     ]]);
-    LINE_SIZE([[
-       if (what->a[0].p) {
-         cnt += inst_line_size(what->a[0].p);
-       }
+
+    ARG_ANY(1);
+
+    POSTFIXIFY([[
+       if (opos < pos)
+         dest->items[pos].flags |= FIF_PRINTED;
+      }
     ]]);
 
     FRET(2);
          runtime( "Setting lclist attribute to non-lclist value" );
        l->attrs[0].u.ptr = v1.val.ad;
        break;
-      case EAF_TYPE_UNDEF:
-       if (v1.type != T_VOID)
-         runtime( "Setting void attribute to non-void value" );
-       l->attrs[0].u.data = 0;
-       break;
       default: bug("Unknown type in e,S");
       }
 
     }
   }
 
+  INST(FI_EA_UNSET, 0, 0) {
+    DYNAMIC_ATTR;
+    ACCESS_RTE;
+    ACCESS_EATTRS;
+
+    {
+      struct ea_list *l = lp_alloc(fs->pool, sizeof(struct ea_list) + sizeof(eattr));
+
+      l->next = NULL;
+      l->flags = EALF_SORTED;
+      l->count = 1;
+      l->attrs[0].id = da.ea_code;
+      l->attrs[0].flags = 0;
+      l->attrs[0].type = EAF_TYPE_UNDEF | EAF_TEMP | EAF_ORIGINATED | EAF_FRESH;
+      l->attrs[0].u.data = 0;
+
+      f_rta_cow(fs);
+      l->next = *fs->eattrs;
+      *fs->eattrs = l;
+    }
+  }
+
   INST(FI_PREF_GET, 0, 1) {
     ACCESS_RTE;
     RESULT(T_INT, i, (*fs->rte)->pref);
     if (!estk.cnt)
       if (vstk.val[retpos].type == T_BOOL)
        if (vstk.val[retpos].val.i)
+
          return F_ACCEPT;
        else
          return F_REJECT;
   }
 
   INST(FI_CALL, 0, 1) {
-    /* First push the code */
-    LINEP(2,0);
+    /* Do not use the symbol on execution */
+    if (0) {
+      UNUSED SYMBOL;
+    }
+
+    /* Postfixify extracts the function body from the symbol */
+    POSTFIXIFY([[
+       dest->items[pos].lines[0] = what->sym->def;
+    ]]);
+
+    /* First push the body on stack */
+    LINEX(what->lines[0]);
     curline.emask |= FE_RETURN;
 
     /* Then push the arguments */
     LINE(1,1);
+
+    NEW([[]], [[
+       if (sym->class != SYM_FUNCTION)
+         cf_error("You can't call something which is not a function. Really.");
+
+       uint count = 0;
+       for (const struct f_inst *inst = f1; inst; inst = inst->next)
+         count++;
+       
+       if (count != sym->aux2)
+         cf_error("Function %s takes %u arguments, got %u.", sym->name, sym->aux2, count);
+    ]]);
   }
 
   INST(FI_DROP_RESULT, 1, 0) {
     ARG_ANY(1);
   }
 
-  INST(FI_CLEAR_LOCAL_VARS, 0, 0) {    /* Clear local variables */
-    SYMBOL(1);
-    for ( ; sym != NULL; sym = sym->aux2)
-      ((struct f_val *) sym->def)->type = T_VOID;
-  }
   INST(FI_SWITCH, 1, 0) {
     ARG_ANY(1);
-    POSTFIXIFY([[
-       dest->items[pos].tree = what->a[1].p;
-       ]]);
+    TREE;
     const struct f_tree *t = find_tree(what->tree, &v1);
     if (!t) {
       v1.type = T_VOID;
 
   INST(FI_ASSERT, 1, 0) {      /* Birdtest Assert */
     ARG(1, T_BOOL);
-    POSTFIXIFY([[
-       dest->items[pos].s = what->a[1].p;
-    ]]);
+    STRING;
     CALL(bt_assert_hook, res.val.i, what);
   }
diff --git a/filter/f-inst.h b/filter/f-inst.h
new file mode 100644 (file)
index 0000000..5c3d1d5
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ *     BIRD Internet Routing Daemon -- Filter instructions
+ *
+ *     (c) 2018--2019 Maria Matejka <mq@jmq.cz>
+ *
+ *     Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+/* Filter instruction words */
+#define FI__TWOCHAR(a,b)       ((a<<8) | b)
+#define FI__LIST \
+  F(FI_NOP,                      0, '0') \
+  F(FI_ADD,                      0, '+') \
+  F(FI_SUBTRACT,                 0, '-') \
+  F(FI_MULTIPLY,                 0, '*') \
+  F(FI_DIVIDE,                   0, '/') \
+  F(FI_AND,                      0, '&') \
+  F(FI_OR,                       0, '|') \
+  F(FI_PAIR_CONSTRUCT,         'm', 'p') \
+  F(FI_EC_CONSTRUCT,           'm', 'c') \
+  F(FI_LC_CONSTRUCT,           'm', 'l') \
+  F(FI_PATHMASK_CONSTRUCT,     'm', 'P') \
+  F(FI_NEQ,                    '!', '=') \
+  F(FI_EQ,                     '=', '=') \
+  F(FI_LT,                       0, '<') \
+  F(FI_LTE,                    '<', '=') \
+  F(FI_NOT,                      0, '!') \
+  F(FI_MATCH,                    0, '~') \
+  F(FI_NOT_MATCH,              '!', '~') \
+  F(FI_DEFINED,                        'd', 'e') \
+  F(FI_TYPE,                     0, 'T') \
+  F(FI_IS_V4,                  'I', 'i') \
+  F(FI_SET,                      0, 's') \
+  F(FI_CONSTANT,                 0, 'c') \
+  F(FI_VARIABLE,                 0, 'V') \
+  F(FI_CONSTANT_INDIRECT,        0, 'C') \
+  F(FI_PRINT,                    0, 'p') \
+  F(FI_CONDITION,                0, '?') \
+  F(FI_PRINT_AND_DIE,          'p', ',') \
+  F(FI_RTA_GET,                          0, 'a') \
+  F(FI_RTA_SET,                        'a', 'S') \
+  F(FI_EA_GET,                 'e', 'a') \
+  F(FI_EA_SET,                 'e', 'S') \
+  F(FI_PREF_GET,                 0, 'P') \
+  F(FI_PREF_SET,               'P', 'S') \
+  F(FI_LENGTH,                   0, 'L') \
+  F(FI_ROA_MAXLEN,             'R', 'M') \
+  F(FI_ROA_ASN,                        'R', 'A') \
+  F(FI_SADR_SRC,               'n', 's') \
+  F(FI_IP,                     'c', 'p') \
+  F(FI_ROUTE_DISTINGUISHER,    'R', 'D') \
+  F(FI_AS_PATH_FIRST,          'a', 'f') \
+  F(FI_AS_PATH_LAST,           'a', 'l') \
+  F(FI_AS_PATH_LAST_NAG,       'a', 'L') \
+  F(FI_RETURN,                   0, 'r') \
+  F(FI_CALL,                   'c', 'a') \
+  F(FI_DROP_RESULT,            'd', 'r') \
+  F(FI_CLEAR_LOCAL_VARS,       'c', 'V') \
+  F(FI_SWITCH,                 'S', 'W') \
+  F(FI_IP_MASK,                        'i', 'M') \
+  F(FI_PATH_PREPEND,           'A', 'p') \
+  F(FI_CLIST_ADD,              'C', 'a') \
+  F(FI_CLIST_DEL,              'C', 'd') \
+  F(FI_CLIST_FILTER,           'C', 'f') \
+  F(FI_ROA_CHECK_IMPLICIT,     'R', 'i') \
+  F(FI_ROA_CHECK_EXPLICIT,     'R', 'e') \
+  F(FI_FORMAT,                   0, 'F') \
+  F(FI_ASSERT,                 'a', 's')
+
+/* The enum itself */
+enum f_instruction_code {
+#define F(c,a,b) \
+  c,
+FI__LIST
+#undef F
+  FI__MAX,
+} PACKED;
+
+/* Convert the instruction back to the enum name */
+const char *f_instruction_name(enum f_instruction_code fi);
+
+
+
+/* Instruction structure for config */
+struct f_inst {
+  const struct f_inst *next;           /* Next instruction to be executed */
+  union {                              /* Instruction content */
+    struct {                           /* Instruction code for dispatching purposes */
+      enum f_instruction_code fi_code;
+    };
+
+    struct {
+      enum f_instruction_code fi_code_a;
+      const struct f_inst *p[3];       /* Three arguments at most */
+    };
+
+    struct {
+
+
+
+    struct {
+      enum f_instruction_code 
+
+
+
+
+    enum f_iknst
+  u16 aux;             /* Extension to instruction code, T_*, EA_*, EAF_*  */
+  union {
+
+    union f_inst_attr a[3];            /* The three arguments */
+    struct f_val val;  /* The value if FI_CONSTANT */
+    struct {
+      union f_inst_attr sa_a[1];
+      struct f_static_attr sa; /* Static attribute def for FI_RTA_* */
+    };
+    struct {
+      union f_inst_attr da_a[1];
+      struct f_dynamic_attr da; /* Dynamic attribute def for FI_EA_* */
+    };
+  };
+  int lineno;
+};
+
index 4f11a6d933a7f9b76cb495894f22f462950fcb48..e94331b66f76eed01961dedb73a6a1bd9de62e8c 100644 (file)
 #include "nest/bird.h"
 #include "conf/conf.h"
 #include "filter/filter.h"
+#include "filter/f-inst-struct.h"
 #include "lib/idm.h"
 #include "nest/protocol.h"
 #include "nest/route.h"
 
 #define P(a,b) ((a<<8) | b)
 
-struct f_inst *
-f_new_inst(enum f_instruction_code fi_code)
-{
-  struct f_inst * ret;
-  ret = cfg_allocz(sizeof(struct f_inst));
-  ret->fi_code = fi_code;
-  ret->lineno = ifs->lino;
-  return ret;
-}
-
-struct f_inst *
-f_new_inst_da(enum f_instruction_code fi_code, struct f_dynamic_attr da)
-{
-  struct f_inst *ret = f_new_inst(fi_code);
-  ret->da = da;
-  return ret;
-}
-
-struct f_inst *
-f_new_inst_sa(enum f_instruction_code fi_code, struct f_static_attr sa)
-{
-  struct f_inst *ret = f_new_inst(fi_code);
-  ret->sa = sa;
-  return ret;
-}
-
-/*
- * Generate set_dynamic( operation( get_dynamic(), argument ) )
- */
-struct f_inst *
-f_generate_complex(enum f_instruction_code fi_code, struct f_dynamic_attr da, struct f_inst *argument)
-{
-  struct f_inst *set_dyn = f_new_inst_da(FI_EA_SET, da),
-                *oper = f_new_inst(fi_code),
-                *get_dyn = f_new_inst_da(FI_EA_GET, da);
-
-  oper->a[0].p = get_dyn;
-  oper->a[1].p = argument;
-
-  set_dyn->a[0].p = oper;
-  return set_dyn;
-}
-
 static const char * const f_instruction_name_str[] = {
-#define F(c,a,b) \
+#define F(c,...) \
   [c] = #c,
 FI__LIST
 #undef F
@@ -88,6 +46,58 @@ filter_name(struct filter *filter)
     return filter->name;
 }
 
+void f_inst_next(struct f_inst *first, const struct f_inst *append)
+{
+  first->next = append;
+}
+
+struct filter *f_new_where(const struct f_inst *where)
+{
+  struct f_inst acc = {
+    .fi_code = FI_PRINT_AND_DIE,
+    .lineno = ifs->lino,
+    .i_FI_PRINT_AND_DIE = { .fret = F_ACCEPT, },
+  };
+
+  struct f_inst rej = {
+    .fi_code = FI_PRINT_AND_DIE,
+    .lineno = ifs->lino,
+    .i_FI_PRINT_AND_DIE = { .fret = F_REJECT, },
+  };
+
+  struct f_inst i = {
+    .fi_code = FI_CONDITION,
+    .lineno = ifs->lino,
+    .i_FI_CONDITION = {
+      .f1 = where,
+      .f2 = &acc,
+      .f3 = &rej,
+    },
+  };
+
+  struct filter *f = cfg_alloc(sizeof(struct filter));
+  f->name = NULL;
+  f->root = f_postfixify(&i);
+  return f;
+}
+
+struct f_inst *f_clear_local_vars(struct f_inst *decls)
+{
+  /* Prepend instructions to clear local variables */
+  struct f_inst *head = NULL;
+
+  for (const struct f_inst *si = decls; si; si = si->next) {
+    struct f_inst *cur = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_VOID });
+    if (head)
+      f_inst_next(cur, head);
+    else
+      f_inst_next(cur, si);
+    head = cur;        /* The first FI_CONSTANT put there */
+  }
+
+  return head;
+}
+
 #define CA_KEY(n)      n->name, n->fda.type
 #define CA_NEXT(n)     n->next
 #define CA_EQ(na,ta,nb,tb)     (!strcmp(na,nb) && (ta == tb))
index 858d5fc580c634340c29db089dcfaa68d0d8733a..a69d1b3d188a357e29093fe33c9db0f213485399 100644 (file)
@@ -47,6 +47,7 @@
 #include "nest/attrs.h"
 #include "conf/conf.h"
 #include "filter/filter.h"
+#include "filter/f-inst-struct.h"
 
 #define CMP_ERROR 999
 
@@ -614,11 +615,11 @@ val_format_str(struct filter_state *fs, struct f_val *v) {
 static struct tbf rl_runtime_err = TBF_DEFAULT_LOG_LIMITS;
 
 static uint
-inst_line_size(const struct f_inst *what)
+inst_line_size(const struct f_inst *what_)
 {
   uint cnt = 0;
-  for ( ; what; what = what->next) {
-    switch (what->fi_code) {
+  for ( ; what_; what_ = what_->next) {
+    switch (what_->fi_code) {
 #include "filter/f-inst-line-size.c"
     }
   }
@@ -671,10 +672,10 @@ f_dump_line(const struct f_line *dest, int indent)
 #endif
 
 static uint
-postfixify(struct f_line *dest, const struct f_inst *what, uint pos)
+postfixify(struct f_line *dest, const struct f_inst *what_, uint pos)
 {
-  for ( ; what; what = what->next) {
-    switch (what->fi_code) {
+  for ( ; what_; what_ = what_->next) {
+    switch (what_->fi_code) {
 #include "filter/f-inst-postfixify.c"
     }
     pos++;
@@ -683,23 +684,16 @@ postfixify(struct f_line *dest, const struct f_inst *what, uint pos)
 }
 
 struct f_line *
-f_postfixify_concat(struct f_inst *first, ...)
+f_postfixify_concat(const struct f_inst * const inst[], uint count)
 {
-  va_list args;
-  va_list argd;
-  va_start(args, first);
-  va_copy(argd, args);
-
   uint len = 0;
-  for (struct f_inst *what = first; what; what = va_arg(args, struct f_inst *))
-    len += inst_line_size(what);
-
-  va_end(args);
+  for (uint i=0; i<count; i++)
+    len += inst_line_size(inst[i]);
 
   struct f_line *out = cfg_allocz(sizeof(struct f_line) + sizeof(struct f_line_item)*len);
 
-  for (struct f_inst *what = first; what; what = va_arg(argd, struct f_inst *))
-    out->len = postfixify(out, what, out->len);
+  for (uint i=0; i<count; i++)
+    out->len = postfixify(out, inst[i], out->len);
 
   f_dump_line(out, 0);
   return out;
index 87bd2c36e173d2e0af38adb9bca816c4d353942b..39f16e93b8b312063842324601e50b1a956482e9 100644 (file)
@@ -2,6 +2,7 @@
  *     BIRD Internet Routing Daemon -- Filters
  *
  *     (c) 1999 Pavel Machek <pavel@ucw.cz>
+ *     (c) 2018--2019 Maria Matejka <mq@jmq.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
@@ -11,6 +12,7 @@
 
 #include "lib/resource.h"
 #include "lib/ip.h"
+#include "lib/macro.h"
 #include "nest/route.h"
 #include "nest/attrs.h"
 
@@ -115,71 +117,80 @@ struct f_static_attr {
   int readonly:1;                      /* Don't allow writing */
 };
 
-/* Filter instruction words */
-#define FI__TWOCHAR(a,b)       ((a<<8) | b)
+/* Possible return values of filter execution */
+enum filter_return {
+  F_NOP = 0,
+  F_NONL,
+  F_RETURN,
+  F_ACCEPT,   /* Need to preserve ordering: accepts < rejects! */
+  F_REJECT,
+  F_ERROR,
+  F_QUITBIRD,
+};
+
+/* Filter instruction declarations */
 #define FI__LIST \
-  F(FI_NOP,                      0, '0') \
-  F(FI_ADD,                      0, '+') \
-  F(FI_SUBTRACT,                 0, '-') \
-  F(FI_MULTIPLY,                 0, '*') \
-  F(FI_DIVIDE,                   0, '/') \
-  F(FI_AND,                      0, '&') \
-  F(FI_OR,                       0, '|') \
-  F(FI_PAIR_CONSTRUCT,         'm', 'p') \
-  F(FI_EC_CONSTRUCT,           'm', 'c') \
-  F(FI_LC_CONSTRUCT,           'm', 'l') \
-  F(FI_PATHMASK_CONSTRUCT,     'm', 'P') \
-  F(FI_NEQ,                    '!', '=') \
-  F(FI_EQ,                     '=', '=') \
-  F(FI_LT,                       0, '<') \
-  F(FI_LTE,                    '<', '=') \
-  F(FI_NOT,                      0, '!') \
-  F(FI_MATCH,                    0, '~') \
-  F(FI_NOT_MATCH,              '!', '~') \
-  F(FI_DEFINED,                        'd', 'e') \
-  F(FI_TYPE,                     0, 'T') \
-  F(FI_IS_V4,                  'I', 'i') \
-  F(FI_SET,                      0, 's') \
-  F(FI_CONSTANT,                 0, 'c') \
-  F(FI_VARIABLE,                 0, 'V') \
-  F(FI_CONSTANT_INDIRECT,        0, 'C') \
-  F(FI_PRINT,                    0, 'p') \
-  F(FI_CONDITION,                0, '?') \
-  F(FI_PRINT_AND_DIE,          'p', ',') \
-  F(FI_RTA_GET,                          0, 'a') \
-  F(FI_RTA_SET,                        'a', 'S') \
-  F(FI_EA_GET,                 'e', 'a') \
-  F(FI_EA_SET,                 'e', 'S') \
-  F(FI_PREF_GET,                 0, 'P') \
-  F(FI_PREF_SET,               'P', 'S') \
-  F(FI_LENGTH,                   0, 'L') \
-  F(FI_ROA_MAXLEN,             'R', 'M') \
-  F(FI_ROA_ASN,                        'R', 'A') \
-  F(FI_SADR_SRC,               'n', 's') \
-  F(FI_IP,                     'c', 'p') \
-  F(FI_ROUTE_DISTINGUISHER,    'R', 'D') \
-  F(FI_AS_PATH_FIRST,          'a', 'f') \
-  F(FI_AS_PATH_LAST,           'a', 'l') \
-  F(FI_AS_PATH_LAST_NAG,       'a', 'L') \
-  F(FI_RETURN,                   0, 'r') \
-  F(FI_CALL,                   'c', 'a') \
-  F(FI_DROP_RESULT,            'd', 'r') \
-  F(FI_CLEAR_LOCAL_VARS,       'c', 'V') \
-  F(FI_SWITCH,                 'S', 'W') \
-  F(FI_IP_MASK,                        'i', 'M') \
-  F(FI_PATH_PREPEND,           'A', 'p') \
-  F(FI_CLIST_ADD,              'C', 'a') \
-  F(FI_CLIST_DEL,              'C', 'd') \
-  F(FI_CLIST_FILTER,           'C', 'f') \
-  F(FI_ROA_CHECK_IMPLICIT,     'R', 'i') \
-  F(FI_ROA_CHECK_EXPLICIT,     'R', 'e') \
-  F(FI_FORMAT,                   0, 'F') \
-  F(FI_ASSERT,                 'a', 's')
+  F(FI_NOP) \
+  F(FI_ADD, ARG, ARG) \
+  F(FI_SUBTRACT, ARG, ARG) \
+  F(FI_MULTIPLY, ARG, ARG) \
+  F(FI_DIVIDE, ARG, ARG) \
+  F(FI_AND, ARG, LINE) \
+  F(FI_OR, ARG, LINE) \
+  F(FI_PAIR_CONSTRUCT, ARG, ARG) \
+  F(FI_EC_CONSTRUCT, ARG, ARG, ECS) \
+  F(FI_LC_CONSTRUCT, ARG, ARG, ARG) \
+  F(FI_PATHMASK_CONSTRUCT, ARG, COUNT) \
+  F(FI_NEQ, ARG, ARG) \
+  F(FI_EQ, ARG, ARG) \
+  F(FI_LT, ARG, ARG) \
+  F(FI_LTE, ARG, ARG) \
+  F(FI_NOT, ARG) \
+  F(FI_MATCH, ARG, ARG) \
+  F(FI_NOT_MATCH, ARG, ARG) \
+  F(FI_DEFINED, ARG) \
+  F(FI_TYPE, ARG) \
+  F(FI_IS_V4, ARG) \
+  F(FI_SET, ARG, SYMBOL) \
+  F(FI_CONSTANT, VALI) \
+  F(FI_VARIABLE, SYMBOL) \
+  F(FI_CONSTANT_INDIRECT, VALP) \
+  F(FI_PRINT, ARG) \
+  F(FI_CONDITION, ARG, LINE, LINE) \
+  F(FI_PRINT_AND_DIE, ARG, FRET) \
+  F(FI_RTA_GET, SA) \
+  F(FI_RTA_SET, SA, ARG) \
+  F(FI_EA_GET, EA) \
+  F(FI_EA_SET, EA, ARG) \
+  F(FI_EA_UNSET, EA) \
+  F(FI_PREF_GET) \
+  F(FI_PREF_SET, ARG) \
+  F(FI_LENGTH, ARG) \
+  F(FI_ROA_MAXLEN, ARG) \
+  F(FI_ROA_ASN, ARG) \
+  F(FI_SADR_SRC, ARG) \
+  F(FI_IP, ARG) \
+  F(FI_ROUTE_DISTINGUISHER, ARG) \
+  F(FI_AS_PATH_FIRST, ARG) \
+  F(FI_AS_PATH_LAST, ARG) \
+  F(FI_AS_PATH_LAST_NAG, ARG) \
+  F(FI_RETURN, ARG) \
+  F(FI_CALL, SYMBOL, LINE) \
+  F(FI_DROP_RESULT, ARG) \
+  F(FI_SWITCH, ARG, TREE) \
+  F(FI_IP_MASK, ARG, ARG) \
+  F(FI_PATH_PREPEND, ARG, ARG) \
+  F(FI_CLIST_ADD, ARG, ARG) \
+  F(FI_CLIST_DEL, ARG, ARG) \
+  F(FI_CLIST_FILTER, ARG, ARG) \
+  F(FI_ROA_CHECK_IMPLICIT, RTC) \
+  F(FI_ROA_CHECK_EXPLICIT, ARG, ARG, RTC) \
+  F(FI_FORMAT, ARG) \
+  F(FI_ASSERT, ARG, STRING)
 
 /* The enum itself */
 enum f_instruction_code {
-#define F(c,a,b) \
-  c,
+#define F(c, ...) c,
 FI__LIST
 #undef F
   FI__MAX,
@@ -188,47 +199,50 @@ FI__LIST
 /* Convert the instruction back to the enum name */
 const char *f_instruction_name(enum f_instruction_code fi);
 
+struct f_inst;
+void f_inst_next(struct f_inst *first, const struct f_inst *append);
+struct f_inst *f_clear_local_vars(struct f_inst *decls);
+
+#define FIA(x) , FIA_##x
+#define FIA_ARG        const struct f_inst *
+#define FIA_LINE const struct f_inst *
+#define FIA_COUNT uint
+#define FIA_SYMBOL const struct symbol *
+#define FIA_VALI struct f_val
+#define FIA_VALP const struct f_val *
+#define FIA_FRET enum filter_return
+#define FIA_ECS enum ec_subtype
+#define FIA_SA struct f_static_attr
+#define FIA_EA struct f_dynamic_attr
+#define FIA_RTC const struct rtable_config *
+#define FIA_TREE const struct f_tree *
+#define FIA_STRING const char *
+#define F(c, ...) \
+  struct f_inst *f_new_inst_##c(enum f_instruction_code MACRO_IFELSE(MACRO_ISLAST(__VA_ARGS__))()(MACRO_FOREACH(FIA, __VA_ARGS__)));
+FI__LIST
+#undef F
+#undef FIA_ARG
+#undef FIA_LINE
+#undef FIA_LINEP
+#undef FIA_COUNT
+#undef FIA_SYMBOL
+#undef FIA_VALI
+#undef FIA_VALP
+#undef FIA_FRET
+#undef FIA_ECS
+#undef FIA_SA
+#undef FIA_EA
+#undef FIA_RTC
+#undef FIA_STRING
+#undef FIA
+
+#define f_new_inst(...) MACRO_CONCAT_AFTER(f_new_inst_, MACRO_FIRST(__VA_ARGS__))(__VA_ARGS__)
+
+/* Flags for instructions */
 enum f_instruction_flags {
   FIF_PRINTED = 1,             /* FI_PRINT_AND_DIE: message put in buffer */
 };
 
-union f_inst_attr {
-  uint i;
-  void *p;
-  struct rtable_config *rtc;
-};
-
-/* Instruction structure for config */
-struct f_inst {
-  struct f_inst *next; /* Next instruction to be executed */
-  enum f_instruction_code fi_code;     /* The instruction itself */
-  u16 aux;             /* Extension to instruction code, T_*, EA_*, EAF_*  */
-  union {
-    union f_inst_attr a[3];            /* The three arguments */
-    struct f_val val;  /* The value if FI_CONSTANT */
-    struct {
-      union f_inst_attr sa_a[1];
-      struct f_static_attr sa; /* Static attribute def for FI_RTA_* */
-    };
-    struct {
-      union f_inst_attr da_a[1];
-      struct f_dynamic_attr da; /* Dynamic attribute def for FI_EA_* */
-    };
-  };
-  int lineno;
-};
-
-/* Possible return values of filter execution */
-enum filter_return {
-  F_NOP = 0,
-  F_NONL,
-  F_RETURN,
-  F_ACCEPT,   /* Need to preserve ordering: accepts < rejects! */
-  F_REJECT,
-  F_ERROR,
-  F_QUITBIRD,
-};
-
 /* Filter structures for execution */
 struct f_line;
 
@@ -242,6 +256,7 @@ struct f_line_item {
       const struct f_val *vp;
       const struct symbol *sym;
     };
+    struct f_val val;
     const struct f_line *lines[2];
     enum filter_return fret;
     struct f_static_attr sa;
@@ -267,9 +282,9 @@ struct filter {
 };
 
 /* Convert the f_inst infix tree to the f_line structures */
-struct f_line *f_postfixify_concat(struct f_inst *root, ...);
-static inline struct f_line *f_postfixify(struct f_inst *root)
-{ return f_postfixify_concat(root, NULL); }
+struct f_line *f_postfixify_concat(const struct f_inst * const inst[], uint count);
+static inline struct f_line *f_postfixify(const struct f_inst *root)
+{ return f_postfixify_concat(&root, 1); }
 
 #define F_VAL_STACK_MAX        4096
 
@@ -295,12 +310,9 @@ struct f_exec_stack {
     enum f_exception emask;            /* Exception mask */
   } item[F_EXEC_STACK_MAX];
   uint cnt;                            /* Current stack size; 0 for empty */
-  
 };
 
-struct f_inst *f_new_inst(enum f_instruction_code fi_code);
-struct f_inst *f_new_inst_da(enum f_instruction_code fi_code, struct f_dynamic_attr da);
-struct f_inst *f_new_inst_sa(enum f_instruction_code fi_code, struct f_static_attr sa);
+struct filter *f_new_where(const struct f_inst *);
 static inline struct f_dynamic_attr f_new_dynamic_attr(u8 type, u8 bit, enum f_type f_type, uint code) /* Type as core knows it, type as filters know it, and code of dynamic attribute */
 { return (struct f_dynamic_attr) { .type = type, .bit = bit, .f_type = f_type, .ea_code = code }; }   /* f_type currently unused; will be handy for static type checking */
 static inline struct f_static_attr f_new_static_attr(int f_type, int code, int readonly)
index 829b48f631d7cd5d4dda0fa36de55ffe1b852f7f..f449d5804f128392d0ea40eaaad7d7a3ed18fe06 100644 (file)
@@ -45,17 +45,22 @@ m4_define(ARG_ANY, `')
 
 m4_define(SYMBOL, `const struct symbol *sym = what->sym')
 
-m4_define(VALI, `res = *what->vp')
-m4_define(VALP, `res = *what->vp')
+m4_define(VALI, `res = what->val')
+m4_define(VALP, `res = what->val')
+m4_define(VAR, `res = *what->vp')
 m4_define(FRET, `enum filter_return fret = what->fret')
 m4_define(ECS, `enum ec_subtype ecs = what->ecs')
 m4_define(RTC, `struct rtable *table = what->rtc->table')
 m4_define(STATIC_ATTR, `struct f_static_attr sa = what->sa')
 m4_define(DYNAMIC_ATTR, `struct f_dynamic_attr da = what->da')
+m4_define(TREE, `')
+m4_define(STRING, `')
+m4_define(COUNT, `')
 m4_define(POSTFIXIFY, `')
 m4_define(LINE_SIZE, `')
 m4_define(SAME, `')
-m4_define(COUNT, `')
+m4_define(STRUCT, `')
+m4_define(NEW, `')
 
 m4_m4wrap(`
 m4_divert(0)DNL
index 0c005fa1c69213567d8881ffb605f757add8fae1..2c6b500bcaaf5a6af32269e4c1d6507c595e8ff1 100644 (file)
@@ -10,13 +10,16 @@ m4_divert(-1)m4_dnl
 # Common aliases
 m4_define(DNL, `m4_dnl')
 
-m4_define(INST, `m4_divert(1)break; case $1: cnt += 1;
+m4_define(INST, `m4_divert(1)
+#undef what
+break; case $1: cnt += 1;
+#define what ((const struct f_inst_$1 *) &(what_->i_$1))
 m4_divert(-1)')
-m4_define(ARG, `m4_divert(1)cnt += inst_line_size(what->a[$1-1].p);
+m4_define(ARG, `m4_divert(1)cnt += inst_line_size(what->f$1);
 m4_divert(-1)')
-m4_define(ARG_T, `m4_divert(1)cnt += inst_line_size(what->a[$1-1].p);
+m4_define(ARG_T, `m4_divert(1)cnt += inst_line_size(what->f$1);
 m4_divert(-1)')
-m4_define(ARG_ANY, `m4_divert(1)cnt += inst_line_size(what->a[$1-1].p);
+m4_define(ARG_ANY, `m4_divert(1)cnt += inst_line_size(what->f$1);
 m4_divert(-1)')
 m4_define(LINE_SIZE, `m4_divert(1)$1m4_divert(-1)')
 
@@ -24,7 +27,8 @@ m4_m4wrap(`
 m4_divert(0)DNL
 case FI_NOP: bug("This shall not happen");
 m4_undivert(1)
-break; default: bug( "Unknown instruction %d (%c)", what->fi_code, what->fi_code & 0xff);
+#undef what
+break; default: bug( "Unknown instruction %d (%c)", what_->fi_code, what_->fi_code & 0xff);
 ')
 
 m4_changequote([[,]])
diff --git a/filter/new.m4 b/filter/new.m4
new file mode 100644 (file)
index 0000000..ebb367d
--- /dev/null
@@ -0,0 +1,84 @@
+m4_divert(-1)m4_dnl
+#
+#      BIRD -- Construction of per-instruction structures
+#
+#      (c) 2018 Maria Matejka <mq@jmq.cz>
+#
+#      Can be freely distributed and used under the terms of the GNU GPL.
+#
+#
+#      Diversions:
+#      1       for prepared output
+#      2       for function arguments
+#      3       for function body
+
+# Common aliases
+m4_define(DNL, `m4_dnl')
+
+m4_define(FNSTOP, `m4_divert(-1)')
+m4_define(FNOUT, `m4_divert(1)')
+m4_define(FNARG, `m4_divert(2)')
+m4_define(FNBODY, `m4_divert(3)')
+
+m4_define(INST,        `m4_define([[INST_NAME]], [[$1]])FNOUT()DNL
+m4_undivert(2)DNL
+m4_undivert(3)DNL
+  return what;
+}
+
+struct f_inst *f_new_inst_$1(enum f_instruction_code fi_code
+FNBODY()) {
+  struct f_inst *what = cfg_allocz(sizeof(struct f_inst));
+  what->fi_code = fi_code;
+  what->lineno = ifs->lino;
+FNSTOP()')
+
+m4_define(WHAT, `what->i_[[]]INST_NAME()')
+
+m4_define(FNMETAARG, `FNARG(), $1 $2
+FNBODY() WHAT().$2 = $2;
+FNSTOP()')
+m4_define(ARG, `FNMETAARG(const struct f_inst *, f$1)')
+m4_define(ARG_ANY, `FNMETAARG(const struct f_inst *, f$1)')
+m4_define(LINE, `FNMETAARG(const struct f_inst *, f$1)')
+m4_define(SYMBOL, `FNMETAARG(const struct symbol *, sym)')
+m4_define(VALI, `FNMETAARG(struct f_val, vali)')
+m4_define(VALP, `FNMETAARG(const struct f_val *, valp)')
+m4_define(VAR, `FNARG(), const struct symbol * sym
+FNBODY() WHAT().valp = (WHAT().sym = sym)->def;
+FNSTOP()')
+m4_define(FRET, `FNMETAARG(enum filter_return, fret)')
+m4_define(ECS, `FNMETAARG(enum ec_subtype, ecs)')
+m4_define(RTC, `FNMETAARG(const struct rtable_config *, rtc)')
+m4_define(STATIC_ATTR, `FNMETAARG(struct f_static_attr, sa)')
+m4_define(DYNAMIC_ATTR, `FNMETAARG(struct f_dynamic_attr, da)')
+m4_define(COUNT, `FNMETAARG(uint, count)')
+m4_define(TREE, `FNMETAARG(const struct f_tree *, tree)')
+m4_define(STRING, `FNMETAARG(const char *, s)')
+m4_define(NEW, `FNARG()$1
+FNBODY()$2
+FNSTOP()')
+
+m4_m4wrap(`
+FNOUT()
+m4_undivert(2)
+m4_undivert(3)
+
+m4_divert(0)
+#include "nest/bird.h"
+#include "conf/conf.h"
+#include "filter/filter.h"
+#include "filter/f-inst-struct.h"
+
+struct f_inst *f_new_inst_FI_NOP(enum f_instruction_code fi_code) {
+  struct f_inst *what = cfg_allocz(sizeof(struct f_inst));
+  what->fi_code = fi_code;
+  what->lineno = ifs->lino;
+
+m4_undivert(1)
+
+  return what;
+}
+')
+
+m4_changequote([[,]])
index 8c96ba642710779afb4ae62338c202e87136594d..36cadfbae5f45cd169d77b871a1aeebccfa37f04 100644 (file)
@@ -10,37 +10,45 @@ m4_divert(-1)m4_dnl
 # Common aliases
 m4_define(DNL, `m4_dnl')
 
-m4_define(POSTFIXIFY_TRAILER, `dest->items[pos].fi_code = what->fi_code;
-dest->items[pos].lineno = what->lineno;')
+m4_define(POSTFIXIFY_TRAILER, `dest->items[pos].fi_code = what_->fi_code;
+dest->items[pos].lineno = what_->lineno;')
 
 m4_define(INST, `m4_divert(1)POSTFIXIFY_TRAILER
-break; case $1:
+#undef what
+break; case $1: 
+#define what ((const struct f_inst_$1 *) &(what_->i_$1))
 m4_divert(-1)'))
-m4_define(ARG, `m4_divert(1)pos = postfixify(dest, what->a[$1-1].p, pos);
+m4_define(ARG, `m4_divert(1)pos = postfixify(dest, what->f$1, pos);
 m4_divert(-1)')
-m4_define(ARG_ANY, `m4_divert(1)pos = postfixify(dest, what->a[$1-1].p, pos);
+m4_define(ARG_ANY, `m4_divert(1)pos = postfixify(dest, what->f$1, pos);
 m4_divert(-1)')
-m4_define(LINE, `m4_divert(1)dest->items[pos].lines[$2] = f_postfixify(what->a[$1-1].p);
+m4_define(LINE, `m4_divert(1)dest->items[pos].lines[$2] = f_postfixify(what->f$1);
 m4_divert(-1)')
-m4_define(LINEP, `m4_divert(1)dest->items[pos].lines[$2] = what->a[$1-1].p;
+m4_define(LINEP, `m4_divert(1)dest->items[pos].lines[$2] = what->fl$1;
 m4_divert(-1)')
-m4_define(SYMBOL, `m4_divert(1)dest->items[pos].sym = what->a[$1-1].p;
+m4_define(SYMBOL, `m4_divert(1)dest->items[pos].sym = what->sym;
 m4_divert(-1)')
-m4_define(VALI, `m4_divert(1)dest->items[pos].vp = &(what->val);
+m4_define(VALI, `m4_divert(1)dest->items[pos].val = what->vali;
 m4_divert(-1)')
-m4_define(VALP, `m4_divert(1)dest->items[pos].vp = (dest->items[pos].sym = what->a[$1-1].p)->def;
+m4_define(VALP, `m4_divert(1)dest->items[pos].val = *(what->valp);
 m4_divert(-1)')
-m4_define(FRET, `m4_divert(1)dest->items[pos].fret = what->a[$1-1].i;
+m4_define(VAR, `m4_divert(1)dest->items[pos].vp = (dest->items[pos].sym = what->sym)->def;
 m4_divert(-1)')
-m4_define(ECS, `m4_divert(1)dest->items[pos].ecs = what->aux;
+m4_define(FRET, `m4_divert(1)dest->items[pos].fret = what->fret;
 m4_divert(-1)')
-m4_define(RTC, `m4_divert(1)dest->items[pos].rtc = what->a[$1-1].rtc;
+m4_define(ECS, `m4_divert(1)dest->items[pos].ecs = what->ecs;
+m4_divert(-1)')
+m4_define(RTC, `m4_divert(1)dest->items[pos].rtc = what->rtc;
 m4_divert(-1)')
 m4_define(STATIC_ATTR, `m4_divert(1)dest->items[pos].sa = what->sa;
 m4_divert(-1)')
 m4_define(DYNAMIC_ATTR, `m4_divert(1)dest->items[pos].da = what->da;
 m4_divert(-1)')
-m4_define(COUNT, `m4_divert(1)dest->items[pos].count = what->a[$1-1].i;
+m4_define(COUNT, `m4_divert(1)dest->items[pos].count = what->count;
+m4_divert(-1)')
+m4_define(TREE, `m4_divert(1)dest->items[pos].tree = what->tree;
+m4_divert(-1)')
+m4_define(STRING, `m4_divert(1)dest->items[pos].s = what->s;
 m4_divert(-1)')
 m4_define(POSTFIXIFY, `m4_divert(1)$1m4_divert(-1)')
 
@@ -49,7 +57,8 @@ m4_divert(0)DNL
 case FI_NOP: bug("This shall not happen");
 m4_undivert(1)
 POSTFIXIFY_TRAILER
-break; default: bug( "Unknown instruction %d (%c)", what->fi_code, what->fi_code & 0xff);
+#undef what
+break; default: bug( "Unknown instruction %d (%c)", what_->fi_code, what_->fi_code & 0xff);
 ')
 
 m4_changequote([[,]])
index 73f2d1c3b5e9d47f2d22d17aa2f4478489f08545..109794494c0eaac727df7dd8626ebb7383b58d6d 100644 (file)
@@ -29,7 +29,9 @@ m4_divert(-1)')
 
 m4_define(VALI, `m4_divert(1)if (!val_same(f1->vp, f2->vp)) return 0;
 m4_divert(-1)')
-m4_define(VALP, `')
+m4_define(VALP, `m4_divert(1)if (!val_same(f1->vp, f2->vp)) return 0;
+m4_divert(-1)')
+m4_define(VAR, `SYMBOL()VALP()')
 
 m4_define(FRET, `m4_divert(1)if (f1->fret != f2->fret) return 0;
 m4_divert(-1)')
diff --git a/filter/struct.m4 b/filter/struct.m4
new file mode 100644 (file)
index 0000000..66205bf
--- /dev/null
@@ -0,0 +1,67 @@
+m4_divert(-1)m4_dnl
+#
+#      BIRD -- Definition of per-instruction structures
+#
+#      (c) 2018 Maria Matejka <mq@jmq.cz>
+#
+#      Can be freely distributed and used under the terms of the GNU GPL.
+#
+
+# Common aliases
+m4_define(DNL, `m4_dnl')
+
+m4_define(INST,        `m4_divert(2)struct f_inst_$1 i_$1;
+m4_divert(1)};
+struct f_inst_$1 {
+m4_divert(-1)'))
+m4_define(ARG, `m4_divert(1)const struct f_inst *f$1;
+m4_divert(-1)')
+m4_define(ARG_ANY, `m4_divert(1)const struct f_inst *f$1;
+m4_divert(-1)')
+m4_define(LINE, `m4_divert(1)const struct f_inst *f$1;
+m4_divert(-1)')
+m4_define(LINEP, `m4_divert(1)const struct f_line *fl$1;
+m4_divert(-1)')
+m4_define(SYMBOL, `m4_divert(1)const struct symbol *sym;
+m4_divert(-1)')
+m4_define(VALI, `m4_divert(1)struct f_val vali;
+m4_divert(-1)')
+m4_define(VALP, `m4_divert(1)const struct f_val *valp;
+m4_divert(-1)')
+m4_define(VAR, `VALP()SYMBOL()')
+m4_define(FRET, `m4_divert(1)enum filter_return fret;
+m4_divert(-1)')
+m4_define(ECS, `m4_divert(1)enum ec_subtype ecs;
+m4_divert(-1)')
+m4_define(RTC, `m4_divert(1)const struct rtable_config *rtc;
+m4_divert(-1)')
+m4_define(STATIC_ATTR, `m4_divert(1)struct f_static_attr sa;
+m4_divert(-1)')
+m4_define(DYNAMIC_ATTR, `m4_divert(1)struct f_dynamic_attr da;
+m4_divert(-1)')
+m4_define(COUNT, `m4_divert(1)uint count;
+m4_divert(-1)')
+m4_define(TREE, `m4_divert(1)const struct f_tree *tree;
+m4_divert(-1)')
+m4_define(STRING, `m4_divert(1)const char *s;
+m4_divert(-1)')
+m4_define(STRUCT, `m4_divert(1)$1
+m4_divert(-1)')
+
+m4_m4wrap(`
+m4_divert(0)DNL
+struct f_inst_FI_NOP {
+m4_undivert(1)
+};
+
+struct f_inst {
+  const struct f_inst *next;           /* Next instruction */
+  enum f_instruction_code fi_code;     /* Instruction code */
+  int lineno;                          /* Line number */
+  union {
+    m4_undivert(2)
+  };
+};
+')
+
+m4_changequote([[,]])
index d9d97136628452da08c013061010fefcc632ac7d..37227d9b7ae903fc897af06dfd9297ae6338cd36 100644 (file)
@@ -123,7 +123,7 @@ enum ec_subtype {
   EC_RT = 0x0002,
   EC_RO = 0x0003,
   EC_GENERIC = 0xFFFF,
-} PACKED;
+};
 
 /* Transitive bit (for first u32 half of EC) */
 #define EC_TBIT 0x40000000
index 56caef24fabe6803b64c6cb55cbd65360b6f21f0..527046eee62b2d25ff2522b079ea948660d8f5fd 100644 (file)
@@ -14,7 +14,7 @@ CF_DEFINES
 
 #define STATIC_CFG ((struct static_config *) this_proto)
 static struct static_route *this_srt, *this_snh;
-static struct f_inst *this_srt_cmds, **this_srt_last_cmd;
+static struct f_inst *this_srt_cmds, *this_srt_last_cmd;
 
 static struct static_route *
 static_nexthop_new(void)
@@ -111,7 +111,7 @@ stat_route0: ROUTE net_any {
      add_tail(&STATIC_CFG->routes, &this_srt->n);
      this_srt->net = $2;
      this_srt_cmds = NULL;
-     this_srt_last_cmd = &this_srt_cmds;
+     this_srt_last_cmd = NULL;
      this_srt->mp_next = NULL;
      this_snh = NULL;
   }
@@ -137,7 +137,13 @@ stat_route:
  ;
 
 stat_route_item:
-   cmd { *this_srt_last_cmd = $1; this_srt_last_cmd = &($1->next); }
+   cmd {
+     if (this_srt_last_cmd)
+       f_inst_next(this_srt_last_cmd, $1);
+     else
+       this_srt_cmds = $1;
+     this_srt_last_cmd = $1;
+   }
  ;
 
 stat_route_opts: