%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
;
-/* 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);
}
;
[[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;
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;