Filter: Improve typecheck error messages
This commit is contained in:
parent
c00c20a799
commit
87512e9751
5 changed files with 71 additions and 9 deletions
|
@ -25,6 +25,49 @@
|
||||||
#include "filter/f-inst.h"
|
#include "filter/f-inst.h"
|
||||||
#include "filter/data.h"
|
#include "filter/data.h"
|
||||||
|
|
||||||
|
static const char * const f_type_str[] = {
|
||||||
|
[T_VOID] = "void",
|
||||||
|
|
||||||
|
[T_INT] = "int",
|
||||||
|
[T_BOOL] = "bool",
|
||||||
|
[T_PAIR] = "pair",
|
||||||
|
[T_QUAD] = "quad",
|
||||||
|
|
||||||
|
[T_ENUM_RTS] = "enum rts",
|
||||||
|
[T_ENUM_BGP_ORIGIN] = "enum bgp_origin",
|
||||||
|
[T_ENUM_SCOPE] = "enum scope",
|
||||||
|
[T_ENUM_RTC] = "enum rtc",
|
||||||
|
[T_ENUM_RTD] = "enum rtd",
|
||||||
|
[T_ENUM_ROA] = "enum roa",
|
||||||
|
[T_ENUM_NETTYPE] = "enum nettype",
|
||||||
|
[T_ENUM_RA_PREFERENCE] = "enum ra_preference",
|
||||||
|
[T_ENUM_AF] = "enum af",
|
||||||
|
|
||||||
|
[T_IP] = "ip",
|
||||||
|
[T_NET] = "prefix",
|
||||||
|
[T_STRING] = "string",
|
||||||
|
[T_PATH_MASK] = "bgpmask",
|
||||||
|
[T_PATH] = "bgppath",
|
||||||
|
[T_CLIST] = "clist",
|
||||||
|
[T_EC] = "ec",
|
||||||
|
[T_ECLIST] = "eclist",
|
||||||
|
[T_LC] = "lc",
|
||||||
|
[T_LCLIST] = "lclist",
|
||||||
|
[T_RD] = "rd",
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *
|
||||||
|
f_type_name(enum f_type t)
|
||||||
|
{
|
||||||
|
if (t < ARRAY_SIZE(f_type_str))
|
||||||
|
return f_type_str[t] ?: "?";
|
||||||
|
|
||||||
|
if ((t == T_SET) || (t == T_PREFIX_SET))
|
||||||
|
return "set";
|
||||||
|
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
|
||||||
const struct f_val f_const_empty_path = {
|
const struct f_val f_const_empty_path = {
|
||||||
.type = T_PATH,
|
.type = T_PATH,
|
||||||
.val.ad = &null_adata,
|
.val.ad = &null_adata,
|
||||||
|
|
|
@ -167,6 +167,8 @@ void trie_format(const struct f_trie *t, buffer *buf);
|
||||||
|
|
||||||
#define F_CMP_ERROR 999
|
#define F_CMP_ERROR 999
|
||||||
|
|
||||||
|
const char *f_type_name(enum f_type t);
|
||||||
|
|
||||||
int val_same(const struct f_val *v1, const struct f_val *v2);
|
int val_same(const struct f_val *v1, const struct f_val *v2);
|
||||||
int val_compare(const struct f_val *v1, const struct f_val *v2);
|
int val_compare(const struct f_val *v1, const struct f_val *v2);
|
||||||
void val_format(const struct f_val *v, buffer *buf);
|
void val_format(const struct f_val *v, buffer *buf);
|
||||||
|
|
|
@ -104,7 +104,7 @@ FID_STRUCT_IN()m4_dnl
|
||||||
struct f_inst * f$1;
|
struct f_inst * f$1;
|
||||||
FID_NEW_ARGS()m4_dnl
|
FID_NEW_ARGS()m4_dnl
|
||||||
, struct f_inst * f$1
|
, struct f_inst * f$1
|
||||||
FID_NEW_BODY
|
FID_NEW_BODY()m4_dnl
|
||||||
whati->f$1 = f$1;
|
whati->f$1 = f$1;
|
||||||
for (const struct f_inst *child = f$1; child; child = child->next) {
|
for (const struct f_inst *child = f$1; child; child = child->next) {
|
||||||
what->size += child->size;
|
what->size += child->size;
|
||||||
|
@ -164,10 +164,19 @@ m4_define(ARG, `ARG_ANY($1) ARG_TYPE($1,$2)')
|
||||||
m4_define(ARG_TYPE, `
|
m4_define(ARG_TYPE, `
|
||||||
FID_NEW_BODY()m4_dnl
|
FID_NEW_BODY()m4_dnl
|
||||||
if (f$1->type && (f$1->type != ($2)) && !f_const_promotion(f$1, ($2)))
|
if (f$1->type && (f$1->type != ($2)) && !f_const_promotion(f$1, ($2)))
|
||||||
cf_error("Argument $1 of instruction %s must be of type $2, got 0x%02x", f_instruction_name(what->fi_code), f$1->type);
|
cf_error("Argument $1 of %s must be of type %s, got type %s",
|
||||||
|
f_instruction_name(what->fi_code), f_type_name($2), f_type_name(f$1->type));
|
||||||
FID_INTERPRET_EXEC()m4_dnl
|
FID_INTERPRET_EXEC()m4_dnl
|
||||||
if (v$1.type != ($2))
|
if (v$1.type != ($2))
|
||||||
runtime("Argument $1 of instruction %s must be of type $2, got 0x%02x", f_instruction_name(what->fi_code), v$1.type)m4_dnl
|
runtime("Argument $1 of %s must be of type %s, got type %s",
|
||||||
|
f_instruction_name(what->fi_code), f_type_name($2), f_type_name(v$1.type));
|
||||||
|
FID_INTERPRET_BODY()')
|
||||||
|
|
||||||
|
m4_define(ARG_SAME_TYPE, `
|
||||||
|
FID_NEW_BODY()m4_dnl
|
||||||
|
if (f$1->type && f$2->type && (f$1->type != f$2->type) &&
|
||||||
|
!f_const_promotion(f$2, f$1->type) && !f_const_promotion(f$1, f$2->type))
|
||||||
|
cf_error("Arguments $1 and $2 of %s must be of the same type", f_instruction_name(what->fi_code));
|
||||||
FID_INTERPRET_BODY()')
|
FID_INTERPRET_BODY()')
|
||||||
|
|
||||||
# Executing another filter line. This replaces the recursion
|
# Executing another filter line. This replaces the recursion
|
||||||
|
@ -217,10 +226,16 @@ m4_define(ERROR,
|
||||||
`m4_errprint(m4___file__:m4___line__: $*
|
`m4_errprint(m4___file__:m4___line__: $*
|
||||||
)m4_m4exit(1)')
|
)m4_m4exit(1)')
|
||||||
|
|
||||||
|
# This macro specifies result type and makes there are no conflicting definitions
|
||||||
m4_define(RESULT_TYPE,
|
m4_define(RESULT_TYPE,
|
||||||
`m4_ifdef([[INST_RESULT_TYPE]],
|
`m4_ifdef([[INST_RESULT_TYPE]],
|
||||||
[[m4_ifelse(INST_RESULT_TYPE,$1,,[[ERROR([[Multiple type definitons]])]])]],
|
[[m4_ifelse(INST_RESULT_TYPE,$1,,[[ERROR([[Multiple type definitons]])]])]],
|
||||||
[[m4_define(INST_RESULT_TYPE,$1) FID_NEW_BODY() what->type = $1;FID_INTERPRET_BODY()]])')
|
[[m4_define(INST_RESULT_TYPE,$1) RESULT_TYPE_($1)]])')
|
||||||
|
|
||||||
|
m4_define(RESULT_TYPE_, `
|
||||||
|
FID_NEW_BODY()m4_dnl
|
||||||
|
what->type = $1;
|
||||||
|
FID_INTERPRET_BODY()')
|
||||||
|
|
||||||
# Some common filter instruction members
|
# Some common filter instruction members
|
||||||
m4_define(SYMBOL, `FID_MEMBER(struct symbol *, sym, [[strcmp(f1->sym->name, f2->sym->name) || (f1->sym->class != f2->sym->class)]], "symbol %s", item->sym->name)')
|
m4_define(SYMBOL, `FID_MEMBER(struct symbol *, sym, [[strcmp(f1->sym->name, f2->sym->name) || (f1->sym->class != f2->sym->class)]], "symbol %s", item->sym->name)')
|
||||||
|
@ -420,7 +435,7 @@ FID_WR_PUT(5)
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
f_instruction_name(enum f_instruction_code fi)
|
f_instruction_name_(enum f_instruction_code fi)
|
||||||
{
|
{
|
||||||
if (fi < (sizeof(f_instruction_name_str) / sizeof(f_instruction_name_str[0])))
|
if (fi < (sizeof(f_instruction_name_str) / sizeof(f_instruction_name_str[0])))
|
||||||
return f_instruction_name_str[fi];
|
return f_instruction_name_str[fi];
|
||||||
|
@ -494,7 +509,7 @@ void f_dump_line(const struct f_line *dest, uint indent)
|
||||||
debug("%sFilter line %p (len=%u)\n", INDENT, dest, dest->len);
|
debug("%sFilter line %p (len=%u)\n", INDENT, dest, dest->len);
|
||||||
for (uint i=0; i<dest->len; i++) {
|
for (uint i=0; i<dest->len; i++) {
|
||||||
const struct f_line_item *item = &dest->items[i];
|
const struct f_line_item *item = &dest->items[i];
|
||||||
debug("%sInstruction %s at line %u\n", INDENT, f_instruction_name(item->fi_code), item->lineno);
|
debug("%sInstruction %s at line %u\n", INDENT, f_instruction_name_(item->fi_code), item->lineno);
|
||||||
switch (item->fi_code) {
|
switch (item->fi_code) {
|
||||||
FID_WR_PUT(7)
|
FID_WR_PUT(7)
|
||||||
default: bug("Unknown instruction %x in f_dump_line", item->fi_code);
|
default: bug("Unknown instruction %x in f_dump_line", item->fi_code);
|
||||||
|
@ -529,7 +544,7 @@ f_linearize_concat(const struct f_inst * const inst[], uint count)
|
||||||
for (uint i=0; i<count; i++)
|
for (uint i=0; i<count; i++)
|
||||||
out->len = linearize(out, inst[i], out->len);
|
out->len = linearize(out, inst[i], out->len);
|
||||||
|
|
||||||
#if DEBUGGING
|
#ifdef LOCAL_DEBUG
|
||||||
f_dump_line(out, 0);
|
f_dump_line(out, 0);
|
||||||
#endif
|
#endif
|
||||||
return out;
|
return out;
|
||||||
|
|
|
@ -29,7 +29,9 @@ enum f_instruction_flags {
|
||||||
#define f_new_inst(...) MACRO_CONCAT_AFTER(f_new_inst_, MACRO_FIRST(__VA_ARGS__))(__VA_ARGS__)
|
#define f_new_inst(...) MACRO_CONCAT_AFTER(f_new_inst_, MACRO_FIRST(__VA_ARGS__))(__VA_ARGS__)
|
||||||
|
|
||||||
/* Convert the instruction back to the enum name */
|
/* Convert the instruction back to the enum name */
|
||||||
const char *f_instruction_name(enum f_instruction_code fi);
|
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; }
|
||||||
|
|
||||||
/* Filter structures for execution */
|
/* Filter structures for execution */
|
||||||
/* Line of instructions to be unconditionally executed one after another */
|
/* Line of instructions to be unconditionally executed one after another */
|
||||||
|
|
|
@ -174,7 +174,7 @@ interpret(struct filter_state *fs, const struct f_line *line, struct f_val *val)
|
||||||
|
|
||||||
#define curline fstk->estk[fstk->ecnt-1]
|
#define curline fstk->estk[fstk->ecnt-1]
|
||||||
|
|
||||||
#if DEBUGGING
|
#ifdef LOCAL_DEBUG
|
||||||
debug("Interpreting line.");
|
debug("Interpreting line.");
|
||||||
f_dump_line(line, 1);
|
f_dump_line(line, 1);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue