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

1598 lines
40 KiB

  1. /*++
  2. Copyright Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. SQL_1.CPP
  5. Abstract:
  6. Level 1 Syntax SQL Parser
  7. Implements the syntax described in SQL_1.BNF. This translates the input
  8. into an RPN stream of tokens.
  9. History:
  10. 21-Jun-96 Created.
  11. --*/
  12. #include "precomp.h"
  13. #include <genlex.h>
  14. #include <sqllex.h>
  15. #include <sql_1.h>
  16. #include <autoptr.h>
  17. class CX_Exception {};
  18. class CX_MemoryException : public CX_Exception {};
  19. #define trace(x)
  20. static DWORD TranslateIntrinsic(LPWSTR pFuncName)
  21. {
  22. if (wbem_wcsicmp(pFuncName, L"UPPER") == 0)
  23. return SQL_LEVEL_1_TOKEN::IFUNC_UPPER;
  24. if (wbem_wcsicmp(pFuncName, L"LOWER") == 0)
  25. return SQL_LEVEL_1_TOKEN::IFUNC_LOWER;
  26. return SQL_LEVEL_1_TOKEN::IFUNC_NONE;
  27. }
  28. SQL1_Parser::SQL1_Parser(CGenLexSource *pSrc)
  29. {
  30. Init(pSrc);
  31. }
  32. SQL1_Parser::~SQL1_Parser()
  33. {
  34. Cleanup();
  35. }
  36. void SQL1_Parser::Init(CGenLexSource *pSrc)
  37. {
  38. m_nLine = 0;
  39. m_pTokenText = 0;
  40. m_nCurrentToken = 0;
  41. m_pExpression = 0;
  42. m_pLexer = 0;
  43. // Semantic transfer variables.
  44. // ============================
  45. m_nRelOp = 0;
  46. VariantInit(&m_vTypedConst);
  47. m_dwPropFunction = 0;
  48. m_dwConstFunction = 0;
  49. m_pIdent = 0;
  50. m_pPropComp = 0;
  51. m_bConstIsStrNumeric = FALSE;
  52. if (pSrc)
  53. {
  54. wmilib::auto_ptr<CGenLexer> t_pLexer ( new CGenLexer(Sql_1_LexTable, pSrc) );
  55. if (! t_pLexer.get())
  56. throw CX_MemoryException();
  57. wmilib::auto_ptr<SQL_LEVEL_1_RPN_EXPRESSION> t_pExpression ( new SQL_LEVEL_1_RPN_EXPRESSION ) ;
  58. if (! t_pExpression.get())
  59. throw CX_MemoryException();
  60. m_pLexer = t_pLexer.release () ;
  61. m_pExpression = t_pExpression.release () ;
  62. }
  63. }
  64. void SQL1_Parser::Cleanup()
  65. {
  66. VariantClear(&m_vTypedConst);
  67. delete m_pIdent;
  68. delete m_pPropComp;
  69. delete m_pLexer;
  70. delete m_pExpression;
  71. }
  72. void SQL1_Parser::SetSource(CGenLexSource *pSrc)
  73. {
  74. Cleanup();
  75. Init(pSrc);
  76. }
  77. int SQL1_Parser::GetQueryClass(
  78. LPWSTR pDestBuf,
  79. int nBufLen
  80. )
  81. {
  82. if ((!m_pLexer) || (!pDestBuf))
  83. {
  84. return FAILED;
  85. }
  86. // Scan until 'FROM' and then get the class name.
  87. // ==============================================
  88. for (;;)
  89. {
  90. m_nCurrentToken = m_pLexer->NextToken();
  91. if (m_nCurrentToken == SQL_1_TOK_EOF)
  92. {
  93. m_pLexer->Reset();
  94. return FAILED;
  95. }
  96. if (wbem_wcsicmp(m_pLexer->GetTokenText(), L"from") == 0)
  97. {
  98. m_nCurrentToken = m_pLexer->NextToken();
  99. if (m_nCurrentToken != SQL_1_TOK_IDENT)
  100. {
  101. m_pLexer->Reset();
  102. return FAILED;
  103. }
  104. // If here, we have the class name.
  105. // ================================
  106. if (wcslen(m_pLexer->GetTokenText()) >= (size_t)nBufLen)
  107. {
  108. m_pLexer->Reset();
  109. return BUFFER_TOO_SMALL;
  110. }
  111. StringCchCopyW(pDestBuf,nBufLen, m_pLexer->GetTokenText());
  112. break;
  113. }
  114. }
  115. // Reset the scanner.
  116. // ==================
  117. m_pLexer->Reset();
  118. return SUCCESS;
  119. }
  120. int SQL1_Parser::Parse(SQL_LEVEL_1_RPN_EXPRESSION **pOutput)
  121. {
  122. if ((!m_pLexer) || (!pOutput))
  123. {
  124. return FAILED;
  125. }
  126. *pOutput = 0;
  127. int nRes = parse();
  128. if (nRes)
  129. return nRes;
  130. *pOutput = m_pExpression;
  131. m_pExpression = 0;
  132. return SUCCESS;
  133. }
  134. //***************************************************************************
  135. //
  136. // Next()
  137. //
  138. // Advances to the next token and recognizes keywords, etc.
  139. //
  140. //***************************************************************************
  141. BOOL SQL1_Parser::Next()
  142. {
  143. m_nCurrentToken = m_pLexer->NextToken();
  144. if (m_nCurrentToken == SQL_1_TOK_ERROR)
  145. return FALSE;
  146. m_nLine = m_pLexer->GetLineNum();
  147. m_pTokenText = m_pLexer->GetTokenText();
  148. if (m_nCurrentToken == SQL_1_TOK_EOF)
  149. m_pTokenText = L"<end of file>";
  150. // Keyword check.
  151. // ==============
  152. if (m_nCurrentToken == SQL_1_TOK_IDENT)
  153. {
  154. if (wbem_wcsicmp(m_pTokenText, L"select") == 0)
  155. m_nCurrentToken = SQL_1_TOK_SELECT;
  156. else if (wbem_wcsicmp(m_pTokenText, L"from") == 0)
  157. m_nCurrentToken = SQL_1_TOK_FROM;
  158. else if (wbem_wcsicmp(m_pTokenText, L"where") == 0)
  159. m_nCurrentToken = SQL_1_TOK_WHERE;
  160. else if (wbem_wcsicmp(m_pTokenText, L"like") == 0)
  161. m_nCurrentToken = SQL_1_TOK_LIKE;
  162. else if (wbem_wcsicmp(m_pTokenText, L"or") == 0)
  163. m_nCurrentToken = SQL_1_TOK_OR;
  164. else if (wbem_wcsicmp(m_pTokenText, L"and") == 0)
  165. m_nCurrentToken = SQL_1_TOK_AND;
  166. else if (wbem_wcsicmp(m_pTokenText, L"not") == 0)
  167. m_nCurrentToken = SQL_1_TOK_NOT;
  168. else if (wbem_wcsicmp(m_pTokenText, L"IS") == 0)
  169. m_nCurrentToken = SQL_1_TOK_IS;
  170. else if (wbem_wcsicmp(m_pTokenText, L"NULL") == 0)
  171. m_nCurrentToken = SQL_1_TOK_NULL;
  172. else if (wbem_wcsicmp(m_pTokenText, L"TRUE") == 0)
  173. {
  174. m_nCurrentToken = SQL_1_TOK_BOOL;
  175. m_pTokenText = L"65535";
  176. }
  177. else if (wbem_wcsicmp(m_pTokenText, L"FALSE") == 0)
  178. {
  179. m_nCurrentToken = SQL_1_TOK_BOOL;
  180. m_pTokenText = L"0";
  181. }
  182. }
  183. return TRUE;
  184. }
  185. //***************************************************************************
  186. //
  187. // <parse> ::= SELECT <prop_list> FROM <classname> WHERE <expr>;
  188. //
  189. //***************************************************************************
  190. // ok
  191. int SQL1_Parser::parse()
  192. {
  193. int nRes;
  194. // SELECT
  195. // ======
  196. if (!Next())
  197. return LEXICAL_ERROR;
  198. if (m_nCurrentToken != SQL_1_TOK_SELECT)
  199. return SYNTAX_ERROR;
  200. if (!Next())
  201. return LEXICAL_ERROR;
  202. // <prop_list>
  203. // ===========
  204. if (nRes = prop_list())
  205. return nRes;
  206. // FROM
  207. // ====
  208. if (m_nCurrentToken != SQL_1_TOK_FROM)
  209. return SYNTAX_ERROR;
  210. if (!Next())
  211. return LEXICAL_ERROR;
  212. // <classname>
  213. // ===========
  214. if (nRes = class_name())
  215. return nRes;
  216. // WHERE clause.
  217. // =============
  218. return opt_where();
  219. }
  220. //***************************************************************************
  221. //
  222. // <opt_where> ::= WHERE <expr>;
  223. // <opt_where> ::= <>;
  224. //
  225. //***************************************************************************
  226. int SQL1_Parser::opt_where()
  227. {
  228. int nRes;
  229. if (m_nCurrentToken == SQL_1_TOK_EOF)
  230. {
  231. trace(("No WHERE clause\n"));
  232. return SUCCESS;
  233. }
  234. if (m_nCurrentToken != SQL_1_TOK_WHERE)
  235. return SYNTAX_ERROR;
  236. if (!Next())
  237. return LEXICAL_ERROR;
  238. // <expr>
  239. // ======
  240. if (nRes = expr())
  241. return nRes;
  242. // Verify that the current token is SQL_1_TOK_EOF.
  243. // ===============================================
  244. if (m_nCurrentToken != SQL_1_TOK_EOF)
  245. return SYNTAX_ERROR;
  246. return SUCCESS;
  247. }
  248. //***************************************************************************
  249. //
  250. // <prop_list> ::= <property_name> <prop_list_2>;
  251. //
  252. //***************************************************************************
  253. int SQL1_Parser::prop_list()
  254. {
  255. int nRes;
  256. if (m_nCurrentToken != SQL_1_TOK_ASTERISK &&
  257. m_nCurrentToken != SQL_1_TOK_IDENT)
  258. return SYNTAX_ERROR;
  259. if (nRes = property_name())
  260. return nRes;
  261. if (!Next())
  262. return LEXICAL_ERROR;
  263. return prop_list_2();
  264. }
  265. //***************************************************************************
  266. //
  267. // <prop_list_2> ::= COMMA <prop_list>;
  268. // <prop_list_2> ::= <>;
  269. //
  270. //***************************************************************************
  271. int SQL1_Parser::prop_list_2()
  272. {
  273. if (m_nCurrentToken == SQL_1_TOK_COMMA)
  274. {
  275. if (!Next())
  276. return LEXICAL_ERROR;
  277. return prop_list();
  278. }
  279. return SUCCESS;
  280. }
  281. //***************************************************************************
  282. //
  283. // <property_name> ::= PROPERTY_NAME_STRING;
  284. // <property_name> ::= ASTERISK;
  285. //
  286. //***************************************************************************
  287. int SQL1_Parser::property_name()
  288. {
  289. try
  290. {
  291. if (m_nCurrentToken == SQL_1_TOK_ASTERISK)
  292. {
  293. trace(("Asterisk\n"));
  294. // We need to clean up the expression so far.
  295. for (int i = 0; i < m_pExpression->nNumberOfProperties; i++)
  296. SysFreeString(m_pExpression->pbsRequestedPropertyNames[i]);
  297. m_pExpression->nNumberOfProperties = 0;
  298. // This signals 'all properties' to the evaluator
  299. return SUCCESS;
  300. }
  301. // Else a property name.
  302. // =====================
  303. trace(("Property name %S\n", m_pTokenText));
  304. m_pExpression->AddProperty(m_pTokenText);
  305. }
  306. catch (...)
  307. {
  308. return FAILED;
  309. }
  310. return SUCCESS;
  311. }
  312. //***************************************************************************
  313. //
  314. // <classname> ::= CLASS_NAME_STRING;
  315. //
  316. //***************************************************************************
  317. int SQL1_Parser::class_name()
  318. {
  319. if (m_nCurrentToken != SQL_1_TOK_IDENT)
  320. return SYNTAX_ERROR;
  321. trace(("Class name is %S\n", m_pTokenText));
  322. m_pExpression->bsClassName = SysAllocString(m_pTokenText);
  323. if ( ! m_pExpression->bsClassName )
  324. {
  325. throw CX_MemoryException();
  326. }
  327. if (!Next())
  328. return LEXICAL_ERROR;
  329. return SUCCESS;
  330. }
  331. //***************************************************************************
  332. //
  333. // <expr> ::= <term> <expr2>;
  334. //
  335. //***************************************************************************
  336. int SQL1_Parser::expr()
  337. {
  338. int nRes;
  339. if (nRes = term())
  340. return nRes;
  341. if (nRes = expr2())
  342. return nRes;
  343. return SUCCESS;
  344. }
  345. //***************************************************************************
  346. //
  347. // <expr2> ::= OR <term> <expr2>;
  348. // <expr2> ::= <>;
  349. //
  350. // Entry: Assumes token OR already current.
  351. // Exit: Advances a token
  352. //
  353. //***************************************************************************
  354. int SQL1_Parser::expr2()
  355. {
  356. int nRes;
  357. while (1)
  358. {
  359. if (m_nCurrentToken == SQL_1_TOK_OR)
  360. {
  361. trace(("Token OR\n"));
  362. if (!Next())
  363. return LEXICAL_ERROR;
  364. if (nRes = term())
  365. return nRes;
  366. SQL_LEVEL_1_TOKEN *pNewTok = new SQL_LEVEL_1_TOKEN;
  367. if ( ! pNewTok )
  368. throw CX_MemoryException();
  369. pNewTok->nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_OR;
  370. m_pExpression->AddToken(pNewTok);
  371. }
  372. else break;
  373. }
  374. return SUCCESS;
  375. }
  376. //***************************************************************************
  377. //
  378. // <term> ::= <simple_expr> <term2>;
  379. //
  380. //***************************************************************************
  381. int SQL1_Parser::term()
  382. {
  383. int nRes;
  384. if (nRes = simple_expr())
  385. return nRes;
  386. if (nRes = term2())
  387. return nRes;
  388. return SUCCESS;
  389. }
  390. //***************************************************************************
  391. //
  392. // <term2> ::= AND <simple_expr> <term2>;
  393. // <term2> ::= <>;
  394. //
  395. //***************************************************************************
  396. int SQL1_Parser::term2()
  397. {
  398. int nRes;
  399. while (1)
  400. {
  401. if (m_nCurrentToken == SQL_1_TOK_AND)
  402. {
  403. trace(("Token AND\n"));
  404. if (!Next())
  405. return LEXICAL_ERROR;
  406. if (nRes = simple_expr())
  407. return nRes;
  408. // Add the AND token.
  409. // ==================
  410. SQL_LEVEL_1_TOKEN *pNewTok = new SQL_LEVEL_1_TOKEN;
  411. if ( ! pNewTok )
  412. {
  413. throw CX_MemoryException();
  414. }
  415. pNewTok->nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_AND;
  416. m_pExpression->AddToken(pNewTok);
  417. }
  418. else break;
  419. }
  420. return SUCCESS;
  421. }
  422. //***************************************************************************
  423. //
  424. // <simple_expr> ::= NOT <expr>;
  425. // <simple_expr> ::= OPEN_PAREN <expr> CLOSE_PAREN;
  426. // <simple_expr> ::= IDENTIFIER <leading_ident_expr> <finalize>;
  427. // <simple_expr> ::= VARIANT <rel_operator> <trailing_prop_expr> <finalize>;
  428. //
  429. //***************************************************************************
  430. // ok
  431. int SQL1_Parser::simple_expr()
  432. {
  433. int nRes;
  434. // NOT <expr>
  435. // ==========
  436. if (m_nCurrentToken == SQL_1_TOK_NOT)
  437. {
  438. trace(("Operator NOT\n"));
  439. if (!Next())
  440. return LEXICAL_ERROR;
  441. if (nRes = simple_expr())
  442. return nRes;
  443. SQL_LEVEL_1_TOKEN *pNewTok = new SQL_LEVEL_1_TOKEN;
  444. if ( ! pNewTok )
  445. {
  446. throw CX_MemoryException();
  447. }
  448. pNewTok->nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_NOT;
  449. m_pExpression->AddToken(pNewTok);
  450. return SUCCESS;
  451. }
  452. // OPEN_PAREN <expr> CLOSE_PAREN
  453. // =============================
  454. else if (m_nCurrentToken == SQL_1_TOK_OPEN_PAREN)
  455. {
  456. trace(("Open Paren: Entering subexpression\n"));
  457. if (!Next())
  458. return LEXICAL_ERROR;
  459. if (expr())
  460. return SYNTAX_ERROR;
  461. if (m_nCurrentToken != SQL_1_TOK_CLOSE_PAREN)
  462. return SYNTAX_ERROR;
  463. trace(("Close paren: Exiting subexpression\n"));
  464. if (!Next())
  465. return LEXICAL_ERROR;
  466. return SUCCESS;
  467. }
  468. // IDENTIFIER <leading_ident_expr> <finalize>
  469. // ==========================================
  470. else if (m_nCurrentToken == SQL_1_TOK_IDENT)
  471. {
  472. trace((" Identifier <%S>\n", m_pTokenText));
  473. size_t cchTmp = wcslen(m_pTokenText) + 1;
  474. m_pIdent = new wchar_t[cchTmp];
  475. if ( ! m_pIdent )
  476. {
  477. throw CX_MemoryException();
  478. }
  479. StringCchCopyW(m_pIdent,cchTmp, m_pTokenText);
  480. if (!Next())
  481. return LEXICAL_ERROR;
  482. if (nRes = leading_ident_expr())
  483. return SYNTAX_ERROR;
  484. return finalize();
  485. }
  486. // <typed_constant> <rel_operator> <trailing_prop_expr> <finalize>
  487. // ======================================================
  488. else if (m_nCurrentToken == SQL_1_TOK_INT ||
  489. m_nCurrentToken == SQL_1_TOK_REAL ||
  490. m_nCurrentToken == SQL_1_TOK_QSTRING
  491. )
  492. {
  493. if (nRes = typed_constant())
  494. return nRes;
  495. if (nRes = rel_operator())
  496. return nRes;
  497. if (nRes = trailing_prop_expr())
  498. return nRes;
  499. return finalize();
  500. }
  501. return SYNTAX_ERROR;
  502. }
  503. //***************************************************************************
  504. //
  505. // <trailing_prop_expr> ::= IDENTIFIER <trailing_prop_expr2>;
  506. //
  507. //***************************************************************************
  508. // ok
  509. int SQL1_Parser::trailing_prop_expr()
  510. {
  511. if (m_nCurrentToken != SQL_1_TOK_IDENT)
  512. return SYNTAX_ERROR;
  513. if (!m_pIdent)
  514. {
  515. size_t cchTmp = wcslen(m_pTokenText) + 1;
  516. m_pIdent = new wchar_t[cchTmp];
  517. if ( ! m_pIdent )
  518. {
  519. throw CX_MemoryException();
  520. }
  521. StringCchCopyW(m_pIdent,cchTmp, m_pTokenText);
  522. }
  523. else
  524. {
  525. size_t cchTmp = wcslen(m_pTokenText) + 1;
  526. m_pPropComp = new wchar_t[cchTmp];
  527. if ( ! m_pPropComp )
  528. {
  529. throw CX_MemoryException();
  530. }
  531. StringCchCopyW(m_pPropComp,cchTmp, m_pTokenText);
  532. }
  533. if (!Next())
  534. return LEXICAL_ERROR;
  535. return trailing_prop_expr2();
  536. }
  537. //***************************************************************************
  538. //
  539. // <trailing_prop_expr2> ::= OPEN_PAREN IDENTIFIER CLOSE_PAREN;
  540. // <trailing_prop_expr2> ::= <>;
  541. //
  542. //***************************************************************************
  543. // ok
  544. int SQL1_Parser::trailing_prop_expr2()
  545. {
  546. if (m_nCurrentToken == SQL_1_TOK_OPEN_PAREN)
  547. {
  548. if (!Next())
  549. return LEXICAL_ERROR;
  550. // If we got to this point, the string pointed to by m_pIdent
  551. // was an intrinsic function and not a property name, and we
  552. // are about to get the property name, so we have to translate
  553. // the function name to its correct code before overwriting it.
  554. // ============================================================
  555. trace(("Translating intrinsic function %S\n", m_pIdent));
  556. m_dwPropFunction = TranslateIntrinsic(m_pIdent);
  557. delete m_pIdent;
  558. size_t cchTmp = wcslen(m_pTokenText) + 1;
  559. m_pIdent = new wchar_t[cchTmp];
  560. if ( ! m_pIdent )
  561. {
  562. throw CX_MemoryException();
  563. }
  564. StringCchCopyW(m_pIdent,cchTmp, m_pTokenText);
  565. if (!Next())
  566. return LEXICAL_ERROR;
  567. if (m_nCurrentToken != SQL_1_TOK_CLOSE_PAREN)
  568. return SYNTAX_ERROR;
  569. if (!Next())
  570. return LEXICAL_ERROR;
  571. }
  572. trace(("Property name is %S\n", m_pIdent));
  573. return SUCCESS;
  574. }
  575. //***************************************************************************
  576. //
  577. // <leading_ident_expr> ::= OPEN_PAREN <unknown_func_expr>;
  578. // <leading_ident_expr> ::= <comp_operator> <trailing_const_expr>;
  579. // <leading_ident_expr> ::= <equiv_operator> <trailing_or_null>;
  580. // <leading_ident_expr> ::= <is_operator> NULL;
  581. //
  582. //***************************************************************************
  583. // ok
  584. int SQL1_Parser::leading_ident_expr()
  585. {
  586. int nRes;
  587. if (m_nCurrentToken == SQL_1_TOK_OPEN_PAREN)
  588. {
  589. if (!Next())
  590. return LEXICAL_ERROR;
  591. return unknown_func_expr();
  592. }
  593. if (SUCCESS == comp_operator() || SUCCESS == equiv_operator())
  594. return trailing_or_null();
  595. nRes = is_operator();
  596. if(nRes != SUCCESS)
  597. return nRes;
  598. if (m_nCurrentToken != SQL_1_TOK_NULL)
  599. return LEXICAL_ERROR;
  600. if (Next())
  601. {
  602. V_VT(&m_vTypedConst) = VT_NULL;
  603. return SUCCESS;
  604. }
  605. else
  606. return LEXICAL_ERROR;
  607. }
  608. //***************************************************************************
  609. //
  610. // <unknown_func_expr> ::= IDENTIFIER CLOSE_PAREN
  611. // <rel_operator> <trailing_const_expr>;
  612. //
  613. // <unknown_func_expr> ::= <typed_constant> CLOSE_PAREN
  614. // <rel_operator> <trailing_prop_expr>;
  615. //
  616. //***************************************************************************
  617. // ok
  618. int SQL1_Parser::unknown_func_expr()
  619. {
  620. int nRes;
  621. if (m_nCurrentToken == SQL_1_TOK_IDENT)
  622. {
  623. m_dwPropFunction = TranslateIntrinsic(m_pIdent);
  624. delete m_pIdent;
  625. size_t cchTmp = wcslen(m_pTokenText) + 1;
  626. m_pIdent = new wchar_t[cchTmp];
  627. if ( ! m_pIdent )
  628. {
  629. throw CX_MemoryException();
  630. }
  631. StringCchCopyW(m_pIdent,cchTmp, m_pTokenText);
  632. if (!Next())
  633. return LEXICAL_ERROR;
  634. if (m_nCurrentToken != SQL_1_TOK_CLOSE_PAREN)
  635. return SYNTAX_ERROR;
  636. if (!Next())
  637. return LEXICAL_ERROR;
  638. if (nRes = rel_operator())
  639. return nRes;
  640. return trailing_const_expr();
  641. }
  642. // Else the other production.
  643. // ==========================
  644. if (nRes = typed_constant())
  645. return nRes;
  646. // If here, we know that the leading ident was
  647. // an intrinsic function.
  648. // ===========================================
  649. m_dwConstFunction = TranslateIntrinsic(m_pIdent);
  650. delete m_pIdent;
  651. m_pIdent = 0;
  652. if (m_nCurrentToken != SQL_1_TOK_CLOSE_PAREN)
  653. return SYNTAX_ERROR;
  654. if (!Next())
  655. return LEXICAL_ERROR;
  656. if (nRes = rel_operator())
  657. return nRes;
  658. return trailing_prop_expr();
  659. }
  660. //***************************************************************************
  661. //
  662. // <trailing_or_null> ::= NULL;
  663. // <trailing_or_null> ::= <trailing_const_expr>;
  664. // <trailing_or_null> ::= <trailing_prop_expr>;
  665. //
  666. //***************************************************************************
  667. int SQL1_Parser::trailing_or_null()
  668. {
  669. int nRes;
  670. if (m_nCurrentToken == SQL_1_TOK_NULL)
  671. {
  672. if (!Next())
  673. return LEXICAL_ERROR;
  674. else
  675. {
  676. V_VT(&m_vTypedConst) = VT_NULL;
  677. return SUCCESS;
  678. }
  679. }
  680. else if (!(nRes = trailing_const_expr()))
  681. return nRes;
  682. return trailing_prop_expr();
  683. }
  684. //***************************************************************************
  685. //
  686. // <trailing_const_expr> ::= IDENTIFIER OPEN_PAREN
  687. // <typed_constant> CLOSE_PAREN;
  688. // <trailing_const_expr> ::= <typed_constant>;
  689. //
  690. //***************************************************************************
  691. // ok
  692. int SQL1_Parser::trailing_const_expr()
  693. {
  694. int nRes;
  695. if (m_nCurrentToken == SQL_1_TOK_IDENT)
  696. {
  697. trace(("Function applied to typed const = %S\n", m_pTokenText));
  698. m_dwConstFunction = TranslateIntrinsic(m_pTokenText);
  699. if (!m_dwConstFunction)
  700. return SYNTAX_ERROR;
  701. if (!Next())
  702. return LEXICAL_ERROR;
  703. if (m_nCurrentToken != SQL_1_TOK_OPEN_PAREN)
  704. return SYNTAX_ERROR;
  705. if (!Next())
  706. return LEXICAL_ERROR;
  707. if (nRes = typed_constant())
  708. return nRes;
  709. if (m_nCurrentToken != SQL_1_TOK_CLOSE_PAREN)
  710. return SYNTAX_ERROR;
  711. if (!Next())
  712. return LEXICAL_ERROR;
  713. return SUCCESS;
  714. }
  715. return typed_constant();
  716. }
  717. //***************************************************************************
  718. //
  719. // <finalize> ::= <>;
  720. //
  721. // This composes the SQL_LEVEL_1_TOKEN for a simple relational expression,
  722. // complete with any associated intrinsic functions. All of the other
  723. // parse functions help isolate the terms of the expression, but only
  724. // this function builds the token.
  725. //
  726. // To build the token, the following member variables are used:
  727. // m_pPropName
  728. // m_vTypedConst
  729. // m_dwPropFunction
  730. // m_dwConstFunction
  731. // m_nRelOp;
  732. //
  733. // After the token is built, these are cleared/deallocated as appropriate.
  734. // No tokens are consumed and the input is not advanced.
  735. //
  736. //***************************************************************************
  737. int SQL1_Parser::finalize()
  738. {
  739. // At this point, we have all the info needed for a token.
  740. // =======================================================
  741. wmilib :: auto_ptr<SQL_LEVEL_1_TOKEN> pNewTok ( new SQL_LEVEL_1_TOKEN ) ;
  742. if (! pNewTok.get())
  743. throw CX_MemoryException();
  744. pNewTok.get()->nTokenType = SQL_LEVEL_1_TOKEN::OP_EXPRESSION;
  745. pNewTok.get()->pPropertyName = SysAllocString(m_pIdent);
  746. if ( ! pNewTok.get()->pPropertyName )
  747. {
  748. throw CX_MemoryException();
  749. }
  750. if (m_pPropComp)
  751. {
  752. pNewTok.get()->pPropName2 = SysAllocString(m_pPropComp);
  753. if ( ! pNewTok.get()->pPropName2 )
  754. {
  755. throw CX_MemoryException();
  756. }
  757. }
  758. pNewTok.get()->nOperator = m_nRelOp;
  759. VariantInit(&pNewTok.get()->vConstValue);
  760. VariantCopy(&pNewTok.get()->vConstValue, &m_vTypedConst);
  761. pNewTok.get()->dwPropertyFunction = m_dwPropFunction;
  762. pNewTok.get()->dwConstFunction = m_dwConstFunction;
  763. pNewTok.get()->bConstIsStrNumeric = m_bConstIsStrNumeric;
  764. m_pExpression->AddToken(pNewTok.release ());
  765. // Cleanup.
  766. // ========
  767. VariantClear(&m_vTypedConst);
  768. delete m_pIdent;
  769. m_pIdent = 0;
  770. m_nRelOp = 0;
  771. m_dwPropFunction = 0;
  772. m_dwConstFunction = 0;
  773. m_bConstIsStrNumeric = FALSE;
  774. return SUCCESS;
  775. }
  776. //***************************************************************************
  777. //
  778. // <typed_constant> ::= VARIANT;
  779. //
  780. // Ouput: m_vTypedConst is set to the value of the constant. The only
  781. // supported types are VT_I4, VT_R8 and VT_BSTR.
  782. //
  783. //***************************************************************************
  784. int SQL1_Parser::typed_constant()
  785. {
  786. trace((" Typed constant <%S> ", m_pTokenText));
  787. VariantClear(&m_vTypedConst);
  788. m_bConstIsStrNumeric = FALSE;
  789. if (m_nCurrentToken == SQL_1_TOK_INT)
  790. {
  791. trace((" Integer\n"));
  792. DWORD x = wcslen(m_pTokenText);
  793. if (*m_pTokenText == L'-')
  794. {
  795. //negative
  796. if ((x < 11) ||
  797. ((x == 11) && (wcscmp(m_pTokenText, L"-2147483648") <= 0)))
  798. {
  799. V_VT(&m_vTypedConst) = VT_I4;
  800. V_I4(&m_vTypedConst) = _wtol(m_pTokenText);
  801. }
  802. else
  803. {
  804. trace((" Actually Integer String\n"));
  805. V_VT(&m_vTypedConst) = VT_BSTR;
  806. V_BSTR(&m_vTypedConst) = SysAllocString(m_pTokenText);
  807. if ( V_BSTR(&m_vTypedConst) == NULL )
  808. {
  809. throw CX_MemoryException();
  810. }
  811. m_bConstIsStrNumeric = TRUE;
  812. }
  813. }
  814. else
  815. {
  816. //positive
  817. if ((x < 10) ||
  818. ((x == 10) && (wcscmp(m_pTokenText, L"2147483647") <= 0)))
  819. {
  820. V_VT(&m_vTypedConst) = VT_I4;
  821. V_I4(&m_vTypedConst) = _wtol(m_pTokenText);
  822. }
  823. else
  824. {
  825. trace((" Actually Integer String\n"));
  826. V_VT(&m_vTypedConst) = VT_BSTR;
  827. V_BSTR(&m_vTypedConst) = SysAllocString(m_pTokenText);
  828. if ( V_BSTR(&m_vTypedConst) == NULL )
  829. {
  830. throw CX_MemoryException();
  831. }
  832. m_bConstIsStrNumeric = TRUE;
  833. }
  834. }
  835. }
  836. else if (m_nCurrentToken == SQL_1_TOK_QSTRING)
  837. {
  838. trace((" String\n"));
  839. V_VT(&m_vTypedConst) = VT_BSTR;
  840. V_BSTR(&m_vTypedConst) = SysAllocString(m_pTokenText);
  841. if ( V_BSTR(&m_vTypedConst) == NULL )
  842. {
  843. throw CX_MemoryException();
  844. }
  845. }
  846. else if (m_nCurrentToken == SQL_1_TOK_REAL)
  847. {
  848. trace((" Real\n"));
  849. V_VT(&m_vTypedConst) = VT_R8;
  850. V_R8(&m_vTypedConst) = 0.0;
  851. if (m_pTokenText)
  852. {
  853. VARIANT varFrom;
  854. varFrom.vt = VT_BSTR;
  855. varFrom.bstrVal = SysAllocString(m_pTokenText);
  856. if(varFrom.bstrVal)
  857. {
  858. VariantClear(&m_vTypedConst);
  859. VariantInit(&m_vTypedConst);
  860. SCODE sc = VariantChangeTypeEx(&m_vTypedConst, &varFrom, 0, 0x409, VT_R8);
  861. VariantClear(&varFrom);
  862. if(sc != S_OK)
  863. {
  864. VariantClear(&m_vTypedConst);
  865. VariantInit(&m_vTypedConst);
  866. return LEXICAL_ERROR;
  867. }
  868. }
  869. else
  870. {
  871. throw CX_MemoryException();
  872. }
  873. }
  874. }
  875. else if (m_nCurrentToken == SQL_1_TOK_BOOL)
  876. {
  877. trace((" Bool\n"));
  878. V_VT(&m_vTypedConst) = VT_BOOL;
  879. if (m_pTokenText && wbem_wcsicmp(m_pTokenText, L"65535") == 0)
  880. {
  881. V_BOOL(&m_vTypedConst) = VARIANT_TRUE;
  882. }
  883. else
  884. V_BOOL(&m_vTypedConst) = VARIANT_FALSE;
  885. }
  886. // Else, not a typed constant.
  887. else
  888. return SYNTAX_ERROR;
  889. if (!Next())
  890. return LEXICAL_ERROR;
  891. return SUCCESS;
  892. }
  893. //***************************************************************************
  894. //
  895. // <rel_operator> ::= <equiv_operator>;
  896. // <rel_operator> ::= <comp_operator>;
  897. //
  898. //***************************************************************************
  899. int SQL1_Parser::rel_operator()
  900. {
  901. if(SUCCESS == equiv_operator())
  902. return SUCCESS;
  903. else if (SUCCESS == comp_operator())
  904. return SUCCESS;
  905. else return LEXICAL_ERROR;
  906. }
  907. //***************************************************************************
  908. //
  909. // <equiv_operator> ::= EQUIV_OPERATOR; // =, !=
  910. //
  911. // Output: m_nRelOp is set to the correct operator for a SQL_LEVEL_1_TOKEN.
  912. //
  913. //***************************************************************************
  914. int SQL1_Parser::equiv_operator()
  915. {
  916. m_nRelOp = 0;
  917. if (m_nCurrentToken == SQL_1_TOK_EQ)
  918. {
  919. trace((" REL OP =\n"));
  920. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_EQUAL;
  921. }
  922. else if (m_nCurrentToken == SQL_1_TOK_NE)
  923. {
  924. trace((" REL OP <> (!=) \n"));
  925. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_NOT_EQUAL;
  926. }
  927. else
  928. return SYNTAX_ERROR;
  929. if (!Next())
  930. return LEXICAL_ERROR;
  931. return SUCCESS;
  932. }
  933. //***************************************************************************
  934. //
  935. // <is_operator> ::= IS_OPERATOR; // is, isnot
  936. //
  937. // Output: m_nRelOp is set to the correct operator for a SQL_LEVEL_1_TOKEN.
  938. //
  939. //***************************************************************************
  940. int SQL1_Parser::is_operator()
  941. {
  942. m_nRelOp = 0;
  943. if (m_nCurrentToken != SQL_1_TOK_IS)
  944. return SYNTAX_ERROR;
  945. if (!Next())
  946. return LEXICAL_ERROR;
  947. if (m_nCurrentToken == SQL_1_TOK_NOT)
  948. {
  949. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_NOT_EQUAL;
  950. if (!Next())
  951. return LEXICAL_ERROR;
  952. trace((" REL OP IS NOT \n"));
  953. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_NOT_EQUAL;
  954. return SUCCESS;
  955. }
  956. else
  957. {
  958. trace((" REL OP IS \n"));
  959. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_EQUAL;
  960. return SUCCESS;
  961. }
  962. return SUCCESS;
  963. }
  964. //***************************************************************************
  965. //
  966. // <comp_operator> ::= COMP_OPERATOR; // <=, >=, <, >, like
  967. //
  968. // Output: m_nRelOp is set to the correct operator for a SQL_LEVEL_1_TOKEN.
  969. //
  970. //***************************************************************************
  971. int SQL1_Parser::comp_operator()
  972. {
  973. m_nRelOp = 0;
  974. if (m_nCurrentToken == SQL_1_TOK_LE)
  975. {
  976. trace((" REL OP <=\n"));
  977. if (m_pIdent)
  978. {
  979. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_EQUALorLESSTHAN;
  980. }
  981. else
  982. {
  983. trace((" REL OP changed to >=\n"));
  984. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_EQUALorGREATERTHAN;
  985. }
  986. }
  987. else if (m_nCurrentToken == SQL_1_TOK_LT)
  988. {
  989. trace((" REL OP <\n"));
  990. if (m_pIdent)
  991. {
  992. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_LESSTHAN;
  993. }
  994. else
  995. {
  996. trace((" REL OP changed to >\n"));
  997. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_GREATERTHAN;
  998. }
  999. }
  1000. else if (m_nCurrentToken == SQL_1_TOK_GE)
  1001. {
  1002. trace((" REL OP >=\n"));
  1003. if (m_pIdent)
  1004. {
  1005. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_EQUALorGREATERTHAN;
  1006. }
  1007. else
  1008. {
  1009. trace((" REL OP changed to <=\n"));
  1010. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_EQUALorLESSTHAN;
  1011. }
  1012. }
  1013. else if (m_nCurrentToken == SQL_1_TOK_GT)
  1014. {
  1015. trace((" REL OP >\n"));
  1016. if (m_pIdent)
  1017. {
  1018. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_GREATERTHAN;
  1019. }
  1020. else
  1021. {
  1022. trace((" REL OP changed to <\n"));
  1023. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_LESSTHAN;
  1024. }
  1025. }
  1026. else if (m_nCurrentToken == SQL_1_TOK_LIKE)
  1027. {
  1028. trace((" REL OP 'like' \n"));
  1029. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_LIKE;
  1030. }
  1031. else
  1032. return SYNTAX_ERROR;
  1033. if (!Next())
  1034. return LEXICAL_ERROR;
  1035. return SUCCESS;
  1036. }
  1037. //***************************************************************************
  1038. //
  1039. // Expression and token structure methods.
  1040. //
  1041. //***************************************************************************
  1042. SQL_LEVEL_1_RPN_EXPRESSION::SQL_LEVEL_1_RPN_EXPRESSION()
  1043. {
  1044. nNumTokens = 0;
  1045. pArrayOfTokens = 0;
  1046. bsClassName = 0;
  1047. nNumberOfProperties = 0;
  1048. pbsRequestedPropertyNames = 0;
  1049. nCurSize = 32;
  1050. nCurPropSize = 32;
  1051. pArrayOfTokens = new SQL_LEVEL_1_TOKEN[nCurSize];
  1052. if (! pArrayOfTokens)
  1053. throw CX_MemoryException();
  1054. pbsRequestedPropertyNames = new BSTR[nCurPropSize];
  1055. if (! pbsRequestedPropertyNames)
  1056. throw CX_MemoryException();
  1057. }
  1058. SQL_LEVEL_1_RPN_EXPRESSION::~SQL_LEVEL_1_RPN_EXPRESSION()
  1059. {
  1060. delete [] pArrayOfTokens;
  1061. if (bsClassName)
  1062. SysFreeString(bsClassName);
  1063. for (int i = 0; i < nNumberOfProperties; i++)
  1064. SysFreeString(pbsRequestedPropertyNames[i]);
  1065. delete pbsRequestedPropertyNames;
  1066. }
  1067. void SQL_LEVEL_1_RPN_EXPRESSION::AddToken(SQL_LEVEL_1_TOKEN *pTok)
  1068. {
  1069. try
  1070. {
  1071. AddToken(*pTok);
  1072. }
  1073. catch ( ... )
  1074. {
  1075. delete pTok;
  1076. pTok = NULL;
  1077. throw ;
  1078. }
  1079. delete pTok;
  1080. pTok = NULL;
  1081. }
  1082. void SQL_LEVEL_1_RPN_EXPRESSION::AddToken(SQL_LEVEL_1_TOKEN &pTok)
  1083. {
  1084. if (nCurSize == nNumTokens)
  1085. {
  1086. nCurSize += 32;
  1087. SQL_LEVEL_1_TOKEN *pTemp = new SQL_LEVEL_1_TOKEN[nCurSize];
  1088. if ( pTemp )
  1089. {
  1090. for (int i = 0; i < nNumTokens; i++)
  1091. pTemp[i] = pArrayOfTokens[i];
  1092. delete [] pArrayOfTokens;
  1093. pArrayOfTokens = pTemp;
  1094. }
  1095. else
  1096. {
  1097. throw CX_MemoryException();
  1098. }
  1099. }
  1100. pArrayOfTokens[nNumTokens++] = pTok;
  1101. }
  1102. void SQL_LEVEL_1_RPN_EXPRESSION::AddProperty (LPWSTR pProp)
  1103. {
  1104. if (nCurPropSize == nNumberOfProperties)
  1105. {
  1106. nCurPropSize += 32;
  1107. wmilib :: auto_ptr<BSTR> pTemp ( new BSTR[nCurPropSize] ) ;
  1108. if (!pTemp.get())
  1109. throw CX_MemoryException();
  1110. if (pbsRequestedPropertyNames)
  1111. {
  1112. memcpy(pTemp.get(), pbsRequestedPropertyNames,
  1113. sizeof(BSTR) * nNumberOfProperties);
  1114. }
  1115. else
  1116. {
  1117. throw CX_MemoryException();
  1118. }
  1119. delete pbsRequestedPropertyNames;
  1120. pbsRequestedPropertyNames = pTemp.release();
  1121. }
  1122. BSTR pTemp = SysAllocString(pProp);
  1123. if ( pTemp)
  1124. {
  1125. pbsRequestedPropertyNames[nNumberOfProperties++] = pTemp ;
  1126. }
  1127. else
  1128. {
  1129. throw CX_MemoryException();
  1130. }
  1131. }
  1132. void SQL_LEVEL_1_RPN_EXPRESSION::Dump(const char *pszTextFile)
  1133. {
  1134. FILE *f = fopen(pszTextFile, "wt");
  1135. if (!f)
  1136. return;
  1137. fprintf(f, "----RPN Expression----\n");
  1138. fprintf(f, "Class name = %S\n", bsClassName);
  1139. fprintf(f, "Properties selected: ");
  1140. if (!nNumberOfProperties)
  1141. {
  1142. fprintf(f, "* = all properties selected\n");
  1143. }
  1144. else for (int i = 0; i < nNumberOfProperties; i++)
  1145. {
  1146. fprintf(f, "%S ", pbsRequestedPropertyNames[i]);
  1147. }
  1148. fprintf(f, "\n------------------\n");
  1149. fprintf(f, "Tokens:\n");
  1150. for (int i = 0; i < nNumTokens; i++)
  1151. pArrayOfTokens[i].Dump(f);
  1152. fprintf(f, "---end of expression---\n");
  1153. fclose(f);
  1154. }
  1155. SQL_LEVEL_1_TOKEN::SQL_LEVEL_1_TOKEN()
  1156. {
  1157. nTokenType = 0;
  1158. pPropertyName = 0;
  1159. pPropName2 = 0;
  1160. nOperator = 0;
  1161. VariantInit(&vConstValue);
  1162. dwPropertyFunction = 0;
  1163. dwConstFunction = 0;
  1164. bConstIsStrNumeric = FALSE;
  1165. }
  1166. SQL_LEVEL_1_TOKEN::SQL_LEVEL_1_TOKEN(SQL_LEVEL_1_TOKEN &Src)
  1167. {
  1168. nTokenType = 0;
  1169. pPropertyName = 0;
  1170. pPropName2 = 0;
  1171. nOperator = 0;
  1172. VariantInit(&vConstValue);
  1173. dwPropertyFunction = 0;
  1174. dwConstFunction = 0;
  1175. bConstIsStrNumeric = FALSE;
  1176. *this = Src;
  1177. }
  1178. SQL_LEVEL_1_TOKEN& SQL_LEVEL_1_TOKEN::operator =(SQL_LEVEL_1_TOKEN &Src)
  1179. {
  1180. //first clear any old values...
  1181. if (pPropertyName)
  1182. {
  1183. SysFreeString(pPropertyName);
  1184. pPropertyName = NULL ;
  1185. }
  1186. if (pPropName2)
  1187. {
  1188. SysFreeString(pPropName2);
  1189. pPropName2 = NULL ;
  1190. }
  1191. VariantClear(&vConstValue);
  1192. nTokenType = Src.nTokenType;
  1193. if ( Src.pPropertyName )
  1194. {
  1195. pPropertyName = SysAllocString(Src.pPropertyName);
  1196. if ( ! pPropertyName )
  1197. {
  1198. throw CX_MemoryException();
  1199. }
  1200. }
  1201. if (Src.pPropName2)
  1202. {
  1203. pPropName2 = SysAllocString(Src.pPropName2);
  1204. if ( ! pPropName2 )
  1205. {
  1206. throw CX_MemoryException();
  1207. }
  1208. }
  1209. nOperator = Src.nOperator;
  1210. if ( FAILED ( VariantCopy(&vConstValue, &Src.vConstValue) ) )
  1211. {
  1212. throw CX_MemoryException();
  1213. }
  1214. dwPropertyFunction = Src.dwPropertyFunction;
  1215. dwConstFunction = Src.dwConstFunction;
  1216. bConstIsStrNumeric = Src.bConstIsStrNumeric;
  1217. return *this;
  1218. }
  1219. SQL_LEVEL_1_TOKEN::~SQL_LEVEL_1_TOKEN()
  1220. {
  1221. nTokenType = 0;
  1222. if (pPropertyName)
  1223. SysFreeString(pPropertyName);
  1224. if (pPropName2)
  1225. SysFreeString(pPropName2);
  1226. nOperator = 0;
  1227. VariantClear(&vConstValue);
  1228. }
  1229. void SQL_LEVEL_1_TOKEN::Dump(FILE *f)
  1230. {
  1231. switch (nTokenType)
  1232. {
  1233. case OP_EXPRESSION:
  1234. fprintf(f, "OP_EXPRESSION ");
  1235. break;
  1236. case TOKEN_AND:
  1237. fprintf(f, "TOKEN_AND ");
  1238. break;
  1239. case TOKEN_OR:
  1240. fprintf(f, "TOKEN_OR ");
  1241. break;
  1242. case TOKEN_NOT:
  1243. fprintf(f, "TOKEN_NOT ");
  1244. break;
  1245. default:
  1246. fprintf(f, "Error: no token type specified\n");
  1247. }
  1248. if (nTokenType == OP_EXPRESSION)
  1249. {
  1250. char *pOp = "<no op>";
  1251. switch (nOperator)
  1252. {
  1253. case OP_EQUAL: pOp = "OP_EQUAL"; break;
  1254. case OP_NOT_EQUAL: pOp = "OP_NOT_EQUAL"; break;
  1255. case OP_EQUALorGREATERTHAN: pOp = "OP_EQUALorGREATERTHAN"; break;
  1256. case OP_EQUALorLESSTHAN: pOp = "OP_EQUALorLESSTHAN"; break;
  1257. case OP_LESSTHAN: pOp = "OP_LESSTHAN"; break;
  1258. case OP_GREATERTHAN: pOp = "OP_GREATERTHAN"; break;
  1259. case OP_LIKE: pOp = "OP_LIKE"; break;
  1260. }
  1261. fprintf(f, " Property = %S\n", pPropertyName);
  1262. fprintf(f, " Operator = %s\n", pOp);
  1263. fprintf(f, " Value = ");
  1264. if (pPropName2)
  1265. fprintf(f, " <Property:%S\n", pPropName2);
  1266. else
  1267. {
  1268. switch (V_VT(&vConstValue))
  1269. {
  1270. case VT_I4:
  1271. fprintf(f, "VT_I4 = %d\n", V_I4(&vConstValue));
  1272. break;
  1273. case VT_BSTR:
  1274. fprintf(f, "VT_BSTR = %S\n", V_BSTR(&vConstValue));
  1275. break;
  1276. case VT_R8:
  1277. fprintf(f, "VT_R8 = %f\n", V_R8(&vConstValue));
  1278. break;
  1279. case VT_BOOL:
  1280. fprintf(f, "VT_BOOL = %d (%s)\n",
  1281. V_BOOL(&vConstValue),
  1282. V_BOOL(&vConstValue) == VARIANT_TRUE ? "VARIANT_TRUE" : "VARIANT_FALSE"
  1283. );
  1284. break;
  1285. default:
  1286. fprintf(f, "<unknown>\n");
  1287. }
  1288. }
  1289. switch (dwPropertyFunction)
  1290. {
  1291. case IFUNC_NONE:
  1292. break;
  1293. case IFUNC_LOWER:
  1294. fprintf(f, "Intrinsic function LOWER() applied to property\n");
  1295. break;
  1296. case IFUNC_UPPER:
  1297. fprintf(f, "Intrinsic function UPPER() applied to property\n");
  1298. break;
  1299. }
  1300. switch (dwConstFunction)
  1301. {
  1302. case IFUNC_NONE:
  1303. break;
  1304. case IFUNC_LOWER:
  1305. fprintf(f, "Intrinsic function LOWER() applied to const value\n");
  1306. break;
  1307. case IFUNC_UPPER:
  1308. fprintf(f, "Intrinsic function UPPER() applied to const value\n");
  1309. break;
  1310. }
  1311. }
  1312. fprintf(f, " <end of token>\n");
  1313. }
  1314. /////////////////////////////////////////////////////////////////////////////
  1315. //
  1316. // Algorithm for evaluating the expression, assuming that it has been
  1317. // tokenized and translated to Reverse Polish.
  1318. //
  1319. // Starting point: (a) An array of SQL tokens.
  1320. // (b) An empty boolean token stack.
  1321. //
  1322. // 1. Read Next Token
  1323. //
  1324. // 2. If a SIMPLE EXPRESSION, evaluate it to TRUE or FALSE, and
  1325. // place this boolean result on the stack. Go to 1.
  1326. //
  1327. // 3. If an OR operator, then pop a boolean token into A,
  1328. // pop another boolean token into B. If either A or B are TRUE,
  1329. // stack TRUE. Else stack FALSE.
  1330. // Go to 1.
  1331. //
  1332. // 4. If an AND operator, then pop a boolean token into A,
  1333. // and pop another into B. If both are TRUE, stack TRUE.
  1334. // Else stack FALSE.
  1335. // Go to 1.
  1336. //
  1337. // 5. If a NOT operator, reverse the value of the top-of-stack boolean.
  1338. // Go to 1.
  1339. //
  1340. // At end-of-input, the result is at top-of-stack.
  1341. //
  1342. /////////////////////////////////////////////////////////////////////////////