diff --git a/conf/confbase.Y b/conf/confbase.Y index cff1b794..9725ef36 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -157,15 +157,14 @@ conf: definition ; definition: DEFINE symbol '=' term ';' { - struct f_val val; - if (f_eval(f_linearize($4, 1), &val) > F_RETURN) cf_error("Runtime error"); - cf_define_symbol($2, SYM_CONSTANT | val.type, val, lp_val_copy(cfg_mem, &val)); + struct f_val *val = cf_eval($4, T_VOID); + cf_define_symbol($2, SYM_CONSTANT | val->type, val, val); } ; expr: NUM - | '(' term ')' { $$ = f_eval_int(f_linearize($2, 1)); } + | '(' term ')' { $$ = cf_eval_int($2); } | symbol_known { if ($1->class != (SYM_CONSTANT | T_INT)) cf_error("Number constant expected"); $$ = SYM_VAL($1).i; } diff --git a/filter/config.Y b/filter/config.Y index 7bf13d9c..238a1c46 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -376,7 +376,7 @@ filter_def: conf: filter_eval ; filter_eval: - EVAL term { f_eval_int(f_linearize($2, 1)); } + EVAL term { cf_eval_int($2); } ; conf: custom_attr ; @@ -598,7 +598,7 @@ set_atom: | VPN_RD { $$.type = T_RD; $$.val.ec = $1; } | ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); } | '(' term ')' { - if (f_eval(f_linearize($2, 1), &($$)) > F_RETURN) cf_error("Runtime error"); + $$ = cf_eval_tmp($2, T_VOID); if (!f_valid_set_type($$.type)) cf_error("Set-incompatible type"); } | symbol_known { @@ -610,13 +610,13 @@ set_atom: switch_atom: NUM { $$.type = T_INT; $$.val.i = $1; } - | '(' term ')' { $$.type = T_INT; $$.val.i = f_eval_int(f_linearize($2, 1)); } + | '(' term ')' { $$ = cf_eval_tmp($2, T_INT); } | fipa { $$ = $1; } | ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); } ; cnum: - term { $$ = f_eval_int(f_linearize($1, 1)); } + term { $$ = cf_eval_int($1); } pair_item: '(' cnum ',' cnum ')' { $$ = f_new_pair_item($2, $2, $4, $4); } diff --git a/filter/filter.c b/filter/filter.c index 931bc85e..7eb109a1 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -277,29 +277,23 @@ f_eval(const struct f_line *expr, struct f_val *pres) } /* - * f_eval_int - get an integer value of a term - * Called internally from the config parser, uses its internal memory pool - * for allocations. Do not call in other cases. + * cf_eval_tmp - evaluate a value of a term and check its type */ -uint -f_eval_int(const struct f_line *expr) +struct f_val +cf_eval_tmp(const struct f_inst *inst, int type) { - /* Called independently in parse-time to eval expressions */ - filter_state = (struct filter_state) {}; - - f_stack_init(filter_state); - struct f_val val; - if (interpret(&filter_state, expr, &val) > F_RETURN) + if (f_eval(f_linearize(inst, 1), &val) > F_RETURN) cf_error("Runtime error while evaluating expression; see log for details"); - if (val.type != T_INT) - cf_error("Integer expression expected"); + if (type != T_VOID && val.type != type) + cf_error("Expression of type %s expected", f_type_name(type)); - return val.val.i; + return val; } + /* * f_eval_buf - get a value of a term and print it to the supplied buffer */ diff --git a/filter/filter.h b/filter/filter.h index 3f2e62eb..1ece636a 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -15,6 +15,8 @@ #include "lib/macro.h" #include "nest/rt.h" #include "lib/attrs.h" +#include "filter/data.h" +#include "conf/conf.h" /* Possible return values of filter execution */ enum filter_return { @@ -40,9 +42,8 @@ static inline const char *filter_return_str(const enum filter_return fret) { } } -struct f_val; - /* The filter encapsulating structure to be pointed-to from outside */ +struct f_inst; struct f_line; struct filter { struct symbol *sym; @@ -53,9 +54,17 @@ struct rte; enum filter_return f_run(const struct filter *filter, struct rte *rte, int flags); enum filter_return f_eval_rte(const struct f_line *expr, struct rte *rte); -uint f_eval_int(const struct f_line *expr); enum filter_return f_eval_buf(const struct f_line *expr, buffer *buf); +struct f_val cf_eval_tmp(const struct f_inst *inst, int type); +static inline struct f_val *cf_eval(const struct f_inst *inst, int type) +{ + struct f_val val = cf_eval_tmp(inst, type); + return lp_val_copy(cfg_mem, &val); +} + +static inline uint cf_eval_int(const struct f_inst *inst) { return cf_eval_tmp(inst, T_INT).val.i; }; + const char *filter_name(const struct filter *filter); int filter_same(const struct filter *new, const struct filter *old); int f_same(const struct f_line *f1, const struct f_line *f2); diff --git a/nest/config.Y b/nest/config.Y index 788ebaed..dcf977fc 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -165,7 +165,7 @@ rtrid: idval: NUM { $$ = $1; } - | '(' term ')' { $$ = f_eval_int(f_linearize($2, 1)); } + | '(' term ')' { $$ = cf_eval_int($2); } | IP4 { $$ = ip4_to_u32($1); } | CF_SYM_KNOWN { if ($1->class == (SYM_CONSTANT | T_INT) || $1->class == (SYM_CONSTANT | T_QUAD))