diff options
-rw-r--r-- | filter/decl.m4 | 19 | ||||
-rw-r--r-- | filter/f-inst.h | 10 | ||||
-rw-r--r-- | filter/f-util.c | 6 |
3 files changed, 25 insertions, 10 deletions
diff --git a/filter/decl.m4 b/filter/decl.m4 index a31b69a9..93ff440e 100644 --- a/filter/decl.m4 +++ b/filter/decl.m4 @@ -379,7 +379,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; @@ -572,8 +573,8 @@ fi_constant(struct f_inst *what, struct f_val val) return what; } -static int -f_const_promotion(struct f_inst *arg, enum f_type want) +int +f_const_promotion_(struct f_inst *arg, enum f_type want, int update) { if (arg->fi_code != FI_CONSTANT) return 0; @@ -581,15 +582,17 @@ f_const_promotion(struct f_inst *arg, enum f_type want) struct f_val *c = &arg->i_FI_CONSTANT.val; if ((c->type == T_IP) && ipa_is_ip4(c->val.ip) && (want == T_QUAD)) { - *c = (struct f_val) { - .type = T_QUAD, - .val.i = ipa_to_u32(c->val.ip), - }; + if (update) + *c = (struct f_val) { + .type = T_QUAD, + .val.i = ipa_to_u32(c->val.ip), + }; return 1; } else if ((c->type == T_SET) && (!c->val.t) && (want == T_PREFIX_SET)) { - *c = f_const_empty_prefix_set; + if (update) + *c = f_const_empty_prefix_set; return 1; } else if ((c->type == T_EMPTY_LIST) && (want == T_CLIST)) { *c = (struct f_val) { diff --git a/filter/f-inst.h b/filter/f-inst.h index f5dfcd20..e8147e26 100644 --- a/filter/f-inst.h +++ b/filter/f-inst.h @@ -36,6 +36,16 @@ const char *f_instruction_name_(enum f_instruction_code fi); static inline const char *f_instruction_name(enum f_instruction_code fi) { return f_instruction_name_(fi) + 3; } + +int f_const_promotion_(struct f_inst *arg, enum f_type want, int update); + +static inline int f_const_promotion(struct f_inst *arg, enum f_type want) +{ return f_const_promotion_(arg, want, 1); } + +static inline int f_try_const_promotion(struct f_inst *arg, enum f_type want) +{ return f_const_promotion_(arg, want, 0); } + + struct f_arg { struct symbol *arg; struct f_arg *next; diff --git a/filter/f-util.c b/filter/f-util.c index e980cef5..768ee83b 100644 --- a/filter/f-util.c +++ b/filter/f-util.c @@ -48,7 +48,8 @@ f_match_signature(const struct f_method *dsc, struct f_inst *args) int i, arg_num = (int) dsc->arg_num; for (i = 1; args && (i < arg_num); args = args->next, i++) - if (dsc->args_type[i] && (args->type != dsc->args_type[i])) + if (dsc->args_type[i] && (args->type != dsc->args_type[i]) && + !f_try_const_promotion(args, dsc->args_type[i])) return 0; return !args && !(i < arg_num); @@ -61,7 +62,8 @@ f_match_signature_err(const struct f_method *dsc, struct f_inst *args, int *pos, int i, arg_num = (int) dsc->arg_num; for (i = 1; args && (i < arg_num); args = args->next, i++) - if (dsc->args_type[i] && (args->type != dsc->args_type[i])) + if (dsc->args_type[i] && (args->type != dsc->args_type[i]) && + !f_try_const_promotion(args, dsc->args_type[i])) break; *pos = i; |