Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2416 lines
64 KiB

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. QL.CPP
  5. Abstract:
  6. Level 1 Syntax QL Parser
  7. Implements the syntax described in QL_1.BNF. This translates the input
  8. into an RPN stream of tokens.
  9. History:
  10. a-raymcc 21-Jun-96 Created.
  11. mdavis 23-Apr-99 Changed to allow 'group' as a property name
  12. for Raid 47767. Also fixed GetText() for
  13. property comparisons and improved Dump().
  14. --*/
  15. #include "precomp.h"
  16. #include <stdio.h>
  17. #include <errno.h>
  18. #include <math.h>
  19. #include <corepol.h>
  20. #include <genlex.h>
  21. #include <qllex.h>
  22. #include <ql.h>
  23. #include <wbemcomn.h>
  24. #include <wbemutil.h>
  25. #include <genutils.h>
  26. #include <corex.h>
  27. #define trace(x) //printf x
  28. WBEM_WSTR WbemStringAlloc(unsigned long lNumChars)
  29. {
  30. return (WBEM_WSTR)CoTaskMemAlloc(lNumChars+1);
  31. }
  32. void WbemStringFree(WBEM_WSTR String)
  33. {
  34. CoTaskMemFree(String);
  35. }
  36. unsigned long WbemStringLen(const WCHAR* String)
  37. {
  38. return wcslen(String);
  39. }
  40. WBEM_WSTR WbemStringCopy(const WCHAR* String)
  41. {
  42. if(String == NULL) return NULL;
  43. size_t newLength = wcslen(String)+1;
  44. WBEM_WSTR NewString = (WBEM_WSTR)CoTaskMemAlloc(2*newLength);
  45. if(NewString == NULL) return NULL;
  46. StringCchCopyW(NewString, newLength, String);
  47. return NewString;
  48. }
  49. //***************************************************************************
  50. //
  51. // WCHARToDOUBLE
  52. //
  53. // Converts a wchar to a double, but does it using the english locale rather
  54. // than whatever local the process is running in. This allows us to support
  55. // all english queries even on German machines.
  56. //
  57. //***************************************************************************
  58. DOUBLE WCHARToDOUBLE(WCHAR * pConv, bool & bSuccess)
  59. {
  60. bSuccess = false;
  61. if(pConv == NULL)
  62. return 0.0;
  63. VARIANT varTo, varFrom;
  64. VariantInit(&varTo);
  65. varFrom.vt = VT_BSTR;
  66. varFrom.bstrVal = SysAllocString(pConv);
  67. if ( varFrom.bstrVal == NULL )
  68. {
  69. return 0.0;
  70. }
  71. SCODE sc = VariantChangeTypeEx(&varTo, &varFrom, 0x409, 0, VT_R8);
  72. SysFreeString(varFrom.bstrVal);
  73. if ( FAILED(sc) )
  74. {
  75. return 0.0;
  76. }
  77. bSuccess = true;
  78. return varTo.dblVal;
  79. }
  80. CPropertyName::CPropertyName(const CPropertyName& Other)
  81. {
  82. Init();
  83. *this = Other;
  84. }
  85. void CPropertyName::Init()
  86. {
  87. m_lNumElements = 0;
  88. m_lAllocated = 0;
  89. m_aElements = NULL;
  90. m_pvHandle = NULL;
  91. }
  92. void CPropertyName::operator=(const CPropertyName& Other)
  93. {
  94. *this = (const WBEM_PROPERTY_NAME&)Other;
  95. m_pvHandle = Other.m_pvHandle;
  96. }
  97. void CPropertyName::operator=(const WBEM_PROPERTY_NAME& Other)
  98. {
  99. Empty();
  100. if ( Other.m_lNumElements > 0)
  101. {
  102. m_aElements = new WBEM_NAME_ELEMENT[Other.m_lNumElements];
  103. if ( m_aElements == NULL )
  104. {
  105. throw CX_MemoryException();
  106. }
  107. }
  108. m_lAllocated = Other.m_lNumElements;
  109. for( long l=0 ; l < Other.m_lNumElements; l++ )
  110. {
  111. if(Other.m_aElements[l].m_nType == WBEM_NAME_ELEMENT_TYPE_PROPERTY)
  112. {
  113. m_aElements[l].Element.m_wszPropertyName =
  114. WbemStringCopy(Other.m_aElements[l].Element.m_wszPropertyName);
  115. if ( m_aElements[l].Element.m_wszPropertyName == NULL )
  116. {
  117. break;
  118. }
  119. }
  120. else
  121. {
  122. m_aElements[l].Element.m_lArrayIndex =
  123. Other.m_aElements[l].Element.m_lArrayIndex;
  124. }
  125. m_aElements[l].m_nType = Other.m_aElements[l].m_nType;
  126. }
  127. m_lNumElements = l;
  128. if ( m_lNumElements != Other.m_lNumElements )
  129. {
  130. throw CX_MemoryException();
  131. }
  132. }
  133. BOOL CPropertyName::operator==(const WBEM_PROPERTY_NAME& Other)
  134. {
  135. if(m_lNumElements != Other.m_lNumElements)
  136. return FALSE;
  137. for(long l = 0; l < m_lNumElements; l++)
  138. {
  139. if(m_aElements[l].m_nType != Other.m_aElements[l].m_nType)
  140. return FALSE;
  141. if(m_aElements[l].m_nType == WBEM_NAME_ELEMENT_TYPE_PROPERTY)
  142. {
  143. if(wbem_wcsicmp(m_aElements[l].Element.m_wszPropertyName,
  144. Other.m_aElements[l].Element.m_wszPropertyName))
  145. {
  146. return FALSE;
  147. }
  148. }
  149. else
  150. {
  151. if(m_aElements[l].Element.m_lArrayIndex !=
  152. Other.m_aElements[l].Element.m_lArrayIndex)
  153. {
  154. return FALSE;
  155. }
  156. }
  157. }
  158. return TRUE;
  159. }
  160. void CPropertyName::Empty()
  161. {
  162. if ( m_aElements!=NULL )
  163. {
  164. for(long l = 0; l < m_lNumElements; l++)
  165. {
  166. if(m_aElements[l].m_nType == WBEM_NAME_ELEMENT_TYPE_PROPERTY)
  167. {
  168. WbemStringFree(m_aElements[l].Element.m_wszPropertyName);
  169. }
  170. }
  171. delete [] m_aElements;
  172. m_aElements = NULL;
  173. }
  174. m_lNumElements = 0;
  175. m_lAllocated = 0;
  176. m_pvHandle = NULL;
  177. }
  178. LPCWSTR CPropertyName::GetStringAt(long lIndex) const
  179. {
  180. if(m_aElements[lIndex].m_nType == WBEM_NAME_ELEMENT_TYPE_PROPERTY)
  181. {
  182. return m_aElements[lIndex].Element.m_wszPropertyName;
  183. }
  184. else return NULL;
  185. }
  186. void CPropertyName::AddElement(LPCWSTR wszElement)
  187. {
  188. if ( wszElement == NULL )
  189. throw CX_MemoryException();
  190. EnsureAllocated(m_lNumElements+1);
  191. LPWSTR wszTemp = WbemStringCopy(wszElement);
  192. if ( wszTemp == NULL )
  193. {
  194. throw CX_MemoryException();
  195. }
  196. m_aElements[m_lNumElements].m_nType = WBEM_NAME_ELEMENT_TYPE_PROPERTY;
  197. m_aElements[m_lNumElements].Element.m_wszPropertyName = wszTemp;
  198. m_lNumElements++;
  199. }
  200. void CPropertyName::EnsureAllocated(long lElements)
  201. {
  202. if(m_lAllocated < lElements)
  203. {
  204. WBEM_NAME_ELEMENT* pTemp = new WBEM_NAME_ELEMENT[lElements+5];
  205. if (!pTemp)
  206. throw CX_MemoryException();
  207. m_lAllocated = lElements+5;
  208. memcpy(pTemp, m_aElements, sizeof(WBEM_NAME_ELEMENT) * m_lNumElements);
  209. delete [] m_aElements;
  210. m_aElements = pTemp;
  211. }
  212. }
  213. DELETE_ME LPWSTR CPropertyName::GetText()
  214. {
  215. WString wsText;
  216. for(int i = 0; i < m_lNumElements; i++)
  217. {
  218. if(m_aElements[i].m_nType != WBEM_NAME_ELEMENT_TYPE_PROPERTY)
  219. return NULL;
  220. if(i > 0)
  221. wsText += L".";
  222. wsText += m_aElements[i].Element.m_wszPropertyName;
  223. }
  224. return wsText.UnbindPtr();
  225. }
  226. //***************************************************************************
  227. //***************************************************************************
  228. DWORD CAbstractQl1Parser::TranslateIntrinsic(LPCWSTR pFuncName)
  229. {
  230. if (wbem_wcsicmp(pFuncName, L"UPPER") == 0)
  231. return QL1_FUNCTION_UPPER;
  232. if (wbem_wcsicmp(pFuncName, L"LOWER") == 0)
  233. return QL1_FUNCTION_LOWER;
  234. return QL1_FUNCTION_NONE;
  235. }
  236. void CAbstractQl1Parser::InitToken(WBEM_QL1_TOKEN* pToken)
  237. {
  238. pToken->m_lTokenType = QL1_NONE;
  239. pToken->m_PropertyName.m_lNumElements = 0;
  240. pToken->m_PropertyName.m_aElements = NULL;
  241. pToken->m_PropertyName2.m_lNumElements = 0;
  242. pToken->m_PropertyName2.m_aElements = NULL;
  243. VariantInit(&pToken->m_vConstValue);
  244. }
  245. CAbstractQl1Parser::CAbstractQl1Parser(CGenLexSource *pSrc)
  246. {
  247. m_pLexer = new CGenLexer(Ql_1_LexTable, pSrc);
  248. if ( m_pLexer == NULL || GetLastError() == ERROR_NOT_ENOUGH_MEMORY)
  249. {
  250. delete m_pLexer;
  251. throw CX_MemoryException();
  252. }
  253. m_nLine = 0;
  254. m_pTokenText = 0;
  255. m_nCurrentToken = 0;
  256. // Semantic transfer variables.
  257. // ============================
  258. m_nRelOp = 0;
  259. VariantInit(&m_vTypedConst);
  260. m_dwPropFunction = 0;
  261. m_dwConstFunction = 0;
  262. m_PropertyName.m_lNumElements = 0;
  263. m_PropertyName.m_aElements = NULL;
  264. m_PropertyName2.m_lNumElements = 0;
  265. m_PropertyName2.m_aElements = NULL;
  266. m_bPropComp = FALSE;
  267. }
  268. CAbstractQl1Parser::~CAbstractQl1Parser()
  269. {
  270. VariantClear(&m_vTypedConst);
  271. DeletePropertyName();
  272. delete m_pLexer;
  273. }
  274. int CAbstractQl1Parser::Parse(CQl1ParseSink* pSink, int nFlags)
  275. {
  276. m_pSink = pSink;
  277. int nRes = parse(nFlags);
  278. m_pSink = NULL;
  279. return nRes;
  280. }
  281. //***************************************************************************
  282. //
  283. // Next()
  284. //
  285. // Advances to the next token and recognizes keywords, etc.
  286. //
  287. //***************************************************************************
  288. BOOL CAbstractQl1Parser::Next(int nFlags)
  289. {
  290. m_nCurrentToken = m_pLexer->NextToken();
  291. if (m_nCurrentToken == QL_1_TOK_ERROR)
  292. return FALSE;
  293. m_nLine = m_pLexer->GetLineNum();
  294. m_pTokenText = m_pLexer->GetTokenText();
  295. if (m_nCurrentToken == QL_1_TOK_EOF)
  296. m_pTokenText = L"<end of file>";
  297. // Keyword check.
  298. // ==============
  299. if (m_nCurrentToken == QL_1_TOK_IDENT && nFlags != NO_KEYWORDS)
  300. {
  301. if (wbem_wcsicmp(m_pTokenText, L"select") == 0)
  302. m_nCurrentToken = QL_1_TOK_SELECT;
  303. else if (wbem_wcsicmp(m_pTokenText, L"from") == 0)
  304. m_nCurrentToken = QL_1_TOK_FROM;
  305. else if (wbem_wcsicmp(m_pTokenText, L"where") == 0)
  306. m_nCurrentToken = QL_1_TOK_WHERE;
  307. else if (wbem_wcsicmp(m_pTokenText, L"like") == 0)
  308. m_nCurrentToken = QL_1_TOK_LIKE;
  309. else if (nFlags != EXCLUDE_EXPRESSION_KEYWORDS && wbem_wcsicmp(m_pTokenText, L"or") == 0)
  310. m_nCurrentToken = QL_1_TOK_OR;
  311. else if (nFlags != EXCLUDE_EXPRESSION_KEYWORDS && wbem_wcsicmp(m_pTokenText, L"and") == 0)
  312. m_nCurrentToken = QL_1_TOK_AND;
  313. else if (nFlags != EXCLUDE_EXPRESSION_KEYWORDS && wbem_wcsicmp(m_pTokenText, L"not") == 0)
  314. m_nCurrentToken = QL_1_TOK_NOT;
  315. else if (nFlags != EXCLUDE_EXPRESSION_KEYWORDS && wbem_wcsicmp(m_pTokenText, L"IS") == 0)
  316. m_nCurrentToken = QL_1_TOK_IS;
  317. else if (nFlags != EXCLUDE_EXPRESSION_KEYWORDS && wbem_wcsicmp(m_pTokenText, L"NULL") == 0)
  318. m_nCurrentToken = QL_1_TOK_NULL;
  319. else if (wbem_wcsicmp(m_pTokenText, L"WITHIN") == 0)
  320. m_nCurrentToken = QL_1_TOK_WITHIN;
  321. else if (nFlags != EXCLUDE_EXPRESSION_KEYWORDS && wbem_wcsicmp(m_pTokenText, L"ISA") == 0)
  322. m_nCurrentToken = QL_1_TOK_ISA;
  323. else if (nFlags != EXCLUDE_GROUP_KEYWORD && wbem_wcsicmp(m_pTokenText, L"GROUP") == 0)
  324. m_nCurrentToken = QL_1_TOK_GROUP;
  325. else if (wbem_wcsicmp(m_pTokenText, L"BY") == 0)
  326. m_nCurrentToken = QL_1_TOK_BY;
  327. else if (wbem_wcsicmp(m_pTokenText, L"HAVING") == 0)
  328. m_nCurrentToken = QL_1_TOK_HAVING;
  329. else if (nFlags != EXCLUDE_EXPRESSION_KEYWORDS && wbem_wcsicmp(m_pTokenText, L"TRUE") == 0)
  330. m_nCurrentToken = QL_1_TOK_TRUE;
  331. else if (nFlags != EXCLUDE_EXPRESSION_KEYWORDS && wbem_wcsicmp(m_pTokenText, L"FALSE") == 0)
  332. m_nCurrentToken = QL_1_TOK_FALSE;
  333. }
  334. return TRUE;
  335. }
  336. LPCWSTR CAbstractQl1Parser::GetSinglePropertyName()
  337. {
  338. if(m_PropertyName.m_lNumElements < 1)
  339. return NULL;
  340. if(m_PropertyName.m_aElements[0].m_nType != WBEM_NAME_ELEMENT_TYPE_PROPERTY)
  341. return NULL;
  342. return m_PropertyName.m_aElements[0].Element.m_wszPropertyName;
  343. }
  344. void CAbstractQl1Parser::DeletePropertyName()
  345. {
  346. for(long l = 0; l < m_PropertyName.m_lNumElements; l++)
  347. {
  348. if(m_PropertyName.m_aElements[l].m_nType ==
  349. WBEM_NAME_ELEMENT_TYPE_PROPERTY)
  350. {
  351. WbemStringFree(m_PropertyName.m_aElements[l].
  352. Element.m_wszPropertyName);
  353. }
  354. }
  355. delete [] m_PropertyName.m_aElements;
  356. m_PropertyName.m_lNumElements = 0;
  357. m_PropertyName.m_aElements = NULL;
  358. }
  359. int CAbstractQl1Parser::FlipOperator(int nOp)
  360. {
  361. switch(nOp)
  362. {
  363. case QL1_OPERATOR_EQUALS:
  364. return QL1_OPERATOR_EQUALS;
  365. case QL1_OPERATOR_NOTEQUALS:
  366. return QL1_OPERATOR_NOTEQUALS;
  367. case QL1_OPERATOR_GREATER:
  368. return QL1_OPERATOR_LESS;
  369. case QL1_OPERATOR_LESS:
  370. return QL1_OPERATOR_GREATER;
  371. case QL1_OPERATOR_LESSOREQUALS:
  372. return QL1_OPERATOR_GREATEROREQUALS;
  373. case QL1_OPERATOR_GREATEROREQUALS:
  374. return QL1_OPERATOR_LESSOREQUALS;
  375. case QL1_OPERATOR_LIKE:
  376. return QL1_OPERATOR_LIKE;
  377. case QL1_OPERATOR_UNLIKE:
  378. return QL1_OPERATOR_UNLIKE;
  379. case QL1_OPERATOR_ISA:
  380. return QL1_OPERATOR_INV_ISA;
  381. case QL1_OPERATOR_ISNOTA:
  382. return QL1_OPERATOR_INV_ISNOTA;
  383. case QL1_OPERATOR_INV_ISA:
  384. return QL1_OPERATOR_ISA;
  385. case QL1_OPERATOR_INV_ISNOTA:
  386. return QL1_OPERATOR_ISNOTA;
  387. default:
  388. return nOp;
  389. }
  390. }
  391. void CAbstractQl1Parser::AddAppropriateToken(const WBEM_QL1_TOKEN& Token)
  392. {
  393. if(m_bInAggregation)
  394. m_pSink->AddHavingToken(Token);
  395. else
  396. m_pSink->AddToken(Token);
  397. }
  398. //***************************************************************************
  399. //
  400. // <parse> ::= SELECT <prop_list> FROM <classname> WHERE <expr>;
  401. //
  402. //***************************************************************************
  403. // ok
  404. int CAbstractQl1Parser::parse(int nFlags)
  405. {
  406. int nRes;
  407. m_bInAggregation = FALSE;
  408. if(nFlags != JUST_WHERE)
  409. {
  410. m_pLexer->Reset();
  411. // SELECT
  412. // ======
  413. if (!Next())
  414. return LEXICAL_ERROR;
  415. if (m_nCurrentToken != QL_1_TOK_SELECT)
  416. return SYNTAX_ERROR;
  417. if (!Next(EXCLUDE_GROUP_KEYWORD))
  418. return LEXICAL_ERROR;
  419. // <prop_list>
  420. // ===========
  421. if (nRes = prop_list())
  422. return nRes;
  423. // FROM
  424. // ====
  425. if (m_nCurrentToken != QL_1_TOK_FROM)
  426. return SYNTAX_ERROR;
  427. if (!Next())
  428. return LEXICAL_ERROR;
  429. // <classname>
  430. // ===========
  431. if (nRes = class_name())
  432. return nRes;
  433. // <tolerance>
  434. // ===========
  435. if(nRes = tolerance())
  436. return nRes;
  437. }
  438. if(nFlags != NO_WHERE)
  439. {
  440. // WHERE clause.
  441. // =============
  442. if(nRes = opt_where())
  443. return nRes;
  444. // GROUP BY clause
  445. // ===============
  446. if(nRes = opt_aggregation())
  447. return nRes;
  448. }
  449. return SUCCESS;
  450. }
  451. //***************************************************************************
  452. //
  453. // <opt_where> ::= WHERE <expr>;
  454. // <opt_where> ::= <>;
  455. //
  456. //***************************************************************************
  457. int CAbstractQl1Parser::opt_where()
  458. {
  459. int nRes;
  460. if (m_nCurrentToken == QL_1_TOK_EOF || m_nCurrentToken == QL_1_TOK_GROUP)
  461. {
  462. trace(("No WHERE clause\n"));
  463. return SUCCESS;
  464. }
  465. if (m_nCurrentToken != QL_1_TOK_WHERE)
  466. return SYNTAX_ERROR;
  467. if (!Next(EXCLUDE_GROUP_KEYWORD))
  468. return LEXICAL_ERROR;
  469. // <expr>
  470. // ======
  471. if (nRes = expr())
  472. return nRes;
  473. // Verify that the current token is QL_1_TOK_EOF.
  474. // ===============================================
  475. if (m_nCurrentToken != QL_1_TOK_EOF && m_nCurrentToken != QL_1_TOK_GROUP)
  476. return SYNTAX_ERROR;
  477. return SUCCESS;
  478. }
  479. //***************************************************************************
  480. //
  481. // <prop_list> ::= <property_name> <prop_list_2>;
  482. //
  483. //***************************************************************************
  484. int CAbstractQl1Parser::prop_list()
  485. {
  486. int nRes;
  487. if (m_nCurrentToken != QL_1_TOK_ASTERISK &&
  488. m_nCurrentToken != QL_1_TOK_IDENT)
  489. return SYNTAX_ERROR;
  490. if (nRes = property_name())
  491. return nRes;
  492. return prop_list_2();
  493. }
  494. //***************************************************************************
  495. //
  496. // <prop_list_2> ::= COMMA <prop_list>;
  497. // <prop_list_2> ::= <>;
  498. //
  499. //***************************************************************************
  500. int CAbstractQl1Parser::prop_list_2()
  501. {
  502. if (m_nCurrentToken == QL_1_TOK_COMMA)
  503. {
  504. if (!Next(EXCLUDE_GROUP_KEYWORD))
  505. return LEXICAL_ERROR;
  506. return prop_list();
  507. }
  508. return SUCCESS;
  509. }
  510. int CAbstractQl1Parser::parse_property_name(CPropertyName& Prop)
  511. {
  512. int nCount = 0;
  513. Prop.Empty();
  514. try
  515. {
  516. while(m_nCurrentToken == QL_1_TOK_IDENT)
  517. {
  518. // VERY TEMPORARY: See if this is a count query
  519. // that should be forwarded to the repository.
  520. BOOL bSkipNext = FALSE;
  521. if (!wbem_wcsicmp(L"count", m_pTokenText))
  522. {
  523. if (Next() && m_nCurrentToken == QL_1_TOK_OPEN_PAREN)
  524. {
  525. if (!Next() || m_nCurrentToken != QL_1_TOK_ASTERISK)
  526. return LEXICAL_ERROR;
  527. if (!Next() || m_nCurrentToken != QL_1_TOK_CLOSE_PAREN)
  528. return LEXICAL_ERROR;
  529. Prop.AddElement(L"count(*)");
  530. m_pSink->SetCountQuery();
  531. }
  532. else
  533. {
  534. bSkipNext = TRUE;
  535. Prop.AddElement(L"count");
  536. }
  537. }
  538. else
  539. Prop.AddElement(m_pTokenText);
  540. nCount++;
  541. if (!bSkipNext)
  542. {
  543. if(!Next())
  544. return LEXICAL_ERROR;
  545. }
  546. if(m_nCurrentToken != QL_1_TOK_DOT)
  547. break;
  548. if(!Next(EXCLUDE_GROUP_KEYWORD))
  549. return LEXICAL_ERROR;
  550. }
  551. }
  552. catch (CX_MemoryException)
  553. {
  554. return OUT_OF_MEMORY;
  555. }
  556. catch (...)
  557. {
  558. return FAILED;
  559. }
  560. if (nCount)
  561. return SUCCESS;
  562. else
  563. return SYNTAX_ERROR;
  564. }
  565. //***************************************************************************
  566. //
  567. // <property_name> ::= PROPERTY_NAME_STRING;
  568. // <property_name> ::= ASTERISK;
  569. //
  570. //***************************************************************************
  571. int CAbstractQl1Parser::property_name()
  572. {
  573. try
  574. {
  575. if (m_nCurrentToken == QL_1_TOK_ASTERISK)
  576. {
  577. trace(("Asterisk\n"));
  578. if(m_bInAggregation)
  579. m_pSink->AddAllAggregationProperties();
  580. else
  581. m_pSink->AddAllProperties();
  582. if(!Next())
  583. return LEXICAL_ERROR;
  584. return SUCCESS;
  585. }
  586. // Else a list of property names
  587. // =============================
  588. CPropertyName Prop;
  589. int nRes = parse_property_name(Prop);
  590. if(nRes != SUCCESS)
  591. return nRes;
  592. if(m_bInAggregation)
  593. m_pSink->AddAggregationProperty(Prop);
  594. else
  595. m_pSink->AddProperty(Prop);
  596. }
  597. catch (CX_MemoryException)
  598. {
  599. return OUT_OF_MEMORY;
  600. }
  601. catch (...)
  602. {
  603. return FAILED;
  604. }
  605. return SUCCESS;
  606. }
  607. //***************************************************************************
  608. //
  609. // <classname> ::= CLASS_NAME_STRING;
  610. //
  611. //***************************************************************************
  612. int CAbstractQl1Parser::class_name()
  613. {
  614. if (m_nCurrentToken != QL_1_TOK_IDENT)
  615. return SYNTAX_ERROR;
  616. trace(("Class name is %S\n", m_pTokenText));
  617. m_pSink->SetClassName(m_pTokenText);
  618. if (!Next())
  619. return LEXICAL_ERROR;
  620. return SUCCESS;
  621. }
  622. //***************************************************************************
  623. //
  624. // <tolerance> ::= <>;
  625. // <tolerance> ::= WITHIN duration;
  626. //
  627. //***************************************************************************
  628. int CAbstractQl1Parser::tolerance()
  629. {
  630. LPWSTR wszGarbage;
  631. WBEM_QL1_TOLERANCE Tolerance;
  632. if(m_nCurrentToken != QL_1_TOK_WITHIN)
  633. {
  634. Tolerance.m_bExact = TRUE;
  635. m_pSink->SetTolerance(Tolerance);
  636. return SUCCESS;
  637. }
  638. if(!Next())
  639. return LEXICAL_ERROR;
  640. if (m_nCurrentToken == QL_1_TOK_REAL)
  641. {
  642. Tolerance.m_bExact = FALSE;
  643. bool bSuccess;
  644. Tolerance.m_fTolerance = WCHARToDOUBLE(m_pTokenText, bSuccess);
  645. if(Tolerance.m_fTolerance <= 0 || bSuccess == false)
  646. {
  647. return SYNTAX_ERROR;
  648. }
  649. m_pSink->SetTolerance(Tolerance);
  650. Next();
  651. return SUCCESS;
  652. }
  653. else if (m_nCurrentToken == QL_1_TOK_INT)
  654. {
  655. Tolerance.m_bExact = FALSE;
  656. Tolerance.m_fTolerance = wcstol(m_pTokenText, &wszGarbage, 10);
  657. if(Tolerance.m_fTolerance < 0)
  658. {
  659. return SYNTAX_ERROR;
  660. }
  661. m_pSink->SetTolerance(Tolerance);
  662. Next();
  663. return SUCCESS;
  664. }
  665. else
  666. {
  667. return SYNTAX_ERROR;
  668. }
  669. }
  670. //***************************************************************************
  671. //
  672. // <expr> ::= <term> <expr2>;
  673. //
  674. //***************************************************************************
  675. int CAbstractQl1Parser::expr()
  676. {
  677. int nRes;
  678. if (nRes = term())
  679. return nRes;
  680. if (nRes = expr2())
  681. return nRes;
  682. return SUCCESS;
  683. }
  684. //***************************************************************************
  685. //
  686. // <expr2> ::= OR <term> <expr2>;
  687. // <expr2> ::= <>;
  688. //
  689. // Entry: Assumes token OR already current.
  690. // Exit: Advances a token
  691. //
  692. //***************************************************************************
  693. int CAbstractQl1Parser::expr2()
  694. {
  695. int nRes;
  696. while (1)
  697. {
  698. if (m_nCurrentToken == QL_1_TOK_OR)
  699. {
  700. trace(("Token OR\n"));
  701. m_pSink->InOrder(QL1_OR);
  702. if (!Next(EXCLUDE_GROUP_KEYWORD))
  703. return LEXICAL_ERROR;
  704. if (nRes = term())
  705. return nRes;
  706. WBEM_QL1_TOKEN NewTok;
  707. InitToken(&NewTok);
  708. NewTok.m_lTokenType = QL1_OR;
  709. AddAppropriateToken(NewTok);
  710. }
  711. else break;
  712. }
  713. return SUCCESS;
  714. }
  715. //***************************************************************************
  716. //
  717. // <term> ::= <simple_expr> <term2>;
  718. //
  719. //***************************************************************************
  720. int CAbstractQl1Parser::term()
  721. {
  722. int nRes;
  723. if (nRes = simple_expr())
  724. return nRes;
  725. if (nRes = term2())
  726. return nRes;
  727. return SUCCESS;
  728. }
  729. //***************************************************************************
  730. //
  731. // <term2> ::= AND <simple_expr> <term2>;
  732. // <term2> ::= <>;
  733. //
  734. //***************************************************************************
  735. int CAbstractQl1Parser::term2()
  736. {
  737. int nRes;
  738. while (1)
  739. {
  740. if (m_nCurrentToken == QL_1_TOK_AND)
  741. {
  742. trace(("Token AND\n"));
  743. m_pSink->InOrder(QL1_AND);
  744. if (!Next(EXCLUDE_GROUP_KEYWORD))
  745. return LEXICAL_ERROR;
  746. if (nRes = simple_expr())
  747. return nRes;
  748. // Add the AND token.
  749. // ==================
  750. WBEM_QL1_TOKEN NewTok;
  751. InitToken(&NewTok);
  752. NewTok.m_lTokenType = QL1_AND;
  753. AddAppropriateToken(NewTok);
  754. }
  755. else break;
  756. }
  757. return SUCCESS;
  758. }
  759. //***************************************************************************
  760. //
  761. // <simple_expr> ::= NOT <expr>;
  762. // <simple_expr> ::= OPEN_PAREN <expr> CLOSE_PAREN;
  763. // <simple_expr> ::= IDENTIFIER <leading_ident_expr> <finalize>;
  764. // <simple_expr> ::= VARIANT <rel_operator> <trailing_prop_expr> <finalize>;
  765. //
  766. //***************************************************************************
  767. // ok
  768. int CAbstractQl1Parser::simple_expr()
  769. {
  770. int nRes;
  771. // NOT <expr>
  772. // ==========
  773. if (m_nCurrentToken == QL_1_TOK_NOT)
  774. {
  775. trace(("Operator NOT\n"));
  776. if (!Next(EXCLUDE_GROUP_KEYWORD))
  777. return LEXICAL_ERROR;
  778. if (nRes = simple_expr())
  779. return nRes;
  780. WBEM_QL1_TOKEN NewTok;
  781. InitToken(&NewTok);
  782. NewTok.m_lTokenType = QL1_NOT;
  783. AddAppropriateToken(NewTok);
  784. return SUCCESS;
  785. }
  786. // OPEN_PAREN <expr> CLOSE_PAREN
  787. // =============================
  788. else if (m_nCurrentToken == QL_1_TOK_OPEN_PAREN)
  789. {
  790. trace(("Open Paren: Entering subexpression\n"));
  791. if (!Next(EXCLUDE_GROUP_KEYWORD))
  792. return LEXICAL_ERROR;
  793. if (expr())
  794. return SYNTAX_ERROR;
  795. if (m_nCurrentToken != QL_1_TOK_CLOSE_PAREN)
  796. return SYNTAX_ERROR;
  797. trace(("Close paren: Exiting subexpression\n"));
  798. if (!Next())
  799. return LEXICAL_ERROR;
  800. return SUCCESS;
  801. }
  802. // IDENTIFIER <leading_ident_expr> <finalize>
  803. // ==========================================
  804. else if (m_nCurrentToken == QL_1_TOK_IDENT)
  805. {
  806. trace((" Identifier <%S>\n", m_pTokenText));
  807. if(nRes = parse_property_name(m_PropertyName))
  808. return nRes;
  809. if (nRes = leading_ident_expr())
  810. return SYNTAX_ERROR;
  811. return finalize();
  812. }
  813. // <typed_constant> <rel_operator> <trailing_prop_expr> <finalize>
  814. // ======================================================
  815. else if (m_nCurrentToken == QL_1_TOK_INT ||
  816. m_nCurrentToken == QL_1_TOK_REAL ||
  817. m_nCurrentToken == QL_1_TOK_TRUE ||
  818. m_nCurrentToken == QL_1_TOK_FALSE ||
  819. m_nCurrentToken == QL_1_TOK_NULL ||
  820. m_nCurrentToken == QL_1_TOK_QSTRING
  821. )
  822. {
  823. if (nRes = typed_constant())
  824. return nRes;
  825. if (nRes = rel_operator())
  826. return nRes;
  827. // dont allow const followed by isa!
  828. if(m_nRelOp == QL1_OPERATOR_ISA)
  829. return SYNTAX_ERROR;
  830. // Since we always view the token as IDENT <rel> constant, we need
  831. // to invert this operator, e.g. replace > with <
  832. // ================================================================
  833. m_nRelOp = FlipOperator(m_nRelOp);
  834. if (nRes = trailing_prop_expr())
  835. return nRes;
  836. return finalize();
  837. }
  838. return SYNTAX_ERROR;
  839. }
  840. //***************************************************************************
  841. //
  842. // <trailing_prop_expr> ::= IDENTIFIER
  843. //
  844. //***************************************************************************
  845. // ok
  846. int CAbstractQl1Parser::trailing_prop_expr()
  847. {
  848. if (m_nCurrentToken != QL_1_TOK_IDENT)
  849. return SYNTAX_ERROR;
  850. int nRes = parse_property_name(m_PropertyName);
  851. return nRes;
  852. }
  853. //***************************************************************************
  854. //
  855. // <leading_ident_expr> ::= <comp_operator> <trailing_const_expr>;
  856. // <leading_ident_expr> ::= <equiv_operator> <trailing_or_null>;
  857. // <leading_ident_expr> ::= <is_operator> NULL;
  858. //
  859. //***************************************************************************
  860. // ok
  861. int CAbstractQl1Parser::leading_ident_expr()
  862. {
  863. int nRes;
  864. if (SUCCESS == comp_operator())
  865. {
  866. return trailing_const_expr();
  867. }
  868. else if(SUCCESS == equiv_operator())
  869. return trailing_or_null();
  870. nRes = is_operator();
  871. if(nRes != SUCCESS)
  872. return nRes;
  873. if (m_nCurrentToken != QL_1_TOK_NULL)
  874. return LEXICAL_ERROR;
  875. if (Next())
  876. {
  877. V_VT(&m_vTypedConst) = VT_NULL;
  878. return SUCCESS;
  879. }
  880. else
  881. return LEXICAL_ERROR;
  882. }
  883. //***************************************************************************
  884. //
  885. // <trailing_or_null> ::= NULL;
  886. // <trailing_or_null> ::= <trailing_const_expr>;
  887. //
  888. //***************************************************************************
  889. int CAbstractQl1Parser::trailing_or_null()
  890. {
  891. if (m_nCurrentToken == QL_1_TOK_NULL)
  892. {
  893. if (!Next())
  894. return LEXICAL_ERROR;
  895. else
  896. {
  897. V_VT(&m_vTypedConst) = VT_NULL;
  898. return SUCCESS;
  899. }
  900. }
  901. return trailing_const_expr();
  902. }
  903. //***************************************************************************
  904. //
  905. // <trailing_const_expr> ::= IDENTIFIER OPEN_PAREN
  906. // <typed_constant> CLOSE_PAREN;
  907. // <trailing_const_expr> ::= <typed_constant>;
  908. // <trailing_const_expr> ::= <trailing_ident_expr>
  909. //
  910. //***************************************************************************
  911. // ok
  912. int CAbstractQl1Parser::trailing_const_expr()
  913. {
  914. int nRes;
  915. nRes = typed_constant();
  916. if (nRes != SUCCESS)
  917. nRes = trailing_ident_expr();
  918. return nRes;
  919. }
  920. //***************************************************************************
  921. //
  922. // <trailing_ident_expr> ::= <property_name>
  923. //
  924. //***************************************************************************
  925. // ok
  926. int CAbstractQl1Parser::trailing_ident_expr()
  927. {
  928. int nRes = parse_property_name(m_PropertyName2) ;
  929. if (nRes == SUCCESS)
  930. m_bPropComp = TRUE;
  931. return nRes;
  932. }
  933. //***************************************************************************
  934. //
  935. // <finalize> ::= <>;
  936. //
  937. // This composes the QL_LEVEL_1_TOKEN for a simple relational expression,
  938. // complete with any associated intrinsic functions. All of the other
  939. // parse functions help isolate the terms of the expression, but only
  940. // this function builds the token.
  941. //
  942. // To build the token, the following member variables are used:
  943. // m_pPropName
  944. // m_vTypedConst
  945. // m_dwPropFunction
  946. // m_dwConstFunction
  947. // m_nRelOp;
  948. //
  949. // After the token is built, these are cleared/deallocated as appropriate.
  950. // No tokens are consumed and the input is not advanced.
  951. //
  952. //***************************************************************************
  953. int CAbstractQl1Parser::finalize()
  954. {
  955. // At this point, we have all the info needed for a token.
  956. // =======================================================
  957. WBEM_QL1_TOKEN NewTok;
  958. InitToken(&NewTok);
  959. NewTok.m_lTokenType = QL1_OP_EXPRESSION;
  960. VariantInit(&NewTok.m_vConstValue);
  961. memcpy((void*)&NewTok.m_PropertyName,
  962. (void*)(WBEM_PROPERTY_NAME*)&m_PropertyName,
  963. sizeof(WBEM_PROPERTY_NAME));
  964. if (m_bPropComp)
  965. {
  966. NewTok.m_bPropComp = true;
  967. memcpy((void*)&NewTok.m_PropertyName2,
  968. (void*)(WBEM_PROPERTY_NAME*)&m_PropertyName2,
  969. sizeof(WBEM_PROPERTY_NAME));
  970. }
  971. else
  972. {
  973. NewTok.m_bPropComp = false;
  974. if ( FAILED(VariantCopy(&NewTok.m_vConstValue, &m_vTypedConst) ))
  975. {
  976. return OUT_OF_MEMORY;
  977. }
  978. }
  979. NewTok.m_lOperator = m_nRelOp;
  980. NewTok.m_lPropertyFunction = m_dwPropFunction;
  981. NewTok.m_lConstFunction = m_dwConstFunction;
  982. NewTok.m_bQuoted = m_bQuoted;
  983. AddAppropriateToken(NewTok);
  984. // m_PropertyName.m_lNumElements = 0;
  985. // m_PropertyName.m_aElements = NULL;
  986. m_PropertyName.Empty();
  987. m_PropertyName2.Empty();
  988. // Cleanup.
  989. // ========
  990. VariantClear(&m_vTypedConst);
  991. VariantClear(&NewTok.m_vConstValue);
  992. m_nRelOp = 0;
  993. m_dwPropFunction = 0;
  994. m_dwConstFunction = 0;
  995. m_bPropComp = FALSE;
  996. return SUCCESS;
  997. }
  998. //***************************************************************************
  999. //
  1000. // <typed_constant> ::= VARIANT;
  1001. //
  1002. // Ouput: m_vTypedConst is set to the value of the constant. The only
  1003. // supported types are VT_I4, VT_R8 and VT_BSTR.
  1004. //
  1005. //***************************************************************************
  1006. int CAbstractQl1Parser::typed_constant()
  1007. {
  1008. trace((" Typed constant <%S> ", m_pTokenText));
  1009. VariantClear(&m_vTypedConst);
  1010. m_bQuoted = FALSE;
  1011. if (m_nCurrentToken == QL_1_TOK_INT)
  1012. {
  1013. trace((" Integer\n"));
  1014. // Read it in as a 64-bit one
  1015. // ==========================
  1016. __int64 i64;
  1017. unsigned __int64 ui64;
  1018. BOOL b32bits = FALSE;
  1019. if(ReadI64(m_pTokenText, i64))
  1020. {
  1021. // Check if it is within range of I4
  1022. // =================================
  1023. if(i64 >= - (__int64)0x80000000 && i64 <= 0x7FFFFFFF)
  1024. {
  1025. V_VT(&m_vTypedConst) = VT_I4;
  1026. V_I4(&m_vTypedConst) = (long)i64;
  1027. b32bits = TRUE;
  1028. }
  1029. }
  1030. else if(!ReadUI64(m_pTokenText, ui64))
  1031. {
  1032. // Not a valid number
  1033. // ==================
  1034. return LEXICAL_ERROR;
  1035. }
  1036. if(!b32bits)
  1037. {
  1038. // Valid 64-bit number but not 32-bit
  1039. // ==================================
  1040. BSTR bstr = SysAllocString(m_pTokenText);
  1041. if ( bstr == NULL )
  1042. {
  1043. return OUT_OF_MEMORY;
  1044. }
  1045. V_VT(&m_vTypedConst) = VT_BSTR;
  1046. V_BSTR(&m_vTypedConst) = bstr;
  1047. m_bQuoted = FALSE;
  1048. }
  1049. }
  1050. else if (m_nCurrentToken == QL_1_TOK_QSTRING)
  1051. {
  1052. trace((" String\n"));
  1053. BSTR bstr = SysAllocString(m_pTokenText);
  1054. if ( bstr == NULL )
  1055. {
  1056. return OUT_OF_MEMORY;
  1057. }
  1058. V_VT(&m_vTypedConst) = VT_BSTR;
  1059. V_BSTR(&m_vTypedConst) = bstr;
  1060. m_bQuoted = TRUE;
  1061. }
  1062. else if (m_nCurrentToken == QL_1_TOK_REAL)
  1063. {
  1064. trace((" Real\n"));
  1065. V_VT(&m_vTypedConst) = VT_R8;
  1066. bool bSuccess;
  1067. V_R8(&m_vTypedConst) = WCHARToDOUBLE(m_pTokenText, bSuccess);
  1068. if(bSuccess == false)
  1069. return LEXICAL_ERROR;
  1070. }
  1071. else if(m_nCurrentToken == QL_1_TOK_TRUE)
  1072. {
  1073. V_VT(&m_vTypedConst) = VT_BOOL;
  1074. V_BOOL(&m_vTypedConst) = VARIANT_TRUE;
  1075. }
  1076. else if(m_nCurrentToken == QL_1_TOK_FALSE)
  1077. {
  1078. V_VT(&m_vTypedConst) = VT_BOOL;
  1079. V_BOOL(&m_vTypedConst) = VARIANT_FALSE;
  1080. }
  1081. else if (m_nCurrentToken == QL_1_TOK_NULL)
  1082. V_VT(&m_vTypedConst) = VT_NULL;
  1083. // Else, not a typed constant.
  1084. else
  1085. return SYNTAX_ERROR;
  1086. if (!Next())
  1087. return LEXICAL_ERROR;
  1088. return SUCCESS;
  1089. }
  1090. //***************************************************************************
  1091. //
  1092. // <rel_operator> ::= <equiv_operator>;
  1093. // <rel_operator> ::= <comp_operator>;
  1094. //
  1095. //***************************************************************************
  1096. int CAbstractQl1Parser::rel_operator()
  1097. {
  1098. if(SUCCESS == equiv_operator())
  1099. return SUCCESS;
  1100. else if (SUCCESS == comp_operator())
  1101. return SUCCESS;
  1102. else return LEXICAL_ERROR;
  1103. }
  1104. //***************************************************************************
  1105. //
  1106. // <equiv_operator> ::= EQUIV_OPERATOR; // =, !=
  1107. //
  1108. // Output: m_nRelOp is set to the correct operator for a QL_LEVEL_1_TOKEN.
  1109. //
  1110. //***************************************************************************
  1111. int CAbstractQl1Parser::equiv_operator()
  1112. {
  1113. m_nRelOp = 0;
  1114. if (m_nCurrentToken == QL_1_TOK_EQ)
  1115. {
  1116. trace((" REL OP =\n"));
  1117. m_nRelOp = QL_LEVEL_1_TOKEN::OP_EQUAL;
  1118. }
  1119. else if (m_nCurrentToken == QL_1_TOK_NE)
  1120. {
  1121. trace((" REL OP <> (!=) \n"));
  1122. m_nRelOp = QL_LEVEL_1_TOKEN::OP_NOT_EQUAL;
  1123. }
  1124. else
  1125. return SYNTAX_ERROR;
  1126. if (!Next(EXCLUDE_GROUP_KEYWORD))
  1127. return LEXICAL_ERROR;
  1128. return SUCCESS;
  1129. }
  1130. //***************************************************************************
  1131. //
  1132. // <is_operator> ::= IS_OPERATOR; // is, isnot
  1133. //
  1134. // Output: m_nRelOp is set to the correct operator for a QL_LEVEL_1_TOKEN.
  1135. //
  1136. //***************************************************************************
  1137. int CAbstractQl1Parser::is_operator()
  1138. {
  1139. m_nRelOp = 0;
  1140. if (m_nCurrentToken != QL_1_TOK_IS)
  1141. return SYNTAX_ERROR;
  1142. if (!Next())
  1143. return LEXICAL_ERROR;
  1144. if (m_nCurrentToken == QL_1_TOK_NOT)
  1145. {
  1146. m_nRelOp = QL_LEVEL_1_TOKEN::OP_NOT_EQUAL;
  1147. if (!Next())
  1148. return LEXICAL_ERROR;
  1149. trace((" REL OP IS NOT \n"));
  1150. m_nRelOp = QL_LEVEL_1_TOKEN::OP_NOT_EQUAL;
  1151. return SUCCESS;
  1152. }
  1153. else
  1154. {
  1155. trace((" REL OP IS \n"));
  1156. m_nRelOp = QL_LEVEL_1_TOKEN::OP_EQUAL;
  1157. return SUCCESS;
  1158. }
  1159. return SUCCESS;
  1160. }
  1161. //***************************************************************************
  1162. //
  1163. // <comp_operator> ::= COMP_OPERATOR; // <=, >=, <, >, like
  1164. //
  1165. // Output: m_nRelOp is set to the correct operator for a QL_LEVEL_1_TOKEN.
  1166. //
  1167. //***************************************************************************
  1168. int CAbstractQl1Parser::comp_operator()
  1169. {
  1170. m_nRelOp = 0;
  1171. if (m_nCurrentToken == QL_1_TOK_LE)
  1172. {
  1173. trace((" REL OP <=\n"));
  1174. m_nRelOp = QL_LEVEL_1_TOKEN::OP_EQUALorLESSTHAN;
  1175. }
  1176. else if (m_nCurrentToken == QL_1_TOK_LT)
  1177. {
  1178. trace((" REL OP <\n"));
  1179. m_nRelOp = QL_LEVEL_1_TOKEN::OP_LESSTHAN;
  1180. }
  1181. else if (m_nCurrentToken == QL_1_TOK_GE)
  1182. {
  1183. trace((" REL OP >=\n"));
  1184. m_nRelOp = QL_LEVEL_1_TOKEN::OP_EQUALorGREATERTHAN;
  1185. }
  1186. else if (m_nCurrentToken == QL_1_TOK_GT)
  1187. {
  1188. trace((" REL OP >\n"));
  1189. m_nRelOp = QL_LEVEL_1_TOKEN::OP_GREATERTHAN;
  1190. }
  1191. else if (m_nCurrentToken == QL_1_TOK_LIKE)
  1192. {
  1193. trace((" REL OP 'like' \n"));
  1194. m_nRelOp = QL_LEVEL_1_TOKEN::OP_LIKE;
  1195. }
  1196. else if (m_nCurrentToken == QL_1_TOK_ISA)
  1197. {
  1198. trace((" REL OP 'isa' \n"));
  1199. m_nRelOp = QL1_OPERATOR_ISA;
  1200. }
  1201. else
  1202. return SYNTAX_ERROR;
  1203. if (!Next(EXCLUDE_GROUP_KEYWORD))
  1204. return LEXICAL_ERROR;
  1205. return SUCCESS;
  1206. }
  1207. int CAbstractQl1Parser::opt_aggregation()
  1208. {
  1209. if(m_nCurrentToken == QL_1_TOK_EOF)
  1210. return SUCCESS;
  1211. if(m_nCurrentToken != QL_1_TOK_GROUP)
  1212. return SYNTAX_ERROR;
  1213. if (!Next())
  1214. return LEXICAL_ERROR;
  1215. m_pSink->SetAggregated();
  1216. int nRes = aggregation_params();
  1217. if(nRes)
  1218. return nRes;
  1219. if(nRes = opt_having())
  1220. return nRes;
  1221. // Make sure we've reached the end
  1222. // ===============================
  1223. if(m_nCurrentToken != QL_1_TOK_EOF)
  1224. return SYNTAX_ERROR;
  1225. return SUCCESS;
  1226. }
  1227. int CAbstractQl1Parser::aggregation_params()
  1228. {
  1229. int nRes;
  1230. WBEM_QL1_TOLERANCE Exact;
  1231. Exact.m_bExact = TRUE;
  1232. if(m_nCurrentToken == QL_1_TOK_BY)
  1233. {
  1234. if (!Next(EXCLUDE_GROUP_KEYWORD))
  1235. return LEXICAL_ERROR;
  1236. if(nRes = aggregate_by())
  1237. return nRes;
  1238. if(m_nCurrentToken == QL_1_TOK_WITHIN)
  1239. {
  1240. if (!Next())
  1241. return LEXICAL_ERROR;
  1242. if(nRes = aggregate_within())
  1243. return nRes;
  1244. }
  1245. else
  1246. {
  1247. m_pSink->SetAggregationTolerance(Exact);
  1248. }
  1249. }
  1250. else if(m_nCurrentToken == QL_1_TOK_WITHIN)
  1251. {
  1252. if (!Next())
  1253. return LEXICAL_ERROR;
  1254. if(nRes = aggregate_within())
  1255. return nRes;
  1256. if(m_nCurrentToken == QL_1_TOK_BY)
  1257. {
  1258. if (!Next(EXCLUDE_GROUP_KEYWORD))
  1259. return LEXICAL_ERROR;
  1260. if(nRes = aggregate_by())
  1261. return nRes;
  1262. }
  1263. }
  1264. else
  1265. {
  1266. return SYNTAX_ERROR;
  1267. }
  1268. return SUCCESS;
  1269. }
  1270. int CAbstractQl1Parser::aggregate_within()
  1271. {
  1272. WBEM_QL1_TOLERANCE Tolerance;
  1273. Tolerance.m_bExact = FALSE;
  1274. LPWSTR wszGarbage;
  1275. if (m_nCurrentToken == QL_1_TOK_REAL)
  1276. {
  1277. bool bSuccess;
  1278. Tolerance.m_fTolerance = WCHARToDOUBLE(m_pTokenText, bSuccess);
  1279. if(!bSuccess)
  1280. return SYNTAX_ERROR;
  1281. m_pSink->SetAggregationTolerance(Tolerance);
  1282. Next();
  1283. return SUCCESS;
  1284. }
  1285. else if (m_nCurrentToken == QL_1_TOK_INT)
  1286. {
  1287. Tolerance.m_fTolerance = (double)wcstol(m_pTokenText, &wszGarbage, 10);
  1288. m_pSink->SetAggregationTolerance(Tolerance);
  1289. Next();
  1290. return SUCCESS;
  1291. }
  1292. else
  1293. {
  1294. return SYNTAX_ERROR;
  1295. }
  1296. }
  1297. int CAbstractQl1Parser::aggregate_by()
  1298. {
  1299. m_bInAggregation = TRUE;
  1300. int nRes = prop_list();
  1301. m_bInAggregation = FALSE;
  1302. return nRes;
  1303. }
  1304. int CAbstractQl1Parser::opt_having()
  1305. {
  1306. if(m_nCurrentToken == QL_1_TOK_HAVING)
  1307. {
  1308. if(!Next(EXCLUDE_GROUP_KEYWORD))
  1309. return LEXICAL_ERROR;
  1310. m_bInAggregation = TRUE;
  1311. int nRes = expr();
  1312. m_bInAggregation = FALSE;
  1313. return nRes;
  1314. }
  1315. else return SUCCESS;
  1316. }
  1317. //***************************************************************************
  1318. //***************************************************************************
  1319. //
  1320. // class QL1_Parser
  1321. //
  1322. // A derivative of CAbstractQlParser for backward compatibility
  1323. //
  1324. //***************************************************************************
  1325. //
  1326. //
  1327. QL1_Parser::QL1_Parser(CGenLexSource *pSrc)
  1328. : m_pExpression(NULL), CAbstractQl1Parser(pSrc), m_bPartiallyParsed(FALSE)
  1329. {
  1330. m_pExpression = new QL_LEVEL_1_RPN_EXPRESSION;
  1331. if ( m_pExpression == NULL )
  1332. {
  1333. throw CX_MemoryException();
  1334. }
  1335. }
  1336. QL1_Parser::~QL1_Parser()
  1337. {
  1338. delete m_pExpression;
  1339. }
  1340. int QL1_Parser::GetQueryClass(
  1341. LPWSTR pDestBuf,
  1342. int nBufLen
  1343. )
  1344. {
  1345. // Get the underlying parser to parse the first part of the query
  1346. // ==============================================================
  1347. if(!m_bPartiallyParsed)
  1348. {
  1349. int nRes = CAbstractQl1Parser::Parse(m_pExpression, NO_WHERE);
  1350. if(nRes != SUCCESS) return nRes;
  1351. }
  1352. if (!m_pExpression->bsClassName)
  1353. return SYNTAX_ERROR;
  1354. m_bPartiallyParsed = TRUE;
  1355. if(wcslen(m_pExpression->bsClassName) >= (unsigned int)nBufLen)
  1356. return BUFFER_TOO_SMALL;
  1357. StringCchCopyW(pDestBuf, nBufLen, m_pExpression->bsClassName);
  1358. return WBEM_S_NO_ERROR;
  1359. }
  1360. int QL1_Parser::Parse(QL_LEVEL_1_RPN_EXPRESSION **pOutput)
  1361. {
  1362. *pOutput = NULL;
  1363. // Get the underying parser to completely parse the query. If
  1364. // GetQueryClass was called in the past, no sense in duplcating
  1365. // the work
  1366. // ============================================================
  1367. QL_LEVEL_1_RPN_EXPRESSION* pTemp = NULL;
  1368. try
  1369. {
  1370. pTemp = new QL_LEVEL_1_RPN_EXPRESSION;
  1371. }
  1372. catch (CX_MemoryException)
  1373. {
  1374. return OUT_OF_MEMORY;
  1375. }
  1376. if ( pTemp == NULL )
  1377. {
  1378. return OUT_OF_MEMORY;
  1379. }
  1380. int nRes = CAbstractQl1Parser::Parse(m_pExpression,
  1381. m_bPartiallyParsed?JUST_WHERE:FULL_PARSE);
  1382. if ( nRes == SUCCESS )
  1383. {
  1384. *pOutput = m_pExpression;
  1385. m_pExpression = pTemp;
  1386. m_bPartiallyParsed = FALSE;
  1387. }
  1388. else
  1389. {
  1390. delete pTemp;
  1391. }
  1392. return nRes;
  1393. }
  1394. DELETE_ME LPWSTR QL1_Parser::ReplaceClassName(QL_LEVEL_1_RPN_EXPRESSION* pExpr,
  1395. LPCWSTR wszClassName)
  1396. {
  1397. QL_LEVEL_1_RPN_EXPRESSION NewExpr(*pExpr);
  1398. if (NewExpr.bsClassName)
  1399. SysFreeString(NewExpr.bsClassName);
  1400. NewExpr.bsClassName = SysAllocString(wszClassName);
  1401. if ( NewExpr.bsClassName == NULL )
  1402. {
  1403. return NULL;
  1404. }
  1405. LPWSTR wszNewQuery = NewExpr.GetText();
  1406. return wszNewQuery;
  1407. }
  1408. //***************************************************************************
  1409. //
  1410. // Expression and token structure methods.
  1411. //
  1412. //***************************************************************************
  1413. QL_LEVEL_1_RPN_EXPRESSION::QL_LEVEL_1_RPN_EXPRESSION()
  1414. {
  1415. nNumTokens = 0;
  1416. bsClassName = 0;
  1417. bCount = FALSE;
  1418. nNumberOfProperties = 0;
  1419. bStar = FALSE;
  1420. pRequestedPropertyNames = 0;
  1421. nCurSize = 1;
  1422. nCurPropSize = 1;
  1423. pArrayOfTokens = new QL_LEVEL_1_TOKEN[nCurSize];
  1424. pRequestedPropertyNames = new CPropertyName[nCurPropSize];
  1425. bAggregated = FALSE;
  1426. bAggregateAll = FALSE;
  1427. nNumAggregatedProperties = 0;
  1428. nCurAggPropSize = 1;
  1429. pAggregatedPropertyNames = new CPropertyName[nCurAggPropSize];
  1430. nNumHavingTokens = 0;
  1431. nCurHavingSize = 1;
  1432. pArrayOfHavingTokens = new QL_LEVEL_1_TOKEN[nCurHavingSize];
  1433. if ( pArrayOfTokens == NULL || pRequestedPropertyNames == NULL ||
  1434. pAggregatedPropertyNames == NULL || pArrayOfHavingTokens == NULL )
  1435. {
  1436. delete [] pArrayOfTokens;
  1437. delete [] pRequestedPropertyNames;
  1438. delete [] pAggregatedPropertyNames;
  1439. delete [] pArrayOfHavingTokens;
  1440. throw CX_MemoryException();
  1441. }
  1442. lRefCount = 0;
  1443. }
  1444. QL_LEVEL_1_RPN_EXPRESSION::QL_LEVEL_1_RPN_EXPRESSION(
  1445. const QL_LEVEL_1_RPN_EXPRESSION& Other)
  1446. {
  1447. nNumTokens = Other.nNumTokens;
  1448. nNumberOfProperties = Other.nNumberOfProperties;
  1449. bStar = Other.bStar;
  1450. bCount = Other.bCount;
  1451. pRequestedPropertyNames = 0;
  1452. nCurSize = Other.nCurSize;
  1453. nCurPropSize = Other.nCurPropSize;
  1454. bAggregated = Other.bAggregated;
  1455. bAggregateAll = Other.bAggregateAll;
  1456. nNumAggregatedProperties = Other.nNumAggregatedProperties;
  1457. nCurAggPropSize = Other.nCurAggPropSize;
  1458. nNumHavingTokens = Other.nNumHavingTokens;
  1459. nCurHavingSize = Other.nCurHavingSize;
  1460. bsClassName = SysAllocString(Other.bsClassName);
  1461. pArrayOfTokens = new QL_LEVEL_1_TOKEN[nCurSize];
  1462. pRequestedPropertyNames = new CPropertyName[nCurPropSize];
  1463. pAggregatedPropertyNames = new CPropertyName[nCurAggPropSize];
  1464. pArrayOfHavingTokens = new QL_LEVEL_1_TOKEN[nCurHavingSize];
  1465. if ( pArrayOfTokens == NULL || pRequestedPropertyNames == NULL ||
  1466. pAggregatedPropertyNames == NULL || pArrayOfHavingTokens == NULL ||
  1467. bsClassName == NULL )
  1468. {
  1469. delete [] pArrayOfTokens;
  1470. delete [] pRequestedPropertyNames;
  1471. delete [] pAggregatedPropertyNames;
  1472. delete [] pArrayOfHavingTokens;
  1473. if ( bsClassName != NULL ) SysFreeString( bsClassName );
  1474. throw CX_MemoryException();
  1475. }
  1476. int i;
  1477. for(i = 0; i < nNumTokens; i++)
  1478. pArrayOfTokens[i] = Other.pArrayOfTokens[i];
  1479. for(i = 0; i < nNumberOfProperties; i++)
  1480. pRequestedPropertyNames[i] = Other.pRequestedPropertyNames[i];
  1481. for(i = 0; i < nNumAggregatedProperties; i++)
  1482. pAggregatedPropertyNames[i] = Other.pAggregatedPropertyNames[i];
  1483. for(i = 0; i < nNumHavingTokens; i++)
  1484. pArrayOfHavingTokens[i] = Other.pArrayOfHavingTokens[i];
  1485. lRefCount = 0;
  1486. }
  1487. void QL_LEVEL_1_RPN_EXPRESSION::AddRef()
  1488. {
  1489. InterlockedIncrement(&lRefCount);
  1490. }
  1491. void QL_LEVEL_1_RPN_EXPRESSION::Release()
  1492. {
  1493. if(InterlockedDecrement(&lRefCount) == 0)
  1494. delete this;
  1495. }
  1496. QL_LEVEL_1_RPN_EXPRESSION::~QL_LEVEL_1_RPN_EXPRESSION()
  1497. {
  1498. delete [] pArrayOfTokens;
  1499. if (bsClassName)
  1500. SysFreeString(bsClassName);
  1501. delete [] pAggregatedPropertyNames;
  1502. delete [] pArrayOfHavingTokens;
  1503. delete [] pRequestedPropertyNames;
  1504. }
  1505. void QL_LEVEL_1_RPN_EXPRESSION::SetClassName(LPCWSTR wszClassName)
  1506. {
  1507. if ( bsClassName != NULL )
  1508. {
  1509. SysFreeString( bsClassName );
  1510. }
  1511. bsClassName = SysAllocString(wszClassName);
  1512. if ( bsClassName == NULL )
  1513. {
  1514. throw CX_MemoryException();
  1515. }
  1516. }
  1517. void QL_LEVEL_1_RPN_EXPRESSION::SetTolerance(
  1518. const WBEM_QL1_TOLERANCE& _Tolerance)
  1519. {
  1520. Tolerance = _Tolerance;
  1521. }
  1522. void QL_LEVEL_1_RPN_EXPRESSION::SetAggregationTolerance(
  1523. const WBEM_QL1_TOLERANCE& _Tolerance)
  1524. {
  1525. AggregationTolerance = _Tolerance;
  1526. }
  1527. void QL_LEVEL_1_RPN_EXPRESSION::AddToken(const WBEM_QL1_TOKEN& Tok)
  1528. {
  1529. if (nCurSize == nNumTokens)
  1530. {
  1531. nCurSize += 1;
  1532. nCurSize *= 2;
  1533. QL_LEVEL_1_TOKEN *pTemp = new QL_LEVEL_1_TOKEN[nCurSize];
  1534. if ( pTemp == NULL )
  1535. {
  1536. throw CX_MemoryException();
  1537. }
  1538. for (int i = 0; i < nNumTokens; i++)
  1539. pTemp[i] = pArrayOfTokens[i];
  1540. delete [] pArrayOfTokens;
  1541. pArrayOfTokens = pTemp;
  1542. }
  1543. pArrayOfTokens[nNumTokens++] = Tok;
  1544. }
  1545. void QL_LEVEL_1_RPN_EXPRESSION::AddToken(const QL_LEVEL_1_TOKEN& Tok)
  1546. {
  1547. if (nCurSize == nNumTokens)
  1548. {
  1549. nCurSize += 1;
  1550. nCurSize *= 2;
  1551. QL_LEVEL_1_TOKEN *pTemp = new QL_LEVEL_1_TOKEN[nCurSize];
  1552. if ( pTemp == NULL )
  1553. {
  1554. throw CX_MemoryException();
  1555. }
  1556. for (int i = 0; i < nNumTokens; i++)
  1557. pTemp[i] = pArrayOfTokens[i];
  1558. delete [] pArrayOfTokens;
  1559. pArrayOfTokens = pTemp;
  1560. }
  1561. pArrayOfTokens[nNumTokens++] = Tok;
  1562. }
  1563. void QL_LEVEL_1_RPN_EXPRESSION::AddHavingToken(
  1564. const WBEM_QL1_TOKEN& Tok)
  1565. {
  1566. if (nCurHavingSize == nNumHavingTokens)
  1567. {
  1568. nCurHavingSize += 1;
  1569. nCurHavingSize *= 2;
  1570. QL_LEVEL_1_TOKEN *pTemp = new QL_LEVEL_1_TOKEN[nCurHavingSize];
  1571. if ( pTemp == NULL )
  1572. {
  1573. throw CX_MemoryException();
  1574. }
  1575. for (int i = 0; i < nNumHavingTokens; i++)
  1576. pTemp[i] = pArrayOfHavingTokens[i];
  1577. delete [] pArrayOfHavingTokens;
  1578. pArrayOfHavingTokens = pTemp;
  1579. }
  1580. pArrayOfHavingTokens[nNumHavingTokens++] = Tok;
  1581. }
  1582. void QL_LEVEL_1_RPN_EXPRESSION::AddProperty(const CPropertyName& Prop)
  1583. {
  1584. if (nCurPropSize == nNumberOfProperties)
  1585. {
  1586. nCurPropSize += 1;
  1587. nCurPropSize *= 2;
  1588. CPropertyName *pTemp = new CPropertyName[nCurPropSize];
  1589. if (!pTemp)
  1590. throw CX_MemoryException();
  1591. for(int i = 0; i < nNumberOfProperties; i++)
  1592. pTemp[i] = pRequestedPropertyNames[i];
  1593. delete [] pRequestedPropertyNames;
  1594. pRequestedPropertyNames = pTemp;
  1595. }
  1596. pRequestedPropertyNames[nNumberOfProperties++] = Prop;
  1597. }
  1598. void QL_LEVEL_1_RPN_EXPRESSION::AddAllProperties()
  1599. {
  1600. bStar = TRUE;
  1601. }
  1602. void QL_LEVEL_1_RPN_EXPRESSION::SetCountQuery()
  1603. {
  1604. bCount = TRUE;
  1605. }
  1606. void QL_LEVEL_1_RPN_EXPRESSION::SetAggregated()
  1607. {
  1608. bAggregated = TRUE;
  1609. }
  1610. void QL_LEVEL_1_RPN_EXPRESSION::AddAggregationProperty(
  1611. const CPropertyName& Property)
  1612. {
  1613. if(pAggregatedPropertyNames == NULL)
  1614. {
  1615. // '*' requested
  1616. return;
  1617. }
  1618. if (nCurAggPropSize == nNumAggregatedProperties)
  1619. {
  1620. nCurAggPropSize += 1;
  1621. nCurAggPropSize *= 2;
  1622. CPropertyName *pTemp = new CPropertyName[nCurAggPropSize];
  1623. if ( pTemp == NULL )
  1624. {
  1625. throw CX_MemoryException();
  1626. }
  1627. for(int i = 0; i < nNumAggregatedProperties; i++)
  1628. pTemp[i] = pAggregatedPropertyNames[i];
  1629. delete [] pAggregatedPropertyNames;
  1630. pAggregatedPropertyNames = pTemp;
  1631. }
  1632. pAggregatedPropertyNames[nNumAggregatedProperties++] = Property;
  1633. }
  1634. void QL_LEVEL_1_RPN_EXPRESSION::AddAllAggregationProperties()
  1635. {
  1636. bAggregateAll = TRUE;
  1637. }
  1638. DELETE_ME LPWSTR QL_LEVEL_1_RPN_EXPRESSION::GetText()
  1639. {
  1640. WString wsText;
  1641. wsText += L"select ";
  1642. for(int i = 0; i < nNumberOfProperties; i++)
  1643. {
  1644. if(i != 0) wsText += L", ";
  1645. wsText += (LPWSTR)pRequestedPropertyNames[i].GetStringAt(0);
  1646. }
  1647. if(bStar)
  1648. {
  1649. if(nNumberOfProperties > 0)
  1650. wsText += L", ";
  1651. wsText += L"*";
  1652. }
  1653. wsText += L" from ";
  1654. if (bsClassName)
  1655. wsText += bsClassName;
  1656. if(nNumTokens > 0)
  1657. {
  1658. wsText += L" where ";
  1659. CWStringArray awsStack;
  1660. for(int i = 0; i < nNumTokens; i++)
  1661. {
  1662. QL_LEVEL_1_TOKEN& Token = pArrayOfTokens[i];
  1663. LPWSTR wszTokenText = Token.GetText();
  1664. if(wszTokenText == NULL)
  1665. return NULL;
  1666. if(Token.nTokenType == QL1_OP_EXPRESSION)
  1667. {
  1668. awsStack.Add(wszTokenText);
  1669. delete [] wszTokenText;
  1670. }
  1671. else if(Token.nTokenType == QL1_NOT)
  1672. {
  1673. LPWSTR wszLast = awsStack[awsStack.Size()-1];
  1674. WString wsNew;
  1675. wsNew += wszTokenText;
  1676. delete [] wszTokenText;
  1677. wsNew += L" (";
  1678. wsNew += wszLast;
  1679. wsNew += L")";
  1680. awsStack.RemoveAt(awsStack.Size()-1); //pop
  1681. awsStack.Add(wsNew);
  1682. }
  1683. else
  1684. {
  1685. if(awsStack.Size() < 2) return NULL;
  1686. LPWSTR wszLast = awsStack[awsStack.Size()-1];
  1687. LPWSTR wszPrev = awsStack[awsStack.Size()-2];
  1688. WString wsNew;
  1689. wsNew += L"(";
  1690. wsNew += wszPrev;
  1691. wsNew += L" ";
  1692. wsNew += wszTokenText;
  1693. delete [] wszTokenText;
  1694. wsNew += L" ";
  1695. wsNew += wszLast;
  1696. wsNew += L")";
  1697. awsStack.RemoveAt(awsStack.Size()-1); //pop
  1698. awsStack.RemoveAt(awsStack.Size()-1); //pop
  1699. awsStack.Add(wsNew);
  1700. }
  1701. }
  1702. if(awsStack.Size() != 1) return NULL;
  1703. wsText += awsStack[0];
  1704. }
  1705. return wsText.UnbindPtr();
  1706. }
  1707. void QL_LEVEL_1_RPN_EXPRESSION::Dump(const char *pszTextFile)
  1708. {
  1709. FILE *f = fopen(pszTextFile, "wt");
  1710. if (!f)
  1711. return;
  1712. fprintf(f, "----RPN Expression----\n");
  1713. fprintf(f, "Class name = %S\n", bsClassName);
  1714. fprintf(f, "Properties selected: ");
  1715. if (!nNumberOfProperties)
  1716. {
  1717. fprintf(f, "* = all properties selected\n");
  1718. }
  1719. else for (int i = 0; i < nNumberOfProperties; i++)
  1720. {
  1721. fprintf(f, "%S ", pRequestedPropertyNames[i].GetStringAt(0));
  1722. }
  1723. fprintf(f, "\n------------------\n");
  1724. fprintf(f, "Tokens:\n");
  1725. for (int i = 0; i < nNumTokens; i++)
  1726. pArrayOfTokens[i].Dump(f);
  1727. fprintf(f, "---end of expression---\n");
  1728. fclose(f);
  1729. }
  1730. QL_LEVEL_1_TOKEN::QL_LEVEL_1_TOKEN()
  1731. {
  1732. nTokenType = 0;
  1733. nOperator = 0;
  1734. VariantInit(&vConstValue);
  1735. dwPropertyFunction = 0;
  1736. dwConstFunction = 0;
  1737. bQuoted = TRUE;
  1738. m_bPropComp = FALSE;
  1739. }
  1740. QL_LEVEL_1_TOKEN::QL_LEVEL_1_TOKEN(const QL_LEVEL_1_TOKEN &Src)
  1741. {
  1742. nTokenType = 0;
  1743. nOperator = 0;
  1744. VariantInit(&vConstValue);
  1745. dwPropertyFunction = 0;
  1746. dwConstFunction = 0;
  1747. bQuoted = TRUE;
  1748. m_bPropComp = FALSE;
  1749. *this = Src;
  1750. }
  1751. QL_LEVEL_1_TOKEN& QL_LEVEL_1_TOKEN::operator =(const QL_LEVEL_1_TOKEN &Src)
  1752. {
  1753. if ( FAILED(VariantCopy(&vConstValue, (VARIANT*)&Src.vConstValue)) )
  1754. {
  1755. throw CX_MemoryException();
  1756. }
  1757. nTokenType = Src.nTokenType;
  1758. PropertyName = Src.PropertyName;
  1759. if (Src.m_bPropComp)
  1760. PropertyName2 = Src.PropertyName2;
  1761. nOperator = Src.nOperator;
  1762. dwPropertyFunction = Src.dwPropertyFunction;
  1763. dwConstFunction = Src.dwConstFunction;
  1764. bQuoted = Src.bQuoted;
  1765. m_bPropComp = Src.m_bPropComp;
  1766. return *this;
  1767. }
  1768. QL_LEVEL_1_TOKEN& QL_LEVEL_1_TOKEN::operator =(const WBEM_QL1_TOKEN &Src)
  1769. {
  1770. if ( FAILED(VariantCopy(&vConstValue, (VARIANT*)&Src.m_vConstValue) ) )
  1771. {
  1772. throw CX_MemoryException();
  1773. }
  1774. nTokenType = Src.m_lTokenType;
  1775. PropertyName = Src.m_PropertyName;
  1776. if (Src.m_bPropComp)
  1777. PropertyName2 = Src.m_PropertyName2;
  1778. nOperator = Src.m_lOperator;
  1779. dwPropertyFunction = Src.m_lPropertyFunction;
  1780. dwConstFunction = Src.m_lConstFunction;
  1781. bQuoted = Src.m_bQuoted;
  1782. m_bPropComp = Src.m_bPropComp;
  1783. return *this;
  1784. }
  1785. QL_LEVEL_1_TOKEN::~QL_LEVEL_1_TOKEN()
  1786. {
  1787. nTokenType = 0;
  1788. nOperator = 0;
  1789. VariantClear(&vConstValue);
  1790. }
  1791. DELETE_ME LPWSTR QL_LEVEL_1_TOKEN::GetText()
  1792. {
  1793. WString wsText;
  1794. wmilib::auto_buffer<WCHAR> wszPropName;
  1795. switch (nTokenType)
  1796. {
  1797. case OP_EXPRESSION:
  1798. wszPropName.reset(PropertyName.GetText());
  1799. if(NULL == wszPropName.get()) return NULL;
  1800. wsText += wszPropName.get();
  1801. wsText += L" ";
  1802. WCHAR* wszOp;
  1803. switch (nOperator)
  1804. {
  1805. case OP_EQUAL: wszOp = L"="; break;
  1806. case OP_NOT_EQUAL: wszOp = L"<>"; break;
  1807. case OP_EQUALorGREATERTHAN: wszOp = L">="; break;
  1808. case OP_EQUALorLESSTHAN: wszOp = L"<="; break;
  1809. case OP_LESSTHAN: wszOp = L"<"; break;
  1810. case OP_GREATERTHAN: wszOp = L">"; break;
  1811. case OP_LIKE: wszOp = L"LIKE"; break;
  1812. case QL1_OPERATOR_ISA: wszOp = L"ISA"; break;
  1813. default: wszOp = NULL;
  1814. }
  1815. if(wszOp)
  1816. wsText += wszOp;
  1817. wsText += L" ";
  1818. if (m_bPropComp)
  1819. {
  1820. // property comparison (e.g., prop1 > prop2)
  1821. wszPropName.reset(PropertyName2.GetText());
  1822. if(NULL == wszPropName.get()) return NULL;
  1823. wsText += wszPropName.get();
  1824. }
  1825. else
  1826. {
  1827. // expression with constant (e.g., prop1 > 5)
  1828. WCHAR wszConst[100];
  1829. switch (V_VT(&vConstValue))
  1830. {
  1831. case VT_NULL:
  1832. wsText += L"NULL";
  1833. break;
  1834. case VT_I4:
  1835. StringCchPrintfW(wszConst, 100 , L"%d", V_I4(&vConstValue));
  1836. wsText += wszConst;
  1837. break;
  1838. case VT_I2:
  1839. StringCchPrintfW(wszConst, 100, L"%d", (int)V_I2(&vConstValue));
  1840. wsText += wszConst;
  1841. break;
  1842. case VT_UI1:
  1843. StringCchPrintfW(wszConst, 100, L"%d", (int)V_UI1(&vConstValue));
  1844. wsText += wszConst;
  1845. break;
  1846. case VT_BSTR:
  1847. {
  1848. if(bQuoted)
  1849. wsText += L"\"";
  1850. //If we need to parse the string we do it the hard way
  1851. WCHAR* pwc = V_BSTR(&vConstValue);
  1852. BOOL bLongMethod = FALSE;
  1853. for (int tmp = 0; pwc[tmp]; tmp++)
  1854. if ((pwc[tmp] == L'\\') || (pwc[tmp] == L'"'))
  1855. bLongMethod = TRUE;
  1856. if (bLongMethod)
  1857. {
  1858. for(pwc; *pwc; pwc++)
  1859. {
  1860. if(*pwc == L'\\' || *pwc == L'"')
  1861. wsText += L'\\';
  1862. wsText += *pwc;
  1863. }
  1864. }
  1865. else
  1866. {
  1867. //otherwise we do it the fast way...
  1868. wsText += pwc;
  1869. }
  1870. if(bQuoted)
  1871. wsText += L"\"";
  1872. }
  1873. break;
  1874. case VT_R4:
  1875. StringCchPrintfW(wszConst, 100, L"%G", V_R4(&vConstValue));
  1876. wsText += wszConst;
  1877. break;
  1878. case VT_R8:
  1879. StringCchPrintfW(wszConst, 100, L"%lG", V_R8(&vConstValue));
  1880. wsText += wszConst;
  1881. break;
  1882. case VT_BOOL:
  1883. wsText += (V_BOOL(&vConstValue)?L"TRUE":L"FALSE");
  1884. break;
  1885. }
  1886. }
  1887. break;
  1888. case TOKEN_AND:
  1889. wsText = "AND";
  1890. break;
  1891. case TOKEN_OR:
  1892. wsText = "OR";
  1893. break;
  1894. case TOKEN_NOT:
  1895. wsText = "NOT";
  1896. break;
  1897. }
  1898. return wsText.UnbindPtr();
  1899. }
  1900. void QL_LEVEL_1_TOKEN::Dump(FILE *f)
  1901. {
  1902. switch (nTokenType)
  1903. {
  1904. case OP_EXPRESSION:
  1905. fprintf(f, "OP_EXPRESSION ");
  1906. break;
  1907. case TOKEN_AND:
  1908. fprintf(f, "TOKEN_AND ");
  1909. break;
  1910. case TOKEN_OR:
  1911. fprintf(f, "TOKEN_OR ");
  1912. break;
  1913. case TOKEN_NOT:
  1914. fprintf(f, "TOKEN_NOT ");
  1915. break;
  1916. default:
  1917. fprintf(f, "Error: no token type specified\n");
  1918. }
  1919. if (nTokenType == OP_EXPRESSION)
  1920. {
  1921. char *pOp = "<no op>";
  1922. switch (nOperator)
  1923. {
  1924. case OP_EQUAL: pOp = "OP_EQUAL"; break;
  1925. case OP_NOT_EQUAL: pOp = "OP_NOT_EQUAL"; break;
  1926. case OP_EQUALorGREATERTHAN: pOp = "OP_EQUALorGREATERTHAN"; break;
  1927. case OP_EQUALorLESSTHAN: pOp = "OP_EQUALorLESSTHAN"; break;
  1928. case OP_LESSTHAN: pOp = "OP_LESSTHAN"; break;
  1929. case OP_GREATERTHAN: pOp = "OP_GREATERTHAN"; break;
  1930. case OP_LIKE: pOp = "OP_LIKE"; break;
  1931. }
  1932. LPWSTR wszPropName = PropertyName.GetText();
  1933. if(wszPropName == NULL)
  1934. return;
  1935. fprintf(f, " Property = %S\n", wszPropName);
  1936. delete [] wszPropName;
  1937. fprintf(f, " Operator = %s\n", pOp);
  1938. fprintf(f, " Value = ");
  1939. if (m_bPropComp)
  1940. {
  1941. wszPropName = PropertyName2.GetText();
  1942. if(wszPropName == NULL)
  1943. return;
  1944. fprintf(f, " <Property:%S>\n", wszPropName);
  1945. delete [] wszPropName;
  1946. }
  1947. else
  1948. {
  1949. switch (V_VT(&vConstValue))
  1950. {
  1951. case VT_I4:
  1952. fprintf(f, "VT_I4 = %d\n", V_I4(&vConstValue));
  1953. break;
  1954. case VT_I2:
  1955. fprintf(f, "VT_I2 = %d\n", (int)V_I2(&vConstValue));
  1956. break;
  1957. case VT_UI1:
  1958. fprintf(f, "VT_UI1 = %d\n", (int)V_UI1(&vConstValue));
  1959. break;
  1960. case VT_BSTR:
  1961. fprintf(f, "VT_BSTR = %S\n", V_BSTR(&vConstValue));
  1962. break;
  1963. case VT_R4:
  1964. fprintf(f, "VT_R4 = %f\n", V_R4(&vConstValue));
  1965. break;
  1966. case VT_R8:
  1967. fprintf(f, "VT_R8 = %f\n", V_R8(&vConstValue));
  1968. break;
  1969. case VT_BOOL:
  1970. fprintf(f, "%S\n", V_BOOL(&vConstValue)?L"TRUE":L"FALSE");
  1971. break;
  1972. case VT_NULL:
  1973. fprintf(f, "%S\n", L"NULL");
  1974. break;
  1975. default:
  1976. fprintf(f, "<unknown>\n");
  1977. }
  1978. switch (dwPropertyFunction)
  1979. {
  1980. case IFUNC_NONE:
  1981. break;
  1982. case IFUNC_LOWER:
  1983. fprintf(f, "Intrinsic function LOWER() applied to property\n");
  1984. break;
  1985. case IFUNC_UPPER:
  1986. fprintf(f, "Intrinsic function UPPER() applied to property\n");
  1987. break;
  1988. }
  1989. switch (dwConstFunction)
  1990. {
  1991. case IFUNC_NONE:
  1992. break;
  1993. case IFUNC_LOWER:
  1994. fprintf(f, "Intrinsic function LOWER() applied to const value\n");
  1995. break;
  1996. case IFUNC_UPPER:
  1997. fprintf(f, "Intrinsic function UPPER() applied to const value\n");
  1998. break;
  1999. }
  2000. }
  2001. }
  2002. fprintf(f, " <end of token>\n");
  2003. }
  2004. /////////////////////////////////////////////////////////////////////////////
  2005. //
  2006. // Algorithm for evaluating the expression, assuming that it has been
  2007. // tokenized and translated to Reverse Polish.
  2008. //
  2009. // Starting point: (a) An array of QL tokens.
  2010. // (b) An empty boolean token stack.
  2011. //
  2012. // 1. Read Next Token
  2013. //
  2014. // 2. If a SIMPLE EXPRESSION, evaluate it to TRUE or FALSE, and
  2015. // place this boolean result on the stack. Go to 1.
  2016. //
  2017. // 3. If an OR operator, then pop a boolean token into A,
  2018. // pop another boolean token into B. If either A or B are TRUE,
  2019. // stack TRUE. Else stack FALSE.
  2020. // Go to 1.
  2021. //
  2022. // 4. If an AND operator, then pop a boolean token into A,
  2023. // and pop another into B. If both are TRUE, stack TRUE.
  2024. // Else stack FALSE.
  2025. // Go to 1.
  2026. //
  2027. // 5. If a NOT operator, reverse the value of the top-of-stack boolean.
  2028. // Go to 1.
  2029. //
  2030. // At end-of-input, the result is at top-of-stack.
  2031. //
  2032. /////////////////////////////////////////////////////////////////////////////