]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Filter: Improve typecheck error messages
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Tue, 5 Nov 2019 14:13:57 +0000 (15:13 +0100)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Tue, 5 Nov 2019 14:30:16 +0000 (15:30 +0100)
filter/data.c
filter/data.h
filter/decl.m4
filter/f-inst.h
filter/filter.c

index db55070fa08f3fb3409ebbc7924885a444e2e43b..62edd9e0e24216fe7ebbe5153b21a872739f8f1b 100644 (file)
 #include "filter/f-inst.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 = {
   .type = T_PATH,
   .val.ad = &null_adata,
index db6b6e121e02d79b25e13e40989acaebe7f87881..578ff98f5945d95a964849ac62b573de98dc1d6b 100644 (file)
@@ -167,6 +167,8 @@ void trie_format(const struct f_trie *t, buffer *buf);
 
 #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_compare(const struct f_val *v1, const struct f_val *v2);
 void val_format(const struct f_val *v, buffer *buf);
index 5618dafa9e02c3abc99c93c4aa6570eeeb253358..a78450a353adc764e32eb4b2f70097b8130a48d0 100644 (file)
@@ -104,7 +104,7 @@ FID_STRUCT_IN()m4_dnl
       struct f_inst * f$1;
 FID_NEW_ARGS()m4_dnl
   , struct f_inst * f$1
-FID_NEW_BODY
+FID_NEW_BODY()m4_dnl
 whati->f$1 = f$1;
 for (const struct f_inst *child = f$1; child; child = child->next) {
   what->size += child->size;
@@ -164,10 +164,19 @@ m4_define(ARG, `ARG_ANY($1) ARG_TYPE($1,$2)')
 m4_define(ARG_TYPE, `
 FID_NEW_BODY()m4_dnl
 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
 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()')
 
 #      Executing another filter line. This replaces the recursion
@@ -217,10 +226,16 @@ m4_define(ERROR,
        `m4_errprint(m4___file__:m4___line__: $*
        )m4_m4exit(1)')
 
+#      This macro specifies result type and makes there are no conflicting definitions
 m4_define(RESULT_TYPE,
        `m4_ifdef([[INST_RESULT_TYPE]],
                  [[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
 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 *
-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])))
     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);
   for (uint i=0; i<dest->len; 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) {
 FID_WR_PUT(7)
       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++)
     out->len = linearize(out, inst[i], out->len);
 
-#if DEBUGGING
+#ifdef LOCAL_DEBUG
   f_dump_line(out, 0);
 #endif
   return out;
index 33fcf4a9e811688c9df9c5f30d6a437c982aa8ff..8be8443b33433b433207ca081dab3ddfc40b9998 100644 (file)
@@ -29,7 +29,9 @@ enum f_instruction_flags {
 #define f_new_inst(...) MACRO_CONCAT_AFTER(f_new_inst_, MACRO_FIRST(__VA_ARGS__))(__VA_ARGS__)
 
 /* 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 */
 /* Line of instructions to be unconditionally executed one after another */
index 60e351f9cad65a9249f75ecb36772c803b61ea9a..ad9588b2adfe3ed7d249ca56a5e0366ea78abe99 100644 (file)
@@ -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]
 
-#if DEBUGGING
+#ifdef LOCAL_DEBUG
   debug("Interpreting line.");
   f_dump_line(line, 1);
 #endif