mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Move bifcl to a separate repo
This commit is contained in:
parent
15d74ac081
commit
e1b7820b01
10 changed files with 9 additions and 1391 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -25,3 +25,6 @@
|
||||||
[submodule "aux/netcontrol-connectors"]
|
[submodule "aux/netcontrol-connectors"]
|
||||||
path = aux/netcontrol-connectors
|
path = aux/netcontrol-connectors
|
||||||
url = git://git.bro.org/bro-netcontrol
|
url = git://git.bro.org/bro-netcontrol
|
||||||
|
[submodule "aux/bifcl"]
|
||||||
|
path = aux/bifcl
|
||||||
|
url = git://git.bro.org/bifcl
|
||||||
|
|
|
@ -108,6 +108,10 @@ if (NOT BinPAC_ROOT_DIR AND
|
||||||
endif ()
|
endif ()
|
||||||
FindRequiredPackage(BinPAC)
|
FindRequiredPackage(BinPAC)
|
||||||
|
|
||||||
|
if ( NOT BIFCL_EXE_PATH )
|
||||||
|
add_subdirectory(aux/bifcl)
|
||||||
|
endif ()
|
||||||
|
|
||||||
if (ENABLE_JEMALLOC)
|
if (ENABLE_JEMALLOC)
|
||||||
find_package(JeMalloc)
|
find_package(JeMalloc)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
1
aux/bifcl
Submodule
1
aux/bifcl
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit a25704cc769438b6ecaf92331511456826e90409
|
2
cmake
2
cmake
|
@ -1 +1 @@
|
||||||
Subproject commit 1600554d1d907f4f252f19cf1f55e13d368a936f
|
Subproject commit a416553abcb7aa650e934cd3800bcab0cbcf3e63
|
|
@ -44,15 +44,6 @@ endmacro(REPLACE_YY_PREFIX_TARGET)
|
||||||
|
|
||||||
set(BISON_FLAGS "--debug")
|
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
|
# Rule parser/scanner
|
||||||
bison_target(RuleParser rule-parse.y
|
bison_target(RuleParser rule-parse.y
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/rup.cc
|
${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
|
flex_target(Scanner scan.l ${CMAKE_CURRENT_BINARY_DIR}/scan.cc
|
||||||
COMPILE_FLAGS "-Pbro")
|
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
|
## bifcl-dependent targets
|
||||||
|
|
||||||
|
|
|
@ -1,83 +0,0 @@
|
||||||
#include "bro-config.h"
|
|
||||||
|
|
||||||
#include <set>
|
|
||||||
#include <string>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#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);
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
#ifndef bif_arg_h
|
|
||||||
#define bif_arg_h
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
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
|
|
|
@ -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")
|
|
|
@ -1,422 +0,0 @@
|
||||||
%{
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#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 <plugin> | -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 <list>\n");
|
|
||||||
fprintf(fp_func_init, "#include <string>\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);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,785 +0,0 @@
|
||||||
%{
|
|
||||||
#include <vector>
|
|
||||||
#include <set>
|
|
||||||
#include <string>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#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<BuiltinFuncArg*> 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 <str> 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 <val> 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;
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue