0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-09-19 20:05:21 +00:00

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).
This commit is contained in:
Ondrej Zajicek (work) 2019-10-20 20:27:06 +02:00
parent f9eb9b4cab
commit b3fdba0bf8
3 changed files with 25 additions and 29 deletions

View 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);
}
;

View 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;

View File

@ -895,25 +895,36 @@
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;