diff --git a/CHANGES b/CHANGES index 7fae4dc943..8db9af5621 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,17 @@ +2.5-924 | 2018-08-29 18:21:37 -0500 + + * Allow event/function headers to be wrapped in directives. (Johanna Amann) + + For example: + + @if ( conditions ) + event a(...) + @else + event b(...) + @endif + { ... } + 2.5-922 | 2018-08-29 17:22:20 -0500 * Fix unit tests (Jon Siwek, Corelight) diff --git a/VERSION b/VERSION index 86e9b1b108..919bb76990 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.5-922 +2.5-924 diff --git a/src/Scope.cc b/src/Scope.cc index 97d8e23003..a707336381 100644 --- a/src/Scope.cc +++ b/src/Scope.cc @@ -11,9 +11,10 @@ static scope_list scopes; static Scope* top_scope; -Scope::Scope(ID* id) +Scope::Scope(ID* id, attr_list* al) { scope_id = id; + attrs = al; return_type = 0; local = new PDict(ID)(ORDERED); @@ -42,6 +43,14 @@ Scope::~Scope() for ( int i = 0; i < local->Length(); ++i ) Unref(local->NthEntry(i)); + if ( attrs ) + { + loop_over_list(*attrs, i) + Unref((*attrs)[i]); + + delete attrs; + } + Unref(scope_id); Unref(return_type); delete local; @@ -186,9 +195,9 @@ void push_existing_scope(Scope* scope) scopes.append(scope); } -void push_scope(ID* id) +void push_scope(ID* id, attr_list* attrs) { - top_scope = new Scope(id); + top_scope = new Scope(id, attrs); scopes.append(top_scope); } diff --git a/src/Scope.h b/src/Scope.h index f2713fef80..5fcd31fd8b 100644 --- a/src/Scope.h +++ b/src/Scope.h @@ -19,7 +19,7 @@ declare(PDict,ID); class Scope : public BroObj { public: - explicit Scope(ID* id); + explicit Scope(ID* id, attr_list* al); ~Scope() override; ID* Lookup(const char* name) const { return local->Lookup(name); } @@ -31,6 +31,7 @@ public: } ID* ScopeID() const { return scope_id; } + attr_list* Attrs() const { return attrs; } BroType* ReturnType() const { return return_type; } int Length() const { return local->Length(); } @@ -53,6 +54,7 @@ public: protected: ID* scope_id; + attr_list* attrs; BroType* return_type; PDict(ID)* local; id_list* inits; @@ -69,7 +71,7 @@ extern ID* lookup_ID(const char* name, const char* module, extern ID* install_ID(const char* name, const char* module_name, bool is_global, bool is_export); -extern void push_scope(ID* id); +extern void push_scope(ID* id, attr_list* attrs); extern void push_existing_scope(Scope* scope); // Returns the one popped off; it's not deleted. diff --git a/src/Var.cc b/src/Var.cc index 009c2003a7..d4659023a0 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -328,8 +328,20 @@ static void transfer_arg_defaults(RecordType* args, RecordType* recv) } } +static bool has_attr(const attr_list* al, attr_tag tag) + { + if ( ! al ) + return false; + + for ( int i = 0; i < al->length(); ++i ) + if ( (*al)[i]->Tag() == tag ) + return true; + + return false; + } + void begin_func(ID* id, const char* module_name, function_flavor flavor, - int is_redef, FuncType* t) + int is_redef, FuncType* t, attr_list* attrs) { if ( flavor == FUNC_FLAVOR_EVENT ) { @@ -384,7 +396,7 @@ void begin_func(ID* id, const char* module_name, function_flavor flavor, else id->SetType(t); - push_scope(id); + push_scope(id, attrs); RecordType* args = t->Args(); int num_args = args->NumFields(); @@ -401,6 +413,9 @@ void begin_func(ID* id, const char* module_name, function_flavor flavor, arg_id = install_ID(arg_i->id, module_name, false, false); arg_id->SetType(arg_i->type->Ref()); } + + if ( has_attr(attrs, ATTR_DEPRECATED) ) + id->MakeDeprecated(); } class OuterIDBindingFinder : public TraversalCallback { @@ -431,7 +446,7 @@ TraversalCode OuterIDBindingFinder::PreExpr(const Expr* expr) return TC_CONTINUE; } -void end_func(Stmt* body, attr_list* attrs) +void end_func(Stmt* body) { int frame_size = current_scope()->Length(); id_list* inits = current_scope()->GetInits(); @@ -440,6 +455,8 @@ void end_func(Stmt* body, attr_list* attrs) ID* id = scope->ScopeID(); int priority = 0; + auto attrs = scope->Attrs(); + if ( attrs ) { loop_over_list(*attrs, i) diff --git a/src/Var.h b/src/Var.h index 831c10e90c..98e0f45163 100644 --- a/src/Var.h +++ b/src/Var.h @@ -21,8 +21,8 @@ extern Expr* add_and_assign_local(ID* id, Expr* init, Val* val = 0); extern void add_type(ID* id, BroType* t, attr_list* attr); extern void begin_func(ID* id, const char* module_name, function_flavor flavor, - int is_redef, FuncType* t); -extern void end_func(Stmt* body, attr_list* attrs = 0); + int is_redef, FuncType* t, attr_list* attrs = nullptr); +extern void end_func(Stmt* body); extern Val* internal_val(const char* name); extern Val* internal_const_val(const char* name); // internal error if not const diff --git a/src/main.cc b/src/main.cc index 757b09351f..ab287ec2f5 100644 --- a/src/main.cc +++ b/src/main.cc @@ -848,7 +848,7 @@ int main(int argc, char** argv) add_input_file(argv[optind++]); } - push_scope(0); + push_scope(nullptr, nullptr); dns_mgr = new DNS_Mgr(dns_type); diff --git a/src/parse.y b/src/parse.y index 25b6c17873..6afab9c3bb 100644 --- a/src/parse.y +++ b/src/parse.y @@ -234,18 +234,6 @@ static bool expr_is_table_type_name(const Expr* expr) return false; } - -static bool has_attr(const attr_list* al, attr_tag tag) - { - if ( ! al ) - return false; - - for ( int i = 0; i < al->length(); ++i ) - if ( (*al)[i]->Tag() == tag ) - return true; - - return false; - } %} %union { @@ -1142,9 +1130,16 @@ decl: | func_hdr func_body { } + | func_hdr conditional_list func_body + { } + | conditional ; +conditional_list: + conditional + | conditional conditional_list + conditional: TOK_ATIF '(' expr ')' { do_atif($3); } @@ -1159,43 +1154,40 @@ conditional: ; func_hdr: - TOK_FUNCTION def_global_id func_params + TOK_FUNCTION def_global_id func_params opt_attr { begin_func($2, current_module.c_str(), - FUNC_FLAVOR_FUNCTION, 0, $3); + FUNC_FLAVOR_FUNCTION, 0, $3, $4); $$ = $3; broxygen_mgr->Identifier($2); } - | TOK_EVENT event_id func_params + | TOK_EVENT event_id func_params opt_attr { begin_func($2, current_module.c_str(), - FUNC_FLAVOR_EVENT, 0, $3); + FUNC_FLAVOR_EVENT, 0, $3, $4); $$ = $3; } - | TOK_HOOK def_global_id func_params + | TOK_HOOK def_global_id func_params opt_attr { $3->ClearYieldType(FUNC_FLAVOR_HOOK); $3->SetYieldType(base_type(TYPE_BOOL)); begin_func($2, current_module.c_str(), - FUNC_FLAVOR_HOOK, 0, $3); + FUNC_FLAVOR_HOOK, 0, $3, $4); $$ = $3; } - | TOK_REDEF TOK_EVENT event_id func_params + | TOK_REDEF TOK_EVENT event_id func_params opt_attr { begin_func($3, current_module.c_str(), - FUNC_FLAVOR_EVENT, 1, $4); + FUNC_FLAVOR_EVENT, 1, $4, $5); $$ = $4; } ; func_body: - opt_attr '{' + '{' { saved_in_init.push_back(in_init); in_init = 0; - - if ( has_attr($1, ATTR_DEPRECATED) ) - current_scope()->ScopeID()->MakeDeprecated(); } stmt_list @@ -1206,7 +1198,7 @@ func_body: '}' { - end_func($4, $1); + end_func($3); } ; diff --git a/testing/btest/Baseline/language.at-if-event/out b/testing/btest/Baseline/language.at-if-event/out new file mode 100644 index 0000000000..9dfcf39f5a --- /dev/null +++ b/testing/btest/Baseline/language.at-if-event/out @@ -0,0 +1,5 @@ +0 +1 +2 +3 +4 diff --git a/testing/btest/language/at-if-event.bro b/testing/btest/language/at-if-event.bro new file mode 100644 index 0000000000..0dd9815908 --- /dev/null +++ b/testing/btest/language/at-if-event.bro @@ -0,0 +1,51 @@ +# @TEST-EXEC: bro -b %INPUT >out +# @TEST-EXEC: btest-diff out +# Check if @if can be used to alternative function/event definitions + +@if ( 1==1 ) +function test_case(msg: string) +@else +lalala +@endif + { + print msg; + } + +@if ( 1==1 ) +event bro_init() +@else +lalala +@endif + { + print "1"; + test_case("2"); + } + +@if ( 1==0 ) +lalala +@else +event bro_init() +@endif + { + print "3"; + } + +@if ( 1==1 ) +@if ( 1==1 ) +event bro_init() +@endif +@else +lalala +@endif + { + print "4"; + } + +@if ( 1==1 ) +event bro_init() &priority=10 +@else +lalala +@endif + { + print "0"; + }