mirror of
https://github.com/zeek/zeek.git
synced 2025-10-06 00:28:21 +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;
|
||||
|
||||
if ( id->AsType() )
|
||||
RunTime("cannot evaluate type name");
|
||||
return new Val(id->AsType(), true);
|
||||
|
||||
if ( id->IsGlobal() )
|
||||
v = id->ID_Val();
|
||||
|
@ -3309,48 +3309,12 @@ RecordConstructorExpr::RecordConstructorExpr(ListExpr* constructor_list)
|
|||
|
||||
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();
|
||||
RecordType* rv_t = rv->Type()->AsRecordType();
|
||||
RecordVal* ar = rv->CoerceTo(t->AsRecordType(), aggr);
|
||||
|
||||
int i;
|
||||
for ( i = 0; i < rv_t->NumFields(); ++i )
|
||||
if ( ar )
|
||||
{
|
||||
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);
|
||||
|
||||
return ar;
|
||||
}
|
||||
|
||||
|
|
|
@ -95,6 +95,7 @@ BroType::BroType(TypeTag t, bool arg_base_type)
|
|||
case TYPE_FUNC:
|
||||
case TYPE_FILE:
|
||||
case TYPE_VECTOR:
|
||||
case TYPE_TYPE:
|
||||
internal_tag = TYPE_INTERNAL_OTHER;
|
||||
break;
|
||||
|
||||
|
@ -1426,6 +1427,9 @@ int same_type(const BroType* t1, const BroType* t2, int is_init)
|
|||
case TYPE_FILE:
|
||||
return same_type(t1->YieldType(), t2->YieldType(), is_init);
|
||||
|
||||
case TYPE_TYPE:
|
||||
return same_type(t1, t2, is_init);
|
||||
|
||||
case TYPE_UNION:
|
||||
error("union type in same_type()");
|
||||
}
|
||||
|
@ -1514,6 +1518,7 @@ int is_assignable(BroType* t)
|
|||
case TYPE_VECTOR:
|
||||
case TYPE_FILE:
|
||||
case TYPE_TABLE:
|
||||
case TYPE_TYPE:
|
||||
return 1;
|
||||
|
||||
case TYPE_VOID:
|
||||
|
|
28
src/Type.h
28
src/Type.h
|
@ -31,6 +31,7 @@ typedef enum {
|
|||
TYPE_FUNC,
|
||||
TYPE_FILE,
|
||||
TYPE_VECTOR,
|
||||
TYPE_TYPE,
|
||||
TYPE_ERROR
|
||||
#define NUM_TYPES (int(TYPE_ERROR) + 1)
|
||||
} TypeTag;
|
||||
|
@ -59,6 +60,7 @@ class ListExpr;
|
|||
class EnumType;
|
||||
class Serializer;
|
||||
class VectorType;
|
||||
class TypeType;
|
||||
|
||||
const int DOES_NOT_MATCH_INDEX = 0;
|
||||
const int MATCHES_INDEX_SCALAR = 1;
|
||||
|
@ -151,6 +153,7 @@ public:
|
|||
CHECK_TYPE_TAG(TYPE_SUBNET, "BroType::AsSubNetType");
|
||||
return (const SubNetType*) this;
|
||||
}
|
||||
|
||||
SubNetType* AsSubNetType()
|
||||
{
|
||||
CHECK_TYPE_TAG(TYPE_SUBNET, "BroType::AsSubNetType");
|
||||
|
@ -192,6 +195,18 @@ public:
|
|||
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
|
||||
{
|
||||
return tag == TYPE_TABLE && (YieldType() == 0);
|
||||
|
@ -359,6 +374,19 @@ protected:
|
|||
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 {
|
||||
public:
|
||||
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];
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
const val_list* vl = AsRecord();
|
||||
|
|
26
src/Val.h
26
src/Val.h
|
@ -39,6 +39,7 @@ class TableVal;
|
|||
class RecordVal;
|
||||
class ListVal;
|
||||
class StringVal;
|
||||
class EnumVal;
|
||||
class MutableVal;
|
||||
|
||||
class StateAccess;
|
||||
|
@ -163,6 +164,15 @@ public:
|
|||
// class has ref'd it.
|
||||
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.int_val = 0;
|
||||
|
@ -245,6 +255,12 @@ public:
|
|||
return &val.subnet_val;
|
||||
}
|
||||
|
||||
const BroType* AsType() const
|
||||
{
|
||||
CHECK_TAG(type->Tag(), TYPE_TYPE, "Val::Type", type_name)
|
||||
return type;
|
||||
}
|
||||
|
||||
// ... in network byte order
|
||||
const addr_type AsAddr() const
|
||||
{
|
||||
|
@ -295,6 +311,7 @@ public:
|
|||
CONVERTER(TYPE_LIST, ListVal*, AsListVal)
|
||||
CONVERTER(TYPE_STRING, StringVal*, AsStringVal)
|
||||
CONVERTER(TYPE_VECTOR, VectorVal*, AsVectorVal)
|
||||
CONVERTER(TYPE_ENUM, EnumVal*, AsEnumVal)
|
||||
|
||||
#define CONST_CONVERTER(tag, ctype, name) \
|
||||
const ctype name() const \
|
||||
|
@ -921,6 +938,15 @@ public:
|
|||
void SetOrigin(BroObj* o) { origin = o; }
|
||||
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;
|
||||
|
||||
protected:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue