Merge remote-tracking branch 'origin/topic/timw/171-deprecation-warnings'

* origin/topic/timw/171-deprecation-warnings:
  GH-171: support warning messages alongside deprecated attributes

Made a minor tweak to give a better error message when using
&deprecated= with something other than a string literal expression.
This commit is contained in:
Jon Siwek 2019-06-21 12:26:08 -07:00
commit 16785a2d70
13 changed files with 269 additions and 74 deletions

2
doc

@ -1 +1 @@
Subproject commit cc4c3e0baf3f3f5e26043846a7c4b8cc9ba139f7 Subproject commit 957e8a6ec80de04e35e6bbd62e12e3970be1c382

View file

@ -2884,9 +2884,8 @@ FieldExpr::FieldExpr(Expr* arg_op, const char* arg_field_name)
SetType(rt->FieldType(field)->Ref()); SetType(rt->FieldType(field)->Ref());
td = rt->FieldDecl(field); td = rt->FieldDecl(field);
if ( td->FindAttr(ATTR_DEPRECATED) ) if ( rt->IsFieldDeprecated(field) )
reporter->Warning("deprecated (%s$%s)", rt->GetName().c_str(), reporter->Warning("%s", rt->GetFieldDeprecationWarning(field, false).c_str());
field_name);
} }
} }
} }
@ -2975,9 +2974,8 @@ HasFieldExpr::HasFieldExpr(Expr* arg_op, const char* arg_field_name)
if ( field < 0 ) if ( field < 0 )
ExprError("no such field in record"); ExprError("no such field in record");
else if ( rt->FieldDecl(field)->FindAttr(ATTR_DEPRECATED) ) else if ( rt->IsFieldDeprecated(field) )
reporter->Warning("deprecated (%s?$%s)", rt->GetName().c_str(), reporter->Warning("%s", rt->GetFieldDeprecationWarning(field, true).c_str());
field_name);
SetType(base_type(TYPE_BOOL)); SetType(base_type(TYPE_BOOL));
} }
@ -3659,13 +3657,8 @@ RecordCoerceExpr::RecordCoerceExpr(Expr* op, RecordType* r)
break; break;
} }
} }
else else if ( t_r->IsFieldDeprecated(i) )
{ reporter->Warning("%s", t_r->GetFieldDeprecationWarning(i, false).c_str());
if ( t_r->FieldDecl(i)->FindAttr(ATTR_DEPRECATED) )
reporter->Warning("deprecated (%s$%s)",
t_r->GetName().c_str(),
t_r->FieldName(i));
}
} }
} }
} }

View file

@ -189,15 +189,35 @@ void ID::UpdateValAttrs()
} }
} }
void ID::MakeDeprecated() void ID::MakeDeprecated(Expr* deprecation)
{ {
if ( IsDeprecated() ) if ( IsDeprecated() )
return; return;
attr_list* attr = new attr_list{new Attr(ATTR_DEPRECATED)}; attr_list* attr = new attr_list{new Attr(ATTR_DEPRECATED, deprecation)};
AddAttrs(new Attributes(attr, Type(), false)); AddAttrs(new Attributes(attr, Type(), false));
} }
string ID::GetDeprecationWarning() const
{
string result;
Attr* depr_attr = FindAttr(ATTR_DEPRECATED);
if ( depr_attr )
{
ConstExpr* expr = static_cast<ConstExpr*>(depr_attr->AttrExpr());
if ( expr )
{
StringVal* text = expr->Value()->AsStringVal();
result = text->CheckString();
}
}
if ( result.empty() )
return fmt("deprecated (%s)", Name());
else
return fmt("deprecated (%s): %s", Name(), result.c_str());
}
void ID::AddAttrs(Attributes* a) void ID::AddAttrs(Attributes* a)
{ {
if ( attrs ) if ( attrs )

View file

@ -82,7 +82,9 @@ public:
bool IsDeprecated() const bool IsDeprecated() const
{ return FindAttr(ATTR_DEPRECATED) != 0; } { return FindAttr(ATTR_DEPRECATED) != 0; }
void MakeDeprecated(); void MakeDeprecated(Expr* deprecation);
string GetDeprecationWarning() const;
void Error(const char* msg, const BroObj* o2 = 0); void Error(const char* msg, const BroObj* o2 = 0);

View file

@ -985,6 +985,33 @@ void RecordType::DescribeFieldsReST(ODesc* d, bool func_args) const
d->PopIndentNoNL(); d->PopIndentNoNL();
} }
string RecordType::GetFieldDeprecationWarning(int field, bool has_check) const
{
const TypeDecl* decl = FieldDecl(field);
if ( decl)
{
string result;
if ( const Attr* deprecation = decl->FindAttr(ATTR_DEPRECATED) )
{
ConstExpr* expr = static_cast<ConstExpr*>(deprecation->AttrExpr());
if ( expr )
{
StringVal* text = expr->Value()->AsStringVal();
result = text->CheckString();
}
}
if ( result.empty() )
return fmt("deprecated (%s%s$%s)", GetName().c_str(), has_check ? "?" : "",
FieldName(field));
else
return fmt("deprecated (%s%s$%s): %s", GetName().c_str(), has_check ? "?" : "",
FieldName(field), result.c_str());
}
return "";
}
SubNetType::SubNetType() : BroType(TYPE_SUBNET) SubNetType::SubNetType() : BroType(TYPE_SUBNET)
{ {
} }
@ -1083,7 +1110,7 @@ EnumType::~EnumType()
// Note, we use reporter->Error() here (not Error()) to include the current script // Note, we use reporter->Error() here (not Error()) to include the current script
// location in the error message, rather than the one where the type was // location in the error message, rather than the one where the type was
// originally defined. // originally defined.
void EnumType::AddName(const string& module_name, const char* name, bool is_export, bool deprecated) void EnumType::AddName(const string& module_name, const char* name, bool is_export, Expr* deprecation)
{ {
/* implicit, auto-increment */ /* implicit, auto-increment */
if ( counter < 0) if ( counter < 0)
@ -1092,11 +1119,11 @@ void EnumType::AddName(const string& module_name, const char* name, bool is_expo
SetError(); SetError();
return; return;
} }
CheckAndAddName(module_name, name, counter, is_export, deprecated); CheckAndAddName(module_name, name, counter, is_export, deprecation);
counter++; counter++;
} }
void EnumType::AddName(const string& module_name, const char* name, bro_int_t val, bool is_export, bool deprecated) void EnumType::AddName(const string& module_name, const char* name, bro_int_t val, bool is_export, Expr* deprecation)
{ {
/* explicit value specified */ /* explicit value specified */
if ( counter > 0 ) if ( counter > 0 )
@ -1106,11 +1133,11 @@ void EnumType::AddName(const string& module_name, const char* name, bro_int_t va
return; return;
} }
counter = -1; counter = -1;
CheckAndAddName(module_name, name, val, is_export, deprecated); CheckAndAddName(module_name, name, val, is_export, deprecation);
} }
void EnumType::CheckAndAddName(const string& module_name, const char* name, void EnumType::CheckAndAddName(const string& module_name, const char* name,
bro_int_t val, bool is_export, bool deprecated) bro_int_t val, bool is_export, Expr* deprecation)
{ {
if ( Lookup(val) ) if ( Lookup(val) )
{ {
@ -1127,8 +1154,8 @@ void EnumType::CheckAndAddName(const string& module_name, const char* name,
id->SetType(this->Ref()); id->SetType(this->Ref());
id->SetEnumConst(); id->SetEnumConst();
if ( deprecated ) if ( deprecation )
id->MakeDeprecated(); id->MakeDeprecated(deprecation);
zeekygen_mgr->Identifier(id); zeekygen_mgr->Identifier(id);
} }

View file

@ -494,6 +494,14 @@ public:
void DescribeFields(ODesc* d) const; void DescribeFields(ODesc* d) const;
void DescribeFieldsReST(ODesc* d, bool func_args) const; void DescribeFieldsReST(ODesc* d, bool func_args) const;
bool IsFieldDeprecated(int field) const
{
const TypeDecl* decl = FieldDecl(field);
return decl && decl->FindAttr(ATTR_DEPRECATED) != 0;
}
string GetFieldDeprecationWarning(int field, bool has_check) const;
protected: protected:
RecordType() { types = 0; } RecordType() { types = 0; }
@ -551,12 +559,12 @@ public:
// The value of this name is next internal counter value, starting // The value of this name is next internal counter value, starting
// with zero. The internal counter is incremented. // with zero. The internal counter is incremented.
void AddName(const string& module_name, const char* name, bool is_export, bool deprecated); void AddName(const string& module_name, const char* name, bool is_export, Expr* deprecation = nullptr);
// The value of this name is set to val. Once a value has been // The value of this name is set to val. Once a value has been
// explicitly assigned using this method, no further names can be // explicitly assigned using this method, no further names can be
// added that aren't likewise explicitly initalized. // added that aren't likewise explicitly initalized.
void AddName(const string& module_name, const char* name, bro_int_t val, bool is_export, bool deprecated); void AddName(const string& module_name, const char* name, bro_int_t val, bool is_export, Expr* deprecation = nullptr);
// -1 indicates not found. // -1 indicates not found.
bro_int_t Lookup(const string& module_name, const char* name) const; bro_int_t Lookup(const string& module_name, const char* name) const;
@ -578,7 +586,7 @@ protected:
void CheckAndAddName(const string& module_name, void CheckAndAddName(const string& module_name,
const char* name, bro_int_t val, bool is_export, const char* name, bro_int_t val, bool is_export,
bool deprecated); Expr* deprecation = nullptr);
typedef std::map<std::string, bro_int_t> NameMap; typedef std::map<std::string, bro_int_t> NameMap;
NameMap names; NameMap names;

View file

@ -312,16 +312,21 @@ static void transfer_arg_defaults(RecordType* args, RecordType* recv)
} }
} }
static bool has_attr(const attr_list* al, attr_tag tag) static Attr* find_attr(const attr_list* al, attr_tag tag)
{ {
if ( ! al ) if ( ! al )
return false; return nullptr;
for ( int i = 0; i < al->length(); ++i ) for ( int i = 0; i < al->length(); ++i )
if ( (*al)[i]->Tag() == tag ) if ( (*al)[i]->Tag() == tag )
return true; return (*al)[i];
return false; return nullptr;
}
static bool has_attr(const attr_list* al, attr_tag tag)
{
return find_attr(al, tag) != nullptr;
} }
void begin_func(ID* id, const char* module_name, function_flavor flavor, void begin_func(ID* id, const char* module_name, function_flavor flavor,
@ -398,8 +403,8 @@ void begin_func(ID* id, const char* module_name, function_flavor flavor,
arg_id->SetType(arg_i->type->Ref()); arg_id->SetType(arg_i->type->Ref());
} }
if ( has_attr(attrs, ATTR_DEPRECATED) ) if ( Attr* depr_attr = find_attr(attrs, ATTR_DEPRECATED) )
id->MakeDeprecated(); id->MakeDeprecated(depr_attr->AttrExpr());
} }
class OuterIDBindingFinder : public TraversalCallback { class OuterIDBindingFinder : public TraversalCallback {

View file

@ -5,7 +5,7 @@
// Switching parser table type fixes ambiguity problems. // Switching parser table type fixes ambiguity problems.
%define lr.type ielr %define lr.type ielr
%expect 104 %expect 105
%token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY %token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY
%token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF %token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF
@ -50,14 +50,14 @@
%left '$' '[' ']' '(' ')' TOK_HAS_FIELD TOK_HAS_ATTR %left '$' '[' ']' '(' ')' TOK_HAS_FIELD TOK_HAS_ATTR
%nonassoc TOK_AS TOK_IS %nonassoc TOK_AS TOK_IS
%type <b> opt_no_test opt_no_test_block opt_deprecated TOK_PATTERN_END %type <b> opt_no_test opt_no_test_block TOK_PATTERN_END
%type <str> TOK_ID TOK_PATTERN_TEXT %type <str> TOK_ID TOK_PATTERN_TEXT
%type <id> local_id global_id def_global_id event_id global_or_event_id resolve_id begin_func case_type %type <id> local_id global_id def_global_id event_id global_or_event_id resolve_id begin_func case_type
%type <id_l> local_id_list case_type_list %type <id_l> local_id_list case_type_list
%type <ic> init_class %type <ic> init_class
%type <expr> opt_init %type <expr> opt_init
%type <val> TOK_CONSTANT %type <val> TOK_CONSTANT
%type <expr> expr opt_expr init anonymous_function index_slice %type <expr> expr opt_expr init anonymous_function index_slice opt_deprecated
%type <event_expr> event %type <event_expr> event
%type <stmt> stmt stmt_list func_body for_head %type <stmt> stmt stmt_list func_body for_head
%type <type> type opt_type enum_body %type <type> type opt_type enum_body
@ -700,7 +700,7 @@ expr:
$$ = new NameExpr(id); $$ = new NameExpr(id);
if ( id->IsDeprecated() ) if ( id->IsDeprecated() )
reporter->Warning("deprecated (%s)", id->Name()); reporter->Warning("%s", id->GetDeprecationWarning().c_str());
} }
} }
@ -1002,7 +1002,7 @@ type:
Ref($$); Ref($$);
if ( $1->IsDeprecated() ) if ( $1->IsDeprecated() )
reporter->Warning("deprecated (%s)", $1->Name()); reporter->Warning("%s", $1->GetDeprecationWarning().c_str());
} }
} }
; ;
@ -1327,6 +1327,19 @@ attr:
{ $$ = new Attr(ATTR_ERROR_HANDLER); } { $$ = new Attr(ATTR_ERROR_HANDLER); }
| TOK_ATTR_DEPRECATED | TOK_ATTR_DEPRECATED
{ $$ = new Attr(ATTR_DEPRECATED); } { $$ = new Attr(ATTR_DEPRECATED); }
| TOK_ATTR_DEPRECATED '=' TOK_CONSTANT
{
if ( IsString($3->Type()->Tag()) )
$$ = new Attr(ATTR_DEPRECATED, new ConstExpr($3));
else
{
ODesc d;
$3->Describe(&d);
reporter->Error("'&deprecated=%s' must use a string literal",
d.Description());
$$ = new Attr(ATTR_DEPRECATED);
}
}
; ;
stmt: stmt:
@ -1535,7 +1548,7 @@ event:
YYERROR; YYERROR;
} }
if ( id->IsDeprecated() ) if ( id->IsDeprecated() )
reporter->Warning("deprecated (%s)", id->Name()); reporter->Warning("%s", id->GetDeprecationWarning().c_str());
} }
$$ = new EventExpr($1, $3); $$ = new EventExpr($1, $3);
@ -1741,7 +1754,7 @@ global_or_event_id:
if ( t->Tag() != TYPE_FUNC || if ( t->Tag() != TYPE_FUNC ||
t->AsFuncType()->Flavor() != FUNC_FLAVOR_FUNCTION ) t->AsFuncType()->Flavor() != FUNC_FLAVOR_FUNCTION )
reporter->Warning("deprecated (%s)", $$->Name()); reporter->Warning("%s", $$->GetDeprecationWarning().c_str());
} }
delete [] $1; delete [] $1;
@ -1787,9 +1800,23 @@ opt_no_test_block:
opt_deprecated: opt_deprecated:
TOK_ATTR_DEPRECATED TOK_ATTR_DEPRECATED
{ $$ = true; } { $$ = new ConstExpr(new StringVal("")); }
| |
{ $$ = false; } TOK_ATTR_DEPRECATED '=' TOK_CONSTANT
{
if ( IsString($3->Type()->Tag()) )
$$ = new ConstExpr($3);
else
{
ODesc d;
$3->Describe(&d);
reporter->Error("'&deprecated=%s' must use a string literal",
d.Description());
$$ = new ConstExpr(new StringVal(""));
}
}
|
{ $$ = nullptr; }
%% %%

View file

@ -244,7 +244,7 @@ void ComponentManager<T, C>::RegisterComponent(C* component,
string id = fmt("%s%s", prefix.c_str(), cname.c_str()); string id = fmt("%s%s", prefix.c_str(), cname.c_str());
tag_enum_type->AddName(module, id.c_str(), tag_enum_type->AddName(module, id.c_str(),
component->Tag().AsEnumVal()->InternalInt(), true, component->Tag().AsEnumVal()->InternalInt(), true,
false); nullptr);
} }
} // namespace plugin } // namespace plugin

View file

@ -0,0 +1,28 @@
warning in ./no-warnings.zeek, line 27: deprecated (ONE)
warning in ./no-warnings.zeek, line 28: deprecated (TWO)
warning in ./no-warnings.zeek, line 30: deprecated (GREEN)
warning in ./no-warnings.zeek, line 31: deprecated (BLUE)
warning in ./no-warnings.zeek, line 33: deprecated (blah)
warning in ./no-warnings.zeek, line 37: deprecated (my_event)
warning in ./no-warnings.zeek, line 38: deprecated (my_event)
warning in ./no-warnings.zeek, line 39: deprecated (my_hook)
warning in ./no-warnings.zeek, line 41: deprecated (my_record$b)
warning in ./no-warnings.zeek, line 42: deprecated (my_record$b)
warning in ./no-warnings.zeek, line 43: deprecated (my_record$b)
warning in ./no-warnings.zeek, line 45: deprecated (my_record?$b)
warning in ./no-warnings.zeek, line 46: deprecated (my_record$b)
warning in ./no-warnings.zeek, line 49: deprecated (my_record$b)
warning in ./no-warnings.zeek, line 52: deprecated (my_event)
warning in ./no-warnings.zeek, line 57: deprecated (my_hook)
warning in ./no-warnings.zeek, line 62: deprecated (blah)
warning in ./no-warnings.zeek, line 71: deprecated (dont_use_me)
warning in ./no-warnings.zeek, line 76: deprecated (dont_use_me_either)
ZERO
ONE
TWO
RED
GREEN
BLUE
generate my_hook please
generate my_event please
schedule my_event please

View file

@ -1,28 +0,0 @@
warning in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.deprecated/deprecated.zeek, line 30: deprecated (ONE)
warning in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.deprecated/deprecated.zeek, line 31: deprecated (TWO)
warning in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.deprecated/deprecated.zeek, line 33: deprecated (GREEN)
warning in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.deprecated/deprecated.zeek, line 34: deprecated (BLUE)
warning in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.deprecated/deprecated.zeek, line 36: deprecated (blah)
warning in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.deprecated/deprecated.zeek, line 40: deprecated (my_event)
warning in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.deprecated/deprecated.zeek, line 41: deprecated (my_event)
warning in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.deprecated/deprecated.zeek, line 42: deprecated (my_hook)
warning in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.deprecated/deprecated.zeek, line 44: deprecated (my_record$b)
warning in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.deprecated/deprecated.zeek, line 45: deprecated (my_record$b)
warning in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.deprecated/deprecated.zeek, line 46: deprecated (my_record$b)
warning in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.deprecated/deprecated.zeek, line 48: deprecated (my_record?$b)
warning in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.deprecated/deprecated.zeek, line 49: deprecated (my_record$b)
warning in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.deprecated/deprecated.zeek, line 52: deprecated (my_record$b)
warning in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.deprecated/deprecated.zeek, line 55: deprecated (my_event)
warning in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.deprecated/deprecated.zeek, line 60: deprecated (my_hook)
warning in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.deprecated/deprecated.zeek, line 65: deprecated (blah)
warning in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.deprecated/deprecated.zeek, line 74: deprecated (dont_use_me)
warning in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.deprecated/deprecated.zeek, line 79: deprecated (dont_use_me_either)
ZERO
ONE
TWO
RED
GREEN
BLUE
generate my_hook please
generate my_event please
schedule my_event please

View file

@ -0,0 +1,28 @@
warning in ./warnings.zeek, line 27: deprecated (ONE): one warning
warning in ./warnings.zeek, line 28: deprecated (TWO): two warning
warning in ./warnings.zeek, line 30: deprecated (GREEN): green warning
warning in ./warnings.zeek, line 31: deprecated (BLUE): red warning
warning in ./warnings.zeek, line 33: deprecated (blah): type warning
warning in ./warnings.zeek, line 37: deprecated (my_event): event warning
warning in ./warnings.zeek, line 38: deprecated (my_event): event warning
warning in ./warnings.zeek, line 39: deprecated (my_hook): hook warning
warning in ./warnings.zeek, line 41: deprecated (my_record$b): record warning
warning in ./warnings.zeek, line 42: deprecated (my_record$b): record warning
warning in ./warnings.zeek, line 43: deprecated (my_record$b): record warning
warning in ./warnings.zeek, line 45: deprecated (my_record?$b): record warning
warning in ./warnings.zeek, line 46: deprecated (my_record$b): record warning
warning in ./warnings.zeek, line 49: deprecated (my_record$b): record warning
warning in ./warnings.zeek, line 52: deprecated (my_event): event warning
warning in ./warnings.zeek, line 57: deprecated (my_hook): hook warning
warning in ./warnings.zeek, line 62: deprecated (blah): type warning
warning in ./warnings.zeek, line 71: deprecated (dont_use_me): global function warning
warning in ./warnings.zeek, line 76: deprecated (dont_use_me_either): function warning
ZERO
ONE
TWO
RED
GREEN
BLUE
generate my_hook please
generate my_event please
schedule my_event please

View file

@ -1,6 +1,10 @@
# @TEST-EXEC: zeek -b %INPUT >out 2>&1 # @TEST-EXEC: zeek -b no-warnings.zeek >no-warnings.out 2>&1
# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff out # @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff no-warnings.out
# @TEST-EXEC: zeek -b warnings.zeek >warnings.out 2>&1
# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff warnings.out
@TEST-START-FILE no-warnings.zeek
type blah: string &deprecated; type blah: string &deprecated;
global my_event: event(arg: string) &deprecated; global my_event: event(arg: string) &deprecated;
@ -21,7 +25,7 @@ type my_enum: enum {
type my_other_enum: enum { type my_other_enum: enum {
ZERO = 0, ZERO = 0,
ONE = 1 &deprecated, ONE = 1 &deprecated,
TWO = 2 &deprecated TWO = 2 &deprecated,
}; };
event zeek_init() event zeek_init()
@ -78,3 +82,84 @@ function dont_use_me_either() &deprecated
{ {
dont_use_me_either(); dont_use_me_either();
} }
@TEST-END-FILE
@TEST-START-FILE warnings.zeek
type blah: string &deprecated="type warning";
global my_event: event(arg: string) &deprecated="event warning";
global my_hook: hook(arg: string) &deprecated="hook warning";
type my_record: record {
a: count &default = 1;
b: string &optional &deprecated="record warning";
};
type my_enum: enum {
RED,
GREEN &deprecated="green warning",
BLUE &deprecated="red warning"
};
type my_other_enum: enum {
ZERO = 0,
ONE = 1 &deprecated="one warning",
TWO = 2 &deprecated="two warning",
};
event zeek_init()
{
print ZERO;
print ONE;
print TWO;
print RED;
print GREEN;
print BLUE;
local l: blah = "testing";
local ls: string = " test";
event my_event("generate my_event please");
schedule 1sec { my_event("schedule my_event please") };
hook my_hook("generate my_hook please");
local mr = my_record($a = 3, $b = "yeah");
mr = [$a = 4, $b = "ye"];
mr = record($a = 5, $b = "y");
if ( ! mr?$b )
mr$b = "nooooooo";
mr$a = 2;
mr$b = "noooo";
}
event my_event(arg: string)
{
print arg;
}
hook my_hook(arg: string)
{
print arg;
}
function hmm(b: blah)
{
print b;
}
global dont_use_me: function() &deprecated="global function warning";
function dont_use_me()
{
dont_use_me();
}
function dont_use_me_either() &deprecated="function warning"
{
dont_use_me_either();
}
@TEST-END-FILE