]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Filter: Update filter functions to use VARARG
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Sun, 20 Oct 2019 18:27:06 +0000 (20:27 +0200)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Sun, 20 Oct 2019 19:01:16 +0000 (21:01 +0200)
Make function call one instruction with variable arguments, instead
of independently setting up arguments and then calling the function.

This fixes code that assumes every term to be one instruction (plus
recursive arguments).

filter/config.Y
filter/decl.m4
filter/f-inst.c

index 340053ba7b11108a22700c2c37a5d78f25696fba..ff1d3cb3a1495500c1a48cbfd257e8309d758305 100644 (file)
@@ -447,7 +447,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
 %nonassoc ELSE
 
 %type <xp> cmds_int cmd_prep
-%type <x> term block cmd cmds constant constructor print_list var_list function_call symbol_value bgp_path_expr bgp_path bgp_path_tail
+%type <x> term block cmd cmds constant constructor print_list args function_call symbol_value bgp_path_expr bgp_path bgp_path_tail
 %type <fda> dynamic_attr
 %type <fsa> static_attr
 %type <f> filter where_filter
@@ -844,33 +844,17 @@ constructor:
  ;
 
 
-/* This generates the function_call variable list backwards. */
-var_list: /* EMPTY */ { $$ = NULL; }
+args:
+   /* EMPTY */ { $$ = NULL; }
  | term { $$ = $1; }
- | var_list ',' term { $$ = $3; $$->next = $1; }
+ | term ',' args { $$ = $1; $$->next = $3; }
 
 function_call:
-   CF_SYM_KNOWN '(' var_list ')' {
+   CF_SYM_KNOWN '(' args ')' {
      if ($1->class != SYM_FUNCTION)
        cf_error("You can't call something which is not a function. Really.");
 
-     struct f_inst *fc = f_new_inst(FI_CALL, $1);
-     uint args = 0;
-     while ($3) {
-       args++;
-       struct f_inst *tmp = $3->next;
-       $3->next = fc;
-
-       fc = $3;
-       $3 = tmp;
-     }
-
-     if (args != $1->function->args)
-       cf_error("Function call '%s' got %u arguments, need %u arguments.",
-          $1->name, args, $1->function->args);
-
-     $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_VOID });
-     $$->next = fc;
+     $$ = f_new_inst(FI_CALL, $3, $1);
    }
  ;
 
index 4d5b70dcfa29d80663eed425b19d26c75011c287..a2ddcf3d0e943e3577a3f7c2a48ada1ea388c7ae 100644 (file)
@@ -274,7 +274,8 @@ m4_undivert(102)m4_dnl
 [[m4_dnl                                The one case in The Big Switch inside interpreter
   case INST_NAME():
   #define whati (&(what->i_]]INST_NAME()[[))
-  m4_ifelse(m4_eval(INST_INVAL() > 0), 1, [[if (fstk->vcnt < INST_INVAL()) runtime("Stack underflow"); fstk->vcnt -= INST_INVAL(); ]])
+  m4_ifelse(m4_eval(INST_INVAL() > 0), 1, [[ if (fstk->vcnt < INST_INVAL()) runtime("Stack underflow");
+                                            fstk->vcnt -= INST_INVAL(); ]])
   m4_undivert(108)m4_dnl
   #undef whati
   break;
index 385d18d054a5cf3de58177744f1b980432b36db6..ad3ef3f6a047740f03d37f4e99ee78098eb780dc 100644 (file)
 
   INST(FI_CALL, 0, 1) {
     NEVER_CONSTANT;
+    VARARG;
     SYMBOL;
 
+    FID_NEW_BODY()
+      if (whati->varcount != sym->function->args)
+       cf_error("Function call '%s' got %u arguments, needs %u arguments",
+                sym->name, whati->varcount, sym->function->args);
+
+      /* Add void slot for return value (requires [[NEVER_CONSTANT]]) */
+      struct f_inst *rv = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_VOID });
+      rv->next = whati->fvar;
+      whati->fvar = rv;
+      what->size += rv->size;
+
     FID_SAME_BODY()
       if (!(f2->sym->flags & SYM_FLAG_SAME))
        return 0;
+
     FID_INTERPRET_BODY()
 
     /* Push the body on stack */
     LINEX(sym->function);
     curline.emask |= FE_RETURN;
 
-    /* Before this instruction was called, there was the T_VOID
-     * automatic return value pushed on value stack and also
-     * sym->function->args function arguments. Setting the
-     * vbase to point to first argument. */
-    ASSERT(curline.ventry >= sym->function->args);
-    curline.ventry -= sym->function->args;
+    /* Set new base for local variables */
     curline.vbase = curline.ventry;
 
+    /* Arguments were substracted by [[VARARG]], now add them back */
+    fstk->vcnt += whati->varcount;
+
     /* Storage for local variables */
     memset(&(fstk->vstk[fstk->vcnt]), 0, sizeof(struct f_val) * sym->function->vars);
     fstk->vcnt += sym->function->vars;