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.

2887 lines
71 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // C++ source expression evaluation.
  4. //
  5. // Copyright (C) Microsoft Corporation, 2001-2002.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. #define DBG_TOKENS 0
  10. #define DBG_TYPES 0
  11. //----------------------------------------------------------------------------
  12. //
  13. // CppEvalExpression.
  14. //
  15. //----------------------------------------------------------------------------
  16. char CppEvalExpression::s_EscapeChars[] = "?afvbntr\"'\\";
  17. char CppEvalExpression::s_EscapeCharValues[] = "?\a\f\v\b\n\t\r\"'\\";
  18. PCSTR CppEvalExpression::s_MultiTokens[] =
  19. {
  20. "EOF",
  21. "identifier",
  22. "integer literal",
  23. "floating-point literal",
  24. "char string literal",
  25. "char literal",
  26. "wchar string literal",
  27. "wchar literal",
  28. "debugger register",
  29. "module name",
  30. "MASM expression",
  31. "Preprocessor function",
  32. "==",
  33. "!=",
  34. "<=",
  35. ">=",
  36. "&&",
  37. "||",
  38. "U+",
  39. "U-",
  40. "<<",
  41. ">>",
  42. "address of",
  43. "dereference",
  44. "->",
  45. ".*",
  46. "->*",
  47. "/=",
  48. "*=",
  49. "%=",
  50. "+=",
  51. "-=",
  52. "<<=",
  53. ">>=",
  54. "&=",
  55. "|=",
  56. "^=",
  57. "++",
  58. "--",
  59. "++",
  60. "--",
  61. "::",
  62. "::~",
  63. "sizeof",
  64. "this",
  65. "operator",
  66. "new",
  67. "delete",
  68. "const",
  69. "struct",
  70. "class",
  71. "union",
  72. "enum",
  73. "volatile",
  74. "signed",
  75. "unsigned",
  76. "dynamic_cast",
  77. "static_cast",
  78. "const_cast",
  79. "reinterpret_cast",
  80. "typeid",
  81. };
  82. CppEvalExpression::CppEvalExpression(void)
  83. : EvalExpression(DEBUG_EXPR_CPLUSPLUS,
  84. "C++ source expressions",
  85. "C++")
  86. {
  87. m_PreprocEval = FALSE;
  88. }
  89. CppEvalExpression::~CppEvalExpression(void)
  90. {
  91. }
  92. PCSTR
  93. CppEvalExpression::TokenImage(CppToken Token)
  94. {
  95. #define TOKIM_CHARS 8
  96. static char s_CharImage[2 * TOKIM_CHARS];
  97. static int s_CharImageIdx = 0;
  98. C_ASSERT(DIMA(s_MultiTokens) == CppTokenCount - CPP_TOKEN_MULTI);
  99. if (Token <= CppTokenError || Token >= CppTokenCount)
  100. {
  101. return NULL;
  102. }
  103. else if (Token < CPP_TOKEN_MULTI)
  104. {
  105. PSTR Image;
  106. Image = s_CharImage + s_CharImageIdx;
  107. s_CharImageIdx += 2;
  108. if (s_CharImageIdx >= sizeof(s_CharImage))
  109. {
  110. s_CharImageIdx = 0;
  111. }
  112. Image[0] = (char)Token;
  113. Image[1] = 0;
  114. return Image;
  115. }
  116. else
  117. {
  118. return s_MultiTokens[Token - CPP_TOKEN_MULTI];
  119. }
  120. }
  121. char
  122. CppEvalExpression::GetStringChar(PBOOL Escaped)
  123. {
  124. char Ch;
  125. PSTR Esc;
  126. int V;
  127. *Escaped = FALSE;
  128. Ch = *m_Lex++;
  129. if (!Ch)
  130. {
  131. m_Lex--;
  132. EvalErrorDesc(SYNTAX, "EOF in literal");
  133. }
  134. else if (Ch == '\n' || Ch == '\r')
  135. {
  136. m_Lex--;
  137. EvalErrorDesc(SYNTAX, "Newline in literal");
  138. }
  139. else if (Ch == '\\')
  140. {
  141. *Escaped = TRUE;
  142. Ch = *m_Lex++;
  143. if (!Ch)
  144. {
  145. EvalErrorDesc(SYNTAX, "EOF in literal");
  146. }
  147. else if (Ch == 'x')
  148. {
  149. // Hex character literal.
  150. V = 0;
  151. for (;;)
  152. {
  153. Ch = *m_Lex++;
  154. if (!isxdigit(Ch))
  155. {
  156. break;
  157. }
  158. if (isupper(Ch))
  159. {
  160. Ch = (char)tolower(Ch);
  161. }
  162. V = V * 16 + (Ch >= 'a' ? Ch - 'a' + 10 : Ch - '0');
  163. }
  164. m_Lex--;
  165. Ch = (char)V;
  166. }
  167. else if (IS_OCTAL_DIGIT(Ch))
  168. {
  169. // Octal character literal.
  170. V = 0;
  171. do
  172. {
  173. V = V * 8 + Ch - '0';
  174. Ch = *m_Lex++;
  175. } while (IS_OCTAL_DIGIT(Ch));
  176. m_Lex--;
  177. Ch = (char)V;
  178. }
  179. else
  180. {
  181. Esc = strchr(s_EscapeChars, Ch);
  182. if (Esc == NULL)
  183. {
  184. EvalErrorDesc(SYNTAX, "Unknown escape character");
  185. }
  186. else
  187. {
  188. Ch = s_EscapeCharValues[Esc - s_EscapeChars];
  189. }
  190. }
  191. }
  192. return Ch;
  193. }
  194. void
  195. CppEvalExpression::FinishFloat(LONG64 IntPart, int Sign)
  196. {
  197. double Val = (double)IntPart;
  198. double Frac = 1;
  199. char Ch;
  200. Ch = *(m_Lex - 1);
  201. if (Ch == '.')
  202. {
  203. for (;;)
  204. {
  205. Ch = *m_Lex++;
  206. if (!isdigit(Ch))
  207. {
  208. break;
  209. }
  210. Frac /= 10;
  211. Val += ((int)Ch - (int)'0') * Frac;
  212. AddLexeme(Ch);
  213. }
  214. }
  215. if (Ch == 'e' || Ch == 'E')
  216. {
  217. long Power = 0;
  218. BOOL Neg = FALSE;
  219. Ch = *m_Lex++;
  220. if (Ch == '-' || Ch == '+')
  221. {
  222. AddLexeme(Ch);
  223. if (Ch == '-')
  224. {
  225. Neg = TRUE;
  226. }
  227. Ch = *m_Lex++;
  228. }
  229. while (isdigit(Ch))
  230. {
  231. AddLexeme(Ch);
  232. Power = Power * 10 + Ch - '0';
  233. Ch = *m_Lex++;
  234. }
  235. if (Neg)
  236. {
  237. Power = -Power;
  238. }
  239. Val *= pow(10.0, Power);
  240. }
  241. m_Lex--;
  242. BOOL Long = FALSE;
  243. BOOL Float = FALSE;
  244. for (;;)
  245. {
  246. if (*m_Lex == 'f' || *m_Lex == 'F')
  247. {
  248. Float = TRUE;
  249. AddLexeme(*m_Lex++);
  250. }
  251. else if (*m_Lex == 'l' || *m_Lex == 'L')
  252. {
  253. Long = TRUE;
  254. AddLexeme(*m_Lex++);
  255. }
  256. else
  257. {
  258. break;
  259. }
  260. }
  261. ZeroMemory(&m_TokenValue, sizeof(m_TokenValue));
  262. if (Long || !Float)
  263. {
  264. m_TokenValue.m_BaseType = DNTYPE_FLOAT64;
  265. m_TokenValue.m_F64 = Val * Sign;
  266. }
  267. else
  268. {
  269. m_TokenValue.m_BaseType = DNTYPE_FLOAT32;
  270. m_TokenValue.m_F32 = (float)(Val * Sign);
  271. }
  272. AddLexeme(0);
  273. m_TokenValue.SetToNativeType(m_TokenValue.m_BaseType);
  274. }
  275. CppToken
  276. CppEvalExpression::ReadNumber(int Sign)
  277. {
  278. ULONG64 IntVal;
  279. char Ch, Nch;
  280. BOOL Decimal = FALSE;
  281. //
  282. // Many number outputs use ` as a separator between
  283. // the high and low parts of a 64-bit number. Ignore
  284. // ` here to make it simple to use such values.
  285. //
  286. Ch = *(m_Lex - 1);
  287. Nch = *m_Lex++;
  288. if (Ch != '0' ||
  289. (Nch != 'x' && Nch != 'X' && !IS_OCTAL_DIGIT(Nch)))
  290. {
  291. IntVal = Ch - '0';
  292. Ch = Nch;
  293. while (isdigit(Ch) || Ch == '`')
  294. {
  295. if (Ch != '`')
  296. {
  297. IntVal = IntVal * 10 + (Ch - '0');
  298. }
  299. AddLexeme(Ch);
  300. Ch = *m_Lex++;
  301. }
  302. if (Ch == '.' || Ch == 'e' || Ch == 'E' || Ch == 'f' || Ch == 'F')
  303. {
  304. AddLexeme(Ch);
  305. FinishFloat((LONG64)IntVal, Sign);
  306. return CppTokenFloat;
  307. }
  308. Decimal = TRUE;
  309. }
  310. else
  311. {
  312. Ch = Nch;
  313. IntVal = 0;
  314. if (Ch == 'x' || Ch == 'X')
  315. {
  316. AddLexeme(Ch);
  317. for (;;)
  318. {
  319. Ch = *m_Lex++;
  320. if (!isxdigit(Ch) && Ch != '`')
  321. {
  322. break;
  323. }
  324. AddLexeme(Ch);
  325. if (Ch == '`')
  326. {
  327. continue;
  328. }
  329. if (isupper(Ch))
  330. {
  331. Ch = (char)tolower(Ch);
  332. }
  333. IntVal = IntVal * 16 + (Ch >= 'a' ? Ch - 'a' + 10 : Ch - '0');
  334. }
  335. }
  336. else if (IS_OCTAL_DIGIT(Ch))
  337. {
  338. do
  339. {
  340. AddLexeme(Ch);
  341. if (Ch != '`')
  342. {
  343. IntVal = IntVal * 8 + (Ch - '0');
  344. }
  345. Ch = *m_Lex++;
  346. }
  347. while (IS_OCTAL_DIGIT(Ch) || Ch == '`');
  348. }
  349. }
  350. m_Lex--;
  351. BOOL Unsigned = FALSE, I64 = FALSE;
  352. for (;;)
  353. {
  354. if (*m_Lex == 'l' || *m_Lex == 'L')
  355. {
  356. AddLexeme(*m_Lex++);
  357. }
  358. else if ((*m_Lex == 'i' || *m_Lex == 'I') &&
  359. *(m_Lex + 1) == '6' && *(m_Lex + 2) == '4')
  360. {
  361. AddLexeme(*m_Lex++);
  362. AddLexeme(*m_Lex++);
  363. AddLexeme(*m_Lex++);
  364. I64 = TRUE;
  365. }
  366. else if (*m_Lex == 'u' || *m_Lex == 'U')
  367. {
  368. AddLexeme(*m_Lex++);
  369. Unsigned = TRUE;
  370. }
  371. else
  372. {
  373. break;
  374. }
  375. }
  376. AddLexeme(0);
  377. ZeroMemory(&m_TokenValue, sizeof(m_TokenValue));
  378. // Constants are given the smallest type which can contain
  379. // their value.
  380. if (!Unsigned)
  381. {
  382. if (I64)
  383. {
  384. if (IntVal >= 0x8000000000000000)
  385. {
  386. // Value has to be an unsigned int64.
  387. m_TokenValue.m_BaseType = DNTYPE_UINT64;
  388. }
  389. else
  390. {
  391. m_TokenValue.m_BaseType = DNTYPE_INT64;
  392. }
  393. }
  394. else
  395. {
  396. if (IntVal >= 0x8000000000000000)
  397. {
  398. // Value has to be an unsigned int64.
  399. m_TokenValue.m_BaseType = DNTYPE_UINT64;
  400. }
  401. else if ((Decimal && IntVal >= 0x80000000) ||
  402. (!Decimal && IntVal >= 0x100000000))
  403. {
  404. // Value has to be an int64.
  405. m_TokenValue.m_BaseType = DNTYPE_INT64;
  406. }
  407. else if (IntVal >= 0x80000000)
  408. {
  409. // Value has to be an unsigned int.
  410. m_TokenValue.m_BaseType = DNTYPE_UINT32;
  411. }
  412. else
  413. {
  414. m_TokenValue.m_BaseType = DNTYPE_INT32;
  415. }
  416. }
  417. }
  418. else if (!I64)
  419. {
  420. if (IntVal >= 0x100000000)
  421. {
  422. // Value has to be an unsigned int64.
  423. m_TokenValue.m_BaseType = DNTYPE_UINT64;
  424. }
  425. else
  426. {
  427. m_TokenValue.m_BaseType = DNTYPE_UINT32;
  428. }
  429. }
  430. else
  431. {
  432. m_TokenValue.m_BaseType = DNTYPE_UINT64;
  433. }
  434. m_TokenValue.SetToNativeType(m_TokenValue.m_BaseType);
  435. m_TokenValue.m_S64 = (LONG64)IntVal * Sign;
  436. return CppTokenInteger;
  437. }
  438. CppToken
  439. CppEvalExpression::Lex(void)
  440. {
  441. char Ch, Nch, Tch;
  442. PSTR Single;
  443. BOOL UnaryOp;
  444. BOOL CharToken;
  445. BOOL Escaped;
  446. UnaryOp = m_AllowUnaryOp;
  447. m_AllowUnaryOp = TRUE;
  448. for (;;)
  449. {
  450. for (;;)
  451. {
  452. Ch = *m_Lex++;
  453. if (IS_EOF(Ch))
  454. {
  455. m_Lex--;
  456. StartLexeme();
  457. m_LexemeSourceStart = m_Lex;
  458. AddLexeme(0);
  459. return CppTokenEof;
  460. }
  461. if (!isspace(Ch))
  462. {
  463. break;
  464. }
  465. }
  466. StartLexeme();
  467. m_LexemeSourceStart = m_Lex - 1;
  468. AddLexeme(Ch);
  469. Nch = *m_Lex;
  470. /* String literals */
  471. if (Ch == '\"' ||
  472. (Ch == 'L' && Nch == '\"'))
  473. {
  474. BOOL Wide = FALSE;
  475. if (Ch == 'L')
  476. {
  477. m_Lex++;
  478. Wide = TRUE;
  479. }
  480. // Store the translated literal in
  481. // the lexeme rather than the source text to
  482. // avoid having two large buffers where one is
  483. // only used for string literals. This means
  484. // the lexeme isn't really the source text but
  485. // that's not a problem for now or the forseeable
  486. // future.
  487. m_LexemeChar--;
  488. for (;;)
  489. {
  490. AddLexeme(GetStringChar(&Escaped));
  491. if (!Escaped &&
  492. (*(m_LexemeChar - 1) == 0 || *(m_LexemeChar - 1) == '\"'))
  493. {
  494. break;
  495. }
  496. }
  497. *(m_LexemeChar - 1) = 0;
  498. m_AllowUnaryOp = FALSE;
  499. return Wide ? CppTokenWcharString : CppTokenCharString;
  500. }
  501. /* Character literals */
  502. if (Ch == '\'' ||
  503. (Ch == 'L' && Nch == '\''))
  504. {
  505. BOOL Wide = FALSE;
  506. if (Ch == 'L')
  507. {
  508. AddLexeme(Nch);
  509. m_Lex++;
  510. Wide = TRUE;
  511. }
  512. int Chars = 0;
  513. ZeroMemory(&m_TokenValue, sizeof(m_TokenValue));
  514. for (;;)
  515. {
  516. Ch = GetStringChar(&Escaped);
  517. AddLexeme(Ch);
  518. if (!Escaped && Ch == '\'')
  519. {
  520. if (Chars == 0)
  521. {
  522. EvalError(SYNTAX);
  523. }
  524. break;
  525. }
  526. if (++Chars > 8)
  527. {
  528. EvalError(OVERFLOW);
  529. }
  530. m_TokenValue.m_S64 = (m_TokenValue.m_S64 << 8) + Ch;
  531. }
  532. AddLexeme(0);
  533. switch(Chars)
  534. {
  535. case 1:
  536. if (Wide)
  537. {
  538. m_TokenValue.SetToNativeType(DNTYPE_WCHAR_T);
  539. }
  540. else
  541. {
  542. m_TokenValue.SetToNativeType(DNTYPE_CHAR);
  543. }
  544. break;
  545. case 2:
  546. m_TokenValue.SetToNativeType(DNTYPE_INT16);
  547. break;
  548. case 3:
  549. case 4:
  550. m_TokenValue.SetToNativeType(DNTYPE_INT32);
  551. case 5:
  552. case 6:
  553. case 7:
  554. case 8:
  555. m_TokenValue.SetToNativeType(DNTYPE_INT64);
  556. break;
  557. }
  558. m_AllowUnaryOp = FALSE;
  559. return Wide ? CppTokenWchar : CppTokenChar;
  560. }
  561. /* Identifiers */
  562. if (isalpha(Ch) || Ch == '_')
  563. {
  564. int KwToken;
  565. for (;;)
  566. {
  567. Ch = *m_Lex++;
  568. if (!isalnum(Ch) && Ch != '_')
  569. {
  570. break;
  571. }
  572. AddLexeme(Ch);
  573. }
  574. m_Lex--;
  575. AddLexeme(0);
  576. m_AllowUnaryOp = FALSE;
  577. for (KwToken = CPP_KEYWORD_FIRST;
  578. KwToken <= CPP_KEYWORD_LAST;
  579. KwToken++)
  580. {
  581. if (!strcmp(m_LexemeStart,
  582. s_MultiTokens[KwToken - CPP_TOKEN_MULTI]))
  583. {
  584. return (CppToken)KwToken;
  585. }
  586. }
  587. return CppTokenIdentifier;
  588. }
  589. // For some reason the compiler emits symbols with
  590. // sections between ` and '. There only seem to be
  591. // normal characters in between them so it's unclear
  592. // why this is done, but allow it as a special
  593. // form of identifier.
  594. if (Ch == '`')
  595. {
  596. for (;;)
  597. {
  598. Ch = *m_Lex++;
  599. if (!Ch)
  600. {
  601. EvalError(SYNTAX);
  602. }
  603. AddLexeme(Ch);
  604. if (Ch == '\'')
  605. {
  606. break;
  607. }
  608. }
  609. AddLexeme(0);
  610. m_AllowUnaryOp = FALSE;
  611. return CppTokenIdentifier;
  612. }
  613. /* Numeric literals */
  614. if (isdigit(Ch))
  615. {
  616. m_AllowUnaryOp = FALSE;
  617. return ReadNumber(1);
  618. }
  619. /* Handle .[digits] floating-point literals */
  620. if (Ch == '.')
  621. {
  622. if (isdigit(Nch))
  623. {
  624. FinishFloat(0, 1);
  625. m_AllowUnaryOp = FALSE;
  626. return CppTokenFloat;
  627. }
  628. else
  629. {
  630. AddLexeme(0);
  631. return CppTokenPeriod;
  632. }
  633. }
  634. /* Unambiguous single character tokens that allow unary */
  635. if (Single = strchr("({}[;,?~.", Ch))
  636. {
  637. AddLexeme(0);
  638. return (CppToken)*Single;
  639. }
  640. /* Unambiguous single character tokens that disallow unary */
  641. if (Single = strchr(")]", Ch))
  642. {
  643. AddLexeme(0);
  644. m_AllowUnaryOp = FALSE;
  645. return (CppToken)*Single;
  646. }
  647. /* All other characters */
  648. Nch = *m_Lex++;
  649. CharToken = TRUE;
  650. switch(Ch)
  651. {
  652. /* Comments, / and /= */
  653. case '/':
  654. if (Nch == '*')
  655. {
  656. for (;;)
  657. {
  658. Ch = *m_Lex++;
  659. CheckChar:
  660. if (!Ch)
  661. {
  662. break;
  663. }
  664. else if (Ch == '*')
  665. {
  666. if ((Ch = *m_Lex++) == '/')
  667. {
  668. break;
  669. }
  670. else
  671. {
  672. goto CheckChar;
  673. }
  674. }
  675. }
  676. if (!Ch)
  677. {
  678. EvalErrorDesc(SYNTAX, "EOF in comment");
  679. }
  680. CharToken = FALSE;
  681. }
  682. else if (Nch == '/')
  683. {
  684. while ((Ch = *m_Lex++) != '\n' && !IS_EOF(Ch))
  685. {
  686. // Iterate.
  687. }
  688. if (IS_EOF(Ch))
  689. {
  690. // IS_EOF includes EOL so EOF is not an error,
  691. // just back up to the EOL.
  692. m_Lex--;
  693. }
  694. CharToken = FALSE;
  695. }
  696. else if (Nch == '=')
  697. {
  698. AddLexeme(Nch);
  699. AddLexeme(0);
  700. return CppTokenDivideAssign;
  701. }
  702. break;
  703. /* :, :: and ::~ */
  704. case ':':
  705. if (Nch == ':')
  706. {
  707. AddLexeme(Nch);
  708. Tch = *m_Lex++;
  709. if (Tch == '~')
  710. {
  711. AddLexeme(Tch);
  712. AddLexeme(0);
  713. return CppTokenDestructor;
  714. }
  715. AddLexeme(0);
  716. m_Lex--;
  717. return CppTokenNameQualifier;
  718. }
  719. break;
  720. /* *, *= and dereference */
  721. case '*':
  722. if (Nch == '=')
  723. {
  724. AddLexeme(Nch);
  725. AddLexeme(0);
  726. return CppTokenMultiplyAssign;
  727. }
  728. else if (UnaryOp)
  729. {
  730. AddLexeme(0);
  731. m_Lex--;
  732. return CppTokenDereference;
  733. }
  734. break;
  735. /* % and %= */
  736. case '%':
  737. if (Nch == '=')
  738. {
  739. AddLexeme(Nch);
  740. AddLexeme(0);
  741. return CppTokenModuloAssign;
  742. }
  743. break;
  744. /* = and == */
  745. case '=':
  746. if (Nch == '=')
  747. {
  748. AddLexeme(Nch);
  749. AddLexeme(0);
  750. return CppTokenEqual;
  751. }
  752. break;
  753. /* ! and != */
  754. case '!':
  755. if (Nch == '=')
  756. {
  757. AddLexeme(Nch);
  758. AddLexeme(0);
  759. return CppTokenNotEqual;
  760. }
  761. break;
  762. /* <, <<, <<= and <= */
  763. case '<':
  764. if (Nch == '=')
  765. {
  766. AddLexeme(Nch);
  767. AddLexeme(0);
  768. return CppTokenLessEqual;
  769. }
  770. else if (Nch == '<')
  771. {
  772. AddLexeme(Nch);
  773. Tch = *m_Lex++;
  774. if (Tch == '=')
  775. {
  776. AddLexeme(Tch);
  777. AddLexeme(0);
  778. return CppTokenLeftShiftAssign;
  779. }
  780. AddLexeme(0);
  781. m_Lex--;
  782. return CppTokenLeftShift;
  783. }
  784. break;
  785. /* >, >>, >>= and >= */
  786. case '>':
  787. if (Nch == '=')
  788. {
  789. AddLexeme(Nch);
  790. AddLexeme(0);
  791. return CppTokenGreaterEqual;
  792. }
  793. else if (Nch == '>')
  794. {
  795. AddLexeme(Nch);
  796. Tch = *m_Lex++;
  797. if (Tch == '=')
  798. {
  799. AddLexeme(Tch);
  800. AddLexeme(0);
  801. return CppTokenRightShiftAssign;
  802. }
  803. AddLexeme(0);
  804. m_Lex--;
  805. return CppTokenRightShift;
  806. }
  807. break;
  808. /* &, &= and && */
  809. case '&':
  810. if (Nch == '&')
  811. {
  812. AddLexeme(Nch);
  813. AddLexeme(0);
  814. return CppTokenLogicalAnd;
  815. }
  816. else if (Nch == '=')
  817. {
  818. AddLexeme(Nch);
  819. AddLexeme(0);
  820. return CppTokenAndAssign;
  821. }
  822. else if (UnaryOp)
  823. {
  824. AddLexeme(0);
  825. m_Lex--;
  826. return CppTokenAddressOf;
  827. }
  828. break;
  829. /* |, |= and || */
  830. case '|':
  831. if (Nch == '|')
  832. {
  833. AddLexeme(Nch);
  834. AddLexeme(0);
  835. return CppTokenLogicalOr;
  836. }
  837. else if (Nch == '=')
  838. {
  839. AddLexeme(Nch);
  840. AddLexeme(0);
  841. return CppTokenOrAssign;
  842. }
  843. break;
  844. /* ^ and ^= */
  845. case '^':
  846. if (Nch == '=')
  847. {
  848. AddLexeme(Nch);
  849. AddLexeme(0);
  850. return CppTokenExclusiveOrAssign;
  851. }
  852. break;
  853. /* U+, +, ++X, X++ and += */
  854. case '+':
  855. if (Nch == '+')
  856. {
  857. AddLexeme(Nch);
  858. AddLexeme(0);
  859. if (UnaryOp)
  860. {
  861. return CppTokenPreIncrement;
  862. }
  863. else
  864. {
  865. m_AllowUnaryOp = FALSE;
  866. return CppTokenPostIncrement;
  867. }
  868. }
  869. else if (Nch == '=')
  870. {
  871. AddLexeme(Nch);
  872. AddLexeme(0);
  873. return CppTokenAddAssign;
  874. }
  875. else if (UnaryOp)
  876. {
  877. if (isdigit(Nch))
  878. {
  879. AddLexeme(Nch);
  880. m_AllowUnaryOp = FALSE;
  881. return ReadNumber(1);
  882. }
  883. else
  884. {
  885. AddLexeme(0);
  886. m_Lex--;
  887. return CppTokenUnaryPlus;
  888. }
  889. }
  890. break;
  891. /* U-, -, --, -> and -= */
  892. case '-':
  893. if (Nch == '-')
  894. {
  895. AddLexeme(Nch);
  896. AddLexeme(0);
  897. if (UnaryOp)
  898. {
  899. return CppTokenPreDecrement;
  900. }
  901. else
  902. {
  903. m_AllowUnaryOp = FALSE;
  904. return CppTokenPostDecrement;
  905. }
  906. }
  907. else if (Nch == '=')
  908. {
  909. AddLexeme(Nch);
  910. AddLexeme(0);
  911. return CppTokenSubtractAssign;
  912. }
  913. else if (Nch == '>')
  914. {
  915. AddLexeme(Nch);
  916. AddLexeme(0);
  917. return CppTokenPointerMember;
  918. }
  919. else if (UnaryOp)
  920. {
  921. if (isdigit(Nch))
  922. {
  923. AddLexeme(Nch);
  924. m_AllowUnaryOp = FALSE;
  925. return ReadNumber(-1);
  926. }
  927. else
  928. {
  929. AddLexeme(0);
  930. m_Lex--;
  931. return CppTokenUnaryMinus;
  932. }
  933. }
  934. break;
  935. /* Special character prefix for debugger registers
  936. and alternate evaluator expressions */
  937. case '@':
  938. if (Nch == '@')
  939. {
  940. ULONG Parens = 1;
  941. PSTR Name;
  942. AddLexeme(Nch);
  943. //
  944. // Look for an optional evaluator name.
  945. //
  946. Name = m_LexemeChar;
  947. while (*m_Lex != '(' && *m_Lex != ';' && *m_Lex)
  948. {
  949. AddLexeme(*m_Lex++);
  950. }
  951. if (Name != m_LexemeChar)
  952. {
  953. EvalExpression* Eval;
  954. // Name was given, identify the evaluator
  955. // and remember the evaluator syntax.
  956. AddLexeme(0);
  957. GetEvaluatorByName(Name, FALSE, &Eval);
  958. m_SwitchEvalSyntax = Eval->m_Syntax;
  959. ReleaseEvaluator(Eval);
  960. // Back up to overwrite the terminator.
  961. m_LexemeChar--;
  962. }
  963. else
  964. {
  965. // No name given, default to MASM.
  966. m_SwitchEvalSyntax = DEBUG_EXPR_MASM;
  967. }
  968. AddLexeme('(');
  969. m_Lex++;
  970. // Collect expression text to a balanced paren.
  971. for (;;)
  972. {
  973. if (!*m_Lex)
  974. {
  975. EvalErrorDesc(SYNTAX,
  976. "EOF in alternate evaluator expression");
  977. }
  978. else if (*m_Lex == '(')
  979. {
  980. Parens++;
  981. }
  982. else if (*m_Lex == ')' && --Parens == 0)
  983. {
  984. break;
  985. }
  986. AddLexeme(*m_Lex++);
  987. }
  988. m_Lex++;
  989. AddLexeme(')');
  990. AddLexeme(0);
  991. m_AllowUnaryOp = FALSE;
  992. return CppTokenSwitchEvalExpression;
  993. }
  994. else
  995. {
  996. if (Nch == '!')
  997. {
  998. AddLexeme(Nch);
  999. Nch = *m_Lex++;
  1000. }
  1001. while (isalnum(Nch) || Nch == '_' || Nch == '$')
  1002. {
  1003. AddLexeme(Nch);
  1004. Nch = *m_Lex++;
  1005. }
  1006. AddLexeme(0);
  1007. m_Lex--;
  1008. m_AllowUnaryOp = FALSE;
  1009. return m_LexemeStart[1] == '!' ?
  1010. CppTokenModule : CppTokenDebugRegister;
  1011. }
  1012. /* Special character prefix for built-in
  1013. equivalents to common preprocessor macros */
  1014. case '#':
  1015. m_Lex--;
  1016. while (isalnum(*m_Lex) || *m_Lex == '_')
  1017. {
  1018. AddLexeme(*m_Lex++);
  1019. }
  1020. AddLexeme(0);
  1021. m_AllowUnaryOp = FALSE;
  1022. return CppTokenPreprocFunction;
  1023. default:
  1024. m_Lex--;
  1025. EvalErrorDesc(SYNTAX, "Unexpected character in");
  1026. CharToken = FALSE;
  1027. break;
  1028. }
  1029. if (CharToken)
  1030. {
  1031. m_Lex--;
  1032. AddLexeme(0);
  1033. return (CppToken)Ch;
  1034. }
  1035. }
  1036. DBG_ASSERT(!"Abnormal exit in CppLex");
  1037. return CppTokenError;
  1038. }
  1039. void
  1040. CppEvalExpression::NextToken(void)
  1041. {
  1042. m_Token = Lex();
  1043. #if DBG_TOKENS
  1044. dprintf("Token is %s (%s)\n", TokenImage(m_Token), m_LexemeStart);
  1045. #endif
  1046. }
  1047. void
  1048. CppEvalExpression::Match(CppToken Token)
  1049. {
  1050. if (m_Token != Token)
  1051. {
  1052. EvalErrorDesc(SYNTAX, "Unexpected token");
  1053. }
  1054. NextToken();
  1055. }
  1056. PCSTR
  1057. CppEvalExpression::Evaluate(PCSTR Expr, PCSTR Desc, ULONG Flags,
  1058. TypedData* Result)
  1059. {
  1060. Start(Expr, Desc, Flags);
  1061. NextToken();
  1062. if (m_Flags & EXPRF_SINGLE_TERM)
  1063. {
  1064. Match(CppTokenOpenBracket);
  1065. Expression(Result);
  1066. Match(CppTokenCloseBracket);
  1067. }
  1068. else
  1069. {
  1070. Expression(Result);
  1071. }
  1072. End(Result);
  1073. return m_LexemeSourceStart;
  1074. }
  1075. PCSTR
  1076. CppEvalExpression::EvaluateAddr(PCSTR Expr, PCSTR Desc,
  1077. ULONG SegReg, PADDR Addr)
  1078. {
  1079. // This result must be on the stack so it
  1080. // isn't caught by the empty-allocator check in end.
  1081. TypedData Result;
  1082. Start(Expr, Desc, EXPRF_DEFAULT);
  1083. NextToken();
  1084. Expression(&Result);
  1085. End(&Result);
  1086. EvalCheck(Result.ConvertToU64());
  1087. ADDRFLAT(Addr, Result.m_U64);
  1088. return m_LexemeSourceStart;
  1089. }
  1090. void
  1091. CppEvalExpression::Expression(TypedData* Result)
  1092. {
  1093. for (;;)
  1094. {
  1095. Assignment(Result);
  1096. if (m_Token == CppTokenComma)
  1097. {
  1098. Accept();
  1099. }
  1100. else
  1101. {
  1102. break;
  1103. }
  1104. }
  1105. }
  1106. void
  1107. CppEvalExpression::Assignment(TypedData* Result)
  1108. {
  1109. TypedDataOp Op;
  1110. Conditional(Result);
  1111. switch(m_Token)
  1112. {
  1113. case '=':
  1114. Op = TDOP_ASSIGN;
  1115. break;
  1116. case CppTokenDivideAssign:
  1117. Op = TDOP_DIVIDE;
  1118. break;
  1119. case CppTokenMultiplyAssign:
  1120. Op = TDOP_MULTIPLY;
  1121. break;
  1122. case CppTokenModuloAssign:
  1123. Op = TDOP_REMAINDER;
  1124. break;
  1125. case CppTokenAddAssign:
  1126. Op = TDOP_ADD;
  1127. break;
  1128. case CppTokenSubtractAssign:
  1129. Op = TDOP_SUBTRACT;
  1130. break;
  1131. case CppTokenLeftShiftAssign:
  1132. Op = TDOP_LEFT_SHIFT;
  1133. break;
  1134. case CppTokenRightShiftAssign:
  1135. Op = TDOP_RIGHT_SHIFT;
  1136. break;
  1137. case CppTokenAndAssign:
  1138. Op = TDOP_BIT_AND;
  1139. break;
  1140. case CppTokenOrAssign:
  1141. Op = TDOP_BIT_OR;
  1142. break;
  1143. case CppTokenExclusiveOrAssign:
  1144. Op = TDOP_BIT_XOR;
  1145. break;
  1146. default:
  1147. return;
  1148. }
  1149. if (!Result->IsWritable())
  1150. {
  1151. EvalError(TYPECONFLICT);
  1152. }
  1153. Accept();
  1154. TypedData* Next = NewResult();
  1155. Assignment(Next);
  1156. switch(Op)
  1157. {
  1158. case TDOP_ASSIGN:
  1159. m_Tmp = *Next;
  1160. EvalCheck(m_Tmp.ConvertToSource(Result));
  1161. break;
  1162. case TDOP_ADD:
  1163. case TDOP_SUBTRACT:
  1164. case TDOP_MULTIPLY:
  1165. case TDOP_DIVIDE:
  1166. case TDOP_REMAINDER:
  1167. // Carry out the operation in a temporary as the
  1168. // address will be wiped out by the operation.
  1169. m_Tmp = *Result;
  1170. EvalCheck(m_Tmp.BinaryArithmetic(Next, Op));
  1171. // The result may be of a different type due
  1172. // to promotions or other implicit conversions.
  1173. // Force conversion to the actual result type.
  1174. EvalCheck(m_Tmp.ConvertTo(Result));
  1175. break;
  1176. case TDOP_LEFT_SHIFT:
  1177. case TDOP_RIGHT_SHIFT:
  1178. m_Tmp = *Result;
  1179. EvalCheck(m_Tmp.Shift(Next, Op));
  1180. EvalCheck(m_Tmp.ConvertTo(Result));
  1181. break;
  1182. case TDOP_BIT_OR:
  1183. case TDOP_BIT_XOR:
  1184. case TDOP_BIT_AND:
  1185. m_Tmp = *Result;
  1186. EvalCheck(m_Tmp.BinaryBitwise(Next, Op));
  1187. EvalCheck(m_Tmp.ConvertTo(Result));
  1188. break;
  1189. }
  1190. // Source and destination types should be compatible
  1191. // at this point to copy the data.
  1192. EvalCheck(Result->WriteData(&m_Tmp, CurrentAccess()));
  1193. Result->CopyData(&m_Tmp);
  1194. DelResult(Next);
  1195. }
  1196. void
  1197. CppEvalExpression::Conditional(TypedData* Result)
  1198. {
  1199. TypedData* Discard;
  1200. TypedData* Left, *Right;
  1201. LogicalOr(Result);
  1202. if (m_Token != CppTokenQuestionMark)
  1203. {
  1204. return;
  1205. }
  1206. EvalCheck(Result->ConvertToBool());
  1207. Accept();
  1208. Discard = NewResult();
  1209. if (Result->m_Bool)
  1210. {
  1211. Left = Result;
  1212. Right = Discard;
  1213. }
  1214. else
  1215. {
  1216. Left = Discard;
  1217. Right = Result;
  1218. m_ParseOnly++;
  1219. }
  1220. Expression(Left);
  1221. Match(CppTokenColon);
  1222. if (Right == Discard)
  1223. {
  1224. m_ParseOnly++;
  1225. }
  1226. else
  1227. {
  1228. m_ParseOnly--;
  1229. }
  1230. Conditional(Right);
  1231. if (Right == Discard)
  1232. {
  1233. m_ParseOnly--;
  1234. }
  1235. DelResult(Discard);
  1236. }
  1237. void
  1238. CppEvalExpression::LogicalOr(TypedData* Result)
  1239. {
  1240. LogicalAnd(Result);
  1241. for (;;)
  1242. {
  1243. TypedData* Next;
  1244. switch(m_Token)
  1245. {
  1246. case CppTokenLogicalOr:
  1247. EvalCheck(Result->ConvertToBool());
  1248. Accept();
  1249. if (Result->m_Bool)
  1250. {
  1251. m_ParseOnly++;
  1252. }
  1253. Next = NewResult();
  1254. LogicalAnd(Next);
  1255. EvalCheck(Next->ConvertToBool());
  1256. if (Result->m_Bool)
  1257. {
  1258. m_ParseOnly--;
  1259. }
  1260. else
  1261. {
  1262. Result->m_Bool = Result->m_Bool || Next->m_Bool;
  1263. }
  1264. DelResult(Next);
  1265. break;
  1266. default:
  1267. return;
  1268. }
  1269. }
  1270. }
  1271. void
  1272. CppEvalExpression::LogicalAnd(TypedData* Result)
  1273. {
  1274. BitwiseOr(Result);
  1275. for (;;)
  1276. {
  1277. TypedData* Next;
  1278. switch(m_Token)
  1279. {
  1280. case CppTokenLogicalAnd:
  1281. EvalCheck(Result->ConvertToBool());
  1282. Accept();
  1283. if (!Result->m_Bool)
  1284. {
  1285. m_ParseOnly++;
  1286. }
  1287. Next = NewResult();
  1288. BitwiseOr(Next);
  1289. EvalCheck(Next->ConvertToBool());
  1290. if (!Result->m_Bool)
  1291. {
  1292. m_ParseOnly--;
  1293. }
  1294. else
  1295. {
  1296. Result->m_Bool = Result->m_Bool && Next->m_Bool;
  1297. }
  1298. DelResult(Next);
  1299. break;
  1300. default:
  1301. return;
  1302. }
  1303. }
  1304. }
  1305. void
  1306. CppEvalExpression::BitwiseOr(TypedData* Result)
  1307. {
  1308. BitwiseXor(Result);
  1309. for (;;)
  1310. {
  1311. TypedData* Next;
  1312. switch(m_Token)
  1313. {
  1314. case '|':
  1315. Accept();
  1316. Next = NewResult();
  1317. BitwiseXor(Next);
  1318. EvalCheck(Result->BinaryBitwise(Next, TDOP_BIT_OR));
  1319. DelResult(Next);
  1320. break;
  1321. default:
  1322. return;
  1323. }
  1324. }
  1325. }
  1326. void
  1327. CppEvalExpression::BitwiseXor(TypedData* Result)
  1328. {
  1329. BitwiseAnd(Result);
  1330. for (;;)
  1331. {
  1332. TypedData* Next;
  1333. switch(m_Token)
  1334. {
  1335. case '^':
  1336. Accept();
  1337. Next = NewResult();
  1338. BitwiseAnd(Next);
  1339. EvalCheck(Result->BinaryBitwise(Next, TDOP_BIT_XOR));
  1340. DelResult(Next);
  1341. break;
  1342. default:
  1343. return;
  1344. }
  1345. }
  1346. }
  1347. void
  1348. CppEvalExpression::BitwiseAnd(TypedData* Result)
  1349. {
  1350. Equality(Result);
  1351. for (;;)
  1352. {
  1353. TypedData* Next;
  1354. switch(m_Token)
  1355. {
  1356. case '&':
  1357. Accept();
  1358. Next = NewResult();
  1359. Equality(Next);
  1360. EvalCheck(Result->BinaryBitwise(Next, TDOP_BIT_AND));
  1361. DelResult(Next);
  1362. break;
  1363. default:
  1364. return;
  1365. }
  1366. }
  1367. }
  1368. void
  1369. CppEvalExpression::Equality(TypedData* Result)
  1370. {
  1371. Relational(Result);
  1372. for (;;)
  1373. {
  1374. TypedDataOp Op;
  1375. switch(m_Token)
  1376. {
  1377. case CppTokenEqual:
  1378. Op = TDOP_EQUAL;
  1379. break;
  1380. case CppTokenNotEqual:
  1381. Op = TDOP_NOT_EQUAL;
  1382. break;
  1383. default:
  1384. return;
  1385. }
  1386. Accept();
  1387. TypedData* Next = NewResult();
  1388. Relational(Next);
  1389. EvalCheck(Result->Relate(Next, Op));
  1390. DelResult(Next);
  1391. }
  1392. }
  1393. void
  1394. CppEvalExpression::Relational(TypedData* Result)
  1395. {
  1396. Shift(Result);
  1397. for (;;)
  1398. {
  1399. TypedDataOp Op;
  1400. switch(m_Token)
  1401. {
  1402. case '<':
  1403. Op = TDOP_LESS;
  1404. break;
  1405. case '>':
  1406. Op = TDOP_GREATER;
  1407. break;
  1408. case CppTokenLessEqual:
  1409. Op = TDOP_LESS_EQUAL;
  1410. break;
  1411. case CppTokenGreaterEqual:
  1412. Op = TDOP_GREATER_EQUAL;
  1413. break;
  1414. default:
  1415. return;
  1416. }
  1417. Accept();
  1418. TypedData* Next = NewResult();
  1419. Shift(Next);
  1420. EvalCheck(Result->Relate(Next, Op));
  1421. DelResult(Next);
  1422. }
  1423. }
  1424. void
  1425. CppEvalExpression::Shift(TypedData* Result)
  1426. {
  1427. Additive(Result);
  1428. for (;;)
  1429. {
  1430. TypedDataOp Op;
  1431. switch(m_Token)
  1432. {
  1433. case CppTokenLeftShift:
  1434. Op = TDOP_LEFT_SHIFT;
  1435. break;
  1436. case CppTokenRightShift:
  1437. Op = TDOP_RIGHT_SHIFT;
  1438. break;
  1439. default:
  1440. return;
  1441. }
  1442. Accept();
  1443. TypedData* Next = NewResult();
  1444. Additive(Next);
  1445. EvalCheck(Result->Shift(Next, Op));
  1446. DelResult(Next);
  1447. }
  1448. }
  1449. void
  1450. CppEvalExpression::Additive(TypedData* Result)
  1451. {
  1452. Multiplicative(Result);
  1453. for (;;)
  1454. {
  1455. TypedDataOp Op;
  1456. switch(m_Token)
  1457. {
  1458. case '+':
  1459. Op = TDOP_ADD;
  1460. break;
  1461. case '-':
  1462. Op = TDOP_SUBTRACT;
  1463. break;
  1464. default:
  1465. return;
  1466. }
  1467. Accept();
  1468. TypedData* Next = NewResult();
  1469. Multiplicative(Next);
  1470. EvalCheck(Result->BinaryArithmetic(Next, Op));
  1471. DelResult(Next);
  1472. }
  1473. }
  1474. void
  1475. CppEvalExpression::Multiplicative(TypedData* Result)
  1476. {
  1477. ClassMemberRef(Result);
  1478. for (;;)
  1479. {
  1480. TypedDataOp Op;
  1481. switch(m_Token)
  1482. {
  1483. case '*':
  1484. Op = TDOP_MULTIPLY;
  1485. break;
  1486. case '/':
  1487. Op = TDOP_DIVIDE;
  1488. break;
  1489. case '%':
  1490. Op = TDOP_REMAINDER;
  1491. break;
  1492. default:
  1493. return;
  1494. }
  1495. Accept();
  1496. TypedData* Next = NewResult();
  1497. ClassMemberRef(Next);
  1498. EvalCheck(Result->BinaryArithmetic(Next, Op));
  1499. DelResult(Next);
  1500. }
  1501. }
  1502. void
  1503. CppEvalExpression::ClassMemberRef(TypedData* Result)
  1504. {
  1505. Cast(Result);
  1506. for (;;)
  1507. {
  1508. //
  1509. // Calling through pointers to members isn't
  1510. // supported, just as normal function calls
  1511. // aren't supported. We could potentially
  1512. // determine the actual method value for
  1513. // simple references to methods but there's
  1514. // virtual no need for that, so just fail
  1515. // these constructs.
  1516. //
  1517. switch(m_Token)
  1518. {
  1519. case CppTokenClassDereference:
  1520. case CppTokenClassPointerMember:
  1521. EvalErrorDesc(UNIMPLEMENT,
  1522. "Pointer to member evaluation is not supported");
  1523. break;
  1524. default:
  1525. return;
  1526. }
  1527. }
  1528. }
  1529. void
  1530. CppEvalExpression::Cast(TypedData* Result)
  1531. {
  1532. if (m_Token == '(')
  1533. {
  1534. PCSTR LexRestart = m_Lex;
  1535. Accept();
  1536. if (TryTypeName(Result) == ERES_TYPE)
  1537. {
  1538. //
  1539. // It was a type name, so process the cast.
  1540. //
  1541. TypedData* CastType = NewResult();
  1542. *CastType = *Result;
  1543. // Unary is allowed after a cast.
  1544. m_AllowUnaryOp = TRUE;
  1545. Match(CppTokenCloseParen);
  1546. Cast(Result);
  1547. EvalCheck(Result->CastTo(CastType));
  1548. DelResult(CastType);
  1549. return;
  1550. }
  1551. else
  1552. {
  1553. // It wasn't a type, so restart the lexer
  1554. // and reparse as an expression.
  1555. StartLexer(LexRestart);
  1556. strcpy(m_LexemeStart, "(");
  1557. m_Token = CppTokenOpenParen;
  1558. }
  1559. }
  1560. Unary(Result);
  1561. }
  1562. void
  1563. CppEvalExpression::Unary(TypedData* Result)
  1564. {
  1565. CppToken Op = m_Token;
  1566. switch(Op)
  1567. {
  1568. case CppTokenSizeof:
  1569. Accept();
  1570. if (m_Token == '(')
  1571. {
  1572. PCSTR LexRestart = m_Lex;
  1573. Accept();
  1574. if (TryTypeName(Result) == ERES_TYPE)
  1575. {
  1576. // It was a type name.
  1577. Match(CppTokenCloseParen);
  1578. }
  1579. else
  1580. {
  1581. // It wasn't a type, so restart the lexer
  1582. // and reparse as an expression.
  1583. StartLexer(LexRestart);
  1584. strcpy(m_LexemeStart, "(");
  1585. m_Token = CppTokenOpenParen;
  1586. Unary(Result);
  1587. }
  1588. }
  1589. else
  1590. {
  1591. Unary(Result);
  1592. }
  1593. Result->m_U64 = Result->m_BaseSize;
  1594. Result->SetToNativeType(m_PtrSize == sizeof(ULONG64) ?
  1595. DNTYPE_UINT64 : DNTYPE_UINT32);
  1596. break;
  1597. case CppTokenUnaryPlus:
  1598. case CppTokenUnaryMinus:
  1599. case '~':
  1600. Accept();
  1601. Cast(Result);
  1602. if (Op == CppTokenUnaryPlus)
  1603. {
  1604. // Nothing to do.
  1605. break;
  1606. }
  1607. EvalCheck(Result->Unary(Op == CppTokenUnaryMinus ?
  1608. TDOP_NEGATE : TDOP_BIT_NOT));
  1609. break;
  1610. case '!':
  1611. Accept();
  1612. Cast(Result);
  1613. EvalCheck(Result->ConvertToBool());
  1614. Result->m_Bool = !Result->m_Bool;
  1615. break;
  1616. case CppTokenAddressOf:
  1617. Accept();
  1618. Cast(Result);
  1619. if (!Result->HasAddress())
  1620. {
  1621. EvalErrorDesc(SYNTAX, "No address for operator&");
  1622. }
  1623. EvalCheck(Result->ConvertToAddressOf(FALSE, m_PtrSize));
  1624. #if DBG_TYPES
  1625. dprintf("& -> id %s!%x, base %x, size %x\n",
  1626. Result->m_Image ? Result->m_Image->m_ModuleName : "<>",
  1627. Result->m_Type, Result->m_BaseType, Result->m_BaseSize);
  1628. #endif
  1629. break;
  1630. case CppTokenDereference:
  1631. Accept();
  1632. Cast(Result);
  1633. if (!Result->IsPointer())
  1634. {
  1635. EvalErrorDesc(SYNTAX, "No pointer for operator*");
  1636. }
  1637. EvalCheck(Result->ConvertToDereference(CurrentAccess(), m_PtrSize));
  1638. #if DBG_TYPES
  1639. dprintf("* -> id %s!%x, base %x, size %x\n",
  1640. Result->m_Image ? Result->m_Image->m_ModuleName : "<>",
  1641. Result->m_Type, Result->m_BaseType, Result->m_BaseSize);
  1642. #endif
  1643. break;
  1644. case CppTokenPreIncrement:
  1645. case CppTokenPreDecrement:
  1646. Accept();
  1647. Unary(Result);
  1648. if (!Result->IsInteger() && !Result->IsPointer())
  1649. {
  1650. EvalError(TYPECONFLICT);
  1651. }
  1652. // Carry out the operation in a temporary as the
  1653. // address will be wiped out by the operation.
  1654. m_Tmp = *Result;
  1655. if ((m_Err = m_Tmp.ConstIntOp(Op == CppTokenPreIncrement ? 1 : -1,
  1656. TRUE, TDOP_ADD)) ||
  1657. (m_Err = Result->WriteData(&m_Tmp, CurrentAccess())))
  1658. {
  1659. EvalError(m_Err);
  1660. }
  1661. Result->CopyData(&m_Tmp);
  1662. break;
  1663. default:
  1664. Postfix(Result);
  1665. break;
  1666. }
  1667. }
  1668. void
  1669. CppEvalExpression::Postfix(TypedData* Result)
  1670. {
  1671. TypedData* Next;
  1672. if (m_Token == CppTokenDynamicCast ||
  1673. m_Token == CppTokenStaticCast ||
  1674. m_Token == CppTokenConstCast ||
  1675. m_Token == CppTokenReinterpretCast)
  1676. {
  1677. // Don't bother trying to emulate
  1678. // the precise rules on casting for
  1679. // these operators, just cast.
  1680. Accept();
  1681. Match(CppTokenOpenAngle);
  1682. Next = NewResult();
  1683. if (TryTypeName(Next) != ERES_TYPE)
  1684. {
  1685. EvalError(TYPECONFLICT);
  1686. }
  1687. Match(CppTokenCloseAngle);
  1688. Match(CppTokenOpenParen);
  1689. Expression(Result);
  1690. Match(CppTokenCloseParen);
  1691. EvalCheck(Result->CastTo(Next));
  1692. DelResult(Next);
  1693. return;
  1694. }
  1695. Term(Result);
  1696. for (;;)
  1697. {
  1698. CppToken Op = m_Token;
  1699. switch(Op)
  1700. {
  1701. case '.':
  1702. if (!Result->IsUdt())
  1703. {
  1704. EvalErrorDesc(TYPECONFLICT,
  1705. "Type is not struct/class/union for operator.");
  1706. }
  1707. Accept();
  1708. UdtMember(Result);
  1709. break;
  1710. case CppTokenPointerMember:
  1711. if (!Result->IsPointer())
  1712. {
  1713. EvalErrorDesc(TYPECONFLICT,
  1714. "Type is not pointer for operator->");
  1715. }
  1716. Accept();
  1717. UdtMember(Result);
  1718. break;
  1719. case '[':
  1720. if (Result->IsArray())
  1721. {
  1722. // There's no need to do a full address convert
  1723. // as all we're going to do is deref later.
  1724. EvalCheck(Result->GetAbsoluteAddress(&Result->m_Ptr));
  1725. }
  1726. else if (!Result->IsPointer())
  1727. {
  1728. EvalErrorDesc(TYPECONFLICT,
  1729. "Type is not a pointer for operator[]");
  1730. }
  1731. if (!Result->m_NextSize)
  1732. {
  1733. EvalError(TYPECONFLICT);
  1734. }
  1735. Accept();
  1736. Next = NewResult();
  1737. Expression(Next);
  1738. if (!Next->IsInteger())
  1739. {
  1740. EvalErrorDesc(TYPECONFLICT,
  1741. "Array index not integral");
  1742. }
  1743. EvalCheck(Next->ConvertToU64());
  1744. Result->m_Ptr += Next->m_U64 * Result->m_NextSize;
  1745. DelResult(Next);
  1746. EvalCheck(Result->
  1747. ConvertToDereference(CurrentAccess(), m_PtrSize));
  1748. Match(CppTokenCloseBracket);
  1749. break;
  1750. case CppTokenPostIncrement:
  1751. case CppTokenPostDecrement:
  1752. if (!Result->IsInteger() && !Result->IsPointer())
  1753. {
  1754. EvalError(TYPECONFLICT);
  1755. }
  1756. m_Tmp = *Result;
  1757. if ((m_Err = m_Tmp.ConstIntOp(Op == CppTokenPostIncrement ? 1 : -1,
  1758. TRUE, TDOP_ADD)) ||
  1759. (m_Err = Result->WriteData(&m_Tmp, CurrentAccess())))
  1760. {
  1761. EvalError(m_Err);
  1762. }
  1763. Accept();
  1764. break;
  1765. default:
  1766. return;
  1767. }
  1768. }
  1769. }
  1770. void
  1771. CppEvalExpression::Term(TypedData* Result)
  1772. {
  1773. EVAL_RESULT_KIND IdKind;
  1774. switch(m_Token)
  1775. {
  1776. case CppTokenInteger:
  1777. case CppTokenFloat:
  1778. case CppTokenWchar:
  1779. case CppTokenChar:
  1780. *Result = m_TokenValue;
  1781. #if DBG_TYPES
  1782. dprintf("%s -> id %s!%x, base %x, size %x\n",
  1783. m_LexemeStart,
  1784. Result->m_Image ? Result->m_Image->m_ModuleName : "<>",
  1785. Result->m_Type, Result->m_BaseType, Result->m_BaseSize);
  1786. #endif
  1787. Accept();
  1788. break;
  1789. case CppTokenWcharString:
  1790. case CppTokenCharString:
  1791. EvalErrorDesc(SYNTAX, "String literals not allowed in");
  1792. case CppTokenIdentifier:
  1793. IdKind = CollectTypeOrSymbolName(Result);
  1794. if (IdKind == ERES_TYPE)
  1795. {
  1796. TypedData* Type = NewResult();
  1797. *Type = *Result;
  1798. Match(CppTokenOpenParen);
  1799. Expression(Result);
  1800. Match(CppTokenCloseParen);
  1801. EvalCheck(Result->CastTo(Type));
  1802. DelResult(Type);
  1803. }
  1804. else if (IdKind == ERES_SYMBOL)
  1805. {
  1806. #if DBG_TYPES
  1807. dprintf("symbol -> id %s!%x, base %x, size %x\n",
  1808. Result->m_Image ? Result->m_Image->m_ModuleName : "<>",
  1809. Result->m_Type, Result->m_BaseType, Result->m_BaseSize);
  1810. #endif
  1811. }
  1812. else
  1813. {
  1814. EvalError(VARDEF);
  1815. }
  1816. break;
  1817. case CppTokenThis:
  1818. if (!m_Process)
  1819. {
  1820. EvalError(BADPROCESS);
  1821. }
  1822. EvalCheck(Result->FindSymbol(m_Process, m_LexemeStart,
  1823. CurrentAccess(), m_PtrSize));
  1824. #if DBG_TYPES
  1825. dprintf("%s -> id %s!%x, base %x, size %x\n",
  1826. m_LexemeStart,
  1827. Result->m_Image ? Result->m_Image->m_ModuleName : "<>",
  1828. Result->m_Type, Result->m_BaseType, Result->m_BaseSize);
  1829. #endif
  1830. Accept();
  1831. break;
  1832. case '(':
  1833. Accept();
  1834. Expression(Result);
  1835. Match(CppTokenCloseParen);
  1836. break;
  1837. case CppTokenDebugRegister:
  1838. // Skip @ at the beginning.
  1839. if (!GetPsuedoOrRegTypedData(TRUE, m_LexemeStart + 1, Result))
  1840. {
  1841. if (GetOffsetFromBreakpoint(m_LexemeStart + 1, &Result->m_U64))
  1842. {
  1843. Result->SetToNativeType(DNTYPE_UINT64);
  1844. Result->ClearAddress();
  1845. }
  1846. else
  1847. {
  1848. EvalError(VARDEF);
  1849. }
  1850. }
  1851. #if DBG_TYPES
  1852. dprintf("%s -> id %s!%x, base %x, size %x\n",
  1853. m_LexemeStart,
  1854. Result->m_Image ? Result->m_Image->m_ModuleName : "<>",
  1855. Result->m_Type, Result->m_BaseType, Result->m_BaseSize);
  1856. #endif
  1857. Accept();
  1858. break;
  1859. case CppTokenModule:
  1860. // Skip the @! at the beginning.
  1861. if (g_Process->GetOffsetFromMod(m_LexemeStart + 2, &Result->m_U64))
  1862. {
  1863. Result->SetToNativeType(DNTYPE_UINT64);
  1864. Result->ClearAddress();
  1865. }
  1866. else
  1867. {
  1868. EvalError(VARDEF);
  1869. }
  1870. Accept();
  1871. break;
  1872. case CppTokenSwitchEvalExpression:
  1873. EvalExpression* Eval;
  1874. PSTR ExprStart;
  1875. Eval = GetEvaluator(m_SwitchEvalSyntax, FALSE);
  1876. Eval->InheritStart(this);
  1877. // Allow all nested evaluators to get cleaned up.
  1878. Eval->m_ChainTop = FALSE;
  1879. ExprStart = m_LexemeStart + 2;
  1880. while (*ExprStart && *ExprStart != '(')
  1881. {
  1882. ExprStart++;
  1883. }
  1884. Eval->Evaluate(ExprStart, NULL, EXPRF_DEFAULT, Result);
  1885. Eval->InheritEnd(this);
  1886. ReleaseEvaluator(Eval);
  1887. Accept();
  1888. break;
  1889. case CppTokenPreprocFunction:
  1890. PreprocFunction(Result);
  1891. break;
  1892. default:
  1893. EvalErrorDesc(SYNTAX, m_ExprDesc);
  1894. }
  1895. }
  1896. EVAL_RESULT_KIND
  1897. CppEvalExpression::TryTypeName(TypedData* Result)
  1898. {
  1899. //
  1900. // If the following tokens can be evaluated as
  1901. // a type then do so, otherwise exit.
  1902. //
  1903. if (CollectTypeOrSymbolName(Result) == ERES_TYPE)
  1904. {
  1905. BOOL Scan = TRUE;
  1906. while (Scan)
  1907. {
  1908. TypedData* Elements;
  1909. switch(m_Token)
  1910. {
  1911. case '*':
  1912. case CppTokenDereference:
  1913. EvalCheck(Result->ConvertToAddressOf(TRUE, m_PtrSize));
  1914. Accept();
  1915. break;
  1916. case '[':
  1917. Elements = NewResult();
  1918. Accept();
  1919. if (m_Token != ']')
  1920. {
  1921. Conditional(Elements);
  1922. if (!Elements->IsInteger())
  1923. {
  1924. EvalErrorDesc(SYNTAX, "Array length not integral");
  1925. }
  1926. EvalCheck(Elements->ConvertToU64());
  1927. Elements->m_U64 *= Result->m_BaseSize;
  1928. }
  1929. else
  1930. {
  1931. // For a elementless array make it the same
  1932. // size as a pointer as that's essentially.
  1933. // what it is.
  1934. Elements->m_U64 = m_PtrSize;
  1935. }
  1936. Match(CppTokenCloseBracket);
  1937. EvalCheck(Result->ConvertToArray((ULONG)Elements->m_U64));
  1938. DelResult(Elements);
  1939. break;
  1940. default:
  1941. Scan = FALSE;
  1942. break;
  1943. }
  1944. }
  1945. #if DBG_TYPES
  1946. dprintf("type -> id %s!%x, base %x, size %x\n",
  1947. Result->m_Image ? Result->m_Image->m_ModuleName : "<>",
  1948. Result->m_Type, Result->m_BaseType, Result->m_BaseSize);
  1949. #endif
  1950. return ERES_TYPE;
  1951. }
  1952. else
  1953. {
  1954. // It wasn't a cast, let the caller handle it.
  1955. return ERES_UNKNOWN;
  1956. }
  1957. }
  1958. EVAL_RESULT_KIND
  1959. CppEvalExpression::CollectTypeOrSymbolName(TypedData* Result)
  1960. {
  1961. EVAL_RESULT_KIND ResKind = ERES_UNKNOWN;
  1962. CppToken LastToken = CppTokenError;
  1963. PCSTR SourceStart = m_LexemeSourceStart;
  1964. ULONG Len;
  1965. for (;;)
  1966. {
  1967. if (IsTypeKeyword(m_Token))
  1968. {
  1969. if (!(LastToken == CppTokenError ||
  1970. LastToken == CppTokenIdentifier ||
  1971. IsTypeKeyword(LastToken)) ||
  1972. (ResKind != ERES_TYPE && ResKind != ERES_UNKNOWN))
  1973. {
  1974. break;
  1975. }
  1976. m_LexemeRestart += strlen(m_LexemeRestart);
  1977. *m_LexemeRestart++ = ' ';
  1978. *m_LexemeRestart = 0;
  1979. LastToken = m_Token;
  1980. Accept();
  1981. ResKind = ERES_TYPE;
  1982. }
  1983. else if (m_Token == CppTokenIdentifier)
  1984. {
  1985. if (LastToken == CppTokenIdentifier)
  1986. {
  1987. break;
  1988. }
  1989. m_LexemeRestart += strlen(m_LexemeRestart);
  1990. *m_LexemeRestart++ = ' ';
  1991. *m_LexemeRestart = 0;
  1992. LastToken = m_Token;
  1993. Accept();
  1994. }
  1995. else if (m_Token == CppTokenModule)
  1996. {
  1997. if (LastToken != CppTokenError)
  1998. {
  1999. break;
  2000. }
  2001. // Back up over @!.
  2002. Len = strlen(m_LexemeRestart) - 2;
  2003. memmove(m_LexemeRestart, m_LexemeRestart + 2, Len);
  2004. m_LexemeRestart += Len;
  2005. *m_LexemeRestart++ = ' ';
  2006. *m_LexemeRestart = 0;
  2007. LastToken = m_Token;
  2008. Accept();
  2009. }
  2010. else if (m_Token == CppTokenNameQualifier ||
  2011. m_Token == CppTokenDestructor)
  2012. {
  2013. if (LastToken != CppTokenIdentifier &&
  2014. LastToken != CppTokenCloseAngle)
  2015. {
  2016. break;
  2017. }
  2018. //
  2019. // Some kind of member reference so keep collecting.
  2020. //
  2021. // Eliminate unnecessary space after identifier.
  2022. Len = strlen(m_LexemeRestart) + 1;
  2023. memmove(m_LexemeRestart - 1, m_LexemeRestart, Len);
  2024. m_LexemeRestart += Len - 2;
  2025. LastToken = m_Token;
  2026. Accept();
  2027. }
  2028. else if (m_Token == '!')
  2029. {
  2030. if (LastToken != CppTokenIdentifier &&
  2031. LastToken != CppTokenModule)
  2032. {
  2033. break;
  2034. }
  2035. //
  2036. // Special syntax to allow module scoping for symbols.
  2037. //
  2038. // Eliminate unnecessary space after identifier.
  2039. *(m_LexemeRestart - 1) = (char)m_Token;
  2040. *m_LexemeRestart = 0;
  2041. LastToken = m_Token;
  2042. Accept();
  2043. }
  2044. else if (m_Token == CppTokenOpenAngle)
  2045. {
  2046. if (LastToken != CppTokenIdentifier)
  2047. {
  2048. break;
  2049. }
  2050. if (CollectTemplateName() == ERES_UNKNOWN)
  2051. {
  2052. break;
  2053. }
  2054. *++m_LexemeRestart = 0;
  2055. LastToken = m_Token;
  2056. Accept();
  2057. }
  2058. else if (m_Token == CppTokenOperator)
  2059. {
  2060. if (LastToken != CppTokenError &&
  2061. LastToken != '!' &&
  2062. LastToken != CppTokenNameQualifier)
  2063. {
  2064. break;
  2065. }
  2066. // Set LastToken first so it's CppTokenOperator for
  2067. // all operators.
  2068. LastToken = m_Token;
  2069. ResKind = ERES_SYMBOL;
  2070. CollectOperatorName();
  2071. }
  2072. else
  2073. {
  2074. break;
  2075. }
  2076. }
  2077. if (LastToken == CppTokenNameQualifier ||
  2078. LastToken == CppTokenDestructor ||
  2079. LastToken == '!')
  2080. {
  2081. // Incomplete name.
  2082. m_LexemeSourceStart = SourceStart;
  2083. EvalErrorDesc(SYNTAX, "Incomplete symbol or type name");
  2084. }
  2085. if (LastToken == CppTokenModule)
  2086. {
  2087. // If the last token was a module name assume this
  2088. // is a plain module name expression.
  2089. return ERES_EXPRESSION;
  2090. }
  2091. PSTR End;
  2092. char Save;
  2093. End = m_LexemeRestart;
  2094. if (End > m_LexemeBuffer && *(End - 1) == ' ')
  2095. {
  2096. End--;
  2097. }
  2098. if (!m_Process || End == m_LexemeBuffer)
  2099. {
  2100. // Can't look anything up without a process or name.
  2101. return ERES_UNKNOWN;
  2102. }
  2103. Save = *End;
  2104. *End = 0;
  2105. // Clear the data address up front for the type cases
  2106. // with no addresses.
  2107. Result->ClearAddress();
  2108. Result->ClearData();
  2109. m_Err = VARDEF;
  2110. if (ResKind != ERES_SYMBOL)
  2111. {
  2112. // First check for a built-in type as this greatly speeds
  2113. // up references to them. This should always be legal
  2114. // because they're keywords so they can't be overriden
  2115. // by symbols.
  2116. PDBG_NATIVE_TYPE Native = FindNativeTypeByName(m_LexemeBuffer);
  2117. if (Native)
  2118. {
  2119. Result->SetToNativeType(DbgNativeTypeId(Native));
  2120. m_Err = NO_ERROR;
  2121. ResKind = ERES_TYPE;
  2122. }
  2123. }
  2124. if (m_Err && ResKind != ERES_TYPE)
  2125. {
  2126. m_Err = Result->FindSymbol(m_Process, m_LexemeBuffer,
  2127. CurrentAccess(), m_PtrSize);
  2128. if (!m_Err)
  2129. {
  2130. ResKind = ERES_SYMBOL;
  2131. }
  2132. }
  2133. if (m_Err && ResKind != ERES_SYMBOL)
  2134. {
  2135. m_Err = Result->FindType(m_Process, m_LexemeBuffer, m_PtrSize);
  2136. if (!m_Err)
  2137. {
  2138. ResKind = ERES_TYPE;
  2139. }
  2140. }
  2141. if (m_Err)
  2142. {
  2143. if (m_AllowUnresolvedSymbols)
  2144. {
  2145. // Always assume that unresolved symbols are symbols.
  2146. m_NumUnresolvedSymbols++;
  2147. ResKind = ERES_SYMBOL;
  2148. }
  2149. else
  2150. {
  2151. m_LexemeSourceStart = SourceStart;
  2152. EvalError(m_Err);
  2153. }
  2154. }
  2155. *End = Save;
  2156. m_LexemeRestart = m_LexemeBuffer;
  2157. return ResKind;
  2158. }
  2159. EVAL_RESULT_KIND
  2160. CppEvalExpression::CollectTemplateName(void)
  2161. {
  2162. EVAL_RESULT_KIND ResKind;
  2163. //
  2164. // Templates are difficult to distinguish from
  2165. // normal arithmetic expressions. Do a prefix
  2166. // search for any symbol starting with what we
  2167. // have so far and a <. If something hits, assume
  2168. // that this is a template reference and consume
  2169. // everything to a matching >.
  2170. //
  2171. if (!m_Process)
  2172. {
  2173. // Can't look up anything without a process.
  2174. return ERES_UNKNOWN;
  2175. }
  2176. // Eliminate unnecessary space after identifier.
  2177. *(m_LexemeRestart - 1) = (char)m_Token;
  2178. *m_LexemeRestart++ = '*';
  2179. *m_LexemeRestart = 0;
  2180. //
  2181. // Check for a symbol or type match.
  2182. //
  2183. SYMBOL_INFO SymInfo = {0};
  2184. if (!SymFromName(m_Process->m_SymHandle, m_LexemeBuffer, &SymInfo))
  2185. {
  2186. PSTR ModNameEnd;
  2187. ImageInfo* Mod, *ModList;
  2188. ModNameEnd = strchr(m_LexemeBuffer, '!');
  2189. if (!ModNameEnd)
  2190. {
  2191. ModNameEnd = m_LexemeBuffer;
  2192. Mod = NULL;
  2193. }
  2194. else
  2195. {
  2196. Mod = m_Process->
  2197. FindImageByName(m_LexemeBuffer,
  2198. (ULONG)(ModNameEnd - m_LexemeBuffer),
  2199. INAME_MODULE, FALSE);
  2200. if (!Mod)
  2201. {
  2202. goto Error;
  2203. }
  2204. ModNameEnd++;
  2205. }
  2206. for (ModList = m_Process->m_ImageHead;
  2207. ModList;
  2208. ModList = ModList->m_Next)
  2209. {
  2210. if (Mod && ModList != Mod)
  2211. {
  2212. continue;
  2213. }
  2214. if (SymGetTypeFromName(m_Process->m_SymHandle,
  2215. ModList->m_BaseOfImage,
  2216. ModNameEnd, &SymInfo))
  2217. {
  2218. break;
  2219. }
  2220. }
  2221. if (!ModList)
  2222. {
  2223. goto Error;
  2224. }
  2225. ResKind = ERES_TYPE;
  2226. }
  2227. else
  2228. {
  2229. ResKind = ERES_SYMBOL;
  2230. }
  2231. //
  2232. // Collect everything until a matching >.
  2233. //
  2234. ULONG Nest = 1;
  2235. *--m_LexemeRestart = 0;
  2236. for (;;)
  2237. {
  2238. Accept();
  2239. if (m_Token == CppTokenEof)
  2240. {
  2241. EvalErrorDesc(SYNTAX, "EOF in template");
  2242. }
  2243. // Put a space after commas and pack everything else.
  2244. m_LexemeRestart += strlen(m_LexemeRestart);
  2245. if (m_Token == CppTokenCloseAngle && --Nest == 0)
  2246. {
  2247. break;
  2248. }
  2249. else if (m_Token == CppTokenOpenAngle)
  2250. {
  2251. Nest++;
  2252. }
  2253. else if (m_Token == ',')
  2254. {
  2255. *m_LexemeRestart++ = ' ';
  2256. *m_LexemeRestart = 0;
  2257. }
  2258. }
  2259. return ResKind;
  2260. Error:
  2261. // No match.
  2262. m_LexemeRestart -= 2;
  2263. *m_LexemeRestart++ = ' ';
  2264. *m_LexemeRestart = 0;
  2265. return ERES_UNKNOWN;
  2266. }
  2267. void
  2268. CppEvalExpression::CollectOperatorName(void)
  2269. {
  2270. PSTR OpEnd;
  2271. //
  2272. // Add in "operator".
  2273. //
  2274. m_LexemeRestart += strlen(m_LexemeRestart);
  2275. OpEnd = m_LexemeRestart;
  2276. Accept();
  2277. //
  2278. // Immediately process the specific operator tokens.
  2279. //
  2280. if (m_Token == CppTokenNew || m_Token == CppTokenDelete)
  2281. {
  2282. ULONG Len;
  2283. // Put a space before new/delete.
  2284. Len = strlen(OpEnd) + 1;
  2285. memmove(OpEnd + 1, OpEnd, Len);
  2286. *OpEnd = ' ';
  2287. m_LexemeRestart = OpEnd + Len;
  2288. Accept();
  2289. // Check for vector forms.
  2290. if (m_Token == CppTokenOpenBracket)
  2291. {
  2292. m_LexemeRestart += strlen(m_LexemeRestart);
  2293. Accept();
  2294. if (m_Token != CppTokenCloseBracket)
  2295. {
  2296. EvalError(SYNTAX);
  2297. }
  2298. m_LexemeRestart += strlen(m_LexemeRestart);
  2299. Accept();
  2300. }
  2301. }
  2302. else
  2303. {
  2304. switch(m_Token)
  2305. {
  2306. case '+':
  2307. case '-':
  2308. case '*':
  2309. case '/':
  2310. case '%':
  2311. case '^':
  2312. case '&':
  2313. case '|':
  2314. case '~':
  2315. case '!':
  2316. case '=':
  2317. case '<':
  2318. case '>':
  2319. case ',':
  2320. case CppTokenEqual:
  2321. case CppTokenNotEqual:
  2322. case CppTokenLessEqual:
  2323. case CppTokenGreaterEqual:
  2324. case CppTokenLogicalAnd:
  2325. case CppTokenLogicalOr:
  2326. case CppTokenUnaryPlus:
  2327. case CppTokenUnaryMinus:
  2328. case CppTokenLeftShift:
  2329. case CppTokenRightShift:
  2330. case CppTokenAddressOf:
  2331. case CppTokenDereference:
  2332. case CppTokenPointerMember:
  2333. case CppTokenClassDereference:
  2334. case CppTokenClassPointerMember:
  2335. case CppTokenDivideAssign:
  2336. case CppTokenMultiplyAssign:
  2337. case CppTokenModuloAssign:
  2338. case CppTokenAddAssign:
  2339. case CppTokenSubtractAssign:
  2340. case CppTokenLeftShiftAssign:
  2341. case CppTokenRightShiftAssign:
  2342. case CppTokenAndAssign:
  2343. case CppTokenOrAssign:
  2344. case CppTokenExclusiveOrAssign:
  2345. case CppTokenPreIncrement:
  2346. case CppTokenPreDecrement:
  2347. case CppTokenPostIncrement:
  2348. case CppTokenPostDecrement:
  2349. break;
  2350. case '(':
  2351. m_LexemeRestart += strlen(m_LexemeRestart);
  2352. Accept();
  2353. if (m_Token != CppTokenCloseParen)
  2354. {
  2355. EvalError(SYNTAX);
  2356. }
  2357. break;
  2358. case '[':
  2359. m_LexemeRestart += strlen(m_LexemeRestart);
  2360. Accept();
  2361. if (m_Token != CppTokenCloseBracket)
  2362. {
  2363. EvalError(SYNTAX);
  2364. }
  2365. break;
  2366. default:
  2367. // Unrecognized operator.
  2368. EvalError(SYNTAX);
  2369. }
  2370. m_LexemeRestart += strlen(m_LexemeRestart);
  2371. Accept();
  2372. }
  2373. }
  2374. void
  2375. CppEvalExpression::UdtMember(TypedData* Result)
  2376. {
  2377. if (m_Token != CppTokenIdentifier)
  2378. {
  2379. EvalError(SYNTAX);
  2380. }
  2381. EvalCheck(Result->ConvertToMember(m_LexemeStart, CurrentAccess(),
  2382. m_PtrSize));
  2383. #if DBG_TYPES
  2384. dprintf("%s -> id %s!%x, base %x, size %x\n",
  2385. m_LexemeStart,
  2386. Result->m_Image ? Result->m_Image->m_ModuleName : "<>",
  2387. Result->m_Type, Result->m_BaseType, Result->m_BaseSize);
  2388. #endif
  2389. Accept();
  2390. }
  2391. #define MAX_CPP_ARGS 16
  2392. struct CPP_REPLACEMENT
  2393. {
  2394. PSTR Name;
  2395. ULONG NumArgs;
  2396. PSTR Repl;
  2397. };
  2398. CPP_REPLACEMENT g_CppPreProcFn[] =
  2399. {
  2400. "CONTAINING_RECORD", 3,
  2401. "(($1$ *)((char*)($0$) - (int64)(&(($1$ *)0)->$2$)))",
  2402. "FIELD_OFFSET", 2,
  2403. "((long)&((($0$ *)0)->$1$))",
  2404. "RTL_FIELD_SIZE", 2,
  2405. "(sizeof((($0$ *)0)->$1$))",
  2406. "RTL_SIZEOF_THROUGH_FIELD", 2,
  2407. "(#FIELD_OFFSET($0$, $1$) + #RTL_FIELD_SIZE($0$, $1$))",
  2408. "RTL_CONTAINS_FIELD", 3,
  2409. "((((char*)(&($0$)->$2$)) + sizeof(($0$)->$2$)) <= "
  2410. "((char*)($0$))+($1$)))",
  2411. "RTL_NUMBER_OF", 1,
  2412. "(sizeof($0$)/sizeof(($0$)[0]))",
  2413. };
  2414. void
  2415. CppEvalExpression::PreprocFunction(TypedData* Result)
  2416. {
  2417. PCSTR Args[MAX_CPP_ARGS];
  2418. ULONG ArgsLen[MAX_CPP_ARGS];
  2419. ULONG i;
  2420. CPP_REPLACEMENT* Repl;
  2421. PCSTR Scan;
  2422. Repl = g_CppPreProcFn;
  2423. for (i = 0; i < DIMA(g_CppPreProcFn); i++)
  2424. {
  2425. // Skip '#' when comparing names.
  2426. if (!strcmp(m_LexemeStart + 1, Repl->Name))
  2427. {
  2428. break;
  2429. }
  2430. Repl++;
  2431. }
  2432. if (i == DIMA(g_CppPreProcFn))
  2433. {
  2434. EvalError(SYNTAX);
  2435. }
  2436. DBG_ASSERT(Repl->NumArgs <= MAX_CPP_ARGS);
  2437. // Accept the name token and verify that the next
  2438. // token is an open paren. Don't accept that token
  2439. // as we're going to switch to grabbing raw characters.
  2440. Accept();
  2441. if (m_Token != CppTokenOpenParen)
  2442. {
  2443. EvalError(SYNTAX);
  2444. }
  2445. i = 0;
  2446. for (;;)
  2447. {
  2448. ULONG Nest;
  2449. // Check for too many arguments.
  2450. if (i >= Repl->NumArgs)
  2451. {
  2452. EvalError(SYNTAX);
  2453. }
  2454. //
  2455. // Gather raw text up to the first comma or extra
  2456. // close paren.
  2457. //
  2458. while (isspace(*m_Lex))
  2459. {
  2460. m_Lex++;
  2461. }
  2462. Scan = m_Lex;
  2463. Nest = 0;
  2464. for (;;)
  2465. {
  2466. if (!*Scan)
  2467. {
  2468. EvalError(SYNTAX);
  2469. }
  2470. if (*Scan == '(')
  2471. {
  2472. Nest++;
  2473. }
  2474. else if ((*Scan == ',' && !Nest) ||
  2475. (*Scan == ')' && Nest-- == 0))
  2476. {
  2477. break;
  2478. }
  2479. Scan++;
  2480. }
  2481. Args[i] = m_Lex;
  2482. ArgsLen[i] = (ULONG)(Scan - m_Lex);
  2483. if (*Scan == ')')
  2484. {
  2485. // Check for too few arguments.
  2486. if (i != Repl->NumArgs - 1)
  2487. {
  2488. EvalError(SYNTAX);
  2489. }
  2490. m_Lex = Scan;
  2491. break;
  2492. }
  2493. else
  2494. {
  2495. m_Lex = Scan + 1;
  2496. }
  2497. i++;
  2498. }
  2499. // Switch back to token lexing.
  2500. NextToken();
  2501. Match(CppTokenCloseParen);
  2502. PSTR NewExpr;
  2503. PSTR Dest;
  2504. ULONG ExprLen;
  2505. //
  2506. // We've accumlated all the arguments, so allocate a destination
  2507. // buffer and do the necessary string replacements.
  2508. // Make the buffer relatively large to allow for complicated
  2509. // replacements.
  2510. //
  2511. ExprLen = 16384;
  2512. NewExpr = new char[ExprLen];
  2513. if (!NewExpr)
  2514. {
  2515. EvalError(NOMEMORY);
  2516. }
  2517. Scan = Repl->Repl;
  2518. Dest = NewExpr;
  2519. for (;;)
  2520. {
  2521. if (*Scan == '$')
  2522. {
  2523. //
  2524. // Argument that needs replacement.
  2525. //
  2526. i = 0;
  2527. Scan++;
  2528. while (isdigit(*Scan))
  2529. {
  2530. i = i * 10 + (ULONG)(*Scan - '0');
  2531. Scan++;
  2532. }
  2533. if (*Scan != '$' ||
  2534. i >= Repl->NumArgs)
  2535. {
  2536. delete [] NewExpr;
  2537. EvalError(IMPLERR);
  2538. }
  2539. Scan++;
  2540. if ((Dest - NewExpr) + ArgsLen[i] >= ExprLen - 1)
  2541. {
  2542. delete [] NewExpr;
  2543. EvalError(OVERFLOW);
  2544. }
  2545. memcpy(Dest, Args[i], ArgsLen[i]);
  2546. Dest += ArgsLen[i];
  2547. }
  2548. else if (*Scan)
  2549. {
  2550. if ((ULONG)(Dest - NewExpr) >= ExprLen - 1)
  2551. {
  2552. delete [] NewExpr;
  2553. EvalError(OVERFLOW);
  2554. }
  2555. *Dest++ = *Scan++;
  2556. }
  2557. else
  2558. {
  2559. *Dest = 0;
  2560. break;
  2561. }
  2562. }
  2563. //
  2564. // Evaluate the new expression for the final result.
  2565. //
  2566. EvalExpression* Eval;
  2567. Eval = GetEvaluator(DEBUG_EXPR_CPLUSPLUS, TRUE);
  2568. if (!Eval)
  2569. {
  2570. delete [] NewExpr;
  2571. EvalError(NOMEMORY);
  2572. }
  2573. Eval->InheritStart(this);
  2574. ((CppEvalExpression*)Eval)->m_PreprocEval = TRUE;
  2575. __try
  2576. {
  2577. Eval->Evaluate(NewExpr, NULL, EXPRF_DEFAULT, Result);
  2578. Eval->InheritEnd(this);
  2579. ReleaseEvaluator(Eval);
  2580. }
  2581. __except(CommandExceptionFilter(GetExceptionInformation()))
  2582. {
  2583. delete [] NewExpr;
  2584. ReleaseEvaluators();
  2585. RaiseException(GetExceptionCode(), 0, 0, NULL);
  2586. }
  2587. delete [] NewExpr;
  2588. }