diff --git a/src/Expr.cc b/src/Expr.cc index 06fcf448e1..5f79d08dbe 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -23,7 +23,7 @@ const char* expr_name(BroExprTag t) static const char* expr_names[int(NUM_EXPRS)] = { "name", "const", "(*)", - "++", "--", "!", "+", "-", + "++", "--", "!", "~", "+", "-", "+", "-", "+=", "-=", "*", "/", "%", "&", "|", "^", "&&", "||", @@ -706,6 +706,12 @@ Val* BinaryExpr::Fold(Val* v1, Val* v2) const else \ Internal("bad type in BinaryExpr::Fold"); +#define DO_UINT_FOLD(op) \ + if ( is_unsigned ) \ + u3 = u1 op u2; \ + else \ + Internal("bad type in BinaryExpr::Fold"); + #define DO_FOLD(op) \ if ( is_integral ) \ i3 = i1 op i2; \ @@ -779,6 +785,10 @@ Val* BinaryExpr::Fold(Val* v1, Val* v2) const break; + case EXPR_AND: DO_UINT_FOLD(&); break; + case EXPR_OR: DO_UINT_FOLD(|); break; + case EXPR_XOR: DO_UINT_FOLD(^); break; + case EXPR_AND_AND: DO_INT_FOLD(&&); break; case EXPR_OR_OR: DO_INT_FOLD(||); break; @@ -1081,6 +1091,39 @@ bool IncrExpr::DoUnserialize(UnserialInfo* info) return true; } +ComplementExpr::ComplementExpr(Expr* arg_op) : UnaryExpr(EXPR_COMPLEMENT, arg_op) + { + if ( IsError() ) + return; + + BroType* t = op->Type(); + TypeTag bt = t->Tag(); + + if ( bt != TYPE_COUNT ) + ExprError("requires \"count\" operand"); + else + SetType(base_type(TYPE_COUNT)); + } + +Val* ComplementExpr::Fold(Val* v) const + { + return new Val(~ v->InternalUnsigned(), type->Tag()); + } + +IMPLEMENT_SERIAL(ComplementExpr, SER_COMPLEMENT_EXPR); + +bool ComplementExpr::DoSerialize(SerialInfo* info) const + { + DO_SERIALIZE(SER_COMPLEMENT_EXPR, UnaryExpr); + return true; + } + +bool ComplementExpr::DoUnserialize(UnserialInfo* info) + { + DO_UNSERIALIZE(UnaryExpr); + return true; + } + NotExpr::NotExpr(Expr* arg_op) : UnaryExpr(EXPR_NOT, arg_op) { if ( IsError() ) @@ -1817,6 +1860,46 @@ bool BoolExpr::DoUnserialize(UnserialInfo* info) return true; } +BitExpr::BitExpr(BroExprTag arg_tag, Expr* arg_op1, Expr* arg_op2) +: BinaryExpr(arg_tag, arg_op1, arg_op2) + { + if ( IsError() ) + return; + + TypeTag bt1 = op1->Type()->Tag(); + if ( IsVector(bt1) ) + bt1 = op1->Type()->AsVectorType()->YieldType()->Tag(); + + TypeTag bt2 = op2->Type()->Tag(); + if ( IsVector(bt2) ) + bt2 = op2->Type()->AsVectorType()->YieldType()->Tag(); + + if ( bt1 == TYPE_COUNT && bt2 == bt1 ) + { + if ( is_vector(op1) || is_vector(op2) ) + SetType(new VectorType(base_type(bt1))); + else + SetType(base_type(bt1)); + } + + else + ExprError("requires \"count\" operands"); + } + +IMPLEMENT_SERIAL(BitExpr, SER_BIT_EXPR); + +bool BitExpr::DoSerialize(SerialInfo* info) const + { + DO_SERIALIZE(SER_BIT_EXPR, BinaryExpr); + return true; + } + +bool BitExpr::DoUnserialize(UnserialInfo* info) + { + DO_UNSERIALIZE(BinaryExpr); + return true; + } + EqExpr::EqExpr(BroExprTag arg_tag, Expr* arg_op1, Expr* arg_op2) : BinaryExpr(arg_tag, arg_op1, arg_op2) { diff --git a/src/Expr.h b/src/Expr.h index 89d44c1cb4..8e8b6cc96b 100644 --- a/src/Expr.h +++ b/src/Expr.h @@ -17,7 +17,9 @@ typedef enum { EXPR_ANY = -1, EXPR_NAME, EXPR_CONST, EXPR_CLONE, - EXPR_INCR, EXPR_DECR, EXPR_NOT, EXPR_POSITIVE, EXPR_NEGATE, + EXPR_INCR, EXPR_DECR, + EXPR_NOT, EXPR_COMPLEMENT, + EXPR_POSITIVE, EXPR_NEGATE, EXPR_ADD, EXPR_SUB, EXPR_ADD_TO, EXPR_REMOVE_FROM, EXPR_TIMES, EXPR_DIVIDE, EXPR_MOD, EXPR_AND, EXPR_OR, EXPR_XOR, @@ -378,6 +380,19 @@ protected: DECLARE_SERIAL(IncrExpr); }; +class ComplementExpr : public UnaryExpr { +public: + explicit ComplementExpr(Expr* op); + +protected: + friend class Expr; + ComplementExpr() { } + + Val* Fold(Val* v) const override; + + DECLARE_SERIAL(ComplementExpr); +}; + class NotExpr : public UnaryExpr { public: explicit NotExpr(Expr* op); @@ -531,6 +546,17 @@ protected: DECLARE_SERIAL(BoolExpr); }; +class BitExpr : public BinaryExpr { +public: + BitExpr(BroExprTag tag, Expr* op1, Expr* op2); + +protected: + friend class Expr; + BitExpr() { } + + DECLARE_SERIAL(BitExpr); +}; + class EqExpr : public BinaryExpr { public: EqExpr(BroExprTag tag, Expr* op1, Expr* op2); diff --git a/src/SerialObj.h b/src/SerialObj.h index 77dc28aefd..b502414f71 100644 --- a/src/SerialObj.h +++ b/src/SerialObj.h @@ -3,7 +3,7 @@ // How to make objects of class Foo serializable: // // 1. Derive Foo (directly or indirectly) from SerialObj. -// 2. Add a SER_FOO constant to SerialTypes below. +// 2. Add a SER_FOO constant to SerialTypes in SerialTypes.h. // 3. Add DECLARE_SERIAL(Foo) into class definition. // 4. Add a (preferably protected) default ctor if it doesn't already exist. // 5. For non-abstract classes, add IMPLEMENT_SERIAL(Foo, SER_FOO) to *.cc diff --git a/src/SerialTypes.h b/src/SerialTypes.h index 8a1a2abf51..c5b25d32fb 100644 --- a/src/SerialTypes.h +++ b/src/SerialTypes.h @@ -162,6 +162,8 @@ SERIAL_EXPR(SET_CONSTRUCTOR_EXPR, 41) SERIAL_EXPR(VECTOR_CONSTRUCTOR_EXPR, 42) SERIAL_EXPR(TABLE_COERCE_EXPR, 43) SERIAL_EXPR(VECTOR_COERCE_EXPR, 44) +SERIAL_EXPR(BIT_EXPR, 45) +SERIAL_EXPR(COMPLEMENT_EXPR, 46) #define SERIAL_STMT(name, val) SERIAL_CONST(name, val, STMT) SERIAL_STMT(STMT, 1) diff --git a/src/parse.y b/src/parse.y index 90d4c71309..6f7a43ae7f 100644 --- a/src/parse.y +++ b/src/parse.y @@ -31,7 +31,7 @@ %token TOK_NO_TEST -%left ',' '|' +%left ',' %right '=' TOK_ADD_TO TOK_REMOVE_FROM %right '?' ':' %left TOK_OR_OR @@ -39,10 +39,13 @@ %nonassoc TOK_HOOK %nonassoc '<' '>' TOK_LE TOK_GE TOK_EQ TOK_NE %left TOK_IN TOK_NOT_IN +%left '|' +%left '^' +%left '&' %left '+' '-' %left '*' '/' '%' %left TOK_INCR TOK_DECR -%right '!' +%right '!' '~' %left '$' '[' ']' '(' ')' TOK_HAS_FIELD TOK_HAS_ATTR %type opt_no_test opt_no_test_block opt_deprecated @@ -334,6 +337,12 @@ expr: $$ = new NotExpr($2); } + | '~' expr + { + set_location(@1, @2); + $$ = new ComplementExpr($2); + } + | '-' expr %prec '!' { set_location(@1, @2); @@ -388,6 +397,24 @@ expr: $$ = new ModExpr($1, $3); } + | expr '&' expr + { + set_location(@1, @3); + $$ = new BitExpr(EXPR_AND, $1, $3); + } + + | expr '|' expr + { + set_location(@1, @3); + $$ = new BitExpr(EXPR_OR, $1, $3); + } + + | expr '^' expr + { + set_location(@1, @3); + $$ = new BitExpr(EXPR_XOR, $1, $3); + } + | expr TOK_AND_AND expr { set_location(@1, @3); @@ -700,7 +727,7 @@ expr: $$ = new ConstExpr(new PatternVal($1)); } - | '|' expr '|' + | '|' expr '|' %prec '(' { set_location(@1, @3); $$ = new SizeExpr($2);