LCOV - code coverage report
Current view: top level - src - Stmt.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 278 1116 24.9 %
Date: 2010-12-13 Functions: 33 218 15.1 %
Branches: 125 1166 10.7 %

           Branch data     Line data    Source code
       1                 :            : // $Id: Stmt.cc 6916 2009-09-24 20:48:36Z 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 "File.h"
      11                 :            : #include "Logger.h"
      12                 :            : #include "NetVar.h"
      13                 :            : #include "Stmt.h"
      14                 :            : #include "Scope.h"
      15                 :            : #include "Var.h"
      16                 :            : #include "Debug.h"
      17                 :            : #include "Traverse.h"
      18                 :            : #include "Trigger.h"
      19                 :            : #include "RemoteSerializer.h"
      20                 :            : 
      21                 :          0 : const char* stmt_name(BroStmtTag t)
      22                 :            :         {
      23                 :            :         static const char* stmt_names[int(NUM_STMTS)] = {
      24                 :            :                 "alarm", "print", "event", "expr", "if", "when", "switch",
      25                 :            :                 "for", "next", "break", "return", "add", "delete",
      26                 :            :                 "list", "bodylist",
      27                 :            :                 "<init>",
      28                 :            :                 "null",
      29                 :            :         };
      30                 :            : 
      31                 :          0 :         return stmt_names[int(t)];
      32                 :            :         }
      33                 :            : 
      34                 :      10505 : Stmt::Stmt(BroStmtTag arg_tag)
      35                 :            :         {
      36                 :      10505 :         tag = arg_tag;
      37                 :      10505 :         breakpoint_count = 0;
      38                 :      10505 :         last_access = 0;
      39                 :      10505 :         access_count = 0;
      40                 :            : 
      41                 :      10505 :         SetLocationInfo(&start_location, &end_location);
      42                 :      10505 :         }
      43                 :            : 
      44                 :        109 : Stmt::~Stmt()
      45                 :            :         {
      46 [ #  # ][ #  # ]:        109 :         }
                 [ -  + ]
      47                 :            : 
      48                 :      18987 : bool Stmt::SetLocationInfo(const Location* start, const Location* end)
      49                 :            :         {
      50         [ -  + ]:      18987 :         if ( ! BroObj::SetLocationInfo(start, end) )
      51                 :          0 :                 return false;
      52                 :            : 
      53                 :            :         // Update the Filemap of line number -> statement mapping for
      54                 :            :         // breakpoints (Debug.h).
      55                 :      18987 :         Filemap* map_ptr = (Filemap*) g_dbgfilemaps.Lookup(location->filename);
      56         [ +  - ]:      18987 :         if ( ! map_ptr )
      57                 :      18987 :                 return false;
      58                 :            : 
      59                 :          0 :         Filemap& map = *map_ptr;
      60                 :            : 
      61                 :          0 :         StmtLocMapping* new_mapping = new StmtLocMapping(GetLocationInfo(), this);
      62                 :            : 
      63                 :            :         // Optimistically just put it at the end.
      64                 :          0 :         map.push_back(new_mapping);
      65                 :            : 
      66                 :          0 :         int curr_idx = map.length() - 1;
      67         [ #  # ]:          0 :         if ( curr_idx == 0 )
      68                 :          0 :                 return true;
      69                 :            : 
      70                 :            :         // In case it wasn't actually lexically last, bubble it to the
      71                 :            :         // right place.
      72         [ #  # ]:          0 :         while ( map[curr_idx - 1]->StartsAfter(map[curr_idx]) )
      73                 :            :                 {
      74                 :          0 :                 StmtLocMapping t = *map[curr_idx - 1];
      75                 :          0 :                 *map[curr_idx - 1] = *map[curr_idx];
      76                 :          0 :                 *map[curr_idx] = t;
      77                 :          0 :                 curr_idx--;
      78                 :            :                 }
      79                 :            : 
      80                 :      18987 :         return true;
      81                 :            :         }
      82                 :            : 
      83                 :          0 : Stmt* Stmt::Simplify()
      84                 :            :         {
      85                 :          0 :         return this;
      86                 :            :         }
      87                 :            : 
      88                 :          0 : int Stmt::IsPure() const
      89                 :            :         {
      90                 :          0 :         return 0;
      91                 :            :         }
      92                 :            : 
      93                 :          0 : void Stmt::Describe(ODesc* d) const
      94                 :            :         {
      95 [ #  # ][ #  # ]:          0 :         if ( ! d->IsReadable() || Tag() != STMT_EXPR )
                 [ #  # ]
      96                 :          0 :                 AddTag(d);
      97                 :          0 :         }
      98                 :            : 
      99                 :          0 : void Stmt::AddTag(ODesc* d) const
     100                 :            :         {
     101         [ #  # ]:          0 :         if ( d->IsBinary() )
     102                 :          0 :                 d->Add(int(Tag()));
     103                 :            :         else
     104                 :          0 :                 d->Add(stmt_name(Tag()));
     105                 :          0 :         d->SP();
     106                 :          0 :         }
     107                 :            : 
     108                 :          0 : void Stmt::DescribeDone(ODesc* d) const
     109                 :            :         {
     110 [ #  # ][ #  # ]:          0 :         if ( d->IsReadable() && ! d->IsShort() )
                 [ #  # ]
     111                 :          0 :                 d->Add(";");
     112                 :          0 :         }
     113                 :            : 
     114                 :          0 : void Stmt::AccessStats(ODesc* d) const
     115                 :            :         {
     116         [ #  # ]:          0 :         if ( d->IncludeStats() )
     117                 :            :                 {
     118                 :          0 :                 d->Add("(@");
     119         [ #  # ]:          0 :                 d->Add(last_access ? fmt_access_time(last_access) : "<never>");
     120                 :          0 :                 d->Add(" #");
     121                 :          0 :                 d->Add(access_count);
     122                 :          0 :                 d->Add(")");
     123                 :          0 :                 d->NL();
     124                 :            :                 }
     125                 :          0 :         }
     126                 :            : 
     127                 :          0 : bool Stmt::Serialize(SerialInfo* info) const
     128                 :            :         {
     129                 :          0 :         return SerialObj::Serialize(info);
     130                 :            :         }
     131                 :            : 
     132                 :          0 : Stmt* Stmt::Unserialize(UnserialInfo* info, BroStmtTag want)
     133                 :            :         {
     134                 :          0 :         Stmt* stmt = (Stmt*) SerialObj::Unserialize(info, SER_STMT);
     135                 :            : 
     136   [ #  #  #  # ]:          0 :         if ( want != STMT_ANY && stmt->tag != want )
     137                 :            :                 {
     138                 :          0 :                 info->s->Error("wrong stmt type");
     139                 :          0 :                 Unref(stmt);
     140                 :          0 :                 return 0;
     141                 :            :                 }
     142                 :            : 
     143                 :          0 :         return stmt;
     144                 :            :         }
     145                 :            : 
     146                 :          0 : bool Stmt::DoSerialize(SerialInfo* info) const
     147                 :            :         {
     148 [ #  # ][ #  # ]:          0 :         DO_SERIALIZE(SER_STMT, BroObj);
     149                 :            : 
     150                 :            :         return SERIALIZE(char(tag)) && SERIALIZE(last_access)
     151 [ #  # ][ #  # ]:          0 :                         && SERIALIZE(access_count);
                 [ #  # ]
     152                 :            :         }
     153                 :            : 
     154                 :          0 : bool Stmt::DoUnserialize(UnserialInfo* info)
     155                 :            :         {
     156         [ #  # ]:          0 :         DO_UNSERIALIZE(BroObj);
     157                 :            : 
     158                 :            :         char c;
     159         [ #  # ]:          0 :         if ( ! UNSERIALIZE(&c) )
     160                 :          0 :                 return 0;
     161                 :            : 
     162                 :          0 :         tag = BroStmtTag(c);
     163                 :            : 
     164 [ #  # ][ #  # ]:          0 :         return UNSERIALIZE(&last_access) && UNSERIALIZE(&access_count);
     165                 :            :         }
     166                 :            : 
     167                 :            : 
     168                 :        281 : ExprListStmt::ExprListStmt(BroStmtTag t, ListExpr* arg_l)
     169                 :        281 : : Stmt(t)
     170                 :            :         {
     171                 :        281 :         l = arg_l;
     172                 :            : 
     173                 :        281 :         const expr_list& e = l->Exprs();
     174 [ #  # ][ +  + ]:        792 :         loop_over_list(e, i)
     175                 :            :                 {
     176                 :        511 :                 const BroType* t = e[i]->Type();
     177   [ #  #  #  # ]:        511 :                 if ( ! t || t->Tag() == TYPE_VOID )
           [ #  #  +  - ]
         [ -  + ][ -  + ]
     178                 :          0 :                         Error("value of type void illegal");
     179                 :            :                 }
     180                 :            : 
     181                 :        281 :         SetLocationInfo(arg_l->GetLocationInfo());
     182                 :        281 :         }
     183                 :            : 
     184                 :          0 : ExprListStmt::~ExprListStmt()
     185                 :            :         {
     186                 :          0 :         Unref(l);
     187 [ #  # ][ #  # ]:          0 :         }
                 [ #  # ]
     188                 :            : 
     189                 :       6344 : Val* ExprListStmt::Exec(Frame* f, stmt_flow_type& flow) const
     190                 :            :         {
     191                 :       6344 :         last_access = network_time;
     192                 :       6344 :         flow = FLOW_NEXT;
     193                 :            : 
     194                 :       6344 :         val_list* vals = eval_list(f, l);
     195         [ +  - ]:       6344 :         if ( vals )
     196                 :            :                 {
     197                 :       6344 :                 Val* result = DoExec(vals, flow);
     198                 :       6344 :                 delete_vals(vals);
     199                 :       6344 :                 return result;
     200                 :            :                 }
     201                 :            :         else
     202                 :       6344 :                 return 0;
     203                 :            :         }
     204                 :            : 
     205                 :          0 : Stmt* ExprListStmt::Simplify()
     206                 :            :         {
     207                 :          0 :         l = simplify_expr_list(l, SIMPLIFY_GENERAL);
     208                 :          0 :         DoSimplify();
     209                 :          0 :         return this;
     210                 :            :         }
     211                 :            : 
     212                 :          0 : Stmt* ExprListStmt::DoSimplify()
     213                 :            :         {
     214                 :          0 :         return this;
     215                 :            :         }
     216                 :            : 
     217                 :          0 : void ExprListStmt::Describe(ODesc* d) const
     218                 :            :         {
     219                 :          0 :         Stmt::Describe(d);
     220                 :          0 :         l->Describe(d);
     221                 :          0 :         DescribeDone(d);
     222                 :          0 :         }
     223                 :            : 
     224                 :       6344 : void ExprListStmt::PrintVals(ODesc* d, val_list* vals, int offset) const
     225                 :            :         {
     226                 :       6344 :         describe_vals(vals, d, offset);
     227                 :       6344 :         }
     228                 :            : 
     229                 :          0 : bool ExprListStmt::DoSerialize(SerialInfo* info) const
     230                 :            :         {
     231 [ #  # ][ #  # ]:          0 :         DO_SERIALIZE(SER_EXPR_LIST_STMT, Stmt);
     232                 :          0 :         return l->Serialize(info);
     233                 :            :         }
     234                 :            : 
     235                 :          0 : bool ExprListStmt::DoUnserialize(UnserialInfo* info)
     236                 :            :         {
     237         [ #  # ]:          0 :         DO_UNSERIALIZE(Stmt);
     238                 :          0 :         l = (ListExpr*) Expr::Unserialize(info, EXPR_LIST);
     239                 :          0 :         return l != 0;
     240                 :            :         }
     241                 :            : 
     242                 :          0 : TraversalCode ExprListStmt::Traverse(TraversalCallback* cb) const
     243                 :            :         {
     244                 :          0 :         TraversalCode tc = cb->PreStmt(this);
     245   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
     246                 :            : 
     247                 :          0 :         const expr_list& e = l->Exprs();
     248         [ #  # ]:          0 :         loop_over_list(e, i)
     249                 :            :                 {
     250                 :          0 :                 tc = e[i]->Traverse(cb);
     251   [ #  #  #  # ]:          0 :                 HANDLE_TC_STMT_PRE(tc);
     252                 :            :                 }
     253                 :            : 
     254                 :          0 :         tc = cb->PostStmt(this);
     255 [ #  # ][ #  # ]:          0 :         HANDLE_TC_STMT_POST(tc);
     256                 :            :         }
     257                 :            : 
     258                 :       1379 : Val* AlarmStmt::DoExec(val_list* vals, stmt_flow_type& /* flow */) const
     259                 :            :         {
     260                 :       1379 :         ODesc d;
     261                 :       1379 :         PrintVals(&d, vals, 0);
     262                 :            : 
     263         [ -  + ]:       1379 :         if ( alarm_hook )
     264                 :            :                 {
     265                 :          0 :                 ListExpr* args = new ListExpr();
     266                 :          0 :                 args->Append(new ConstExpr(new StringVal(d.Description())));
     267                 :            : 
     268                 :            :                 CallExpr* ce =
     269                 :          0 :                         new CallExpr(new ConstExpr(new Val(alarm_hook)), args);
     270                 :            : 
     271                 :          0 :                 Val* hook_eval = ce->Eval(0);
     272                 :          0 :                 int do_log = hook_eval->IsOne();
     273                 :            : 
     274                 :          0 :                 Unref(ce);
     275                 :          0 :                 Unref(hook_eval);
     276                 :            : 
     277         [ #  # ]:          0 :                 if ( ! do_log )
     278                 :          0 :                         return 0;
     279                 :            :                 }
     280                 :            : 
     281                 :       1379 :         bro_logger->Log(d.Description());
     282                 :       1379 :         return 0;
     283                 :            :         }
     284                 :            : 
     285                 :          3 : IMPLEMENT_SERIAL(AlarmStmt, SER_ALARM_STMT);
     286                 :            : 
     287                 :          0 : bool AlarmStmt::DoSerialize(SerialInfo* info) const
     288                 :            :         {
     289 [ #  # ][ #  # ]:          0 :         DO_SERIALIZE(SER_ALARM_STMT, ExprListStmt);
     290                 :          0 :         return true;
     291                 :            :         }
     292                 :            : 
     293                 :          0 : bool AlarmStmt::DoUnserialize(UnserialInfo* info)
     294                 :            :         {
     295         [ #  # ]:          0 :         DO_UNSERIALIZE(ExprListStmt);
     296                 :          0 :         return true;
     297                 :            :         }
     298                 :            : 
     299                 :            : static BroFile* print_stdout = 0;
     300                 :            : 
     301                 :       4965 : Val* PrintStmt::DoExec(val_list* vals, stmt_flow_type& /* flow */) const
     302                 :            :         {
     303         [ +  + ]:       4965 :         if ( ! print_stdout )
     304                 :          1 :                 print_stdout = new BroFile(stdout);
     305                 :            : 
     306                 :       4965 :         BroFile* f = print_stdout;
     307                 :       4965 :         int offset = 0;
     308                 :            : 
     309 [ +  - ][ +  - ]:       4965 :         if ( vals->length() > 0 && (*vals)[0]->Type()->Tag() == TYPE_FILE )
                 [ +  - ]
     310                 :            :                 {
     311                 :       4965 :                 f = (*vals)[0]->AsFile();
     312         [ -  + ]:       4965 :                 if ( ! f->IsOpen() )
     313                 :          0 :                         return 0;
     314                 :            : 
     315                 :       4965 :                 ++offset;
     316                 :            :                 }
     317                 :            : 
     318 [ -  + ][ #  # ]:       4965 :         bool ph = print_hook && f->IsPrintHookEnabled();
     319                 :            : 
     320         [ -  + ]:       4965 :         desc_style style = f->IsRawOutput() ? ALTERNATIVE_STYLE : STANDARD_STYLE;
     321                 :            : 
     322 [ -  + ][ #  # ]:       4965 :         if ( ! (suppress_local_output && ph) )
     323                 :            :                 {
     324                 :       4965 :                 ODesc d(DESC_READABLE, f);
     325                 :       4965 :                 d.SetFlush(0);
     326                 :       4965 :                 d.SetStyle(style);
     327                 :            : 
     328                 :       4965 :                 PrintVals(&d, vals, offset);
     329                 :       4965 :                 f->Write("\n", 1);
     330                 :            :                 }
     331                 :            : 
     332         [ -  + ]:       4965 :         if ( ph )
     333                 :            :                 {
     334                 :          0 :                 ODesc d(DESC_READABLE);
     335                 :          0 :                 d.SetStyle(style);
     336                 :          0 :                 PrintVals(&d, vals, offset);
     337                 :            : 
     338         [ #  # ]:          0 :                 if ( print_hook )
     339                 :            :                         {
     340                 :          0 :                         val_list* vl = new val_list(2);
     341                 :          0 :                         ::Ref(f);
     342                 :          0 :                         vl->append(new Val(f));
     343                 :          0 :                         vl->append(new StringVal(d.Description()));
     344                 :            : 
     345                 :            :                         // Note, this doesn't do remote printing.
     346                 :          0 :                         mgr.Dispatch(new Event(print_hook, vl), true);
     347                 :            :                         }
     348                 :            : 
     349         [ #  # ]:          0 :                 if ( remote_serializer )
     350                 :          0 :                         remote_serializer->SendPrintHookEvent(f, d.Description());
     351                 :            :                 }
     352                 :            : 
     353                 :       4965 :         return 0;
     354                 :            :         }
     355                 :            : 
     356                 :          3 : IMPLEMENT_SERIAL(PrintStmt, SER_PRINT_STMT);
     357                 :            : 
     358                 :          0 : bool PrintStmt::DoSerialize(SerialInfo* info) const
     359                 :            :         {
     360 [ #  # ][ #  # ]:          0 :         DO_SERIALIZE(SER_PRINT_STMT, ExprListStmt);
     361                 :          0 :         return true;
     362                 :            :         }
     363                 :            : 
     364                 :          0 : bool PrintStmt::DoUnserialize(UnserialInfo* info)
     365                 :            :         {
     366         [ #  # ]:          0 :         DO_UNSERIALIZE(ExprListStmt);
     367                 :          0 :         return true;
     368                 :            :         }
     369                 :            : 
     370                 :       3564 : ExprStmt::ExprStmt(Expr* arg_e) : Stmt(STMT_EXPR)
     371                 :            :         {
     372                 :       3564 :         e = arg_e;
     373   [ +  -  -  + ]:       3564 :         if ( e && e->IsPure() )
           [ -  +  #  # ]
         [ #  # ][ #  # ]
     374                 :          0 :                 Warn("expression value ignored");
     375                 :            : 
     376                 :       3564 :         SetLocationInfo(arg_e->GetLocationInfo());
     377                 :       3564 :         }
     378                 :            : 
     379                 :       3017 : ExprStmt::ExprStmt(BroStmtTag t, Expr* arg_e) : Stmt(t)
     380                 :            :         {
     381                 :       3017 :         e = arg_e;
     382                 :            : 
     383   [ #  #  +  + ]:       3017 :         if ( e )
     384                 :       2814 :                 SetLocationInfo(e->GetLocationInfo());
     385                 :       3017 :         }
     386                 :            : 
     387                 :          1 : ExprStmt::~ExprStmt()
     388                 :            :         {
     389                 :          1 :         Unref(e);
     390 [ #  # ][ #  # ]:          1 :         }
                 [ -  + ]
     391                 :            : 
     392                 :     454774 : Val* ExprStmt::Exec(Frame* f, stmt_flow_type& flow) const
     393                 :            :         {
     394                 :     454774 :         RegisterAccess();
     395                 :     454774 :         flow = FLOW_NEXT;
     396                 :            : 
     397                 :     454774 :         Val* v = e->Eval(f);
     398                 :            : 
     399         [ +  + ]:     454774 :         if ( v )
     400                 :            :                 {
     401                 :     443748 :                 Val* ret_val = DoExec(f, v, flow);
     402                 :     443748 :                 Unref(v);
     403                 :     443748 :                 return ret_val;
     404                 :            :                 }
     405                 :            :         else
     406                 :     454774 :                 return 0;
     407                 :            :         }
     408                 :            : 
     409                 :     244223 : Val* ExprStmt::DoExec(Frame* /* f */, Val* /* v */, stmt_flow_type& /* flow */) const
     410                 :            :         {
     411                 :     244223 :         return 0;
     412                 :            :         }
     413                 :            : 
     414                 :          0 : Stmt* ExprStmt::Simplify()
     415                 :            :         {
     416                 :          0 :         e = simplify_expr(e, SIMPLIFY_GENERAL);
     417                 :          0 :         return DoSimplify();
     418                 :            :         }
     419                 :            : 
     420                 :          0 : Stmt* ExprStmt::DoSimplify()
     421                 :            :         {
     422                 :          0 :         return this;
     423                 :            :         }
     424                 :            : 
     425                 :          0 : int ExprStmt::IsPure() const
     426                 :            :         {
     427 [ #  # ][ #  # ]:          0 :         return ! e || e->IsPure();
     428                 :            :         }
     429                 :            : 
     430                 :          0 : void ExprStmt::Describe(ODesc* d) const
     431                 :            :         {
     432                 :          0 :         Stmt::Describe(d);
     433                 :            : 
     434   [ #  #  #  # ]:          0 :         if ( d->IsReadable() && Tag() == STMT_IF )
                 [ #  # ]
     435                 :          0 :                 d->Add("(");
     436                 :          0 :         e->Describe(d);
     437                 :            : 
     438   [ #  #  #  # ]:          0 :         if ( Tag() == STMT_IF || Tag() == STMT_SWITCH )
                 [ #  # ]
     439                 :            :                 {
     440         [ #  # ]:          0 :                 if ( d->IsReadable() )
     441                 :            :                         {
     442         [ #  # ]:          0 :                         if ( Tag() == STMT_IF )
     443                 :          0 :                                 d->Add(")");
     444                 :          0 :                         d->SP();
     445                 :            :                         }
     446                 :            :                 }
     447                 :            :         else
     448                 :          0 :                 DescribeDone(d);
     449                 :          0 :         }
     450                 :            : 
     451                 :          0 : TraversalCode ExprStmt::Traverse(TraversalCallback* cb) const
     452                 :            :         {
     453                 :          0 :         TraversalCode tc = cb->PreStmt(this);
     454   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
     455                 :            : 
     456         [ #  # ]:          0 :         if ( e )
     457                 :            :                 {
     458                 :          0 :                 tc = e->Traverse(cb);
     459   [ #  #  #  # ]:          0 :                 HANDLE_TC_STMT_PRE(tc);
     460                 :            :                 }
     461                 :            : 
     462                 :          0 :         tc = cb->PostStmt(this);
     463 [ #  # ][ #  # ]:          0 :         HANDLE_TC_STMT_POST(tc);
     464                 :            :         }
     465                 :            : 
     466                 :          3 : IMPLEMENT_SERIAL(ExprStmt, SER_EXPR_STMT);
     467                 :            : 
     468                 :          0 : bool ExprStmt::DoSerialize(SerialInfo* info) const
     469                 :            :         {
     470 [ #  # ][ #  # ]:          0 :         DO_SERIALIZE(SER_EXPR_STMT, Stmt);
     471 [ #  # ][ #  # ]:          0 :         SERIALIZE_OPTIONAL(e);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     472                 :          0 :         return true;
     473                 :            :         }
     474                 :            : 
     475                 :          0 : bool ExprStmt::DoUnserialize(UnserialInfo* info)
     476                 :            :         {
     477         [ #  # ]:          0 :         DO_UNSERIALIZE(Stmt);
     478 [ #  # ][ #  # ]:          0 :         UNSERIALIZE_OPTIONAL(e, Expr::Unserialize(info));
                 [ #  # ]
     479                 :          0 :         return true;
     480                 :            :         }
     481                 :            : 
     482                 :       1725 : IfStmt::IfStmt(Expr* test, Stmt* arg_s1, Stmt* arg_s2) : ExprStmt(STMT_IF, test)
     483                 :            :         {
     484                 :       1725 :         s1 = arg_s1;
     485                 :       1725 :         s2 = arg_s2;
     486                 :            : 
     487   [ +  -  -  + ]:       1725 :         if ( ! e->IsError() && ! IsBool(e->Type()->Tag()) )
           [ -  +  #  # ]
         [ #  # ][ #  # ]
     488                 :          0 :                 e->Error("conditional in test must be boolean");
     489                 :            : 
     490                 :       1725 :         const Location* loc1 = arg_s1->GetLocationInfo();
     491                 :       1725 :         const Location* loc2 = arg_s2->GetLocationInfo();
     492                 :       1725 :         SetLocationInfo(loc1, loc2);
     493                 :       1725 :         }
     494                 :            : 
     495                 :          0 : IfStmt::~IfStmt()
     496                 :            :         {
     497                 :          0 :         Unref(s1);
     498                 :          0 :         Unref(s2);
     499 [ #  # ][ #  # ]:          0 :         }
                 [ #  # ]
     500                 :            : 
     501                 :     175768 : Val* IfStmt::DoExec(Frame* f, Val* v, stmt_flow_type& flow) const
     502                 :            :         {
     503                 :            :         // Treat 0 as false, but don't require 1 for true.
     504         [ +  + ]:     175768 :         Stmt* do_stmt = v->IsZero() ? s2 : s1;
     505                 :            : 
     506                 :     175768 :         f->SetNextStmt(do_stmt);
     507                 :            : 
     508                 :     175768 :         if ( ! pre_execute_stmt(do_stmt, f) )
     509                 :            :                 { // ### Abort or something
     510                 :            :                 }
     511                 :            : 
     512                 :     175768 :         Val* result = do_stmt->Exec(f, flow);
     513                 :            : 
     514                 :     175768 :         if ( ! post_execute_stmt(do_stmt, f, result, &flow) )
     515                 :            :                 { // ### Abort or something
     516                 :            :                 }
     517                 :            : 
     518                 :     175768 :         return result;
     519                 :            :         }
     520                 :            : 
     521                 :          0 : Stmt* IfStmt::DoSimplify()
     522                 :            :         {
     523                 :          0 :         s1 = simplify_stmt(s1);
     524                 :          0 :         s2 = simplify_stmt(s2);
     525                 :            : 
     526         [ #  # ]:          0 :         if ( e->IsConst() )
     527                 :            :                 {
     528         [ #  # ]:          0 :                 if ( ! optimize )
     529                 :          0 :                         Warn("constant in conditional");
     530                 :            : 
     531         [ #  # ]:          0 :                 return e->IsZero() ? s2->Ref() : s1->Ref();
     532                 :            :                 }
     533                 :            : 
     534         [ #  # ]:          0 :         if ( e->Tag() == EXPR_NOT )
     535                 :            :                 {
     536                 :          0 :                 Stmt* t = s1;
     537                 :          0 :                 s1 = s2;
     538                 :          0 :                 s2 = t;
     539                 :            : 
     540                 :          0 :                 e = new NotExpr(e);
     541                 :            : 
     542                 :          0 :                 return Simplify();
     543                 :            :                 }
     544                 :            : 
     545                 :          0 :         return this;
     546                 :            :         }
     547                 :            : 
     548                 :          0 : int IfStmt::IsPure() const
     549                 :            :         {
     550 [ #  # ][ #  # ]:          0 :         return e->IsPure() && s1->IsPure() && s2->IsPure();
                 [ #  # ]
     551                 :            :         }
     552                 :            : 
     553                 :          0 : void IfStmt::Describe(ODesc* d) const
     554                 :            :         {
     555                 :          0 :         ExprStmt::Describe(d);
     556                 :            : 
     557                 :          0 :         d->PushIndent();
     558                 :          0 :         s1->AccessStats(d);
     559                 :          0 :         s1->Describe(d);
     560                 :          0 :         d->PopIndent();
     561                 :            : 
     562         [ #  # ]:          0 :         if ( d->IsReadable() )
     563                 :            :                 {
     564         [ #  # ]:          0 :                 if ( s2->Tag() != STMT_NULL )
     565                 :            :                         {
     566                 :          0 :                         d->Add("else");
     567                 :          0 :                         d->PushIndent();
     568                 :          0 :                         s2->AccessStats(d);
     569                 :          0 :                         s2->Describe(d);
     570                 :          0 :                         d->PopIndent();
     571                 :            :                         }
     572                 :            :                 }
     573                 :            :         else
     574                 :          0 :                 s2->Describe(d);
     575                 :          0 :         }
     576                 :            : 
     577                 :          0 : TraversalCode IfStmt::Traverse(TraversalCallback* cb) const
     578                 :            :         {
     579                 :          0 :         TraversalCode tc = cb->PreStmt(this);
     580   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
     581                 :            : 
     582                 :            :         // Condition is stored in base class's "e" field.
     583                 :          0 :         tc = e->Traverse(cb);
     584   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
     585                 :            : 
     586                 :          0 :         tc = TrueBranch()->Traverse(cb);
     587   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
     588                 :            : 
     589                 :          0 :         tc = FalseBranch()->Traverse(cb);
     590   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
     591                 :            : 
     592                 :          0 :         tc = cb->PostStmt(this);
     593 [ #  # ][ #  # ]:          0 :         HANDLE_TC_STMT_POST(tc);
     594                 :            :         }
     595                 :            : 
     596                 :          3 : IMPLEMENT_SERIAL(IfStmt, SER_IF_STMT);
     597                 :            : 
     598                 :          0 : bool IfStmt::DoSerialize(SerialInfo* info) const
     599                 :            :         {
     600 [ #  # ][ #  # ]:          0 :         DO_SERIALIZE(SER_IF_STMT, ExprStmt);
     601 [ #  # ][ #  # ]:          0 :         return s1->Serialize(info) && s2->Serialize(info);
     602                 :            :         }
     603                 :            : 
     604                 :          0 : bool IfStmt::DoUnserialize(UnserialInfo* info)
     605                 :            :         {
     606         [ #  # ]:          0 :         DO_UNSERIALIZE(ExprStmt);
     607                 :          0 :         s1 = Stmt::Unserialize(info);
     608         [ #  # ]:          0 :         if ( ! s1 )
     609                 :          0 :                 return false;
     610                 :            : 
     611                 :          0 :         s2 = Stmt::Unserialize(info);
     612                 :          0 :         return s2 != 0;
     613                 :            :         }
     614                 :            : 
     615                 :          0 : Case::~Case()
     616                 :            :         {
     617                 :          0 :         Unref(cases);
     618                 :          0 :         Unref(s);
     619 [ #  # ][ #  # ]:          0 :         }
                 [ #  # ]
     620                 :            : 
     621                 :          0 : void Case::Describe(ODesc* d) const
     622                 :            :         {
     623                 :          0 :         const expr_list& e = Cases()->Exprs();
     624                 :            : 
     625         [ #  # ]:          0 :         if ( ! d->IsBinary() )
     626                 :          0 :                 d->Add("case");
     627                 :            : 
     628                 :          0 :         d->AddCount(e.length());
     629                 :            : 
     630         [ #  # ]:          0 :         loop_over_list(e, j)
     631                 :            :                 {
     632 [ #  # ][ #  # ]:          0 :                 if ( j > 0 && ! d->IsReadable() )
                 [ #  # ]
     633                 :          0 :                         d->Add(",");
     634                 :            : 
     635                 :          0 :                 d->SP();
     636                 :          0 :                 e[j]->Describe(d);
     637                 :            :                 }
     638                 :            : 
     639         [ #  # ]:          0 :         if ( d->IsReadable() )
     640                 :          0 :                 d->Add(":");
     641                 :            : 
     642                 :          0 :         d->PushIndent();
     643                 :          0 :         Body()->AccessStats(d);
     644                 :          0 :         Body()->Describe(d);
     645                 :          0 :         d->PopIndent();
     646                 :          0 :         }
     647                 :            : 
     648                 :          0 : TraversalCode Case::Traverse(TraversalCallback* cb) const
     649                 :            :         {
     650                 :          0 :         TraversalCode tc = cases->Traverse(cb);
     651   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
     652                 :            : 
     653                 :          0 :         tc = s->Traverse(cb);
     654   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
     655                 :            : 
     656                 :          0 :         return TC_CONTINUE;
     657                 :            :         }
     658                 :            : 
     659                 :          0 : bool Case::Serialize(SerialInfo* info) const
     660                 :            :         {
     661                 :          0 :         return SerialObj::Serialize(info);
     662                 :            :         }
     663                 :            : 
     664                 :          0 : Case* Case::Unserialize(UnserialInfo* info)
     665                 :            :         {
     666                 :          0 :         return (Case*) SerialObj::Unserialize(info, SER_CASE);
     667                 :            :         }
     668                 :            : 
     669                 :          3 : IMPLEMENT_SERIAL(Case, SER_CASE);
     670                 :            : 
     671                 :          0 : bool Case::DoSerialize(SerialInfo* info) const
     672                 :            :         {
     673 [ #  # ][ #  # ]:          0 :         DO_SERIALIZE(SER_CASE, BroObj);
     674 [ #  # ][ #  # ]:          0 :         return cases->Serialize(info) && this->s->Serialize(info);
     675                 :            :         }
     676                 :            : 
     677                 :          0 : bool Case::DoUnserialize(UnserialInfo* info)
     678                 :            :         {
     679         [ #  # ]:          0 :         DO_UNSERIALIZE(BroObj);
     680                 :            : 
     681                 :          0 :         cases = (ListExpr*) Expr::Unserialize(info, EXPR_LIST);
     682         [ #  # ]:          0 :         if ( ! cases )
     683                 :          0 :                 return false;
     684                 :            : 
     685                 :          0 :         this->s = Stmt::Unserialize(info);
     686                 :          0 :         return this->s != 0;
     687                 :            :         }
     688                 :            : 
     689                 :          0 : SwitchStmt::SwitchStmt(Expr* index, case_list* arg_cases) :
     690                 :          0 :         ExprStmt(STMT_SWITCH, index)
     691                 :            :         {
     692                 :          0 :         cases = arg_cases;
     693                 :            : 
     694                 :            :         //### need to loop over cases and make sure their type matches
     695                 :            :         //### the index, and they're constant and not redundant
     696                 :          0 :         }
     697                 :            : 
     698                 :          0 : SwitchStmt::~SwitchStmt()
     699                 :            :         {
     700 [ #  # ][ #  # ]:          0 :         loop_over_list(*cases, i)
                 [ #  # ]
     701                 :          0 :                 Unref((*cases)[i]);
     702                 :            : 
     703 [ #  # ][ #  # ]:          0 :         delete cases;
                 [ #  # ]
     704 [ #  # ][ #  # ]:          0 :         }
                 [ #  # ]
     705                 :            : 
     706                 :          0 : Val* SwitchStmt::DoExec(Frame* /* f */, Val* /* v */, stmt_flow_type& /* flow */) const
     707                 :            :         {
     708                 :          0 :         printf("switch statement not implemented\n");
     709                 :          0 :         return 0;
     710                 :            :         }
     711                 :            : 
     712                 :          0 : Stmt* SwitchStmt::DoSimplify()
     713                 :            :         {
     714         [ #  # ]:          0 :         loop_over_list(*cases, i)
     715                 :            :                 {
     716                 :          0 :                 Case* c = (*cases)[i];
     717                 :          0 :                 ListExpr* new_cases = simplify_expr_list(c->Cases(), SIMPLIFY_GENERAL);
     718                 :          0 :                 Stmt* new_body = simplify_stmt(c->Body());
     719                 :            : 
     720   [ #  #  #  # ]:          0 :                 if ( new_cases != c->Cases() || new_body != c->Body() )
                 [ #  # ]
     721                 :            :                         {
     722                 :          0 :                         cases->replace(i, new Case(new_cases, new_body));
     723                 :          0 :                         Unref(c);
     724                 :            :                         }
     725                 :            :                 }
     726                 :            : 
     727         [ #  # ]:          0 :         if ( e->IsConst() )
     728                 :            :                 { // ### go through cases and pull out the one it matches
     729         [ #  # ]:          0 :                 if ( ! optimize )
     730                 :          0 :                         Warn("constant in switch");
     731                 :            :                 }
     732                 :            : 
     733                 :          0 :         return this;
     734                 :            :         }
     735                 :            : 
     736                 :          0 : int SwitchStmt::IsPure() const
     737                 :            :         {
     738         [ #  # ]:          0 :         if ( ! e->IsPure() )
     739                 :          0 :                 return 0;
     740                 :            : 
     741         [ #  # ]:          0 :         loop_over_list(*cases, i)
     742                 :            :                 {
     743                 :          0 :                 Case* c = (*cases)[i];
     744   [ #  #  #  # ]:          0 :                 if ( ! c->Cases()->IsPure() || ! c->Body()->IsPure() )
                 [ #  # ]
     745                 :          0 :                         return 0;
     746                 :            :                 }
     747                 :            : 
     748                 :          0 :         return 1;
     749                 :            :         }
     750                 :            : 
     751                 :          0 : void SwitchStmt::Describe(ODesc* d) const
     752                 :            :         {
     753                 :          0 :         ExprStmt::Describe(d);
     754                 :            : 
     755         [ #  # ]:          0 :         if ( ! d->IsBinary() )
     756                 :          0 :                 d->Add("{");
     757                 :            : 
     758                 :          0 :         d->PushIndent();
     759                 :          0 :         d->AddCount(cases->length());
     760         [ #  # ]:          0 :         loop_over_list(*cases, i)
     761                 :          0 :                 (*cases)[i]->Describe(d);
     762                 :          0 :         d->PopIndent();
     763                 :            : 
     764         [ #  # ]:          0 :         if ( ! d->IsBinary() )
     765                 :          0 :                 d->Add("}");
     766                 :          0 :         d->NL();
     767                 :          0 :         }
     768                 :            : 
     769                 :          0 : TraversalCode SwitchStmt::Traverse(TraversalCallback* cb) const
     770                 :            :         {
     771                 :          0 :         TraversalCode tc = cb->PreStmt(this);
     772   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
     773                 :            : 
     774                 :            :         // Index is stored in base class's "e" field.
     775                 :          0 :         tc = e->Traverse(cb);
     776   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
     777                 :            : 
     778         [ #  # ]:          0 :         loop_over_list(*cases, i)
     779                 :            :                 {
     780                 :          0 :                 tc = (*cases)[i]->Traverse(cb);
     781   [ #  #  #  # ]:          0 :                 HANDLE_TC_STMT_PRE(tc);
     782                 :            :                 }
     783                 :            : 
     784                 :          0 :         tc = cb->PostStmt(this);
     785 [ #  # ][ #  # ]:          0 :         HANDLE_TC_STMT_POST(tc);
     786                 :            :         }
     787                 :            : 
     788                 :          3 : IMPLEMENT_SERIAL(SwitchStmt, SER_SWITCH_STMT);
     789                 :            : 
     790                 :          0 : bool SwitchStmt::DoSerialize(SerialInfo* info) const
     791                 :            :         {
     792 [ #  # ][ #  # ]:          0 :         DO_SERIALIZE(SER_SWITCH_STMT, ExprStmt);
     793                 :            : 
     794         [ #  # ]:          0 :         if ( ! SERIALIZE(cases->length()) )
     795                 :          0 :                 return false;
     796                 :            : 
     797         [ #  # ]:          0 :         loop_over_list((*cases), i)
     798         [ #  # ]:          0 :                 if ( ! (*cases)[i]->Serialize(info) )
     799                 :          0 :                         return false;
     800                 :            : 
     801                 :          0 :         return true;
     802                 :            :         }
     803                 :            : 
     804                 :          0 : bool SwitchStmt::DoUnserialize(UnserialInfo* info)
     805                 :            :         {
     806         [ #  # ]:          0 :         DO_UNSERIALIZE(ExprStmt);
     807                 :            : 
     808                 :            :         int len;
     809         [ #  # ]:          0 :         if ( ! UNSERIALIZE(&len) )
     810                 :          0 :                 return false;
     811                 :            : 
     812         [ #  # ]:          0 :         while ( len-- )
     813                 :            :                 {
     814                 :          0 :                 Case* c = Case::Unserialize(info);
     815         [ #  # ]:          0 :                 if ( ! c )
     816                 :          0 :                         return false;
     817                 :            : 
     818                 :          0 :                 cases->append(c);
     819                 :            :                 }
     820                 :            : 
     821                 :          0 :         return true;
     822                 :            :         }
     823                 :            : 
     824                 :        134 : AddStmt::AddStmt(Expr* arg_e) : ExprStmt(STMT_ADD, arg_e)
     825                 :            :         {
     826   [ -  +  #  # ]:        134 :         if ( ! e->CanAdd() )
     827                 :          0 :                 Error("illegal add statement");
     828                 :        134 :         }
     829                 :            : 
     830                 :          0 : int AddStmt::IsPure() const
     831                 :            :         {
     832                 :          0 :         return 0;
     833                 :            :         }
     834                 :            : 
     835                 :        279 : Val* AddStmt::Exec(Frame* f, stmt_flow_type& flow) const
     836                 :            :         {
     837                 :        279 :         RegisterAccess();
     838                 :        279 :         flow = FLOW_NEXT;
     839                 :        279 :         e->Add(f);
     840                 :        279 :         return 0;
     841                 :            :         }
     842                 :            : 
     843                 :            : 
     844                 :          0 : TraversalCode AddStmt::Traverse(TraversalCallback* cb) const
     845                 :            :         {
     846                 :          0 :         TraversalCode tc = cb->PreStmt(this);
     847   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
     848                 :            : 
     849                 :            :         // Argument is stored in base class's "e" field.
     850                 :          0 :         tc = e->Traverse(cb);
     851   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
     852                 :            : 
     853                 :          0 :         tc = cb->PostStmt(this);
     854 [ #  # ][ #  # ]:          0 :         HANDLE_TC_STMT_POST(tc);
     855                 :            :         }
     856                 :            : 
     857                 :          3 : IMPLEMENT_SERIAL(AddStmt, SER_ADD_STMT);
     858                 :            : 
     859                 :          0 : bool AddStmt::DoSerialize(SerialInfo* info) const
     860                 :            :         {
     861 [ #  # ][ #  # ]:          0 :         DO_SERIALIZE(SER_ADD_STMT, ExprStmt);
     862                 :          0 :         return true;
     863                 :            :         }
     864                 :            : 
     865                 :          0 : bool AddStmt::DoUnserialize(UnserialInfo* info)
     866                 :            :         {
     867         [ #  # ]:          0 :         DO_UNSERIALIZE(ExprStmt);
     868                 :          0 :         return true;
     869                 :            :         }
     870                 :            : 
     871                 :        141 : DelStmt::DelStmt(Expr* arg_e) : ExprStmt(STMT_DELETE, arg_e)
     872                 :            :         {
     873   [ -  +  #  # ]:        141 :         if ( ! e->CanDel() )
     874                 :          0 :                 Error("illegal delete statement");
     875                 :        141 :         }
     876                 :            : 
     877                 :          0 : int DelStmt::IsPure() const
     878                 :            :         {
     879                 :          0 :         return 0;
     880                 :            :         }
     881                 :            : 
     882                 :       8295 : Val* DelStmt::Exec(Frame* f, stmt_flow_type& flow) const
     883                 :            :         {
     884                 :       8295 :         RegisterAccess();
     885                 :       8295 :         flow = FLOW_NEXT;
     886                 :       8295 :         e->Delete(f);
     887                 :       8295 :         return 0;
     888                 :            :         }
     889                 :            : 
     890                 :          0 : TraversalCode DelStmt::Traverse(TraversalCallback* cb) const
     891                 :            :         {
     892                 :          0 :         TraversalCode tc = cb->PreStmt(this);
     893   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
     894                 :            : 
     895                 :            :         // Argument is stored in base class's "e" field.
     896                 :          0 :         tc = e->Traverse(cb);
     897   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
     898                 :            : 
     899                 :          0 :         tc = cb->PostStmt(this);
     900 [ #  # ][ #  # ]:          0 :         HANDLE_TC_STMT_POST(tc);
     901                 :            :         }
     902                 :            : 
     903                 :          3 : IMPLEMENT_SERIAL(DelStmt, SER_DEL_STMT);
     904                 :            : 
     905                 :          0 : bool DelStmt::DoSerialize(SerialInfo* info) const
     906                 :            :         {
     907 [ #  # ][ #  # ]:          0 :         DO_SERIALIZE(SER_DEL_STMT, ExprStmt);
     908                 :          0 :         return true;
     909                 :            :         }
     910                 :            : 
     911                 :          0 : bool DelStmt::DoUnserialize(UnserialInfo* info)
     912                 :            :         {
     913         [ #  # ]:          0 :         DO_UNSERIALIZE(ExprStmt);
     914                 :          0 :         return true;
     915                 :            :         }
     916                 :            : 
     917                 :         78 : EventStmt::EventStmt(EventExpr* arg_e) : ExprStmt(STMT_EVENT, arg_e)
     918                 :            :         {
     919                 :         78 :         event_expr = arg_e;
     920                 :         78 :         }
     921                 :            : 
     922                 :       3360 : Val* EventStmt::Exec(Frame* f, stmt_flow_type& flow) const
     923                 :            :         {
     924                 :       3360 :         RegisterAccess();
     925                 :       3360 :         val_list* args = eval_list(f, event_expr->Args());
     926                 :            : 
     927         [ +  - ]:       3360 :         if ( args )
     928                 :       3360 :                 mgr.QueueEvent(event_expr->Handler(), args);
     929                 :            : 
     930                 :       3360 :         flow = FLOW_NEXT;
     931                 :            : 
     932                 :       3360 :         return 0;
     933                 :            :         }
     934                 :            : 
     935                 :          0 : TraversalCode EventStmt::Traverse(TraversalCallback* cb) const
     936                 :            :         {
     937                 :          0 :         TraversalCode tc = cb->PreStmt(this);
     938   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
     939                 :            : 
     940                 :            :         // Event is stored in base class's "e" field.
     941                 :          0 :         tc = e->Traverse(cb);
     942   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
     943                 :            : 
     944                 :          0 :         tc = cb->PostStmt(this);
     945 [ #  # ][ #  # ]:          0 :         HANDLE_TC_STMT_POST(tc);
     946                 :            :         }
     947                 :            : 
     948                 :          3 : IMPLEMENT_SERIAL(EventStmt, SER_EVENT_STMT);
     949                 :            : 
     950                 :          0 : bool EventStmt::DoSerialize(SerialInfo* info) const
     951                 :            :         {
     952 [ #  # ][ #  # ]:          0 :         DO_SERIALIZE(SER_EVENT_STMT, ExprStmt);
     953                 :          0 :         return event_expr->Serialize(info);
     954                 :            :         }
     955                 :            : 
     956                 :          0 : bool EventStmt::DoUnserialize(UnserialInfo* info)
     957                 :            :         {
     958         [ #  # ]:          0 :         DO_UNSERIALIZE(ExprStmt);
     959                 :            : 
     960                 :          0 :         event_expr = (EventExpr*) Expr::Unserialize(info, EXPR_EVENT);
     961                 :          0 :         return event_expr != 0;
     962                 :            :         }
     963                 :            : 
     964                 :        123 : ForStmt::ForStmt(id_list* arg_loop_vars, Expr* loop_expr)
     965                 :        123 : : ExprStmt(STMT_FOR, loop_expr)
     966                 :            :         {
     967                 :        123 :         loop_vars = arg_loop_vars;
     968                 :        123 :         body = 0;
     969                 :            : 
     970   [ +  +  #  # ]:        123 :         if ( e->Type()->Tag() == TYPE_TABLE )
     971                 :            :                 {
     972                 :        115 :                 const type_list* indices = e->Type()->AsTableType()->IndexTypes();
     973   [ -  +  #  # ]:        115 :                 if ( indices->length() != loop_vars->length() )
     974                 :          0 :                         e->Error("wrong index size");
     975                 :            : 
     976 [ +  + ][ #  # ]:        231 :                 for ( int i = 0; i < indices->length(); i++ )
     977                 :            :                         {
     978                 :        116 :                         BroType* ind_type = (*indices)[i]->Ref();
     979                 :            : 
     980   [ +  +  #  # ]:        116 :                         if ( (*loop_vars)[i]->Type() )
     981                 :            :                                 {
     982 [ -  + ][ #  # ]:         16 :                                 if ( ! same_type((*loop_vars)[i]->Type(), ind_type) )
     983                 :         16 :                                         (*loop_vars)[i]->Type()->Error("type clash in iteration", ind_type);
     984                 :            :                                 }
     985                 :            : 
     986                 :            :                         else
     987                 :            :                                 {
     988                 :            :                                 delete add_local((*loop_vars)[i],
     989                 :            :                                                 ind_type->Ref(), INIT_NONE,
     990 [ +  - ][ #  # ]:        100 :                                                 0, 0, VAR_REGULAR);
     991                 :            :                                 }
     992                 :            :                         }
     993                 :            :                 }
     994                 :            : 
     995 [ +  + ][ #  # ]:          8 :         else if ( e->Type()->Tag() == TYPE_VECTOR )
     996                 :            :                 {
     997 [ -  + ][ #  # ]:          5 :                 if ( loop_vars->length() != 1 )
     998                 :            :                         {
     999                 :          0 :                         e->Error("iterating over a vector requires only a single index type");
    1000                 :          0 :                         return;
    1001                 :            :                         }
    1002                 :            : 
    1003                 :          5 :                 BroType* t = (*loop_vars)[0]->Type();
    1004   [ +  +  #  # ]:          5 :                 if ( ! t )
    1005                 :            :                         delete add_local((*loop_vars)[0], base_type(TYPE_INT),
    1006 [ +  - ][ #  # ]:          4 :                                                 INIT_NONE, 0, 0, VAR_REGULAR);
    1007                 :            : 
    1008 [ +  - ][ -  + ]:          1 :                 else if ( ! IsIntegral(t->Tag()) )
         [ #  # ][ -  + ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1009                 :            :                         {
    1010                 :          0 :                         e->Error("vector index in \"for\" loop must be integral");
    1011                 :          5 :                         return;
    1012                 :            :                         }
    1013                 :            :                 }
    1014                 :            : 
    1015 [ +  - ][ #  # ]:          3 :         else if ( e->Type()->Tag() == TYPE_STRING )
    1016                 :            :                 {
    1017 [ -  + ][ #  # ]:          3 :                 if ( loop_vars->length() != 1 )
    1018                 :            :                         {
    1019                 :          0 :                         e->Error("iterating over a string requires only a single index type");
    1020                 :          0 :                         return;
    1021                 :            :                         }
    1022                 :            : 
    1023                 :          3 :                 BroType* t = (*loop_vars)[0]->Type();
    1024   [ +  -  #  # ]:          3 :                 if ( ! t )
    1025                 :            :                         delete add_local((*loop_vars)[0],
    1026                 :            :                                         base_type(TYPE_STRING),
    1027 [ +  - ][ #  # ]:          3 :                                         INIT_NONE, 0, 0, VAR_REGULAR);
    1028                 :            : 
    1029 [ #  # ][ #  # ]:          0 :                 else if ( t->Tag() != TYPE_STRING )
    1030                 :            :                         {
    1031                 :          0 :                         e->Error("string index in \"for\" loop must be string");
    1032                 :          3 :                         return;
    1033                 :            :                         }
    1034                 :            :                 }
    1035                 :            :         else
    1036                 :        123 :                 e->Error("target to iterate over must be a table, set, vector, or string");
    1037                 :        123 :         }
    1038                 :            : 
    1039                 :          0 : ForStmt::~ForStmt()
    1040                 :            :         {
    1041 [ #  # ][ #  # ]:          0 :         loop_over_list(*loop_vars, i)
                 [ #  # ]
    1042                 :          0 :                 Unref((*loop_vars)[i]);
    1043 [ #  # ][ #  # ]:          0 :         delete loop_vars;
                 [ #  # ]
    1044                 :            : 
    1045                 :          0 :         Unref(body);
    1046 [ #  # ][ #  # ]:          0 :         }
                 [ #  # ]
    1047                 :            : 
    1048                 :      23757 : Val* ForStmt::DoExec(Frame* f, Val* v, stmt_flow_type& flow) const
    1049                 :            :         {
    1050                 :      23757 :         Val* ret = 0;
    1051                 :            : 
    1052         [ +  + ]:      23757 :         if ( v->Type()->Tag() == TYPE_TABLE )
    1053                 :            :                 {
    1054                 :        314 :                 TableVal* tv = v->AsTableVal();
    1055                 :        314 :                 const PDict(TableEntryVal)* loop_vals = tv->AsTable();
    1056                 :            : 
    1057                 :            :                 HashKey* k;
    1058                 :            :                 TableEntryVal* iter_val;
    1059                 :        314 :                 IterCookie* c = loop_vals->InitForIteration();
    1060         [ +  + ]:        346 :                 while ( (iter_val = loop_vals->NextEntry(k, c)) )
    1061                 :            :                         {
    1062                 :         32 :                         ListVal* ind_lv = tv->RecoverIndex(k);
    1063         [ +  - ]:         32 :                         delete k;
    1064                 :            : 
    1065         [ +  + ]:         64 :                         for ( int i = 0; i < ind_lv->Length(); i++ )
    1066                 :         32 :                                 f->SetElement((*loop_vars)[i]->Offset(), ind_lv->Index(i)->Ref());
    1067                 :         32 :                         Unref(ind_lv);
    1068                 :            : 
    1069                 :         32 :                         flow = FLOW_NEXT;
    1070                 :         32 :                         ret = body->Exec(f, flow);
    1071                 :            : 
    1072   [ +  -  -  + ]:         32 :                         if ( flow == FLOW_BREAK || flow == FLOW_RETURN )
    1073                 :            :                                 {
    1074                 :            :                                 // If we broke or returned from inside a for loop,
    1075                 :            :                                 // the cookie may still exist.
    1076                 :          0 :                                 loop_vals->StopIteration(c);
    1077                 :          0 :                                 break;
    1078                 :            :                                 }
    1079                 :            :                         }
    1080                 :            :                 }
    1081                 :            : 
    1082         [ +  + ]:      23443 :         else if ( v->Type()->Tag() == TYPE_VECTOR )
    1083                 :            :                 {
    1084                 :       1379 :                 VectorVal* vv = v->AsVectorVal();
    1085                 :            : 
    1086         [ +  + ]:      24822 :                 for ( int i = 0; i <= int(vv->Size()); ++i )
    1087                 :            :                         {
    1088                 :            :                         // Skip unassigned vector indices.
    1089         [ +  + ]:      23443 :                         if ( ! vv->Lookup(i) )
    1090                 :       1379 :                                 continue;
    1091                 :            : 
    1092                 :            :                         // Set the loop variable to the current index, and make
    1093                 :            :                         // another pass over the loop body.
    1094                 :            :                         f->SetElement((*loop_vars)[0]->Offset(),
    1095                 :      22064 :                                         new Val(i, TYPE_INT));
    1096                 :      22064 :                         flow = FLOW_NEXT;
    1097                 :      22064 :                         ret = body->Exec(f, flow);
    1098                 :            : 
    1099   [ +  -  -  + ]:      22064 :                         if ( flow == FLOW_BREAK || flow == FLOW_RETURN )
    1100                 :          0 :                                 break;
    1101                 :            :                         }
    1102                 :            :                 }
    1103         [ +  - ]:      22064 :         else if ( v->Type()->Tag() == TYPE_STRING )
    1104                 :            :                 {
    1105                 :      22064 :                 StringVal* sval = v->AsStringVal();
    1106                 :            : 
    1107         [ +  + ]:      44128 :                 for ( int i = 0; i < sval->Len(); ++i )
    1108                 :            :                         {
    1109                 :            :                         f->SetElement((*loop_vars)[0]->Offset(),
    1110                 :      22064 :                                         new StringVal(1, (const char*) sval->Bytes() + i));
    1111                 :      22064 :                         flow = FLOW_NEXT;
    1112                 :      22064 :                         ret = body->Exec(f, flow);
    1113                 :            : 
    1114   [ +  -  -  + ]:      22064 :                         if ( flow == FLOW_BREAK || flow == FLOW_RETURN )
    1115                 :          0 :                                 break;
    1116                 :            :                         }
    1117                 :            :                 }
    1118                 :            : 
    1119                 :            :         else
    1120                 :          0 :                 e->Error("Invalid type in for-loop execution");
    1121                 :            : 
    1122         [ -  + ]:      23757 :         if ( flow == FLOW_LOOP )
    1123                 :          0 :                 flow = FLOW_NEXT;       // last iteration exited with a "next"
    1124                 :            : 
    1125         [ -  + ]:      23757 :         if ( flow == FLOW_BREAK )
    1126                 :          0 :                 flow = FLOW_NEXT;       // we've now finished the "break"
    1127                 :            : 
    1128                 :      23757 :         return ret;
    1129                 :            :         }
    1130                 :            : 
    1131                 :          0 : Stmt* ForStmt::DoSimplify()
    1132                 :            :         {
    1133                 :          0 :         body = simplify_stmt(body);
    1134                 :            : 
    1135         [ #  # ]:          0 :         if ( e->IsConst() )
    1136                 :            :                 {
    1137                 :          0 :                 const PDict(TableEntryVal)* vt = e->ExprVal()->AsTable();
    1138                 :            : 
    1139         [ #  # ]:          0 :                 if ( vt->Length() == 0 )
    1140                 :          0 :                         return new NullStmt();
    1141                 :            :                 }
    1142                 :            : 
    1143                 :          0 :         return this;
    1144                 :            :         }
    1145                 :            : 
    1146                 :          0 : int ForStmt::IsPure() const
    1147                 :            :         {
    1148 [ #  # ][ #  # ]:          0 :         return e->IsPure() && body->IsPure();
    1149                 :            :         }
    1150                 :            : 
    1151                 :          0 : void ForStmt::Describe(ODesc* d) const
    1152                 :            :         {
    1153                 :          0 :         Stmt::Describe(d);
    1154                 :            : 
    1155         [ #  # ]:          0 :         if ( d->IsReadable() )
    1156                 :          0 :                 d->Add("(");
    1157                 :            : 
    1158         [ #  # ]:          0 :         if ( loop_vars->length() )
    1159                 :          0 :                 d->Add("[");
    1160                 :            : 
    1161         [ #  # ]:          0 :         loop_over_list(*loop_vars, i)
    1162                 :            :                 {
    1163                 :          0 :                 (*loop_vars)[i]->Describe(d);
    1164         [ #  # ]:          0 :                 if ( i > 0 )
    1165                 :          0 :                         d->Add(",");
    1166                 :            :                 }
    1167                 :            :         
    1168         [ #  # ]:          0 :         if ( loop_vars->length() )
    1169                 :          0 :                 d->Add("]");
    1170                 :            : 
    1171         [ #  # ]:          0 :         if ( d->IsReadable() )
    1172                 :          0 :                 d->Add(" in ");
    1173                 :            : 
    1174                 :          0 :         e->Describe(d);
    1175                 :            : 
    1176         [ #  # ]:          0 :         if ( d->IsReadable() )
    1177                 :          0 :                 d->Add(")");
    1178                 :            : 
    1179                 :          0 :         d->SP();
    1180                 :            : 
    1181                 :          0 :         d->PushIndent();
    1182                 :          0 :         body->AccessStats(d);
    1183                 :          0 :         body->Describe(d);
    1184                 :          0 :         d->PopIndent();
    1185                 :          0 :         }
    1186                 :            : 
    1187                 :          0 : TraversalCode ForStmt::Traverse(TraversalCallback* cb) const
    1188                 :            :         {
    1189                 :          0 :         TraversalCode tc = cb->PreStmt(this);
    1190   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
    1191                 :            : 
    1192         [ #  # ]:          0 :         loop_over_list(*loop_vars, i)
    1193                 :            :                 {
    1194                 :          0 :                 tc = (*loop_vars)[i]->Traverse(cb);
    1195   [ #  #  #  # ]:          0 :                 HANDLE_TC_STMT_PRE(tc);
    1196                 :            :                 }
    1197                 :            : 
    1198                 :          0 :         tc = LoopExpr()->Traverse(cb);
    1199   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
    1200                 :            : 
    1201                 :          0 :         tc = LoopBody()->Traverse(cb);
    1202   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
    1203                 :            : 
    1204                 :          0 :         tc = cb->PostStmt(this);
    1205 [ #  # ][ #  # ]:          0 :         HANDLE_TC_STMT_POST(tc);
    1206                 :            :         }
    1207                 :            : 
    1208                 :          3 : IMPLEMENT_SERIAL(ForStmt, SER_FOR_STMT);
    1209                 :            : 
    1210                 :          0 : bool ForStmt::DoSerialize(SerialInfo* info) const
    1211                 :            :         {
    1212 [ #  # ][ #  # ]:          0 :         DO_SERIALIZE(SER_FOR_STMT, ExprStmt);
    1213                 :            : 
    1214         [ #  # ]:          0 :         if ( ! SERIALIZE(loop_vars->length()) )
    1215                 :          0 :                 return false;
    1216                 :            : 
    1217         [ #  # ]:          0 :         loop_over_list((*loop_vars), i)
    1218                 :            :                 {
    1219         [ #  # ]:          0 :                 if ( ! (*loop_vars)[i]->Serialize(info) )
    1220                 :          0 :                         return false;
    1221                 :            :                 }
    1222                 :            : 
    1223                 :          0 :         return body->Serialize(info);
    1224                 :            :         }
    1225                 :            : 
    1226                 :          0 : bool ForStmt::DoUnserialize(UnserialInfo* info)
    1227                 :            :         {
    1228         [ #  # ]:          0 :         DO_UNSERIALIZE(ExprStmt);
    1229                 :            : 
    1230                 :            :         int len;
    1231         [ #  # ]:          0 :         if ( ! UNSERIALIZE(&len) )
    1232                 :          0 :                 return false;
    1233                 :            : 
    1234                 :          0 :         loop_vars = new id_list;
    1235                 :            : 
    1236         [ #  # ]:          0 :         while ( len-- )
    1237                 :            :                 {
    1238                 :          0 :                 ID* id = ID::Unserialize(info);
    1239         [ #  # ]:          0 :                 if ( ! id )
    1240                 :          0 :                         return false;
    1241                 :            : 
    1242                 :          0 :                 loop_vars->append(id);
    1243                 :            :                 }
    1244                 :            : 
    1245                 :          0 :         body = Stmt::Unserialize(info);
    1246                 :          0 :         return body != 0;
    1247                 :            :         }
    1248                 :            : 
    1249                 :          0 : Val* NextStmt::Exec(Frame* /* f */, stmt_flow_type& flow) const
    1250                 :            :         {
    1251                 :          0 :         RegisterAccess();
    1252                 :          0 :         flow = FLOW_LOOP;
    1253                 :          0 :         return 0;
    1254                 :            :         }
    1255                 :            : 
    1256                 :          0 : int NextStmt::IsPure() const
    1257                 :            :         {
    1258                 :          0 :         return 1;
    1259                 :            :         }
    1260                 :            : 
    1261                 :          0 : void NextStmt::Describe(ODesc* d) const
    1262                 :            :         {
    1263                 :          0 :         Stmt::Describe(d);
    1264                 :          0 :         Stmt::DescribeDone(d);
    1265                 :          0 :         }
    1266                 :            : 
    1267                 :          0 : TraversalCode NextStmt::Traverse(TraversalCallback* cb) const
    1268                 :            :         {
    1269                 :          0 :         TraversalCode tc = cb->PreStmt(this);
    1270   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
    1271                 :            : 
    1272                 :          0 :         tc = cb->PostStmt(this);
    1273 [ #  # ][ #  # ]:          0 :         HANDLE_TC_STMT_POST(tc);
    1274                 :            :         }
    1275                 :            : 
    1276                 :          3 : IMPLEMENT_SERIAL(NextStmt, SER_NEXT_STMT);
    1277                 :            : 
    1278                 :          0 : bool NextStmt::DoSerialize(SerialInfo* info) const
    1279                 :            :         {
    1280 [ #  # ][ #  # ]:          0 :         DO_SERIALIZE(SER_NEXT_STMT, Stmt);
    1281                 :          0 :         return true;
    1282                 :            :         }
    1283                 :            : 
    1284                 :          0 : bool NextStmt::DoUnserialize(UnserialInfo* info)
    1285                 :            :         {
    1286         [ #  # ]:          0 :         DO_UNSERIALIZE(Stmt);
    1287                 :          0 :         return true;
    1288                 :            :         }
    1289                 :            : 
    1290                 :          0 : Val* BreakStmt::Exec(Frame* /* f */, stmt_flow_type& flow) const
    1291                 :            :         {
    1292                 :          0 :         RegisterAccess();
    1293                 :          0 :         flow = FLOW_BREAK;
    1294                 :          0 :         return 0;
    1295                 :            :         }
    1296                 :            : 
    1297                 :          0 : int BreakStmt::IsPure() const
    1298                 :            :         {
    1299                 :          0 :         return 1;
    1300                 :            :         }
    1301                 :            : 
    1302                 :          0 : void BreakStmt::Describe(ODesc* d) const
    1303                 :            :         {
    1304                 :          0 :         Stmt::Describe(d);
    1305                 :          0 :         Stmt::DescribeDone(d);
    1306                 :          0 :         }
    1307                 :            : 
    1308                 :          0 : TraversalCode BreakStmt::Traverse(TraversalCallback* cb) const
    1309                 :            :         {
    1310                 :          0 :         TraversalCode tc = cb->PreStmt(this);
    1311   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
    1312                 :            : 
    1313                 :          0 :         tc = cb->PostStmt(this);
    1314 [ #  # ][ #  # ]:          0 :         HANDLE_TC_STMT_POST(tc);
    1315                 :            :         }
    1316                 :            : 
    1317                 :          3 : IMPLEMENT_SERIAL(BreakStmt, SER_BREAK_STMT);
    1318                 :            : 
    1319                 :          0 : bool BreakStmt::DoSerialize(SerialInfo* info) const
    1320                 :            :         {
    1321 [ #  # ][ #  # ]:          0 :         DO_SERIALIZE(SER_BREAK_STMT, Stmt);
    1322                 :          0 :         return true;
    1323                 :            :         }
    1324                 :            : 
    1325                 :          0 : bool BreakStmt::DoUnserialize(UnserialInfo* info)
    1326                 :            :         {
    1327         [ #  # ]:          0 :         DO_UNSERIALIZE(Stmt);
    1328                 :          0 :         return true;
    1329                 :            :         }
    1330                 :            : 
    1331                 :        816 : ReturnStmt::ReturnStmt(Expr* arg_e) : ExprStmt(STMT_RETURN, arg_e)
    1332                 :            :         {
    1333                 :        816 :         Scope* s = current_scope();
    1334                 :            : 
    1335   [ +  -  -  + ]:        816 :         if ( ! s || ! s->ScopeID() )
           [ -  +  #  # ]
         [ #  # ][ #  # ]
    1336                 :            :                 {
    1337                 :          0 :                 Error("return statement outside of function/event");
    1338                 :          0 :                 return;
    1339                 :            :                 }
    1340                 :            : 
    1341                 :        816 :         FuncType* ft = s->ScopeID()->Type()->AsFuncType();
    1342                 :        816 :         BroType* yt = ft->YieldType();
    1343                 :            : 
    1344   [ +  +  #  # ]:        816 :         if ( s->ScopeID()->DoInferReturnType() )
    1345                 :            :                 {
    1346 [ +  - ][ #  # ]:          5 :                 if ( e )
    1347                 :            :                         {
    1348                 :          5 :                         ft->SetYieldType(e->Type());
    1349                 :          5 :                         s->ScopeID()->SetInferReturnType(false);
    1350                 :            :                         }
    1351                 :            :                 }
    1352                 :            : 
    1353 [ +  + ][ +  + ]:        811 :         else if ( ! yt || yt->Tag() == TYPE_VOID )
         [ +  + ][ #  # ]
         [ #  # ][ #  # ]
    1354                 :            :                 {
    1355 [ -  + ][ #  # ]:        203 :                 if ( e )
    1356                 :        203 :                         Error("return statement cannot have an expression");
    1357                 :            :                 }
    1358                 :            : 
    1359 [ -  + ][ #  # ]:        608 :         else if ( ! e )
    1360                 :          0 :                 Error("return statement needs expression");
    1361                 :            : 
    1362                 :            :         else
    1363                 :        816 :                 (void) check_and_promote_expr(e, yt);
    1364                 :        816 :         }
    1365                 :            : 
    1366                 :      70733 : Val* ReturnStmt::Exec(Frame* f, stmt_flow_type& flow) const
    1367                 :            :         {
    1368                 :      70733 :         RegisterAccess();
    1369                 :      70733 :         flow = FLOW_RETURN;
    1370                 :            : 
    1371         [ +  + ]:      70733 :         if ( e )
    1372                 :      62147 :                 return e->Eval(f);
    1373                 :            :         else
    1374                 :      70733 :                 return 0;
    1375                 :            :         }
    1376                 :            : 
    1377                 :          0 : void ReturnStmt::Describe(ODesc* d) const
    1378                 :            :         {
    1379                 :          0 :         Stmt::Describe(d);
    1380         [ #  # ]:          0 :         if ( ! d->IsReadable() )
    1381                 :          0 :                 d->Add(e != 0);
    1382                 :            : 
    1383         [ #  # ]:          0 :         if ( e )
    1384                 :            :                 {
    1385         [ #  # ]:          0 :                 if ( ! d->IsBinary() )
    1386                 :          0 :                         d->Add("(");
    1387                 :          0 :                 e->Describe(d);
    1388         [ #  # ]:          0 :                 if ( ! d->IsBinary() )
    1389                 :          0 :                         d->Add(")");
    1390                 :            :                 }
    1391                 :            : 
    1392                 :          0 :         DescribeDone(d);
    1393                 :          0 :         }
    1394                 :            : 
    1395                 :          3 : IMPLEMENT_SERIAL(ReturnStmt, SER_RETURN_STMT);
    1396                 :            : 
    1397                 :          0 : bool ReturnStmt::DoSerialize(SerialInfo* info) const
    1398                 :            :         {
    1399 [ #  # ][ #  # ]:          0 :         DO_SERIALIZE(SER_RETURN_STMT, ExprStmt);
    1400                 :          0 :         return true;
    1401                 :            :         }
    1402                 :            : 
    1403                 :          0 : bool ReturnStmt::DoUnserialize(UnserialInfo* info)
    1404                 :            :         {
    1405         [ #  # ]:          0 :         DO_UNSERIALIZE(ExprStmt);
    1406                 :          0 :         return true;
    1407                 :            :         }
    1408                 :            : 
    1409                 :       2002 : StmtList::StmtList() : Stmt(STMT_LIST)
    1410                 :            :         {
    1411                 :       2002 :         }
    1412                 :            : 
    1413                 :          1 : StmtList::~StmtList()
    1414                 :            :         {
    1415 [ +  + ][ #  # ]:          2 :         loop_over_list(stmts, i)
                 [ #  # ]
    1416                 :          1 :                 Unref(stmts[i]);
    1417 [ +  - ][ #  # ]:          1 :         }
                 [ #  # ]
    1418                 :            : 
    1419                 :     154589 : Val* StmtList::Exec(Frame* f, stmt_flow_type& flow) const
    1420                 :            :         {
    1421                 :     154589 :         RegisterAccess();
    1422                 :     154589 :         flow = FLOW_NEXT;
    1423                 :            : 
    1424         [ +  + ]:     532811 :         loop_over_list(stmts, i)
    1425                 :            :                 {
    1426                 :     460442 :                 f->SetNextStmt(stmts[i]);
    1427                 :            : 
    1428                 :     460442 :                 if ( ! pre_execute_stmt(stmts[i], f) )
    1429                 :            :                         { // ### Abort or something
    1430                 :            :                         }
    1431                 :            : 
    1432                 :     460442 :                 Val* result = stmts[i]->Exec(f, flow);
    1433                 :            : 
    1434                 :     460442 :                 if ( ! post_execute_stmt(stmts[i], f, result, &flow) )
    1435                 :            :                         { // ### Abort or something
    1436                 :            :                         }
    1437                 :            : 
    1438   [ +  +  +  - ]:     460442 :                 if ( flow != FLOW_NEXT || result || f->HasDelayed() )
         [ -  + ][ +  + ]
    1439                 :      82220 :                         return result;
    1440                 :            :                 }
    1441                 :            : 
    1442                 :     154589 :         return 0;
    1443                 :            :         }
    1444                 :            : 
    1445                 :          0 : Stmt* StmtList::Simplify()
    1446                 :            :         {
    1447         [ #  # ]:          0 :         if ( stmts.length() == 0 )
    1448                 :          0 :                 return new NullStmt();
    1449                 :            : 
    1450         [ #  # ]:          0 :         if ( stmts.length() == 1 )
    1451                 :          0 :                 return stmts[0]->Ref();
    1452                 :            : 
    1453         [ #  # ]:          0 :         loop_over_list(stmts, i)
    1454                 :          0 :                 stmts.replace(i, simplify_stmt(stmts[i]));
    1455                 :            : 
    1456                 :          0 :         return this;
    1457                 :            :         }
    1458                 :            : 
    1459                 :          0 : int StmtList::IsPure() const
    1460                 :            :         {
    1461         [ #  # ]:          0 :         loop_over_list(stmts, i)
    1462         [ #  # ]:          0 :                 if ( ! stmts[i]->IsPure() )
    1463                 :          0 :                         return 0;
    1464                 :          0 :         return 1;
    1465                 :            :         }
    1466                 :            : 
    1467                 :          0 : void StmtList::Describe(ODesc* d) const
    1468                 :            :         {
    1469         [ #  # ]:          0 :         if ( ! d->IsReadable() )
    1470                 :            :                 {
    1471                 :          0 :                 AddTag(d);
    1472                 :          0 :                 d->AddCount(stmts.length());
    1473                 :            :                 }
    1474                 :            : 
    1475         [ #  # ]:          0 :         if ( stmts.length() == 0 )
    1476                 :          0 :                 DescribeDone(d);
    1477                 :            : 
    1478                 :            :         else
    1479                 :            :                 {
    1480         [ #  # ]:          0 :                 if ( ! d->IsBinary() )
    1481                 :            :                         {
    1482                 :          0 :                         d->Add("{ ");
    1483                 :          0 :                         d->NL();
    1484                 :            :                         }
    1485                 :            : 
    1486         [ #  # ]:          0 :                 loop_over_list(stmts, i)
    1487                 :            :                         {
    1488                 :          0 :                         stmts[i]->Describe(d);
    1489                 :          0 :                         d->NL();
    1490                 :            :                         }
    1491                 :            : 
    1492         [ #  # ]:          0 :                 if ( ! d->IsBinary() )
    1493                 :          0 :                         d->Add("}");
    1494                 :            :                 }
    1495                 :          0 :         }
    1496                 :            : 
    1497                 :          0 : TraversalCode StmtList::Traverse(TraversalCallback* cb) const
    1498                 :            :         {
    1499                 :          0 :         TraversalCode tc = cb->PreStmt(this);
    1500   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
    1501                 :            : 
    1502         [ #  # ]:          0 :         loop_over_list(stmts, i)
    1503                 :            :                 {
    1504                 :          0 :                 tc = stmts[i]->Traverse(cb);
    1505   [ #  #  #  # ]:          0 :                 HANDLE_TC_STMT_PRE(tc);
    1506                 :            :                 }
    1507                 :            : 
    1508                 :          0 :         tc = cb->PostStmt(this);
    1509 [ #  # ][ #  # ]:          0 :         HANDLE_TC_STMT_POST(tc);
    1510                 :            :         }
    1511                 :            : 
    1512                 :          3 : IMPLEMENT_SERIAL(StmtList, SER_STMT_LIST);
    1513                 :            : 
    1514                 :          0 : bool StmtList::DoSerialize(SerialInfo* info) const
    1515                 :            :         {
    1516 [ #  # ][ #  # ]:          0 :         DO_SERIALIZE(SER_STMT_LIST, Stmt);
    1517                 :            : 
    1518         [ #  # ]:          0 :         if ( ! SERIALIZE(stmts.length()) )
    1519                 :          0 :                 return false;
    1520                 :            : 
    1521         [ #  # ]:          0 :         loop_over_list(stmts, i)
    1522         [ #  # ]:          0 :                 if ( ! stmts[i]->Serialize(info) )
    1523                 :          0 :                         return false;
    1524                 :            : 
    1525                 :          0 :         return true;
    1526                 :            :         }
    1527                 :            : 
    1528                 :          0 : bool StmtList::DoUnserialize(UnserialInfo* info)
    1529                 :            :         {
    1530         [ #  # ]:          0 :         DO_UNSERIALIZE(Stmt);
    1531                 :            : 
    1532                 :            :         int len;
    1533         [ #  # ]:          0 :         if ( ! UNSERIALIZE(&len) )
    1534                 :          0 :                 return false;
    1535                 :            : 
    1536         [ #  # ]:          0 :         while ( len-- )
    1537                 :            :                 {
    1538                 :          0 :                 Stmt* stmt = Stmt::Unserialize(info);
    1539         [ #  # ]:          0 :                 if ( ! stmt )
    1540                 :          0 :                         return false;
    1541                 :            : 
    1542                 :          0 :                 stmts.append(stmt);
    1543                 :            :                 }
    1544                 :            : 
    1545                 :          0 :         return true;
    1546                 :            :         }
    1547                 :            : 
    1548                 :            : 
    1549                 :          0 : Val* EventBodyList::Exec(Frame* f, stmt_flow_type& flow) const
    1550                 :            :         {
    1551                 :          0 :         RegisterAccess();
    1552                 :          0 :         flow = FLOW_NEXT;
    1553                 :            : 
    1554         [ #  # ]:          0 :         loop_over_list(stmts, i)
    1555                 :            :                 {
    1556                 :          0 :                 f->SetNextStmt(stmts[i]);
    1557                 :            : 
    1558                 :            :                 // Ignore the return value, since there shouldn't be
    1559                 :            :                 // any; and ignore the flow, since we still execute
    1560                 :            :                 // all of the event bodies even if one of them does
    1561                 :            :                 // a FLOW_RETURN.
    1562                 :          0 :                 if ( ! pre_execute_stmt(stmts[i], f) )
    1563                 :            :                         { // ### Abort or something
    1564                 :            :                         }
    1565                 :            : 
    1566                 :          0 :                 Val* result = stmts[i]->Exec(f, flow);
    1567                 :            : 
    1568                 :          0 :                 if ( ! post_execute_stmt(stmts[i], f, result, &flow) )
    1569                 :            :                         { // ### Abort or something
    1570                 :            :                         }
    1571                 :            :                 }
    1572                 :            : 
    1573                 :            :         // Simulate a return so the hooks operate properly.
    1574                 :          0 :         stmt_flow_type ft = FLOW_RETURN;
    1575                 :          0 :         (void) post_execute_stmt(f->GetNextStmt(), f, 0, &ft);
    1576                 :            : 
    1577                 :          0 :         return 0;
    1578                 :            :         }
    1579                 :            : 
    1580                 :          0 : Stmt* EventBodyList::Simplify()
    1581                 :            :         {
    1582         [ #  # ]:          0 :         if ( stmts.length() <= 1 )
    1583                 :            :                 // Don't simplify these, we don't want to lose our
    1584                 :            :                 // "execute even across returns" property.
    1585                 :          0 :                 return this;
    1586                 :            : 
    1587                 :            :         else
    1588                 :          0 :                 return StmtList::Simplify();
    1589                 :            :         }
    1590                 :            : 
    1591                 :          0 : void EventBodyList::Describe(ODesc* d) const
    1592                 :            :         {
    1593 [ #  # ][ #  # ]:          0 :         if ( d->IsReadable() && stmts.length() > 0 )
                 [ #  # ]
    1594                 :            :                 {
    1595         [ #  # ]:          0 :                 loop_over_list(stmts, i)
    1596                 :            :                         {
    1597         [ #  # ]:          0 :                         if ( ! d->IsBinary() )
    1598                 :            :                                 {
    1599                 :          0 :                                 d->Add("{");
    1600                 :          0 :                                 d->PushIndent();
    1601                 :          0 :                                 stmts[i]->AccessStats(d);
    1602                 :            :                                 }
    1603                 :            : 
    1604                 :          0 :                         stmts[i]->Describe(d);
    1605                 :            : 
    1606         [ #  # ]:          0 :                         if ( ! d->IsBinary() )
    1607                 :            :                                 {
    1608                 :          0 :                                 d->Add("}");
    1609                 :          0 :                                 d->PopIndent();
    1610                 :            :                                 }
    1611                 :            :                         }
    1612                 :            :                 }
    1613                 :            : 
    1614                 :            :         else
    1615                 :          0 :                 StmtList::Describe(d);
    1616                 :          0 :         }
    1617                 :            : 
    1618                 :          3 : IMPLEMENT_SERIAL(EventBodyList, SER_EVENT_BODY_LIST);
    1619                 :            : 
    1620                 :          0 : bool EventBodyList::DoSerialize(SerialInfo* info) const
    1621                 :            :         {
    1622 [ #  # ][ #  # ]:          0 :         DO_SERIALIZE(SER_EVENT_BODY_LIST, StmtList);
    1623                 :          0 :         return SERIALIZE(topmost);
    1624                 :            :         }
    1625                 :            : 
    1626                 :          0 : bool EventBodyList::DoUnserialize(UnserialInfo* info)
    1627                 :            :         {
    1628         [ #  # ]:          0 :         DO_UNSERIALIZE(StmtList);
    1629                 :          0 :         return UNSERIALIZE(&topmost);
    1630                 :            :         }
    1631                 :            : 
    1632                 :          0 : InitStmt::~InitStmt()
    1633                 :            :         {
    1634 [ #  # ][ #  # ]:          0 :         loop_over_list(*inits, i)
                 [ #  # ]
    1635                 :          0 :                 Unref((*inits)[i]);
    1636                 :            : 
    1637 [ #  # ][ #  # ]:          0 :         delete inits;
                 [ #  # ]
    1638 [ #  # ][ #  # ]:          0 :         }
                 [ #  # ]
    1639                 :            : 
    1640                 :       5771 : Val* InitStmt::Exec(Frame* f, stmt_flow_type& flow) const
    1641                 :            :         {
    1642                 :       5771 :         RegisterAccess();
    1643                 :       5771 :         flow = FLOW_NEXT;
    1644                 :            : 
    1645         [ +  + ]:      11842 :         loop_over_list(*inits, i)
    1646                 :            :                 {
    1647                 :       6071 :                 ID* aggr = (*inits)[i];
    1648                 :       6071 :                 BroType* t = aggr->Type();
    1649                 :            : 
    1650                 :            :                 Val* v;
    1651         [ +  + ]:       6071 :                 if ( t->Tag() == TYPE_RECORD )
    1652                 :       3905 :                         v = new RecordVal(t->AsRecordType());
    1653         [ -  + ]:       2166 :                 else if ( aggr->Type()->Tag() == TYPE_VECTOR )
    1654                 :          0 :                         v = new VectorVal(t->AsVectorType());
    1655                 :            :                 else
    1656                 :       2166 :                         v = new TableVal(t->AsTableType(), aggr->Attrs());
    1657                 :            : 
    1658                 :       6071 :                 f->SetElement(aggr->Offset(), v);
    1659                 :            :                 }
    1660                 :            : 
    1661                 :       5771 :         return 0;
    1662                 :            :         }
    1663                 :            : 
    1664                 :          0 : void InitStmt::Describe(ODesc* d) const
    1665                 :            :         {
    1666                 :          0 :         AddTag(d);
    1667                 :            : 
    1668         [ #  # ]:          0 :         if ( ! d->IsReadable() )
    1669                 :          0 :                 d->AddCount(inits->length());
    1670                 :            : 
    1671         [ #  # ]:          0 :         loop_over_list(*inits, i)
    1672                 :            :                 {
    1673 [ #  # ][ #  # ]:          0 :                 if ( ! d->IsBinary() && i > 0 )
                 [ #  # ]
    1674                 :          0 :                         d->AddSP(",");
    1675                 :            : 
    1676                 :          0 :                 (*inits)[i]->Describe(d);
    1677                 :            :                 }
    1678                 :            : 
    1679                 :          0 :         DescribeDone(d);
    1680                 :          0 :         }
    1681                 :            : 
    1682                 :          0 : TraversalCode InitStmt::Traverse(TraversalCallback* cb) const
    1683                 :            :         {
    1684                 :          0 :         TraversalCode tc = cb->PreStmt(this);
    1685   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
    1686                 :            : 
    1687         [ #  # ]:          0 :         loop_over_list(*inits, i)
    1688                 :            :                 {
    1689                 :          0 :                 tc = (*inits)[i]->Traverse(cb);
    1690   [ #  #  #  # ]:          0 :                 HANDLE_TC_STMT_PRE(tc);
    1691                 :            :                 }
    1692                 :            : 
    1693                 :          0 :         tc = cb->PostStmt(this);
    1694 [ #  # ][ #  # ]:          0 :         HANDLE_TC_STMT_POST(tc);
    1695                 :            :         }
    1696                 :            : 
    1697                 :          3 : IMPLEMENT_SERIAL(InitStmt, SER_INIT_STMT);
    1698                 :            : 
    1699                 :          0 : bool InitStmt::DoSerialize(SerialInfo* info) const
    1700                 :            :         {
    1701 [ #  # ][ #  # ]:          0 :         DO_SERIALIZE(SER_INIT_STMT, Stmt);
    1702                 :            : 
    1703         [ #  # ]:          0 :         if ( ! SERIALIZE(inits->length()) )
    1704                 :          0 :                 return false;
    1705                 :            : 
    1706         [ #  # ]:          0 :         loop_over_list((*inits), i)
    1707                 :            :                 {
    1708         [ #  # ]:          0 :                 if ( ! (*inits)[i]->Serialize(info) )
    1709                 :          0 :                         return false;
    1710                 :            :                 }
    1711                 :            : 
    1712                 :          0 :         return true;
    1713                 :            :         }
    1714                 :            : 
    1715                 :          0 : bool InitStmt::DoUnserialize(UnserialInfo* info)
    1716                 :            :         {
    1717         [ #  # ]:          0 :         DO_UNSERIALIZE(Stmt);
    1718                 :            : 
    1719                 :            :         int len;
    1720         [ #  # ]:          0 :         if ( ! UNSERIALIZE(&len) )
    1721                 :          0 :                 return false;
    1722                 :            : 
    1723                 :          0 :         inits = new id_list;
    1724                 :            : 
    1725         [ #  # ]:          0 :         while ( len-- )
    1726                 :            :                 {
    1727                 :          0 :                 ID* id = ID::Unserialize(info);
    1728         [ #  # ]:          0 :                 if ( ! id )
    1729                 :          0 :                         return false;
    1730                 :          0 :                 inits->append(id);
    1731                 :            :                 }
    1732                 :          0 :         return true;
    1733                 :            :         }
    1734                 :            : 
    1735                 :            : 
    1736                 :      84462 : Val* NullStmt::Exec(Frame* /* f */, stmt_flow_type& flow) const
    1737                 :            :         {
    1738                 :      84462 :         RegisterAccess();
    1739                 :      84462 :         flow = FLOW_NEXT;
    1740                 :      84462 :         return 0;
    1741                 :            :         }
    1742                 :            : 
    1743                 :          0 : int NullStmt::IsPure() const
    1744                 :            :         {
    1745                 :          0 :         return 1;
    1746                 :            :         }
    1747                 :            : 
    1748                 :          0 : void NullStmt::Describe(ODesc* d) const
    1749                 :            :         {
    1750         [ #  # ]:          0 :         if ( d->IsReadable() )
    1751                 :          0 :                 DescribeDone(d);
    1752                 :            :         else
    1753                 :          0 :                 AddTag(d);
    1754                 :          0 :         }
    1755                 :            : 
    1756                 :          0 : TraversalCode NullStmt::Traverse(TraversalCallback* cb) const
    1757                 :            :         {
    1758                 :          0 :         TraversalCode tc = cb->PreStmt(this);
    1759   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
    1760                 :            : 
    1761                 :          0 :         tc = cb->PostStmt(this);
    1762 [ #  # ][ #  # ]:          0 :         HANDLE_TC_STMT_POST(tc);
    1763                 :            :         }
    1764                 :            : 
    1765                 :          3 : IMPLEMENT_SERIAL(NullStmt, SER_NULL_STMT);
    1766                 :            : 
    1767                 :          0 : bool NullStmt::DoSerialize(SerialInfo* info) const
    1768                 :            :         {
    1769 [ #  # ][ #  # ]:          0 :         DO_SERIALIZE(SER_NULL_STMT, Stmt);
    1770                 :          0 :         return true;
    1771                 :            :         }
    1772                 :            : 
    1773                 :          0 : bool NullStmt::DoUnserialize(UnserialInfo* info)
    1774                 :            :         {
    1775         [ #  # ]:          0 :         DO_UNSERIALIZE(Stmt);
    1776                 :          0 :         return true;
    1777                 :            :         }
    1778                 :            : 
    1779                 :            : WhenStmt::WhenStmt(Expr* arg_cond, Stmt* arg_s1, Stmt* arg_s2,
    1780                 :          2 :                         Expr* arg_timeout, bool arg_is_return)
    1781                 :          2 : : Stmt(STMT_WHEN)
    1782                 :            :         {
    1783   [ -  +  #  # ]:          2 :         assert(arg_cond);
    1784 [ -  + ][ #  # ]:          2 :         assert(arg_s1);
    1785                 :            : 
    1786                 :          2 :         cond = arg_cond;
    1787                 :          2 :         s1 = arg_s1;
    1788                 :          2 :         s2 = arg_s2;
    1789                 :          2 :         timeout = arg_timeout;
    1790                 :          2 :         is_return = arg_is_return;
    1791                 :            : 
    1792 [ +  - ][ -  + ]:          2 :         if ( ! cond->IsError() && ! IsBool(cond->Type()->Tag()) )
         [ -  + ][ #  # ]
         [ #  # ][ #  # ]
    1793                 :          0 :                 cond->Error("conditional in test must be boolean");
    1794                 :            : 
    1795 [ +  - ][ #  # ]:          2 :         if ( timeout )
    1796                 :            :                 {
    1797 [ +  - ][ #  # ]:          2 :                 if ( timeout->IsError() )
    1798                 :          2 :                         return;
    1799                 :            : 
    1800                 :          2 :                 TypeTag bt = timeout->Type()->Tag();
    1801 [ +  -  -  +  # :          2 :                 if ( bt != TYPE_TIME && bt != TYPE_INTERVAL )
              # ][ #  # ]
    1802                 :          2 :                         cond->Error("when timeout requires a time or time interval");
    1803                 :            :                 }
    1804                 :          0 :         }
    1805                 :            : 
    1806                 :          0 : WhenStmt::~WhenStmt()
    1807                 :            :         {
    1808                 :          0 :         Unref(cond);
    1809                 :          0 :         Unref(s1);
    1810                 :          0 :         Unref(s2);
    1811 [ #  # ][ #  # ]:          0 :         }
                 [ #  # ]
    1812                 :            : 
    1813                 :          0 : Val* WhenStmt::Exec(Frame* f, stmt_flow_type& flow) const
    1814                 :            :         {
    1815                 :          0 :         RegisterAccess();
    1816                 :          0 :         flow = FLOW_NEXT;
    1817                 :            : 
    1818                 :          0 :         ::Ref(cond);
    1819                 :          0 :         ::Ref(s1);
    1820         [ #  # ]:          0 :         if ( s2 )
    1821                 :          0 :                 ::Ref(s2);
    1822         [ #  # ]:          0 :         if ( timeout )
    1823                 :          0 :                 ::Ref(timeout);
    1824                 :            : 
    1825                 :            :         // The new trigger object will take care of its own deletion.
    1826                 :          0 :         new Trigger(cond, s1, s2, timeout, f, is_return, location);
    1827                 :            : 
    1828                 :          0 :         return 0;
    1829                 :            :         }
    1830                 :            : 
    1831                 :          0 : Stmt* WhenStmt::Simplify()
    1832                 :            :         {
    1833                 :          0 :         cond = simplify_expr(cond, SIMPLIFY_GENERAL);
    1834                 :          0 :         s1 = simplify_stmt(s1);
    1835         [ #  # ]:          0 :         if ( s2 )
    1836                 :          0 :                 s2 = simplify_stmt(s2);
    1837                 :            : 
    1838         [ #  # ]:          0 :         if ( cond->IsPure() )
    1839                 :          0 :                 Warn("non-varying expression in when clause");
    1840                 :            : 
    1841                 :          0 :         return this;
    1842                 :            :         }
    1843                 :            : 
    1844                 :          0 : int WhenStmt::IsPure() const
    1845                 :            :         {
    1846 [ #  # ][ #  # ]:          0 :         return cond->IsPure() && s1->IsPure() && (! s2 || s2->IsPure());
         [ #  # ][ #  # ]
    1847                 :            :         }
    1848                 :            : 
    1849                 :          0 : void WhenStmt::Describe(ODesc* d) const
    1850                 :            :         {
    1851                 :          0 :         Stmt::Describe(d);
    1852                 :            : 
    1853         [ #  # ]:          0 :         if ( d->IsReadable() )
    1854                 :          0 :                 d->Add("(");
    1855                 :            : 
    1856                 :          0 :         cond->Describe(d);
    1857                 :            : 
    1858         [ #  # ]:          0 :         if ( d->IsReadable() )
    1859                 :          0 :                 d->Add(")");
    1860                 :            : 
    1861                 :          0 :         d->SP();
    1862                 :          0 :         d->PushIndent();
    1863                 :          0 :         s1->AccessStats(d);
    1864                 :          0 :         s1->Describe(d);
    1865                 :          0 :         d->PopIndent();
    1866                 :            : 
    1867         [ #  # ]:          0 :         if ( s2 )
    1868                 :            :                 {
    1869         [ #  # ]:          0 :                 if ( d->IsReadable() )
    1870                 :            :                         {
    1871                 :          0 :                         d->SP();
    1872                 :          0 :                         d->Add("timeout");
    1873                 :          0 :                         d->SP();
    1874                 :          0 :                         timeout->Describe(d);
    1875                 :          0 :                         d->SP();
    1876                 :          0 :                         d->PushIndent();
    1877                 :          0 :                         s2->AccessStats(d);
    1878                 :          0 :                         s2->Describe(d);
    1879                 :          0 :                         d->PopIndent();
    1880                 :            :                         }
    1881                 :            :                 else
    1882                 :          0 :                         s2->Describe(d);
    1883                 :            :                 }
    1884                 :          0 :         }
    1885                 :            : 
    1886                 :          0 : TraversalCode WhenStmt::Traverse(TraversalCallback* cb) const
    1887                 :            :         {
    1888                 :          0 :         TraversalCode tc = cb->PreStmt(this);
    1889   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
    1890                 :            : 
    1891                 :          0 :         tc = cond->Traverse(cb);
    1892   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
    1893                 :            : 
    1894                 :          0 :         tc = s1->Traverse(cb);
    1895   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
    1896                 :            : 
    1897         [ #  # ]:          0 :         if ( s2 )
    1898                 :            :                 {
    1899                 :          0 :                 tc = s2->Traverse(cb);
    1900   [ #  #  #  # ]:          0 :                 HANDLE_TC_STMT_PRE(tc);
    1901                 :            :                 }
    1902                 :            : 
    1903                 :          0 :         tc = cb->PostStmt(this);
    1904 [ #  # ][ #  # ]:          0 :         HANDLE_TC_STMT_POST(tc);
    1905                 :            :         }
    1906                 :            : 
    1907                 :          3 : IMPLEMENT_SERIAL(WhenStmt, SER_WHEN_STMT);
    1908                 :            : 
    1909                 :          0 : bool WhenStmt::DoSerialize(SerialInfo* info) const
    1910                 :            :         {
    1911 [ #  # ][ #  # ]:          0 :         DO_SERIALIZE(SER_WHEN_STMT, Stmt);
    1912                 :            : 
    1913 [ #  # ][ #  # ]:          0 :         if ( cond->Serialize(info) && s1->Serialize(info) )
                 [ #  # ]
    1914                 :          0 :                 return false;
    1915                 :            : 
    1916 [ #  # ][ #  # ]:          0 :         SERIALIZE_OPTIONAL(s2);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1917 [ #  # ][ #  # ]:          0 :         SERIALIZE_OPTIONAL(timeout);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1918                 :            : 
    1919                 :          0 :         return true;
    1920                 :            :         }
    1921                 :            : 
    1922                 :          0 : bool WhenStmt::DoUnserialize(UnserialInfo* info)
    1923                 :            :         {
    1924         [ #  # ]:          0 :         DO_UNSERIALIZE(Stmt);
    1925                 :            : 
    1926                 :          0 :         cond = Expr::Unserialize(info);
    1927         [ #  # ]:          0 :         if ( ! cond )
    1928                 :          0 :                 return false;
    1929                 :            : 
    1930                 :          0 :         s1 = Stmt::Unserialize(info);
    1931         [ #  # ]:          0 :         if ( ! s1 )
    1932                 :          0 :                 return false;
    1933                 :            : 
    1934 [ #  # ][ #  # ]:          0 :         UNSERIALIZE_OPTIONAL(s2, Stmt::Unserialize(info));
                 [ #  # ]
    1935 [ #  # ][ #  # ]:          0 :         UNSERIALIZE_OPTIONAL(timeout, Expr::Unserialize(info));
                 [ #  # ]
    1936                 :            : 
    1937                 :          0 :         return true;
    1938                 :            :         }
    1939                 :            : 
    1940                 :          0 : Stmt* simplify_stmt(Stmt* s)
    1941                 :            :         {
    1942         [ #  # ]:          0 :         for ( Stmt* ss = s->Simplify(); ss != s; ss = s->Simplify() )
    1943                 :            :                 {
    1944                 :          0 :                 Unref(s);
    1945                 :          0 :                 s = ss;
    1946                 :            :                 }
    1947                 :            : 
    1948                 :          0 :         return s;
    1949                 :            :         }
    1950                 :            : 
    1951                 :          0 : int same_stmt(const Stmt* s1, const Stmt* s2)
    1952                 :            :         {
    1953         [ #  # ]:          0 :         if ( s1 == s2 )
    1954                 :          0 :                 return 1;
    1955                 :            : 
    1956         [ #  # ]:          0 :         if ( s1->Tag() != s2->Tag() )
    1957                 :          0 :                 return 0;
    1958                 :            : 
    1959 [ #  #  #  #  # :          0 :         switch ( s1->Tag() ) {
          #  #  #  #  # ]
    1960                 :            :         case STMT_ALARM:
    1961                 :            :         case STMT_PRINT:
    1962                 :            :                 {
    1963                 :          0 :                 const ListExpr* l1 = ((const ExprListStmt*) s1)->ExprList();
    1964                 :          0 :                 const ListExpr* l2 = ((const ExprListStmt*) s2)->ExprList();
    1965                 :          0 :                 return same_expr(l1, l2);
    1966                 :            :                 }
    1967                 :            : 
    1968                 :            :         case STMT_ADD:
    1969                 :            :         case STMT_DELETE:
    1970                 :            :         case STMT_RETURN:
    1971                 :            :         case STMT_EXPR:
    1972                 :            :         case STMT_EVENT:
    1973                 :            :                 {
    1974                 :          0 :                 const ExprStmt* e1 = (const ExprStmt*) s1;
    1975                 :          0 :                 const ExprStmt* e2 = (const ExprStmt*) s2;
    1976                 :          0 :                 return same_expr(e1->StmtExpr(), e2->StmtExpr());
    1977                 :            :                 }
    1978                 :            : 
    1979                 :            :         case STMT_FOR:
    1980                 :            :                 {
    1981                 :          0 :                 const ForStmt* f1 = (const ForStmt*) s1;
    1982                 :          0 :                 const ForStmt* f2 = (const ForStmt*) s2;
    1983                 :            : 
    1984                 :            :                 return f1->LoopVar() == f2->LoopVar() &&
    1985                 :            :                         same_expr(f1->LoopExpr(), f2->LoopExpr()) &&
    1986 [ #  # ][ #  # ]:          0 :                         same_stmt(f1->LoopBody(), f2->LoopBody());
                 [ #  # ]
    1987                 :            :                 }
    1988                 :            : 
    1989                 :            :         case STMT_IF:
    1990                 :            :                 {
    1991                 :          0 :                 const IfStmt* i1 = (const IfStmt*) s1;
    1992                 :          0 :                 const IfStmt* i2 = (const IfStmt*) s2;
    1993                 :            : 
    1994         [ #  # ]:          0 :                 if ( ! same_expr(i1->StmtExpr(), i2->StmtExpr()) )
    1995                 :          0 :                         return 0;
    1996                 :            : 
    1997 [ #  # ][ #  # ]:          0 :                 if ( i1->TrueBranch() || i2->TrueBranch() )
                 [ #  # ]
    1998                 :            :                         {
    1999 [ #  # ][ #  # ]:          0 :                         if ( ! i1->TrueBranch() || ! i2->TrueBranch() )
                 [ #  # ]
    2000                 :          0 :                                 return 0;
    2001         [ #  # ]:          0 :                         if ( ! same_stmt(i1->TrueBranch(), i2->TrueBranch()) )
    2002                 :          0 :                                 return 0;
    2003                 :            :                         }
    2004                 :            : 
    2005 [ #  # ][ #  # ]:          0 :                 if ( i1->FalseBranch() || i2->FalseBranch() )
                 [ #  # ]
    2006                 :            :                         {
    2007 [ #  # ][ #  # ]:          0 :                         if ( ! i1->FalseBranch() || ! i2->FalseBranch() )
                 [ #  # ]
    2008                 :          0 :                                 return 0;
    2009         [ #  # ]:          0 :                         if ( ! same_stmt(i1->FalseBranch(), i2->FalseBranch()) )
    2010                 :          0 :                                 return 0;
    2011                 :            :                         }
    2012                 :            : 
    2013                 :          0 :                 return 1;
    2014                 :            :                 }
    2015                 :            : 
    2016                 :            :         case STMT_SWITCH:
    2017                 :            :                 {
    2018                 :          0 :                 const SwitchStmt* sw1 = (const SwitchStmt*) s1;
    2019                 :          0 :                 const SwitchStmt* sw2 = (const SwitchStmt*) s2;
    2020                 :            : 
    2021         [ #  # ]:          0 :                 if ( ! same_expr(sw1->StmtExpr(), sw2->StmtExpr()) )
    2022                 :          0 :                         return 0;
    2023                 :            : 
    2024                 :          0 :                 const case_list* c1 = sw1->Cases();
    2025                 :          0 :                 const case_list* c2 = sw1->Cases();
    2026                 :            : 
    2027         [ #  # ]:          0 :                 if ( c1->length() != c2->length() )
    2028                 :          0 :                         return 0;
    2029                 :            : 
    2030         [ #  # ]:          0 :                 loop_over_list(*c1, i)
    2031                 :            :                         {
    2032         [ #  # ]:          0 :                         if ( ! same_expr((*c1)[i]->Cases(), (*c2)[i]->Cases()) )
    2033                 :          0 :                                 return 0;
    2034         [ #  # ]:          0 :                         if ( ! same_stmt((*c1)[i]->Body(), (*c2)[i]->Body()) )
    2035                 :          0 :                                 return 0;
    2036                 :            :                         }
    2037                 :            : 
    2038                 :          0 :                 return 1;
    2039                 :            :                 }
    2040                 :            : 
    2041                 :            :         case STMT_LIST:
    2042                 :            :         case STMT_EVENT_BODY_LIST:
    2043                 :            :                 {
    2044                 :          0 :                 const stmt_list& l1 = ((const StmtList*) s1)->Stmts();
    2045                 :          0 :                 const stmt_list& l2 = ((const StmtList*) s2)->Stmts();
    2046                 :            : 
    2047         [ #  # ]:          0 :                 if ( l1.length() != l2.length() )
    2048                 :          0 :                         return 0;
    2049                 :            : 
    2050         [ #  # ]:          0 :                 loop_over_list(l1, i)
    2051         [ #  # ]:          0 :                         if ( ! same_stmt(l1[i], l2[i]) )
    2052                 :          0 :                                 return 0;
    2053                 :            : 
    2054                 :          0 :                 return 1;
    2055                 :            :                 }
    2056                 :            : 
    2057                 :            :         case STMT_INIT:
    2058                 :            :                 {
    2059                 :          0 :                 const id_list* i1 = ((const InitStmt*) s1)->Inits();
    2060                 :          0 :                 const id_list* i2 = ((const InitStmt*) s2)->Inits();
    2061                 :            : 
    2062         [ #  # ]:          0 :                 if ( i1->length() != i2->length() )
    2063                 :          0 :                         return 0;
    2064                 :            : 
    2065         [ #  # ]:          0 :                 loop_over_list(*i1, i)
    2066         [ #  # ]:          0 :                         if ( (*i1)[i] != (*i2)[i] )
    2067                 :          0 :                                 return 0;
    2068                 :            : 
    2069                 :          0 :                 return 1;
    2070                 :            :                 }
    2071                 :            : 
    2072                 :            :         case STMT_WHEN:
    2073                 :            :                 {
    2074                 :          0 :                 const WhenStmt* w1 = (const WhenStmt*) s1;
    2075                 :          0 :                 const WhenStmt* w2 = (const WhenStmt*) s2;
    2076                 :            : 
    2077         [ #  # ]:          0 :                 if ( ! same_expr(w1->Cond(), w2->Cond()) )
    2078                 :          0 :                         return 0;
    2079                 :            : 
    2080         [ #  # ]:          0 :                 if ( ! same_stmt(w1->Body(), w2->Body()) )
    2081                 :          0 :                         return 0;
    2082                 :            : 
    2083 [ #  # ][ #  # ]:          0 :                 if ( w1->TimeoutBody() || w2->TimeoutBody() )
                 [ #  # ]
    2084                 :            :                         {
    2085 [ #  # ][ #  # ]:          0 :                         if ( ! w1->TimeoutBody() || ! w2->TimeoutBody() )
                 [ #  # ]
    2086                 :          0 :                                 return 0;
    2087                 :            : 
    2088         [ #  # ]:          0 :                         if ( ! same_expr(w1->TimeoutExpr(), w2->TimeoutExpr()) )
    2089                 :          0 :                                 return 0;
    2090                 :            : 
    2091         [ #  # ]:          0 :                         if ( ! same_stmt(w1->TimeoutBody(), w2->TimeoutBody()) )
    2092                 :          0 :                                 return 0;
    2093                 :            :                         }
    2094                 :            : 
    2095                 :          0 :                 return 1;
    2096                 :            :                 }
    2097                 :            : 
    2098                 :            :         case STMT_NEXT:
    2099                 :            :         case STMT_BREAK:
    2100                 :            :         case STMT_NULL:
    2101                 :          0 :                 return 1;
    2102                 :            : 
    2103                 :            :         default:
    2104                 :          0 :                 error("bad tag in same_stmt()");
    2105                 :            :         }
    2106                 :            : 
    2107                 :          0 :         return 0;
    2108 [ +  - ][ +  - ]:          6 :         }

Generated by: LCOV version 1.8