Branch data Line data Source code
1 : : // $Id: Expr.cc 6864 2009-08-16 23:30:39Z vern $
2 : : //
3 : : // See the file "COPYING" in the main distribution directory for copyright.
4 : :
5 : : #include "config.h"
6 : :
7 : : #include "Expr.h"
8 : : #include "Event.h"
9 : : #include "Frame.h"
10 : : #include "Func.h"
11 : : #include "RE.h"
12 : : #include "Scope.h"
13 : : #include "Stmt.h"
14 : : #include "EventRegistry.h"
15 : : #include "RemoteSerializer.h"
16 : : #include "Net.h"
17 : : #include "Traverse.h"
18 : : #include "Trigger.h"
19 : :
20 : 0 : const char* expr_name(BroExprTag t)
21 : : {
22 : : static char errbuf[512];
23 : :
24 : : static const char* expr_names[int(NUM_EXPRS)] = {
25 : : "name", "const",
26 : : "(*)",
27 : : "++", "--", "!", "+", "-",
28 : : "+", "-", "+=", "-=", "*", "/", "%", "&&", "||",
29 : : "<", "<=", "==", "!=", ">=", ">", "?:", "ref",
30 : : "=", "~", "[]", "$", "?$", "[=]",
31 : : "table()", "set()", "vector()",
32 : : "$=", "in", "<<>>",
33 : : "()", "event", "schedule",
34 : : "coerce", "record_coerce", "table_coerce",
35 : : "sizeof", "flatten"
36 : : };
37 : :
38 [ # # ]: 0 : if ( int(t) >= NUM_EXPRS )
39 : : {
40 : : static char errbuf[512];
41 : :
42 : : // This isn't quite right - we return a static buffer,
43 : : // so multiple calls to expr_name() could lead to confusion
44 : : // by overwriting the buffer. But oh well.
45 : : snprintf(errbuf, sizeof(errbuf),
46 : 0 : "%d: not an expression tag", int(t));
47 : 0 : return errbuf;
48 : : }
49 : :
50 : 0 : return expr_names[int(t)];
51 : : }
52 : :
53 : 57429 : Expr::Expr(BroExprTag arg_tag)
54 : : {
55 : 57429 : tag = arg_tag;
56 : 57429 : type = 0;
57 : 57429 : paren = 0;
58 : :
59 : 57429 : SetLocationInfo(&start_location, &end_location);
60 : 57429 : }
61 : :
62 : 13 : Expr::~Expr()
63 : : {
64 : 13 : Unref(type);
65 [ # # ][ # # ]: 13 : }
[ - + ]
66 : :
67 : 0 : int Expr::CanAdd() const
68 : : {
69 : 0 : return 0;
70 : : }
71 : :
72 : 0 : int Expr::CanDel() const
73 : : {
74 : 0 : return 0;
75 : : }
76 : :
77 : 0 : void Expr::Add(Frame* /* f */)
78 : : {
79 : 0 : Internal("Expr::Delete called");
80 : 0 : }
81 : :
82 : 0 : void Expr::Delete(Frame* /* f */)
83 : : {
84 : 0 : Internal("Expr::Delete called");
85 : 0 : }
86 : :
87 : 0 : Expr* Expr::MakeLvalue()
88 : : {
89 [ # # ]: 0 : if ( ! IsError() )
90 : 0 : ExprError("can't be assigned to");
91 : 0 : return this;
92 : : }
93 : :
94 : : void Expr::EvalIntoAggregate(const BroType* /* t */, Val* /* aggr */,
95 : 0 : Frame* /* f */) const
96 : : {
97 : 0 : Internal("Expr::EvalIntoAggregate called");
98 : 0 : }
99 : :
100 : 0 : void Expr::Assign(Frame* /* f */, Val* /* v */, Opcode /* op */)
101 : : {
102 : 0 : Internal("Expr::Assign called");
103 : 0 : }
104 : :
105 : 2748 : BroType* Expr::InitType() const
106 : : {
107 : 2748 : return type->Ref();
108 : : }
109 : :
110 : 123 : int Expr::IsRecordElement(TypeDecl* /* td */) const
111 : : {
112 : 123 : return 0;
113 : : }
114 : :
115 : 0 : int Expr::IsPure() const
116 : : {
117 : 0 : return 1;
118 : : }
119 : :
120 : 5065 : Val* Expr::InitVal(const BroType* t, Val* aggr) const
121 : : {
122 [ - + ]: 5065 : if ( aggr )
123 : : {
124 : 0 : Error("bad initializer");
125 : 0 : return 0;
126 : : }
127 : :
128 [ - + ]: 5065 : if ( IsError() )
129 : 0 : return 0;
130 : :
131 : 5065 : return check_and_promote(Eval(0), t, 1);
132 : : }
133 : :
134 : 0 : void Expr::SetError(const char* msg)
135 : : {
136 : 0 : Error(msg);
137 : 0 : SetError();
138 : 0 : }
139 : :
140 : 0 : void Expr::Describe(ODesc* d) const
141 : : {
142 [ # # ][ # # ]: 0 : if ( IsParen() && ! d->IsBinary() )
[ # # ]
143 : 0 : d->Add("(");
144 : :
145 [ # # ][ # # ]: 0 : if ( d->IsPortable() || d->IsBinary() )
[ # # ]
146 : 0 : AddTag(d);
147 : :
148 : 0 : ExprDescribe(d);
149 : :
150 [ # # # # ]: 0 : if ( IsParen() && ! d->IsBinary() )
[ # # ]
151 : 0 : d->Add(")");
152 : 0 : }
153 : :
154 : 0 : void Expr::AddTag(ODesc* d) const
155 : : {
156 [ # # ]: 0 : if ( d->IsBinary() )
157 : 0 : d->Add(int(Tag()));
158 : : else
159 : 0 : d->AddSP(expr_name(Tag()));
160 : 0 : }
161 : :
162 : 0 : void Expr::Canonicize()
163 : : {
164 : 0 : }
165 : :
166 : 57304 : void Expr::SetType(BroType* t)
167 : : {
168 [ - + ][ # # ]: 57304 : if ( ! type || type->Tag() != TYPE_ERROR )
[ + - ]
169 : : {
170 : 57304 : Unref(type);
171 : 57304 : type = t;
172 : : }
173 : : else
174 : 0 : Unref(t);
175 : 57304 : }
176 : :
177 : 0 : void Expr::ExprError(const char msg[])
178 : : {
179 : 0 : Error(msg);
180 : 0 : SetError();
181 : 0 : }
182 : :
183 : 8 : bool Expr::Serialize(SerialInfo* info) const
184 : : {
185 : 8 : return SerialObj::Serialize(info);
186 : : }
187 : :
188 : 0 : Expr* Expr::Unserialize(UnserialInfo* info, BroExprTag want)
189 : : {
190 : 0 : Expr* e = (Expr*) SerialObj::Unserialize(info, SER_EXPR);
191 : :
192 [ # # ]: 0 : if ( ! e )
193 : 0 : return 0;
194 : :
195 [ # # ][ # # ]: 0 : if ( want != EXPR_ANY && e->tag != want )
196 : : {
197 : 0 : info->s->Error("wrong expression type");
198 : 0 : Unref(e);
199 : 0 : return 0;
200 : : }
201 : :
202 : 0 : return e;
203 : : }
204 : :
205 : 7 : bool Expr::DoSerialize(SerialInfo* info) const
206 : : {
207 [ - + ][ - + ]: 7 : DO_SERIALIZE(SER_EXPR, BroObj);
208 : :
209 [ + - ][ - + ]: 7 : if ( ! (SERIALIZE(char(tag)) && SERIALIZE(paren)) )
[ - + ]
210 : 0 : return false;
211 : :
212 [ + - ][ + - ]: 7 : SERIALIZE_OPTIONAL(type);
[ - + ][ - + ]
[ - + ][ # # ]
213 : 7 : return true;
214 : : }
215 : :
216 : 0 : bool Expr::DoUnserialize(UnserialInfo* info)
217 : : {
218 [ # # ]: 0 : DO_UNSERIALIZE(BroObj);
219 : :
220 : : char c;
221 [ # # ][ # # ]: 0 : if ( ! (UNSERIALIZE(&c) && UNSERIALIZE(&paren)) )
[ # # ]
222 : 0 : return 0;
223 : :
224 : 0 : tag = BroExprTag(c);
225 : :
226 [ # # ][ # # ]: 0 : UNSERIALIZE_OPTIONAL(type, BroType::Unserialize(info));
[ # # ]
227 : 0 : return true;
228 : : }
229 : :
230 : :
231 : 19039 : NameExpr::NameExpr(ID* arg_id) : Expr(EXPR_NAME)
232 : : {
233 : 19039 : id = arg_id;
234 : 19039 : ReferenceID();
235 : 19039 : SetType(id->Type()->Ref());
236 : :
237 : 19039 : EventHandler* h = event_registry->Lookup(id->Name());
238 [ + + # # ]: 19039 : if ( h )
239 : 5 : h->SetUsed();
240 : 19039 : }
241 : :
242 : 3 : NameExpr::~NameExpr()
243 : : {
244 : 3 : Unref(id);
245 [ + - ][ # # ]: 3 : }
[ # # ]
246 : :
247 : 19039 : void NameExpr::ReferenceID()
248 : : {
249 : : // ### This is a hack. We check whether one of the remote serializer's
250 : : // built-in functions is referenced. If so, we activate the serializer.
251 : : // A better solution would be to either (1) a generic mechanism in
252 : : // which have (internal) attributes associated with identifiers and
253 : : // as we see references to the identifiers, we do bookkeeping
254 : : // associated with their attribute (so in this case the attribute
255 : : // would be "flag that inter-Bro communication is being used"),
256 : : // or (2) after the parse is done, we'd query whether these
257 : : // particular identifiers were seen, rather than doing the test
258 : : // here for every NameExpr we create.
259 [ + + ]: 19039 : if ( id->Type()->Tag() == TYPE_FUNC )
260 : : {
261 : 3499 : const char* const* builtins = remote_serializer->GetBuiltins();
262 [ + + ]: 10497 : while( *builtins )
263 : : {
264 [ + + ]: 6998 : if ( streq(id->Name(), *builtins++) )
265 : 3 : using_communication = true;
266 : : }
267 : : }
268 : 19039 : }
269 : :
270 : 0 : Expr* NameExpr::Simplify(SimplifyType simp_type)
271 : : {
272 [ # # ][ # # ]: 0 : if ( simp_type != SIMPLIFY_LHS && id->IsConst() )
[ # # ]
273 : : {
274 : 0 : Val* v = Eval(0);
275 [ # # ]: 0 : if ( v )
276 : 0 : return new ConstExpr(v);
277 : : }
278 : :
279 : 0 : return this;
280 : : }
281 : :
282 : 1103055 : Val* NameExpr::Eval(Frame* f) const
283 : : {
284 : : Val* v;
285 : :
286 [ - + ]: 1103055 : if ( id->AsType() )
287 : 0 : RunTime("cannot evaluate type name");
288 : :
289 [ + + ]: 1103055 : if ( id->IsGlobal() )
290 : 333801 : v = id->ID_Val();
291 : :
292 [ + + ]: 769254 : else if ( f )
293 : 769252 : v = f->NthElement(id->Offset());
294 : :
295 : : else
296 : : // No frame - evaluating for Simplify() purposes
297 : 2 : return 0;
298 : :
299 [ + - ]: 1103053 : if ( v )
300 : 1103053 : return v->Ref();
301 : : else
302 : : {
303 : 0 : RunTime("value used but not set");
304 : 1103055 : return 0;
305 : : }
306 : : }
307 : :
308 : 1662 : Expr* NameExpr::MakeLvalue()
309 : : {
310 [ - + ]: 1662 : if ( id->AsType() )
311 : 0 : ExprError("Type name is not an lvalue");
312 : :
313 : 1662 : return new RefExpr(this);
314 : : }
315 : :
316 : 194107 : void NameExpr::Assign(Frame* f, Val* v, Opcode op)
317 : : {
318 [ + + ]: 194107 : if ( id->IsGlobal() )
319 : 1847 : id->SetVal(v, op);
320 : : else
321 : 192260 : f->SetElement(id->Offset(), v);
322 : 194107 : }
323 : :
324 : 1058 : int NameExpr::IsPure() const
325 : : {
326 : 1058 : return id->IsConst();
327 : : }
328 : :
329 : 0 : TraversalCode NameExpr::Traverse(TraversalCallback* cb) const
330 : : {
331 : 0 : TraversalCode tc = cb->PreExpr(this);
332 [ # # ]: 0 : HANDLE_TC_EXPR_PRE(tc);
333 : :
334 : 0 : tc = id->Traverse(cb);
335 [ # # ]: 0 : HANDLE_TC_EXPR_PRE(tc);
336 : :
337 : 0 : tc = cb->PostExpr(this);
338 : 0 : HANDLE_TC_EXPR_POST(tc);
339 : : }
340 : :
341 : :
342 : 0 : void NameExpr::ExprDescribe(ODesc* d) const
343 : : {
344 [ # # ]: 0 : if ( d->IsReadable() )
345 : 0 : d->Add(id->Name());
346 : : else
347 : : {
348 [ # # ]: 0 : if ( d->IsPortable() )
349 : 0 : d->Add(id->Name());
350 : : else
351 : 0 : d->AddCS(id->Name());
352 : : }
353 : 0 : }
354 : :
355 : 5 : IMPLEMENT_SERIAL(NameExpr, SER_NAME_EXPR);
356 : :
357 : 1 : bool NameExpr::DoSerialize(SerialInfo* info) const
358 : : {
359 [ + - ][ - + ]: 1 : DO_SERIALIZE(SER_NAME_EXPR, Expr);
360 : :
361 : : // Write out just the name of the function if requested.
362 [ + - ][ + - ]: 1 : if ( info->globals_as_names && id->IsGlobal() )
[ + - ]
363 [ + - ][ + - ]: 1 : return SERIALIZE('n') && SERIALIZE(id->Name());
364 : : else
365 [ # # ][ # # ]: 1 : return SERIALIZE('f') && id->Serialize(info);
366 : : }
367 : :
368 : 0 : bool NameExpr::DoUnserialize(UnserialInfo* info)
369 : : {
370 [ # # ]: 0 : DO_UNSERIALIZE(Expr);
371 : :
372 : : char type;
373 [ # # ]: 0 : if ( ! UNSERIALIZE(&type) )
374 : 0 : return false;
375 : :
376 [ # # ]: 0 : if ( type == 'n' )
377 : : {
378 : : const char* name;
379 [ # # ]: 0 : if ( ! UNSERIALIZE_STR(&name, 0) )
380 : 0 : return false;
381 : :
382 : 0 : id = global_scope()->Lookup(name);
383 [ # # ]: 0 : if ( id )
384 : 0 : ::Ref(id);
385 : : else
386 : 0 : run_time("unserialized unknown global name");
387 : :
388 [ # # ]: 0 : delete [] name;
389 : : }
390 : : else
391 : 0 : id = ID::Unserialize(info);
392 : :
393 [ # # ]: 0 : if ( ! id )
394 : 0 : return false;
395 : :
396 : 0 : ReferenceID();
397 : :
398 : 0 : return true;
399 : : }
400 : :
401 : 9274 : ConstExpr::ConstExpr(Val* arg_val) : Expr(EXPR_CONST)
402 : : {
403 : 9274 : val = arg_val;
404 : :
405 [ - + # # ]: 9274 : if ( val->Type()->Tag() == TYPE_LIST && val->AsListVal()->Length() == 1 )
[ - + # # ]
[ # # ][ # # ]
406 : : {
407 : 0 : val = val->AsListVal()->Index(0);
408 : 0 : val->Ref();
409 : 0 : Unref(arg_val);
410 : : }
411 : :
412 : 9274 : SetType(val->Type()->Ref());
413 : 9274 : }
414 : :
415 : 2 : ConstExpr::~ConstExpr()
416 : : {
417 : 2 : Unref(val);
418 [ + - ][ # # ]: 2 : }
[ # # ]
419 : :
420 : 0 : void ConstExpr::ExprDescribe(ODesc* d) const
421 : : {
422 : 0 : val->Describe(d);
423 : 0 : }
424 : :
425 : 0 : Expr* ConstExpr::Simplify(SimplifyType /* simp_type */)
426 : : {
427 : 0 : return this;
428 : : }
429 : :
430 : 352268 : Val* ConstExpr::Eval(Frame* /* f */) const
431 : : {
432 : 352268 : return Value()->Ref();
433 : : }
434 : :
435 : 0 : TraversalCode ConstExpr::Traverse(TraversalCallback* cb) const
436 : : {
437 : 0 : TraversalCode tc = cb->PreExpr(this);
438 [ # # ]: 0 : HANDLE_TC_EXPR_PRE(tc);
439 : :
440 : 0 : tc = cb->PostExpr(this);
441 : 0 : HANDLE_TC_EXPR_POST(tc);
442 : : }
443 : :
444 : 15 : IMPLEMENT_SERIAL(ConstExpr, SER_CONST_EXPR);
445 : :
446 : 6 : bool ConstExpr::DoSerialize(SerialInfo* info) const
447 : : {
448 [ + - ][ - + ]: 6 : DO_SERIALIZE(SER_CONST_EXPR, Expr);
449 : 6 : return val->Serialize(info);
450 : : }
451 : :
452 : 0 : bool ConstExpr::DoUnserialize(UnserialInfo* info)
453 : : {
454 [ # # ]: 0 : DO_UNSERIALIZE(Expr);
455 : 0 : val = Val::Unserialize(info);
456 : 0 : return val != 0;
457 : : }
458 : :
459 : :
460 : 9535 : UnaryExpr::UnaryExpr(BroExprTag arg_tag, Expr* arg_op) : Expr(arg_tag)
461 : : {
462 : 9535 : op = arg_op;
463 [ # # - + ]: 9535 : if ( op->IsError() )
464 : 0 : SetError();
465 : 9535 : }
466 : :
467 : 0 : UnaryExpr::~UnaryExpr()
468 : : {
469 : 0 : Unref(op);
470 [ # # ][ # # ]: 0 : }
[ # # ]
471 : :
472 : 0 : Expr* UnaryExpr::Simplify(SimplifyType simp_type)
473 : : {
474 [ # # ]: 0 : if ( IsError() )
475 : 0 : return this;
476 : :
477 : 0 : op = simplify_expr(op, simp_type);
478 : 0 : Canonicize();
479 : 0 : return DoSimplify();
480 : : }
481 : :
482 : 272697 : Val* UnaryExpr::Eval(Frame* f) const
483 : : {
484 [ - + ]: 272697 : if ( IsError() )
485 : 0 : return 0;
486 : :
487 : 272697 : Val* v = op->Eval(f);
488 : :
489 [ - + ]: 272697 : if ( ! v )
490 : 0 : return 0;
491 : :
492 [ - + ]: 272697 : if ( is_vector(v) )
493 : : {
494 : 0 : VectorVal* v_op = v->AsVectorVal();
495 : 0 : VectorVal* result = new VectorVal(Type()->AsVectorType());
496 : :
497 [ # # ]: 0 : for ( unsigned int i = VECTOR_MIN;
498 : : i < v_op->Size() + VECTOR_MIN; ++i )
499 : : {
500 : 0 : Val* v_i = v_op->Lookup(i);
501 [ # # ]: 0 : result->Assign(i, v_i ? Fold(v_i) : 0, this);
502 : : }
503 : :
504 : 0 : Unref(v);
505 : 0 : return result;
506 : : }
507 : : else
508 : : {
509 : 272697 : Val* result = Fold(v);
510 : 272697 : Unref(v);
511 : 272697 : return result;
512 : : }
513 : : }
514 : :
515 : 22 : int UnaryExpr::IsPure() const
516 : : {
517 : 22 : return op->IsPure();
518 : : }
519 : :
520 : 0 : TraversalCode UnaryExpr::Traverse(TraversalCallback* cb) const
521 : : {
522 : 0 : TraversalCode tc = cb->PreExpr(this);
523 [ # # ]: 0 : HANDLE_TC_EXPR_PRE(tc);
524 : :
525 : 0 : tc = op->Traverse(cb);
526 [ # # ]: 0 : HANDLE_TC_EXPR_PRE(tc);
527 : :
528 : 0 : tc = cb->PostExpr(this);
529 : 0 : HANDLE_TC_EXPR_POST(tc);
530 : : }
531 : :
532 : 0 : Expr* UnaryExpr::DoSimplify()
533 : : {
534 : 0 : return this;
535 : : }
536 : :
537 : 7955 : Val* UnaryExpr::Fold(Val* v) const
538 : : {
539 : 7955 : return v->Ref();
540 : : }
541 : :
542 : 0 : void UnaryExpr::ExprDescribe(ODesc* d) const
543 : : {
544 : : bool is_coerce =
545 : : Tag() == EXPR_ARITH_COERCE || Tag() == EXPR_RECORD_COERCE ||
546 [ # # ][ # # ]: 0 : Tag() == EXPR_TABLE_COERCE;
[ # # ]
547 : :
548 [ # # ]: 0 : if ( d->IsReadable() )
549 : : {
550 [ # # ]: 0 : if ( is_coerce )
551 : 0 : d->Add("(coerce ");
552 [ # # ]: 0 : else if ( Tag() == EXPR_FLATTEN )
553 : 0 : d->Add("flatten ");
554 [ # # ]: 0 : else if ( Tag() != EXPR_REF )
555 : 0 : d->Add(expr_name(Tag()));
556 : : }
557 : :
558 : 0 : op->Describe(d);
559 : :
560 [ # # # # ]: 0 : if ( d->IsReadable() && is_coerce )
[ # # ]
561 : : {
562 : 0 : d->Add(" to ");
563 : 0 : Type()->Describe(d);
564 : 0 : d->Add(")");
565 : : }
566 : 0 : }
567 : :
568 : 3 : IMPLEMENT_SERIAL(UnaryExpr, SER_UNARY_EXPR);
569 : :
570 : 0 : bool UnaryExpr::DoSerialize(SerialInfo* info) const
571 : : {
572 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_UNARY_EXPR, Expr);
573 : 0 : return op->Serialize(info);
574 : : }
575 : :
576 : 0 : bool UnaryExpr::DoUnserialize(UnserialInfo* info)
577 : : {
578 [ # # ]: 0 : DO_UNSERIALIZE(Expr);
579 : 0 : op = Expr::Unserialize(info);
580 : 0 : return op != 0;
581 : : }
582 : :
583 : 0 : BinaryExpr::~BinaryExpr()
584 : : {
585 : 0 : Unref(op1);
586 : 0 : Unref(op2);
587 [ # # ][ # # ]: 0 : }
[ # # ]
588 : :
589 : 0 : Expr* BinaryExpr::Simplify(SimplifyType /* simp_type */)
590 : : {
591 [ # # ]: 0 : if ( IsError() )
592 : 0 : return this;
593 : :
594 : 0 : SimplifyOps();
595 : :
596 [ # # ]: 0 : if ( BothConst() )
597 : 0 : return new ConstExpr(Fold(op1->ExprVal(), op2->ExprVal()));
598 : : else
599 : 0 : return DoSimplify();
600 : : }
601 : :
602 : 169951 : Val* BinaryExpr::Eval(Frame* f) const
603 : : {
604 [ - + ]: 169951 : if ( IsError() )
605 : 0 : return 0;
606 : :
607 : 169951 : Val* v1 = op1->Eval(f);
608 [ - + ]: 169951 : if ( ! v1 )
609 : 0 : return 0;
610 : :
611 : 169951 : Val* v2 = op2->Eval(f);
612 [ - + ]: 169951 : if ( ! v2 )
613 : : {
614 : 0 : Unref(v1);
615 : 0 : return 0;
616 : : }
617 : :
618 : 169951 : Val* result = 0;
619 : :
620 : 169951 : int is_vec1 = is_vector(v1);
621 : 169951 : int is_vec2 = is_vector(v2);
622 : :
623 [ - + # # ]: 169951 : if ( is_vec1 && is_vec2 )
624 : : { // fold pairs of elements
625 : 0 : VectorVal* v_op1 = v1->AsVectorVal();
626 : 0 : VectorVal* v_op2 = v2->AsVectorVal();
627 : :
628 [ # # ]: 0 : if ( v_op1->Size() != v_op2->Size() )
629 : : {
630 : 0 : RunTime("vector operands are of different sizes");
631 : 0 : return 0;
632 : : }
633 : :
634 : 0 : VectorVal* v_result = new VectorVal(Type()->AsVectorType());
635 : :
636 [ # # ]: 0 : for ( unsigned int i = VECTOR_MIN;
637 : : i < v_op1->Size() + VECTOR_MIN; ++i )
638 : : {
639 [ # # ][ # # ]: 0 : if ( v_op1->Lookup(i) && v_op2->Lookup(i) )
[ # # ]
640 : : v_result->Assign(i,
641 : : Fold(v_op1->Lookup(i),
642 : : v_op2->Lookup(i)),
643 : 0 : this);
644 : : else
645 : 0 : v_result->Assign(i, 0, this);
646 : : // SetError("undefined element in vector operation");
647 : : }
648 : :
649 : 0 : Unref(v1);
650 : 0 : Unref(v2);
651 : 0 : return v_result;
652 : : }
653 : :
654 [ + - ][ - + ]: 169951 : if ( is_vec1 || is_vec2 )
655 : : { // fold vector against scalar
656 [ # # ]: 0 : VectorVal* vv = (is_vec1 ? v1 : v2)->AsVectorVal();
657 : 0 : VectorVal* v_result = new VectorVal(Type()->AsVectorType());
658 : :
659 [ # # ]: 0 : for ( unsigned int i = VECTOR_MIN;
660 : : i < vv->Size() + VECTOR_MIN; ++i )
661 : : {
662 : 0 : Val* vv_i = vv->Lookup(i);
663 [ # # ]: 0 : if ( vv_i )
664 : : v_result->Assign(i,
665 : : is_vec1 ?
666 : : Fold(vv_i, v2) : Fold(v1, vv_i),
667 [ # # ]: 0 : this);
668 : : else
669 : 0 : v_result->Assign(i, 0, this);
670 : :
671 : : // SetError("Undefined element in vector operation");
672 : : }
673 : :
674 : 0 : Unref(v1);
675 : 0 : Unref(v2);
676 : 0 : return v_result;
677 : : }
678 : :
679 : : // scalar op scalar
680 : 169951 : result = Fold(v1, v2);
681 : :
682 : 169951 : Unref(v1);
683 : 169951 : Unref(v2);
684 : 169951 : return result;
685 : : }
686 : :
687 : 31 : int BinaryExpr::IsPure() const
688 : : {
689 [ - + ][ # # ]: 31 : return op1->IsPure() && op2->IsPure();
690 : : }
691 : :
692 : 0 : TraversalCode BinaryExpr::Traverse(TraversalCallback* cb) const
693 : : {
694 : 0 : TraversalCode tc = cb->PreExpr(this);
695 [ # # ]: 0 : HANDLE_TC_EXPR_PRE(tc);
696 : :
697 : 0 : tc = op1->Traverse(cb);
698 [ # # ]: 0 : HANDLE_TC_EXPR_PRE(tc);
699 : :
700 : 0 : tc = op2->Traverse(cb);
701 [ # # ]: 0 : HANDLE_TC_EXPR_PRE(tc);
702 : :
703 : 0 : tc = cb->PostExpr(this);
704 : 0 : HANDLE_TC_EXPR_POST(tc);
705 : : }
706 : :
707 : 0 : Expr* BinaryExpr::DoSimplify()
708 : : {
709 : 0 : return this;
710 : : }
711 : :
712 : 0 : void BinaryExpr::ExprDescribe(ODesc* d) const
713 : : {
714 : 0 : op1->Describe(d);
715 : :
716 : 0 : d->SP();
717 [ # # ]: 0 : if ( d->IsReadable() )
718 : 0 : d->AddSP(expr_name(Tag()));
719 : :
720 : 0 : op2->Describe(d);
721 : 0 : }
722 : :
723 : 0 : void BinaryExpr::SimplifyOps()
724 : : {
725 : 0 : op1 = simplify_expr(op1, SIMPLIFY_GENERAL);
726 : 0 : op2 = simplify_expr(op2, SIMPLIFY_GENERAL);
727 : 0 : Canonicize();
728 : 0 : }
729 : :
730 : 112943 : Val* BinaryExpr::Fold(Val* v1, Val* v2) const
731 : : {
732 : 112943 : InternalTypeTag it = v1->Type()->InternalType();
733 : :
734 [ + + ]: 112943 : if ( it == TYPE_INTERNAL_STRING )
735 : 48973 : return StringFold(v1, v2);
736 : :
737 [ + + ]: 63970 : if ( it == TYPE_INTERNAL_ADDR )
738 : 834 : return AddrFold(v1, v2);
739 : :
740 [ - + ]: 63136 : if ( it == TYPE_INTERNAL_SUBNET )
741 : 0 : return SubNetFold(v1, v2);
742 : :
743 : 63136 : bro_int_t i1 = 0, i2 = 0, i3 = 0;
744 : 63136 : bro_uint_t u1 = 0, u2 = 0, u3 = 0;
745 : 63136 : double d1 = 0.0, d2 = 0.0, d3 = 0.0;
746 : 63136 : int is_integral = 0;
747 : 63136 : int is_unsigned = 0;
748 : :
749 [ + + ]: 63136 : if ( it == TYPE_INTERNAL_INT )
750 : : {
751 : 22394 : i1 = v1->InternalInt();
752 : 22394 : i2 = v2->InternalInt();
753 : 22394 : ++is_integral;
754 : : }
755 [ + + ]: 40742 : else if ( it == TYPE_INTERNAL_UNSIGNED )
756 : : {
757 : 40737 : u1 = v1->InternalUnsigned();
758 : 40737 : u2 = v2->InternalUnsigned();
759 : 40737 : ++is_unsigned;
760 : : }
761 [ + - ]: 5 : else if ( it == TYPE_INTERNAL_DOUBLE )
762 : : {
763 : 5 : d1 = v1->InternalDouble();
764 : 5 : d2 = v2->InternalDouble();
765 : : }
766 : : else
767 : 0 : Internal("bad type in BinaryExpr::Fold");
768 : :
769 [ + - + - + : 63136 : switch ( tag ) {
+ + - - +
+ + + - -
- ]
770 : : #define DO_INT_FOLD(op) \
771 : : if ( is_integral ) \
772 : : i3 = i1 op i2; \
773 : : else if ( is_unsigned ) \
774 : : u3 = u1 op u2; \
775 : : else \
776 : : Internal("bad type in BinaryExpr::Fold");
777 : :
778 : : #define DO_FOLD(op) \
779 : : if ( is_integral ) \
780 : : i3 = i1 op i2; \
781 : : else if ( is_unsigned ) \
782 : : u3 = u1 op u2; \
783 : : else \
784 : : d3 = d1 op d2;
785 : :
786 : : #define DO_INT_VAL_FOLD(op) \
787 : : if ( is_integral ) \
788 : : i3 = i1 op i2; \
789 : : else if ( is_unsigned ) \
790 : : i3 = u1 op u2; \
791 : : else \
792 : : i3 = d1 op d2;
793 : :
794 [ - + ][ + + ]: 67 : case EXPR_ADD: DO_FOLD(+); break;
795 [ # # ][ # # ]: 0 : case EXPR_ADD_TO: DO_FOLD(+); break;
796 [ - + ][ + + ]: 5 : case EXPR_SUB: DO_FOLD(-); break;
797 [ # # ][ # # ]: 0 : case EXPR_REMOVE_FROM: DO_FOLD(-); break;
798 [ - + ][ + - ]: 98 : case EXPR_TIMES: DO_FOLD(*); break;
799 [ - + ][ + + ]: 20 : case EXPR_DIVIDE: DO_FOLD(/); break;
800 : :
801 [ - + ][ + - ]: 18 : case EXPR_MOD: DO_INT_FOLD(%); break;
802 [ # # ][ # # ]: 0 : case EXPR_AND: DO_INT_FOLD(&&); break;
[ # # ][ # # ]
[ # # ][ # # ]
803 [ # # ][ # # ]: 0 : case EXPR_OR: DO_INT_FOLD(||); break;
[ # # ][ # # ]
[ # # ][ # # ]
804 : :
805 [ - + ][ + - ]: 7559 : case EXPR_LT: DO_INT_VAL_FOLD(<); break;
806 [ - + ][ + - ]: 1543 : case EXPR_LE: DO_INT_VAL_FOLD(<=); break;
807 [ + + ][ + - ]: 45525 : case EXPR_EQ: DO_INT_VAL_FOLD(==); break;
808 [ + + ][ + - ]: 8301 : case EXPR_NE: DO_INT_VAL_FOLD(!=); break;
809 [ # # ][ # # ]: 0 : case EXPR_GE: DO_INT_VAL_FOLD(>=); break;
810 [ # # ][ # # ]: 0 : case EXPR_GT: DO_INT_VAL_FOLD(>); break;
811 : :
812 : : default:
813 : 0 : BadTag("BinaryExpr::Fold", expr_name(tag));
814 : : }
815 : :
816 : 63136 : BroType* ret_type = type;
817 [ - + ]: 63136 : if ( IsVector(ret_type->Tag()) )
818 : 0 : ret_type = ret_type->YieldType();
819 : :
820 [ + + ]: 63136 : if ( ret_type->Tag() == TYPE_INTERVAL )
821 : 1 : return new IntervalVal(d3, 1.0);
822 [ + + ]: 63135 : else if ( ret_type->InternalType() == TYPE_INTERNAL_DOUBLE )
823 : 4 : return new Val(d3, ret_type->Tag());
824 [ + + ]: 63131 : else if ( ret_type->InternalType() == TYPE_INTERNAL_UNSIGNED )
825 : 203 : return new Val(u3, ret_type->Tag());
826 : : else
827 : 112943 : return new Val(i3, ret_type->Tag());
828 : : }
829 : :
830 : 48973 : Val* BinaryExpr::StringFold(Val* v1, Val* v2) const
831 : : {
832 : 48973 : const BroString* s1 = v1->AsString();
833 : 48973 : const BroString* s2 = v2->AsString();
834 : 48973 : int result = 0;
835 : :
836 [ - - + + - : 48973 : switch ( tag ) {
- - - ]
837 : : #undef DO_FOLD
838 : : #define DO_FOLD(sense) { result = Bstr_cmp(s1, s2) sense 0; break; }
839 : :
840 : 0 : case EXPR_LT: DO_FOLD(<)
841 : 0 : case EXPR_LE: DO_FOLD(<=)
842 : 45817 : case EXPR_EQ: DO_FOLD(==)
843 : 3156 : case EXPR_NE: DO_FOLD(!=)
844 : 0 : case EXPR_GE: DO_FOLD(>=)
845 : 0 : case EXPR_GT: DO_FOLD(>)
846 : :
847 : : case EXPR_ADD:
848 : : case EXPR_ADD_TO:
849 : : {
850 : 0 : vector<const BroString*> strings;
851 : 0 : strings.push_back(s1);
852 : 0 : strings.push_back(s2);
853 : :
854 : 0 : return new StringVal(concatenate(strings));
855 : : }
856 : :
857 : : default:
858 : 0 : BadTag("BinaryExpr::StringFold", expr_name(tag));
859 : : }
860 : :
861 : 48973 : return new Val(result, TYPE_BOOL);
862 : : }
863 : :
864 : 820 : Val* BinaryExpr::AddrFold(Val* v1, Val* v2) const
865 : : {
866 : 820 : addr_type a1 = v1->AsAddr();
867 : 820 : addr_type a2 = v2->AsAddr();
868 : 820 : int result = 0;
869 : :
870 [ - - + - - : 820 : switch ( tag ) {
- - ]
871 : : #undef DO_FOLD
872 : : #ifdef BROv6
873 : : #define DO_FOLD(sense) { result = memcmp(a1, a2, 16) sense 0; break; }
874 : : #else
875 : : #define DO_FOLD(sense) \
876 : : { \
877 : : a1 = ntohl(a1); \
878 : : a2 = ntohl(a2); \
879 : : result = (a1 < a2 ? -1 : (a1 == a2 ? 0 : 1)) sense 0; \
880 : : break; \
881 : : }
882 : : #endif
883 : :
884 : 0 : case EXPR_LT: DO_FOLD(<)
885 [ # # ][ # # ]: 0 : case EXPR_LE: DO_FOLD(<=)
886 [ + - ][ + - ]: 820 : case EXPR_EQ: DO_FOLD(==)
887 [ # # ][ # # ]: 0 : case EXPR_NE: DO_FOLD(!=)
888 : 0 : case EXPR_GE: DO_FOLD(>=)
889 [ # # ][ # # ]: 0 : case EXPR_GT: DO_FOLD(>)
890 : :
891 : : default:
892 : 0 : BadTag("BinaryExpr::AddrFold", expr_name(tag));
893 : : }
894 : :
895 : 820 : return new Val(result, TYPE_BOOL);
896 : : }
897 : :
898 : 0 : Val* BinaryExpr::SubNetFold(Val* v1, Val* v2) const
899 : : {
900 : 0 : subnet_type* n1 = v1->AsSubNet();
901 : 0 : subnet_type* n2 = v2->AsSubNet();
902 : :
903 [ # # ]: 0 : if ( n1->width != n2->width )
904 : 0 : return new Val(0, TYPE_BOOL);
905 : :
906 : : #ifdef BROv6
907 : : if ( memcmp(n1->net, n2->net, 16) )
908 : : #else
909 [ # # ]: 0 : if ( n1->net != n2->net )
910 : : #endif
911 : 0 : return new Val(0, TYPE_BOOL);
912 : :
913 : 0 : return new Val(1, TYPE_BOOL);
914 : : }
915 : :
916 : 660 : void BinaryExpr::SwapOps()
917 : : {
918 : : // We could check here whether the operator is commutative.
919 : 660 : Expr* t = op1;
920 : 660 : op1 = op2;
921 : 660 : op2 = t;
922 : 660 : }
923 : :
924 : 898 : void BinaryExpr::PromoteOps(TypeTag t)
925 : : {
926 : 898 : TypeTag bt1 = op1->Type()->Tag();
927 : 898 : TypeTag bt2 = op2->Type()->Tag();
928 : :
929 [ - + ]: 898 : if ( IsVector(bt1) )
930 : 0 : bt1 = op1->Type()->AsVectorType()->YieldType()->Tag();
931 [ - + ]: 898 : if ( IsVector(bt2) )
932 : 0 : bt2 = op2->Type()->AsVectorType()->YieldType()->Tag();
933 : :
934 [ + + ]: 898 : if ( bt1 != t )
935 : 60 : op1 = new ArithCoerceExpr(op1, t);
936 [ + + ]: 898 : if ( bt2 != t )
937 : 43 : op2 = new ArithCoerceExpr(op2, t);
938 : 898 : }
939 : :
940 : 213 : void BinaryExpr::PromoteType(TypeTag t, bool is_vector)
941 : : {
942 : 213 : PromoteOps(t);
943 [ - + ]: 213 : SetType(is_vector ? new VectorType(base_type(t)) : base_type(t));
944 : 213 : }
945 : :
946 : 3 : IMPLEMENT_SERIAL(BinaryExpr, SER_BINARY_EXPR);
947 : :
948 : 0 : bool BinaryExpr::DoSerialize(SerialInfo* info) const
949 : : {
950 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_BINARY_EXPR, Expr);
951 [ # # ][ # # ]: 0 : return op1->Serialize(info) && op2->Serialize(info);
952 : : }
953 : :
954 : 0 : bool BinaryExpr::DoUnserialize(UnserialInfo* info)
955 : : {
956 [ # # ]: 0 : DO_UNSERIALIZE(Expr);
957 : :
958 : 0 : op1 = Expr::Unserialize(info);
959 [ # # ]: 0 : if ( ! op1 )
960 : 0 : return false;
961 : :
962 : 0 : op2 = Expr::Unserialize(info);
963 : 0 : return op2 != 0;
964 : : }
965 : :
966 : 5 : CloneExpr::CloneExpr(Expr* arg_op) : UnaryExpr(EXPR_CLONE, arg_op)
967 : : {
968 [ + - # # ]: 5 : if ( IsError() )
969 : 5 : return;
970 : :
971 : 5 : BroType* t = op->Type();
972 : 5 : SetType(t->Ref());
973 : 0 : }
974 : :
975 : 0 : Val* CloneExpr::Eval(Frame* f) const
976 : : {
977 [ # # ]: 0 : if ( IsError() )
978 : 0 : return 0;
979 : :
980 : 0 : Val* v = op->Eval(f);
981 : :
982 [ # # ]: 0 : if ( ! v )
983 : 0 : return 0;
984 : :
985 : 0 : Val* result = Fold(v);
986 : 0 : Unref(v);
987 : :
988 : 0 : return result;
989 : : }
990 : :
991 : 0 : Val* CloneExpr::Fold(Val* v) const
992 : : {
993 : 0 : return v->Clone();
994 : : }
995 : :
996 : 3 : IMPLEMENT_SERIAL(CloneExpr, SER_CLONE_EXPR);
997 : :
998 : 0 : bool CloneExpr::DoSerialize(SerialInfo* info) const
999 : : {
1000 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_CLONE_EXPR, UnaryExpr);
1001 : 0 : return true;
1002 : : }
1003 : :
1004 : 0 : bool CloneExpr::DoUnserialize(UnserialInfo* info)
1005 : : {
1006 [ # # ]: 0 : DO_UNSERIALIZE(UnaryExpr);
1007 : 0 : return true;
1008 : : }
1009 : :
1010 : 162 : IncrExpr::IncrExpr(BroExprTag arg_tag, Expr* arg_op)
1011 : 162 : : UnaryExpr(arg_tag, arg_op->MakeLvalue())
1012 : : {
1013 [ + - # # ]: 162 : if ( IsError() )
1014 : 162 : return;
1015 : :
1016 : 162 : BroType* t = op->Type();
1017 : :
1018 [ - + # # ]: 162 : if ( IsVector(t->Tag()) )
1019 : : {
1020 [ # # ][ # # ]: 0 : if ( ! IsIntegral(t->AsVectorType()->YieldType()->Tag()) )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1021 : 0 : ExprError("vector elements must be integral for increment operator");
1022 : : else
1023 : 0 : SetType(t->Ref());
1024 : : }
1025 : : else
1026 : : {
1027 [ + - ][ - + ]: 162 : if ( ! IsIntegral(t->Tag()) )
[ # # ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
1028 : 0 : ExprError("requires an integral operand");
1029 : : else
1030 : 162 : SetType(t->Ref());
1031 : : }
1032 : 0 : }
1033 : :
1034 : 3448 : Val* IncrExpr::DoSingleEval(Frame* f, Val* v) const
1035 : : {
1036 : 3448 : bro_int_t k = v->CoerceToInt();
1037 : :
1038 [ + + ]: 3448 : if ( Tag() == EXPR_INCR )
1039 : 2479 : ++k;
1040 : : else
1041 : : {
1042 : 969 : --k;
1043 : :
1044 [ - + ][ # # ]: 969 : if ( k < 0 &&
[ - + ]
1045 : : v->Type()->InternalType() == TYPE_INTERNAL_UNSIGNED )
1046 : 0 : RunTime("count underflow");
1047 : : }
1048 : :
1049 : 3448 : BroType* ret_type = Type();
1050 [ - + ]: 3448 : if ( IsVector(ret_type->Tag()) )
1051 : 0 : ret_type = Type()->YieldType();
1052 : :
1053 : 3448 : return new Val(k, ret_type->Tag());
1054 : : }
1055 : :
1056 : :
1057 : 3448 : Val* IncrExpr::Eval(Frame* f) const
1058 : : {
1059 : 3448 : Val* v = op->Eval(f);
1060 [ - + ]: 3448 : if ( ! v )
1061 : 0 : return 0;
1062 : :
1063 [ - + ]: 3448 : if ( is_vector(v) )
1064 : : {
1065 : 0 : VectorVal* v_vec = v->AsVectorVal();
1066 [ # # ]: 0 : for ( unsigned int i = VECTOR_MIN;
1067 : : i < v_vec->Size() + VECTOR_MIN; ++i )
1068 : : {
1069 : 0 : Val* elt = v_vec->Lookup(i);
1070 [ # # ]: 0 : if ( elt )
1071 : : {
1072 : 0 : Val* new_elt = DoSingleEval(f, elt);
1073 : 0 : v_vec->Assign(i, new_elt, this, OP_INCR);
1074 : 0 : Unref(new_elt); // was Ref()'d by Assign()
1075 : : }
1076 : : else
1077 : 0 : v_vec->Assign(i, 0, this, OP_INCR);
1078 : : }
1079 : : // FIXME: Is the next line needed?
1080 : 0 : op->Assign(f, v_vec, OP_INCR);
1081 : : }
1082 : :
1083 : : else
1084 : : {
1085 : 3448 : Val* old_v = v;
1086 : 3448 : op->Assign(f, v = DoSingleEval(f, old_v), OP_INCR);
1087 : 3448 : Unref(old_v);
1088 : : }
1089 : :
1090 : 3448 : return v->Ref();
1091 : : }
1092 : :
1093 : 94 : int IncrExpr::IsPure() const
1094 : : {
1095 : 94 : return 0;
1096 : : }
1097 : :
1098 : 3 : IMPLEMENT_SERIAL(IncrExpr, SER_INCR_EXPR);
1099 : :
1100 : 0 : bool IncrExpr::DoSerialize(SerialInfo* info) const
1101 : : {
1102 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_INCR_EXPR, UnaryExpr);
1103 : 0 : return true;
1104 : : }
1105 : :
1106 : 0 : bool IncrExpr::DoUnserialize(UnserialInfo* info)
1107 : : {
1108 [ # # ]: 0 : DO_UNSERIALIZE(UnaryExpr);
1109 : 0 : return true;
1110 : : }
1111 : :
1112 : 441 : NotExpr::NotExpr(Expr* arg_op) : UnaryExpr(EXPR_NOT, arg_op)
1113 : : {
1114 [ + - # # ]: 441 : if ( IsError() )
1115 : 441 : return;
1116 : :
1117 : 441 : BroType* t = op->Type();
1118 [ - + # # ]: 441 : if ( IsVector(t->Tag()) )
1119 : 0 : t = t->AsVectorType()->YieldType();
1120 : :
1121 : 441 : TypeTag bt = t->Tag();
1122 : :
1123 [ + - + + ]: 441 : if ( ! IsIntegral(bt) && bt != TYPE_BOOL )
[ + - ]
[ - + # # ]
[ # # ][ # # ]
[ # # ]
1124 : 0 : ExprError("requires an integral or boolean operand");
1125 [ - + ][ # # ]: 441 : else if ( IsVector(bt) )
1126 : 0 : SetType(new VectorType(base_type(TYPE_BOOL)));
1127 : : else
1128 : 441 : SetType(base_type(TYPE_BOOL));
1129 : 0 : }
1130 : :
1131 : 0 : Expr* NotExpr::DoSimplify()
1132 : : {
1133 : 0 : op = simplify_expr(op, SIMPLIFY_GENERAL);
1134 : 0 : Canonicize();
1135 : :
1136 [ # # ]: 0 : if ( op->Tag() == EXPR_NOT )
1137 : : // !!x == x
1138 : 0 : return ((NotExpr*) op)->Op()->Ref();
1139 : :
1140 [ # # ][ # # ]: 0 : if ( op->IsConst() && ! is_vector(op->ExprVal()) )
[ # # ]
1141 : 0 : return new ConstExpr(Fold(op->ExprVal()));
1142 : :
1143 : 0 : return this;
1144 : : }
1145 : :
1146 : 41898 : Val* NotExpr::Fold(Val* v) const
1147 : : {
1148 : 41898 : return new Val(! v->InternalInt(), type->Tag());
1149 : : }
1150 : :
1151 : 3 : IMPLEMENT_SERIAL(NotExpr, SER_NOT_EXPR);
1152 : :
1153 : 0 : bool NotExpr::DoSerialize(SerialInfo* info) const
1154 : : {
1155 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_NOT_EXPR, UnaryExpr);
1156 : 0 : return true;
1157 : : }
1158 : :
1159 : 0 : bool NotExpr::DoUnserialize(UnserialInfo* info)
1160 : : {
1161 [ # # ]: 0 : DO_UNSERIALIZE(UnaryExpr);
1162 : 0 : return true;
1163 : : }
1164 : :
1165 : 76 : PosExpr::PosExpr(Expr* arg_op) : UnaryExpr(EXPR_POSITIVE, arg_op)
1166 : : {
1167 [ + - # # ]: 76 : if ( IsError() )
1168 : 76 : return;
1169 : :
1170 : 76 : BroType* t = op->Type();
1171 [ - + # # ]: 76 : if ( IsVector(t->Tag()) )
1172 : 0 : t = t->AsVectorType()->YieldType();
1173 : 76 : TypeTag bt = t->Tag();
1174 : :
1175 : 76 : BroType* base_result_type = 0;
1176 : :
1177 [ + - + + ]: 151 : if ( IsIntegral(bt) )
[ - + # # ]
[ # # ][ # # ]
1178 : : // Promote count and counter to int.
1179 : 75 : base_result_type = base_type(TYPE_INT);
1180 [ - + ][ # # ]: 2 : else if ( bt == TYPE_INTERVAL || bt == TYPE_DOUBLE )
[ # # ][ # # ]
1181 : 1 : base_result_type = t->Ref();
1182 : : else
1183 : 0 : ExprError("requires an integral or double operand");
1184 : :
1185 [ - + ][ # # ]: 76 : if ( is_vector(op) )
1186 : 0 : SetType(new VectorType(base_result_type));
1187 : : else
1188 : 76 : SetType(base_result_type);
1189 : 0 : }
1190 : :
1191 : 0 : Expr* PosExpr::DoSimplify()
1192 : : {
1193 : 0 : op = simplify_expr(op, SIMPLIFY_GENERAL);
1194 : 0 : Canonicize();
1195 : :
1196 : 0 : TypeTag t = op->Type()->Tag();
1197 : :
1198 [ # # # # ]: 0 : if ( t == TYPE_DOUBLE || t == TYPE_INTERVAL || t == TYPE_INT )
[ # # ]
1199 : 0 : return op->Ref();
1200 : :
1201 [ # # ][ # # ]: 0 : if ( op->IsConst() && ! is_vector(op->ExprVal()) )
[ # # ]
1202 : 0 : return new ConstExpr(Fold(op->ExprVal()));
1203 : :
1204 : 0 : return this;
1205 : : }
1206 : :
1207 : 69 : Val* PosExpr::Fold(Val* v) const
1208 : : {
1209 : 69 : TypeTag t = v->Type()->Tag();
1210 : :
1211 [ + - + - ]: 69 : if ( t == TYPE_DOUBLE || t == TYPE_INTERVAL || t == TYPE_INT )
[ - + ]
1212 : 0 : return v->Ref();
1213 : : else
1214 : 69 : return new Val(v->CoerceToInt(), type->Tag());
1215 : : }
1216 : :
1217 : 3 : IMPLEMENT_SERIAL(PosExpr, SER_POS_EXPR);
1218 : :
1219 : 0 : bool PosExpr::DoSerialize(SerialInfo* info) const
1220 : : {
1221 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_POS_EXPR, UnaryExpr);
1222 : 0 : return true;
1223 : : }
1224 : :
1225 : 0 : bool PosExpr::DoUnserialize(UnserialInfo* info)
1226 : : {
1227 [ # # ]: 0 : DO_UNSERIALIZE(UnaryExpr);
1228 : 0 : return true;
1229 : : }
1230 : :
1231 : 26 : NegExpr::NegExpr(Expr* arg_op) : UnaryExpr(EXPR_NEGATE, arg_op)
1232 : : {
1233 [ + - # # ]: 26 : if ( IsError() )
1234 : 26 : return;
1235 : :
1236 : 26 : BroType* t = op->Type();
1237 [ - + # # ]: 26 : if ( IsVector(t->Tag()) )
1238 : 0 : t = t->AsVectorType()->YieldType();
1239 : 26 : TypeTag bt = t->Tag();
1240 : :
1241 : 26 : BroType* base_result_type = 0;
1242 : :
1243 [ + - + + ]: 51 : if ( IsIntegral(bt) )
[ - + # # ]
[ # # ][ # # ]
1244 : : // Promote count and counter to int.
1245 : 25 : base_result_type = base_type(TYPE_INT);
1246 [ - + ][ # # ]: 2 : else if ( bt == TYPE_INTERVAL || bt == TYPE_DOUBLE )
[ # # ][ # # ]
1247 : 1 : base_result_type = t->Ref();
1248 : : else
1249 : 0 : ExprError("requires an integral or double operand");
1250 : :
1251 [ - + ][ # # ]: 26 : if ( is_vector(op) )
1252 : 0 : SetType(new VectorType(base_result_type));
1253 : : else
1254 : 26 : SetType(base_result_type);
1255 : 0 : }
1256 : :
1257 : 0 : Expr* NegExpr::DoSimplify()
1258 : : {
1259 : 0 : op = simplify_expr(op, SIMPLIFY_GENERAL);
1260 : 0 : Canonicize();
1261 : :
1262 [ # # ]: 0 : if ( op->Tag() == EXPR_NEGATE )
1263 : : // -(-x) == x
1264 : 0 : return ((NegExpr*) op)->Op()->Ref();
1265 : :
1266 [ # # ][ # # ]: 0 : if ( op->IsConst() && ! is_vector(op->ExprVal()) )
[ # # ]
1267 : 0 : return new ConstExpr(Fold(op->ExprVal()));
1268 : :
1269 [ # # ]: 0 : if ( op->Tag() == EXPR_SUB )
1270 : : { // -(a-b) == b-a
1271 : 0 : SubExpr* s = (SubExpr*) op;
1272 : 0 : return new SubExpr(s->Op2()->Ref(), s->Op1()->Ref());
1273 : : }
1274 : :
1275 : 0 : return this;
1276 : : }
1277 : :
1278 : 10 : Val* NegExpr::Fold(Val* v) const
1279 : : {
1280 [ - + ]: 10 : if ( v->Type()->Tag() == TYPE_DOUBLE )
1281 : 0 : return new Val(- v->InternalDouble(), v->Type()->Tag());
1282 [ - + ]: 10 : else if ( v->Type()->Tag() == TYPE_INTERVAL )
1283 : 0 : return new IntervalVal(- v->InternalDouble(), 1.0);
1284 : : else
1285 : 10 : return new Val(- v->CoerceToInt(), TYPE_INT);
1286 : : }
1287 : :
1288 : :
1289 : 3 : IMPLEMENT_SERIAL(NegExpr, SER_NEG_EXPR);
1290 : :
1291 : 0 : bool NegExpr::DoSerialize(SerialInfo* info) const
1292 : : {
1293 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_NEG_EXPR, UnaryExpr);
1294 : 0 : return true;
1295 : : }
1296 : :
1297 : 0 : bool NegExpr::DoUnserialize(UnserialInfo* info)
1298 : : {
1299 [ # # ]: 0 : DO_UNSERIALIZE(UnaryExpr);
1300 : 0 : return true;
1301 : : }
1302 : :
1303 : 84 : SizeExpr::SizeExpr(Expr* arg_op) : UnaryExpr(EXPR_SIZE, arg_op)
1304 : : {
1305 [ + - # # ]: 84 : if ( IsError() )
1306 : 84 : return;
1307 : :
1308 : 84 : SetType(base_type(TYPE_COUNT));
1309 : 0 : }
1310 : :
1311 : 1195 : Val* SizeExpr::Eval(Frame* f) const
1312 : : {
1313 : 1195 : Val* v = op->Eval(f);
1314 [ - + ]: 1195 : if ( ! v )
1315 : 0 : return 0;
1316 : :
1317 : 1195 : Val* result = Fold(v);
1318 : 1195 : Unref(v);
1319 : 1195 : return result;
1320 : : }
1321 : :
1322 : 1195 : Val* SizeExpr::Fold(Val* v) const
1323 : : {
1324 : 1195 : return v->SizeVal();
1325 : : }
1326 : :
1327 : 3 : IMPLEMENT_SERIAL(SizeExpr, SER_SIZE_EXPR);
1328 : :
1329 : 0 : bool SizeExpr::DoSerialize(SerialInfo* info) const
1330 : : {
1331 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_SIZE_EXPR, UnaryExpr);
1332 : 0 : return true;
1333 : : }
1334 : :
1335 : 0 : bool SizeExpr::DoUnserialize(UnserialInfo* info)
1336 : : {
1337 [ # # ]: 0 : DO_UNSERIALIZE(UnaryExpr);
1338 : 0 : return true;
1339 : : }
1340 : :
1341 : :
1342 : 83 : AddExpr::AddExpr(Expr* arg_op1, Expr* arg_op2)
1343 : 83 : : BinaryExpr(EXPR_ADD, arg_op1, arg_op2)
1344 : : {
1345 [ + - # # ]: 83 : if ( IsError() )
1346 : 83 : return;
1347 : :
1348 : 83 : TypeTag bt1 = op1->Type()->Tag();
1349 [ - + # # ]: 83 : if ( IsVector(bt1) )
1350 : 0 : bt1 = op1->Type()->AsVectorType()->YieldType()->Tag();
1351 : :
1352 : 83 : TypeTag bt2 = op2->Type()->Tag();
1353 [ - + # # ]: 83 : if ( IsVector(bt2) )
1354 : 0 : bt2 = op2->Type()->AsVectorType()->YieldType()->Tag();
1355 : :
1356 : 83 : BroType* base_result_type = 0;
1357 : :
1358 [ + + ][ + - ]: 86 : if ( bt1 == TYPE_TIME && bt2 == TYPE_INTERVAL )
[ # # ][ # # ]
1359 : 3 : base_result_type = base_type(bt1);
1360 [ - + ][ # # ]: 80 : else if ( bt2 == TYPE_TIME && bt1 == TYPE_INTERVAL )
[ # # ][ # # ]
1361 : 0 : base_result_type = base_type(bt2);
1362 [ + + ][ + - ]: 86 : else if ( bt1 == TYPE_INTERVAL && bt2 == TYPE_INTERVAL )
[ # # ][ # # ]
1363 : 6 : base_result_type = base_type(bt1);
1364 [ + + ][ + + ]: 148 : else if ( BothArithmetic(bt1, bt2) )
[ + - ][ + - ]
[ + - ][ + + ]
[ + - ][ + - ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1365 [ + - ][ - + ]: 74 : PromoteType(max_type(bt1, bt2), is_vector(op1) || is_vector(op2));
[ # # ][ # # ]
1366 [ # # ][ # # ]: 0 : else if ( BothString(bt1, bt2) )
[ # # ][ # # ]
1367 : 0 : base_result_type = base_type(bt1);
1368 : : else
1369 : 0 : ExprError("requires arithmetic operands");
1370 : :
1371 [ + + ][ # # ]: 83 : if ( base_result_type )
1372 : : {
1373 [ + - ][ - + ]: 9 : if ( is_vector(op1) || is_vector(op2) )
[ - + ][ # # ]
[ # # ][ # # ]
1374 : 0 : SetType(new VectorType(base_result_type));
1375 : : else
1376 : 83 : SetType(base_result_type);
1377 : : }
1378 : 0 : }
1379 : :
1380 : 0 : Expr* AddExpr::DoSimplify()
1381 : : {
1382 : : // If there's a constant, then it's in op1, since Canonicize()
1383 : : // makes sure of that.
1384 [ # # ]: 0 : if ( op1->IsZero() )
1385 : 0 : return op2->Ref();
1386 : :
1387 [ # # ]: 0 : else if ( op1->Tag() == EXPR_NEGATE )
1388 : : // (-a)+b = b-a
1389 : 0 : return new AddExpr(op2->Ref(), ((NegExpr*) op1)->Op()->Ref());
1390 : :
1391 [ # # ]: 0 : else if ( op2->Tag() == EXPR_NEGATE )
1392 : : // a+(-b) == a-b
1393 : 0 : return new SubExpr(op1->Ref(), ((NegExpr*) op2)->Op()->Ref());
1394 : :
1395 : 0 : return this;
1396 : : }
1397 : :
1398 : 0 : void AddExpr::Canonicize()
1399 : : {
1400 [ # # ][ # # ]: 0 : if ( expr_greater(op2, op1) ||
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1401 : : (op1->Type()->Tag() == TYPE_INTERVAL &&
1402 : : op2->Type()->Tag() == TYPE_TIME) ||
1403 : : (op2->IsConst() && ! is_vector(op2->ExprVal()) && ! op1->IsConst()))
1404 : 0 : SwapOps();
1405 : 0 : }
1406 : :
1407 : 3 : IMPLEMENT_SERIAL(AddExpr, SER_ADD_EXPR);
1408 : :
1409 : 0 : bool AddExpr::DoSerialize(SerialInfo* info) const
1410 : : {
1411 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_ADD_EXPR, BinaryExpr);
1412 : 0 : return true;
1413 : : }
1414 : :
1415 : 0 : bool AddExpr::DoUnserialize(UnserialInfo* info)
1416 : : {
1417 [ # # ]: 0 : DO_UNSERIALIZE(BinaryExpr);
1418 : 0 : return true;
1419 : : }
1420 : :
1421 : 28 : AddToExpr::AddToExpr(Expr* arg_op1, Expr* arg_op2)
1422 : 28 : : BinaryExpr(EXPR_ADD_TO, arg_op1, arg_op2)
1423 : : {
1424 [ + - # # ]: 28 : if ( IsError() )
1425 : 28 : return;
1426 : :
1427 : 28 : TypeTag bt1 = op1->Type()->Tag();
1428 : 28 : TypeTag bt2 = op2->Type()->Tag();
1429 : :
1430 [ + + + + ]: 41 : if ( BothArithmetic(bt1, bt2) )
[ + - ][ - + ]
[ + + ][ - + ]
[ # # ]
[ # # # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1431 [ + - ][ - + ]: 13 : PromoteType(max_type(bt1, bt2), is_vector(op1) || is_vector(op2));
[ # # ][ # # ]
1432 [ + + ][ + - ]: 25 : else if ( BothString(bt1, bt2) )
[ # # ][ # # ]
1433 : 10 : SetType(base_type(bt1));
1434 [ + - ][ + - ]: 10 : else if ( BothInterval(bt1, bt2) )
[ # # ][ # # ]
1435 : 5 : SetType(base_type(bt1));
1436 : : else
1437 : 28 : ExprError("requires two arithmetic or two string operands");
1438 : 0 : }
1439 : :
1440 : 0 : Val* AddToExpr::Eval(Frame* f) const
1441 : : {
1442 : 0 : Val* v1 = op1->Eval(f);
1443 [ # # ]: 0 : if ( ! v1 )
1444 : 0 : return 0;
1445 : :
1446 : 0 : Val* v2 = op2->Eval(f);
1447 [ # # ]: 0 : if ( ! v2 )
1448 : : {
1449 : 0 : Unref(v1);
1450 : 0 : return 0;
1451 : : }
1452 : :
1453 : 0 : Val* result = Fold(v1, v2);
1454 : 0 : Unref(v1);
1455 : 0 : Unref(v2);
1456 : :
1457 [ # # ]: 0 : if ( result )
1458 : : {
1459 : 0 : op1->Assign(f, result);
1460 : 0 : return result->Ref();
1461 : : }
1462 : : else
1463 : 0 : return 0;
1464 : : }
1465 : :
1466 : 3 : IMPLEMENT_SERIAL(AddToExpr, SER_ADD_TO_EXPR);
1467 : :
1468 : 0 : bool AddToExpr::DoSerialize(SerialInfo* info) const
1469 : : {
1470 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_ADD_TO_EXPR, BinaryExpr);
1471 : 0 : return true;
1472 : : }
1473 : :
1474 : 0 : bool AddToExpr::DoUnserialize(UnserialInfo* info)
1475 : : {
1476 [ # # ]: 0 : DO_UNSERIALIZE(BinaryExpr);
1477 : 0 : return true;
1478 : : }
1479 : :
1480 : 48 : SubExpr::SubExpr(Expr* arg_op1, Expr* arg_op2)
1481 : 48 : : BinaryExpr(EXPR_SUB, arg_op1, arg_op2)
1482 : : {
1483 [ + - # # ]: 48 : if ( IsError() )
1484 : 48 : return;
1485 : :
1486 : 48 : TypeTag bt1 = op1->Type()->Tag();
1487 [ - + # # ]: 48 : if ( IsVector(bt1) )
1488 : 0 : bt1 = op1->Type()->AsVectorType()->YieldType()->Tag();
1489 : :
1490 : 48 : TypeTag bt2 = op2->Type()->Tag();
1491 [ - + # # ]: 48 : if ( IsVector(bt2) )
1492 : 0 : bt2 = op2->Type()->AsVectorType()->YieldType()->Tag();
1493 : :
1494 : 48 : BroType* base_result_type = 0;
1495 : :
1496 [ + + ][ - + ]: 48 : if ( bt1 == TYPE_TIME && bt2 == TYPE_INTERVAL )
[ # # ][ # # ]
1497 : 0 : base_result_type = base_type(bt1);
1498 [ + + ][ + - ]: 57 : else if ( bt1 == TYPE_TIME && bt2 == TYPE_TIME )
[ # # ][ # # ]
1499 : 9 : SetType(base_type(TYPE_INTERVAL));
1500 [ + + ][ + - ]: 44 : else if ( bt1 == TYPE_INTERVAL && bt2 == TYPE_INTERVAL )
[ # # ][ # # ]
1501 : 5 : base_result_type = base_type(bt1);
1502 [ + + ][ - + ]: 68 : else if ( BothArithmetic(bt1, bt2) )
[ # # ][ # # ]
[ + - ][ + + ]
[ + - ][ + - ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1503 [ + - ][ - + ]: 34 : PromoteType(max_type(bt1, bt2), is_vector(op1) || is_vector(op2));
[ # # ][ # # ]
1504 : : else
1505 : 0 : ExprError("requires arithmetic operands");
1506 : :
1507 [ + + ][ # # ]: 48 : if ( base_result_type )
1508 : : {
1509 [ + - ][ - + ]: 5 : if ( is_vector(op1) || is_vector(op2) )
[ - + ][ # # ]
[ # # ][ # # ]
1510 : 0 : SetType(new VectorType(base_result_type));
1511 : : else
1512 : 48 : SetType(base_result_type);
1513 : : }
1514 : 0 : }
1515 : :
1516 : 0 : Expr* SubExpr::DoSimplify()
1517 : : {
1518 [ # # ]: 0 : if ( op1->IsZero() )
1519 : 0 : return new NegExpr(op2->Ref());
1520 : :
1521 [ # # ]: 0 : else if ( op2->IsZero() )
1522 : 0 : return op1->Ref();
1523 : :
1524 [ # # ]: 0 : else if ( op2->Tag() == EXPR_NEGATE )
1525 : : // a-(-b) = a+b
1526 : 0 : return new AddExpr(op1->Ref(), ((NegExpr*) op2)->Op()->Ref());
1527 : :
1528 : 0 : return this;
1529 : : }
1530 : :
1531 : 3 : IMPLEMENT_SERIAL(SubExpr, SER_SUB_EXPR);
1532 : :
1533 : 0 : bool SubExpr::DoSerialize(SerialInfo* info) const
1534 : : {
1535 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_SUB_EXPR, BinaryExpr);
1536 : 0 : return true;
1537 : : }
1538 : :
1539 : 0 : bool SubExpr::DoUnserialize(UnserialInfo* info)
1540 : : {
1541 [ # # ]: 0 : DO_UNSERIALIZE(BinaryExpr);
1542 : 0 : return true;
1543 : : }
1544 : :
1545 : 0 : RemoveFromExpr::RemoveFromExpr(Expr* arg_op1, Expr* arg_op2)
1546 : 0 : : BinaryExpr(EXPR_REMOVE_FROM, arg_op1, arg_op2)
1547 : : {
1548 [ # # # # ]: 0 : if ( IsError() )
1549 : 0 : return;
1550 : :
1551 : 0 : TypeTag bt1 = op1->Type()->Tag();
1552 : 0 : TypeTag bt2 = op2->Type()->Tag();
1553 : :
1554 [ # # # # ]: 0 : if ( BothArithmetic(bt1, bt2) )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
[ # # # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1555 [ # # ][ # # ]: 0 : PromoteType(max_type(bt1, bt2), is_vector(op1) || is_vector(op2));
[ # # ][ # # ]
1556 : : else
1557 : 0 : ExprError("requires two arithmetic operands");
1558 : 0 : }
1559 : :
1560 : 0 : Val* RemoveFromExpr::Eval(Frame* f) const
1561 : : {
1562 : 0 : Val* v1 = op1->Eval(f);
1563 [ # # ]: 0 : if ( ! v1 )
1564 : 0 : return 0;
1565 : :
1566 : 0 : Val* v2 = op2->Eval(f);
1567 [ # # ]: 0 : if ( ! v2 )
1568 : : {
1569 : 0 : Unref(v1);
1570 : 0 : return 0;
1571 : : }
1572 : :
1573 : 0 : Val* result = Fold(v1, v2);
1574 : :
1575 : 0 : Unref(v1);
1576 : 0 : Unref(v2);
1577 : :
1578 [ # # ]: 0 : if ( result )
1579 : : {
1580 : 0 : op1->Assign(f, result);
1581 : 0 : return result->Ref();
1582 : : }
1583 : : else
1584 : 0 : return 0;
1585 : : }
1586 : :
1587 : 3 : IMPLEMENT_SERIAL(RemoveFromExpr, SER_REMOVE_FROM_EXPR);
1588 : :
1589 : 0 : bool RemoveFromExpr::DoSerialize(SerialInfo* info) const
1590 : : {
1591 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_REMOVE_FROM_EXPR, BinaryExpr);
1592 : 0 : return true;
1593 : : }
1594 : :
1595 : 0 : bool RemoveFromExpr::DoUnserialize(UnserialInfo* info)
1596 : : {
1597 [ # # ]: 0 : DO_UNSERIALIZE(BinaryExpr);
1598 : 0 : return true;
1599 : : }
1600 : :
1601 : 46 : TimesExpr::TimesExpr(Expr* arg_op1, Expr* arg_op2)
1602 : 46 : : BinaryExpr(EXPR_TIMES, arg_op1, arg_op2)
1603 : : {
1604 [ + - # # ]: 46 : if ( IsError() )
1605 : 46 : return;
1606 : :
1607 : 46 : Canonicize();
1608 : :
1609 : 46 : TypeTag bt1 = op1->Type()->Tag();
1610 [ - + # # ]: 46 : if ( IsVector(bt1) )
1611 : 0 : bt1 = op1->Type()->AsVectorType()->YieldType()->Tag();
1612 : :
1613 : 46 : TypeTag bt2 = op2->Type()->Tag();
1614 [ - + # # ]: 46 : if ( IsVector(bt2) )
1615 : 0 : bt2 = op2->Type()->AsVectorType()->YieldType()->Tag();
1616 : :
1617 [ + - ][ + + ]: 47 : if ( bt1 == TYPE_INTERVAL || bt2 == TYPE_INTERVAL )
[ # # ][ # # ]
1618 : : {
1619 [ + - ][ - + ]: 2 : if ( IsArithmetic(bt1) || IsArithmetic(bt2) )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1620 [ + - ][ - + ]: 1 : PromoteType(TYPE_INTERVAL, is_vector(op1) || is_vector(op2) );
[ # # ][ # # ]
1621 : : else
1622 : 0 : ExprError("multiplication with interval requires arithmetic operand");
1623 : : }
1624 [ + - ][ + + ]: 90 : else if ( BothArithmetic(bt1, bt2) )
[ + - ][ + - ]
[ + - ][ + + ]
[ + - ][ + - ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1625 [ + - ][ - + ]: 45 : PromoteType(max_type(bt1, bt2), is_vector(op1) || is_vector(op2));
[ # # ][ # # ]
1626 : : else
1627 : 46 : ExprError("requires arithmetic operands");
1628 : 0 : }
1629 : :
1630 : 0 : Expr* TimesExpr::DoSimplify()
1631 : : {
1632 : : // If there's a constant, then it's in op1, since Canonicize()
1633 : : // makes sure of that.
1634 [ # # ]: 0 : if ( op1->IsConst() )
1635 : : {
1636 [ # # ]: 0 : if ( op1->IsZero() )
1637 : : {
1638 [ # # ]: 0 : if ( IsVector(op2->Type()->Tag()) )
1639 : 0 : return this;
1640 : : else
1641 : 0 : return make_zero(type);
1642 : : }
1643 : :
1644 [ # # ]: 0 : else if ( op1->IsOne() )
1645 : 0 : return op2->Ref();
1646 : : }
1647 : :
1648 : 0 : return this;
1649 : : }
1650 : :
1651 : 46 : void TimesExpr::Canonicize()
1652 : : {
1653 [ + + ][ + - ]: 46 : if ( expr_greater(op2, op1) || op2->Type()->Tag() == TYPE_INTERVAL ||
[ + + ][ + - ]
[ + + ][ + + ]
1654 : : (op2->IsConst() && ! is_vector(op2->ExprVal()) && ! op1->IsConst()) )
1655 : 23 : SwapOps();
1656 : 46 : }
1657 : :
1658 : 3 : IMPLEMENT_SERIAL(TimesExpr, SER_TIMES_EXPR);
1659 : :
1660 : 0 : bool TimesExpr::DoSerialize(SerialInfo* info) const
1661 : : {
1662 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_TIMES_EXPR, BinaryExpr);
1663 : 0 : return true;
1664 : : }
1665 : :
1666 : 0 : bool TimesExpr::DoUnserialize(UnserialInfo* info)
1667 : : {
1668 [ # # ]: 0 : DO_UNSERIALIZE(BinaryExpr);
1669 : 0 : return true;
1670 : : }
1671 : :
1672 : 49 : DivideExpr::DivideExpr(Expr* arg_op1, Expr* arg_op2)
1673 : 49 : : BinaryExpr(EXPR_DIVIDE, arg_op1, arg_op2)
1674 : : {
1675 [ + - # # ]: 49 : if ( IsError() )
1676 : 49 : return;
1677 : :
1678 : 49 : TypeTag bt1 = op1->Type()->Tag();
1679 [ - + # # ]: 49 : if ( IsVector(bt1) )
1680 : 0 : bt1 = op1->Type()->AsVectorType()->YieldType()->Tag();
1681 : :
1682 : 49 : TypeTag bt2 = op2->Type()->Tag();
1683 [ - + # # ]: 49 : if ( IsVector(bt2) )
1684 : 0 : bt2 = op2->Type()->AsVectorType()->YieldType()->Tag();
1685 : :
1686 [ + + ][ + + ]: 53 : if ( bt1 == TYPE_INTERVAL || bt2 == TYPE_INTERVAL )
[ # # ][ # # ]
1687 : : {
1688 [ + - ][ + + ]: 5 : if ( IsArithmetic(bt1) || IsArithmetic(bt2) )
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1689 [ + - ][ - + ]: 1 : PromoteType(TYPE_INTERVAL, is_vector(op1) || is_vector(op2));
[ # # ][ # # ]
1690 [ + - ][ + - ]: 6 : else if ( bt1 == TYPE_INTERVAL && bt2 == TYPE_INTERVAL )
[ # # ][ # # ]
1691 : : {
1692 [ + - ][ - + ]: 3 : if ( is_vector(op1) || is_vector(op2) )
[ - + ][ # # ]
[ # # ][ # # ]
1693 : 0 : SetType(new VectorType(base_type(TYPE_DOUBLE)));
1694 : : else
1695 : 3 : SetType(base_type(TYPE_DOUBLE));
1696 : : }
1697 : : else
1698 : 0 : ExprError("division of interval requires arithmetic operand");
1699 : : }
1700 : :
1701 [ + - ][ + + ]: 74 : else if ( BothArithmetic(bt1, bt2) )
[ + - ][ + + ]
[ + - ][ + + ]
[ + - ][ + - ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1702 [ + - ][ - + ]: 29 : PromoteType(max_type(bt1, bt2), is_vector(op1) || is_vector(op2));
[ # # ][ # # ]
1703 : :
1704 [ + - ][ + - ]: 16 : else if ( bt1 == TYPE_ADDR && ! is_vector(op2) &&
[ - + ][ # # ]
[ + - ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1705 : : (bt2 == TYPE_COUNT || bt2 == TYPE_INT) )
1706 : 16 : SetType(base_type(TYPE_SUBNET));
1707 : :
1708 : : else
1709 : 49 : ExprError("requires arithmetic operands");
1710 : 0 : }
1711 : :
1712 : 14 : Val* DivideExpr::AddrFold(Val* v1, Val* v2) const
1713 : : {
1714 : 14 : addr_type a1 = v1->AsAddr();
1715 : :
1716 : : uint32 mask;
1717 [ + - ]: 14 : if ( v2->Type()->Tag() == TYPE_COUNT )
1718 : 14 : mask = static_cast<uint32>(v2->InternalUnsigned());
1719 : : else
1720 : 0 : mask = static_cast<uint32>(v2->InternalInt());
1721 : :
1722 : 14 : return new SubNetVal(a1, mask);
1723 : : }
1724 : :
1725 : 0 : Expr* DivideExpr::DoSimplify()
1726 : : {
1727 [ # # ]: 0 : if ( IsError() )
1728 : 0 : return this;
1729 : :
1730 [ # # ]: 0 : if ( op1->Type()->Tag() == TYPE_ADDR )
1731 : 0 : return this;
1732 : :
1733 [ # # ][ # # ]: 0 : if ( is_vector(op1) || is_vector(op2) )
[ # # ]
1734 : 0 : return this;
1735 : :
1736 [ # # ]: 0 : if ( op2->IsConst() )
1737 : : {
1738 [ # # ]: 0 : if ( op2->IsOne() )
1739 : 0 : return op1->Ref();
1740 [ # # ]: 0 : else if ( op2->IsZero() )
1741 : 0 : Error("zero divisor");
1742 : : }
1743 : :
1744 [ # # ]: 0 : else if ( same_expr(op1, op2) )
1745 : 0 : return make_one(type);
1746 : :
1747 : 0 : return this;
1748 : : }
1749 : :
1750 : 3 : IMPLEMENT_SERIAL(DivideExpr, SER_DIVIDE_EXPR);
1751 : :
1752 : 0 : bool DivideExpr::DoSerialize(SerialInfo* info) const
1753 : : {
1754 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_DIVIDE_EXPR, BinaryExpr);
1755 : 0 : return true;
1756 : : }
1757 : :
1758 : 0 : bool DivideExpr::DoUnserialize(UnserialInfo* info)
1759 : : {
1760 [ # # ]: 0 : DO_UNSERIALIZE(BinaryExpr);
1761 : 0 : return true;
1762 : : }
1763 : :
1764 : 16 : ModExpr::ModExpr(Expr* arg_op1, Expr* arg_op2)
1765 : 16 : : BinaryExpr(EXPR_MOD, arg_op1, arg_op2)
1766 : : {
1767 [ + - # # ]: 16 : if ( IsError() )
1768 : 16 : return;
1769 : :
1770 : 16 : TypeTag bt1 = op1->Type()->Tag();
1771 [ - + # # ]: 16 : if ( IsVector(bt1) )
1772 : 0 : bt1 = op1->Type()->AsVectorType()->YieldType()->Tag();
1773 : :
1774 : 16 : TypeTag bt2 = op2->Type()->Tag();
1775 [ - + # # ]: 16 : if ( IsVector(bt2) )
1776 : 0 : bt2 = op2->Type()->AsVectorType()->YieldType()->Tag();
1777 : :
1778 [ + + ][ - + ]: 32 : if ( BothIntegral(bt1, bt2) )
[ # # ][ + - ]
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1779 [ + - ][ - + ]: 16 : PromoteType(max_type(bt1, bt2), is_vector(op1) || is_vector(op2));
[ # # ][ # # ]
1780 : : else
1781 : 16 : ExprError("requires integral operands");
1782 : 0 : }
1783 : :
1784 : 0 : Expr* ModExpr::DoSimplify()
1785 : : {
1786 [ # # ]: 0 : if ( IsError() )
1787 : 0 : return this;
1788 : :
1789 : 0 : TypeTag bt1 = op1->Type()->Tag();
1790 : 0 : TypeTag bt2 = op2->Type()->Tag();
1791 : :
1792 [ # # # # ]: 0 : if ( IsVector(bt1) || IsVector(bt2) )
1793 : 0 : return this;
1794 : :
1795 [ # # ]: 0 : if ( op2->IsConst() )
1796 : : {
1797 [ # # ]: 0 : if ( op2->IsOne() )
1798 : 0 : return make_zero(type);
1799 [ # # ]: 0 : else if ( op2->IsZero() )
1800 : 0 : Error("zero modulus");
1801 : : }
1802 : :
1803 [ # # ]: 0 : else if ( same_expr(op1, op2) )
1804 : 0 : return make_zero(type);
1805 : :
1806 : 0 : return this;
1807 : : }
1808 : :
1809 : 3 : IMPLEMENT_SERIAL(ModExpr, SER_MOD_EXPR);
1810 : :
1811 : 0 : bool ModExpr::DoSerialize(SerialInfo* info) const
1812 : : {
1813 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_MOD_EXPR, BinaryExpr);
1814 : 0 : return true;
1815 : : }
1816 : :
1817 : 0 : bool ModExpr::DoUnserialize(UnserialInfo* info)
1818 : : {
1819 [ # # ]: 0 : DO_UNSERIALIZE(BinaryExpr);
1820 : 0 : return true;
1821 : : }
1822 : :
1823 : 650 : BoolExpr::BoolExpr(BroExprTag arg_tag, Expr* arg_op1, Expr* arg_op2)
1824 : 650 : : BinaryExpr(arg_tag, arg_op1, arg_op2)
1825 : : {
1826 [ + - # # ]: 650 : if ( IsError() )
1827 : 650 : return;
1828 : :
1829 : 650 : TypeTag bt1 = op1->Type()->Tag();
1830 [ - + # # ]: 650 : if ( IsVector(bt1) )
1831 : 0 : bt1 = op1->Type()->AsVectorType()->YieldType()->Tag();
1832 : :
1833 : 650 : TypeTag bt2 = op2->Type()->Tag();
1834 [ - + # # ]: 650 : if ( IsVector(bt2) )
1835 : 0 : bt2 = op2->Type()->AsVectorType()->YieldType()->Tag();
1836 : :
1837 [ + - ][ + - ]: 1300 : if ( BothBool(bt1, bt2) )
[ # # ][ # # ]
1838 : : {
1839 [ + - ][ - + ]: 650 : if ( is_vector(op1) || is_vector(op2) )
[ - + ][ # # ]
[ # # ][ # # ]
1840 : 0 : SetType(new VectorType(base_type(TYPE_BOOL)));
1841 : : else
1842 : 650 : SetType(base_type(TYPE_BOOL));
1843 : : }
1844 : :
1845 [ # # ][ # # ]: 0 : else if ( bt1 == TYPE_PATTERN && bt2 == bt1 )
[ # # ][ # # ]
1846 : 0 : SetType(base_type(TYPE_PATTERN));
1847 : :
1848 : : else
1849 : 650 : ExprError("requires boolean operands");
1850 : 0 : }
1851 : :
1852 : 63375 : Val* BoolExpr::DoSingleEval(Frame* f, Val* v1, Expr* op2) const
1853 : : {
1854 [ - + ]: 63375 : if ( ! v1 )
1855 : 0 : return 0;
1856 : :
1857 [ - + ]: 63375 : if ( Type()->Tag() == TYPE_PATTERN )
1858 : : {
1859 : 0 : Val* v2 = op2->Eval(f);
1860 [ # # ]: 0 : if ( ! v2 )
1861 : 0 : return 0;
1862 : :
1863 : 0 : RE_Matcher* re1 = v1->AsPattern();
1864 : 0 : RE_Matcher* re2 = v2->AsPattern();
1865 : :
1866 : : RE_Matcher* res = tag == EXPR_AND ?
1867 : : RE_Matcher_conjunction(re1, re2) :
1868 [ # # ]: 0 : RE_Matcher_disjunction(re1, re2);
1869 : :
1870 : 0 : return new PatternVal(res);
1871 : : }
1872 : :
1873 [ + + ]: 63375 : if ( tag == EXPR_AND )
1874 : : {
1875 [ + + ]: 41158 : if ( v1->IsZero() )
1876 : 18804 : return v1;
1877 : : else
1878 : : {
1879 : 22354 : Unref(v1);
1880 : 22354 : return op2->Eval(f);
1881 : : }
1882 : : }
1883 : :
1884 : : else
1885 : : {
1886 [ + + ]: 22217 : if ( v1->IsZero() )
1887 : : {
1888 : 15208 : Unref(v1);
1889 : 15208 : return op2->Eval(f);
1890 : : }
1891 : : else
1892 : 63375 : return v1;
1893 : : }
1894 : : }
1895 : :
1896 : :
1897 : 63375 : Val* BoolExpr::Eval(Frame* f) const
1898 : : {
1899 [ - + ]: 63375 : if ( IsError() )
1900 : 0 : return 0;
1901 : :
1902 : 63375 : Val* v1 = op1->Eval(f);
1903 [ - + ]: 63375 : if ( ! v1 )
1904 : 0 : return 0;
1905 : :
1906 : 63375 : int is_vec1 = is_vector(op1);
1907 : 63375 : int is_vec2 = is_vector(op2);
1908 : :
1909 : : // Handle scalar op scalar
1910 [ + - + - ]: 63375 : if ( ! is_vec1 && ! is_vec2 )
1911 : 63375 : return DoSingleEval(f, v1, op2);
1912 : :
1913 : : // Handle scalar op vector or vector op scalar
1914 : : // We can't short-circuit everything since we need to eval
1915 : : // a vector in order to find out its length.
1916 [ # # ][ # # ]: 0 : if ( ! (is_vec1 && is_vec2) )
1917 : : { // Only one is a vector.
1918 : 0 : Val* scalar_v = 0;
1919 : 0 : VectorVal* vector_v = 0;
1920 : :
1921 [ # # ]: 0 : if ( is_vec1 )
1922 : : {
1923 : 0 : scalar_v = op2->Eval(f);
1924 : 0 : vector_v = v1->AsVectorVal();
1925 : : }
1926 : : else
1927 : : {
1928 : 0 : scalar_v = v1;
1929 : 0 : vector_v = op2->Eval(f)->AsVectorVal();
1930 : : }
1931 : :
1932 [ # # ][ # # ]: 0 : if ( ! scalar_v || ! vector_v )
1933 : 0 : return 0;
1934 : :
1935 : 0 : VectorVal* result = 0;
1936 : :
1937 : : // It's either and EXPR_AND or an EXPR_OR.
1938 : 0 : bool is_and = (tag == EXPR_AND);
1939 : :
1940 [ # # ]: 0 : if ( scalar_v->IsZero() == is_and )
1941 : : {
1942 : 0 : result = new VectorVal(Type()->AsVectorType());
1943 : 0 : result->Resize(vector_v->Size());
1944 : : result->AssignRepeat(VECTOR_MIN, result->Size(),
1945 : 0 : scalar_v, this);
1946 : : }
1947 : : else
1948 : 0 : result = vector_v->Ref()->AsVectorVal();
1949 : :
1950 : 0 : Unref(scalar_v);
1951 : 0 : Unref(vector_v);
1952 : :
1953 : 0 : return result;
1954 : : }
1955 : :
1956 : : // Only case remaining: both are vectors.
1957 : 0 : Val* v2 = op2->Eval(f);
1958 [ # # ]: 0 : if ( ! v2 )
1959 : 0 : return 0;
1960 : :
1961 : 0 : VectorVal* vec_v1 = v1->AsVectorVal();
1962 : 0 : VectorVal* vec_v2 = v2->AsVectorVal();
1963 : :
1964 [ # # ]: 0 : if ( vec_v1->Size() != vec_v2->Size() )
1965 : : {
1966 : 0 : RunTime("vector operands have different sizes");
1967 : 0 : return 0;
1968 : : }
1969 : :
1970 : 0 : VectorVal* result = new VectorVal(Type()->AsVectorType());
1971 : 0 : result->Resize(vec_v1->Size());
1972 : :
1973 [ # # ]: 0 : for ( unsigned int i = VECTOR_MIN;
1974 : : i < vec_v1->Size() + VECTOR_MIN; ++i )
1975 : : {
1976 : 0 : Val* op1 = vec_v1->Lookup(i);
1977 : 0 : Val* op2 = vec_v2->Lookup(i);
1978 [ # # # # ]: 0 : if ( op1 && op2 )
1979 : : {
1980 : : bool local_result = (tag == EXPR_AND) ?
1981 : : (! op1->IsZero() && ! op2->IsZero()) :
1982 [ # # ][ # # ]: 0 : (! op1->IsZero() || ! op2->IsZero());
[ # # ][ # # ]
[ # # ]
1983 : :
1984 : 0 : result->Assign(i, new Val(local_result, TYPE_BOOL), this);
1985 : : }
1986 : : else
1987 : 0 : result->Assign(i, 0, this);
1988 : : }
1989 : :
1990 : 0 : Unref(v1);
1991 : 0 : Unref(v2);
1992 : :
1993 : 63375 : return result;
1994 : : }
1995 : :
1996 : 0 : Expr* BoolExpr::DoSimplify()
1997 : : {
1998 [ # # ][ # # ]: 0 : if ( op1->IsConst() && ! is_vector(op1) )
[ # # ]
1999 : : {
2000 [ # # ]: 0 : if ( op1->IsZero() )
2001 : : // F && x or F || x
2002 [ # # ]: 0 : return (tag == EXPR_AND) ? make_zero(type) : op2->Ref();
2003 : : else
2004 : : // T && x or T || x
2005 [ # # ]: 0 : return (tag == EXPR_AND) ? op2->Ref() : make_one(type);
2006 : : }
2007 : :
2008 [ # # ][ # # ]: 0 : else if ( op2->IsConst() && ! is_vector(op2) )
[ # # ]
2009 : : {
2010 [ # # ]: 0 : if ( op1->IsZero() )
2011 : : // x && F or x || F
2012 [ # # ]: 0 : return (tag == EXPR_AND) ? make_zero(type) : op1->Ref();
2013 : : else
2014 : : // x && T or x || T
2015 [ # # ]: 0 : return (tag == EXPR_AND) ? op1->Ref() : make_one(type);
2016 : : }
2017 : :
2018 [ # # ]: 0 : else if ( same_expr(op1, op2) )
2019 : : {
2020 : 0 : Warn("redundant boolean operation");
2021 : 0 : return op1->Ref();
2022 : : }
2023 : :
2024 : 0 : return this;
2025 : : }
2026 : :
2027 : 3 : IMPLEMENT_SERIAL(BoolExpr, SER_BOOL_EXPR);
2028 : :
2029 : 0 : bool BoolExpr::DoSerialize(SerialInfo* info) const
2030 : : {
2031 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_BOOL_EXPR, BinaryExpr);
2032 : 0 : return true;
2033 : : }
2034 : :
2035 : 0 : bool BoolExpr::DoUnserialize(UnserialInfo* info)
2036 : : {
2037 [ # # ]: 0 : DO_UNSERIALIZE(BinaryExpr);
2038 : 0 : return true;
2039 : : }
2040 : :
2041 : 882 : EqExpr::EqExpr(BroExprTag arg_tag, Expr* arg_op1, Expr* arg_op2)
2042 : 882 : : BinaryExpr(arg_tag, arg_op1, arg_op2)
2043 : : {
2044 [ + - # # ]: 882 : if ( IsError() )
2045 : 882 : return;
2046 : :
2047 : 882 : Canonicize();
2048 : :
2049 : 882 : TypeTag bt1 = op1->Type()->Tag();
2050 [ - + # # ]: 882 : if ( IsVector(bt1) )
2051 : 0 : bt1 = op1->Type()->AsVectorType()->YieldType()->Tag();
2052 : :
2053 : 882 : TypeTag bt2 = op2->Type()->Tag();
2054 [ - + # # ]: 882 : if ( IsVector(bt2) )
2055 : 0 : bt2 = op2->Type()->AsVectorType()->YieldType()->Tag();
2056 : :
2057 [ + - ][ - + ]: 882 : if ( is_vector(op1) || is_vector(op2) )
[ - + ][ # # ]
[ # # ][ # # ]
2058 : 0 : SetType(new VectorType(base_type(TYPE_BOOL)));
2059 : : else
2060 : 882 : SetType(base_type(TYPE_BOOL));
2061 : :
2062 [ + + ][ + + ]: 1214 : if ( BothArithmetic(bt1, bt2) )
[ + - ][ + + ]
[ + + ][ + + ]
[ + - ][ + + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2063 : 332 : PromoteOps(max_type(bt1, bt2));
2064 : :
2065 [ + - ][ + + ]: 550 : else if ( EitherArithmetic(bt1, bt2) &&
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + + ]
[ + + ][ - + ]
[ + - ][ + - ]
[ + + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2066 : : // Allow comparisons with zero.
2067 : : ((bt1 == TYPE_TIME && op2->IsZero()) ||
2068 : : (bt2 == TYPE_TIME && op1->IsZero())) )
2069 : 3 : PromoteOps(TYPE_TIME);
2070 : :
2071 [ + + ][ # # ]: 547 : else if ( bt1 == bt2 )
2072 : : {
2073 [ + + - ]: 498 : switch ( bt1 ) {
[ # # # ]
2074 : : case TYPE_BOOL:
2075 : : case TYPE_TIME:
2076 : : case TYPE_INTERVAL:
2077 : : case TYPE_STRING:
2078 : : case TYPE_PORT:
2079 : : case TYPE_ADDR:
2080 : : case TYPE_NET:
2081 : : case TYPE_SUBNET:
2082 : : case TYPE_ERROR:
2083 : 372 : break;
2084 : :
2085 : : case TYPE_ENUM:
2086 [ - + ][ # # ]: 126 : if ( ! same_type(op1->Type(), op2->Type()) )
2087 : 0 : ExprError("illegal enum comparison");
2088 : 126 : break;
2089 : :
2090 : : default:
2091 : 498 : ExprError("illegal comparison");
2092 : : }
2093 : : }
2094 : :
2095 [ + - ][ + - ]: 49 : else if ( bt1 == TYPE_PATTERN && bt2 == TYPE_STRING )
[ # # ][ # # ]
2096 : : ;
2097 : :
2098 : : else
2099 : 882 : ExprError("type clash in comparison");
2100 : 0 : }
2101 : :
2102 : 882 : void EqExpr::Canonicize()
2103 : : {
2104 [ + + ]: 882 : if ( op2->Type()->Tag() == TYPE_PATTERN )
2105 : 49 : SwapOps();
2106 : :
2107 [ + - ]: 833 : else if ( op1->Type()->Tag() == TYPE_PATTERN )
2108 : : ;
2109 : :
2110 [ + + ]: 833 : else if ( expr_greater(op2, op1) )
2111 : 349 : SwapOps();
2112 : 882 : }
2113 : :
2114 : 0 : Expr* EqExpr::DoSimplify()
2115 : : {
2116 [ # # ][ # # ]: 0 : if ( same_expr(op1, op2) && ! is_vector(op1) )
[ # # ]
2117 : : {
2118 [ # # ]: 0 : if ( ! optimize )
2119 : 0 : Warn("redundant comparison");
2120 : :
2121 [ # # ]: 0 : if ( tag == EXPR_EQ )
2122 : 0 : return make_one(type);
2123 : : else
2124 : 0 : return make_zero(type);
2125 : : }
2126 : :
2127 : 0 : return this;
2128 : : }
2129 : :
2130 : 103627 : Val* EqExpr::Fold(Val* v1, Val* v2) const
2131 : : {
2132 [ + + ]: 103627 : if ( op1->Type()->Tag() == TYPE_PATTERN )
2133 : : {
2134 : 8 : RE_Matcher* re = v1->AsPattern();
2135 : 8 : const BroString* s = v2->AsString();
2136 [ + - ]: 8 : if ( tag == EXPR_EQ )
2137 : 8 : return new Val(re->MatchExactly(s), TYPE_BOOL);
2138 : : else
2139 : 0 : return new Val(! re->MatchExactly(s), TYPE_BOOL);
2140 : : }
2141 : :
2142 : : else
2143 : 103627 : return BinaryExpr::Fold(v1, v2);
2144 : : }
2145 : :
2146 : 3 : IMPLEMENT_SERIAL(EqExpr, SER_EQ_EXPR);
2147 : :
2148 : 0 : bool EqExpr::DoSerialize(SerialInfo* info) const
2149 : : {
2150 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_EQ_EXPR, BinaryExpr);
2151 : 0 : return true;
2152 : : }
2153 : :
2154 : 0 : bool EqExpr::DoUnserialize(UnserialInfo* info)
2155 : : {
2156 [ # # ]: 0 : DO_UNSERIALIZE(BinaryExpr);
2157 : 0 : return true;
2158 : : }
2159 : :
2160 : 336 : RelExpr::RelExpr(BroExprTag arg_tag, Expr* arg_op1, Expr* arg_op2)
2161 : 336 : : BinaryExpr(arg_tag, arg_op1, arg_op2)
2162 : : {
2163 [ + - # # ]: 336 : if ( IsError() )
2164 : 336 : return;
2165 : :
2166 : 336 : Canonicize();
2167 : :
2168 : 336 : TypeTag bt1 = op1->Type()->Tag();
2169 [ - + # # ]: 336 : if ( IsVector(bt1) )
2170 : 0 : bt1 = op1->Type()->AsVectorType()->YieldType()->Tag();
2171 : :
2172 : 336 : TypeTag bt2 = op2->Type()->Tag();
2173 [ - + # # ]: 336 : if ( IsVector(bt2) )
2174 : 0 : bt2 = op2->Type()->AsVectorType()->YieldType()->Tag();
2175 : :
2176 [ + - ][ - + ]: 336 : if ( is_vector(op1) || is_vector(op2) )
[ - + ][ # # ]
[ # # ][ # # ]
2177 : 0 : SetType(new VectorType(base_type(TYPE_BOOL)));
2178 : : else
2179 : 336 : SetType(base_type(TYPE_BOOL));
2180 : :
2181 [ + + ][ + + ]: 632 : if ( BothArithmetic(bt1, bt2) )
[ + - ][ + + ]
[ + + ][ + + ]
[ + - ][ + - ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2182 : 296 : PromoteOps(max_type(bt1, bt2));
2183 : :
2184 [ - + ][ # # ]: 40 : else if ( bt1 != bt2 )
2185 : 0 : ExprError("operands must be of the same type");
2186 : :
2187 [ + + ][ + + ]: 40 : else if ( bt1 != TYPE_TIME && bt1 != TYPE_INTERVAL &&
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2188 : : bt1 != TYPE_PORT && bt1 != TYPE_ADDR &&
2189 : : bt1 != TYPE_STRING )
2190 : 336 : ExprError("illegal comparison");
2191 : 0 : }
2192 : :
2193 : 0 : Expr* RelExpr::DoSimplify()
2194 : : {
2195 [ # # ]: 0 : if ( same_expr(op1, op2) )
2196 : : {
2197 : 0 : Warn("redundant comparison");
2198 : : // Here we use the fact that the canonical form of
2199 : : // a RelExpr only uses EXPR_LE or EXPR_LT.
2200 [ # # ]: 0 : if ( tag == EXPR_LE )
2201 : 0 : return make_one(type);
2202 : : else
2203 : 0 : return make_zero(type);
2204 : : }
2205 : :
2206 : 0 : return this;
2207 : : }
2208 : :
2209 : 336 : void RelExpr::Canonicize()
2210 : : {
2211 [ + + ]: 336 : if ( tag == EXPR_GT )
2212 : : {
2213 : 165 : SwapOps();
2214 : 165 : tag = EXPR_LT;
2215 : : }
2216 : :
2217 [ + + ]: 171 : else if ( tag == EXPR_GE )
2218 : : {
2219 : 74 : SwapOps();
2220 : 74 : tag = EXPR_LE;
2221 : : }
2222 : 336 : }
2223 : :
2224 : 3 : IMPLEMENT_SERIAL(RelExpr, SER_REL_EXPR);
2225 : :
2226 : 0 : bool RelExpr::DoSerialize(SerialInfo* info) const
2227 : : {
2228 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_REL_EXPR, BinaryExpr);
2229 : 0 : return true;
2230 : : }
2231 : :
2232 : 0 : bool RelExpr::DoUnserialize(UnserialInfo* info)
2233 : : {
2234 [ # # ]: 0 : DO_UNSERIALIZE(BinaryExpr);
2235 : 0 : return true;
2236 : : }
2237 : :
2238 : 269 : CondExpr::CondExpr(Expr* arg_op1, Expr* arg_op2, Expr* arg_op3)
2239 : 269 : : Expr(EXPR_COND)
2240 : : {
2241 : 269 : op1 = arg_op1;
2242 : 269 : op2 = arg_op2;
2243 : 269 : op3 = arg_op3;
2244 : :
2245 : 269 : TypeTag bt1 = op1->Type()->Tag();
2246 [ - + # # ]: 269 : if ( IsVector(bt1) )
2247 : 0 : bt1 = op1->Type()->AsVectorType()->YieldType()->Tag();
2248 : :
2249 [ + - ][ + - ]: 269 : if ( op1->IsError() || op2->IsError() || op3->IsError() )
[ - + ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
2250 : 0 : SetError();
2251 : :
2252 [ - + ][ # # ]: 269 : else if ( bt1 != TYPE_BOOL )
2253 : 0 : ExprError("requires boolean conditional");
2254 : :
2255 : : else
2256 : : {
2257 : 269 : TypeTag bt2 = op2->Type()->Tag();
2258 [ - + # # ]: 269 : if ( is_vector(op2) )
2259 : 0 : bt2 = op2->Type()->AsVectorType()->YieldType()->Tag();
2260 : :
2261 : 269 : TypeTag bt3 = op3->Type()->Tag();
2262 [ - + # # ]: 269 : if ( IsVector(bt3) )
2263 : 0 : bt3 = op3->Type()->AsVectorType()->YieldType()->Tag();
2264 : :
2265 [ - + ][ # # ]: 269 : if ( is_vector(op1) && ! (is_vector(op2) && is_vector(op3)) )
[ # # ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
2266 : : {
2267 : 0 : ExprError("vector conditional requires vector alternatives");
2268 : 0 : return;
2269 : : }
2270 : :
2271 [ + + ][ + + ]: 300 : if ( BothArithmetic(bt2, bt3) )
[ + - ][ + + ]
[ + + ][ + + ]
[ + - ][ + - ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2272 : : {
2273 : 31 : TypeTag t = max_type(bt2, bt3);
2274 [ - + # # ]: 31 : if ( bt2 != t )
2275 : 0 : op2 = new ArithCoerceExpr(op2, t);
2276 [ - + ][ # # ]: 31 : if ( bt3 != t )
2277 : 0 : op3 = new ArithCoerceExpr(op3, t);
2278 : :
2279 [ - + ][ # # ]: 31 : if ( is_vector(op2) )
2280 : 0 : SetType(new VectorType(base_type(t)));
2281 : : else
2282 : 31 : SetType(base_type(t));
2283 : : }
2284 : :
2285 [ - + ][ # # ]: 238 : else if ( bt2 != bt3 )
2286 : 0 : ExprError("operands must be of the same type");
2287 : :
2288 : : else
2289 : 269 : SetType(op2->Type()->Ref());
2290 : : }
2291 : 269 : }
2292 : :
2293 : 0 : CondExpr::~CondExpr()
2294 : : {
2295 : 0 : Unref(op1);
2296 : 0 : Unref(op2);
2297 : 0 : Unref(op3);
2298 [ # # ][ # # ]: 0 : }
[ # # ]
2299 : :
2300 : 0 : Expr* CondExpr::Simplify(SimplifyType /* simp_type */)
2301 : : {
2302 : 0 : op1 = simplify_expr(op1, SIMPLIFY_GENERAL);
2303 : 0 : op2 = simplify_expr(op2, SIMPLIFY_GENERAL);
2304 : 0 : op3 = simplify_expr(op3, SIMPLIFY_GENERAL);
2305 : :
2306 [ # # # # ]: 0 : if ( op1->IsConst() && ! is_vector(op1) )
[ # # ]
2307 : : {
2308 : 0 : Val* v = op1->ExprVal();
2309 [ # # ]: 0 : return (v->IsZero() ? op3 : op2)->Ref();
2310 : : }
2311 : :
2312 [ # # ]: 0 : if ( op1->Tag() == EXPR_NOT )
2313 : : return new CondExpr(((NotExpr*) op1)->Op()->Ref(),
2314 : 0 : op3->Ref(), op2->Ref());
2315 : :
2316 : 0 : return this;
2317 : : }
2318 : :
2319 : 35221 : Val* CondExpr::Eval(Frame* f) const
2320 : : {
2321 [ + - ]: 35221 : if ( ! is_vector(op1) )
2322 : : { // scalar is easy
2323 : 35221 : Val* v = op1->Eval(f);
2324 : 35221 : int false_eval = v->IsZero();
2325 : 35221 : Unref(v);
2326 : :
2327 [ + + ][ + + ]: 35221 : return (false_eval ? op3 : op2)->Eval(f);
[ + + ]
2328 : : }
2329 : :
2330 : : // Vector case: no mixed scalar/vector cases allowed
2331 : 0 : Val* v1 = op1->Eval(f);
2332 [ # # ]: 0 : if ( ! v1 )
2333 : 0 : return 0;
2334 : :
2335 : 0 : Val* v2 = op2->Eval(f);
2336 [ # # ]: 0 : if ( ! v2 )
2337 : 0 : return 0;
2338 : :
2339 : 0 : Val* v3 = op3->Eval(f);
2340 [ # # ]: 0 : if ( ! v3 )
2341 : 0 : return 0;
2342 : :
2343 : 0 : VectorVal* cond = v1->AsVectorVal();
2344 : 0 : VectorVal* a = v2->AsVectorVal();
2345 : 0 : VectorVal* b = v3->AsVectorVal();
2346 : :
2347 [ # # # # ]: 0 : if ( cond->Size() != a->Size() || a->Size() != b->Size() )
[ # # ]
2348 : : {
2349 : 0 : RunTime("vectors in conditional expression have different sizes");
2350 : 0 : return 0;
2351 : : }
2352 : :
2353 : 0 : VectorVal* result = new VectorVal(Type()->AsVectorType());
2354 : 0 : result->Resize(cond->Size());
2355 : :
2356 [ # # ]: 0 : for ( unsigned int i = VECTOR_MIN; i < cond->Size() + VECTOR_MIN; ++i )
2357 : : {
2358 : 0 : Val* local_cond = cond->Lookup(i);
2359 [ # # ]: 0 : if ( local_cond )
2360 : : result->Assign(i,
2361 : : local_cond->IsZero() ?
2362 : : b->Lookup(i) : a->Lookup(i),
2363 [ # # ]: 0 : this);
2364 : : else
2365 : 0 : result->Assign(i, 0, this);
2366 : : }
2367 : :
2368 : 35221 : return result;
2369 : : }
2370 : :
2371 : 0 : int CondExpr::IsPure() const
2372 : : {
2373 [ # # ][ # # ]: 0 : return op1->IsPure() && op2->IsPure() && op3->IsPure();
[ # # ]
2374 : : }
2375 : :
2376 : 0 : TraversalCode CondExpr::Traverse(TraversalCallback* cb) const
2377 : : {
2378 : 0 : TraversalCode tc = cb->PreExpr(this);
2379 [ # # ]: 0 : HANDLE_TC_EXPR_PRE(tc);
2380 : :
2381 : 0 : tc = op1->Traverse(cb);
2382 [ # # ]: 0 : HANDLE_TC_EXPR_PRE(tc);
2383 : :
2384 : 0 : tc = op2->Traverse(cb);
2385 [ # # ]: 0 : HANDLE_TC_EXPR_PRE(tc);
2386 : :
2387 : 0 : tc = op3->Traverse(cb);
2388 [ # # ]: 0 : HANDLE_TC_EXPR_PRE(tc);
2389 : :
2390 : 0 : tc = cb->PostExpr(this);
2391 : 0 : HANDLE_TC_EXPR_POST(tc);
2392 : : }
2393 : :
2394 : 0 : void CondExpr::ExprDescribe(ODesc* d) const
2395 : : {
2396 : 0 : op1->Describe(d);
2397 : 0 : d->AddSP(" ?");
2398 : 0 : op2->Describe(d);
2399 : 0 : d->AddSP(" :");
2400 : 0 : op3->Describe(d);
2401 : 0 : }
2402 : :
2403 : 3 : IMPLEMENT_SERIAL(CondExpr, SER_COND_EXPR);
2404 : :
2405 : 0 : bool CondExpr::DoSerialize(SerialInfo* info) const
2406 : : {
2407 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_COND_EXPR, Expr);
2408 : : return op1->Serialize(info) && op2->Serialize(info)
2409 [ # # ][ # # ]: 0 : && op3->Serialize(info);
[ # # ]
2410 : : }
2411 : :
2412 : 0 : bool CondExpr::DoUnserialize(UnserialInfo* info)
2413 : : {
2414 [ # # ]: 0 : DO_UNSERIALIZE(Expr);
2415 : :
2416 : 0 : op1 = Expr::Unserialize(info);
2417 [ # # ]: 0 : if ( ! op1 )
2418 : 0 : return false;
2419 : :
2420 : 0 : op2 = Expr::Unserialize(info);
2421 [ # # ]: 0 : if ( ! op2 )
2422 : 0 : return false;
2423 : :
2424 : 0 : op3 = Expr::Unserialize(info);
2425 : :
2426 : 0 : return op3 != 0;
2427 : : }
2428 : :
2429 : 2559 : RefExpr::RefExpr(Expr* arg_op) : UnaryExpr(EXPR_REF, arg_op)
2430 : : {
2431 [ + - # # ]: 2559 : if ( IsError() )
2432 : 2559 : return;
2433 : :
2434 [ - + ][ # # ]: 2559 : if ( ! is_assignable(op->Type()) )
2435 : 0 : ExprError("illegal assignment target");
2436 : : else
2437 : 2559 : SetType(op->Type()->Ref());
2438 : 0 : }
2439 : :
2440 : 0 : Expr* RefExpr::MakeLvalue()
2441 : : {
2442 : 0 : return this;
2443 : : }
2444 : :
2445 : 0 : Val* RefExpr::Eval(Val* v) const
2446 : : {
2447 : 0 : return Fold(v);
2448 : : }
2449 : :
2450 : 243001 : void RefExpr::Assign(Frame* f, Val* v, Opcode opcode)
2451 : : {
2452 : 243001 : op->Assign(f, v, opcode);
2453 : 243001 : }
2454 : :
2455 : 3 : IMPLEMENT_SERIAL(RefExpr, SER_REF_EXPR);
2456 : :
2457 : 0 : bool RefExpr::DoSerialize(SerialInfo* info) const
2458 : : {
2459 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_REF_EXPR, UnaryExpr);
2460 : 0 : return true;
2461 : : }
2462 : :
2463 : 0 : bool RefExpr::DoUnserialize(UnserialInfo* info)
2464 : : {
2465 [ # # ]: 0 : DO_UNSERIALIZE(UnaryExpr);
2466 : 0 : return true;
2467 : : }
2468 : :
2469 : : AssignExpr::AssignExpr(Expr* arg_op1, Expr* arg_op2, int arg_is_init,
2470 : 3625 : Val* arg_val)
2471 : : : BinaryExpr(EXPR_ASSIGN,
2472 [ + + ][ # # ]: 3625 : arg_is_init ? arg_op1 : arg_op1->MakeLvalue(), arg_op2)
2473 : : {
2474 : 3625 : is_init = arg_is_init;
2475 : :
2476 [ + - # # ]: 3625 : if ( IsError() )
2477 : 3625 : return;
2478 : :
2479 [ + + ][ # # ]: 3625 : SetType(arg_val ? arg_val->Type()->Ref() : op1->Type()->Ref());
2480 : :
2481 [ + + # # ]: 3625 : if ( is_init )
2482 : : {
2483 : : SetLocationInfo(arg_op1->GetLocationInfo(),
2484 : 1228 : arg_op2->GetLocationInfo());
2485 : 1228 : return;
2486 : : }
2487 : :
2488 : : // We discard the status from TypeCheck since it has already
2489 : : // generated error messages.
2490 : 2397 : (void) TypeCheck();
2491 : :
2492 [ + + ][ # # ]: 2397 : val = arg_val ? arg_val->Ref() : 0;
2493 : :
2494 : 2397 : SetLocationInfo(arg_op1->GetLocationInfo(), arg_op2->GetLocationInfo());
2495 : 0 : }
2496 : :
2497 : 2397 : bool AssignExpr::TypeCheck()
2498 : : {
2499 : 2397 : TypeTag bt1 = op1->Type()->Tag();
2500 [ + + ]: 2397 : if ( IsVector(bt1) )
2501 : 6 : bt1 = op1->Type()->AsVectorType()->YieldType()->Tag();
2502 : :
2503 : 2397 : TypeTag bt2 = op2->Type()->Tag();
2504 [ + + ]: 2397 : if ( IsVector(bt2) )
2505 : 6 : bt2 = op2->Type()->AsVectorType()->YieldType()->Tag();
2506 : :
2507 [ - + ][ # # ]: 2397 : if ( bt1 == TYPE_LIST && bt2 == TYPE_ANY )
2508 : : // This is ok because we cannot explicitly declare lists on
2509 : : // the script level.
2510 : 0 : return true;
2511 : :
2512 [ - + ]: 2397 : if ( ((bt1 == TYPE_ENUM) ^ (bt2 == TYPE_ENUM)) )
2513 : : {
2514 : 0 : ExprError("can't convert to/from enumerated type");
2515 : 0 : return false;
2516 : : }
2517 : :
2518 [ + + ][ + + ]: 2397 : if ( IsArithmetic(bt1) )
[ + - ][ + + ]
2519 : 401 : return TypeCheckArithmetics(bt1, bt2);
2520 : :
2521 [ + + ][ + - ]: 1996 : if ( bt1 == TYPE_TIME && IsArithmetic(bt2) && op2->IsZero() )
[ + + ][ + - ]
[ + + ][ + - ]
[ + + ]
2522 : : { // Allow assignments to zero as a special case.
2523 : 2 : op2 = new ArithCoerceExpr(op2, bt1);
2524 : 2 : return true;
2525 : : }
2526 : :
2527 [ + + ][ + - ]: 1994 : if ( bt1 == TYPE_TABLE && bt2 == bt1 &&
[ + + ][ + + ]
2528 : : op2->Type()->AsTableType()->IsUnspecifiedTable() )
2529 : : {
2530 : 41 : op2 = new TableCoerceExpr(op2, op1->Type()->AsTableType());
2531 : 41 : return true;
2532 : : }
2533 : :
2534 [ + + ]: 1953 : if ( ! same_type(op1->Type(), op2->Type()) )
2535 : : {
2536 [ + - ][ + - ]: 6 : if ( op1->Type()->Tag() == TYPE_RECORD &&
[ + - ]
2537 : : op2->Type()->Tag() == TYPE_RECORD )
2538 : 6 : op2 = new RecordCoerceExpr(op2, op1->Type()->AsRecordType());
2539 : : else
2540 : : {
2541 : 0 : ExprError("type clash in assignment");
2542 : 0 : return false;
2543 : : }
2544 : : }
2545 : :
2546 : 2397 : return true;
2547 : : }
2548 : :
2549 : 401 : bool AssignExpr::TypeCheckArithmetics(TypeTag bt1, TypeTag bt2)
2550 : : {
2551 [ + + ][ + + ]: 401 : if ( ! IsArithmetic(bt2) )
[ + - ][ - + ]
2552 : : {
2553 : : char err[512];
2554 : : snprintf(err, sizeof(err),
2555 : : "assignment of non-arithmetic value to arithmetic (%s/%s)",
2556 : 0 : type_name(bt1), type_name(bt2));
2557 : 0 : ExprError(err);
2558 : 0 : return false;
2559 : : }
2560 : :
2561 [ + + ]: 401 : if ( bt1 == TYPE_DOUBLE )
2562 : : {
2563 : 27 : PromoteOps(TYPE_DOUBLE);
2564 : 27 : return true;
2565 : : }
2566 : :
2567 [ - + ]: 374 : if ( bt2 == TYPE_DOUBLE )
2568 : : {
2569 : 0 : Warn("dangerous assignment of double to integral");
2570 : 0 : op2 = new ArithCoerceExpr(op2, bt1);
2571 : 0 : bt2 = op2->Type()->Tag();
2572 : : }
2573 : :
2574 [ + + ]: 374 : if ( bt1 == TYPE_INT )
2575 : 27 : PromoteOps(TYPE_INT);
2576 : : else
2577 : : {
2578 [ - + ]: 347 : if ( bt2 == TYPE_INT )
2579 : : {
2580 : 0 : Warn("dangerous assignment of integer to count");
2581 : 0 : op2 = new ArithCoerceExpr(op2, bt1);
2582 : 0 : bt2 = op2->Type()->Tag();
2583 : : }
2584 : :
2585 : : // Assignment of count to counter or vice
2586 : : // versa is allowed, and requires no
2587 : : // coercion.
2588 : : }
2589 : :
2590 : 401 : return true;
2591 : : }
2592 : :
2593 : :
2594 : 0 : Expr* AssignExpr::Simplify(SimplifyType /* simp_type */)
2595 : : {
2596 : 0 : op1 = simplify_expr(op1, SIMPLIFY_LHS);
2597 : 0 : op2 = simplify_expr(op2, SIMPLIFY_GENERAL);
2598 : 0 : return this;
2599 : : }
2600 : :
2601 : 239553 : Val* AssignExpr::Eval(Frame* f) const
2602 : : {
2603 [ - + ]: 239553 : if ( is_init )
2604 : : {
2605 : 0 : Error("illegal assignment in initialization");
2606 : 0 : return 0;
2607 : : }
2608 : :
2609 : 239553 : Val* v = op2->Eval(f);
2610 : :
2611 [ + - ]: 239553 : if ( v )
2612 : : {
2613 : 239553 : op1->Assign(f, v);
2614 : : //### op1->SetAttribs();
2615 [ + + ]: 239553 : return val ? val->Ref() : v->Ref();
2616 : : }
2617 : : else
2618 : 239553 : return 0;
2619 : : }
2620 : :
2621 : 379 : BroType* AssignExpr::InitType() const
2622 : : {
2623 [ - + ]: 379 : if ( op1->Tag() != EXPR_LIST )
2624 : : {
2625 : 0 : Error("bad initializer");
2626 : 0 : return 0;
2627 : : }
2628 : :
2629 : 379 : BroType* tl = op1->Type();
2630 [ - + ]: 379 : if ( tl->Tag() != TYPE_LIST )
2631 : 0 : Internal("inconsistent list expr in AssignExpr::InitType");
2632 : :
2633 : 379 : return new TableType(tl->Ref()->AsTypeList(), op2->Type()->Ref());
2634 : : }
2635 : :
2636 : 0 : void AssignExpr::EvalIntoAggregate(const BroType* t, Val* aggr, Frame* f) const
2637 : : {
2638 [ # # ]: 0 : if ( IsError() )
2639 : 0 : return;
2640 : :
2641 : 0 : TypeDecl td(0, 0);
2642 [ # # ]: 0 : if ( IsRecordElement(&td) )
2643 : : {
2644 [ # # ]: 0 : if ( t->Tag() != TYPE_RECORD )
2645 : : {
2646 : 0 : Error("not a record initializer", t);
2647 : : return;
2648 : : }
2649 : :
2650 : 0 : const RecordType* rt = t->AsRecordType();
2651 : 0 : int field = rt->FieldOffset(td.id);
2652 : :
2653 [ # # ]: 0 : if ( field < 0 )
2654 : : {
2655 : 0 : Error("no such field");
2656 : : return;
2657 : : }
2658 : :
2659 : 0 : RecordVal* aggr_r = aggr->AsRecordVal();
2660 : :
2661 : 0 : Val* v = op2->Eval(f);
2662 [ # # ]: 0 : if ( v )
2663 : 0 : aggr_r->Assign(field, v);
2664 : :
2665 : : return;
2666 : : }
2667 : :
2668 [ # # ]: 0 : if ( op1->Tag() != EXPR_LIST )
2669 : 0 : Error("bad table insertion");
2670 : :
2671 : 0 : TableVal* tv = aggr->AsTableVal();
2672 : 0 : const TableType* tt = tv->Type()->AsTableType();
2673 : 0 : const BroType* yt = tv->Type()->YieldType();
2674 : :
2675 : 0 : Val* index = op1->Eval(f);
2676 : 0 : Val* v = op2->Eval(f);
2677 [ # # # # ]: 0 : if ( ! index || ! v )
2678 : 0 : return;
2679 : :
2680 [ # # ]: 0 : if ( ! tv->Assign(index, v) )
2681 : 0 : Error("type clash in table assignment");
2682 : :
2683 [ # # ]: 0 : Unref(index);
2684 : : }
2685 : :
2686 : 1228 : Val* AssignExpr::InitVal(const BroType* t, Val* aggr) const
2687 : : {
2688 [ - + ]: 1228 : if ( ! aggr )
2689 : : {
2690 : 0 : Error("assignment in initialization");
2691 : 0 : return 0;
2692 : : }
2693 : :
2694 [ - + ]: 1228 : if ( IsError() )
2695 : 0 : return 0;
2696 : :
2697 : 1228 : TypeDecl td(0, 0);
2698 [ - + ]: 1228 : if ( IsRecordElement(&td) )
2699 : : {
2700 [ # # ]: 0 : if ( t->Tag() != TYPE_RECORD )
2701 : : {
2702 : 0 : Error("not a record initializer", t);
2703 : 1228 : return 0;
2704 : : }
2705 : 0 : const RecordType* rt = t->AsRecordType();
2706 : 0 : int field = rt->FieldOffset(td.id);
2707 : :
2708 [ # # ]: 0 : if ( field < 0 )
2709 : : {
2710 : 0 : Error("no such field");
2711 : 0 : return 0;
2712 : : }
2713 : :
2714 [ # # ]: 0 : if ( aggr->Type()->Tag() != TYPE_RECORD )
2715 : 0 : Internal("bad aggregate in AssignExpr::InitVal");
2716 : 0 : RecordVal* aggr_r = aggr->AsRecordVal();
2717 : :
2718 : 0 : Val* v = op2->InitVal(rt->FieldType(td.id), 0);
2719 [ # # ]: 0 : if ( ! v )
2720 : 0 : return 0;
2721 : :
2722 : 0 : aggr_r->Assign(field, v);
2723 : 0 : return v;
2724 : : }
2725 : :
2726 [ + - ]: 1228 : else if ( op1->Tag() == EXPR_LIST )
2727 : : {
2728 [ - + ]: 1228 : if ( t->Tag() != TYPE_TABLE )
2729 : : {
2730 : 0 : Error("not a table initialization", t);
2731 : 0 : return 0;
2732 : : }
2733 : :
2734 [ - + ]: 1228 : if ( aggr->Type()->Tag() != TYPE_TABLE )
2735 : 0 : Internal("bad aggregate in AssignExpr::InitVal");
2736 : :
2737 : 1228 : TableVal* tv = aggr->AsTableVal();
2738 : 1228 : const TableType* tt = tv->Type()->AsTableType();
2739 : 1228 : const BroType* yt = tv->Type()->YieldType();
2740 : 1228 : Val* index = op1->InitVal(tt->Indices(), 0);
2741 : 1228 : Val* v = op2->InitVal(yt, 0);
2742 [ + - - + ]: 1228 : if ( ! index || ! v )
2743 : 0 : return 0;
2744 : :
2745 [ - + ]: 1228 : if ( ! tv->ExpandAndInit(index, v) )
2746 : : {
2747 : 0 : Unref(index);
2748 : 0 : Unref(tv);
2749 : 0 : return 0;
2750 : : }
2751 : :
2752 : 1228 : Unref(index);
2753 : 1228 : return tv;
2754 : : }
2755 : :
2756 : : else
2757 : : {
2758 : 0 : Error("illegal initializer");
2759 : 0 : return 0;
2760 : 1228 : }
2761 : : }
2762 : :
2763 : 1246 : int AssignExpr::IsRecordElement(TypeDecl* td) const
2764 : : {
2765 [ - + ]: 1246 : if ( op1->Tag() == EXPR_NAME )
2766 : : {
2767 [ # # ]: 0 : if ( td )
2768 : : {
2769 : 0 : const NameExpr* n = (const NameExpr*) op1;
2770 : 0 : td->type = op2->Type()->Ref();
2771 : 0 : td->id = copy_string(n->Id()->Name());
2772 : : }
2773 : :
2774 : 0 : return 1;
2775 : : }
2776 : : else
2777 : 1246 : return 0;
2778 : : }
2779 : :
2780 : 2365 : int AssignExpr::IsPure() const
2781 : : {
2782 : 2365 : return 0;
2783 : : }
2784 : :
2785 : 3 : IMPLEMENT_SERIAL(AssignExpr, SER_ASSIGN_EXPR);
2786 : :
2787 : 0 : bool AssignExpr::DoSerialize(SerialInfo* info) const
2788 : : {
2789 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_ASSIGN_EXPR, BinaryExpr);
2790 [ # # ][ # # ]: 0 : SERIALIZE_OPTIONAL(val);
[ # # ][ # # ]
[ # # ][ # # ]
2791 : 0 : return SERIALIZE(is_init);
2792 : : }
2793 : :
2794 : 0 : bool AssignExpr::DoUnserialize(UnserialInfo* info)
2795 : : {
2796 [ # # ]: 0 : DO_UNSERIALIZE(BinaryExpr);
2797 [ # # ][ # # ]: 0 : UNSERIALIZE_OPTIONAL(val, Val::Unserialize(info));
[ # # ]
2798 : 0 : return UNSERIALIZE(&is_init);
2799 : : }
2800 : :
2801 : 1367 : IndexExpr::IndexExpr(Expr* arg_op1, ListExpr* arg_op2)
2802 : 1367 : : BinaryExpr(EXPR_INDEX, arg_op1, arg_op2)
2803 : : {
2804 [ + - # # ]: 1367 : if ( IsError() )
2805 : 1367 : return;
2806 : :
2807 : 1367 : int match_type = op1->Type()->MatchesIndex(arg_op2);
2808 [ - + # # ]: 1367 : if ( match_type == DOES_NOT_MATCH_INDEX )
2809 : 0 : SetError("not an index type");
2810 : :
2811 [ + + ][ # # ]: 1367 : else if ( ! op1->Type()->YieldType() )
2812 : : // It's a set - so indexing it yields void. We don't
2813 : : // directly generate an error message, though, since this
2814 : : // expression might be part of an add/delete statement,
2815 : : // rather than yielding a value.
2816 : 168 : SetType(base_type(TYPE_VOID));
2817 : :
2818 [ + - ][ # # ]: 1199 : else if ( match_type == MATCHES_INDEX_SCALAR )
2819 : 1199 : SetType(op1->Type()->YieldType()->Ref());
2820 : :
2821 [ # # ][ # # ]: 0 : else if ( match_type == MATCHES_INDEX_VECTOR )
2822 : 0 : SetType(new VectorType(op1->Type()->YieldType()->Ref()));
2823 : :
2824 : : else
2825 : 1367 : ExprError("Unknown MatchesIndex() return value");
2826 : :
2827 : 0 : }
2828 : :
2829 : 134 : int IndexExpr::CanAdd() const
2830 : : {
2831 [ - + ]: 134 : if ( IsError() )
2832 : 0 : return 1; // avoid cascading the error report
2833 : :
2834 : : // "add" only allowed if our type is "set".
2835 : 134 : return op1->Type()->IsSet();
2836 : : }
2837 : :
2838 : 141 : int IndexExpr::CanDel() const
2839 : : {
2840 [ - + ]: 141 : if ( IsError() )
2841 : 0 : return 1; // avoid cascading the error report
2842 : :
2843 : 141 : return op1->Type()->Tag() == TYPE_TABLE;
2844 : : }
2845 : :
2846 : 279 : void IndexExpr::Add(Frame* f)
2847 : : {
2848 [ - + ]: 279 : if ( IsError() )
2849 : 0 : return;
2850 : :
2851 : 279 : Val* v1 = op1->Eval(f);
2852 [ - + ]: 279 : if ( ! v1 )
2853 : 0 : return;
2854 : :
2855 : 279 : Val* v2 = op2->Eval(f);
2856 [ - + ]: 279 : if ( ! v2 )
2857 : : {
2858 : 0 : Unref(v1);
2859 : 0 : return;
2860 : : }
2861 : :
2862 : 279 : v1->AsTableVal()->Assign(v2, 0);
2863 : :
2864 : 279 : Unref(v1);
2865 : 279 : Unref(v2);
2866 : : }
2867 : :
2868 : 8295 : void IndexExpr::Delete(Frame* f)
2869 : : {
2870 [ - + ]: 8295 : if ( IsError() )
2871 : 0 : return;
2872 : :
2873 : 8295 : Val* v1 = op1->Eval(f);
2874 [ - + ]: 8295 : if ( ! v1 )
2875 : 0 : return;
2876 : :
2877 : 8295 : Val* v2 = op2->Eval(f);
2878 [ - + ]: 8295 : if ( ! v2 )
2879 : : {
2880 : 0 : Unref(v1);
2881 : 0 : return;
2882 : : }
2883 : :
2884 : 8295 : Unref(v1->AsTableVal()->Delete(v2));
2885 : :
2886 : 8295 : Unref(v1);
2887 : 8295 : Unref(v2);
2888 : : }
2889 : :
2890 : 259 : Expr* IndexExpr::MakeLvalue()
2891 : : {
2892 : 259 : return new RefExpr(this);
2893 : : }
2894 : :
2895 : 0 : Expr* IndexExpr::Simplify(SimplifyType simp_type)
2896 : : {
2897 : 0 : op1 = simplify_expr(op1, simp_type);
2898 : 0 : op2 = simplify_expr(op2, SIMPLIFY_GENERAL);
2899 : 0 : return this;
2900 : : }
2901 : :
2902 : 60003 : Val* IndexExpr::Eval(Frame* f) const
2903 : : {
2904 : 60003 : Val* v1 = op1->Eval(f);
2905 [ - + ]: 60003 : if ( ! v1 )
2906 : 0 : return 0;
2907 : :
2908 : 60003 : Val* v2 = op2->Eval(f);
2909 [ - + ]: 60003 : if ( ! v2 )
2910 : : {
2911 : 0 : Unref(v1);
2912 : 0 : return 0;
2913 : : }
2914 : :
2915 : : Val* result;
2916 : :
2917 : 60003 : Val* indv = v2->AsListVal()->Index(0);
2918 [ - + ]: 60003 : if ( is_vector(indv) )
2919 : : {
2920 : 0 : VectorVal* v_v1 = v1->AsVectorVal();
2921 : 0 : VectorVal* v_v2 = indv->AsVectorVal();
2922 : 0 : VectorVal* v_result = new VectorVal(Type()->AsVectorType());
2923 : 0 : result = v_result;
2924 : :
2925 : : // Booleans select each element (or not).
2926 [ # # ]: 0 : if ( IsBool(v_v2->Type()->YieldType()->Tag()) )
2927 : : {
2928 [ # # ]: 0 : if ( v_v1->Size() != v_v2->Size() )
2929 : : {
2930 : 0 : RunTime("size mismatch, boolean index and vector");
2931 : 0 : return 0;
2932 : : }
2933 : :
2934 [ # # ]: 0 : for ( unsigned int i = VECTOR_MIN;
2935 : : i < v_v2->Size() + VECTOR_MIN; ++i )
2936 : : {
2937 [ # # ]: 0 : if ( v_v2->Lookup(i)->AsBool() )
2938 : 0 : v_result->Assign(v_result->Size() + 1, v_v1->Lookup(i), this);
2939 : : }
2940 : : }
2941 : : else
2942 : : { // The elements are indices.
2943 : : // ### Should handle negative indices here like
2944 : : // S does, i.e., by excluding those elements.
2945 : : // Probably only do this if *all* are negative.
2946 : 0 : v_result->Resize(v_v2->Size());
2947 [ # # ]: 0 : for ( unsigned int i = VECTOR_MIN;
2948 : : i < v_v2->Size() + VECTOR_MIN; ++i )
2949 : 0 : v_result->Assign(i, v_v1->Lookup(v_v2->Lookup(i)->CoerceToInt()), this);
2950 : : }
2951 : : }
2952 : : else
2953 : 60003 : result = Fold(v1, v2);
2954 : :
2955 : 60003 : Unref(v1);
2956 : 60003 : Unref(v2);
2957 : 60003 : return result;
2958 : : }
2959 : :
2960 : 60003 : Val* IndexExpr::Fold(Val* v1, Val* v2) const
2961 : : {
2962 [ - + ]: 60003 : if ( IsError() )
2963 : 0 : return 0;
2964 : :
2965 [ + + ]: 60003 : if ( v1->Type()->Tag() == TYPE_VECTOR )
2966 : : {
2967 : 22174 : Val* v = v1->AsVectorVal()->Lookup(v2);
2968 : : // ### dangerous - this can silently fail larger operations
2969 : : // due to a missing element
2970 [ + - ]: 22174 : return v ? v->Ref() : 0;
2971 : : }
2972 : :
2973 : 37829 : TableVal* v_tbl = v1->AsTableVal();
2974 : 37829 : Val* v = v_tbl->Lookup(v2);
2975 : :
2976 [ + - ]: 37829 : if ( v )
2977 : 37829 : return v->Ref();
2978 : :
2979 : 0 : RunTime("no such index");
2980 : 60003 : return 0;
2981 : : }
2982 : :
2983 : 27409 : void IndexExpr::Assign(Frame* f, Val* v, Opcode op)
2984 : : {
2985 [ - + ]: 27409 : if ( IsError() )
2986 : 0 : return;
2987 : :
2988 : 27409 : Val* v1 = op1->Eval(f);
2989 [ - + ]: 27409 : if ( ! v1 )
2990 : 0 : return;
2991 : :
2992 : 27409 : Val* v2 = op2->Eval(f);
2993 : :
2994 [ + - - + ]: 27409 : if ( ! v1 || ! v2 )
2995 : : {
2996 : 0 : Unref(v1);
2997 : 0 : Unref(v2);
2998 : 0 : return;
2999 : : }
3000 : :
3001 [ - + ]: 27409 : if ( v1->Type()->Tag() == TYPE_VECTOR )
3002 : : {
3003 [ # # ]: 0 : if ( ! v1->AsVectorVal()->Assign(v2, v, this, op) )
3004 : 0 : Internal("assignment failed");
3005 : : }
3006 : :
3007 [ - + ]: 27409 : else if ( ! v1->AsTableVal()->Assign(v2, v, op) )
3008 : 0 : Internal("assignment failed");
3009 : :
3010 : 27409 : Unref(v1);
3011 : 27409 : Unref(v2);
3012 : : }
3013 : :
3014 : 0 : void IndexExpr::ExprDescribe(ODesc* d) const
3015 : : {
3016 : 0 : op1->Describe(d);
3017 [ # # ]: 0 : if ( d->IsReadable() )
3018 : 0 : d->Add("[");
3019 : :
3020 : 0 : op2->Describe(d);
3021 [ # # ]: 0 : if ( d->IsReadable() )
3022 : 0 : d->Add("]");
3023 : 0 : }
3024 : :
3025 : 0 : TraversalCode IndexExpr::Traverse(TraversalCallback* cb) const
3026 : : {
3027 : 0 : TraversalCode tc = cb->PreExpr(this);
3028 [ # # ]: 0 : HANDLE_TC_EXPR_PRE(tc);
3029 : :
3030 : 0 : tc = op1->Traverse(cb);
3031 [ # # ]: 0 : HANDLE_TC_EXPR_PRE(tc);
3032 : :
3033 : 0 : tc = op2->Traverse(cb);
3034 [ # # ]: 0 : HANDLE_TC_EXPR_PRE(tc);
3035 : :
3036 : 0 : tc = cb->PostExpr(this);
3037 : 0 : HANDLE_TC_EXPR_POST(tc);
3038 : : }
3039 : :
3040 : :
3041 : 3 : IMPLEMENT_SERIAL(IndexExpr, SER_INDEX_EXPR);
3042 : :
3043 : 0 : bool IndexExpr::DoSerialize(SerialInfo* info) const
3044 : : {
3045 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_INDEX_EXPR, BinaryExpr);
3046 : 0 : return true;
3047 : : }
3048 : :
3049 : 0 : bool IndexExpr::DoUnserialize(UnserialInfo* info)
3050 : : {
3051 [ # # ]: 0 : DO_UNSERIALIZE(BinaryExpr);
3052 : 0 : return true;
3053 : : }
3054 : :
3055 : 4442 : FieldExpr::FieldExpr(Expr* arg_op, const char* arg_field_name)
3056 : 4442 : : UnaryExpr(EXPR_FIELD, arg_op)
3057 : : {
3058 : 4442 : field_name = copy_string(arg_field_name);
3059 : 4442 : td = 0;
3060 : 4442 : field = 0;
3061 : :
3062 [ + - # # ]: 4442 : if ( IsError() )
3063 : 4442 : return;
3064 : :
3065 [ - + ][ # # ]: 4442 : if ( streq(arg_field_name, "attr") )
3066 : : {
3067 : 0 : field = -1;
3068 : 0 : SetType(op->Type()->AttributesType()->Ref());
3069 : 0 : return;
3070 : : }
3071 : :
3072 [ - + ][ # # ]: 4442 : if ( ! IsRecord(op->Type()->Tag()) )
[ - + ][ # # ]
[ # # ][ # # ]
3073 : 0 : ExprError("not a record");
3074 : : else
3075 : : {
3076 : 4442 : RecordType* rt = op->Type()->AsRecordType();
3077 : 4442 : field = rt->FieldOffset(field_name);
3078 : 4442 : td = rt->FieldDecl(field);
3079 : :
3080 [ - + # # ]: 4442 : if ( field < 0 )
3081 : 0 : ExprError("no such field in record");
3082 : : else
3083 : 4442 : SetType(rt->FieldType(field)->Ref());
3084 : : }
3085 : 0 : }
3086 : :
3087 : 0 : FieldExpr::~FieldExpr()
3088 : : {
3089 [ # # ][ # # ]: 0 : delete [] field_name;
[ # # ]
3090 [ # # ][ # # ]: 0 : }
[ # # ]
3091 : :
3092 : 638 : Expr* FieldExpr::MakeLvalue()
3093 : : {
3094 : 638 : return new RefExpr(this);
3095 : : }
3096 : :
3097 : 0 : Expr* FieldExpr::Simplify(SimplifyType simp_type)
3098 : : {
3099 : 0 : op = simplify_expr(op, simp_type);
3100 : 0 : return this;
3101 : : }
3102 : :
3103 : 21485 : void FieldExpr::Assign(Frame* f, Val* v, Opcode opcode)
3104 : : {
3105 [ + - ][ - + ]: 21485 : if ( IsError() || ! v )
[ - + ]
3106 : 0 : return;
3107 : :
3108 [ - + ]: 21485 : if ( field < 0 )
3109 : : {
3110 : 0 : Val* lhs = op->Eval(f);
3111 : 0 : lhs->SetAttribs(v->AsRecordVal());
3112 : 0 : Unref(lhs);
3113 : 0 : return;
3114 : : }
3115 : :
3116 : 21485 : Val* op_v = op->Eval(f);
3117 [ + - ]: 21485 : if ( op_v )
3118 : : {
3119 : 21485 : RecordVal* r = op_v->AsRecordVal();
3120 : 21485 : r->Assign(field, v, opcode);
3121 : 21485 : Unref(r);
3122 : : }
3123 : : }
3124 : :
3125 : 178800 : Val* FieldExpr::Fold(Val* v) const
3126 : : {
3127 [ - + ]: 178800 : if ( field < 0 )
3128 : 0 : return v->GetAttribs(true)->Ref();
3129 : :
3130 : 178800 : Val* result = v->AsRecordVal()->Lookup(field);
3131 [ + + ]: 178800 : if ( result )
3132 : 176042 : return result->Ref();
3133 : :
3134 : : // Check for &default.
3135 [ + - ]: 2758 : const Attr* def_attr = td ? td->FindAttr(ATTR_DEFAULT) : 0;
3136 [ + - ]: 2758 : if ( def_attr )
3137 : 2758 : return def_attr->AttrExpr()->Eval(0);
3138 : : else
3139 : : {
3140 : 0 : Internal("field value missing");
3141 : 178800 : return 0;
3142 : : }
3143 : : }
3144 : :
3145 : 0 : void FieldExpr::ExprDescribe(ODesc* d) const
3146 : : {
3147 : 0 : op->Describe(d);
3148 [ # # ]: 0 : if ( d->IsReadable() )
3149 : 0 : d->Add("$");
3150 : :
3151 [ # # ]: 0 : if ( IsError() )
3152 : 0 : d->Add("<error>");
3153 [ # # ]: 0 : else if ( d->IsReadable() )
3154 : 0 : d->Add(field_name);
3155 : : else
3156 : 0 : d->Add(field);
3157 : 0 : }
3158 : :
3159 : 3 : IMPLEMENT_SERIAL(FieldExpr, SER_FIELD_EXPR);
3160 : :
3161 : 0 : bool FieldExpr::DoSerialize(SerialInfo* info) const
3162 : : {
3163 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_FIELD_EXPR, UnaryExpr);
3164 : :
3165 [ # # ][ # # ]: 0 : if ( ! (SERIALIZE(field_name) && SERIALIZE(field) ) )
[ # # ]
3166 : 0 : return false;
3167 : :
3168 : 0 : return td->Serialize(info);
3169 : : }
3170 : :
3171 : 0 : bool FieldExpr::DoUnserialize(UnserialInfo* info)
3172 : : {
3173 [ # # ]: 0 : DO_UNSERIALIZE(UnaryExpr);
3174 : :
3175 [ # # ][ # # ]: 0 : if ( ! (UNSERIALIZE_STR(&field_name, 0) && UNSERIALIZE(&field) ) )
[ # # ]
3176 : 0 : return false;
3177 : :
3178 : 0 : td = TypeDecl::Unserialize(info);
3179 : 0 : return td != 0;
3180 : : }
3181 : :
3182 : : HasFieldExpr::HasFieldExpr(Expr* arg_op, const char* arg_field_name,
3183 : 102 : bool arg_is_attr)
3184 : 102 : : UnaryExpr(EXPR_HAS_FIELD, arg_op)
3185 : : {
3186 : 102 : field_name = arg_field_name;
3187 : 102 : is_attr = arg_is_attr;
3188 : 102 : field = 0;
3189 : :
3190 [ + - # # ]: 102 : if ( IsError() )
3191 : 102 : return;
3192 : :
3193 [ + - ][ - + ]: 102 : if ( ! is_attr && ! IsRecord(op->Type()->Tag()) )
[ # # ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
3194 : 0 : ExprError("not a record");
3195 : : else
3196 : : {
3197 : : RecordType* rt = is_attr ?
3198 : : op->Type()->AttributesType() :
3199 [ - + ][ # # ]: 102 : op->Type()->AsRecordType();
3200 : 102 : field = rt->FieldOffset(field_name);
3201 : :
3202 [ - + # # ]: 102 : if ( field < 0 )
3203 : 0 : ExprError("no such field in record");
3204 : :
3205 : 102 : SetType(base_type(TYPE_BOOL));
3206 : : }
3207 : 0 : }
3208 : :
3209 : 0 : HasFieldExpr::~HasFieldExpr()
3210 : : {
3211 : 0 : delete field_name;
3212 [ # # ][ # # ]: 0 : }
[ # # ]
3213 : :
3214 : 39171 : Val* HasFieldExpr::Fold(Val* v) const
3215 : : {
3216 : : RecordVal* rec_to_look_at;
3217 : :
3218 [ - + ]: 39171 : if ( is_attr )
3219 : 0 : rec_to_look_at = v->GetAttribs(false);
3220 : : else
3221 : 39171 : rec_to_look_at = v->AsRecordVal();
3222 : :
3223 [ - + ]: 39171 : if ( ! rec_to_look_at )
3224 : 0 : return new Val(0, TYPE_BOOL);
3225 : :
3226 : 39171 : RecordVal* r = rec_to_look_at->Ref()->AsRecordVal();
3227 : 78342 : Val* ret = new Val(r->Lookup(field) != 0, TYPE_BOOL);
3228 : 39171 : Unref(r);
3229 : :
3230 : 39171 : return ret;
3231 : : }
3232 : :
3233 : 0 : void HasFieldExpr::ExprDescribe(ODesc* d) const
3234 : : {
3235 : 0 : op->Describe(d);
3236 : :
3237 [ # # ]: 0 : if ( d->IsReadable() )
3238 : : {
3239 [ # # ]: 0 : if ( is_attr )
3240 : 0 : d->Add("?$$");
3241 : : else
3242 : 0 : d->Add("?$");
3243 : : }
3244 : :
3245 [ # # ]: 0 : if ( IsError() )
3246 : 0 : d->Add("<error>");
3247 [ # # ]: 0 : else if ( d->IsReadable() )
3248 : 0 : d->Add(field_name);
3249 : : else
3250 : 0 : d->Add(field);
3251 : 0 : }
3252 : :
3253 : 3 : IMPLEMENT_SERIAL(HasFieldExpr, SER_HAS_FIELD_EXPR);
3254 : :
3255 : 0 : bool HasFieldExpr::DoSerialize(SerialInfo* info) const
3256 : : {
3257 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_HAS_FIELD_EXPR, UnaryExpr);
3258 [ # # ][ # # ]: 0 : return SERIALIZE(is_attr) && SERIALIZE(field_name) && SERIALIZE(field);
[ # # ]
3259 : : }
3260 : :
3261 : 0 : bool HasFieldExpr::DoUnserialize(UnserialInfo* info)
3262 : : {
3263 [ # # ]: 0 : DO_UNSERIALIZE(UnaryExpr);
3264 [ # # ][ # # ]: 0 : return UNSERIALIZE(&is_attr) && UNSERIALIZE_STR(&field_name, 0) && UNSERIALIZE(&field);
[ # # ]
3265 : : }
3266 : :
3267 : 266 : RecordConstructorExpr::RecordConstructorExpr(ListExpr* constructor_list)
3268 : 266 : : UnaryExpr(EXPR_RECORD_CONSTRUCTOR, constructor_list)
3269 : : {
3270 [ + - # # ]: 266 : if ( IsError() )
3271 : 266 : return;
3272 : :
3273 : : // Spin through the list, which should be comprised of
3274 : : // either record's or record-field-assign, and build up a
3275 : : // record type to associate with this constructor.
3276 : 266 : type_decl_list* record_types = new type_decl_list;
3277 : :
3278 : 266 : const expr_list& exprs = constructor_list->Exprs();
3279 [ + + ][ # # ]: 1218 : loop_over_list(exprs, i)
3280 : : {
3281 : 952 : Expr* e = exprs[i];
3282 : 952 : BroType* t = e->Type();
3283 : :
3284 [ + - # # ]: 952 : if ( e->Tag() == EXPR_FIELD_ASSIGN )
3285 : : {
3286 : 952 : FieldAssignExpr* field = (FieldAssignExpr*) e;
3287 : :
3288 : 952 : BroType* field_type = field->Type()->Ref();
3289 : 952 : char* field_name = copy_string(field->FieldName());
3290 : :
3291 : 952 : record_types->append(new TypeDecl(field_type, field_name));
3292 : 952 : continue;
3293 : : }
3294 : :
3295 [ # # ][ # # ]: 0 : if ( t->Tag() != TYPE_RECORD )
3296 : : {
3297 : 0 : Error("bad type in record constructor", e);
3298 : 0 : SetError();
3299 : 0 : continue;
3300 : : }
3301 : :
3302 : : // It's a record - add in its fields.
3303 : 0 : const RecordType* rt = t->AsRecordType();
3304 : 0 : int n = rt->NumFields();
3305 [ # # ][ # # ]: 0 : for ( int j = 0; j < n; ++j )
3306 : : {
3307 : 0 : const TypeDecl* td = rt->FieldDecl(j);
3308 : 0 : record_types->append(new TypeDecl(td->type->Ref(), td->id));
3309 : : }
3310 : : }
3311 : :
3312 : 266 : SetType(new RecordType(record_types));
3313 : 0 : }
3314 : :
3315 : 43 : Val* RecordConstructorExpr::InitVal(const BroType* t, Val* aggr) const
3316 : : {
3317 [ + - ]: 43 : if ( ! aggr )
3318 : 43 : aggr = new RecordVal(const_cast<RecordType*>(t->AsRecordType()));
3319 : :
3320 [ + - ]: 43 : if ( record_promotion_compatible(t->AsRecordType(), Type()->AsRecordType()) )
3321 : : {
3322 : 43 : RecordVal* ar = aggr->AsRecordVal();
3323 : 43 : RecordType* ar_t = aggr->Type()->AsRecordType();
3324 : :
3325 : 43 : RecordVal* rv = Eval(0)->AsRecordVal();
3326 : 43 : RecordType* rv_t = rv->Type()->AsRecordType();
3327 : :
3328 : : int i;
3329 [ + + ]: 104 : for ( i = 0; i < rv_t->NumFields(); ++i )
3330 : : {
3331 : 61 : int t_i = ar_t->FieldOffset(rv_t->FieldName(i));
3332 : :
3333 [ - + ]: 61 : if ( t_i < 0 )
3334 : : {
3335 : : char buf[512];
3336 : : safe_snprintf(buf, sizeof(buf),
3337 : : "orphan field \"%s\" in initialization",
3338 : 0 : rv_t->FieldName(i));
3339 : 0 : Error(buf);
3340 : 0 : break;
3341 : : }
3342 : :
3343 : : else
3344 : 61 : ar->Assign(t_i, rv->Lookup(i)->Ref());
3345 : : }
3346 : :
3347 [ + + ]: 138 : for ( i = 0; i < ar_t->NumFields(); ++i )
3348 [ + + ][ - + ]: 95 : if ( ! ar->Lookup(i) &&
[ - + ]
3349 : : ! ar_t->FieldDecl(i)->FindAttr(ATTR_OPTIONAL) )
3350 : : {
3351 : : char buf[512];
3352 : : safe_snprintf(buf, sizeof(buf),
3353 : 0 : "non-optional field \"%s\" missing in initialization", ar_t->FieldName(i));
3354 : 0 : Error(buf);
3355 : : }
3356 : :
3357 : 43 : Unref(rv);
3358 : :
3359 : 43 : return ar;
3360 : : }
3361 : :
3362 : : else
3363 : : {
3364 : 0 : Error("bad record initializer");
3365 : 43 : return 0;
3366 : : }
3367 : : }
3368 : :
3369 : 1848 : Val* RecordConstructorExpr::Fold(Val* v) const
3370 : : {
3371 : 1848 : ListVal* lv = v->AsListVal();
3372 : 1848 : RecordType* rt = type->AsRecordType();
3373 : :
3374 [ - + ]: 1848 : if ( lv->Length() != rt->NumFields() )
3375 : 0 : Internal("inconsistency evaluating record constructor");
3376 : :
3377 : 1848 : RecordVal* rv = new RecordVal(rt);
3378 : :
3379 [ + + ]: 6355 : for ( int i = 0; i < lv->Length(); ++i )
3380 : 4507 : rv->Assign(i, lv->Index(i)->Ref());
3381 : :
3382 : 1848 : return rv;
3383 : : }
3384 : :
3385 : 0 : void RecordConstructorExpr::ExprDescribe(ODesc* d) const
3386 : : {
3387 : 0 : d->Add("[");
3388 : 0 : op->Describe(d);
3389 : 0 : d->Add("]");
3390 : 0 : }
3391 : :
3392 : 3 : IMPLEMENT_SERIAL(RecordConstructorExpr, SER_RECORD_CONSTRUCTOR_EXPR);
3393 : :
3394 : 0 : bool RecordConstructorExpr::DoSerialize(SerialInfo* info) const
3395 : : {
3396 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_RECORD_CONSTRUCTOR_EXPR, UnaryExpr);
3397 : 0 : return true;
3398 : : }
3399 : :
3400 : 0 : bool RecordConstructorExpr::DoUnserialize(UnserialInfo* info)
3401 : : {
3402 [ # # ]: 0 : DO_UNSERIALIZE(UnaryExpr);
3403 : 0 : return true;
3404 : : }
3405 : :
3406 : : TableConstructorExpr::TableConstructorExpr(ListExpr* constructor_list,
3407 : 7 : attr_list* arg_attrs)
3408 : 7 : : UnaryExpr(EXPR_TABLE_CONSTRUCTOR, constructor_list)
3409 : : {
3410 [ + - # # ]: 7 : if ( IsError() )
3411 : 7 : return;
3412 : :
3413 [ + - ][ # # ]: 7 : if ( constructor_list->Exprs().length() == 0 )
3414 : 7 : SetType(new TableType(new TypeList(base_type(TYPE_ANY)), 0));
3415 : : else
3416 : : {
3417 : 0 : SetType(init_type(constructor_list));
3418 : :
3419 [ # # # # ]: 0 : if ( ! type )
3420 : 0 : SetError();
3421 : :
3422 [ # # ][ # # ]: 0 : else if ( type->Tag() != TYPE_TABLE ||
[ # # ][ # # ]
[ # # ][ # # ]
3423 : : type->AsTableType()->IsSet() )
3424 : 0 : SetError("values in table(...) constructor do not specify a table");
3425 : : }
3426 : :
3427 [ + + ][ # # ]: 7 : attrs = arg_attrs ? new Attributes(arg_attrs, type) : 0;
3428 : 0 : }
3429 : :
3430 : 300 : Val* TableConstructorExpr::Eval(Frame* f) const
3431 : : {
3432 [ - + ]: 300 : if ( IsError() )
3433 : 0 : return 0;
3434 : :
3435 : 300 : Val* aggr = new TableVal(Type()->AsTableType(), attrs);
3436 : 300 : const expr_list& exprs = op->AsListExpr()->Exprs();
3437 : :
3438 [ - + ]: 300 : loop_over_list(exprs, i)
3439 : 0 : exprs[i]->EvalIntoAggregate(type, aggr, f);
3440 : :
3441 : 300 : return aggr;
3442 : : }
3443 : :
3444 : 0 : Val* TableConstructorExpr::InitVal(const BroType* t, Val* aggr) const
3445 : : {
3446 [ # # ]: 0 : if ( IsError() )
3447 : 0 : return 0;
3448 : :
3449 : 0 : return op->InitVal(t, aggr);
3450 : : }
3451 : :
3452 : 0 : void TableConstructorExpr::ExprDescribe(ODesc* d) const
3453 : : {
3454 : 0 : d->Add("table(");
3455 : 0 : op->Describe(d);
3456 : 0 : d->Add(")");
3457 : 0 : }
3458 : :
3459 : 3 : IMPLEMENT_SERIAL(TableConstructorExpr, SER_TABLE_CONSTRUCTOR_EXPR);
3460 : :
3461 : 0 : bool TableConstructorExpr::DoSerialize(SerialInfo* info) const
3462 : : {
3463 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_TABLE_CONSTRUCTOR_EXPR, UnaryExpr);
3464 [ # # ][ # # ]: 0 : SERIALIZE_OPTIONAL(attrs);
[ # # ][ # # ]
[ # # ][ # # ]
3465 : 0 : return true;
3466 : : }
3467 : :
3468 : 0 : bool TableConstructorExpr::DoUnserialize(UnserialInfo* info)
3469 : : {
3470 [ # # ]: 0 : DO_UNSERIALIZE(UnaryExpr);
3471 [ # # ][ # # ]: 0 : UNSERIALIZE_OPTIONAL(attrs, Attributes::Unserialize(info));
[ # # ]
3472 : 0 : return true;
3473 : : }
3474 : :
3475 : : SetConstructorExpr::SetConstructorExpr(ListExpr* constructor_list,
3476 : 40 : attr_list* arg_attrs)
3477 : 40 : : UnaryExpr(EXPR_SET_CONSTRUCTOR, constructor_list)
3478 : : {
3479 [ + - # # ]: 40 : if ( IsError() )
3480 : 40 : return;
3481 : :
3482 [ + + ][ # # ]: 40 : if ( constructor_list->Exprs().length() == 0 )
3483 : 36 : SetType(new ::SetType(new TypeList(base_type(TYPE_ANY)), 0));
3484 : : else
3485 : 4 : SetType(init_type(constructor_list));
3486 : :
3487 [ - + ][ # # ]: 40 : if ( ! type )
3488 : 0 : SetError();
3489 : :
3490 [ + - ][ - + ]: 40 : else if ( type->Tag() != TYPE_TABLE || ! type->AsTableType()->IsSet() )
[ - + ][ # # ]
[ # # ][ # # ]
3491 : 0 : SetError("values in set(...) constructor do not specify a set");
3492 : :
3493 [ + + ][ # # ]: 40 : attrs = arg_attrs ? new Attributes(arg_attrs, type) : 0;
3494 : 0 : }
3495 : :
3496 : 1050 : Val* SetConstructorExpr::Eval(Frame* f) const
3497 : : {
3498 [ - + ]: 1050 : if ( IsError() )
3499 : 0 : return 0;
3500 : :
3501 : 1050 : TableVal* aggr = new TableVal(type->AsTableType(), 0);
3502 : 1050 : const expr_list& exprs = op->AsListExpr()->Exprs();
3503 : :
3504 [ - + ]: 1050 : loop_over_list(exprs, i)
3505 : : {
3506 : 0 : Val* element = exprs[i]->Eval(f);
3507 : 0 : aggr->Assign(element, 0);
3508 : : }
3509 : :
3510 : 1050 : aggr->AsTableVal()->SetAttrs(attrs);
3511 : :
3512 : 1050 : return aggr;
3513 : : }
3514 : :
3515 : 2 : Val* SetConstructorExpr::InitVal(const BroType* t, Val* aggr) const
3516 : : {
3517 [ - + ]: 2 : if ( IsError() )
3518 : 0 : return 0;
3519 : :
3520 : 2 : return op->InitVal(t, aggr);
3521 : : }
3522 : :
3523 : 0 : void SetConstructorExpr::ExprDescribe(ODesc* d) const
3524 : : {
3525 : 0 : d->Add("set(");
3526 : 0 : op->Describe(d);
3527 : 0 : d->Add(")");
3528 : 0 : }
3529 : :
3530 : 3 : IMPLEMENT_SERIAL(SetConstructorExpr, SER_SET_CONSTRUCTOR_EXPR);
3531 : :
3532 : 0 : bool SetConstructorExpr::DoSerialize(SerialInfo* info) const
3533 : : {
3534 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_SET_CONSTRUCTOR_EXPR, UnaryExpr);
3535 [ # # ][ # # ]: 0 : SERIALIZE_OPTIONAL(attrs);
[ # # ][ # # ]
[ # # ][ # # ]
3536 : 0 : return true;
3537 : : }
3538 : :
3539 : 0 : bool SetConstructorExpr::DoUnserialize(UnserialInfo* info)
3540 : : {
3541 [ # # ]: 0 : DO_UNSERIALIZE(UnaryExpr);
3542 [ # # ][ # # ]: 0 : UNSERIALIZE_OPTIONAL(attrs, Attributes::Unserialize(info));
[ # # ]
3543 : 0 : return true;
3544 : : }
3545 : :
3546 : 6 : VectorConstructorExpr::VectorConstructorExpr(ListExpr* constructor_list)
3547 : 6 : : UnaryExpr(EXPR_VECTOR_CONSTRUCTOR, constructor_list)
3548 : : {
3549 [ + - # # ]: 6 : if ( IsError() )
3550 : 6 : return;
3551 : :
3552 : 6 : BroType* t = merge_type_list(constructor_list);
3553 [ + - # # ]: 6 : if ( t )
3554 : : {
3555 : 6 : SetType(new VectorType(t->Ref()));
3556 : :
3557 [ - + # # ]: 6 : if ( ! check_and_promote_exprs_to_type(constructor_list, t) )
3558 : 0 : ExprError("inconsistent types in vector constructor");
3559 : :
3560 : 6 : Unref(t);
3561 : : }
3562 : : else
3563 : 6 : SetError();
3564 : 0 : }
3565 : :
3566 : 1821 : Val* VectorConstructorExpr::Eval(Frame* f) const
3567 : : {
3568 [ - + ]: 1821 : if ( IsError() )
3569 : 0 : return 0;
3570 : :
3571 : 1821 : VectorVal* vec = new VectorVal(Type()->AsVectorType());
3572 : 1821 : const expr_list& exprs = op->AsListExpr()->Exprs();
3573 : :
3574 [ + + ]: 24327 : loop_over_list(exprs, i)
3575 : : {
3576 : 22506 : Expr* e = exprs[i];
3577 : 22506 : Val* v = e->Eval(f);
3578 [ - + ]: 22506 : if ( ! vec->Assign(i + VECTOR_MIN, v, e) )
3579 : : {
3580 : 0 : Error(fmt("type mismatch at index %d", i + VECTOR_MIN), e);
3581 : 0 : return 0;
3582 : : }
3583 : : }
3584 : :
3585 : 1821 : return vec;
3586 : : }
3587 : :
3588 : 0 : Val* VectorConstructorExpr::InitVal(const BroType* t, Val* aggr) const
3589 : : {
3590 [ # # ]: 0 : if ( IsError() )
3591 : 0 : return 0;
3592 : :
3593 : 0 : VectorVal* vec = aggr->AsVectorVal();
3594 : 0 : const BroType* vt = vec->Type()->AsVectorType()->YieldType();
3595 : 0 : const expr_list& exprs = op->AsListExpr()->Exprs();
3596 : :
3597 [ # # ]: 0 : loop_over_list(exprs, i)
3598 : : {
3599 : 0 : Expr* e = exprs[i];
3600 : 0 : Val* v = check_and_promote(e->Eval(0), vt, 1);
3601 : :
3602 [ # # # # ]: 0 : if ( ! v || ! vec->Assign(i + VECTOR_MIN, v, e) )
[ # # ]
3603 : : {
3604 : 0 : Error(fmt("initialization type mismatch at index %d", i + VECTOR_MIN), e);
3605 : 0 : return 0;
3606 : : }
3607 : : }
3608 : :
3609 : 0 : return vec;
3610 : : }
3611 : :
3612 : 0 : void VectorConstructorExpr::ExprDescribe(ODesc* d) const
3613 : : {
3614 : 0 : d->Add("vector(");
3615 : 0 : op->Describe(d);
3616 : 0 : d->Add(")");
3617 : 0 : }
3618 : :
3619 : 3 : IMPLEMENT_SERIAL(VectorConstructorExpr, SER_VECTOR_CONSTRUCTOR_EXPR);
3620 : :
3621 : 0 : bool VectorConstructorExpr::DoSerialize(SerialInfo* info) const
3622 : : {
3623 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_VECTOR_CONSTRUCTOR_EXPR, UnaryExpr);
3624 : 0 : return true;
3625 : : }
3626 : :
3627 : 0 : bool VectorConstructorExpr::DoUnserialize(UnserialInfo* info)
3628 : : {
3629 [ # # ]: 0 : DO_UNSERIALIZE(UnaryExpr);
3630 : 0 : return true;
3631 : : }
3632 : :
3633 : 956 : FieldAssignExpr::FieldAssignExpr(const char* arg_field_name, Expr* value)
3634 : 956 : : UnaryExpr(EXPR_FIELD_ASSIGN, value), field_name(arg_field_name)
3635 : : {
3636 : 956 : op->Ref();
3637 : 956 : SetType(value->Type()->Ref());
3638 : 956 : }
3639 : :
3640 : : void FieldAssignExpr::EvalIntoAggregate(const BroType* t, Val* aggr, Frame* f)
3641 : 0 : const
3642 : : {
3643 [ # # ]: 0 : if ( IsError() )
3644 : 0 : return;
3645 : :
3646 : 0 : RecordVal* rec = aggr->AsRecordVal();
3647 : 0 : const RecordType* rt = t->AsRecordType();
3648 : 0 : Val* v = op->Eval(f);
3649 : :
3650 [ # # ]: 0 : if ( v )
3651 : 0 : rec->Assign(rt->FieldOffset(field_name.c_str()), v);
3652 : : }
3653 : :
3654 : 0 : int FieldAssignExpr::IsRecordElement(TypeDecl* td) const
3655 : : {
3656 [ # # ]: 0 : if ( td )
3657 : : {
3658 : 0 : td->type = op->Type()->Ref();
3659 : 0 : td->id = copy_string(field_name.c_str());
3660 : : }
3661 : :
3662 : 0 : return 1;
3663 : : }
3664 : :
3665 : 0 : void FieldAssignExpr::ExprDescribe(ODesc* d) const
3666 : : {
3667 : 0 : d->Add("$");
3668 : 0 : d->Add(FieldName());
3669 : 0 : d->Add("=");
3670 : 0 : op->Describe(d);
3671 : 0 : }
3672 : :
3673 : 3 : IMPLEMENT_SERIAL(FieldAssignExpr, SER_FIELD_ASSIGN_EXPR);
3674 : :
3675 : 0 : bool FieldAssignExpr::DoSerialize(SerialInfo* info) const
3676 : : {
3677 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_FIELD_ASSIGN_EXPR, UnaryExpr);
3678 : 0 : return true;
3679 : : }
3680 : :
3681 : 0 : bool FieldAssignExpr::DoUnserialize(UnserialInfo* info)
3682 : : {
3683 [ # # ]: 0 : DO_UNSERIALIZE(UnaryExpr);
3684 : 0 : return true;
3685 : : }
3686 : :
3687 : : RecordMatchExpr::RecordMatchExpr(Expr* op1 /* record to match */,
3688 : 2 : Expr* op2 /* cases to match against */)
3689 : 2 : : BinaryExpr(EXPR_MATCH, op1, op2)
3690 : : {
3691 : 2 : BroType* result_type = 0;
3692 : :
3693 : : // Make sure the second argument is of a suitable type.
3694 [ - + # # ]: 2 : if ( ! op2->Type()->IsSet() )
3695 : : {
3696 : 0 : ExprError("matching must be done against a set of match records");
3697 : 0 : return;
3698 : : }
3699 : :
3700 : 2 : type_list* elt_types = op2->Type()->AsSetType()->Indices()->Types();
3701 : :
3702 [ + - - + ]: 2 : if ( ! elt_types->length() ||
[ - + # # ]
[ # # ][ # # ]
3703 : : (*elt_types)[0]->Tag() != TYPE_RECORD )
3704 : : {
3705 : 0 : ExprError("matching must be done against a set of match records");
3706 : 0 : return;
3707 : : }
3708 : :
3709 : 2 : RecordType* case_rec_type = (*elt_types)[0]->AsRecordType();
3710 : :
3711 : : // NOTE: The "result" and "pred" field names are hardcoded here.
3712 : 2 : result_field_index = case_rec_type->FieldOffset("result");
3713 : :
3714 [ - + # # ]: 2 : if ( result_field_index < 0 )
3715 : : {
3716 : 0 : ExprError("match records must have a $result field");
3717 : 0 : return;
3718 : : }
3719 : :
3720 : 2 : result_type = case_rec_type->FieldType("result")->Ref();
3721 : :
3722 : : // Check that pred exists, and that the first argument matches it.
3723 [ + - - + ]: 2 : if ( (pred_field_index = case_rec_type->FieldOffset("pred")) < 0 ||
[ - + # # ]
[ # # ][ # # ]
3724 : : case_rec_type->FieldType("pred")->Tag() != TYPE_FUNC )
3725 : : {
3726 : 0 : ExprError("match records must have a $pred' field of function type");
3727 : 0 : return;
3728 : : }
3729 : :
3730 : 2 : FuncType* pred_type = case_rec_type->FieldType("pred")->AsFuncType();
3731 : 2 : type_list* pred_arg_types = pred_type->ArgTypes()->Types();
3732 [ + - - + ]: 2 : if ( pred_arg_types->length() != 1 ||
[ - + # # ]
[ # # ][ # # ]
3733 : : ! check_and_promote_expr(op1, (*pred_arg_types)[0]) )
3734 : 0 : ExprError("record to match does not have the same type as predicate argument");
3735 : :
3736 : : // NOTE: The "priority" field name is hardcoded here.
3737 [ + - ][ + - ]: 2 : if ( (priority_field_index = case_rec_type->FieldOffset("priority")) >= 0 &&
[ - + ][ # # ]
[ # # ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
3738 : : ! IsArithmetic(case_rec_type->FieldType("priority")->Tag()) )
3739 : 0 : ExprError("$priority field must have a numeric type");
3740 : :
3741 : 2 : SetType(result_type);
3742 : 2 : }
3743 : :
3744 : 0 : void RecordMatchExpr::ExprDescribe(ODesc* d) const
3745 : : {
3746 [ # # ]: 0 : if ( d->IsReadable() )
3747 : : {
3748 : 0 : d->Add("match ");
3749 : 0 : op1->Describe(d);
3750 : 0 : d->Add(" using ");
3751 : 0 : op2->Describe(d);
3752 : : }
3753 : 0 : }
3754 : :
3755 : 1379 : Val* RecordMatchExpr::Fold(Val* v1, Val* v2) const
3756 : : {
3757 : 1379 : TableVal* match_set = v2->AsTableVal();
3758 [ - + ]: 1379 : if ( ! match_set )
3759 : 0 : Internal("non-table in RecordMatchExpr");
3760 : :
3761 : 1379 : Val* return_val = 0;
3762 : 1379 : double highest_priority = -1e100;
3763 : :
3764 : 1379 : ListVal* match_recs = match_set->ConvertToList(TYPE_ANY);
3765 [ - - + ]: 4137 : for ( int i = 0; i < match_recs->Length(); ++i )
[ + + ]
3766 : : {
3767 : 1379 : val_list args(1);
3768 : 1379 : args.append(v1->Ref());
3769 : :
3770 : 1379 : double this_priority = 0;
3771 : :
3772 : : // ### Get rid of the double Index if TYPE_ANY->TYPE_RECORD.
3773 : 1379 : Val* v = match_recs->Index(i)->AsListVal()->Index(0);
3774 : :
3775 : 1379 : const RecordVal* match_rec = v->AsRecordVal();
3776 [ - + ]: 1379 : if ( ! match_rec )
3777 : 0 : Internal("Element of match set is not a record");
3778 : :
3779 [ + - ]: 1379 : if ( priority_field_index >= 0 )
3780 : : {
3781 : : this_priority =
3782 : 1379 : match_rec->Lookup(priority_field_index)->CoerceToDouble();
3783 [ - + ]: 1379 : if ( this_priority <= highest_priority )
3784 : : {
3785 : 0 : Unref(v1);
3786 : 0 : continue;
3787 : : }
3788 : : }
3789 : :
3790 : : Val* pred_val =
3791 : 1379 : match_rec->Lookup(pred_field_index)->AsFunc()->Call(&args);
3792 : 1379 : bool is_zero = pred_val->IsZero();
3793 : 1379 : Unref(pred_val);
3794 : :
3795 [ + - ]: 1379 : if ( ! is_zero )
3796 : : {
3797 : : Val* new_return_val =
3798 : 1379 : match_rec->Lookup(result_field_index);
3799 : :
3800 : 1379 : Unref(return_val);
3801 : 1379 : return_val = new_return_val->Ref();
3802 : :
3803 [ - + ]: 1379 : if ( priority_field_index >= 0 )
3804 : 1379 : highest_priority = this_priority;
3805 : : else
3806 : 1379 : break;
3807 : : }
3808 : : }
3809 : :
3810 : 1379 : Unref(match_recs);
3811 : :
3812 : 1379 : return return_val;
3813 : : }
3814 : :
3815 : 3 : IMPLEMENT_SERIAL(RecordMatchExpr, SER_RECORD_MATCH_EXPR);
3816 : :
3817 : 0 : bool RecordMatchExpr::DoSerialize(SerialInfo* info) const
3818 : : {
3819 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_RECORD_MATCH_EXPR, BinaryExpr);
3820 : : return SERIALIZE(pred_field_index) && SERIALIZE(result_field_index) &&
3821 [ # # ][ # # ]: 0 : SERIALIZE(priority_field_index);
[ # # ]
3822 : : }
3823 : :
3824 : 0 : bool RecordMatchExpr::DoUnserialize(UnserialInfo* info)
3825 : : {
3826 [ # # ]: 0 : DO_UNSERIALIZE(BinaryExpr);
3827 : : return UNSERIALIZE(&pred_field_index) && UNSERIALIZE(&result_field_index) &&
3828 [ # # ][ # # ]: 0 : UNSERIALIZE(&priority_field_index);
[ # # ]
3829 : : }
3830 : :
3831 : 129 : ArithCoerceExpr::ArithCoerceExpr(Expr* arg_op, TypeTag t)
3832 : 129 : : UnaryExpr(EXPR_ARITH_COERCE, arg_op)
3833 : : {
3834 [ + - # # ]: 129 : if ( IsError() )
3835 : 129 : return;
3836 : :
3837 : 129 : TypeTag bt = op->Type()->Tag();
3838 : 129 : TypeTag vbt = bt;
3839 : :
3840 [ - + # # ]: 129 : if ( IsVector(bt) )
3841 : : {
3842 : 0 : SetType(new VectorType(base_type(t)));
3843 : 0 : vbt = op->Type()->AsVectorType()->YieldType()->Tag();
3844 : : }
3845 : : else
3846 : 129 : SetType(base_type(t));
3847 : :
3848 [ - + ][ # # ]: 129 : if ( (bt == TYPE_ENUM) != (t == TYPE_ENUM) )
3849 : 0 : ExprError("can't convert to/from enumerated type");
3850 : :
3851 [ + + ][ + - ]: 129 : else if ( ! IsArithmetic(t) && ! IsBool(t) &&
[ + - ][ + + ]
[ + - ][ + + ]
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
3852 : : t != TYPE_TIME && t != TYPE_INTERVAL )
3853 : 0 : ExprError("bad coercion");
3854 : :
3855 [ + - ][ + + ]: 129 : else if ( ! IsArithmetic(bt) && ! IsBool(bt) &&
[ + - ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
3856 : : ! IsArithmetic(vbt) && ! IsBool(vbt) )
3857 : 129 : ExprError("bad coercion value");
3858 : 0 : }
3859 : :
3860 : 0 : Expr* ArithCoerceExpr::DoSimplify()
3861 : : {
3862 [ # # ]: 0 : if ( is_vector(op) )
3863 : 0 : return this;
3864 : :
3865 : 0 : InternalTypeTag my_int = type->InternalType();
3866 : 0 : InternalTypeTag op_int = op->Type()->InternalType();
3867 : :
3868 [ # # ]: 0 : if ( my_int == TYPE_INTERNAL_UNSIGNED )
3869 : 0 : my_int = TYPE_INTERNAL_INT;
3870 [ # # ]: 0 : if ( op_int == TYPE_INTERNAL_UNSIGNED )
3871 : 0 : op_int = TYPE_INTERNAL_INT;
3872 : :
3873 [ # # ]: 0 : if ( my_int == op_int )
3874 : 0 : return op->Ref();
3875 : :
3876 [ # # ]: 0 : if ( op->IsConst() )
3877 : : {
3878 [ # # ]: 0 : if ( my_int == TYPE_INTERNAL_INT )
3879 : : {
3880 [ # # ]: 0 : if ( op_int != TYPE_INTERNAL_DOUBLE )
3881 : 0 : Internal("bad coercion in CoerceExpr::DoSimplify");
3882 : 0 : double d = op->ExprVal()->InternalDouble();
3883 : 0 : bro_int_t i = bro_int_t(d);
3884 : :
3885 [ # # # # ]: 0 : if ( i < 0 &&
[ # # ]
3886 : : type->InternalType() == TYPE_INTERNAL_UNSIGNED )
3887 : 0 : Warn("coercion produces negative count value");
3888 : :
3889 [ # # ]: 0 : if ( d != double(i) )
3890 : 0 : Warn("coercion loses precision");
3891 : :
3892 : 0 : return new ConstExpr(new Val(i, type->Tag()));
3893 : : }
3894 : :
3895 [ # # ]: 0 : if ( my_int == TYPE_INTERNAL_DOUBLE )
3896 : : {
3897 [ # # ]: 0 : if ( op_int == TYPE_INTERNAL_INT )
3898 : : {
3899 : 0 : bro_int_t i = op->ExprVal()->InternalInt();
3900 : 0 : double d = double(i);
3901 : :
3902 [ # # ]: 0 : if ( i != bro_int_t(d) )
3903 : 0 : Warn("coercion loses precision");
3904 : :
3905 : 0 : return new ConstExpr(new Val(d, type->Tag()));
3906 : : }
3907 : :
3908 [ # # ]: 0 : if ( op_int == TYPE_INTERNAL_UNSIGNED )
3909 : : {
3910 : 0 : bro_uint_t u = op->ExprVal()->InternalUnsigned();
3911 : 0 : double d = double(u);
3912 : :
3913 [ # # ]: 0 : if ( u != (bro_uint_t) (d) )
3914 : 0 : Warn("coercion loses precision");
3915 : :
3916 : 0 : return new ConstExpr(new Val(d, type->Tag()));
3917 : : }
3918 : :
3919 : : }
3920 : :
3921 : 0 : Internal("bad coercion in CoerceExpr::DoSimplify");
3922 : : }
3923 : :
3924 : 0 : return this;
3925 : : }
3926 : :
3927 : 217 : Val* ArithCoerceExpr::FoldSingleVal(Val* v, InternalTypeTag t) const
3928 : : {
3929 [ + + - - ]: 217 : switch ( t ) {
3930 : : case TYPE_INTERNAL_DOUBLE:
3931 : 2 : return new Val(v->CoerceToDouble(), TYPE_DOUBLE);
3932 : :
3933 : : case TYPE_INTERNAL_INT:
3934 : 215 : return new Val(v->CoerceToInt(), TYPE_INT);
3935 : :
3936 : : case TYPE_INTERNAL_UNSIGNED:
3937 : 0 : return new Val(v->CoerceToUnsigned(), TYPE_COUNT);
3938 : :
3939 : : default:
3940 : 0 : Internal("bad type in CoerceExpr::Fold");
3941 : 217 : return 0;
3942 : : }
3943 : : }
3944 : :
3945 : 217 : Val* ArithCoerceExpr::Fold(Val* v) const
3946 : : {
3947 : 217 : InternalTypeTag t = type->InternalType();
3948 : :
3949 [ + - ]: 217 : if ( ! is_vector(v) )
3950 : : {
3951 : : // Our result type might be vector, in which case this
3952 : : // invocation is being done per-element rather than on
3953 : : // the whole vector. Correct the type tag if necessary.
3954 [ - + ]: 217 : if ( type->Tag() == TYPE_VECTOR )
3955 : 0 : t = Type()->AsVectorType()->YieldType()->InternalType();
3956 : 217 : return FoldSingleVal(v, t);
3957 : : }
3958 : :
3959 : 0 : t = Type()->AsVectorType()->YieldType()->InternalType();
3960 : :
3961 : 0 : VectorVal* vv = v->AsVectorVal();
3962 : 0 : VectorVal* result = new VectorVal(Type()->AsVectorType());
3963 [ # # ]: 0 : for ( unsigned int i = VECTOR_MIN; i < vv->Size() + VECTOR_MIN; ++i )
3964 : : {
3965 : 0 : Val* elt = vv->Lookup(i);
3966 [ # # ]: 0 : if ( elt )
3967 : 0 : result->Assign(i, FoldSingleVal(elt, t), this);
3968 : : else
3969 : 0 : result->Assign(i, 0, this);
3970 : : }
3971 : :
3972 : 217 : return result;
3973 : : }
3974 : :
3975 : 3 : IMPLEMENT_SERIAL(ArithCoerceExpr, SER_ARITH_COERCE_EXPR);
3976 : :
3977 : 0 : bool ArithCoerceExpr::DoSerialize(SerialInfo* info) const
3978 : : {
3979 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_ARITH_COERCE_EXPR, UnaryExpr);
3980 : 0 : return true;
3981 : : }
3982 : :
3983 : 0 : bool ArithCoerceExpr::DoUnserialize(UnserialInfo* info)
3984 : : {
3985 [ # # ]: 0 : DO_UNSERIALIZE(UnaryExpr);
3986 : 0 : return true;
3987 : : }
3988 : :
3989 : :
3990 : 191 : RecordCoerceExpr::RecordCoerceExpr(Expr* op, RecordType* r)
3991 : 191 : : UnaryExpr(EXPR_RECORD_COERCE, op)
3992 : : {
3993 : 191 : map_size = 0;
3994 : 191 : map = 0;
3995 : :
3996 [ + - # # ]: 191 : if ( IsError() )
3997 : 191 : return;
3998 : :
3999 : 191 : SetType(r->Ref());
4000 : :
4001 [ - + # # ]: 191 : if ( Type()->Tag() != TYPE_RECORD )
4002 : 0 : ExprError("coercion to non-record");
4003 : :
4004 [ - + ][ # # ]: 191 : else if ( op->Type()->Tag() != TYPE_RECORD )
4005 : 0 : ExprError("coercion of non-record to record");
4006 : :
4007 : : else
4008 : : {
4009 : 191 : RecordType* t_r = type->AsRecordType();
4010 : 191 : RecordType* sub_r = op->Type()->AsRecordType();
4011 : :
4012 : 191 : map_size = t_r->NumFields();
4013 : 191 : map = new int[map_size];
4014 : :
4015 : : int i;
4016 [ + + ][ # # ]: 3999 : for ( i = 0; i < map_size; ++i )
4017 : 3808 : map[i] = -1; // -1 = field is not mapped
4018 : :
4019 [ + + ][ # # ]: 985 : for ( i = 0; i < sub_r->NumFields(); ++i )
4020 : : {
4021 : 794 : int t_i = t_r->FieldOffset(sub_r->FieldName(i));
4022 [ - + # # ]: 794 : if ( t_i < 0 )
4023 : : {
4024 : : // Same as in RecordConstructorExpr::InitVal.
4025 : : char buf[512];
4026 : : safe_snprintf(buf, sizeof(buf),
4027 : : "orphan record field \"%s\"",
4028 : 0 : sub_r->FieldName(i));
4029 : 0 : Error(buf);
4030 : 0 : continue;
4031 : : }
4032 : :
4033 : 794 : BroType* sub_t_i = sub_r->FieldType(i);
4034 : 794 : BroType* sup_t_i = t_r->FieldType(t_i);
4035 : :
4036 [ - + # # ]: 794 : if ( ! same_type(sup_t_i, sub_t_i) )
4037 : : {
4038 : : char buf[512];
4039 : : safe_snprintf(buf, sizeof(buf),
4040 : 0 : "type clash for field \"%s\"", sub_r->FieldName(i));
4041 : 0 : Error(buf, sub_t_i);
4042 : 0 : SetError();
4043 : 0 : break;
4044 : : }
4045 : :
4046 : 794 : map[t_i] = i;
4047 : : }
4048 : :
4049 [ + + ][ # # ]: 3999 : for ( i = 0; i < map_size; ++i )
4050 [ + + ][ - + ]: 3808 : if ( map[i] == -1 &&
[ - + ][ # # ]
[ # # ][ # # ]
4051 : : ! t_r->FieldDecl(i)->FindAttr(ATTR_OPTIONAL) )
4052 : : {
4053 : : char buf[512];
4054 : : safe_snprintf(buf, sizeof(buf),
4055 : 0 : "non-optional field \"%s\" missing", t_r->FieldName(i));
4056 : 0 : Error(buf);
4057 : 0 : SetError();
4058 : 0 : break;
4059 : : }
4060 : : }
4061 : 0 : }
4062 : :
4063 : 0 : RecordCoerceExpr::~RecordCoerceExpr()
4064 : : {
4065 [ # # ][ # # ]: 0 : delete [] map;
[ # # ]
4066 [ # # ][ # # ]: 0 : }
[ # # ]
4067 : :
4068 : 1379 : Val* RecordCoerceExpr::Fold(Val* v) const
4069 : : {
4070 : 1379 : RecordVal* val = new RecordVal(Type()->Ref()->AsRecordType());
4071 : 1379 : RecordVal* rv = v->AsRecordVal();
4072 : :
4073 [ + + ]: 30338 : for ( int i = 0; i < map_size; ++i )
4074 : : {
4075 [ + + ]: 28959 : if ( map[i] >= 0 )
4076 : 3168 : val->Assign(i, rv->Lookup(map[i])->Ref());
4077 : : else
4078 : 25791 : val->Assign(i, 0);
4079 : : }
4080 : :
4081 : 1379 : return val;
4082 : : }
4083 : :
4084 : 3 : IMPLEMENT_SERIAL(RecordCoerceExpr, SER_RECORD_COERCE_EXPR);
4085 : :
4086 : 0 : bool RecordCoerceExpr::DoSerialize(SerialInfo* info) const
4087 : : {
4088 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_RECORD_COERCE_EXPR, UnaryExpr);
4089 : :
4090 [ # # ]: 0 : if ( ! SERIALIZE(map_size) )
4091 : 0 : return false;
4092 : :
4093 [ # # ]: 0 : for ( int i = 0; i < map_size; ++i )
4094 [ # # ]: 0 : if ( ! SERIALIZE(map[i]) )
4095 : 0 : return false;
4096 : :
4097 : 0 : return true;
4098 : : }
4099 : :
4100 : 0 : bool RecordCoerceExpr::DoUnserialize(UnserialInfo* info)
4101 : : {
4102 [ # # ]: 0 : DO_UNSERIALIZE(UnaryExpr);
4103 : :
4104 [ # # ]: 0 : if ( ! UNSERIALIZE(&map_size) )
4105 : 0 : return false;
4106 : :
4107 : 0 : map = new int[map_size];
4108 : :
4109 [ # # ]: 0 : for ( int i = 0; i < map_size; ++i )
4110 [ # # ]: 0 : if ( ! UNSERIALIZE(&map[i]) )
4111 : 0 : return false;
4112 : :
4113 : 0 : return true;
4114 : : }
4115 : :
4116 : :
4117 : 43 : TableCoerceExpr::TableCoerceExpr(Expr* op, TableType* r)
4118 : 43 : : UnaryExpr(EXPR_TABLE_COERCE, op)
4119 : : {
4120 [ + - # # ]: 43 : if ( IsError() )
4121 : 43 : return;
4122 : :
4123 : 43 : SetType(r->Ref());
4124 : :
4125 [ - + # # ]: 43 : if ( Type()->Tag() != TYPE_TABLE )
4126 : 0 : ExprError("coercion to non-table");
4127 : :
4128 [ - + ][ # # ]: 43 : else if ( op->Type()->Tag() != TYPE_TABLE )
4129 : 43 : ExprError("coercion of non-table/set to table/set");
4130 : 0 : }
4131 : :
4132 : :
4133 : 0 : TableCoerceExpr::~TableCoerceExpr()
4134 : : {
4135 [ # # ][ # # ]: 0 : }
[ # # ]
4136 : :
4137 : 1350 : Val* TableCoerceExpr::Fold(Val* v) const
4138 : : {
4139 : 1350 : TableVal* tv = v->AsTableVal();
4140 : :
4141 [ - + ]: 1350 : if ( tv->Size() > 0 )
4142 : 0 : Internal("coercion of non-empty table/set");
4143 : :
4144 : 1350 : return new TableVal(Type()->Ref()->AsTableType(), tv->Attrs());
4145 : : }
4146 : :
4147 : 3 : IMPLEMENT_SERIAL(TableCoerceExpr, SER_TABLE_COERCE_EXPR);
4148 : :
4149 : 0 : bool TableCoerceExpr::DoSerialize(SerialInfo* info) const
4150 : : {
4151 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_TABLE_COERCE_EXPR, UnaryExpr);
4152 : 0 : return true;
4153 : : }
4154 : :
4155 : 0 : bool TableCoerceExpr::DoUnserialize(UnserialInfo* info)
4156 : : {
4157 [ # # ]: 0 : DO_UNSERIALIZE(UnaryExpr);
4158 : 0 : return true;
4159 : : }
4160 : :
4161 : 0 : FlattenExpr::FlattenExpr(Expr* arg_op)
4162 : 0 : : UnaryExpr(EXPR_FLATTEN, arg_op)
4163 : : {
4164 [ # # # # ]: 0 : if ( IsError() )
4165 : 0 : return;
4166 : :
4167 : 0 : BroType* t = op->Type();
4168 [ # # # # ]: 0 : if ( t->Tag() != TYPE_RECORD )
4169 : 0 : Internal("bad type in FlattenExpr::FlattenExpr");
4170 : :
4171 : 0 : RecordType* rt = t->AsRecordType();
4172 : 0 : num_fields = rt->NumFields();
4173 : :
4174 : 0 : TypeList* tl = new TypeList();
4175 [ # # ][ # # ]: 0 : for ( int i = 0; i < num_fields; ++i )
4176 : 0 : tl->Append(rt->FieldType(i)->Ref());
4177 : :
4178 : 0 : Unref(rt);
4179 : 0 : SetType(tl);
4180 : 0 : }
4181 : :
4182 : 0 : Val* FlattenExpr::Fold(Val* v) const
4183 : : {
4184 : 0 : RecordVal* rv = v->AsRecordVal();
4185 : 0 : ListVal* l = new ListVal(TYPE_ANY);
4186 : :
4187 [ # # ]: 0 : for ( int i = 0; i < num_fields; ++i )
4188 : : {
4189 : 0 : Val* fv = rv->Lookup(i);
4190 : :
4191 [ # # ]: 0 : if ( fv )
4192 : : {
4193 : 0 : l->Append(fv->Ref());
4194 : 0 : continue;
4195 : : }
4196 : :
4197 : 0 : const RecordType* rv_t = rv->Type()->AsRecordType();
4198 : 0 : const Attr* fa = rv_t->FieldDecl(i)->FindAttr(ATTR_DEFAULT);
4199 [ # # ]: 0 : if ( fa )
4200 : 0 : l->Append(fa->AttrExpr()->Eval(0));
4201 : :
4202 : : else
4203 : 0 : Internal("missing field value");
4204 : : }
4205 : :
4206 : 0 : return l;
4207 : : }
4208 : :
4209 : 3 : IMPLEMENT_SERIAL(FlattenExpr, SER_FLATTEN_EXPR);
4210 : :
4211 : 0 : bool FlattenExpr::DoSerialize(SerialInfo* info) const
4212 : : {
4213 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_FLATTEN_EXPR, UnaryExpr);
4214 : 0 : return SERIALIZE(num_fields);
4215 : : }
4216 : :
4217 : 0 : bool FlattenExpr::DoUnserialize(UnserialInfo* info)
4218 : : {
4219 [ # # ]: 0 : DO_UNSERIALIZE(UnaryExpr);
4220 : 0 : return UNSERIALIZE(&num_fields);
4221 : : }
4222 : :
4223 : : ScheduleTimer::ScheduleTimer(EventHandlerPtr arg_event, val_list* arg_args,
4224 : 1705 : double t, TimerMgr* arg_tmgr)
4225 : 1705 : : Timer(t, TIMER_SCHEDULE)
4226 : : {
4227 : 1705 : event = arg_event;
4228 : 1705 : args = arg_args;
4229 : 1705 : tmgr = arg_tmgr;
4230 : 1705 : }
4231 : :
4232 : 1705 : ScheduleTimer::~ScheduleTimer()
4233 : : {
4234 [ + - ][ # # ]: 1705 : }
[ # # ]
4235 : :
4236 : 1705 : void ScheduleTimer::Dispatch(double /* t */, int /* is_expire */)
4237 : : {
4238 : 1705 : mgr.QueueEvent(event, args, SOURCE_LOCAL, 0, tmgr);
4239 : 1705 : }
4240 : :
4241 : 47 : ScheduleExpr::ScheduleExpr(Expr* arg_when, EventExpr* arg_event)
4242 : 47 : : Expr(EXPR_SCHEDULE)
4243 : : {
4244 : 47 : when = arg_when;
4245 : 47 : event = arg_event;
4246 : :
4247 [ + - + - ]: 47 : if ( IsError() || when->IsError() || event->IsError() )
[ - + ]
[ + - # # ]
[ # # ][ # # ]
[ # # ]
4248 : 47 : return;
4249 : :
4250 : 47 : TypeTag bt = when->Type()->Tag();
4251 [ + - - + # : 47 : if ( bt != TYPE_TIME && bt != TYPE_INTERVAL )
# ][ # # ]
4252 : 0 : ExprError("schedule expression requires a time or time interval");
4253 : : else
4254 : 47 : SetType(base_type(TYPE_TIMER));
4255 : 0 : }
4256 : :
4257 : 0 : ScheduleExpr::~ScheduleExpr()
4258 : : {
4259 : 0 : Unref(when);
4260 : 0 : Unref(event);
4261 [ # # ][ # # ]: 0 : }
[ # # ]
4262 : :
4263 : 47 : int ScheduleExpr::IsPure() const
4264 : : {
4265 : 47 : return 0;
4266 : : }
4267 : :
4268 : 0 : Expr* ScheduleExpr::Simplify(SimplifyType simp_type)
4269 : : {
4270 : 0 : when = when->Simplify(simp_type);
4271 : 0 : Expr* generic_event = event->Simplify(simp_type);
4272 : :
4273 [ # # ]: 0 : if ( ! generic_event )
4274 : 0 : return 0;
4275 : :
4276 [ # # ]: 0 : if ( generic_event->Tag() != EXPR_CALL )
4277 : 0 : Internal("bad event type in ScheduleExpr::Simplify");
4278 : :
4279 : 0 : event = (EventExpr*) generic_event;
4280 : :
4281 : 0 : return this;
4282 : : }
4283 : :
4284 : 1710 : Val* ScheduleExpr::Eval(Frame* f) const
4285 : : {
4286 [ + + ]: 1710 : if ( terminating )
4287 : 5 : return 0;
4288 : :
4289 : 1705 : Val* when_val = when->Eval(f);
4290 [ - + ]: 1705 : if ( ! when_val )
4291 : 0 : return 0;
4292 : :
4293 : 1705 : double dt = when_val->InternalDouble();
4294 [ + - ]: 1705 : if ( when->Type()->Tag() == TYPE_INTERVAL )
4295 : 1705 : dt += network_time;
4296 : :
4297 : 1705 : val_list* args = eval_list(f, event->Args());
4298 : :
4299 [ + - ]: 1705 : if ( args )
4300 : : {
4301 : 1705 : TimerMgr* tmgr = mgr.CurrentTimerMgr();
4302 : 1705 : tmgr->Add(new ScheduleTimer(event->Handler(), args, dt, tmgr));
4303 : : }
4304 : :
4305 : 1705 : Unref(when_val);
4306 : :
4307 : 1710 : return 0;
4308 : : }
4309 : :
4310 : 0 : TraversalCode ScheduleExpr::Traverse(TraversalCallback* cb) const
4311 : : {
4312 : 0 : TraversalCode tc = cb->PreExpr(this);
4313 [ # # ]: 0 : HANDLE_TC_EXPR_PRE(tc);
4314 : :
4315 : 0 : tc = when->Traverse(cb);
4316 [ # # ]: 0 : HANDLE_TC_EXPR_PRE(tc);
4317 : :
4318 : 0 : tc = event->Traverse(cb);
4319 [ # # ]: 0 : HANDLE_TC_EXPR_PRE(tc);
4320 : :
4321 : 0 : tc = cb->PostExpr(this);
4322 : 0 : HANDLE_TC_EXPR_POST(tc);
4323 : : }
4324 : :
4325 : 0 : void ScheduleExpr::ExprDescribe(ODesc* d) const
4326 : : {
4327 [ # # ]: 0 : if ( d->IsReadable() )
4328 : 0 : d->AddSP("schedule");
4329 : :
4330 : 0 : when->Describe(d);
4331 : 0 : d->SP();
4332 : :
4333 [ # # ]: 0 : if ( d->IsReadable() )
4334 : : {
4335 : 0 : d->Add("{");
4336 : 0 : d->PushIndent();
4337 : 0 : event->Describe(d);
4338 : 0 : d->PopIndent();
4339 : 0 : d->Add("}");
4340 : : }
4341 : : else
4342 : 0 : event->Describe(d);
4343 : 0 : }
4344 : :
4345 : 3 : IMPLEMENT_SERIAL(ScheduleExpr, SER_SCHEDULE_EXPR);
4346 : :
4347 : 0 : bool ScheduleExpr::DoSerialize(SerialInfo* info) const
4348 : : {
4349 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_SCHEDULE_EXPR, Expr);
4350 [ # # ][ # # ]: 0 : return when->Serialize(info) && event->Serialize(info);
4351 : : }
4352 : :
4353 : 0 : bool ScheduleExpr::DoUnserialize(UnserialInfo* info)
4354 : : {
4355 [ # # ]: 0 : DO_UNSERIALIZE(Expr);
4356 : :
4357 : 0 : when = Expr::Unserialize(info);
4358 [ # # ]: 0 : if ( ! when )
4359 : 0 : return false;
4360 : :
4361 : 0 : event = (EventExpr*) Expr::Unserialize(info, EXPR_EVENT);
4362 : 0 : return event != 0;
4363 : : }
4364 : :
4365 : 752 : InExpr::InExpr(Expr* arg_op1, Expr* arg_op2)
4366 : 752 : : BinaryExpr(EXPR_IN, arg_op1, arg_op2)
4367 : : {
4368 [ + - # # ]: 752 : if ( IsError() )
4369 : 752 : return;
4370 : :
4371 [ + + ][ # # ]: 752 : if ( op1->Type()->Tag() == TYPE_PATTERN )
4372 : : {
4373 [ - + ][ # # ]: 99 : if ( op2->Type()->Tag() != TYPE_STRING )
4374 : : {
4375 : 0 : op2->Type()->Error("pattern requires string index", op1);
4376 : 0 : SetError();
4377 : : }
4378 : : else
4379 : 99 : SetType(base_type(TYPE_BOOL));
4380 : : }
4381 : :
4382 [ + + ][ # # ]: 653 : else if ( op1->Type()->Tag() == TYPE_RECORD )
4383 : : {
4384 [ - + ][ # # ]: 103 : if ( op2->Type()->Tag() != TYPE_TABLE )
4385 : : {
4386 : 0 : op2->Type()->Error("table/set required");
4387 : 0 : SetError();
4388 : : }
4389 : :
4390 : : else
4391 : : {
4392 : 103 : const BroType* t1 = op1->Type();
4393 : : const TypeList* it =
4394 : 103 : op2->Type()->AsTableType()->Indices();
4395 : :
4396 [ - + # # ]: 103 : if ( ! same_type(t1, it) )
4397 : : {
4398 : 0 : t1->Error("indexing mismatch", op2->Type());
4399 : 0 : SetError();
4400 : : }
4401 : : else
4402 : 103 : SetType(base_type(TYPE_BOOL));
4403 : : }
4404 : : }
4405 : :
4406 [ + + ][ + + ]: 550 : else if ( op1->Type()->Tag() == TYPE_STRING &&
[ + + ][ # # ]
[ # # ][ # # ]
4407 : : op2->Type()->Tag() == TYPE_STRING )
4408 : 7 : SetType(base_type(TYPE_BOOL));
4409 : :
4410 : : else
4411 : : {
4412 : : // Check for: <addr> in <subnet>
4413 : : // <addr> in set[subnet]
4414 : : // <addr> in table[subnet] of ...
4415 [ + + ][ # # ]: 543 : if ( op1->Type()->Tag() == TYPE_ADDR )
4416 : : {
4417 [ + + ][ # # ]: 160 : if ( op2->Type()->Tag() == TYPE_SUBNET )
4418 : : {
4419 : 8 : SetType(base_type(TYPE_BOOL));
4420 : 8 : return;
4421 : : }
4422 : :
4423 [ + - ][ + + ]: 152 : if ( op2->Type()->Tag() == TYPE_TABLE &&
[ + + ][ # # ]
[ # # ][ # # ]
4424 : : op2->Type()->AsTableType()->IsSubNetIndex() )
4425 : : {
4426 : 21 : SetType(base_type(TYPE_BOOL));
4427 : 21 : return;
4428 : : }
4429 : : }
4430 : :
4431 [ + + ][ # # ]: 514 : if ( op1->Tag() != EXPR_LIST )
4432 : 419 : op1 = new ListExpr(op1);
4433 : :
4434 : 514 : ListExpr* lop1 = op1->AsListExpr();
4435 : :
4436 [ - + # # ]: 514 : if ( ! op2->Type()->MatchesIndex(lop1) )
4437 : 0 : SetError("not an index type");
4438 : : else
4439 : : {
4440 : 514 : op1 = lop1;
4441 : 723 : SetType(base_type(TYPE_BOOL));
4442 : : }
4443 : : }
4444 : 0 : }
4445 : :
4446 : 55621 : Val* InExpr::Fold(Val* v1, Val* v2) const
4447 : : {
4448 [ + + ]: 55621 : if ( v1->Type()->Tag() == TYPE_PATTERN )
4449 : : {
4450 : 2204 : RE_Matcher* re = v1->AsPattern();
4451 : 2204 : const BroString* s = v2->AsString();
4452 : 2204 : return new Val(re->MatchAnywhere(s) != 0, TYPE_BOOL);
4453 : : }
4454 : :
4455 [ + + ]: 53417 : if ( v2->Type()->Tag() == TYPE_STRING )
4456 : : {
4457 : 1994 : const BroString* s1 = v1->AsString();
4458 : 1994 : const BroString* s2 = v2->AsString();
4459 : :
4460 : : // Could do better here - either roll our own, to deal with
4461 : : // NULs, and/or Boyer-Moore if done repeatedly.
4462 : 1994 : return new Val(strstr(s2->CheckString(), s1->CheckString()) != 0, TYPE_BOOL);
4463 : : }
4464 : :
4465 [ + + ][ - + ]: 51423 : if ( v1->Type()->Tag() == TYPE_ADDR &&
[ - + ]
4466 : : v2->Type()->Tag() == TYPE_SUBNET )
4467 : 0 : return new Val(v2->AsSubNetVal()->Contains(v1->AsAddr()), TYPE_BOOL);
4468 : :
4469 : 51423 : TableVal* vt = v2->AsTableVal();
4470 [ + + ]: 51423 : if ( vt->Lookup(v1, false) )
4471 : 17583 : return new Val(1, TYPE_BOOL);
4472 : : else
4473 : 55621 : return new Val(0, TYPE_BOOL);
4474 : : }
4475 : :
4476 : 3 : IMPLEMENT_SERIAL(InExpr, SER_IN_EXPR);
4477 : :
4478 : 0 : bool InExpr::DoSerialize(SerialInfo* info) const
4479 : : {
4480 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_IN_EXPR, BinaryExpr);
4481 : 0 : return true;
4482 : : }
4483 : :
4484 : 0 : bool InExpr::DoUnserialize(UnserialInfo* info)
4485 : : {
4486 [ # # ]: 0 : DO_UNSERIALIZE(BinaryExpr);
4487 : 0 : return true;
4488 : : }
4489 : :
4490 : 3460 : CallExpr::CallExpr(Expr* arg_func, ListExpr* arg_args)
4491 : 3460 : : Expr(EXPR_CALL)
4492 : : {
4493 : 3460 : func = arg_func;
4494 : 3460 : args = arg_args;
4495 : :
4496 [ + - - + ]: 3460 : if ( func->IsError() || args->IsError() )
[ - + # # ]
[ # # ][ # # ]
4497 : : {
4498 : 0 : SetError();
4499 : 0 : return;
4500 : : }
4501 : :
4502 : 3460 : BroType* func_type = func->Type();
4503 [ - + # # ]: 3460 : if ( ! IsFunc(func_type->Tag()) )
4504 : : {
4505 : 0 : func->Error("not a function");
4506 : 0 : SetError();
4507 : 0 : return;
4508 : : }
4509 : :
4510 [ - + ][ # # ]: 3460 : if ( ! func_type->MatchesIndex(args) )
4511 : 0 : SetError("argument type mismatch in function call");
4512 : : else
4513 : : {
4514 : 3460 : BroType* yield = func_type->YieldType();
4515 : :
4516 [ - + # # ]: 3460 : if ( ! yield )
4517 : : {
4518 : 0 : Error("event called in expression");
4519 : 0 : SetError();
4520 : : }
4521 : : else
4522 : 3460 : SetType(yield->Ref());
4523 : :
4524 : : // Check for call to built-ins that can be statically
4525 : : // analyzed.
4526 : : Val* func_val;
4527 [ + + ][ + + ]: 3460 : if ( func->Tag() == EXPR_NAME &&
[ + + ][ + - ]
[ + + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
4528 : : // This is cheating, but without it processing gets
4529 : : // quite confused regarding "value used but not set"
4530 : : // run-time errors when we apply this analysis during
4531 : : // parsing. Really we should instead do it after we've
4532 : : // parsed the entire set of scripts.
4533 : : streq(((NameExpr*) func)->Id()->Name(), "fmt") &&
4534 : : // The following is needed because fmt might not yet
4535 : : // be bound as a name.
4536 : : did_builtin_init &&
4537 : : (func_val = func->Eval(0)) )
4538 : : {
4539 : 892 : ::Func* f = func_val->AsFunc();
4540 [ + - - + ]: 892 : if ( f->GetKind() == Func::BUILTIN_FUNC &&
[ - + # # ]
[ # # ][ # # ]
4541 : : ! check_built_in_call((BuiltinFunc*) f, this) )
4542 : 3460 : SetError();
4543 : : }
4544 : : }
4545 : 3460 : }
4546 : :
4547 : 4 : CallExpr::~CallExpr()
4548 : : {
4549 : 4 : Unref(func);
4550 : 4 : Unref(args);
4551 [ + - ][ # # ]: 4 : }
[ # # ]
4552 : :
4553 : 1030 : int CallExpr::IsPure() const
4554 : : {
4555 [ - + ]: 1030 : if ( IsError() )
4556 : 0 : return 1;
4557 : :
4558 [ + + ]: 1030 : if ( ! func->IsPure() )
4559 : 208 : return 0;
4560 : :
4561 : 822 : Val* func_val = func->Eval(0);
4562 [ - + ]: 822 : if ( ! func_val )
4563 : 0 : return 0;
4564 : :
4565 : 822 : ::Func* f = func_val->AsFunc();
4566 : :
4567 : : // Only recurse for built-in functions, as recursing on script
4568 : : // functions can lead to infinite recursion if the function being
4569 : : // called here happens to be recursive (either directly
4570 : : // or indirectly).
4571 : 822 : int pure = 0;
4572 [ - + ]: 822 : if ( f->GetKind() == Func::BUILTIN_FUNC )
4573 [ # # ][ # # ]: 0 : pure = f->IsPure() && args->IsPure();
4574 : 822 : Unref(func_val);
4575 : :
4576 : 1030 : return pure;
4577 : : }
4578 : :
4579 : 0 : Expr* CallExpr::Simplify(SimplifyType /* simp_type */)
4580 : : {
4581 [ # # ]: 0 : if ( IsError() )
4582 : 0 : return this;
4583 : :
4584 : 0 : func = simplify_expr(func, SIMPLIFY_GENERAL);
4585 : 0 : args = simplify_expr_list(args, SIMPLIFY_GENERAL);
4586 : :
4587 [ # # ]: 0 : if ( IsPure() )
4588 : 0 : return new ConstExpr(Eval(0));
4589 : : else
4590 : 0 : return this;
4591 : : }
4592 : :
4593 : 200604 : Val* CallExpr::Eval(Frame* f) const
4594 : : {
4595 [ - + ]: 200604 : if ( IsError() )
4596 : 0 : return 0;
4597 : :
4598 : : // If we are inside a trigger condition, we may have already been
4599 : : // called, delayed, and then produced a result which is now cached.
4600 : : // Check for that.
4601 [ + + ]: 200604 : if ( f )
4602 : : {
4603 : 200536 : Trigger* trigger = f->GetTrigger();
4604 : :
4605 [ - + ]: 200536 : if ( trigger )
4606 : : {
4607 : 0 : Val* v = trigger->Lookup(this);
4608 [ # # ]: 0 : if ( v )
4609 : : {
4610 : 0 : DBG_LOG(DBG_NOTIFIERS,
4611 : : "%s: provides cached function result",
4612 : : trigger->Name());
4613 : 0 : return v->Ref();
4614 : : }
4615 : : }
4616 : : }
4617 : :
4618 : 200604 : Val* ret = 0;
4619 : 200604 : Val* func_val = func->Eval(f);
4620 : 200604 : val_list* v = eval_list(f, args);
4621 : :
4622 [ + - + - ]: 401208 : if ( func_val && v )
4623 : : {
4624 : 200604 : const ::Func* func = func_val->AsFunc();
4625 : 200604 : calling_expr = this;
4626 : :
4627 [ + + ]: 200604 : if ( f )
4628 : 200536 : f->SetCall(this);
4629 : 200604 : ret = func->Call(v, f);
4630 [ + + ]: 200604 : if ( f )
4631 : 200536 : f->ClearCall();
4632 : : // Don't Unref() the arguments, as Func::Call already did that.
4633 [ + - ]: 200604 : delete v;
4634 : :
4635 : 200604 : calling_expr = 0;
4636 : : }
4637 : : else
4638 : 0 : delete_vals(v);
4639 : :
4640 : 200604 : Unref(func_val);
4641 : :
4642 : 200604 : return ret;
4643 : : }
4644 : :
4645 : 0 : TraversalCode CallExpr::Traverse(TraversalCallback* cb) const
4646 : : {
4647 : 0 : TraversalCode tc = cb->PreExpr(this);
4648 [ # # ]: 0 : HANDLE_TC_EXPR_PRE(tc);
4649 : :
4650 : 0 : tc = func->Traverse(cb);
4651 [ # # ]: 0 : HANDLE_TC_EXPR_PRE(tc);
4652 : :
4653 : 0 : tc = args->Traverse(cb);
4654 [ # # ]: 0 : HANDLE_TC_EXPR_PRE(tc);
4655 : :
4656 : 0 : tc = cb->PostExpr(this);
4657 : 0 : HANDLE_TC_EXPR_POST(tc);
4658 : : }
4659 : :
4660 : 0 : void CallExpr::ExprDescribe(ODesc* d) const
4661 : : {
4662 : 0 : func->Describe(d);
4663 [ # # # # ]: 0 : if ( d->IsReadable() || d->IsPortable() )
[ # # ]
4664 : : {
4665 : 0 : d->Add("(");
4666 : 0 : args->Describe(d);
4667 : 0 : d->Add(")");
4668 : : }
4669 : : else
4670 : 0 : args->Describe(d);
4671 : 0 : }
4672 : :
4673 : 3 : IMPLEMENT_SERIAL(CallExpr, SER_CALL_EXPR);
4674 : :
4675 : 0 : bool CallExpr::DoSerialize(SerialInfo* info) const
4676 : : {
4677 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_CALL_EXPR, Expr);
4678 [ # # ][ # # ]: 0 : return func->Serialize(info) && args->Serialize(info);
4679 : : }
4680 : :
4681 : 0 : bool CallExpr::DoUnserialize(UnserialInfo* info)
4682 : : {
4683 [ # # ]: 0 : DO_UNSERIALIZE(Expr);
4684 : :
4685 : 0 : func = Expr::Unserialize(info);
4686 [ # # ]: 0 : if ( ! func )
4687 : 0 : return false;
4688 : :
4689 : 0 : args = (ListExpr*) Expr::Unserialize(info, EXPR_LIST);
4690 : 0 : return args != 0;
4691 : : }
4692 : :
4693 : 125 : EventExpr::EventExpr(const char* arg_name, ListExpr* arg_args)
4694 : 125 : : Expr(EXPR_EVENT)
4695 : : {
4696 : 125 : name = arg_name;
4697 : 125 : args = arg_args;
4698 : :
4699 : 125 : EventHandler* h = event_registry->Lookup(name.c_str());
4700 [ + + # # ]: 125 : if ( ! h )
4701 : : {
4702 : 32 : h = new EventHandler(name.c_str());
4703 : 32 : event_registry->Register(h);
4704 : : }
4705 : :
4706 : 125 : h->SetUsed();
4707 : :
4708 : 125 : handler = h;
4709 : :
4710 [ - + # # ]: 125 : if ( args->IsError() )
4711 : : {
4712 : 0 : SetError();
4713 : 0 : return;
4714 : : }
4715 : :
4716 : 125 : FuncType* func_type = h->FType();
4717 [ - + # # ]: 125 : if ( ! func_type )
4718 : : {
4719 : 0 : Error("not an event");
4720 : 0 : SetError();
4721 : 0 : return;
4722 : : }
4723 : :
4724 [ - + ][ # # ]: 125 : if ( ! func_type->MatchesIndex(args) )
4725 : 0 : SetError("argument type mismatch in event invocation");
4726 : : else
4727 : : {
4728 [ - + ][ # # ]: 125 : if ( func_type->YieldType() )
4729 : : {
4730 : 0 : Error("function invoked as an event");
4731 : 125 : SetError();
4732 : : }
4733 : : }
4734 : 125 : }
4735 : :
4736 : 0 : EventExpr::~EventExpr()
4737 : : {
4738 : 0 : Unref(args);
4739 [ # # ][ # # ]: 0 : }
[ # # ]
4740 : :
4741 : 0 : Expr* EventExpr::Simplify(SimplifyType /* simp_type */)
4742 : : {
4743 [ # # ]: 0 : if ( ! IsError() )
4744 : 0 : args = simplify_expr_list(args, SIMPLIFY_GENERAL);
4745 : :
4746 : 0 : return this;
4747 : : }
4748 : :
4749 : 0 : Val* EventExpr::Eval(Frame* f) const
4750 : : {
4751 [ # # ]: 0 : if ( IsError() )
4752 : 0 : return 0;
4753 : :
4754 : 0 : val_list* v = eval_list(f, args);
4755 : 0 : mgr.QueueEvent(handler, v);
4756 : :
4757 : 0 : return 0;
4758 : : }
4759 : :
4760 : 0 : TraversalCode EventExpr::Traverse(TraversalCallback* cb) const
4761 : : {
4762 : 0 : TraversalCode tc = cb->PreExpr(this);
4763 [ # # ]: 0 : HANDLE_TC_EXPR_PRE(tc);
4764 : :
4765 : 0 : tc = args->Traverse(cb);
4766 [ # # ]: 0 : HANDLE_TC_EXPR_PRE(tc);
4767 : :
4768 : 0 : tc = cb->PostExpr(this);
4769 : 0 : HANDLE_TC_EXPR_POST(tc);
4770 : : }
4771 : :
4772 : 0 : void EventExpr::ExprDescribe(ODesc* d) const
4773 : : {
4774 : 0 : d->Add(name.c_str());
4775 [ # # # # ]: 0 : if ( d->IsReadable() || d->IsPortable() )
[ # # ]
4776 : : {
4777 : 0 : d->Add("(");
4778 : 0 : args->Describe(d);
4779 : 0 : d->Add(")");
4780 : : }
4781 : : else
4782 : 0 : args->Describe(d);
4783 : 0 : }
4784 : :
4785 : 3 : IMPLEMENT_SERIAL(EventExpr, SER_EVENT_EXPR);
4786 : :
4787 : 0 : bool EventExpr::DoSerialize(SerialInfo* info) const
4788 : : {
4789 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_EVENT_EXPR, Expr);
4790 : :
4791 [ # # ]: 0 : if ( ! handler->Serialize(info) )
4792 : 0 : return false;
4793 : :
4794 [ # # ][ # # ]: 0 : return SERIALIZE(name) && args->Serialize(info);
4795 : : }
4796 : :
4797 : 0 : bool EventExpr::DoUnserialize(UnserialInfo* info)
4798 : : {
4799 [ # # ]: 0 : DO_UNSERIALIZE(Expr);
4800 : :
4801 : 0 : EventHandler* h = EventHandler::Unserialize(info);
4802 [ # # ]: 0 : if ( ! h )
4803 : 0 : return false;
4804 : :
4805 : 0 : handler = h;
4806 : :
4807 [ # # ]: 0 : if ( ! UNSERIALIZE(&name) )
4808 : 0 : return false;
4809 : :
4810 : 0 : args = (ListExpr*) Expr::Unserialize(info, EXPR_LIST);
4811 : 0 : return args;
4812 : : }
4813 : :
4814 : 430 : ListExpr::ListExpr() : Expr(EXPR_LIST)
4815 : : {
4816 : 430 : SetType(new TypeList());
4817 : 430 : }
4818 : :
4819 : 7366 : ListExpr::ListExpr(Expr* e) : Expr(EXPR_LIST)
4820 : : {
4821 : 7366 : SetType(new TypeList());
4822 : 7366 : Append(e);
4823 : 7366 : }
4824 : :
4825 : 4 : ListExpr::~ListExpr()
4826 : : {
4827 [ + + ][ # # ]: 10 : loop_over_list(exprs, i)
[ # # ]
4828 : 6 : Unref(exprs[i]);
4829 [ + - ][ # # ]: 4 : }
[ # # ]
4830 : :
4831 : 15413 : void ListExpr::Append(Expr* e)
4832 : : {
4833 : 15413 : exprs.append(e);
4834 : 15413 : ((TypeList*) type)->Append(e->Type()->Ref());
4835 : 15413 : }
4836 : :
4837 : 0 : int ListExpr::IsPure() const
4838 : : {
4839 [ # # ]: 0 : loop_over_list(exprs, i)
4840 [ # # ]: 0 : if ( ! exprs[i]->IsPure() )
4841 : 0 : return 0;
4842 : :
4843 : 0 : return 1;
4844 : : }
4845 : :
4846 : 0 : int ListExpr::AllConst() const
4847 : : {
4848 [ # # ]: 0 : loop_over_list(exprs, i)
4849 [ # # ]: 0 : if ( ! exprs[i]->IsConst() )
4850 : 0 : return 0;
4851 : :
4852 : 0 : return 1;
4853 : : }
4854 : :
4855 : 0 : Expr* ListExpr::Simplify(SimplifyType /* simp_type */)
4856 : : {
4857 [ # # ]: 0 : loop_over_list(exprs, i)
4858 : 0 : exprs.replace(i, simplify_expr(exprs[i], SIMPLIFY_GENERAL));
4859 : :
4860 : : // Note that we do *not* simplify a list with one element
4861 : : // to just that element. The assumption that simplify_expr(ListExpr*)
4862 : : // returns a ListExpr* is widespread.
4863 : 0 : return this;
4864 : : }
4865 : :
4866 : 130241 : Val* ListExpr::Eval(Frame* f) const
4867 : : {
4868 : 130241 : ListVal* v = new ListVal(TYPE_ANY);
4869 : :
4870 [ + + ]: 268264 : loop_over_list(exprs, i)
4871 : : {
4872 : 138023 : Val* ev = exprs[i]->Eval(f);
4873 [ - + ]: 138023 : if ( ! ev )
4874 : : {
4875 : 0 : RunTime("uninitialized list value");
4876 : 0 : return 0;
4877 : : }
4878 : :
4879 : 138023 : v->Append(ev);
4880 : : }
4881 : :
4882 : 130241 : return v;
4883 : : }
4884 : :
4885 : 7 : BroType* ListExpr::InitType() const
4886 : : {
4887 [ - + ]: 7 : if ( exprs.length() == 0 )
4888 : : {
4889 : 0 : Error("empty list in untyped initialization");
4890 : 0 : return 0;
4891 : : }
4892 : :
4893 [ - + ]: 7 : if ( exprs[0]->IsRecordElement(0) )
4894 : : {
4895 : 0 : type_decl_list* types = new type_decl_list;
4896 [ # # ]: 0 : loop_over_list(exprs, i)
4897 : : {
4898 : 0 : TypeDecl* td = new TypeDecl(0, 0);
4899 [ # # ]: 0 : if ( ! exprs[i]->IsRecordElement(td) )
4900 : : {
4901 : 0 : exprs[i]->Error("record element expected");
4902 [ # # ]: 0 : delete td;
4903 [ # # ]: 0 : delete types;
4904 : 0 : return 0;
4905 : : }
4906 : :
4907 : 0 : types->append(td);
4908 : : }
4909 : :
4910 : 0 : return new RecordType(types);
4911 : : }
4912 : :
4913 : : else
4914 : : {
4915 : 7 : TypeList* tl = new TypeList();
4916 [ + + ]: 21 : loop_over_list(exprs, i)
4917 : : {
4918 : 14 : Expr* e = exprs[i];
4919 : 14 : BroType* ti = e->Type();
4920 : :
4921 : : // Collapse any embedded sets or lists.
4922 [ + + - + ]: 14 : if ( ti->IsSet() || ti->Tag() == TYPE_LIST )
[ + + ]
4923 : : {
4924 : : TypeList* til = ti->IsSet() ?
4925 : : ti->AsSetType()->Indices() :
4926 [ + - ]: 3 : ti->AsTypeList();
4927 : :
4928 [ + - ][ - + ]: 3 : if ( ! til->IsPure() ||
[ - + ]
4929 : : ! til->AllMatch(til->PureType(), 1) )
4930 : 0 : tl->Append(til->Ref());
4931 : : else
4932 : 3 : tl->Append(til->PureType()->Ref());
4933 : : }
4934 : : else
4935 : 11 : tl->Append(ti->Ref());
4936 : : }
4937 : :
4938 : 7 : return tl;
4939 : : }
4940 : : }
4941 : :
4942 : 1732 : Val* ListExpr::InitVal(const BroType* t, Val* aggr) const
4943 : : {
4944 : : // While fairly similar to the EvalIntoAggregate() code,
4945 : : // we keep this separate since it also deals with initialization
4946 : : // idioms such as embedded aggregates and cross-product
4947 : : // expansion.
4948 [ - + ]: 1732 : if ( IsError() )
4949 : 0 : return 0;
4950 : :
4951 : : // Check whether each element of this list itself matches t,
4952 : : // in which case we should expand as a ListVal.
4953 [ + + ][ + + ]: 1732 : if ( ! aggr && type->AsTypeList()->AllMatch(t, 1) )
[ + + ]
4954 : : {
4955 : 1267 : ListVal* v = new ListVal(TYPE_ANY);
4956 : :
4957 [ + + ]: 2809 : loop_over_list(exprs, i)
4958 : : {
4959 : 1542 : Val* vi = exprs[i]->InitVal(t, 0);
4960 [ - + ]: 1542 : if ( ! vi )
4961 : : {
4962 : 0 : Unref(v);
4963 : 0 : return 0;
4964 : : }
4965 : 1542 : v->Append(vi);
4966 : : }
4967 : 1267 : return v;
4968 : : }
4969 : :
4970 [ + + ]: 465 : if ( t->Tag() == TYPE_LIST )
4971 : : {
4972 [ - + ]: 101 : if ( aggr )
4973 : : {
4974 : 0 : Error("bad use of list in initialization", t);
4975 : 0 : return 0;
4976 : : }
4977 : :
4978 : 101 : const type_list* tl = t->AsTypeList()->Types();
4979 [ - + ]: 101 : if ( exprs.length() != tl->length() )
4980 : : {
4981 : 0 : Error("index mismatch", t);
4982 : 0 : return 0;
4983 : : }
4984 : :
4985 : 101 : ListVal* v = new ListVal(TYPE_ANY);
4986 [ + + ]: 303 : loop_over_list(exprs, i)
4987 : : {
4988 : 202 : Val* vi = exprs[i]->InitVal((*tl)[i], 0);
4989 [ - + ]: 202 : if ( ! vi )
4990 : : {
4991 : 0 : Unref(v);
4992 : 0 : return 0;
4993 : : }
4994 : 202 : v->Append(vi);
4995 : : }
4996 : 101 : return v;
4997 : : }
4998 : :
4999 [ + - ][ + + ]: 364 : if ( t->Tag() != TYPE_RECORD && t->Tag() != TYPE_TABLE &&
[ - + ][ - + ]
5000 : : t->Tag() != TYPE_VECTOR )
5001 : : {
5002 [ # # ]: 0 : if ( exprs.length() == 1 )
5003 : : // Allow "global x:int = { 5 }"
5004 : 0 : return exprs[0]->InitVal(t, aggr);
5005 : : else
5006 : : {
5007 : 0 : Error("aggregate initializer for scalar type", t);
5008 : 0 : return 0;
5009 : : }
5010 : : }
5011 : :
5012 [ - + ]: 364 : if ( ! aggr )
5013 : 0 : Internal("missing aggregate in ListExpr::InitVal");
5014 : :
5015 [ + + ]: 364 : if ( t->IsSet() )
5016 : 196 : return AddSetInit(t, aggr);
5017 : :
5018 [ + + ]: 168 : if ( t->Tag() == TYPE_VECTOR )
5019 : : {
5020 : : // v: vector = [10, 20, 30];
5021 : 14 : VectorVal* vec = aggr->AsVectorVal();
5022 : :
5023 [ + + ]: 109 : loop_over_list(exprs, i)
5024 : : {
5025 : 95 : Expr* e = exprs[i];
5026 : 95 : Val* v = e->Eval(0);
5027 [ - + ]: 95 : if ( ! vec->Assign(i + VECTOR_MIN, v, e) )
5028 : : {
5029 : 0 : e->Error(fmt("type mismatch at index %d", i + VECTOR_MIN));
5030 : 0 : return 0;
5031 : : }
5032 : :
5033 : 95 : Unref(v);
5034 : : }
5035 : :
5036 : 14 : return aggr;
5037 : : }
5038 : :
5039 : : // If we got this far, then it's either a table or record
5040 : : // initialization. Both of those involve AssignExpr's, which
5041 : : // know how to add themselves to a table or record. Another
5042 : : // possibility is an expression that evaluates itself to a
5043 : : // table, which we can then add to the aggregate.
5044 [ + + ]: 1383 : loop_over_list(exprs, i)
5045 : : {
5046 : 1229 : Expr* e = exprs[i];
5047 : :
5048 [ + + - + ]: 1229 : if ( e->Tag() == EXPR_ASSIGN || e->Tag() == EXPR_FIELD_ASSIGN )
[ + + ]
5049 : : {
5050 [ - + ]: 1228 : if ( ! e->InitVal(t, aggr) )
5051 : 1228 : return 0;
5052 : : }
5053 : : else
5054 : : {
5055 [ - + ]: 1 : if ( t->Tag() == TYPE_RECORD )
5056 : : {
5057 : 0 : e->Error("bad record initializer", t);
5058 : 0 : return 0;
5059 : : }
5060 : :
5061 : 1 : Val* v = e->Eval(0);
5062 [ - + ]: 1 : if ( ! same_type(v->Type(), t) )
5063 : : {
5064 : 0 : v->Type()->Error("type clash in table initializer", t);
5065 : 0 : return 0;
5066 : : }
5067 : :
5068 [ - + ]: 1 : if ( ! v->AsTableVal()->AddTo(aggr->AsTableVal(), 1) )
5069 : 0 : return 0;
5070 : : }
5071 : : }
5072 : :
5073 : 1732 : return aggr;
5074 : : }
5075 : :
5076 : 196 : Val* ListExpr::AddSetInit(const BroType* t, Val* aggr) const
5077 : : {
5078 [ - + ]: 196 : if ( aggr->Type()->Tag() != TYPE_TABLE )
5079 : 0 : Internal("bad aggregate in ListExpr::InitVal");
5080 : :
5081 : 196 : TableVal* tv = aggr->AsTableVal();
5082 : 196 : const TableType* tt = tv->Type()->AsTableType();
5083 : 196 : const TypeList* it = tt->Indices();
5084 : :
5085 [ + + ]: 1297 : loop_over_list(exprs, i)
5086 : : {
5087 : : Val* element;
5088 : :
5089 [ + + ]: 1101 : if ( exprs[i]->Type()->IsSet() )
5090 : : // A set to flatten.
5091 : 89 : element = exprs[i]->Eval(0);
5092 [ + + ]: 1012 : else if ( exprs[i]->Type()->Tag() == TYPE_LIST )
5093 : 87 : element = exprs[i]->InitVal(it, 0);
5094 : : else
5095 : 925 : element = exprs[i]->InitVal((*it->Types())[0], 0);
5096 : :
5097 [ - + ]: 1101 : if ( ! element )
5098 : 0 : return 0;
5099 : :
5100 [ + + ]: 1101 : if ( element->Type()->IsSet() )
5101 : : {
5102 [ - + ]: 89 : if ( ! same_type(element->Type(), t) )
5103 : : {
5104 : 0 : element->Error("type clash in set initializer", t);
5105 : 0 : return 0;
5106 : : }
5107 : :
5108 [ - + ]: 89 : if ( ! element->AsTableVal()->AddTo(tv, 1) )
5109 : 0 : return 0;
5110 : :
5111 : 89 : continue;
5112 : : }
5113 : :
5114 [ + + ]: 1012 : if ( exprs[i]->Type()->Tag() == TYPE_LIST )
5115 : 87 : element = check_and_promote(element, it, 1);
5116 : : else
5117 : 925 : element = check_and_promote(element, (*it->Types())[0], 1);
5118 : :
5119 [ - + ]: 1012 : if ( ! element )
5120 : 0 : return 0;
5121 : :
5122 [ - + ]: 1012 : if ( ! tv->ExpandAndInit(element, 0) )
5123 : : {
5124 : 0 : Unref(element);
5125 : 0 : Unref(tv);
5126 : 0 : return 0;
5127 : : }
5128 : :
5129 : 1012 : Unref(element);
5130 : : }
5131 : :
5132 : 196 : return tv;
5133 : : }
5134 : :
5135 : 0 : void ListExpr::ExprDescribe(ODesc* d) const
5136 : : {
5137 : 0 : d->AddCount(exprs.length());
5138 : :
5139 [ # # ]: 0 : loop_over_list(exprs, i)
5140 : : {
5141 [ # # ][ # # ]: 0 : if ( (d->IsReadable() || d->IsPortable()) && i > 0 )
[ # # ][ # # ]
5142 : 0 : d->Add(", ");
5143 : :
5144 : 0 : exprs[i]->Describe(d);
5145 : : }
5146 : 0 : }
5147 : :
5148 : 0 : Expr* ListExpr::MakeLvalue()
5149 : : {
5150 [ # # ]: 0 : loop_over_list(exprs, i)
5151 [ # # ]: 0 : if ( exprs[i]->Tag() != EXPR_NAME )
5152 : 0 : ExprError("can only assign to list of identifiers");
5153 : :
5154 : 0 : return new RefExpr(this);
5155 : : }
5156 : :
5157 : 0 : void ListExpr::Assign(Frame* f, Val* v, Opcode op)
5158 : : {
5159 : 0 : ListVal* lv = v->AsListVal();
5160 : :
5161 [ # # ]: 0 : if ( exprs.length() != lv->Vals()->length() )
5162 : 0 : ExprError("mismatch in list lengths");
5163 : :
5164 [ # # ]: 0 : loop_over_list(exprs, i)
5165 : 0 : exprs[i]->Assign(f, (*lv->Vals())[i]->Ref(), op);
5166 : :
5167 : 0 : Unref(lv);
5168 : 0 : }
5169 : :
5170 : 0 : TraversalCode ListExpr::Traverse(TraversalCallback* cb) const
5171 : : {
5172 : 0 : TraversalCode tc = cb->PreExpr(this);
5173 [ # # ]: 0 : HANDLE_TC_EXPR_PRE(tc);
5174 : :
5175 [ # # ]: 0 : loop_over_list(exprs, i)
5176 : : {
5177 : 0 : exprs[i]->Traverse(cb);
5178 [ # # ]: 0 : HANDLE_TC_EXPR_PRE(tc);
5179 : : }
5180 : :
5181 : 0 : tc = cb->PostExpr(this);
5182 : 0 : HANDLE_TC_EXPR_POST(tc);
5183 : : }
5184 : :
5185 : 3 : IMPLEMENT_SERIAL(ListExpr, SER_LIST_EXPR);
5186 : :
5187 : 0 : bool ListExpr::DoSerialize(SerialInfo* info) const
5188 : : {
5189 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_LIST_EXPR, Expr);
5190 : :
5191 [ # # ]: 0 : if ( ! SERIALIZE(exprs.length()) )
5192 : 0 : return false;
5193 : :
5194 [ # # ]: 0 : loop_over_list(exprs, i)
5195 [ # # ]: 0 : if ( ! exprs[i]->Serialize(info) )
5196 : 0 : return false;
5197 : :
5198 : 0 : return true;
5199 : : }
5200 : :
5201 : 0 : bool ListExpr::DoUnserialize(UnserialInfo* info)
5202 : : {
5203 [ # # ]: 0 : DO_UNSERIALIZE(Expr);
5204 : :
5205 : : int len;
5206 [ # # ]: 0 : if ( ! UNSERIALIZE(&len) )
5207 : 0 : return false;
5208 : :
5209 [ # # ]: 0 : while ( len-- )
5210 : : {
5211 : 0 : Expr* e = Expr::Unserialize(info);
5212 [ # # ]: 0 : if ( ! e )
5213 : 0 : return false;
5214 : :
5215 : 0 : exprs.append(e);
5216 : : }
5217 : :
5218 : 0 : return true;
5219 : : }
5220 : :
5221 : 0 : RecordAssignExpr::RecordAssignExpr(Expr* record, Expr* init_list, int is_init)
5222 : : {
5223 : 0 : const expr_list& inits = init_list->AsListExpr()->Exprs();
5224 : :
5225 : 0 : RecordType* lhs = record->Type()->AsRecordType();
5226 : :
5227 : : // The inits have two forms:
5228 : : // 1) other records -- use all matching field names+types
5229 : : // 2) a string indicating the field name, then (as the next element)
5230 : : // the value to use for that field.
5231 : :
5232 [ # # ][ # # ]: 0 : for ( int i = 0; i < inits.length(); ++i )
5233 : : {
5234 [ # # ][ # # ]: 0 : if ( inits[i]->Type()->Tag() == TYPE_RECORD )
5235 : : {
5236 : 0 : RecordType* t = inits[i]->Type()->AsRecordType();
5237 : :
5238 [ # # ][ # # ]: 0 : for ( int j = 0; j < t->NumFields(); ++j )
5239 : : {
5240 : 0 : const char* field_name = t->FieldName(j);
5241 : 0 : int field = lhs->FieldOffset(field_name);
5242 : :
5243 [ # # # # ]: 0 : if ( field >= 0 &&
[ # # # # ]
[ # # ][ # # ]
5244 : : same_type(lhs->FieldType(field), t->FieldType(j)) )
5245 : : {
5246 : 0 : FieldExpr* fe_lhs = new FieldExpr(record, field_name);
5247 : 0 : FieldExpr* fe_rhs = new FieldExpr(inits[i], field_name);
5248 : 0 : Append(get_assign_expr(fe_lhs->Ref(), fe_rhs->Ref(), is_init));
5249 : : }
5250 : : }
5251 : : }
5252 : :
5253 [ # # ][ # # ]: 0 : else if ( inits[i]->Tag() == EXPR_FIELD_ASSIGN )
5254 : : {
5255 : 0 : FieldAssignExpr* rf = (FieldAssignExpr*) inits[i];
5256 : 0 : rf->Ref();
5257 : :
5258 : 0 : const char* field_name = ""; // rf->FieldName();
5259 [ # # # # ]: 0 : if ( lhs->HasField(field_name) )
5260 : : {
5261 : 0 : FieldExpr* fe_lhs = new FieldExpr(record, field_name);
5262 : 0 : Expr* fe_rhs = rf->Op();
5263 : 0 : Append(get_assign_expr(fe_lhs->Ref(), fe_rhs, is_init));
5264 : : }
5265 : : else
5266 : : {
5267 : 0 : string s = "No such field '";
5268 : 0 : s += field_name;
5269 : 0 : s += "'";
5270 : 0 : init_list->SetError(s.c_str());
5271 : : }
5272 : : }
5273 : :
5274 : : else
5275 : : {
5276 : 0 : init_list->SetError("bad record initializer");
5277 : 0 : return;
5278 : : }
5279 : : }
5280 : 0 : }
5281 : :
5282 : 3 : IMPLEMENT_SERIAL(RecordAssignExpr, SER_RECORD_ASSIGN_EXPR);
5283 : :
5284 : 0 : bool RecordAssignExpr::DoSerialize(SerialInfo* info) const
5285 : : {
5286 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_RECORD_ASSIGN_EXPR, ListExpr);
5287 : 0 : return true;
5288 : : }
5289 : :
5290 : 0 : bool RecordAssignExpr::DoUnserialize(UnserialInfo* info)
5291 : : {
5292 [ # # ]: 0 : DO_UNSERIALIZE(ListExpr);
5293 : 0 : return true;
5294 : : }
5295 : :
5296 : 2507 : Expr* get_assign_expr(Expr* op1, Expr* op2, int is_init)
5297 : : {
5298 [ + + ][ - + ]: 2507 : if ( op1->Type()->Tag() == TYPE_RECORD &&
[ - + ]
5299 : : op2->Type()->Tag() == TYPE_LIST )
5300 : 0 : return new RecordAssignExpr(op1, op2, is_init);
5301 : : else
5302 : 2507 : return new AssignExpr(op1, op2, is_init);
5303 : : }
5304 : :
5305 : :
5306 : 6951 : int check_and_promote_expr(Expr*& e, BroType* t)
5307 : : {
5308 : 6951 : BroType* et = e->Type();
5309 : 6951 : TypeTag e_tag = et->Tag();
5310 : 6951 : TypeTag t_tag = t->Tag();
5311 : :
5312 [ + + ]: 6951 : if ( t->Tag() == TYPE_ANY )
5313 : 2 : return 1;
5314 : :
5315 [ + + ][ + + ]: 6949 : if ( EitherArithmetic(t_tag, e_tag) )
[ + - ][ + + ]
[ + - ][ + - ]
[ + - ][ - + ]
5316 : : {
5317 [ + + ]: 946 : if ( e_tag == t_tag )
5318 : 922 : return 1;
5319 : :
5320 [ - + ][ # # ]: 24 : if ( ! BothArithmetic(t_tag, e_tag) )
[ # # ][ # # ]
[ + - ][ - + ]
[ # # ][ # # ]
5321 : : {
5322 : 0 : t->Error("arithmetic mixed with non-arithmetic", e);
5323 : 0 : return 0;
5324 : : }
5325 : :
5326 : 24 : TypeTag mt = max_type(t_tag, e_tag);
5327 [ - + ]: 24 : if ( mt != t_tag )
5328 : : {
5329 : 0 : t->Error("over-promotion of arithmetic value", e);
5330 : 0 : return 0;
5331 : : }
5332 : :
5333 : 24 : e = new ArithCoerceExpr(e, t_tag);
5334 : 24 : return 1;
5335 : : }
5336 : :
5337 [ + + ]: 6003 : else if ( ! same_type(t, et) )
5338 : : {
5339 [ + + ][ + - ]: 187 : if ( t->Tag() == TYPE_RECORD && et->Tag() == TYPE_RECORD )
[ + + ]
5340 : : {
5341 : 185 : RecordType* t_r = t->AsRecordType();
5342 : 185 : RecordType* et_r = et->AsRecordType();
5343 : :
5344 [ + - ]: 185 : if ( record_promotion_compatible(t_r, et_r) )
5345 : : {
5346 : 185 : e = new RecordCoerceExpr(e, t_r);
5347 : 185 : return 1;
5348 : : }
5349 : : }
5350 : :
5351 [ + - ][ + - ]: 2 : else if ( t->Tag() == TYPE_TABLE && et->Tag() == TYPE_TABLE &&
[ + - ][ + - ]
5352 : : et->AsTableType()->IsUnspecifiedTable() )
5353 : : {
5354 : 2 : e = new TableCoerceExpr(e, t->AsTableType());
5355 : 2 : return 1;
5356 : : }
5357 : :
5358 : 0 : t->Error("type clash", e);
5359 : 0 : return 0;
5360 : : }
5361 : :
5362 : 6951 : return 1;
5363 : : }
5364 : :
5365 : 5447 : int check_and_promote_exprs(ListExpr*& elements, TypeList* types)
5366 : : {
5367 : 5447 : expr_list& el = elements->Exprs();
5368 : 5447 : const type_list* tl = types->Types();
5369 : :
5370 [ + + + + ]: 5447 : if ( tl->length() == 1 && (*tl)[0]->Tag() == TYPE_ANY )
[ + + ]
5371 : 1031 : return 1;
5372 : :
5373 [ - + ]: 4416 : if ( el.length() != tl->length() )
5374 : : {
5375 : 0 : types->Error("indexing mismatch", elements);
5376 : 0 : return 0;
5377 : : }
5378 : :
5379 [ + + ]: 10685 : loop_over_list(el, i)
5380 : : {
5381 : 6269 : Expr* e = el[i];
5382 [ - + ]: 6269 : if ( ! check_and_promote_expr(e, (*tl)[i]) )
5383 : : {
5384 : 0 : e->Error("type mismatch", (*tl)[i]);
5385 : 0 : return 0;
5386 : : }
5387 : :
5388 [ + + ]: 6269 : if ( e != el[i] )
5389 : 201 : el.replace(i, e);
5390 : : }
5391 : :
5392 : 5447 : return 1;
5393 : : }
5394 : :
5395 : 6 : int check_and_promote_exprs_to_type(ListExpr*& elements, BroType* type)
5396 : : {
5397 : 6 : expr_list& el = elements->Exprs();
5398 : :
5399 [ - + ]: 6 : if ( type->Tag() == TYPE_ANY )
5400 : 0 : return 1;
5401 : :
5402 [ + + ]: 78 : loop_over_list(el, i)
5403 : : {
5404 : 72 : Expr* e = el[i];
5405 [ - + ]: 72 : if ( ! check_and_promote_expr(e, type) )
5406 : : {
5407 : 0 : e->Error("type mismatch", type);
5408 : 0 : return 0;
5409 : : }
5410 : :
5411 [ - + ]: 72 : if ( e != el[i] )
5412 : 0 : el.replace(i, e);
5413 : : }
5414 : :
5415 : 6 : return 1;
5416 : : }
5417 : :
5418 : 0 : Expr* simplify_expr(Expr* e, SimplifyType simp_type)
5419 : : {
5420 [ # # ]: 0 : if ( ! e )
5421 : 0 : return 0;
5422 : :
5423 [ # # ]: 0 : for ( Expr* s = e->Simplify(simp_type); s != e; s = e->Simplify(simp_type) )
5424 : : {
5425 : 0 : Unref(e);
5426 : 0 : e = s;
5427 : : }
5428 : :
5429 : 0 : return e;
5430 : : }
5431 : :
5432 : 0 : ListExpr* simplify_expr_list(ListExpr* l, SimplifyType simp_type)
5433 : : {
5434 : 0 : return (ListExpr*) simplify_expr(l, simp_type);
5435 : : }
5436 : :
5437 : 212013 : val_list* eval_list(Frame* f, const ListExpr* l)
5438 : : {
5439 : 212013 : const expr_list& e = l->Exprs();
5440 : 212013 : val_list* v = new val_list(e.length());
5441 : :
5442 [ + + ]: 694197 : loop_over_list(e, i)
5443 : : {
5444 : 482184 : Val* ev = e[i]->Eval(f);
5445 [ - + ]: 482184 : if ( ! ev )
5446 : 0 : break;
5447 : 482184 : v->append(ev);
5448 : : }
5449 : :
5450 [ - + ]: 212013 : if ( i < e.length() )
5451 : : { // Failure.
5452 [ # # ]: 0 : loop_over_list(*v, j)
5453 : 0 : Unref((*v)[j]);
5454 [ # # ]: 0 : delete v;
5455 : 0 : return 0;
5456 : : }
5457 : :
5458 : : else
5459 : 212013 : return v;
5460 : : }
5461 : :
5462 : 0 : int same_expr(const Expr* e1, const Expr* e2)
5463 : : {
5464 [ # # ]: 0 : if ( e1 == e2 )
5465 : 0 : return 1;
5466 : :
5467 [ # # ][ # # ]: 0 : if ( e1->Tag() != e2->Tag() || ! same_type(e1->Type(), e2->Type()) )
[ # # ]
5468 : 0 : return 0;
5469 : :
5470 [ # # ][ # # ]: 0 : if ( e1->IsError() || e2->IsError() )
[ # # ]
5471 : 0 : return 0;
5472 : :
5473 [ # # # # # : 0 : switch ( e1->Tag() ) {
# # # # ]
5474 : : case EXPR_NAME:
5475 : : {
5476 : 0 : const NameExpr* n1 = (NameExpr*) e1;
5477 : 0 : const NameExpr* n2 = (NameExpr*) e2;
5478 : 0 : return n1->Id() == n2->Id();
5479 : : }
5480 : :
5481 : : case EXPR_CONST:
5482 : : {
5483 : 0 : const ConstExpr* c1 = (ConstExpr*) e1;
5484 : 0 : const ConstExpr* c2 = (ConstExpr*) e2;
5485 : 0 : return same_val(c1->Value(), c2->Value());
5486 : : }
5487 : :
5488 : : case EXPR_INCR:
5489 : : case EXPR_DECR:
5490 : : case EXPR_NOT:
5491 : : case EXPR_NEGATE:
5492 : : case EXPR_POSITIVE:
5493 : : case EXPR_REF:
5494 : : case EXPR_RECORD_CONSTRUCTOR:
5495 : : case EXPR_TABLE_CONSTRUCTOR:
5496 : : case EXPR_SET_CONSTRUCTOR:
5497 : : case EXPR_VECTOR_CONSTRUCTOR:
5498 : : case EXPR_FIELD_ASSIGN:
5499 : : case EXPR_ARITH_COERCE:
5500 : : case EXPR_RECORD_COERCE:
5501 : : case EXPR_TABLE_COERCE:
5502 : : case EXPR_FLATTEN:
5503 : : {
5504 : 0 : const UnaryExpr* u1 = (UnaryExpr*) e1;
5505 : 0 : const UnaryExpr* u2 = (UnaryExpr*) e2;
5506 : 0 : return same_expr(u1->Op(), u2->Op());
5507 : : }
5508 : :
5509 : : case EXPR_FIELD:
5510 : : {
5511 : 0 : const FieldExpr* f1 = (FieldExpr*) e1;
5512 : 0 : const FieldExpr* f2 = (FieldExpr*) e2;
5513 : : return same_expr(f1->Op(), f2->Op()) &&
5514 [ # # ][ # # ]: 0 : f1->Field() == f2->Field();
5515 : : }
5516 : :
5517 : : case EXPR_SCHEDULE:
5518 : : {
5519 : 0 : const ScheduleExpr* s1 = (ScheduleExpr*) e1;
5520 : 0 : const ScheduleExpr* s2 = (ScheduleExpr*) e2;
5521 : : return same_expr(s1->When(), s2->When()) &&
5522 [ # # ][ # # ]: 0 : same_expr(s1->Event(), s2->Event());
5523 : : }
5524 : :
5525 : : case EXPR_ADD:
5526 : : case EXPR_ADD_TO:
5527 : : case EXPR_SUB:
5528 : : case EXPR_REMOVE_FROM:
5529 : : case EXPR_TIMES:
5530 : : case EXPR_DIVIDE:
5531 : : case EXPR_MOD:
5532 : : case EXPR_AND:
5533 : : case EXPR_OR:
5534 : : case EXPR_LT:
5535 : : case EXPR_LE:
5536 : : case EXPR_EQ:
5537 : : case EXPR_NE:
5538 : : case EXPR_GE:
5539 : : case EXPR_GT:
5540 : : case EXPR_ASSIGN:
5541 : : case EXPR_MATCH:
5542 : : case EXPR_INDEX:
5543 : : case EXPR_IN:
5544 : : {
5545 : 0 : const BinaryExpr* b1 = (BinaryExpr*) e1;
5546 : 0 : const BinaryExpr* b2 = (BinaryExpr*) e2;
5547 : : return same_expr(b1->Op1(), b2->Op1()) &&
5548 [ # # ][ # # ]: 0 : same_expr(b1->Op2(), b2->Op2());
5549 : : }
5550 : :
5551 : : case EXPR_LIST:
5552 : : {
5553 : 0 : const ListExpr* l1 = (ListExpr*) e1;
5554 : 0 : const ListExpr* l2 = (ListExpr*) e2;
5555 : :
5556 : 0 : const expr_list& le1 = l1->Exprs();
5557 : 0 : const expr_list& le2 = l2->Exprs();
5558 : :
5559 [ # # ]: 0 : if ( le1.length() != le2.length() )
5560 : 0 : return 0;
5561 : :
5562 [ # # ]: 0 : loop_over_list(le1, i)
5563 [ # # ]: 0 : if ( ! same_expr(le1[i], le2[i]) )
5564 : 0 : return 0;
5565 : :
5566 : 0 : return 1;
5567 : : }
5568 : :
5569 : : case EXPR_CALL:
5570 : : {
5571 : 0 : const CallExpr* c1 = (CallExpr*) e1;
5572 : 0 : const CallExpr* c2 = (CallExpr*) e2;
5573 : :
5574 : : return same_expr(c1->Func(), c2->Func()) &&
5575 [ # # ][ # # ]: 0 : c1->IsPure() && same_expr(c1->Args(), c2->Args());
[ # # ]
5576 : : }
5577 : :
5578 : : default:
5579 : 0 : internal_error("bad tag in same_expr()");
5580 : : }
5581 : :
5582 : : return 0;
5583 : : }
5584 : :
5585 : 879 : int expr_greater(const Expr* e1, const Expr* e2)
5586 : : {
5587 : 879 : return int(e1->Tag()) > int(e2->Tag());
5588 : : }
5589 : :
5590 : 0 : static Expr* make_constant(BroType* t, double d)
5591 : : {
5592 : 0 : Val* v = 0;
5593 [ # # # # ]: 0 : switch ( t->InternalType() ) {
5594 : 0 : case TYPE_INTERNAL_INT: v = new Val(bro_int_t(d), t->Tag()); break;
5595 : 0 : case TYPE_INTERNAL_UNSIGNED: v = new Val(bro_uint_t(d), t->Tag()); break;
5596 : 0 : case TYPE_INTERNAL_DOUBLE: v = new Val(double(d), t->Tag()); break;
5597 : :
5598 : : default:
5599 : 0 : internal_error("bad type in make_constant()");
5600 : : }
5601 : :
5602 : 0 : return new ConstExpr(v);
5603 : : }
5604 : :
5605 : 0 : Expr* make_zero(BroType* t)
5606 : : {
5607 : 0 : return make_constant(t, 0.0);
5608 : : }
5609 : :
5610 : 0 : Expr* make_one(BroType* t)
5611 : : {
5612 : 0 : return make_constant(t, 1.0);
5613 [ + - ][ + - ]: 6 : }
|