Source code of Windows XP (NT5)
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.

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