asmrulep.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:35k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. // #include "hlxclib/stdio.h"      /* printf */
  36. #include "hxtypes.h"    /* Basic Types */
  37. #include "hlxclib/stdlib.h"
  38. #include "hxstrutl.h"
  39. #include "hxcom.h"      /* IUnknown */
  40. #include "ihxpckts.h"
  41. #include "asmrulep.h" /* ASM Public Include File */
  42. #include "asmrulpp.h" /* ASM Private Include File */
  43. #include "chxpckts.h"
  44. #define RULE_VAL_INFINITY -1
  45. #include "hxheap.h"
  46. /*
  47. #ifdef _DEBUG
  48. #undef HX_THIS_FILE
  49. static const char HX_THIS_FILE[] = __FILE__;
  50. #endif
  51. */
  52. static const char* const zpOpName[] =
  53. {
  54.     ">",
  55.     "<",
  56.     ">=",
  57.     "<=",
  58.     "==",
  59.     "!=",
  60.     "AND",
  61.     "OR"
  62. };
  63. ASMRuleExpression::ASMRuleExpression(const char* pExpression)
  64. {
  65.     int temp;
  66.     char* pTemp = new char[temp = (strlen(pExpression) + 1)];
  67.     memcpy(pTemp, pExpression, temp); /* Flawfinder: ignore */
  68.     m_ulNumThresholds = 1; // always have one zero rule
  69.     m_pHead = Parse(pTemp, m_ulNumThresholds);
  70.     delete[] pTemp;
  71. }
  72. ASMRuleExpression::~ASMRuleExpression()
  73. {
  74.     RDelete(m_pHead);
  75. }
  76. /* Note:  This parse is destructive to pExpression */
  77. Node*
  78. ASMRuleExpression::Parse(char* pExpression, UINT32& ulNumThreshold)
  79. {
  80.     char* pTemp = pExpression;
  81.     int PLevel = 0;
  82.     BOOL bStripAgain = 1;
  83.     int OperSize;
  84.     //printf ("Parse Expression: %sn", pExpression);
  85.     // Strip outside unneccesary parens
  86.     while ((*pExpression == '(') && (bStripAgain))
  87.     {
  88. for (pTemp = pExpression, PLevel = 0; *pTemp; pTemp++)
  89. {
  90.     if (*pTemp == '(')
  91. PLevel++;
  92.     if (*pTemp == ')')
  93.     {
  94. PLevel--;
  95. if ((!(*(pTemp + 1))) && (!PLevel))
  96. {
  97.     pExpression++;
  98.     pExpression[strlen(pExpression) - 1] = 0;
  99.     bStripAgain = 1;
  100.     break;
  101. }
  102. if (!PLevel)
  103. {
  104.     bStripAgain = 0;
  105.     break;
  106. }
  107.     }
  108. }
  109.     }
  110.     for (pTemp = pExpression, PLevel = 0; *pTemp; pTemp++)
  111.     {
  112. if (*pTemp == '(')
  113.     PLevel++;
  114. if (*pTemp == ')')
  115.     PLevel--;
  116. if (!PLevel)
  117. {
  118.     OperSize = 1;
  119.     if (((*pTemp == '>') || (*pTemp == '<')) ||
  120.         ((*pTemp == '=') || (*pTemp == '!')) ||
  121.         ((*pTemp == '&') || (*pTemp == '|')))
  122.     {
  123. OperatorNode* pNode = new OperatorNode;
  124. pNode->m_Type = HX_RE_OPERATOR;
  125. switch (*pTemp)
  126. {
  127. case '>':
  128.     if ((*(pTemp + 1)) == '=')
  129.     {
  130. pNode->m_Data = HX_RE_GREATEREQUAL;
  131. OperSize = 2;
  132.     }
  133.     else
  134. pNode->m_Data = HX_RE_GREATER;
  135.     break;
  136. case '<':
  137.     if ((*(pTemp + 1)) == '=')
  138.     {
  139. pNode->m_Data = HX_RE_LESSEQUAL;
  140. OperSize = 2;
  141.     }
  142.     else
  143. pNode->m_Data = HX_RE_LESS;
  144.     break;
  145. case '=':
  146.     if ((*(pTemp + 1)) == '=')
  147.     {
  148. pNode->m_Data = HX_RE_EQUAL;
  149. OperSize = 2;
  150.     }
  151.     break;
  152. case '!':
  153.     if ((*(pTemp + 1)) == '=')
  154.     {
  155. pNode->m_Data = HX_RE_NOTEQUAL;
  156. OperSize = 2;
  157.     }
  158.     break;
  159. case '&':
  160.     if ((*(pTemp + 1)) == '&')
  161.     {
  162. pNode->m_Data = HX_RE_AND;
  163. OperSize = 2;
  164.     }
  165.     break;
  166. case '|':
  167.     if ((*(pTemp + 1)) == '|')
  168.     {
  169. pNode->m_Data = HX_RE_OR;
  170. OperSize = 2;
  171.     }
  172.     break;
  173. default:
  174.     break;
  175. };
  176. *pTemp = 0;
  177. pNode->m_pLeft  = Parse(pExpression, ulNumThreshold);
  178. pNode->m_pRight = Parse(pTemp + OperSize, ulNumThreshold);
  179. return pNode;
  180.     }
  181. }
  182.     }
  183.     for (pTemp = pExpression, PLevel = 0; *pTemp; pTemp++)
  184.     {
  185. if (*pTemp == '(')
  186.     PLevel++;
  187. if (*pTemp == ')')
  188.     PLevel--;
  189. if (!PLevel)
  190. {
  191.     if (*pTemp == '$')
  192.     {
  193. VariableNode* pNode = new VariableNode;
  194. pNode->m_Type = HX_RE_VARIABLE;
  195. pNode->m_Data = new char[strlen(pTemp)];
  196. memcpy(pNode->m_Data, pTemp + 1, strlen(pTemp)); /* Flawfinder: ignore */
  197. pNode->m_pLeft  = 0;
  198. pNode->m_pRight = 0;
  199. ulNumThreshold++; // each open variable means one more threshold.
  200. return pNode;
  201.     }
  202. }
  203.     }
  204.     for (pTemp = pExpression, PLevel = 0; *pTemp; pTemp++)
  205.     {
  206. if (*pTemp == '(')
  207.     PLevel++;
  208. if (*pTemp == ')')
  209.     PLevel--;
  210. if (!PLevel)
  211. {
  212.     if  ((*pTemp == '0') || (*pTemp == '1') || (*pTemp == '2') ||
  213.  (*pTemp == '3') || (*pTemp == '4') || (*pTemp == '5') ||
  214.  (*pTemp == '6') || (*pTemp == '7') || (*pTemp == '8') ||
  215.  (*pTemp == '9'))
  216.     {
  217. if (strchr(pTemp, '.'))
  218. {
  219.     FloatNode* pNode = new FloatNode;
  220.     pNode->m_Type = HX_RE_FLOAT;
  221.     pNode->m_Data = (float)atof(pTemp);
  222.     pNode->m_pLeft  = 0;
  223.     pNode->m_pRight = 0;
  224.     return pNode;
  225. }
  226. else
  227. {
  228.     IntegerNode* pNode = new IntegerNode;
  229.     pNode->m_Type = HX_RE_INTEGER;
  230.     pNode->m_Data = atoi(pTemp);
  231.     pNode->m_pLeft  = 0;
  232.     pNode->m_pRight = 0;
  233.     return pNode;
  234. }
  235.     }
  236. }
  237.     }
  238.     //printf ("Panic: Bad rulen");
  239.     return 0;
  240. }
  241. void
  242. ASMRuleExpression::Dump()
  243. {
  244.     //printf ("Dumping ASMRuleExpression:n");
  245.     RDump(m_pHead);
  246.     //printf ("n");
  247. }
  248. void
  249. ASMRuleExpression::RDump(Node* pNode)
  250. {
  251.     if (!pNode)
  252. return;
  253. #if 0
  254.     switch(pNode->m_Type)
  255.     {
  256.     case HX_RE_VARIABLE:
  257. printf ("   Variable: %sn", ((VariableNode *)pNode)->m_Data);
  258. break;
  259.     case HX_RE_INTEGER:
  260. printf ("   Integer: %dn", ((IntegerNode *)pNode)->m_Data);
  261. break;
  262.     case HX_RE_FLOAT:
  263. printf ("   Float: %fn", ((FloatNode *)pNode)->m_Data);
  264. break;
  265.     case HX_RE_OPERATOR:
  266. printf ("   Operator: %sn",
  267.     zpOpName[((OperatorNode *)pNode)->m_Data]);
  268. break;
  269.     }
  270. #endif
  271.     RDump(pNode->m_pLeft);
  272.     RDump(pNode->m_pRight);
  273. }
  274. void
  275. ASMRuleExpression::RDelete(Node* pNode)
  276. {
  277.     if (!pNode)
  278. return;
  279.     if (pNode->m_Type == HX_RE_VARIABLE)
  280.     {
  281. HX_VECTOR_DELETE(((VariableNode *)pNode)->m_Data);
  282.     };
  283.     RDelete(pNode->m_pLeft);
  284.     RDelete(pNode->m_pRight);
  285.     delete pNode;
  286. }
  287. /*
  288.  * This is a recursive expression evaluator that will determine whether
  289.  * or not we are subscribed to a particular rule, given the current conditions
  290.  */ 
  291. float
  292. ASMRuleExpression::REvaluate(Node* pNode, IHXValues* pVars)
  293. {
  294.     if (!pNode)
  295.         return (float)0;
  296.     switch(pNode->m_Type)
  297.     {
  298.     case HX_RE_VARIABLE:
  299. {
  300.     IHXBuffer* pValue=NULL;
  301.             float nValue = (float)0;
  302.     pVars->GetPropertyCString(((VariableNode *)pNode)->m_Data, pValue);
  303.     if (pValue)
  304.     {
  305.                 nValue = (float)atof((const char *)pValue->GetBuffer());
  306. pValue->Release();
  307.     }
  308.     return nValue;
  309. }
  310.     case HX_RE_INTEGER:
  311.         return (float)((IntegerNode *)pNode)->m_Data;
  312. break;
  313.     case HX_RE_FLOAT:
  314. return ((FloatNode *)pNode)->m_Data;
  315. break;
  316.     case HX_RE_OPERATOR:
  317. {
  318.     float Left  = REvaluate(pNode->m_pLeft,  pVars); 
  319.     float Right = REvaluate(pNode->m_pRight, pVars); 
  320.     switch (((OperatorNode *)pNode)->m_Data)
  321.     {
  322.     case HX_RE_GREATEREQUAL:
  323.                 return (float)(Left >= Right);
  324. break;
  325.     case HX_RE_GREATER:
  326.                 return (float)(Left > Right);
  327. break;
  328.             case HX_RE_LESSEQUAL:
  329. if( Right == RULE_VAL_INFINITY )
  330. {
  331.     return (float)TRUE;
  332. }
  333.                 return (float)(Left <= Right);
  334. break;
  335.     case HX_RE_LESS:
  336. if( Right == RULE_VAL_INFINITY )
  337. {
  338.     return (float)TRUE;
  339. }
  340.                 return (float)(Left < Right);
  341. break;
  342.     case HX_RE_EQUAL:
  343.                 return (float)(Left == Right);
  344. break;
  345.     case HX_RE_NOTEQUAL:
  346.                 return (float)(Left != Right);
  347. break;
  348.     case HX_RE_AND:
  349.                 return (float)(Left && Right);
  350. break;
  351.     case HX_RE_OR:
  352.                 return (float)(Left || Right);
  353. break;
  354.             default:
  355.                 HX_ASSERT(0);
  356.                 return (float)0;
  357.                 break;
  358.     }
  359. }
  360. break;
  361.     default:
  362.         HX_ASSERT(0);
  363.         return (float)0;
  364.         break;
  365.     }
  366. }
  367. BOOL
  368. ASMRuleExpression::Evaluate(IHXValues* pVars)
  369. {
  370.     BOOL res;
  371.     //printf ("Evaluate ASMRuleExpression:n");
  372.     res = (BOOL)REvaluate(m_pHead, pVars);
  373.     //printf ("%dn", res);
  374.     return res;
  375. }
  376. /*
  377.  * This is a recursive function which will evaluate a tree with one free
  378.  * variable (pPrevar).  The returned array will contain all possible values
  379.  * that are border cases.
  380.  */
  381. float
  382. ASMRuleExpression::RPreEvaluate(Node* pNode, IHXValues* pVars,
  383. const char* pPreVar, float*& pThreshold,
  384. UINT32& ulNumThreshold,
  385. BOOL& bInvolvesTheOpenVariable)
  386. {
  387.     bInvolvesTheOpenVariable = FALSE;
  388.     float retval = 0;
  389.     float* pThresholdL = NULL;
  390.     float* pThresholdR = NULL;
  391. #define RETURN(x) retval = x; goto exitpoint;
  392.     if (!pNode)
  393.         return (float)0;
  394.     switch(pNode->m_Type)
  395.     {
  396.     case HX_RE_VARIABLE:
  397. {
  398.     IHXBuffer* pValue=NULL;
  399.             float nValue = (float)0;
  400.     pVars->GetPropertyCString(((VariableNode *)pNode)->m_Data, pValue);
  401.     if (pValue)
  402.     {
  403.                 nValue = (float)atof((const char *)pValue->GetBuffer());
  404. pValue->Release();
  405.     }
  406.     if (strcasecmp(((VariableNode *)pNode)->m_Data, pPreVar) == 0)
  407.     {
  408. bInvolvesTheOpenVariable = TRUE;
  409.     }
  410.     return nValue;
  411. }
  412.     case HX_RE_INTEGER:
  413.         return (float)((IntegerNode *)pNode)->m_Data;
  414. break;
  415.     case HX_RE_FLOAT:
  416. return ((FloatNode *)pNode)->m_Data;
  417. break;
  418.     case HX_RE_OPERATOR:
  419. {
  420.     BOOL bInvolveL, bInvolveR;
  421.     UINT32 ulNumThresholdL = 0;
  422.     pThresholdL = pThreshold;
  423.     float Left  = RPreEvaluate(pNode->m_pLeft,  pVars, pPreVar,
  424.     pThresholdL, ulNumThresholdL, bInvolveL);
  425.     UINT32 ulNumThresholdR = 0;
  426.     pThresholdR = pThreshold + ulNumThresholdL;
  427.     float Right = RPreEvaluate(pNode->m_pRight, pVars, pPreVar,
  428.     pThresholdR, ulNumThresholdR, bInvolveR);
  429.     /* Handle aggregation of Threshold arrays */
  430.     switch (((OperatorNode *)pNode)->m_Data)
  431.     {
  432.     case HX_RE_GREATEREQUAL:
  433.     case HX_RE_GREATER:
  434.     case HX_RE_LESSEQUAL:
  435.     case HX_RE_LESS:
  436.     case HX_RE_EQUAL:
  437.     case HX_RE_NOTEQUAL:
  438. if (bInvolveR)
  439. {
  440.     bInvolvesTheOpenVariable = TRUE;
  441.     *pThreshold = Left;
  442.     pThreshold++;
  443.     ulNumThreshold++;
  444.     RETURN ((float)1);
  445. }
  446. if (bInvolveL)
  447. {
  448.     bInvolvesTheOpenVariable = TRUE;
  449.     *pThreshold = Right;
  450.     pThreshold++;
  451.     ulNumThreshold++;
  452.     RETURN ((float)1);
  453. }
  454. break;
  455.     case HX_RE_AND:
  456. if ((Left && bInvolveR) || (Right && bInvolveL))
  457. {
  458.     bInvolvesTheOpenVariable = TRUE;
  459.     UINT32 ulSize = ulNumThresholdL + ulNumThresholdR;
  460.     pThreshold += ulSize;
  461.     ulNumThreshold += ulSize;
  462.     RETURN ((float)1);
  463. }
  464. else
  465. {
  466.     RETURN ((float)0);
  467. }
  468.     case HX_RE_OR:
  469. if (Left || bInvolveL || Right || bInvolveR)
  470. {
  471.     bInvolvesTheOpenVariable = TRUE;
  472.     UINT32 ulSize = ulNumThresholdL + ulNumThresholdR;
  473.     pThreshold += ulSize;
  474.     ulNumThreshold += ulSize;
  475.     RETURN ((float)1);
  476. }
  477. else
  478. {
  479.     RETURN ((float)0);
  480. }
  481.     }
  482.     switch (((OperatorNode *)pNode)->m_Data)
  483.     {
  484.     case HX_RE_GREATEREQUAL:
  485.                 RETURN ((float)(Left >= Right));
  486.     case HX_RE_GREATER:
  487.                 RETURN ((float)(Left > Right));
  488.             case HX_RE_LESSEQUAL:
  489.                 RETURN ((float)(Left <= Right));
  490.     case HX_RE_LESS:
  491.                 RETURN ((float)(Left < Right));
  492.     case HX_RE_EQUAL:
  493.                 RETURN ((float)(Left == Right));
  494.     case HX_RE_NOTEQUAL:
  495.                 RETURN ((float)(Left != Right));
  496.     case HX_RE_AND:
  497.                 RETURN ((float)(Left && Right));
  498.     case HX_RE_OR:
  499.                 RETURN ((float)(Left || Right));
  500.             default:
  501.                 HX_ASSERT(0);
  502.                 RETURN ((float)0);
  503.     }
  504. }
  505.     default:
  506.         HX_ASSERT(0);
  507.         RETURN ((float)0);
  508.     }
  509. exitpoint:
  510.     return retval;
  511. #undef RETURN
  512. }
  513. void
  514. ASMRuleExpression::PreEvaluate(float*& pThreshold, UINT32& ulNumThreshold,
  515.     IHXValues* pVariables, const char* pPreVar)
  516. {
  517.     BOOL bJunk = 0;
  518.     RPreEvaluate(m_pHead, pVariables, pPreVar, 
  519.  pThreshold, ulNumThreshold, bJunk);
  520. }
  521. /*
  522.  * This is a recursive expression evaluator that will determine whether
  523.  * or not the given variable occurs anywhere in the expression.
  524.  */ 
  525. BOOL
  526. ASMRuleExpression::RFindVariable(Node* pNode, const char* pVariable)
  527. {
  528.     if (!pNode)
  529.         return FALSE;
  530.     switch(pNode->m_Type)
  531.     {
  532.     case HX_RE_VARIABLE:
  533. {
  534.     if (strcasecmp(((VariableNode *)pNode)->m_Data, pVariable) == 0)
  535.     {
  536. return TRUE;
  537.     }
  538. }
  539. break;
  540.     case HX_RE_OPERATOR:
  541. {
  542.     return (RFindVariable(pNode->m_pLeft, pVariable) ||
  543.     RFindVariable(pNode->m_pRight, pVariable));
  544. }
  545.     case HX_RE_INTEGER:
  546.     case HX_RE_FLOAT:
  547.     default:
  548.         break;
  549.     }
  550.     return FALSE;
  551. }
  552. BOOL
  553. ASMRuleExpression::FindVariable(const char* pVariable)
  554. {
  555.     return RFindVariable(m_pHead, pVariable);
  556. }
  557. class Rule
  558. {
  559. public:
  560. Rule();
  561.     void SetExpression(const char* pExpression);
  562.     void Dump();
  563. private:
  564.     ASMRuleExpression* m_pASMRuleExpression;
  565.     // Add Properties Definitions Here
  566. };
  567. ASMRule::ASMRule()
  568.     : m_pRuleExpression(0)
  569. {
  570. m_pRuleProps = new CHXHeader;
  571. HX_ASSERT(m_pRuleProps != NULL);
  572. if(m_pRuleProps)
  573. {
  574. m_pRuleProps->AddRef();
  575. }
  576. }
  577. ASMRule::~ASMRule()
  578. {
  579.     HX_RELEASE(m_pRuleProps);
  580.     HX_DELETE(m_pRuleExpression);
  581. }
  582. void
  583. ASMRule::SetExpression(const char* pExpression)
  584. {
  585.     m_pRuleExpression = new ASMRuleExpression(pExpression);
  586. }
  587. void
  588. ASMRule::Dump()
  589. {
  590.     m_pRuleExpression->Dump();
  591. }
  592. ASMRuleBook::ASMRuleBook(const char* pRuleBook)
  593. : m_pValidRulesArray(NULL)
  594. , m_pDeletedRulesArray(NULL)
  595. , m_pRuleBook(NULL)
  596. , m_LastError(HXR_OK)
  597. {
  598.     m_ulNumThresholds = 1; // always have a default
  599.     int i;
  600.     const char* pRule;
  601.     // Count Rules
  602.     i = 0;
  603.     BOOL bSingleQuote      = 0;
  604.     BOOL bDoubleQuote     = 0;
  605.     for (pRule = pRuleBook; *pRule; pRule++)
  606.     {
  607. if ((*pRule == ''') && (!bDoubleQuote))
  608.     bSingleQuote = !bSingleQuote;
  609. if ((*pRule == '"') && (!bSingleQuote))
  610.     bDoubleQuote = !bDoubleQuote;
  611. // Count the number of semi-colons (number of rules)
  612. if ((bSingleQuote == 0) && (bDoubleQuote == 0) && (*pRule == ';'))
  613.     i++;
  614.     }
  615.     m_unNumRules = i;
  616.     m_pRules = new ASMRule[i];
  617.     if(!m_pRules)
  618.     {
  619.        m_LastError = HXR_OUTOFMEMORY;
  620.         return;
  621.     }
  622.     //printf ("%d Rulesn", i);
  623.     // Iterate through each rule
  624.     m_pRuleBook = new char[ strlen( pRuleBook ) + 1 ];
  625.     if(!m_pRuleBook)
  626.     {
  627.         m_LastError = HXR_OUTOFMEMORY;
  628.         HX_DELETE(m_pRules);
  629.         return;
  630.     }
  631.     else
  632.     {
  633.         memcpy( (void*) m_pRuleBook, pRuleBook, strlen( pRuleBook ) + 1 );
  634.     }
  635.     m_LastError = Reset();
  636. }
  637. ASMRuleBook::~ASMRuleBook()
  638. {
  639.     delete [] m_pRules;
  640.     if( m_pValidRulesArray )
  641.     {
  642.        HX_VECTOR_DELETE(m_pValidRulesArray);
  643.     }
  644.     if( m_pDeletedRulesArray )
  645.     {
  646.        HX_VECTOR_DELETE(m_pDeletedRulesArray);
  647.     }
  648. HX_VECTOR_DELETE(m_pRuleBook);
  649. }
  650. BOOL
  651. ASMRuleBook::HasExpression()
  652. {
  653.     for (int i = 0; i < m_unNumRules; i++)
  654.     {
  655.         if (m_pRules[i].m_pRuleExpression)
  656.     return TRUE;
  657.     }
  658.     return FALSE;
  659. }
  660. HX_RESULT
  661. ASMRuleBook::GetProperties(UINT16 unRuleNumber, IHXValues*& pRuleProps)
  662. {
  663.     pRuleProps = m_pRules[unRuleNumber].m_pRuleProps;
  664.     if( pRuleProps )
  665.     {
  666.         pRuleProps->AddRef();
  667.     }
  668.     return HXR_OK;
  669. }
  670. /* Uses REvaluate to return the current subscription given pVariables */
  671. HX_RESULT
  672. ASMRuleBook::GetSubscription(BOOL* pSubInfo, IHXValues* pVariables)
  673. {
  674.     UINT32 i = 0;
  675.     for (i = 0; i < m_unNumRules; i++)
  676.     {
  677.         if( m_pDeletedRulesArray && m_pDeletedRulesArray[i] == TRUE )
  678. {
  679.             pSubInfo[i] = 0;
  680. }
  681. else if (m_pRules[i].m_pRuleExpression)
  682.         {
  683.             pSubInfo[i] = m_pRules[i].m_pRuleExpression->Evaluate(pVariables);
  684.         }
  685.         else
  686.         {
  687.             pSubInfo[i] = 1;
  688.         }
  689.     }
  690.     return HXR_OK;
  691. }
  692. /* 
  693.  * Uses RFindVariable to return information on which rules contain a 
  694.  * given variable in their expressions 
  695.  */
  696. HX_RESULT
  697. ASMRuleBook::FindVariable(BOOL* pFound, const char* pVariable)
  698. {
  699.     UINT32 i = 0;
  700.     for (i = 0; i < m_unNumRules; i++)
  701.     {
  702. if (m_pRules[i].m_pRuleExpression)
  703. {
  704.     pFound[i] = m_pRules[i].m_pRuleExpression->FindVariable(pVariable);
  705. }
  706. else
  707. {
  708.     pFound[i] = FALSE;
  709. }
  710.     }
  711.     return HXR_OK;
  712. }
  713. /* 
  714.  * Uses GetProperties to return information on which rules contain a 
  715.  * given property 
  716.  */
  717. HX_RESULT
  718. ASMRuleBook::FindProperty(BOOL* pFound, const char* pProperty)
  719. {
  720.     HX_RESULT hResult     = HXR_OK;
  721.     UINT32 i     = 0;
  722.     IHXValues* pProperties = NULL;
  723.     IHXBuffer* pBuffer     = NULL;
  724.     for (i = 0; i < m_unNumRules; i++)
  725.     {
  726. hResult = GetProperties((UINT16)i, pProperties);
  727. if (HXR_OK == hResult)
  728. {
  729.     hResult = pProperties->GetPropertyCString(pProperty, pBuffer);
  730.     if (HXR_OK == hResult)
  731.     {
  732. pFound[i] = TRUE;
  733. HX_RELEASE(pBuffer);
  734.     }
  735.     HX_RELEASE(pProperties);
  736. }
  737.     }
  738.     return HXR_OK;
  739. }
  740. static int FloatCompare(const void* p1, const void* p2)
  741. {
  742.     if (*(float*)p1 < *(float*)p2)
  743. return -1;
  744.     if (*(float*)p1 > *(float*)p2)
  745. return 1;
  746.     return 0;
  747. }
  748. /*
  749.  * Uses RPreEvaluate to return the array of threshold values, 
  750.  * given pVariables and pPreVar (the free variable)
  751.  * Caveat: Your variables must say "0" for pPreVar in pVariables.
  752.  */
  753. HX_RESULT
  754. ASMRuleBook::GetPreEvaluate(float* pThreshold, UINT32& ulNumThreshold,
  755.     IHXValues* pVariables, const char* pPreVar)
  756. {
  757.     UINT16 i;
  758.     float* pUnsortedFinal   = new float[m_ulNumThresholds+1];
  759.     float* pTemp = pUnsortedFinal;
  760.     UINT32 ulUFNum = 0;
  761.     ulNumThreshold = 0;
  762.     /* Get everything into a unsorted array with duplicates */ 
  763.     for (i = 0; i < m_unNumRules; i++)
  764.     {
  765.         if (m_pRules[i].m_pRuleExpression)
  766. {
  767.             m_pRules[i].m_pRuleExpression->PreEvaluate(pTemp, ulUFNum,
  768. pVariables, pPreVar);
  769. }
  770.     }
  771.     /*
  772.      * XXXSMP Totally disgusting and doesn't belong here.  So much for
  773.      * a clean, extensible function.
  774.      */
  775.     IHXValues* pValues = 0;
  776.     IHXBuffer* pBuffer = 0;
  777.     pUnsortedFinal[ulUFNum] = (float)0;
  778.     for (i = 0; i < m_unNumRules; i++)
  779.     {
  780. BOOL bOn = TRUE;
  781. if (m_pRules[i].m_pRuleExpression)
  782. {
  783.     bOn = m_pRules[i].m_pRuleExpression->Evaluate(pVariables);
  784. }
  785. if (bOn)
  786. {
  787.     GetProperties((UINT16) i, pValues);
  788.     if (HXR_OK == pValues->GetPropertyCString("AverageBandwidth",
  789. pBuffer))
  790.     {
  791. pUnsortedFinal[ulUFNum] += atoi((char*)pBuffer->GetBuffer());
  792. pBuffer->Release();
  793.     }
  794.     if (HXR_OK == pValues->GetPropertyCString("DropByN",
  795. pBuffer))
  796.     {
  797. pUnsortedFinal[ulUFNum] += 1;
  798. pBuffer->Release();
  799.     }
  800.             HX_RELEASE(pValues);
  801. }
  802.     }
  803.     ulUFNum++;
  804.     pUnsortedFinal[ulUFNum] = (float)0;
  805.     qsort(pUnsortedFinal, ulUFNum+1, sizeof(float), FloatCompare);
  806.     /* Sort and squash duplicates into the output array */
  807.     pTemp = pUnsortedFinal;
  808.     float fLast = *pUnsortedFinal;
  809.     *pThreshold = *pUnsortedFinal;
  810.     pTemp++;
  811.     pThreshold++;
  812.     ulNumThreshold++;
  813.     for (i = 0; i < ulUFNum; i++)
  814.     {
  815. if (*pTemp > fLast)
  816. {
  817.     fLast = *pTemp;
  818.     *pThreshold = fLast;
  819.     pThreshold++;
  820.     ulNumThreshold++;
  821. }
  822. pTemp++;
  823.     }
  824.     delete [] pUnsortedFinal;
  825.     return HXR_OK;
  826. }
  827. #ifdef TESTING
  828. int
  829. main()
  830. {
  831.     const char* pRuleBook =
  832. {
  833. /* Rule 0 */
  834. "     
  835.     #(24000 <= $Bandwidth) && ($Cpu > 50),     
  836.     TolerablePacketLoss=1.5,     
  837.     AverageBandwidth=4000,     
  838.     AverageBandwidthStd=0,     
  839.     Priority=7;     
  840. "
  841. /* Rule 1 */
  842. "     
  843.     #(20000 <= $Bandwidth),     
  844.     TolerablePacketLoss=1.5,     
  845.     AverageBandwidth=4000,     
  846.     AverageBandwidthStd=0,     
  847.     Priority=7;     
  848. "
  849. /* Rule 2 */
  850. "     
  851.     # $Bandwidth >= 16000,     
  852.     TolerablePacketLoss=1.5,     
  853.     AverageBandwidth=16000,     
  854.     AverageBandwidthStd=0,     
  855.     Priority=7;     
  856. "
  857. /* Rule 3 */
  858. "     
  859.     #(16000 > $Bandwidth) && (($Bandwidth >= 8000)),     
  860.     TolerablePacketLoss=2,     
  861.     AverageBandwidth=8000,     
  862.     AverageBandwidthStd=0,     
  863.     Foo="This is a test",     
  864.     Bar="This wu'z a test",     
  865.     Priority=7;     
  866. "
  867. /* Rule 4 */
  868. "     
  869.     # ($Bandwidth > 8000),     
  870.     AverageBandwidth=4000,     
  871.     Priority=7;     
  872. "
  873. };
  874.     ASMRuleBook     r(pRuleBook);
  875.     for (int i = 0; i < 25000; i += 1000)
  876.     {
  877. IHXValues* pVal = new CHXHeader;
  878. IHXBuffer* pBuffer = new CHXBuffer;
  879. char s[1024]; /* Flawfinder: ignore */
  880. //printf ("%dn", i);
  881. sprintf (s, "%d", i); /* Flawfinder: ignore */
  882. pBuffer->Set((unsigned char *)s, 5);
  883. pVal->SetPropertyCString("Bandwidth", pBuffer);
  884. pVal->AddRef();
  885. pBuffer = new CHXBuffer;
  886. sprintf (s, "%d", 60); /* Flawfinder: ignore */
  887. pBuffer->Set((unsigned char *)s, 5);
  888. pVal->SetPropertyCString("Cpu", pBuffer);
  889. pVal->AddRef();
  890. if (i == 0)
  891. {
  892.     printf ("Threshold Points:  ");
  893.     float pThreshold[1024];
  894.     memset (pThreshold, 0xffffffff, sizeof(float) * 1024);
  895.     UINT32 ulNum = 0;
  896.     r.GetPreEvaluate(pThreshold, ulNum, pVal, "Bandwidth");
  897.     for (int j = 0; j < ulNum; j++)
  898.     {
  899. printf ("%.2f ", pThreshold[j]);
  900.     }
  901.     printf ("n");
  902. }
  903. BOOL pSubInfo[1024];
  904. r.GetSubscription(pSubInfo, pVal);
  905. printf ("    bw %5d: %d %d %d %dn", i,
  906.     pSubInfo[0], pSubInfo[1], pSubInfo[2], pSubInfo[3], pSubInfo[4]);
  907. pVal->Release();
  908.     }
  909.     return 0;
  910. }
  911. #endif
  912. HX_RESULT
  913. ASMRuleBook::InitRulesArray()
  914. {
  915.    if( !m_pValidRulesArray )
  916.    {
  917.       m_pValidRulesArray = new BOOL[ m_unNumRules ];
  918.       if(!m_pValidRulesArray)
  919.       {
  920.           return HXR_OUTOFMEMORY;
  921.       }
  922.       for( int ii=0; ii<m_unNumRules; ii++ )
  923.       {
  924.          m_pValidRulesArray[ii] = TRUE;
  925.       }
  926.    }
  927.    if( !m_pDeletedRulesArray )
  928.    {
  929.       m_pDeletedRulesArray = new BOOL[ m_unNumRules ];
  930.       if(!m_pDeletedRulesArray)
  931.       {
  932.           HX_VECTOR_DELETE(m_pValidRulesArray);
  933.           return HXR_OUTOFMEMORY;
  934.       }
  935.       for( int ii=0; ii<m_unNumRules; ii++ )
  936.       {
  937.          m_pDeletedRulesArray[ii] = FALSE;
  938.       }
  939.    }
  940.    return HXR_OK;
  941. }
  942. HX_RESULT
  943. ASMRuleBook::Enable( UINT16 nRule )
  944. {
  945.    // Allocate and initialized m_pValidRulesArray if necessary.
  946.    if( HXR_OUTOFMEMORY == InitRulesArray() )
  947.    {
  948.        return HXR_OUTOFMEMORY;
  949.    }
  950.    else
  951.    {
  952.        m_pValidRulesArray[nRule] = TRUE;
  953.    }
  954.    return HXR_OK;
  955. }
  956. HX_RESULT
  957. ASMRuleBook::Disable( UINT16 nRule )
  958. {
  959.    // Allocate and initialized m_pValidRulesArray if necessary.
  960.    if( HXR_OUTOFMEMORY == InitRulesArray() )
  961.    {
  962.        return HXR_OUTOFMEMORY;
  963.    }
  964.    else
  965.    {
  966.        m_pValidRulesArray[nRule] = FALSE;
  967.    }
  968.    return HXR_OK;
  969. }
  970. HX_RESULT
  971. ASMRuleBook::ReCompute()
  972. {
  973.    // We should call a Reset function here
  974.    if( HXR_OUTOFMEMORY == Reset() )
  975.    {
  976.        return HXR_OUTOFMEMORY;
  977.    }
  978.    for( int ii=0; ii<m_unNumRules; ii++ )
  979.    {
  980.       if( m_pValidRulesArray[ ii ] == FALSE )
  981.       {
  982.  DeleteRule( ii );
  983.       }
  984.    }
  985.    return HXR_OK;
  986. }
  987. // Remove a rule from the rulebook and 'collapse' the surrounding rules
  988. // to cover the bandwidth range that up to now was covered by this rule.
  989. HX_RESULT
  990. ASMRuleBook::DeleteRule( int uRuleToDel )
  991. {
  992.    int nLeftEdge = 0;
  993.    int nRightEdge = 0;
  994.    ULONG32 uNumActiveRules = 0;
  995.    int ii;
  996.    // The rule should not be greater the max, of course.
  997.    if( uRuleToDel > m_unNumRules )
  998.    {
  999.       return HXR_FAIL;
  1000.    }
  1001.    // Find the "right edge" rule.
  1002.    for( ii=0; ii<m_unNumRules; ii++ )
  1003.    {
  1004.       if( !m_pDeletedRulesArray[ii] && m_pRules[ii].m_pRuleExpression->IsRightEdge() )
  1005.       {
  1006.          nRightEdge = ii;
  1007.  break;
  1008.       }
  1009.    }
  1010.    // Find the "left edge" rule.
  1011.    for( ii=m_unNumRules-1; ii>=0; ii-- )
  1012.    {
  1013.       if( ( m_pDeletedRulesArray[ii] == FALSE ) && ( m_pRules[ ii ].m_pRuleExpression->GetLeft() || m_pRules[ ii ].m_pRuleExpression->GetRight() ) )
  1014.       {
  1015.          nLeftEdge = ii;
  1016.       }
  1017.    }
  1018.    // Determine the number of active rules.
  1019.    for( ii=0; ii<m_unNumRules; ii++ )
  1020.    {
  1021.       if( !m_pDeletedRulesArray[ii] )
  1022.       {
  1023.          uNumActiveRules++;
  1024.       }
  1025.    }
  1026.    // We handle the 3 possible cases separately: 1) Left Edge, 2) Right Edge, 
  1027.    // and 3) Non-Edge.
  1028.    if( uRuleToDel == nLeftEdge )
  1029.    {
  1030.       // Left edge case
  1031.       // Modify the next rule(s) to the right so that it's > value is 0.
  1032.       // But only if this is the only rule covering uRuleToDel's bw range.
  1033.       if( CheckCurrentRangeEmpty( uRuleToDel ) == TRUE )
  1034.       {
  1035.          for( ii=uRuleToDel+1; ii<m_unNumRules; ii++ )
  1036.          {
  1037.             if( !m_pDeletedRulesArray[ ii ] && (
  1038.                 ( m_pRules[ ii ].m_pRuleExpression->GetLeft() == m_pRules[ uRuleToDel ].m_pRuleExpression->GetRight() ) ) )
  1039.             {
  1040.                m_pRules[ ii ].m_pRuleExpression->SetLeft( 0 );
  1041.             }
  1042.          }
  1043.       }
  1044.    }
  1045.    else if( uRuleToDel >= nRightEdge )
  1046.    {
  1047.       // Right edge case
  1048.       // Set the right value (less than x) to infinity
  1049.       // But only if this is the only rule covering uRuleToDel's bw range.
  1050.       if( CheckCurrentRangeEmpty( uRuleToDel ) == TRUE )
  1051.       {
  1052.          for( ii=uRuleToDel-1; ii>=0; ii-- )
  1053.          {
  1054.             if( !m_pDeletedRulesArray[ ii ] && (
  1055.                 ( m_pRules[ ii ].m_pRuleExpression->GetRight() == m_pRules[ uRuleToDel ].m_pRuleExpression->GetRight() ) ) )
  1056.             {
  1057.                m_pRules[ ii ].m_pRuleExpression->SetRight( RULE_VAL_INFINITY );
  1058.             }
  1059.          }
  1060.       }
  1061.    }
  1062.    else if( uRuleToDel > nLeftEdge )
  1063.    {
  1064.       // Non-edge case
  1065.       // Set all "left-adjacent" rules "right-hand" value to nRight.
  1066.       // But only if this is the only rule covering uRuleToDel's bw range.
  1067.       if( CheckCurrentRangeEmpty( uRuleToDel ) == FALSE )
  1068.       {
  1069.          // Determine the value of our right-hand value.
  1070.          int nRight = (int) m_pRules[ uRuleToDel ].m_pRuleExpression->GetRight();
  1071.          for( ii=uRuleToDel-1; ii>=0; ii-- )
  1072.          {
  1073.             if( !m_pDeletedRulesArray[ ii ] && (
  1074.         ( m_pRules[ ii ].m_pRuleExpression->GetRight() == m_pRules[ uRuleToDel ].m_pRuleExpression->GetLeft() ) ) )
  1075.             {
  1076.                m_pRules[ ii ].m_pRuleExpression->SetRight( nRight );
  1077.             }
  1078.          }
  1079.       }
  1080.    }
  1081.    m_pDeletedRulesArray[uRuleToDel] = TRUE;
  1082.    return HXR_OK;
  1083. }
  1084. void
  1085. ASMRuleExpression::SetLeft( int nLeft )
  1086. {
  1087.    int nRight = ((IntegerNode*) ((VariableNode*)m_pHead->m_pRight))->m_Data;
  1088.    if( nRight == 1 )
  1089.    {
  1090.       ((IntegerNode*)(m_pHead->m_pLeft->m_pRight))->m_Data = nLeft;
  1091.    }
  1092. }
  1093. void
  1094. ASMRuleExpression::SetRight( int nRight )
  1095. {
  1096.    int nTmpRight = 0;
  1097.    if( m_pHead && m_pHead->m_pRight )
  1098.    {
  1099.       nTmpRight = ((IntegerNode*) ((VariableNode*)m_pHead->m_pRight))->m_Data;
  1100.    }
  1101.    if( nTmpRight == 1 )
  1102.    {
  1103.       ( (IntegerNode*)((VariableNode*) ((VariableNode*)m_pHead->m_pRight)->m_pRight) )->m_Data = nRight;
  1104.    }
  1105.    else if( nTmpRight != 0 )
  1106.    {
  1107.       ((VariableNode*)m_pHead->m_pRight)->m_Data = (char*)nRight;
  1108.    }
  1109. }
  1110. float
  1111. ASMRuleExpression::GetLeft()
  1112. {
  1113.    int nLeft = 0;
  1114.    int nRight = 0;
  1115.    if( m_pHead && m_pHead->m_pRight )
  1116.    {
  1117.       nRight = ((IntegerNode*) ((VariableNode*)m_pHead->m_pRight))->m_Data;
  1118.    }
  1119.    if( nRight == 1 )
  1120.    {
  1121.       nLeft = ((IntegerNode*) ((VariableNode*)m_pHead->m_pLeft->m_pRight))->m_Data;
  1122.    }
  1123.    return (float)nLeft;
  1124. }
  1125. float
  1126. ASMRuleExpression::GetRight()
  1127. {
  1128.    int nRight = 0;
  1129.    if( m_pHead && m_pHead->m_pRight )
  1130.    {
  1131.       nRight = ((IntegerNode*) ((VariableNode*)(m_pHead->m_pRight)))->m_Data;
  1132.    }
  1133.    if( nRight == 1 )
  1134.    {
  1135.       nRight = ((IntegerNode*) ((VariableNode*)m_pHead->m_pRight->m_pRight))->m_Data;
  1136.    }
  1137.    return (float)nRight;
  1138. }
  1139. int
  1140. ASMRuleExpression::GetOperatorAsInt()
  1141. {
  1142.    return (int) ((OperatorNode*) m_pHead)->m_Data;
  1143. }
  1144. // This function checks to see if the current rule's operator is GREATER or
  1145. // GREATEROREQUAL, both of which would suggest that we are the "right edge"
  1146. // rule.
  1147. BOOL
  1148. ASMRuleExpression::IsRightEdge()
  1149. {
  1150.    if( m_pHead )
  1151.    {
  1152.       switch(((OperatorNode*)m_pHead)->m_Data)
  1153.       {
  1154.   case HX_RE_GREATER:
  1155.   case HX_RE_GREATEREQUAL:
  1156.       return TRUE;
  1157.       break;
  1158.           default:
  1159.       return FALSE;
  1160.       break;
  1161.       }
  1162.    }
  1163.    else
  1164.    {
  1165.       return FALSE;
  1166.    }
  1167. }
  1168. HX_RESULT
  1169. ASMRuleBook::Reset()
  1170. {
  1171.     int i = 0;
  1172.     { //XXXSMPNOW
  1173. BOOL bSeenExpression = 0;
  1174. //printf ("******* Rule %dn", i);
  1175. const char* pRuleBook = m_pRuleBook;
  1176. while (*pRuleBook)
  1177. {
  1178.     char pTemp[2048 + 1];
  1179.     int  n  = 0;
  1180.     BOOL bSingleQuote   = 0;
  1181.     BOOL bDoubleQuote  = 0;
  1182.     for (;((*pRuleBook) && (bDoubleQuote || ((*pRuleBook != ',') && (*pRuleBook != ';')))); pRuleBook++)
  1183.     {
  1184. if ((*pRuleBook == ''') && (!bDoubleQuote))
  1185.     bSingleQuote = !bSingleQuote;
  1186. if ((*pRuleBook == '"') && (!bSingleQuote))
  1187.     bDoubleQuote = !bDoubleQuote;
  1188. // Kill whitespace outside of quotes
  1189. if (bSingleQuote || bDoubleQuote || (
  1190. (*pRuleBook != ' ') &&
  1191. (*pRuleBook != 'n') &&
  1192. (*pRuleBook != 'r') &&
  1193. (*pRuleBook != 't')))
  1194. {
  1195.     pTemp[n++] = *pRuleBook;
  1196.     if (n >= 2048)
  1197.     {
  1198. //printf ("Panic: Rule Property %d too longn", i);
  1199. HX_ASSERT(0);
  1200. break;
  1201.     }
  1202. }
  1203.     }
  1204.     pTemp[n] = 0;
  1205.     if ((*pRuleBook == ',') || (*pRuleBook == ';'))
  1206.     {
  1207. // Rule is Valid!
  1208.      if (*pTemp == '#')
  1209. {
  1210.     // This part of the rule is an expression
  1211.     if (!bSeenExpression)
  1212.     {
  1213. m_pRules[i].SetExpression(pTemp + 1);
  1214. m_pRules[i].Dump();
  1215. bSeenExpression = 1;
  1216. m_ulNumThresholds += m_pRules[i].m_pRuleExpression->GetNumThresholds();
  1217.     }
  1218.     else
  1219.     {
  1220. //printf ("Panic: Two expressions in Rule %dn", i);
  1221. HX_ASSERT(0);
  1222.     }
  1223. }
  1224. else
  1225. {
  1226.                     char *pProp;
  1227.                     char *pValue;
  1228.                     pProp  = pTemp;
  1229.                     pValue = pTemp;
  1230.                     while ((*pValue != '=') && (pValue-pTemp < ((int) strlen(pTemp))))
  1231.                     pValue++;
  1232.                     if (*pValue == '=')
  1233.                     {
  1234.                         *pValue++ = '';
  1235.                     }
  1236.                     else
  1237.                     {
  1238.                         pValue = NULL;
  1239.                     }
  1240.                     if (pValue)
  1241.                     {
  1242.                         IHXBuffer* pBuffer = new CHXBuffer;
  1243.                         if(!pBuffer)
  1244.                         {
  1245.                             return HXR_OUTOFMEMORY;
  1246.                         }
  1247.                         pBuffer->AddRef();
  1248.                         /* Strip Outside Quotes */
  1249.                         if (*pValue == '"')
  1250.                         {
  1251.                             pValue++;
  1252.                             int end = (strlen(pValue) ? strlen(pValue)-1 : 0);
  1253.                             HX_ASSERT(pValue[end] == '"');
  1254.                             pValue[end] = 0;
  1255.                         }
  1256.                         HX_RESULT theErr = 
  1257.                         pBuffer->Set((const unsigned char *)pValue,
  1258.                         strlen(pValue) + 1);
  1259.                         if( theErr == HXR_OUTOFMEMORY )
  1260.                         {
  1261.                             pBuffer->Release();
  1262.                             return theErr;
  1263.                         }
  1264.                         //printf ("Property '%s'--'%s'n", pProp, pValue);
  1265.                         if( m_pRules[i].m_pRuleProps )
  1266.                         {
  1267.                             m_pRules[i].m_pRuleProps->
  1268.                             SetPropertyCString(pProp, pBuffer);
  1269.                         }
  1270.                         pBuffer->Release();
  1271.                     }
  1272. }
  1273. if (*pRuleBook == ';')
  1274. {
  1275.     i++;
  1276.     bSeenExpression = 0;
  1277.                     if (i >= m_unNumRules)
  1278.                     {
  1279.                         break;
  1280.                     }
  1281.     //printf ("******* Rule %dn", i);
  1282. }
  1283. pRuleBook++;
  1284.     }
  1285. }
  1286.     }
  1287.     return InitRulesArray();
  1288. }
  1289. BOOL
  1290. ASMRuleBook::CheckCurrentRangeEmpty( int uRuleToDel )
  1291. {
  1292.     for( int ii=0; ii<m_unNumRules; ii++ )
  1293.     {
  1294.         // But only if this is the only rule covering uRuleToDel's bw range.
  1295.         if( uRuleToDel != ii && !m_pDeletedRulesArray[ ii ] &&
  1296.             ( m_pRules[ ii ].m_pRuleExpression->GetLeft() == m_pRules[ uRuleToDel ].m_pRuleExpression->GetLeft() ) &&
  1297.             ( m_pRules[ ii ].m_pRuleExpression->GetRight() == m_pRules[ uRuleToDel ].m_pRuleExpression->GetRight() ) &&
  1298.             ( m_pRules[ ii ].m_pRuleExpression->GetOperatorAsInt() == m_pRules[ uRuleToDel ].m_pRuleExpression->GetOperatorAsInt() ) )
  1299.         {
  1300.             return FALSE;
  1301.         }
  1302.     }
  1303.     return TRUE;
  1304. }