Commit b3fdba0b authored by Ondrej Zajicek (work)'s avatar Ondrej Zajicek (work)
Browse files

Filter: Update filter functions to use VARARG

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).
parent f9eb9b4c
Loading
Loading
Loading
Loading
+6 −22
Original line number Original line Diff line number Diff line
@@ -447,7 +447,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
%nonassoc ELSE
%nonassoc ELSE


%type <xp> cmds_int cmd_prep
%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 <fda> dynamic_attr
%type <fsa> static_attr
%type <fsa> static_attr
%type <f> filter where_filter
%type <f> filter where_filter
@@ -844,33 +844,17 @@ constructor:
 ;
 ;




/* This generates the function_call variable list backwards. */
args:
var_list: /* EMPTY */ { $$ = NULL; }
   /* EMPTY */ { $$ = NULL; }
 | term { $$ = $1; }
 | term { $$ = $1; }
 | var_list ',' term { $$ = $3; $$->next = $1; }
 | term ',' args { $$ = $1; $$->next = $3; }


function_call:
function_call:
   CF_SYM_KNOWN '(' var_list ')' {
   CF_SYM_KNOWN '(' args ')' {
     if ($1->class != SYM_FUNCTION)
     if ($1->class != SYM_FUNCTION)
       cf_error("You can't call something which is not a function. Really.");
       cf_error("You can't call something which is not a function. Really.");


     struct f_inst *fc = f_new_inst(FI_CALL, $1);
     $$ = f_new_inst(FI_CALL, $3, $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;
   }
   }
 ;
 ;


+2 −1
Original line number Original line Diff line number Diff line
@@ -274,7 +274,8 @@ m4_undivert(102)m4_dnl
[[m4_dnl				 The one case in The Big Switch inside interpreter
[[m4_dnl				 The one case in The Big Switch inside interpreter
  case INST_NAME():
  case INST_NAME():
  #define whati (&(what->i_]]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
  m4_undivert(108)m4_dnl
  #undef whati
  #undef whati
  break;
  break;
+17 −6
Original line number Original line Diff line number Diff line
@@ -895,25 +895,36 @@


  INST(FI_CALL, 0, 1) {
  INST(FI_CALL, 0, 1) {
    NEVER_CONSTANT;
    NEVER_CONSTANT;
    VARARG;
    SYMBOL;
    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()
    FID_SAME_BODY()
      if (!(f2->sym->flags & SYM_FLAG_SAME))
      if (!(f2->sym->flags & SYM_FLAG_SAME))
	return 0;
	return 0;

    FID_INTERPRET_BODY()
    FID_INTERPRET_BODY()


    /* Push the body on stack */
    /* Push the body on stack */
    LINEX(sym->function);
    LINEX(sym->function);
    curline.emask |= FE_RETURN;
    curline.emask |= FE_RETURN;


    /* Before this instruction was called, there was the T_VOID
    /* Set new base for local variables */
     * 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;
    curline.vbase = curline.ventry;
    curline.vbase = curline.ventry;


    /* Arguments were substracted by [[VARARG]], now add them back */
    fstk->vcnt += whati->varcount;

    /* Storage for local variables */
    /* Storage for local variables */
    memset(&(fstk->vstk[fstk->vcnt]), 0, sizeof(struct f_val) * sym->function->vars);
    memset(&(fstk->vstk[fstk->vcnt]), 0, sizeof(struct f_val) * sym->function->vars);
    fstk->vcnt += sym->function->vars;
    fstk->vcnt += sym->function->vars;