mirror of
https://github.com/zeek/zeek.git
synced 2025-10-06 08:38:20 +00:00
Two small infrastructure extensions for passing information into the
logging framework. - To enable passing a type into a bif, there's now a new BroType-derived class TypeType and a corresponding TYPE_TYPE tag. With that, a Val can now have a type as its value. This is experimental for now. - RecordVal's get a new method CoerceTo() to coerce their value into a another record type with the usual semantics. Most of the code in there was previously in RecordContructorExpr::InitVal(), which is now calling the new CoerceTo() method.
This commit is contained in:
parent
ffa494e428
commit
9d407d882c
5 changed files with 119 additions and 40 deletions
42
src/Expr.cc
42
src/Expr.cc
|
@ -284,7 +284,7 @@ Val* NameExpr::Eval(Frame* f) const
|
||||||
Val* v;
|
Val* v;
|
||||||
|
|
||||||
if ( id->AsType() )
|
if ( id->AsType() )
|
||||||
RunTime("cannot evaluate type name");
|
return new Val(id->AsType(), true);
|
||||||
|
|
||||||
if ( id->IsGlobal() )
|
if ( id->IsGlobal() )
|
||||||
v = id->ID_Val();
|
v = id->ID_Val();
|
||||||
|
@ -3309,48 +3309,12 @@ RecordConstructorExpr::RecordConstructorExpr(ListExpr* constructor_list)
|
||||||
|
|
||||||
Val* RecordConstructorExpr::InitVal(const BroType* t, Val* aggr) const
|
Val* RecordConstructorExpr::InitVal(const BroType* t, Val* aggr) const
|
||||||
{
|
{
|
||||||
if ( ! aggr )
|
|
||||||
aggr = new RecordVal(const_cast<RecordType*>(t->AsRecordType()));
|
|
||||||
|
|
||||||
if ( record_promotion_compatible(t->AsRecordType(), Type()->AsRecordType()) )
|
|
||||||
{
|
|
||||||
RecordVal* ar = aggr->AsRecordVal();
|
|
||||||
RecordType* ar_t = aggr->Type()->AsRecordType();
|
|
||||||
|
|
||||||
RecordVal* rv = Eval(0)->AsRecordVal();
|
RecordVal* rv = Eval(0)->AsRecordVal();
|
||||||
RecordType* rv_t = rv->Type()->AsRecordType();
|
RecordVal* ar = rv->CoerceTo(t->AsRecordType(), aggr);
|
||||||
|
|
||||||
int i;
|
if ( ar )
|
||||||
for ( i = 0; i < rv_t->NumFields(); ++i )
|
|
||||||
{
|
{
|
||||||
int t_i = ar_t->FieldOffset(rv_t->FieldName(i));
|
|
||||||
|
|
||||||
if ( t_i < 0 )
|
|
||||||
{
|
|
||||||
char buf[512];
|
|
||||||
safe_snprintf(buf, sizeof(buf),
|
|
||||||
"orphan field \"%s\" in initialization",
|
|
||||||
rv_t->FieldName(i));
|
|
||||||
Error(buf);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
ar->Assign(t_i, rv->Lookup(i)->Ref());
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( i = 0; i < ar_t->NumFields(); ++i )
|
|
||||||
if ( ! ar->Lookup(i) &&
|
|
||||||
! ar_t->FieldDecl(i)->FindAttr(ATTR_OPTIONAL) )
|
|
||||||
{
|
|
||||||
char buf[512];
|
|
||||||
safe_snprintf(buf, sizeof(buf),
|
|
||||||
"non-optional field \"%s\" missing in initialization", ar_t->FieldName(i));
|
|
||||||
Error(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
Unref(rv);
|
Unref(rv);
|
||||||
|
|
||||||
return ar;
|
return ar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,7 @@ BroType::BroType(TypeTag t, bool arg_base_type)
|
||||||
case TYPE_FUNC:
|
case TYPE_FUNC:
|
||||||
case TYPE_FILE:
|
case TYPE_FILE:
|
||||||
case TYPE_VECTOR:
|
case TYPE_VECTOR:
|
||||||
|
case TYPE_TYPE:
|
||||||
internal_tag = TYPE_INTERNAL_OTHER;
|
internal_tag = TYPE_INTERNAL_OTHER;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1426,6 +1427,9 @@ int same_type(const BroType* t1, const BroType* t2, int is_init)
|
||||||
case TYPE_FILE:
|
case TYPE_FILE:
|
||||||
return same_type(t1->YieldType(), t2->YieldType(), is_init);
|
return same_type(t1->YieldType(), t2->YieldType(), is_init);
|
||||||
|
|
||||||
|
case TYPE_TYPE:
|
||||||
|
return same_type(t1, t2, is_init);
|
||||||
|
|
||||||
case TYPE_UNION:
|
case TYPE_UNION:
|
||||||
error("union type in same_type()");
|
error("union type in same_type()");
|
||||||
}
|
}
|
||||||
|
@ -1514,6 +1518,7 @@ int is_assignable(BroType* t)
|
||||||
case TYPE_VECTOR:
|
case TYPE_VECTOR:
|
||||||
case TYPE_FILE:
|
case TYPE_FILE:
|
||||||
case TYPE_TABLE:
|
case TYPE_TABLE:
|
||||||
|
case TYPE_TYPE:
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case TYPE_VOID:
|
case TYPE_VOID:
|
||||||
|
|
28
src/Type.h
28
src/Type.h
|
@ -31,6 +31,7 @@ typedef enum {
|
||||||
TYPE_FUNC,
|
TYPE_FUNC,
|
||||||
TYPE_FILE,
|
TYPE_FILE,
|
||||||
TYPE_VECTOR,
|
TYPE_VECTOR,
|
||||||
|
TYPE_TYPE,
|
||||||
TYPE_ERROR
|
TYPE_ERROR
|
||||||
#define NUM_TYPES (int(TYPE_ERROR) + 1)
|
#define NUM_TYPES (int(TYPE_ERROR) + 1)
|
||||||
} TypeTag;
|
} TypeTag;
|
||||||
|
@ -59,6 +60,7 @@ class ListExpr;
|
||||||
class EnumType;
|
class EnumType;
|
||||||
class Serializer;
|
class Serializer;
|
||||||
class VectorType;
|
class VectorType;
|
||||||
|
class TypeType;
|
||||||
|
|
||||||
const int DOES_NOT_MATCH_INDEX = 0;
|
const int DOES_NOT_MATCH_INDEX = 0;
|
||||||
const int MATCHES_INDEX_SCALAR = 1;
|
const int MATCHES_INDEX_SCALAR = 1;
|
||||||
|
@ -151,6 +153,7 @@ public:
|
||||||
CHECK_TYPE_TAG(TYPE_SUBNET, "BroType::AsSubNetType");
|
CHECK_TYPE_TAG(TYPE_SUBNET, "BroType::AsSubNetType");
|
||||||
return (const SubNetType*) this;
|
return (const SubNetType*) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
SubNetType* AsSubNetType()
|
SubNetType* AsSubNetType()
|
||||||
{
|
{
|
||||||
CHECK_TYPE_TAG(TYPE_SUBNET, "BroType::AsSubNetType");
|
CHECK_TYPE_TAG(TYPE_SUBNET, "BroType::AsSubNetType");
|
||||||
|
@ -192,6 +195,18 @@ public:
|
||||||
return (VectorType*) this;
|
return (VectorType*) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TypeType* AsTypeType() const
|
||||||
|
{
|
||||||
|
CHECK_TYPE_TAG(TYPE_TYPE, "BroType::AsTypeType");
|
||||||
|
return (TypeType*) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeType* AsTypeType()
|
||||||
|
{
|
||||||
|
CHECK_TYPE_TAG(TYPE_TYPE, "BroType::AsTypeType");
|
||||||
|
return (TypeType*) this;
|
||||||
|
}
|
||||||
|
|
||||||
int IsSet() const
|
int IsSet() const
|
||||||
{
|
{
|
||||||
return tag == TYPE_TABLE && (YieldType() == 0);
|
return tag == TYPE_TABLE && (YieldType() == 0);
|
||||||
|
@ -359,6 +374,19 @@ protected:
|
||||||
ID* return_value;
|
ID* return_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TypeType : public BroType {
|
||||||
|
public:
|
||||||
|
TypeType(BroType* t) : BroType(TYPE_TYPE) { type = t->Ref(); }
|
||||||
|
~TypeType() { Unref(type); }
|
||||||
|
|
||||||
|
BroType* Type() { return type; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
TypeType() {}
|
||||||
|
|
||||||
|
BroType* type;
|
||||||
|
};
|
||||||
|
|
||||||
class TypeDecl {
|
class TypeDecl {
|
||||||
public:
|
public:
|
||||||
TypeDecl(BroType* t, const char* i, attr_list* attrs = 0);
|
TypeDecl(BroType* t, const char* i, attr_list* attrs = 0);
|
||||||
|
|
56
src/Val.cc
56
src/Val.cc
|
@ -2892,6 +2892,62 @@ Val* RecordVal::Lookup(int field) const
|
||||||
return (*AsRecord())[field];
|
return (*AsRecord())[field];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RecordVal* RecordVal::CoerceTo(const RecordType* t, Val* aggr) const
|
||||||
|
{
|
||||||
|
if ( ! record_promotion_compatible(t->AsRecordType(), Type()->AsRecordType()) )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ( ! aggr )
|
||||||
|
aggr = new RecordVal(const_cast<RecordType*>(t->AsRecordType()));
|
||||||
|
|
||||||
|
RecordVal* ar = aggr->AsRecordVal();
|
||||||
|
RecordType* ar_t = aggr->Type()->AsRecordType();
|
||||||
|
|
||||||
|
const RecordType* rv_t = Type()->AsRecordType();
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for ( i = 0; i < rv_t->NumFields(); ++i )
|
||||||
|
{
|
||||||
|
int t_i = ar_t->FieldOffset(rv_t->FieldName(i));
|
||||||
|
|
||||||
|
if ( t_i < 0 )
|
||||||
|
{
|
||||||
|
char buf[512];
|
||||||
|
safe_snprintf(buf, sizeof(buf),
|
||||||
|
"orphan field \"%s\" in initialization",
|
||||||
|
rv_t->FieldName(i));
|
||||||
|
Error(buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
ar->Assign(t_i, Lookup(i)->Ref());
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( i = 0; i < ar_t->NumFields(); ++i )
|
||||||
|
if ( ! ar->Lookup(i) &&
|
||||||
|
! ar_t->FieldDecl(i)->FindAttr(ATTR_OPTIONAL) )
|
||||||
|
{
|
||||||
|
char buf[512];
|
||||||
|
safe_snprintf(buf, sizeof(buf),
|
||||||
|
"non-optional field \"%s\" missing in initialization", ar_t->FieldName(i));
|
||||||
|
Error(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ar;
|
||||||
|
}
|
||||||
|
|
||||||
|
RecordVal* RecordVal::CoerceTo(RecordType* t)
|
||||||
|
{
|
||||||
|
if ( same_type(Type(), t) )
|
||||||
|
{
|
||||||
|
this->Ref();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CoerceTo(t, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void RecordVal::Describe(ODesc* d) const
|
void RecordVal::Describe(ODesc* d) const
|
||||||
{
|
{
|
||||||
const val_list* vl = AsRecord();
|
const val_list* vl = AsRecord();
|
||||||
|
|
26
src/Val.h
26
src/Val.h
|
@ -39,6 +39,7 @@ class TableVal;
|
||||||
class RecordVal;
|
class RecordVal;
|
||||||
class ListVal;
|
class ListVal;
|
||||||
class StringVal;
|
class StringVal;
|
||||||
|
class EnumVal;
|
||||||
class MutableVal;
|
class MutableVal;
|
||||||
|
|
||||||
class StateAccess;
|
class StateAccess;
|
||||||
|
@ -163,6 +164,15 @@ public:
|
||||||
// class has ref'd it.
|
// class has ref'd it.
|
||||||
Val(BroFile* f);
|
Val(BroFile* f);
|
||||||
|
|
||||||
|
Val(BroType* t, bool type_type) // Extra arg to differentiate from protected version.
|
||||||
|
{
|
||||||
|
type = new TypeType(t->Ref());
|
||||||
|
attribs = 0;
|
||||||
|
#ifdef DEBUG
|
||||||
|
bound_id = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
Val()
|
Val()
|
||||||
{
|
{
|
||||||
val.int_val = 0;
|
val.int_val = 0;
|
||||||
|
@ -245,6 +255,12 @@ public:
|
||||||
return &val.subnet_val;
|
return &val.subnet_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const BroType* AsType() const
|
||||||
|
{
|
||||||
|
CHECK_TAG(type->Tag(), TYPE_TYPE, "Val::Type", type_name)
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
// ... in network byte order
|
// ... in network byte order
|
||||||
const addr_type AsAddr() const
|
const addr_type AsAddr() const
|
||||||
{
|
{
|
||||||
|
@ -295,6 +311,7 @@ public:
|
||||||
CONVERTER(TYPE_LIST, ListVal*, AsListVal)
|
CONVERTER(TYPE_LIST, ListVal*, AsListVal)
|
||||||
CONVERTER(TYPE_STRING, StringVal*, AsStringVal)
|
CONVERTER(TYPE_STRING, StringVal*, AsStringVal)
|
||||||
CONVERTER(TYPE_VECTOR, VectorVal*, AsVectorVal)
|
CONVERTER(TYPE_VECTOR, VectorVal*, AsVectorVal)
|
||||||
|
CONVERTER(TYPE_ENUM, EnumVal*, AsEnumVal)
|
||||||
|
|
||||||
#define CONST_CONVERTER(tag, ctype, name) \
|
#define CONST_CONVERTER(tag, ctype, name) \
|
||||||
const ctype name() const \
|
const ctype name() const \
|
||||||
|
@ -921,6 +938,15 @@ public:
|
||||||
void SetOrigin(BroObj* o) { origin = o; }
|
void SetOrigin(BroObj* o) { origin = o; }
|
||||||
BroObj* GetOrigin() const { return origin; }
|
BroObj* GetOrigin() const { return origin; }
|
||||||
|
|
||||||
|
// Returns a new value representing the value coerced to the given type.
|
||||||
|
// If coercion is not possible, returns 0. The non-const version may
|
||||||
|
// return the current value ref'ed if its type matches directly.
|
||||||
|
//
|
||||||
|
// *aggr* is optional; if non-zero, we add to it. See Expr::InitVal(). We
|
||||||
|
// leave it out in the non-const version to make the choice unambigious.
|
||||||
|
RecordVal* CoerceTo(const RecordType* other, Val* aggr) const;
|
||||||
|
RecordVal* CoerceTo(RecordType* other);
|
||||||
|
|
||||||
unsigned int MemoryAllocation() const;
|
unsigned int MemoryAllocation() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue