mirror of
https://github.com/zeek/zeek.git
synced 2025-10-05 08:08:19 +00:00
Merge remote-tracking branch 'origin/topic/jsiwek/table-attribute-fixes'
* origin/topic/jsiwek/table-attribute-fixes: Fix various bugs with table/set attributes. Closes #866.
This commit is contained in:
commit
d9f90fcac0
8 changed files with 270 additions and 2 deletions
18
CHANGES
18
CHANGES
|
@ -1,4 +1,22 @@
|
||||||
|
|
||||||
|
2.1-193 | 2012-12-03 14:11:14 -0800
|
||||||
|
|
||||||
|
* Fix a set of bugs with table/set attributes. (Jon Siwek)
|
||||||
|
|
||||||
|
- Identifiers that are initialized with set()/table() constructor
|
||||||
|
expressions now inherit attributes from the expression. Before,
|
||||||
|
statements like
|
||||||
|
|
||||||
|
const i: set[string] = set() &redef;
|
||||||
|
|
||||||
|
associated the attribute with the set() constructor, but not the
|
||||||
|
"i" identifier, preventing redefinition. Addresses #866.
|
||||||
|
|
||||||
|
- Allow &default attribute to apply to tables initialized as empty
|
||||||
|
(via either "{ }" or "table()") or if the expression supplied to it
|
||||||
|
can evaluate to a type that's promotable to the same yield type as
|
||||||
|
the table.
|
||||||
|
|
||||||
2.1-191 | 2012-12-03 14:08:56 -0800
|
2.1-191 | 2012-12-03 14:08:56 -0800
|
||||||
|
|
||||||
* Add test of record() constructor to table initializer unit test.
|
* Add test of record() constructor to table initializer unit test.
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
2.1-191
|
2.1-193
|
||||||
|
|
10
src/Attr.cc
10
src/Attr.cc
|
@ -260,6 +260,11 @@ void Attributes::CheckAttr(Attr* a)
|
||||||
// Ok.
|
// Ok.
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if ( type->Tag() == TYPE_TABLE &&
|
||||||
|
type->AsTableType()->IsUnspecifiedTable() )
|
||||||
|
// Ok.
|
||||||
|
break;
|
||||||
|
|
||||||
a->AttrExpr()->Error("&default value has inconsistent type", type);
|
a->AttrExpr()->Error("&default value has inconsistent type", type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,6 +295,11 @@ void Attributes::CheckAttr(Attr* a)
|
||||||
// Ok.
|
// Ok.
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
Expr* e = a->AttrExpr();
|
||||||
|
if ( check_and_promote_expr(e, ytype) )
|
||||||
|
// Ok.
|
||||||
|
break;
|
||||||
|
|
||||||
Error("&default value has inconsistent type 2");
|
Error("&default value has inconsistent type 2");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3445,7 +3445,7 @@ Val* SetConstructorExpr::Eval(Frame* f) const
|
||||||
if ( IsError() )
|
if ( IsError() )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
TableVal* aggr = new TableVal(type->AsTableType(), 0);
|
TableVal* aggr = new TableVal(type->AsTableType(), attrs);
|
||||||
const expr_list& exprs = op->AsListExpr()->Exprs();
|
const expr_list& exprs = op->AsListExpr()->Exprs();
|
||||||
|
|
||||||
loop_over_list(exprs, i)
|
loop_over_list(exprs, i)
|
||||||
|
|
|
@ -747,6 +747,8 @@ public:
|
||||||
TableConstructorExpr(ListExpr* constructor_list, attr_list* attrs);
|
TableConstructorExpr(ListExpr* constructor_list, attr_list* attrs);
|
||||||
~TableConstructorExpr() { Unref(attrs); }
|
~TableConstructorExpr() { Unref(attrs); }
|
||||||
|
|
||||||
|
Attributes* Attrs() { return attrs; }
|
||||||
|
|
||||||
Val* Eval(Frame* f) const;
|
Val* Eval(Frame* f) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -767,6 +769,8 @@ public:
|
||||||
SetConstructorExpr(ListExpr* constructor_list, attr_list* attrs);
|
SetConstructorExpr(ListExpr* constructor_list, attr_list* attrs);
|
||||||
~SetConstructorExpr() { Unref(attrs); }
|
~SetConstructorExpr() { Unref(attrs); }
|
||||||
|
|
||||||
|
Attributes* Attrs() { return attrs; }
|
||||||
|
|
||||||
Val* Eval(Frame* f) const;
|
Val* Eval(Frame* f) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
30
src/Var.cc
30
src/Var.cc
|
@ -109,6 +109,36 @@ static void make_var(ID* id, BroType* t, init_class c, Expr* init,
|
||||||
if ( attr )
|
if ( attr )
|
||||||
id->AddAttrs(new Attributes(attr, t, false));
|
id->AddAttrs(new Attributes(attr, t, false));
|
||||||
|
|
||||||
|
if ( init )
|
||||||
|
{
|
||||||
|
switch ( init->Tag() ) {
|
||||||
|
case EXPR_TABLE_CONSTRUCTOR:
|
||||||
|
{
|
||||||
|
TableConstructorExpr* ctor = (TableConstructorExpr*) init;
|
||||||
|
if ( ctor->Attrs() )
|
||||||
|
{
|
||||||
|
::Ref(ctor->Attrs());
|
||||||
|
id->AddAttrs(ctor->Attrs());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXPR_SET_CONSTRUCTOR:
|
||||||
|
{
|
||||||
|
SetConstructorExpr* ctor = (SetConstructorExpr*) init;
|
||||||
|
if ( ctor->Attrs() )
|
||||||
|
{
|
||||||
|
::Ref(ctor->Attrs());
|
||||||
|
id->AddAttrs(ctor->Attrs());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( id->FindAttr(ATTR_PERSISTENT) || id->FindAttr(ATTR_SYNCHRONIZED) )
|
if ( id->FindAttr(ATTR_PERSISTENT) || id->FindAttr(ATTR_SYNCHRONIZED) )
|
||||||
{
|
{
|
||||||
if ( dt == VAR_CONST )
|
if ( dt == VAR_CONST )
|
||||||
|
|
91
testing/btest/Baseline/language.table-init-attrs/output
Normal file
91
testing/btest/Baseline/language.table-init-attrs/output
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
my_set_ctor_init
|
||||||
|
{
|
||||||
|
test2,
|
||||||
|
test3,
|
||||||
|
test4,
|
||||||
|
test1
|
||||||
|
}
|
||||||
|
|
||||||
|
my_table_ctor_init
|
||||||
|
{
|
||||||
|
[2] = test2,
|
||||||
|
[1] = test1,
|
||||||
|
[3] = test3
|
||||||
|
}
|
||||||
|
nope
|
||||||
|
|
||||||
|
my_set_init
|
||||||
|
{
|
||||||
|
test2,
|
||||||
|
test3,
|
||||||
|
test4,
|
||||||
|
test1
|
||||||
|
}
|
||||||
|
|
||||||
|
my_table_init
|
||||||
|
{
|
||||||
|
[2] = test2,
|
||||||
|
[4] = test4,
|
||||||
|
[1] = test1,
|
||||||
|
[3] = test3
|
||||||
|
}
|
||||||
|
nope
|
||||||
|
|
||||||
|
inception
|
||||||
|
{
|
||||||
|
[0] = {
|
||||||
|
[13] = bar
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
[13] = bar
|
||||||
|
}
|
||||||
|
bar
|
||||||
|
forty-two
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
we need to go deeper
|
||||||
|
{
|
||||||
|
[0] = {
|
||||||
|
[13] = bar
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
[13] = bar
|
||||||
|
}
|
||||||
|
bar
|
||||||
|
forty-two
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
we need to go deeper
|
||||||
|
|
||||||
|
local table t1
|
||||||
|
{
|
||||||
|
[1] = foo
|
||||||
|
}
|
||||||
|
foo
|
||||||
|
nope
|
||||||
|
|
||||||
|
local table t2
|
||||||
|
{
|
||||||
|
[1] = foo
|
||||||
|
}
|
||||||
|
foo
|
||||||
|
nope
|
||||||
|
|
||||||
|
local table t3
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
nope
|
||||||
|
nope
|
||||||
|
|
||||||
|
local table t4
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
nope
|
||||||
|
nope
|
||||||
|
|
115
testing/btest/language/table-init-attrs.bro
Normal file
115
testing/btest/language/table-init-attrs.bro
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
# @TEST-EXEC: bro -b %INPUT >output
|
||||||
|
# @TEST-EXEC: btest-diff output
|
||||||
|
|
||||||
|
# set()/table() constructors are allowed to have attributes. When initializing
|
||||||
|
# an identifier, those attributes should also apply to it.
|
||||||
|
|
||||||
|
const my_set_ctor_init: set[string] = set("test1") &redef;
|
||||||
|
|
||||||
|
redef my_set_ctor_init += {
|
||||||
|
"test2",
|
||||||
|
"test3",
|
||||||
|
};
|
||||||
|
|
||||||
|
redef my_set_ctor_init += set("test4");
|
||||||
|
|
||||||
|
const my_table_ctor_init: table[count] of string = table([1] = "test1") &redef &default="nope";
|
||||||
|
|
||||||
|
redef my_table_ctor_init += {
|
||||||
|
[2] = "test2",
|
||||||
|
[3] = "test3",
|
||||||
|
};
|
||||||
|
|
||||||
|
# initializer list versions work the same way.
|
||||||
|
|
||||||
|
const my_set_init: set[string] = { "test1" } &redef;
|
||||||
|
|
||||||
|
redef my_set_init += {
|
||||||
|
"test2",
|
||||||
|
"test3",
|
||||||
|
};
|
||||||
|
|
||||||
|
redef my_set_init += set("test4");
|
||||||
|
|
||||||
|
const my_table_init: table[count] of string = { [1] = "test1" } &redef &default="nope";
|
||||||
|
|
||||||
|
redef my_table_init += {
|
||||||
|
[2] = "test2",
|
||||||
|
[3] = "test3",
|
||||||
|
};
|
||||||
|
|
||||||
|
redef my_table_init += table([4] = "test4");
|
||||||
|
|
||||||
|
# For tables that yield tables, we can apply attributes to the both other and
|
||||||
|
# inner tables...
|
||||||
|
|
||||||
|
global inception_table: table[count] of table[count] of string = table(
|
||||||
|
[0] = table([13] = "bar") &default="forty-two"
|
||||||
|
) &default=table() &default="we need to go deeper";
|
||||||
|
|
||||||
|
global inception_table2: table[count] of table[count] of string = {
|
||||||
|
[0] = table([13] = "bar") &default="forty-two",
|
||||||
|
} &default=table() &default="we need to go deeper";
|
||||||
|
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
print "my_set_ctor_init";
|
||||||
|
print my_set_ctor_init;
|
||||||
|
print "";
|
||||||
|
print "my_table_ctor_init";
|
||||||
|
print my_table_ctor_init;
|
||||||
|
print my_table_ctor_init[5];
|
||||||
|
print "";
|
||||||
|
print "my_set_init";
|
||||||
|
print my_set_init;
|
||||||
|
print "";
|
||||||
|
print "my_table_init";
|
||||||
|
print my_table_init;
|
||||||
|
print my_table_init[5];
|
||||||
|
print "";
|
||||||
|
print "inception";
|
||||||
|
print inception_table;
|
||||||
|
print inception_table[0];
|
||||||
|
print inception_table[0][13];
|
||||||
|
print inception_table[0][42];
|
||||||
|
print inception_table[1];
|
||||||
|
print inception_table[1][2];
|
||||||
|
print inception_table2;
|
||||||
|
print inception_table2[0];
|
||||||
|
print inception_table2[0][13];
|
||||||
|
print inception_table2[0][42];
|
||||||
|
print inception_table2[1];
|
||||||
|
print inception_table2[1][2];
|
||||||
|
print "";
|
||||||
|
|
||||||
|
# just checking attributes on locals works, too
|
||||||
|
print "local table t1";
|
||||||
|
local t1: table[count] of string = table([1] = "foo") &default="nope";
|
||||||
|
print t1;
|
||||||
|
print t1[1];
|
||||||
|
print t1[2];
|
||||||
|
print "";
|
||||||
|
|
||||||
|
print "local table t2";
|
||||||
|
local t2: table[count] of string = {[1] = "foo"} &default="nope";
|
||||||
|
print t2;
|
||||||
|
print t2[1];
|
||||||
|
print t2[2];
|
||||||
|
print "";
|
||||||
|
|
||||||
|
# and for empty initializers...
|
||||||
|
print "local table t3";
|
||||||
|
local t3: table[count] of string = table() &default="nope";
|
||||||
|
print t3;
|
||||||
|
print t3[1];
|
||||||
|
print t3[2];
|
||||||
|
print "";
|
||||||
|
|
||||||
|
print "local table t4";
|
||||||
|
local t4: table[count] of string = {} &default="nope";
|
||||||
|
print t4;
|
||||||
|
print t4[1];
|
||||||
|
print t4[2];
|
||||||
|
print "";
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue