diff --git a/tools/bifcl/bif_arg.cc b/tools/bifcl/bif_arg.cc index c4f27f96de..735b5ff329 100644 --- a/tools/bifcl/bif_arg.cc +++ b/tools/bifcl/bif_arg.cc @@ -9,6 +9,7 @@ using namespace std; static struct { + const char* type_enum; const char* bif_type; const char* zeek_type; const char* c_type; @@ -21,8 +22,8 @@ static struct } builtin_func_arg_type[] = { #define DEFINE_BIF_TYPE(id, bif_type, zeek_type, c_type, c_type_smart, accessor, accessor_smart, \ cast_smart, constructor, ctor_smart) \ - {bif_type, zeek_type, c_type, c_type_smart, accessor, \ - accessor_smart, cast_smart, constructor, ctor_smart}, + {#id, bif_type, zeek_type, c_type, c_type_smart, \ + accessor, accessor_smart, cast_smart, constructor, ctor_smart}, #include "bif_type.def" #undef DEFINE_BIF_TYPE }; @@ -58,8 +59,24 @@ void BuiltinFuncArg::PrintZeek(FILE* fp) fprintf(fp, "%s: %s%s %s", name, builtin_func_arg_type[type].zeek_type, type_str, attr_str); } -void BuiltinFuncArg::PrintCDef(FILE* fp, int n) +void BuiltinFuncArg::PrintCDef(FILE* fp, int n, bool runtime_type_check) { + // Generate a runtime type-check pre-amble for types we understand + if ( runtime_type_check && type != TYPE_OTHER && type != TYPE_ANY ) + { + fprintf(fp, "\t\t{\n"); + fprintf(fp, "\t\t// Runtime type check for %s argument\n", name); + fprintf(fp, "\t\tzeek::TypeTag __tag = (*%s)[%d]->GetType()->Tag();\n", arg_list_name, n); + fprintf(fp, "\t\tif ( __tag != %s )\n", builtin_func_arg_type[type].type_enum); + fprintf(fp, "\t\t\t{\n"); + fprintf(fp, + "\t\t\tzeek::emit_builtin_error(zeek::util::fmt(\"expected type %s for %s, got " + "%%s\", zeek::type_name(__tag)));\n", + builtin_func_arg_type[type].zeek_type, name); + fprintf(fp, "\t\t\treturn nullptr;\n"); + fprintf(fp, "\t\t\t}\n"); + fprintf(fp, "\t\t}\n"); + } fprintf(fp, "\t%s %s = (%s) (", builtin_func_arg_type[type].c_type, name, builtin_func_arg_type[type].c_type); diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 66ef357d05..87144e18b7 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -708,8 +708,8 @@ body_start: TOK_LPB c_code_begin fprintf(fp_func_def, "\tif ( %s->size() != %d )\n", arg_list_name, argc); fprintf(fp_func_def, "\t\t{\n"); fprintf(fp_func_def, - "\t\treporter->Error(\"%s() takes exactly %d argument(s)\");\n", - decl.zeek_fullname.c_str(), argc); + "\t\tzeek::emit_builtin_error(zeek::util::fmt(\"%s() takes exactly %d argument(s), got %%lu\", %s->size()));\n", + decl.zeek_fullname.c_str(), argc, arg_list_name); fprintf(fp_func_def, "\t\treturn nullptr;\n"); fprintf(fp_func_def, "\t\t}\n"); } @@ -718,14 +718,14 @@ body_start: TOK_LPB c_code_begin fprintf(fp_func_def, "\tif ( %s->size() < %d )\n", arg_list_name, argc); fprintf(fp_func_def, "\t\t{\n"); fprintf(fp_func_def, - "\t\treporter->Error(\"%s() takes at least %d argument(s)\");\n", - decl.zeek_fullname.c_str(), argc); + "\t\tzeek::emit_builtin_error(zeek::util::fmt(\"%s() takes at least %d argument(s), got %%lu\", %s->size()));\n", + decl.zeek_fullname.c_str(), argc, arg_list_name); fprintf(fp_func_def, "\t\treturn nullptr;\n"); fprintf(fp_func_def, "\t\t}\n"); } for ( int i = 0; i < (int) args.size(); ++i ) - args[i]->PrintCDef(fp_func_def, i + implicit_arg); + args[i]->PrintCDef(fp_func_def, i + implicit_arg, var_arg); print_line_directive(fp_func_def); } ; diff --git a/tools/bifcl/include/bif_arg.h b/tools/bifcl/include/bif_arg.h index 588f1d60d2..67df7be12d 100644 --- a/tools/bifcl/include/bif_arg.h +++ b/tools/bifcl/include/bif_arg.h @@ -25,7 +25,7 @@ public: int Type() const { return type; } void PrintZeek(FILE* fp); - void PrintCDef(FILE* fp, int n); + void PrintCDef(FILE* fp, int n, bool runtime_type_check = false); void PrintCArg(FILE* fp, int n); void PrintValConstructor(FILE* fp);