]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Filter: Converted FI_PRINT and FI_PATHMASK_CONSTRUCT to VARARG
authorMaria Matejka <mq@ucw.cz>
Mon, 15 Jul 2019 13:12:18 +0000 (15:12 +0200)
committerMaria Matejka <mq@ucw.cz>
Mon, 15 Jul 2019 13:12:18 +0000 (15:12 +0200)
filter/config.Y
filter/decl.m4
filter/f-inst.c
filter/filter.c

index f3e83cfdf29b6d4c9f4cc6c19a062618926d8a46..9a240763ab5633ebe25ee916b82f5276094c30ff 100644 (file)
@@ -828,7 +828,7 @@ constructor:
    '(' 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); }
+ | bgp_path { $$ = f_new_inst(FI_PATHMASK_CONSTRUCT, $1); }
  ;
 
 
index b1cdaf0df423fb1f53d6fa24aa031c867725382e..d8bbf2bc784164d0f44ebdd6eb45a484da77d90e 100644 (file)
@@ -93,25 +93,6 @@ FID_INTERPRET_EXEC()m4_dnl
 const $1 $2 = whati->$2
 FID_INTERPRET_BODY')
 
-m4_define(FID_MEMBER_IN, `m4_dnl
-FID_LINE_IN()m4_dnl
-      $1 $2;
-FID_STRUCT_IN()m4_dnl
-      $1 $2;
-FID_LINEARIZE_BODY()m4_dnl
-item->$2 = whati->$2;
-m4_ifelse($3,,,[[
-FID_SAME_BODY()m4_dnl
-if ($3) return 0;
-]])
-m4_ifelse($4,,,[[
-FID_DUMP_BODY()m4_dnl
-debug("%s$4\n", INDENT, $5);
-]])
-FID_INTERPRET_EXEC()m4_dnl
-const $1 $2 = whati->$2
-FID_INTERPRET_BODY')
-
 #      Instruction arguments are needed only until linearization is done.
 #      This puts the arguments into the filter line to be executed before
 #      the instruction itself.
@@ -136,6 +117,48 @@ FID_LINEARIZE_BODY
 pos = linearize(dest, whati->f$1, pos);
 FID_INTERPRET_BODY()')
 
+#      Some instructions accept variable number of arguments.
+m4_define(VARARG, `
+FID_NEW_ARGS()m4_dnl
+  , struct f_inst * fvar
+FID_STRUCT_IN()m4_dnl
+      struct f_inst * fvar;
+      uint varcount;
+FID_LINE_IN()m4_dnl
+      uint varcount;
+FID_NEW_BODY()m4_dnl
+whati->varcount = 0;
+whati->fvar = fvar;
+for (const struct f_inst *child = fvar; child; child = child->next, whati->varcount++) {
+  what->size += child->size;
+FID_IFCONST([[
+  if (child->fi_code != FI_CONSTANT)
+    constargs = 0;
+]])
+}
+FID_IFCONST([[
+  const struct f_inst **items = NULL;
+  if (constargs) {
+    items = alloca(whati->varcount * sizeof(struct f_inst *));
+    const struct f_inst *child = fvar;
+    for (uint i=0; child; i++)
+      child = (items[i] = child)->next;
+  }
+]])
+FID_LINEARIZE_BODY()m4_dnl
+  pos = linearize(dest, whati->fvar, pos);
+  item->varcount = whati->varcount;
+FID_DUMP_BODY()m4_dnl
+  debug("%snumber of varargs %u\n", INDENT, item->varcount);
+FID_SAME_BODY()m4_dnl
+  if (f1->varcount != f2->varcount) return 0;
+FID_INTERPRET_BODY()
+FID_HIC(,[[
+  if (fstk->vcnt < whati->varcount) runtime("Stack underflow");
+  fstk->vcnt -= whati->varcount;
+]],)
+')
+
 #      Some arguments need to check their type. After that, ARG_ANY is called.
 m4_define(ARG, `ARG_ANY($1)
 FID_INTERPRET_EXEC()m4_dnl
@@ -410,6 +433,7 @@ fi_constant(struct f_inst *what, struct f_val val)
 #define v1 whati->f1->i_FI_CONSTANT.val
 #define v2 whati->f2->i_FI_CONSTANT.val
 #define v3 whati->f3->i_FI_CONSTANT.val
+#define vv(i) items[i]->i_FI_CONSTANT.val
 #define runtime(fmt, ...) cf_error("filter preevaluation, line %d: " fmt, ifs->lino, ##__VA_ARGS__)
 #define fpool cfg_mem
 #define falloc(size) cfg_alloc(size)
@@ -418,6 +442,7 @@ FID_WR_PUT(3)
 #undef v1
 #undef v2
 #undef v3
+#undef vv
 
 /* Line dumpers */
 #define INDENT (((const char *) f_dump_line_indent_str) + sizeof(f_dump_line_indent_str) - (indent) - 1)
index 7d41efe60c5b9bcd2e6063270a39b0e5d5de1184..f13048332479a92d836e056415f5863071de975f 100644 (file)
@@ -60,8 +60,9 @@
  *
  *     What is the syntax here?
  *     m4_dnl  INST(FI_NOP, in, out) {                 enum value, input args, output args
- *     m4_dnl    ARG(num, type);                       argument, its id (in data fields) and type
- *     m4_dnl    ARG_ANY(num);                         argument with no type check
+ *     m4_dnl    ARG(num, type);                       argument, its id (in data fields) and type accessible by v1, v2, v3
+ *     m4_dnl    ARG_ANY(num);                         argument with no type check accessible by v1, v2, v3
+ *     m4_dnl    VARARG;                               variable-length argument list; accessible by vv(i) and whati->varcount
  *     m4_dnl    LINE(num, unused);                    this argument has to be converted to its own f_line
  *     m4_dnl    SYMBOL;                               symbol handed from config
  *     m4_dnl    STATIC_ATTR;                          static attribute definition
   }
 
   INST(FI_PATHMASK_CONSTRUCT, 0, 1) {
-    ARG_ANY(1);
-    FID_MEMBER(uint, count, f1->count != f2->count, number of items %u, item->count);
-
-    FID_NEW_BODY
-      uint len = 0;
-      for (const struct f_inst *tt = f1; tt; tt = tt->next, len++);
-
-      whati->count = len;
-      struct f_inst **items;
-      if (constargs) {
-       items = alloca(len * sizeof(struct f_inst *));
-       for (uint i=0; f1; i++) {
-         items[i] = f1;
-         f1 = f1->next;
-         items[i]->next = 0;
-       }
-       whati->f1 = NULL;
-      }
-    FID_INTERPRET_BODY
-
-    FID_INTERPRET_EXEC
-    if (fstk->vcnt < whati->count) /* TODO: make this check systematic */
-      runtime("Construction of BGP path mask from %u elements must have at least that number of elements", whati->count);
-
-#define pv(i) fstk->vstk[fstk->vcnt - whati->count + (i)]
+    VARARG;
 
-    FID_INTERPRET_NEW
-#define pv(i) items[i]->i_FI_CONSTANT.val
+    struct f_path_mask *pm = falloc(sizeof(struct f_path_mask) + whati->varcount * sizeof(struct f_path_mask_item));
+    pm->len = whati->varcount;
 
-    FID_INTERPRET_BODY
-    struct f_path_mask *pm = falloc(sizeof(struct f_path_mask) + whati->count * sizeof(struct f_path_mask_item));
-    for (uint i=0; i<whati->count; i++) {
-      switch (pv(i).type) {
+    for (uint i=0; i<whati->varcount; i++) {
+      switch (vv(i).type) {
        case T_PATH_MASK_ITEM:
-         pm->item[i] = pv(i).val.pmi;
+         pm->item[i] = vv(i).val.pmi;
          break;
        case T_INT:
          pm->item[i] = (struct f_path_mask_item) {
-           .asn = pv(i).val.i,
+           .asn = vv(i).val.i,
            .kind = PM_ASN,
          };
          break;
          runtime( "Error resolving path mask template: value not an integer" );
       }
     }
-#undef pv
 
-    FID_INTERPRET_EXEC
-      fstk->vcnt -= whati->count;
-    FID_INTERPRET_BODY
-
-    pm->len = whati->count;
     RESULT(T_PATH_MASK, path_mask, pm);
   }
 
 
   INST(FI_PRINT, 0, 0) {
     NEVER_CONSTANT;
-    ARG_ANY(1);
-    FID_MEMBER_IN(uint, count, f1->count != f2->count, number of items %u, item->count);
-
-    FID_NEW_BODY
-      uint len = 0;
-      for (const struct f_inst *tt = f1; tt; tt = tt->next, len++)
-       ;
-      whati->count = len;
-
-    FID_INTERPRET_BODY
-
-#define pv(i) fstk->vstk[fstk->vcnt - whati->count + (i)]
-    if (whati->count && !(fs->flags & FF_SILENT))
-      for (uint i=0; i<whati->count; i++)
-       val_format(&(pv(i)), &fs->buf);
-#undef pv
+    VARARG;
 
-    fstk->vcnt -= whati->count;
+    if (whati->varcount && !(fs->flags & FF_SILENT))
+      for (uint i=0; i<whati->varcount; i++)
+       val_format(&(vv(i)), &fs->buf);
   }
 
   INST(FI_DIE, 0, 0) {
index 0d727449ac7f44e3d2467e11ef7030ad6e195386..2aa2f629e9144edc3f7906ff056aedd5f2d0ae54 100644 (file)
@@ -190,9 +190,10 @@ interpret(struct filter_state *fs, const struct f_line *line, struct f_val *val)
 
       switch (what->fi_code) {
 #define res fstk->vstk[fstk->vcnt]
-#define v1 fstk->vstk[fstk->vcnt]
-#define v2 fstk->vstk[fstk->vcnt + 1]
-#define v3 fstk->vstk[fstk->vcnt + 2]
+#define vv(i) fstk->vstk[fstk->vcnt + (i)]
+#define v1 vv(0)
+#define v2 vv(1)
+#define v3 vv(2)
 
 #define runtime(fmt, ...) do { \
   if (!(fs->flags & FF_SILENT)) \