diff --git a/.gitmodules b/.gitmodules index 738888bf85..789449bca6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -25,3 +25,6 @@ [submodule "aux/netcontrol-connectors"] path = aux/netcontrol-connectors url = git://git.bro.org/bro-netcontrol +[submodule "aux/bifcl"] + path = aux/bifcl + url = git://git.bro.org/bifcl diff --git a/CMakeLists.txt b/CMakeLists.txt index d0ea236330..370bf78c92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -108,6 +108,10 @@ if (NOT BinPAC_ROOT_DIR AND endif () FindRequiredPackage(BinPAC) +if ( NOT BIFCL_EXE_PATH ) + add_subdirectory(aux/bifcl) +endif () + if (ENABLE_JEMALLOC) find_package(JeMalloc) endif () diff --git a/aux/bifcl b/aux/bifcl new file mode 160000 index 0000000000..a25704cc76 --- /dev/null +++ b/aux/bifcl @@ -0,0 +1 @@ +Subproject commit a25704cc769438b6ecaf92331511456826e90409 diff --git a/cmake b/cmake index 1600554d1d..a416553abc 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit 1600554d1d907f4f252f19cf1f55e13d368a936f +Subproject commit a416553abcb7aa650e934cd3800bcab0cbcf3e63 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 00f19b9348..ff0cfc019e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -44,15 +44,6 @@ endmacro(REPLACE_YY_PREFIX_TARGET) set(BISON_FLAGS "--debug") -# BIF parser/scanner -bison_target(BIFParser builtin-func.y - ${CMAKE_CURRENT_BINARY_DIR}/bif_parse.cc - HEADER ${CMAKE_CURRENT_BINARY_DIR}/bif_parse.h - #VERBOSE ${CMAKE_CURRENT_BINARY_DIR}/bif_parse.output - COMPILE_FLAGS "${BISON_FLAGS}") -flex_target(BIFScanner builtin-func.l ${CMAKE_CURRENT_BINARY_DIR}/bif_lex.cc) -add_flex_bison_dependency(BIFScanner BIFParser) - # Rule parser/scanner bison_target(RuleParser rule-parse.y ${CMAKE_CURRENT_BINARY_DIR}/rup.cc @@ -93,24 +84,6 @@ replace_yy_prefix_target(${CMAKE_CURRENT_BINARY_DIR}/p.cc flex_target(Scanner scan.l ${CMAKE_CURRENT_BINARY_DIR}/scan.cc COMPILE_FLAGS "-Pbro") -######################################################################## -## bifcl (BIF compiler) target - -set(bifcl_SRCS - ${BISON_BIFParser_INPUT} - ${FLEX_BIFScanner_INPUT} - ${BISON_BIFParser_OUTPUTS} - ${FLEX_BIFScanner_OUTPUTS} - bif_arg.cc - module_util.cc - bif_arg.h - module_util.h -) - -add_executable(bifcl ${bifcl_SRCS}) - -target_link_libraries(bifcl) - ######################################################################## ## bifcl-dependent targets diff --git a/src/bif_arg.cc b/src/bif_arg.cc deleted file mode 100644 index f5e25f3746..0000000000 --- a/src/bif_arg.cc +++ /dev/null @@ -1,83 +0,0 @@ -#include "bro-config.h" - -#include -#include -using namespace std; - -#include - -#include "bif_arg.h" - -static struct { - const char* bif_type; - const char* bro_type; - const char* c_type; - const char* accessor; - const char* constructor; -} builtin_func_arg_type[] = { -#define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, accessor, constructor) \ - {bif_type, bro_type, c_type, accessor, constructor}, -#include "bif_type.def" -#undef DEFINE_BIF_TYPE -}; - -extern const char* arg_list_name; - -BuiltinFuncArg::BuiltinFuncArg(const char* arg_name, int arg_type) - { - name = arg_name; - type = arg_type; - type_str = ""; - attr_str = ""; - } - -BuiltinFuncArg::BuiltinFuncArg(const char* arg_name, const char* arg_type_str, - const char* arg_attr_str) - { - name = arg_name; - type = TYPE_OTHER; - type_str = arg_type_str; - attr_str = arg_attr_str; - - for ( int i = 0; builtin_func_arg_type[i].bif_type[0] != '\0'; ++i ) - if ( ! strcmp(builtin_func_arg_type[i].bif_type, arg_type_str) ) - { - type = i; - type_str = ""; - } - } - -void BuiltinFuncArg::PrintBro(FILE* fp) - { - fprintf(fp, "%s: %s%s %s", name, builtin_func_arg_type[type].bro_type, - type_str, attr_str); - } - -void BuiltinFuncArg::PrintCDef(FILE* fp, int n) - { - fprintf(fp, - "\t%s %s = (%s) (", - builtin_func_arg_type[type].c_type, - name, - builtin_func_arg_type[type].c_type); - - char buf[1024]; - snprintf(buf, sizeof(buf), "(*%s)[%d]", arg_list_name, n); - // Print the accessor expression. - fprintf(fp, builtin_func_arg_type[type].accessor, buf); - - fprintf(fp, ");\n"); - } - -void BuiltinFuncArg::PrintCArg(FILE* fp, int n) - { - const char* ctype = builtin_func_arg_type[type].c_type; - char buf[1024]; - - fprintf(fp, "%s %s", ctype, name); - } - -void BuiltinFuncArg::PrintBroValConstructor(FILE* fp) - { - fprintf(fp, builtin_func_arg_type[type].constructor, name); - } diff --git a/src/bif_arg.h b/src/bif_arg.h deleted file mode 100644 index 906cfd9c6a..0000000000 --- a/src/bif_arg.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef bif_arg_h -#define bif_arg_h - -#include - -enum builtin_func_arg_type { -#define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, accessor, constructor) \ - id, -#include "bif_type.def" -#undef DEFINE_BIF_TYPE -/* - TYPE_ANY, - TYPE_BOOL, - TYPE_COUNT, - TYPE_INT, - TYPE_STRING, - TYPE_PATTERN, - TYPE_PORT, - TYPE_OTHER, -*/ -}; - -extern const char* builtin_func_arg_type_bro_name[]; - -class BuiltinFuncArg { -public: - BuiltinFuncArg(const char* arg_name, int arg_type); - BuiltinFuncArg(const char* arg_name, const char* arg_type_str, - const char* arg_attr_str = ""); - - void SetAttrStr(const char* arg_attr_str) - { - attr_str = arg_attr_str; - }; - - const char* Name() const { return name; } - int Type() const { return type; } - - void PrintBro(FILE* fp); - void PrintCDef(FILE* fp, int n); - void PrintCArg(FILE* fp, int n); - void PrintBroValConstructor(FILE* fp); - -protected: - const char* name; - int type; - const char* type_str; - const char* attr_str; -}; - -#endif diff --git a/src/bif_type.def b/src/bif_type.def deleted file mode 100644 index c30ffeb49b..0000000000 --- a/src/bif_type.def +++ /dev/null @@ -1,22 +0,0 @@ -// DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, accessor, constructor) - -DEFINE_BIF_TYPE(TYPE_ADDR, "addr", "addr", "AddrVal*", "%s->AsAddrVal()", "%s") -DEFINE_BIF_TYPE(TYPE_ANY, "any", "any", "Val*", "%s", "%s") -DEFINE_BIF_TYPE(TYPE_BOOL, "bool", "bool", "int", "%s->AsBool()", "new Val(%s, TYPE_BOOL)") -DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "Val*", "%s", "%s") -DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "Connection*", "%s->AsRecordVal()->GetOrigin()", "%s->BuildConnVal()") -DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "bro_uint_t", "%s->AsCount()", "new Val(%s, TYPE_COUNT)") -DEFINE_BIF_TYPE(TYPE_DOUBLE, "double", "double", "double", "%s->AsDouble()", "new Val(%s, TYPE_DOUBLE)") -DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "BroFile*", "%s->AsFile()", "new Val(%s)") -DEFINE_BIF_TYPE(TYPE_INT, "int", "int", "bro_int_t", "%s->AsInt()", "new Val(%s, TYPE_INT)") -DEFINE_BIF_TYPE(TYPE_INTERVAL, "interval", "interval", "double", "%s->AsInterval()", "new IntervalVal(%s, Seconds)") -DEFINE_BIF_TYPE(TYPE_PACKET, "packet", "packet", "TCP_TracePacket*", "%s->AsRecordVal()->GetOrigin()", "%s->PacketVal()") -DEFINE_BIF_TYPE(TYPE_PATTERN, "pattern", "pattern", "RE_Matcher*", "%s->AsPattern()", "new PatternVal(%s)") -// DEFINE_BIF_TYPE(TYPE_PORT, "port", "port", "uint32", "%s->AsPortVal()->Port()", "incomplete data") -DEFINE_BIF_TYPE(TYPE_PORT, "port", "port", "PortVal*", "%s->AsPortVal()", "%s") -DEFINE_BIF_TYPE(TYPE_PORTVAL, "portval", "port", "PortVal*", "%s->AsPortVal()", "%s") -DEFINE_BIF_TYPE(TYPE_STRING, "string", "string", "StringVal*", "%s->AsStringVal()", "%s") -// DEFINE_BIF_TYPE(TYPE_STRING, "string", "string", "BroString*", "%s->AsString()", "new StringVal(%s)") -DEFINE_BIF_TYPE(TYPE_SUBNET, "subnet", "subnet", "SubNetVal*", "%s->AsSubNetVal()", "%s") -DEFINE_BIF_TYPE(TYPE_TIME, "time", "time", "double", "%s->AsTime()", "new Val(%s, TYPE_TIME)") -DEFINE_BIF_TYPE(TYPE_OTHER, "", "", "Val*", "%s", "%s") diff --git a/src/builtin-func.l b/src/builtin-func.l deleted file mode 100644 index 2d59408f83..0000000000 --- a/src/builtin-func.l +++ /dev/null @@ -1,422 +0,0 @@ -%{ -#include -#include -#include -#include "bif_arg.h" -#include "bif_parse.h" - -char* copy_string(const char* s) - { - char* c = new char[strlen(s)+1]; - strcpy(c, s); - return c; - } - -int line_number = 1; - -extern int in_c_code; - -int check_c_mode(int t) - { - if ( ! in_c_code ) - return t; - - yylval.str = copy_string(yytext); - return TOK_C_TOKEN; - } -%} - -WS [ \t]+ -OWS [ \t]* - /* Note, bifcl only accepts a single "::" in IDs while the policy - layer acceptes multiple. (But the policy layer doesn't have - a hierachy. */ -IDCOMPONENT [A-Za-z_][A-Za-z_0-9]* -ID {IDCOMPONENT}(::{IDCOMPONENT})? -ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+)) -DEC [[:digit:]]+ -HEX [0-9a-fA-F]+ - - -%option nodefault - -%% - -#.* { - yylval.str = copy_string(yytext); - return TOK_COMMENT; - } - -\n { - ++line_number; - return TOK_LF; - } - -{WS} { - yylval.str = copy_string(yytext); - return TOK_WS; - } - -[=,:;] return check_c_mode(yytext[0]); - -"%{" return TOK_LPB; -"%}" return TOK_RPB; -"%%{" return TOK_LPPB; -"%%}" return TOK_RPPB; - -"%(" return check_c_mode(TOK_LPP); -"%)" return check_c_mode(TOK_RPP); -"..." return check_c_mode(TOK_VAR_ARG); -"function" return check_c_mode(TOK_FUNCTION); -"event" return check_c_mode(TOK_EVENT); -"const" return check_c_mode(TOK_CONST); -"enum" return check_c_mode(TOK_ENUM); -"type" return check_c_mode(TOK_TYPE); -"record" return check_c_mode(TOK_RECORD); -"set" return check_c_mode(TOK_SET); -"table" return check_c_mode(TOK_TABLE); -"vector" return check_c_mode(TOK_VECTOR); -"of" return check_c_mode(TOK_OF); -"opaque" return check_c_mode(TOK_OPAQUE); -"module" return check_c_mode(TOK_MODULE); - -"@ARG@" return TOK_ARG; -"@ARGS@" return TOK_ARGS; -"@ARGC@" return TOK_ARGC; - -"T" yylval.val = 1; return TOK_BOOL; -"F" yylval.val = 0; return TOK_BOOL; - -{DEC} { - yylval.str = copy_string(yytext); - return TOK_INT; - } - -"0x"{HEX} { - yylval.str = copy_string(yytext); - return TOK_INT; - } - - -{ID} { - yylval.str = copy_string(yytext); - return TOK_ID; - } - - /* - Hacky way to pass along arbitrary attribute expressions since the BIF parser - has little understanding of valid Bro expressions. With this pattern, the - attribute expression should stop when it reaches another attribute, another - function argument, or the end of the function declaration. - */ -&{ID}({OWS}={OWS}[^&%;,]+)? { - int t = check_c_mode(TOK_ATTR); - - if ( t == TOK_ATTR ) - { - yylval.str = copy_string(yytext); - return TOK_ATTR; - } - else - return t; - } - -\"([^\\\n\"]|{ESCSEQ})*\" { - yylval.str = copy_string(yytext); - return TOK_CSTR; - } - -\'([^\\\n\']|{ESCSEQ})*\' { - yylval.str = copy_string(yytext); - return TOK_CSTR; - } - -. { - yylval.val = yytext[0]; - return TOK_ATOM; - } -%% - -int yywrap() - { - yy_delete_buffer(YY_CURRENT_BUFFER); - return 1; - } - -extern int yyparse(); -char* input_filename = 0; -char* input_filename_with_path = 0; -char* plugin = 0; -int alternative_mode = 0; - -FILE* fp_bro_init = 0; -FILE* fp_func_def = 0; -FILE* fp_func_h = 0; -FILE* fp_func_init = 0; -FILE* fp_func_register = 0; -FILE* fp_netvar_h = 0; -FILE* fp_netvar_def = 0; -FILE* fp_netvar_init = 0; - -void remove_file(const char *surfix); -void err_exit(void); -FILE* open_output_file(const char* surfix); -void close_if_open(FILE **fpp); -void close_all_output_files(void); - - -FILE* open_output_file(const char* surfix) - { - char fn[1024]; - FILE* fp; - - snprintf(fn, sizeof(fn), "%s.%s", input_filename, surfix); - if ( (fp = fopen(fn, "w")) == NULL ) - { - fprintf(stderr, "Error: cannot open file: %s\n", fn); - err_exit(); - } - - return fp; - } - -void usage() - { - fprintf(stderr, "usage: bifcl [-p | -s] *.bif\n"); - exit(1); - } - -void init_alternative_mode() - { - fp_bro_init = open_output_file("bro"); - fp_func_h = open_output_file("h"); - fp_func_def = open_output_file("cc"); - fp_func_init = open_output_file("init.cc"); - fp_func_register = plugin ? open_output_file("register.cc") : NULL; - - fp_netvar_h = fp_func_h; - fp_netvar_def = fp_func_def; - fp_netvar_init = fp_func_init; - - int n = 1024 + strlen(input_filename); - char auto_gen_comment[n]; - - snprintf(auto_gen_comment, n, - "This file was automatically generated by bifcl from %s (%s mode).", - input_filename_with_path, plugin ? "plugin" : "alternative"); - - fprintf(fp_bro_init, "# %s\n\n", auto_gen_comment); - fprintf(fp_func_def, "// %s\n\n", auto_gen_comment); - fprintf(fp_func_h, "// %s\n\n", auto_gen_comment); - fprintf(fp_func_init, "// %s\n\n", auto_gen_comment); - - if ( fp_func_register ) - fprintf(fp_func_register, "// %s\n\n", auto_gen_comment); - - static char guard[1024]; - if ( getcwd(guard, sizeof(guard)) == NULL ) - { - fprintf(stderr, "Error: cannot get current working directory\n"); - err_exit(); - } - strncat(guard, "/", sizeof(guard) - strlen(guard) - 1); - strncat(guard, input_filename, sizeof(guard) - strlen(guard) - 1); - - for ( char* p = guard; *p; p++ ) - { - if ( ! isalnum(*p) ) - *p = '_'; - } - - fprintf(fp_func_h, "#if defined(BRO_IN_NETVAR) || ! defined(%s)\n", guard); - - fprintf(fp_func_h, "#ifndef BRO_IN_NETVAR\n"); - fprintf(fp_func_h, "#ifndef %s\n", guard); - fprintf(fp_func_h, "#define %s\n", guard); - fprintf(fp_func_h, "#include \"bro-bif.h\"\n"); - fprintf(fp_func_h, "#endif\n"); - fprintf(fp_func_h, "#endif\n"); - fprintf(fp_func_h, "\n"); - - fprintf(fp_func_def, "\n"); - fprintf(fp_func_def, "#include \"%s.h\"\n", input_filename); - fprintf(fp_func_def, "\n"); - - static char name[1024]; - strncpy(name, input_filename, sizeof(name)); - char* dot = strchr(name, '.'); - if ( dot ) - *dot = '\0'; - - if ( plugin ) - { - static char plugin_canon[1024]; - strncpy(plugin_canon, plugin, sizeof(plugin_canon)); - char* colon = strstr(plugin_canon, "::"); - - if ( colon ) { - *colon = '_'; - memmove(colon + 1, colon + 2, plugin_canon + strlen(plugin_canon) - colon); - } - - fprintf(fp_func_init, "\n"); - fprintf(fp_func_init, "#include \n"); - fprintf(fp_func_init, "#include \n"); - fprintf(fp_func_init, "#include \"plugin/Plugin.h\"\n"); - fprintf(fp_func_init, "#include \"%s.h\"\n", input_filename); - fprintf(fp_func_init, "\n"); - fprintf(fp_func_init, "namespace plugin { namespace %s {\n", plugin_canon); - fprintf(fp_func_init, "\n"); - fprintf(fp_func_init, "void __bif_%s_init(plugin::Plugin* plugin)\n", name); - fprintf(fp_func_init, "\t{\n"); - - fprintf(fp_func_register, "#include \"plugin/Manager.h\"\n"); - fprintf(fp_func_register, "\n"); - fprintf(fp_func_register, "namespace plugin { namespace %s {\n", plugin_canon); - fprintf(fp_func_register, "void __bif_%s_init(plugin::Plugin* plugin);\n", name); - fprintf(fp_func_register, "::plugin::__RegisterBif __register_bifs_%s_%s(\"%s\", __bif_%s_init);\n", plugin_canon, name, plugin, name); - fprintf(fp_func_register, "} }\n"); - } - } - -void finish_alternative_mode() - { - fprintf(fp_func_h, "\n"); - fprintf(fp_func_h, "#endif\n"); - - if ( plugin ) - { - fprintf(fp_func_init, "\n"); - fprintf(fp_func_init, "\t}\n"); - fprintf(fp_func_init, "} }\n"); - fprintf(fp_func_init, "\n"); - fprintf(fp_func_init, "\n"); - } - } - -int main(int argc, char* argv[]) - { - int opt; - - while ( (opt = getopt(argc, argv, "p:s")) != -1 ) - { - switch ( opt ) { - case 'p': - alternative_mode = 1; - plugin = optarg; - break; - - case 's': - alternative_mode = 1; - break; - - default: - usage(); - } - } - - for ( int i = optind; i < argc; i++ ) - { - FILE* fp_input; - char* slash; - - input_filename = input_filename_with_path = argv[i]; - slash = strrchr(input_filename, '/'); - - if ( (fp_input = fopen(input_filename, "r")) == NULL ) - { - fprintf(stderr, "Error: cannot open file: %s\n", input_filename); - /* no output files open. can simply exit */ - exit(1); - } - - if ( slash ) - input_filename = slash + 1; - - if ( ! alternative_mode ) - { - fp_bro_init = open_output_file("bro"); - fp_func_h = open_output_file("func_h"); - fp_func_def = open_output_file("func_def"); - fp_func_init = open_output_file("func_init"); - fp_netvar_h = open_output_file("netvar_h"); - fp_netvar_def = open_output_file("netvar_def"); - fp_netvar_init = open_output_file("netvar_init"); - - int n = 1024 + strlen(input_filename); - char auto_gen_comment[n]; - - snprintf(auto_gen_comment, n, - "This file was automatically generated by bifcl from %s.", - input_filename); - - fprintf(fp_bro_init, "# %s\n\n", auto_gen_comment); - fprintf(fp_func_def, "// %s\n\n", auto_gen_comment); - fprintf(fp_func_h, "// %s\n\n", auto_gen_comment); - fprintf(fp_func_init, "// %s\n\n", auto_gen_comment); - fprintf(fp_netvar_def, "// %s\n\n", auto_gen_comment); - fprintf(fp_netvar_h, "// %s\n\n", auto_gen_comment); - fprintf(fp_netvar_init, "// %s\n\n", auto_gen_comment); - } - - else - init_alternative_mode(); - - yy_switch_to_buffer(yy_create_buffer(fp_input, YY_BUF_SIZE)); - yyparse(); - - if ( alternative_mode ) - finish_alternative_mode(); - - fclose(fp_input); - close_all_output_files(); - - } - } - -void close_if_open(FILE **fpp) - { - if (*fpp) - fclose(*fpp); - *fpp = NULL; - } - -void close_all_output_files(void) - { - close_if_open(&fp_bro_init); - close_if_open(&fp_func_h); - close_if_open(&fp_func_def); - close_if_open(&fp_func_init); - close_if_open(&fp_func_register); - - if ( ! alternative_mode ) - { - close_if_open(&fp_netvar_h); - close_if_open(&fp_netvar_def); - close_if_open(&fp_netvar_init); - } - } - -void remove_file(const char *surfix) - { - char fn[1024]; - - snprintf(fn, sizeof(fn), "%s.%s", input_filename, surfix); - unlink(fn); - } - -void err_exit(void) - { - close_all_output_files(); - /* clean up. remove all output files we've generated so far */ - remove_file("bro"); - remove_file("func_h"); - remove_file("func_def"); - remove_file("func_init"); - remove_file("func_register"); - remove_file("netvar_h"); - remove_file("netvar_def"); - remove_file("netvar_init"); - exit(1); - } - diff --git a/src/builtin-func.y b/src/builtin-func.y deleted file mode 100644 index 0f895ced52..0000000000 --- a/src/builtin-func.y +++ /dev/null @@ -1,785 +0,0 @@ -%{ -#include -#include -#include -#include - -using namespace std; - -#include -#include - -#include "module_util.h" - -using namespace std; - -extern int line_number; -extern char* input_filename; -extern char* plugin; - -#define print_line_directive(fp) fprintf(fp, "\n#line %d \"%s\"\n", line_number, input_filename) - -extern FILE* fp_bro_init; -extern FILE* fp_func_def; -extern FILE* fp_func_h; -extern FILE* fp_func_init; -extern FILE* fp_netvar_h; -extern FILE* fp_netvar_def; -extern FILE* fp_netvar_init; - -int in_c_code = 0; -string current_module = GLOBAL_MODULE_NAME; -int definition_type; -string type_name; - - -enum { - C_SEGMENT_DEF, - FUNC_DEF, - EVENT_DEF, - TYPE_DEF, - CONST_DEF, -}; - -// Holds the name of a declared object (function, enum, record type, event, -// etc. and information about namespaces, etc. -struct decl_struct { - string module_name; - string bare_name; // name without module or namespace - string c_namespace_start; // "opening" namespace for use in netvar_* - string c_namespace_end; // closing "}" for all the above namespaces - string c_fullname; // fully qualified name (namespace::....) for use in netvar_init - string bro_fullname; // fully qualified bro name, for netvar (and lookup_ID()) - string bro_name; // the name as we read it from input. What we write into the .bro file - - // special cases for events. Events have an EventHandlerPtr - // and a generate_* function. This name is for the generate_* function - string generate_bare_name; - string generate_c_fullname; - string generate_c_namespace_start; - string generate_c_namespace_end; -} decl; - -void set_definition_type(int type, const char *arg_type_name) - { - definition_type = type; - if ( type == TYPE_DEF && arg_type_name ) - type_name = string(arg_type_name); - else - type_name = ""; - } - -void set_decl_name(const char *name) - { - decl.bare_name = extract_var_name(name); - - // make_full_var_name prepends the correct module, if any - // then we can extract the module name again. - string varname = make_full_var_name(current_module.c_str(), name); - decl.module_name = extract_module_name(varname.c_str()); - - decl.c_namespace_start = ""; - decl.c_namespace_end = ""; - decl.c_fullname = ""; - decl.bro_fullname = ""; - decl.bro_name = ""; - - decl.generate_c_fullname = ""; - decl.generate_bare_name = string("generate_") + decl.bare_name; - decl.generate_c_namespace_start = ""; - decl.generate_c_namespace_end = ""; - - switch ( definition_type ) { - case TYPE_DEF: - decl.c_namespace_start = "namespace BifType { namespace " + type_name + "{ "; - decl.c_namespace_end = " } }"; - decl.c_fullname = "BifType::" + type_name + "::"; - break; - - case CONST_DEF: - decl.c_namespace_start = "namespace BifConst { "; - decl.c_namespace_end = " } "; - decl.c_fullname = "BifConst::"; - break; - - case FUNC_DEF: - decl.c_namespace_start = "namespace BifFunc { "; - decl.c_namespace_end = " } "; - decl.c_fullname = "BifFunc::"; - break; - - case EVENT_DEF: - decl.c_namespace_start = ""; - decl.c_namespace_end = ""; - decl.c_fullname = "::"; // need this for namespace qualified events due do event_c_body - decl.generate_c_namespace_start = "namespace BifEvent { "; - decl.generate_c_namespace_end = " } "; - decl.generate_c_fullname = "BifEvent::"; - break; - - default: - break; - } - - if ( decl.module_name != GLOBAL_MODULE_NAME ) - { - decl.c_namespace_start += "namespace " + decl.module_name + " { "; - decl.c_namespace_end += string(" }"); - decl.c_fullname += decl.module_name + "::"; - decl.bro_fullname += decl.module_name + "::"; - - decl.generate_c_namespace_start += "namespace " + decl.module_name + " { "; - decl.generate_c_namespace_end += " } "; - decl.generate_c_fullname += decl.module_name + "::"; - } - - decl.bro_fullname += decl.bare_name; - if ( definition_type == FUNC_DEF ) - decl.bare_name = string("bro_") + decl.bare_name; - - decl.c_fullname += decl.bare_name; - decl.bro_name += name; - decl.generate_c_fullname += decl.generate_bare_name; - - } - -const char* arg_list_name = "BiF_ARGS"; - -#include "bif_arg.h" - -/* Map bif/bro type names to C types for use in const declaration */ -static struct { - const char* bif_type; - const char* bro_type; - const char* c_type; - const char* accessor; - const char* constructor; -} builtin_types[] = { -#define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, accessor, constructor) \ - {bif_type, bro_type, c_type, accessor, constructor}, -#include "bif_type.def" -#undef DEFINE_BIF_TYPE -}; - -int get_type_index(const char *type_name) - { - for ( int i = 0; builtin_types[i].bif_type[0] != '\0'; ++i ) - { - if ( strcmp(builtin_types[i].bif_type, type_name) == 0 ) - return i; - } - return TYPE_OTHER; - } - - -int var_arg; // whether the number of arguments is variable -std::vector args; - -extern int yyerror(const char[]); -extern int yywarn(const char msg[]); -extern int yylex(); - -char* concat(const char* str1, const char* str2) - { - int len1 = strlen(str1); - int len2 = strlen(str2); - - char* s = new char[len1 + len2 +1]; - - memcpy(s, str1, len1); - memcpy(s + len1, str2, len2); - - s[len1+len2] = '\0'; - - return s; - } - -// Print the bro_event_* function prototype in C++, without the ending ';' -void print_event_c_prototype(FILE *fp, bool is_header) - { - if ( is_header ) - fprintf(fp, "%s void %s(analyzer::Analyzer* analyzer%s", - decl.generate_c_namespace_start.c_str(), decl.generate_bare_name.c_str(), - args.size() ? ", " : "" ); - else - fprintf(fp, "void %s(analyzer::Analyzer* analyzer%s", - decl.generate_c_fullname.c_str(), - args.size() ? ", " : "" ); - for ( int i = 0; i < (int) args.size(); ++i ) - { - if ( i > 0 ) - fprintf(fp, ", "); - args[i]->PrintCArg(fp, i); - } - fprintf(fp, ")"); - if ( is_header ) - fprintf(fp, "; %s\n", decl.generate_c_namespace_end.c_str()); - else - fprintf(fp, "\n"); - } - -// Print the bro_event_* function body in C++. -void print_event_c_body(FILE *fp) - { - fprintf(fp, "\t{\n"); - fprintf(fp, "\t// Note that it is intentional that here we do not\n"); - fprintf(fp, "\t// check if %s is NULL, which should happen *before*\n", - decl.c_fullname.c_str()); - fprintf(fp, "\t// %s is called to avoid unnecessary Val\n", - decl.generate_c_fullname.c_str()); - fprintf(fp, "\t// allocation.\n"); - fprintf(fp, "\n"); - - fprintf(fp, "\tval_list* vl = new val_list;\n\n"); - BuiltinFuncArg *connection_arg = 0; - - for ( int i = 0; i < (int) args.size(); ++i ) - { - fprintf(fp, "\t"); - fprintf(fp, "vl->append("); - args[i]->PrintBroValConstructor(fp); - fprintf(fp, ");\n"); - - if ( args[i]->Type() == TYPE_CONNECTION ) - { - if ( connection_arg == 0 ) - connection_arg = args[i]; - else - { - // We are seeing two connection type arguments. - yywarn("Warning: with more than connection-type " - "event arguments, bifcl only passes " - "the first one to EventMgr as cookie."); - } - } - } - - fprintf(fp, "\n"); - fprintf(fp, "\tmgr.QueueEvent(%s, vl, SOURCE_LOCAL, analyzer->GetID(), timer_mgr", - decl.c_fullname.c_str()); - - if ( connection_arg ) - // Pass the connection to the EventMgr as the "cookie" - fprintf(fp, ", %s", connection_arg->Name()); - - fprintf(fp, ");\n"); - fprintf(fp, "\t} // event generation\n"); - //fprintf(fp, "%s // end namespace\n", decl.generate_c_namespace_end.c_str()); - } - -void record_bif_item(const char* id, const char* type) - { - if ( ! plugin ) - return; - - fprintf(fp_func_init, "\tplugin->AddBifItem(\"%s\", plugin::BifItem::%s);\n", id, type); - } - -%} - -%token TOK_LPP TOK_RPP TOK_LPB TOK_RPB TOK_LPPB TOK_RPPB TOK_VAR_ARG -%token TOK_BOOL -%token TOK_FUNCTION TOK_EVENT TOK_CONST TOK_ENUM TOK_OF -%token TOK_TYPE TOK_RECORD TOK_SET TOK_VECTOR TOK_OPAQUE TOK_TABLE TOK_MODULE -%token TOK_ARGS TOK_ARG TOK_ARGC -%token TOK_ID TOK_ATTR TOK_CSTR TOK_LF TOK_WS TOK_COMMENT -%token TOK_ATOM TOK_INT TOK_C_TOKEN - -%left ',' ':' - -%type TOK_C_TOKEN TOK_ID TOK_CSTR TOK_WS TOK_COMMENT TOK_ATTR TOK_INT opt_ws type attr_list opt_attr_list opt_func_attrs -%type TOK_ATOM TOK_BOOL - -%union { - const char* str; - int val; -} - -%% - -builtin_lang: definitions - { - fprintf(fp_bro_init, "} # end of export section\n"); - fprintf(fp_bro_init, "module %s;\n", GLOBAL_MODULE_NAME); - } - - - -definitions: definitions definition opt_ws - { - if ( in_c_code ) - fprintf(fp_func_def, "%s", $3); - else - fprintf(fp_bro_init, "%s", $3); - } - | opt_ws - { - fprintf(fp_bro_init, "%s", $1); - fprintf(fp_bro_init, "export {\n"); - } - ; - -definition: event_def - | func_def - | c_code_segment - | enum_def - | const_def - | type_def - | module_def - ; - - -module_def: TOK_MODULE opt_ws TOK_ID opt_ws ';' - { - current_module = string($3); - fprintf(fp_bro_init, "module %s;\n", $3); - } - - // XXX: Add the netvar glue so that the event engine knows about - // the type. One still has to define the type in bro.init. - // Would be nice, if we could just define the record type here - // and then copy to the .bif.bro file, but type declarations in - // Bro can be quite powerful. Don't know whether it's worth it - // extend the bif-language to be able to handle that all.... - // Or we just support a simple form of record type definitions - // TODO: add other types (tables, sets) -type_def: TOK_TYPE opt_ws TOK_ID opt_ws ':' opt_ws type_def_types opt_ws ';' - { - set_decl_name($3); - - fprintf(fp_netvar_h, "%s extern %sType * %s; %s\n", - decl.c_namespace_start.c_str(), type_name.c_str(), - decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_def, "%s %sType * %s; %s\n", - decl.c_namespace_start.c_str(), type_name.c_str(), - decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_init, - "\t%s = internal_type(\"%s\")->As%sType();\n", - decl.c_fullname.c_str(), decl.bro_fullname.c_str(), - type_name.c_str()); - - record_bif_item(decl.bro_fullname.c_str(), "TYPE"); - } - ; - -type_def_types: TOK_RECORD - { set_definition_type(TYPE_DEF, "Record"); } - | TOK_SET - { set_definition_type(TYPE_DEF, "Set"); } - | TOK_VECTOR - { set_definition_type(TYPE_DEF, "Vector"); } - | TOK_TABLE - { set_definition_type(TYPE_DEF, "Table"); } - ; - -opt_func_attrs: attr_list opt_ws - { $$ = $1; } - | /* nothing */ - { $$ = ""; } - ; - -event_def: event_prefix opt_ws plain_head opt_func_attrs - { fprintf(fp_bro_init, "%s", $4); } end_of_head ';' - { - print_event_c_prototype(fp_func_h, true); - print_event_c_prototype(fp_func_def, false); - print_event_c_body(fp_func_def); - } - -func_def: func_prefix opt_ws typed_head opt_func_attrs - { fprintf(fp_bro_init, "%s", $4); } end_of_head body - ; - -enum_def: enum_def_1 enum_list TOK_RPB opt_attr_list - { - // First, put an end to the enum type decl. - fprintf(fp_bro_init, "} "); - fprintf(fp_bro_init, "%s", $4); - fprintf(fp_bro_init, ";\n"); - if ( decl.module_name != GLOBAL_MODULE_NAME ) - fprintf(fp_netvar_h, "}; } }\n"); - else - fprintf(fp_netvar_h, "}; }\n"); - - // Now generate the netvar's. - fprintf(fp_netvar_h, "%s extern EnumType * %s; %s\n", - decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_def, "%s EnumType * %s; %s\n", - decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_init, - "\t%s = internal_type(\"%s\")->AsEnumType();\n", - decl.c_fullname.c_str(), decl.bro_fullname.c_str()); - - record_bif_item(decl.bro_fullname.c_str(), "TYPE"); - } - ; - -enum_def_1: TOK_ENUM opt_ws TOK_ID opt_ws TOK_LPB opt_ws - { - set_definition_type(TYPE_DEF, "Enum"); - set_decl_name($3); - fprintf(fp_bro_init, "type %s: enum %s{%s", decl.bro_name.c_str(), $4, $6); - - // this is the namespace were the enumerators are defined, not where - // the type is defined. - // We don't support fully qualified names as enumerators. Use a module name - fprintf(fp_netvar_h, "namespace BifEnum { "); - if ( decl.module_name != GLOBAL_MODULE_NAME ) - fprintf(fp_netvar_h, "namespace %s { ", decl.module_name.c_str()); - fprintf(fp_netvar_h, "enum %s {\n", $3); - } - ; - -enum_list: enum_list TOK_ID opt_ws ',' opt_ws - { - fprintf(fp_bro_init, "%s%s,%s", $2, $3, $5); - fprintf(fp_netvar_h, "\t%s,\n", $2); - } - | enum_list TOK_ID opt_ws '=' opt_ws TOK_INT opt_ws ',' opt_ws - { - fprintf(fp_bro_init, "%s = %s%s,%s", $2, $6, $7, $9); - fprintf(fp_netvar_h, "\t%s = %s,\n", $2, $6); - } - | /* nothing */ - ; - - -const_def: TOK_CONST opt_ws TOK_ID opt_ws ':' opt_ws TOK_ID opt_ws ';' - { - set_definition_type(CONST_DEF, 0); - set_decl_name($3); - int typeidx = get_type_index($7); - char accessor[1024]; - - snprintf(accessor, sizeof(accessor), builtin_types[typeidx].accessor, ""); - - - fprintf(fp_netvar_h, "%s extern %s %s; %s\n", - decl.c_namespace_start.c_str(), - builtin_types[typeidx].c_type, decl.bare_name.c_str(), - decl.c_namespace_end.c_str()); - fprintf(fp_netvar_def, "%s %s %s; %s\n", - decl.c_namespace_start.c_str(), - builtin_types[typeidx].c_type, decl.bare_name.c_str(), - decl.c_namespace_end.c_str()); - fprintf(fp_netvar_init, "\t%s = internal_const_val(\"%s\")%s;\n", - decl.c_fullname.c_str(), decl.bro_fullname.c_str(), - accessor); - - record_bif_item(decl.bro_fullname.c_str(), "CONSTANT"); - } - -attr_list: - attr_list TOK_ATTR - { $$ = concat($1, $2); } - | - TOK_ATTR - ; - -opt_attr_list: - attr_list - | /* nothing */ - { $$ = ""; } - ; - -func_prefix: TOK_FUNCTION - { set_definition_type(FUNC_DEF, 0); } - ; - -event_prefix: TOK_EVENT - { set_definition_type(EVENT_DEF, 0); } - ; - -end_of_head: /* nothing */ - { - fprintf(fp_bro_init, ";\n"); - } - ; - -typed_head: plain_head return_type - { - } - ; - -plain_head: head_1 args arg_end opt_ws - { - if ( var_arg ) - fprintf(fp_bro_init, "va_args: any"); - else - { - for ( int i = 0; i < (int) args.size(); ++i ) - { - if ( i > 0 ) - fprintf(fp_bro_init, ", "); - args[i]->PrintBro(fp_bro_init); - } - } - - fprintf(fp_bro_init, ")"); - - fprintf(fp_bro_init, "%s", $4); - fprintf(fp_func_def, "%s", $4); - } - ; - -head_1: TOK_ID opt_ws arg_begin - { - const char* method_type = 0; - set_decl_name($1); - - if ( definition_type == FUNC_DEF ) - { - method_type = "function"; - print_line_directive(fp_func_def); - } - else if ( definition_type == EVENT_DEF ) - method_type = "event"; - - if ( method_type ) - fprintf(fp_bro_init, - "global %s: %s%s(", - decl.bro_name.c_str(), method_type, $2); - - if ( definition_type == FUNC_DEF ) - { - fprintf(fp_func_init, - "\t(void) new BuiltinFunc(%s, \"%s\", 0);\n", - decl.c_fullname.c_str(), decl.bro_fullname.c_str()); - - fprintf(fp_func_h, - "%sextern Val* %s(Frame* frame, val_list*);%s\n", - decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - - fprintf(fp_func_def, - "Val* %s(Frame* frame, val_list* %s)", - decl.c_fullname.c_str(), arg_list_name); - - record_bif_item(decl.bro_fullname.c_str(), "FUNCTION"); - } - else if ( definition_type == EVENT_DEF ) - { - // TODO: add namespace for events here - fprintf(fp_netvar_h, - "%sextern EventHandlerPtr %s; %s\n", - decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - - fprintf(fp_netvar_def, - "%sEventHandlerPtr %s; %s\n", - decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - - fprintf(fp_netvar_init, - "\t%s = internal_handler(\"%s\");\n", - decl.c_fullname.c_str(), decl.bro_fullname.c_str()); - - record_bif_item(decl.bro_fullname.c_str(), "EVENT"); - - // C++ prototypes of bro_event_* functions will - // be generated later. - } - } - ; - -arg_begin: TOK_LPP - { args.clear(); var_arg = 0; } - ; - -arg_end: TOK_RPP - ; - -args: args_1 - | opt_ws - { /* empty, to avoid yacc complaint about type clash */ } - ; - -args_1: args_1 ',' opt_ws arg opt_ws opt_attr_list - { if ( ! args.empty() ) args[args.size()-1]->SetAttrStr($6); } - | opt_ws arg opt_ws opt_attr_list - { if ( ! args.empty() ) args[args.size()-1]->SetAttrStr($4); } - ; - -// TODO: Migrate all other compound types to this rule. Once the BiF language -// can parse all regular Bro types, we can throw out the unnecessary -// boilerplate typedefs for addr_set, string_set, etc. -type: - TOK_OPAQUE opt_ws TOK_OF opt_ws TOK_ID - { $$ = concat("opaque of ", $5); } - | TOK_ID - { $$ = $1; } - ; - -arg: TOK_ID opt_ws ':' opt_ws type - { args.push_back(new BuiltinFuncArg($1, $5)); } - | TOK_VAR_ARG - { - if ( definition_type == EVENT_DEF ) - yyerror("events cannot have variable arguments"); - var_arg = 1; - } - ; - -return_type: ':' opt_ws type opt_ws - { - BuiltinFuncArg* ret = new BuiltinFuncArg("", $3); - ret->PrintBro(fp_bro_init); - delete ret; - fprintf(fp_func_def, "%s", $4); - } - ; - -body: body_start c_body body_end - { - fprintf(fp_func_def, " // end of %s\n", decl.c_fullname.c_str()); - print_line_directive(fp_func_def); - } - ; - -c_code_begin: /* empty */ - { - in_c_code = 1; - print_line_directive(fp_func_def); - } - ; - -c_code_end: /* empty */ - { in_c_code = 0; } - ; - -body_start: TOK_LPB c_code_begin - { - int implicit_arg = 0; - int argc = args.size(); - - fprintf(fp_func_def, "{"); - - if ( argc > 0 || ! var_arg ) - fprintf(fp_func_def, "\n"); - - if ( ! var_arg ) - { - fprintf(fp_func_def, "\tif ( %s->length() != %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.bro_fullname.c_str(), argc); - fprintf(fp_func_def, "\t\treturn 0;\n"); - fprintf(fp_func_def, "\t\t}\n"); - } - else if ( argc > 0 ) - { - fprintf(fp_func_def, "\tif ( %s->length() < %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.bro_fullname.c_str(), argc); - fprintf(fp_func_def, "\t\treturn 0;\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); - print_line_directive(fp_func_def); - } - ; - -body_end: TOK_RPB c_code_end - { - fprintf(fp_func_def, "}"); - } - ; - -c_code_segment: TOK_LPPB c_code_begin c_body c_code_end TOK_RPPB - ; - -c_body: opt_ws - { fprintf(fp_func_def, "%s", $1); } - | c_body c_atom opt_ws - { fprintf(fp_func_def, "%s", $3); } - ; - -c_atom: TOK_ID - { fprintf(fp_func_def, "%s", $1); } - | TOK_C_TOKEN - { fprintf(fp_func_def, "%s", $1); } - | TOK_ARG - { fprintf(fp_func_def, "(*%s)", arg_list_name); } - | TOK_ARGS - { fprintf(fp_func_def, "%s", arg_list_name); } - | TOK_ARGC - { fprintf(fp_func_def, "%s->length()", arg_list_name); } - | TOK_CSTR - { fprintf(fp_func_def, "%s", $1); } - | TOK_ATOM - { fprintf(fp_func_def, "%c", $1); } - | TOK_INT - { fprintf(fp_func_def, "%s", $1); } - - ; - -opt_ws: opt_ws TOK_WS - { $$ = concat($1, $2); } - | opt_ws TOK_LF - { $$ = concat($1, "\n"); } - | opt_ws TOK_COMMENT - { - if ( in_c_code ) - $$ = concat($1, $2); - else - if ( $2[1] == '#' ) - // This is a special type of comment that is used to - // generate bro script documentation, so pass it through. - $$ = concat($1, $2); - else - $$ = $1; - } - | /* empty */ - { $$ = ""; } - ; - -%% - -extern char* yytext; -extern char* input_filename; -extern int line_number; -void err_exit(void); - -void print_msg(const char msg[]) - { - int msg_len = strlen(msg) + strlen(yytext) + 64; - char* msgbuf = new char[msg_len]; - - if ( yytext[0] == '\n' ) - snprintf(msgbuf, msg_len, "%s, on previous line", msg); - - else if ( yytext[0] == '\0' ) - snprintf(msgbuf, msg_len, "%s, at end of file", msg); - - else - snprintf(msgbuf, msg_len, "%s, at or near \"%s\"", msg, yytext); - - /* - extern int column; - sprintf(msgbuf, "%*s\n%*s\n", column, "^", column, msg); - */ - - if ( input_filename ) - fprintf(stderr, "%s:%d: ", input_filename, line_number); - else - fprintf(stderr, "line %d: ", line_number); - fprintf(stderr, "%s\n", msgbuf); - - delete [] msgbuf; - } - -int yywarn(const char msg[]) - { - print_msg(msg); - return 0; - } - -int yyerror(const char msg[]) - { - print_msg(msg); - - err_exit(); - return 0; - }