CF_HDR
+#include "lib/buffer.h"
#include "filter/f-inst.h"
#include "filter/data.h"
#define f_generate_complex(fi_code, da, arg) \
f_new_inst(FI_EA_SET, f_new_inst(fi_code, f_new_inst(FI_EA_GET, da), arg), da)
+BUFFER_(struct f_arg) this_args;
+
/*
* Sets and their items are during parsing handled as lists, linked
* through left ptr. The first item in a list also contains a pointer
%type <flv> lvalue
%type <i> type function_args function_vars
%type <ecs> ec_kind
-%type <fret> break_command
+%type <fret> break_command
%type <i32> cnum
%type <e> pair_item ec_item lc_item set_item switch_item set_items switch_items switch_body
%type <trie> fprefix_set
}
;
+function_arg:
+ type symbol {
+ cf_define_symbol($2, SYM_VARIABLE | $1, offset, $2->scope->slots++);
+ BUFFER_PUSH(this_args) = (struct f_arg){ .type = $1 };
+ }
+ ;
+
function_argsn:
- /* EMPTY */
- | function_argsn type symbol ';' {
- if ($3->scope->slots >= 0xfe) cf_error("Too many declarations, at most 255 allowed");
- cf_define_symbol($3, SYM_VARIABLE | $2, offset, $3->scope->slots++);
+ /* EMPTY */ {
+ /* Initialize the buffer */
+ if (!this_args.data)
+ BUFFER_INIT(this_args, &root_pool, 4);
+ else
+ BUFFER_FLUSH(this_args);
}
+ | function_argsn function_arg ';'
;
function_args:
'(' ')' { $$ = 0; }
- | '(' function_argsn type symbol ')' {
- cf_define_symbol($4, SYM_VARIABLE | $3, offset, $4->scope->slots++);
- $$ = $4->scope->slots;
- }
+ | '(' function_argsn function_arg ')' { $$ = this_args.used; }
;
function_vars:
struct function *fn = cfg_alloc(sizeof(struct function));
*fn = (struct function) { .sym = $2, .body = $5 };
$2->function = fn;
- $5->args = $4;
+ if ($4) {
+ struct f_arg *args = cfg_alloc(BUFFER_SIZE(this_args));
+ memcpy(args, this_args.data, BUFFER_SIZE(this_args));
+ fn->args = args;
+ fn->arg_count = this_args.used;
+ }
+ $5->args = fn->arg_count;
cf_pop_scope();
}
;
SYMBOL;
FID_NEW_BODY()
- if (whati->varcount != sym->function->body->args)
+ const struct function *fn = sym->function;
+
+ if (whati->varcount != fn->arg_count)
cf_error("Function call '%s' got %u arguments, needs %u arguments",
- sym->name, whati->varcount, sym->function->body->args);
+ sym->name, whati->varcount, fn->arg_count);
/* Add void slot for return value (requires [[NEVER_CONSTANT]]) */
struct f_inst *rv = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_VOID });
return 0;
FID_INTERPRET_BODY()
+ const struct function *fn = sym->function;
+
+ /* Check types of arguments */
+ for (uint i = 0; i < fn->arg_count; i++)
+ if ((vv(i).type != fn->args[i].type) && (vv(i).type != T_VOID))
+ {
+ /* IP->Quad implicit conversion */
+ if ((fn->args[i].type == T_QUAD) && val_is_ip4(&vv(i)))
+ vv(i) = (struct f_val) {
+ .type = T_QUAD,
+ .val.i = ipa_to_u32(vv(i).val.ip),
+ };
+ else
+ runtime("Function call '%s' argument %u must be of type 0x%02x, got 0x%02x",
+ sym->name, i, fn->args[i].type, vv(i).type);
+ }
/* Push the body on stack */
LINEX(sym->function->body);