%{
  //===========================================================================
  //  @(#) $Name: cflowd-2-1-b1 $
  //  @(#) $Id: FlowFilter.y,v 1.3 1998/12/11 16:06:50 dwm Exp $
  //===========================================================================
  //  CAIDA Copyright Notice
  //
  //  By accessing this software, cflowd++, you are duly informed
  //  of and agree to be bound by the conditions described below in this
  //  notice:
  //
  //  This software product, cflowd++, is developed by Daniel W. McRobb, and
  //  copyrighted(C) 1998 by the University of California, San Diego
  //  (UCSD), with all rights reserved.  UCSD administers the CAIDA grant,
  //  NCR-9711092, under which part of this code was developed.
  //
  //  There is no charge for cflowd++ software. You can redistribute it
  //  and/or modify it under the terms of the GNU General Public License,
  //  v.  2 dated June 1991 which is incorporated by reference herein.
  //  cflowd++ is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, OF
  //  MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that the use
  //  of it will not infringe on any third party's intellectual property
  //  rights.
  //
  //  You should have received a copy of the GNU GPL along with cflowd++.
  //  Copies can also be obtained from:
  //
  //    http://www.gnu.org/copyleft/gpl.html
  //
  //  or by writing to:
  //
  //    University of California, San Diego
  //
  //    SDSC/CAIDA
  //    9500 Gilman Dr., MS-0505
  //    La Jolla, CA 92093 - 0505  USA
  //
  //  Or contact:
  //
  //    info@caida.org
  //===========================================================================
  
  #include <math.h>

  #include <string>
  
  #include "CflowdRawFlow.hh"

  static const string rcsid = "@(#) $Name: cflowd-2-1-b1 $ $Id: FlowFilter.y,v 1.3 1998/12/11 16:06:50 dwm Exp $";
  
  extern int            flowfiltparseval;
  int                   fieldval;
  extern int            yydebug;
  extern int            yylex(void);
  extern void           flowfilterror(const char *msg);
  const CflowdRawFlow  *g_rawFlowPtr;
  
  //-------------------------------------------------------------------------
  //            void SetFlowPointer(const CflowdRawFlow *flowPtr)            
  //.........................................................................
  //  
  //-------------------------------------------------------------------------
  void SetFlowPointer(const CflowdRawFlow *flowPtr)
  {
    g_rawFlowPtr = flowPtr;
    return;
  }

  //-------------------------------------------------------------------------
  //    uint32_t GetFieldValueByMask(CflowdRawFlow::index_type fieldMask)    
  //.........................................................................
  //  
  //-------------------------------------------------------------------------
  uint32_t GetFieldValueByMask(CflowdRawFlow::index_type fieldMask)
  {
    uint32_t  returnVal = 0;
    
    switch (fieldMask) {
      case CflowdRawFlow::k_routerMask:
        returnVal = g_rawFlowPtr->Router();
        break;
      case CflowdRawFlow::k_srcIpAddrMask:
        returnVal = g_rawFlowPtr->SrcIpAddr();
        break;
      case CflowdRawFlow::k_dstIpAddrMask:
        returnVal = g_rawFlowPtr->DstIpAddr();
        break;
      case CflowdRawFlow::k_inputIfIndexMask:
        returnVal = g_rawFlowPtr->InputIfIndex();
        break;
      case CflowdRawFlow::k_outputIfIndexMask:
        returnVal = g_rawFlowPtr->OutputIfIndex();
        break;
      case CflowdRawFlow::k_srcPortMask:
        returnVal = g_rawFlowPtr->SrcPort();
        break;
      case CflowdRawFlow::k_dstPortMask:
        returnVal = g_rawFlowPtr->DstPort();
        break;
      case CflowdRawFlow::k_pktsMask:
        returnVal = g_rawFlowPtr->Pkts();
        break;
      case CflowdRawFlow::k_bytesMask:
        returnVal = g_rawFlowPtr->Bytes();
        break;
      case CflowdRawFlow::k_ipNextHopMask:
        returnVal = g_rawFlowPtr->IpNextHop();
        break;
      case CflowdRawFlow::k_startTimeMask:
        returnVal = g_rawFlowPtr->StartTime();
        break;
      case CflowdRawFlow::k_endTimeMask:
        returnVal = g_rawFlowPtr->EndTime();
        break;
      case CflowdRawFlow::k_protocolMask:
        returnVal = g_rawFlowPtr->Protocol();
        break;
      case CflowdRawFlow::k_tosMask:
        returnVal = g_rawFlowPtr->Tos();
        break;
      case CflowdRawFlow::k_srcAsMask:
        returnVal = g_rawFlowPtr->SrcAs();
        break;
      case CflowdRawFlow::k_dstAsMask:
        returnVal = g_rawFlowPtr->DstAs();
        break;
      case CflowdRawFlow::k_srcMaskLenMask:
        returnVal = g_rawFlowPtr->SrcMaskLen();
        break;
      case CflowdRawFlow::k_dstMaskLenMask:
        returnVal = g_rawFlowPtr->DstMaskLen();
        break;
      case CflowdRawFlow::k_tcpFlagsMask:
        returnVal = g_rawFlowPtr->TcpFlags();
        break;
      case CflowdRawFlow::k_inputEncapMask:
      case CflowdRawFlow::k_outputEncapMask:
      case CflowdRawFlow::k_peerNextHopMask:
        //  Not implemented
        break;
      case CflowdRawFlow::k_engineTypeMask:
        returnVal = g_rawFlowPtr->EngineType();
        break;
      case CflowdRawFlow::k_engineIdMask:
        returnVal = g_rawFlowPtr->EngineId();
        break;
      default:
        break;
    }
    return(returnVal);
  }

%}
%token FIELDNAME IPADDR INTEGER EQ NE LT GT LE GE IGNORE ENDOFFILE AND LOGOR
%token BITAND BITOR BITXOR LPAREN RPAREN DIV MUL ADD SUB MOD LOGNOT BITNOT
%token ALL

%left LOGOR
%left AND
%left BITOR
%left BITXOR
%left BITAND
%left EQ NE
%left LT LE GT GE
%left ADD SUB
%left MUL DIV MOD
%left LOGNOT BITNOT
%left LPAREN RPAREN

%%

expression: 
        |   expression EQ expression { $$ = ($1 == $3) ? 1 : 0;
                                       flowfiltparseval = $$; }
        |   expression NE expression { $$ = ($1 != $3) ? 1 : 0;
                                       flowfiltparseval = $$; }
        |   expression GT expression { $$ = ($1 > $3) ? 1 : 0;
                                       flowfiltparseval = $$; }
        |   expression GE expression { $$ = ($1 >= $3) ? 1 : 0;
                                       flowfiltparseval = $$; }
        |   expression LT expression { $$ = ($1 < $3) ? 1 : 0;
                                       flowfiltparseval = $$; }
        |   expression LE expression { $$ = ($1 <= $3) ? 1 : 0;
                                       flowfiltparseval = $$; }
        |   LOGNOT expression        { $$ = (!$2); flowfiltparseval = $$; }
        |   expression DIV expression { $$ = (int)(ceil(($1 * 1.0) / $3)); }
        |   expression MUL expression { $$ = (int)(($1 * 1.0) * $3); }
        |   expression ADD expression { $$ = ($1 + $3); }
        |   expression SUB expression { $$ = ($1 - $3); }
        |   expression MOD expression { $$ = ($1 % $3); }
        |   expression BITXOR expression { $$ = ($1 ^ $3);
                                           flowfiltparseval = $$; }
        |   BITNOT expression { $$ = (~ $2); flowfiltparseval = $$; }
        |   FIELDNAME BITAND INTEGER { $$ = (GetFieldValueByMask($1) & $3);
                                        flowfiltparseval = $$; }
        |   FIELDNAME BITOR INTEGER { $$ = (GetFieldValueByMask($1) | $3);
                                      flowfiltparseval = $$; }
        |   expression AND expression { $$ = ($1 && $3) ? 1 : 0;
                                        flowfiltparseval = $$; }
        |   expression LOGOR expression { $$ = ($1 || $3) ? 1 : 0;
                                       flowfiltparseval = $$; }
        |   LPAREN expression RPAREN { $$ = $2; }
        |   FIELDNAME { $$ = GetFieldValueByMask($1); }
        |   INTEGER { $$ = $1; }
        |   ALL { $$ = 1; flowfiltparseval = $$; }
;
