mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-23 02:01:55 +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:
parent
f9eb9b4cab
commit
b3fdba0bf8
@ -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;
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user