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.

2258 lines
58 KiB

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