Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1085 lines
27 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000.
  5. //
  6. // File: CXX.CXX
  7. //
  8. // Contents: C and C++ Filter
  9. //
  10. // Classes: CxxFilter
  11. //
  12. // History: 26-Jun-92 BartoszM Created
  13. // 17-Oct-94 BartoszM Rewrote
  14. //
  15. //----------------------------------------------------------------------------
  16. #include <pch.cxx>
  17. #pragma hdrstop
  18. //+---------------------------------------------------------------------------
  19. //
  20. // Member: CxxScanner::CxxScanner, public
  21. //
  22. // History: 26-Jun-92 BartoszM Created
  23. //
  24. //----------------------------------------------------------------------------
  25. CxxScanner::CxxScanner ()
  26. : _pStream(0),
  27. _fIgnorePreamble(FALSE),
  28. _fScanningPrepro(FALSE),
  29. _fIdFound(FALSE),
  30. _cLines( 0 )
  31. {
  32. _buf[0] = L'\0';
  33. }
  34. //+---------------------------------------------------------------------------
  35. //
  36. // Member: CxxScanner::Init, public
  37. //
  38. // Arguments: [pStream] -- stream for text
  39. //
  40. // History: 24-Nov-93 AmyA Created
  41. //
  42. //----------------------------------------------------------------------------
  43. void CxxScanner::Init ( CFilterTextStream * pStream )
  44. {
  45. _pStream = pStream;
  46. // Position scanner on a token
  47. Accept();
  48. }
  49. //+---------------------------------------------------------------------------
  50. //
  51. // Member: CxxScanner::NextToken, public
  52. //
  53. // Arguments: [c] -- lookahead character
  54. //
  55. // Returns: Recognized token
  56. //
  57. // History: 26-Jun-92 BartoszM Created
  58. //
  59. //----------------------------------------------------------------------------
  60. CToken CxxScanner::NextToken( int c )
  61. {
  62. BOOL fFirstTime = TRUE;
  63. // Loop until a token is recognized
  64. for(;;)
  65. {
  66. switch (c)
  67. {
  68. case -1: // UNICODE EOF
  69. _token = tEnd;
  70. return _token;
  71. case L'\n':
  72. _cLines++;
  73. _fScanningPrepro = FALSE;
  74. c = _pStream->GetChar();
  75. break;
  76. case L'{':
  77. _token = tLBrace;
  78. return _token;
  79. case L'}':
  80. _token = tRBrace;
  81. return _token;
  82. case L';':
  83. _token = tSemi;
  84. return _token;
  85. case L',':
  86. if ( _fIgnorePreamble )
  87. {
  88. // skip comma in the preamble
  89. c = _pStream->GetChar();
  90. break;
  91. }
  92. _token = tComma;
  93. return _token;
  94. case L'*':
  95. if ( _fIgnorePreamble )
  96. {
  97. // skip star in the preamble
  98. c = _pStream->GetChar();
  99. break;
  100. }
  101. _token = tStar;
  102. return _token;
  103. case L'#': // not a token!
  104. // consume preprocessor command
  105. _fScanningPrepro = TRUE;
  106. c = _pStream->GetChar();
  107. break;
  108. case L'(':
  109. if ( _fIgnorePreamble )
  110. {
  111. // skip parentheses in the preamble
  112. c = _pStream->GetChar();
  113. break;
  114. }
  115. _token = tLParen;
  116. return _token;
  117. case L')':
  118. if ( _fIgnorePreamble )
  119. {
  120. // skip parentheses in the preamble
  121. c = _pStream->GetChar();
  122. break;
  123. }
  124. _token = tRParen;
  125. return _token;
  126. case L':':
  127. c = _pStream->GetChar();
  128. // ignore colons in the preamble
  129. if ( !_fIgnorePreamble && c == L':')
  130. {
  131. _token = tDoubleColon;
  132. return _token;
  133. }
  134. break;
  135. case L'/': // not a token!
  136. // consume comment
  137. c = EatComment();
  138. break;
  139. case L'"': // not a token!
  140. // consume string literal
  141. c = EatString();
  142. break;
  143. case L'\'': // not a token!
  144. // consume character literal
  145. c = EatCharLiteral();
  146. break;
  147. default:
  148. // We don't really care about indentifiers.
  149. // We store them in the buffer so that when
  150. // we recognize a real token like :: or (
  151. // we can retrieve them.
  152. // Look out for 'class' 'struct' and 'union' though.
  153. if ( iswalpha((wint_t)c) || (c == L'_') || (c == L'~') )
  154. {
  155. _fIdFound = TRUE;
  156. // in preamble skip names except for the first
  157. // one, which is the name of the procedure
  158. if ( _fIgnorePreamble && !fFirstTime )
  159. {
  160. c = SkipName(c);
  161. continue;
  162. }
  163. else
  164. {
  165. c = LoadName (c);
  166. fFirstTime = FALSE;
  167. }
  168. if (!_fIgnorePreamble)
  169. {
  170. // look for class/struct/union keywords
  171. if ( wcscmp(_buf, L"class" ) == 0 )
  172. {
  173. _token = tClass;
  174. return _token;
  175. }
  176. else if ( wcscmp(_buf, L"struct") == 0 )
  177. {
  178. _token = tStruct;
  179. return _token;
  180. }
  181. else if ( wcscmp(_buf, L"union" ) == 0 )
  182. {
  183. _token = tUnion;
  184. return _token;
  185. }
  186. else if ( wcscmp(_buf, L"interface" ) == 0 )
  187. {
  188. _token = tInterface;
  189. return _token;
  190. }
  191. else if ( wcscmp(_buf, L"typedef" ) == 0 )
  192. {
  193. _token = tTypedef;
  194. return _token;
  195. }
  196. else if ( wcscmp(_buf, L"enum" ) == 0 )
  197. {
  198. _token = tEnum;
  199. return _token;
  200. }
  201. }
  202. if ( _fScanningPrepro )
  203. {
  204. if ( wcscmp(_buf, L"define" ) == 0 )
  205. {
  206. _token = tDefine;
  207. c = LoadName(c);
  208. return _token;
  209. }
  210. else if ( wcscmp(_buf, L"include" ) == 0 )
  211. {
  212. _token = tInclude;
  213. c = LoadIncludeFileName(c);
  214. return _token;
  215. }
  216. else
  217. {
  218. c = EatPrepro();
  219. _fScanningPrepro = FALSE;
  220. }
  221. }
  222. }
  223. else // not recognized, continue scanning
  224. {
  225. c = _pStream->GetChar();
  226. }
  227. break;
  228. } // end of switch
  229. } // end of infinite loop
  230. return _token;
  231. }
  232. //+---------------------------------------------------------------------------
  233. //
  234. // Member: CxxScanner::SkipName, public
  235. //
  236. // Returns: Next character after identifier
  237. //
  238. // History: 26-Jun-92 BartoszM Created
  239. //
  240. //----------------------------------------------------------------------------
  241. int CxxScanner::SkipName(int c)
  242. {
  243. int i = 0;
  244. do
  245. {
  246. c = _pStream->GetChar();
  247. i++;
  248. }
  249. while ( (iswalnum((wint_t)c) || (c == L'_')) && (i < MAXIDENTIFIER) );
  250. return c;
  251. }
  252. //+---------------------------------------------------------------------------
  253. //
  254. // Member: CxxScanner::LoadName, public
  255. //
  256. // Synopsis: Scans and copies identifier into scanner's buffer
  257. //
  258. // Arguments: [c] -- GetChar character
  259. //
  260. // Returns: Next character after identifier
  261. //
  262. // History: 26-Jun-92 BartoszM Created
  263. //
  264. //----------------------------------------------------------------------------
  265. int CxxScanner::LoadName(int c)
  266. {
  267. WCHAR * pCur = _buf;
  268. _pStream->GetRegion ( _region, -1, 0 );
  269. int i = 0;
  270. do
  271. {
  272. _buf[i++] = (WCHAR)c;
  273. c = _pStream->GetChar();
  274. }
  275. while ( (iswalnum((wint_t)c) || (c == L'_')) && (i < MAXIDENTIFIER));
  276. _region.cwcExtent = i;
  277. // c is not a symbol character
  278. _buf[i] = L'\0';
  279. //DbgPrint("LoadName: =================> %ws\n", _buf);
  280. return c;
  281. }
  282. //+---------------------------------------------------------------------------
  283. //
  284. // Member: CxxScanner::LoadIncludeFileName, public
  285. //
  286. // Synopsis: Scans and copies a file name following a
  287. // #include statement to internal buffer
  288. // If a path exists, it is ignored.
  289. // A '.' is converted to '_' because searching an id
  290. // with a '.' does not seem to work with ci.
  291. // For example,
  292. // #include <\foo\bar\fname.h> --> fname_h
  293. //
  294. // Arguments: [c] -- GetChar character
  295. //
  296. // Returns: Next character after the #include stmt
  297. //
  298. // History: 10-June-2000 kumarp Created
  299. //
  300. //----------------------------------------------------------------------------
  301. int CxxScanner::LoadIncludeFileName(int c)
  302. {
  303. WCHAR * pCur = _buf;
  304. int i = 0;
  305. // skip chars preceeding the file name
  306. do
  307. {
  308. c = _pStream->GetChar();
  309. }
  310. while ((c == L'\t') || (c == L' ') || (c == L'"') || (c == L'<'));
  311. _pStream->GetRegion ( _region, -1, 0 );
  312. do
  313. {
  314. _buf[i++] = (WCHAR)c;
  315. if ((c == L'\\') || (c == L'/'))
  316. {
  317. // ignore path
  318. i = 0;
  319. _pStream->GetRegion ( _region, 0, 0 );
  320. }
  321. c = _pStream->GetChar();
  322. // if (c == L'.')
  323. // {
  324. // c = L'_';
  325. // }
  326. }
  327. while ((iswalnum((wint_t)c) || ( c == L'.' ) ||
  328. (c == L'_') || (c == L'\\') || (c == L'/')) &&
  329. (i < MAXIDENTIFIER));
  330. _region.cwcExtent = i;
  331. _buf[i] = L'\0';
  332. c = EatPrepro();
  333. return c;
  334. }
  335. //+---------------------------------------------------------------------------
  336. //
  337. // Member: CxxScanner::EatComment, public
  338. //
  339. // Synopsis: Eats comments
  340. //
  341. // Returns: First non-comment character
  342. //
  343. // Requires: Leading '/' found and scanned
  344. //
  345. // History: 26-Jun-92 BartoszM Created
  346. //
  347. //----------------------------------------------------------------------------
  348. int CxxScanner::EatComment()
  349. {
  350. int c = _pStream->GetChar();
  351. if ( c == L'*')
  352. {
  353. // C style comment
  354. while ((c = _pStream->GetChar()) != EOF )
  355. {
  356. while ( c == L'*' )
  357. {
  358. c = _pStream->GetChar();
  359. if ( c == EOF )
  360. return EOF;
  361. if ( c == L'/' )
  362. return _pStream->GetChar();
  363. }
  364. }
  365. }
  366. else if ( c == L'/' )
  367. {
  368. // C++ style comment
  369. while ((c = _pStream->GetChar()) != EOF )
  370. {
  371. if ( c == L'\n' )
  372. break;
  373. }
  374. }
  375. return c;
  376. }
  377. //+---------------------------------------------------------------------------
  378. //
  379. // Member: CxxScanner::EatString, public
  380. //
  381. // Synopsis: Eats string literal
  382. //
  383. // Returns: First non-string character
  384. //
  385. // Requires: Leading '"' found and scanned
  386. //
  387. // History: 26-Jun-92 BartoszM Created
  388. //
  389. //----------------------------------------------------------------------------
  390. int CxxScanner::EatString()
  391. {
  392. int c;
  393. while ((c = _pStream->GetChar()) != EOF )
  394. {
  395. if ( c == L'"' )
  396. {
  397. c = _pStream->GetChar();
  398. break;
  399. }
  400. // eat backslashes
  401. // skip escaped quotes
  402. if ( c == L'\\' )
  403. {
  404. c = _pStream->GetChar();
  405. if ( c == EOF )
  406. return EOF;
  407. }
  408. }
  409. return c;
  410. }
  411. //+---------------------------------------------------------------------------
  412. //
  413. // Member: CxxScanner::EatCharLiteral, public
  414. //
  415. // Synopsis: Eats character literal
  416. //
  417. // Returns: First non-char-literal character
  418. //
  419. // Requires: Leading apostrophe ' found and scanned
  420. //
  421. // History: 26-Jun-92 BartoszM Created
  422. //
  423. //----------------------------------------------------------------------------
  424. int CxxScanner::EatCharLiteral()
  425. {
  426. int c;
  427. while ((c = _pStream->GetChar()) != EOF )
  428. {
  429. if ( c == L'\'' )
  430. {
  431. c = _pStream->GetChar();
  432. break;
  433. }
  434. // eat backslashes
  435. // skip escaped quotes
  436. if ( c == L'\\' )
  437. {
  438. c = _pStream->GetChar();
  439. if ( c == EOF )
  440. return EOF;
  441. }
  442. }
  443. return c;
  444. }
  445. //+---------------------------------------------------------------------------
  446. //
  447. // Member: CxxScanner::EatPrepro, public
  448. //
  449. // Synopsis: Eats preprocessor commands. Possibly multi-line.
  450. //
  451. // Returns: First non-preprocessor character
  452. //
  453. // Requires: Leading # found and scanned
  454. //
  455. // History: 26-Jun-92 BartoszM Created
  456. //
  457. //----------------------------------------------------------------------------
  458. int CxxScanner::EatPrepro()
  459. {
  460. int c;
  461. _fScanningPrepro = FALSE;
  462. while ((c = _pStream->GetChar()) != EOF && (c != L'\n'))
  463. {
  464. if ( c == L'\\' ) // skip whatever follows backslash
  465. {
  466. c = _pStream->GetChar();
  467. if (c == L'\r')
  468. c = _pStream->GetChar();
  469. if ( c == EOF )
  470. return EOF;
  471. }
  472. }
  473. return c;
  474. }
  475. //+---------------------------------------------------------------------------
  476. //
  477. // Member: CxxParser::CxxParser, public
  478. //
  479. // Synopsis: Initialize parser
  480. //
  481. // Arguments: [pStm] -- stream
  482. // [drep] -- data repository
  483. //
  484. // History: 26-Jun-92 BartoszM Created
  485. //
  486. //----------------------------------------------------------------------------
  487. CxxParser::CxxParser ()
  488. : _scope(0),
  489. _inClass(0),
  490. _fParsingTypedef(FALSE),
  491. _fParsingFnPtrTypedef(FALSE),
  492. _iVal(0)
  493. {
  494. _strClass[0] = L'\0';
  495. _strName[0] = L'\0';
  496. _attribute.ulKind = PRSPEC_LPWSTR;
  497. _attribute.lpwstr = PROP_CLASS;
  498. _psVal[Function].ulKind = PRSPEC_LPWSTR;
  499. _psVal[Function].lpwstr = PROP_FUNC;
  500. _psVal[Class].ulKind = PRSPEC_LPWSTR;
  501. _psVal[Class].lpwstr = PROP_CLASS;
  502. _psVal[Lines].ulKind = PRSPEC_LPWSTR;
  503. _psVal[Lines].lpwstr = PROP_LINES;
  504. _aVal[Function] = 0;
  505. _aVal[Class] = 0;
  506. _aVal[Lines] = 0;
  507. }
  508. CxxParser::~CxxParser()
  509. {
  510. delete _aVal[Function];
  511. delete _aVal[Class];
  512. delete _aVal[Lines];
  513. }
  514. //+---------------------------------------------------------------------------
  515. //
  516. // Member: CxxParser::Init, public
  517. //
  518. // Synopsis: Initialize parser
  519. //
  520. // Arguments: [pStream] -- stream
  521. //
  522. // History: 24-Nov-93 AmyA Created
  523. //
  524. //----------------------------------------------------------------------------
  525. void CxxParser::Init ( CFilterTextStream * pStream )
  526. {
  527. _scan.Init(pStream);
  528. _token = _scan.Token();
  529. }
  530. //+---------------------------------------------------------------------------
  531. //
  532. // Member: CxxParser::Parse, public
  533. //
  534. // Synopsis: Parse the file
  535. //
  536. // History: 26-Jun-92 BartoszM Created
  537. //
  538. //----------------------------------------------------------------------------
  539. BOOL CxxParser::Parse()
  540. {
  541. _cwcCopiedClass = 0;
  542. _cwcCopiedName = 0;
  543. while ( _token != tEnd)
  544. {
  545. switch ( _token )
  546. {
  547. case tTypedef:
  548. if ( !_fParsingTypedef )
  549. {
  550. _fParsingTypedef = TRUE;
  551. _typedefScope = _scope;
  552. }
  553. _token = _scan.Accept();
  554. break;
  555. case tSemi:
  556. if ( _fParsingTypedef && ( _scope == _typedefScope ))
  557. {
  558. ASSERT(_fParsingFnPtrTypedef == FALSE);
  559. SetName();
  560. //DbgPrint("tSemi: name: %ws, scope: %d\n", _strName, _scope);
  561. PutFunction();
  562. _fParsingTypedef = FALSE;
  563. _token = _scan.Accept();
  564. return TRUE;
  565. }
  566. _token = _scan.Accept();
  567. break;
  568. case tComma:
  569. if ( _fParsingTypedef && ( _scope == _typedefScope ))
  570. {
  571. ASSERT(_fParsingFnPtrTypedef == FALSE);
  572. SetName();
  573. //DbgPrint("tComma: name: %ws, scope: %d\n", _strName, _scope);
  574. PutFunction();
  575. _token = _scan.Accept();
  576. return TRUE;
  577. }
  578. _token = _scan.Accept();
  579. break;
  580. case tEnum:
  581. //DbgPrint("tEnum\n");
  582. //_scan.IgnorePreamble(TRUE);
  583. _token = _scan.Accept();
  584. //_scan.IgnorePreamble(FALSE);
  585. if ( _token == tLBrace )
  586. {
  587. // Good, we're inside a enum definition
  588. _scope++;
  589. SetName();
  590. //DbgPrint("tEnum: %ws\n", _strName);
  591. PutFunction();
  592. _token = _scan.Accept();
  593. return TRUE;
  594. }
  595. // otherwise it was a false alarm
  596. break;
  597. case tClass:
  598. case tStruct:
  599. case tUnion:
  600. case tInterface:
  601. // We have to recognize stuff like this:
  602. // class FOO : public bar:a, private b {
  603. // ----- --
  604. // text between 'class' and left brace is
  605. // a preamble that the scanner will skip
  606. // If it's only a forward declaration, we
  607. // will stop at a semicolon and ignore the
  608. // whole business.
  609. #if CIDBG == 1
  610. _classToken = _token;
  611. #endif // CIDBG == 1
  612. // scan through stuff like
  613. // : public foo, private bar
  614. _scan.IgnorePreamble(TRUE);
  615. _token = _scan.Accept();
  616. _scan.IgnorePreamble(FALSE);
  617. // Ignore embedded classes
  618. if ( _inClass == 0 )
  619. SetClass(); // record class name for later
  620. if ( _token == tLBrace )
  621. {
  622. // Good, we're inside a class definition
  623. _inClass++;
  624. _scope++;
  625. PutClass ();
  626. _token = _scan.Accept();
  627. return TRUE;
  628. }
  629. // otherwise it was a false alarm
  630. break;
  631. case tDoubleColon:
  632. // Here we deal with constructs like
  633. // FOO::FOO ( int x ) : bar(state::ok), (true) {
  634. // -- - --
  635. // Text between left paren and left brace is preamble
  636. // and the scanner skips it. If we hit a semicolon
  637. // rather than left brace, we ignore the whole
  638. // construct (it was an invocation or something)
  639. SetClass(); // record class name just in case
  640. _token = _scan.Accept();
  641. if ( _token == tLParen )
  642. {
  643. SetName(); // record method name just in case
  644. _scan.IgnorePreamble(TRUE);
  645. _token = _scan.Accept();
  646. _scan.IgnorePreamble(FALSE);
  647. if ( _token == tLBrace )
  648. {
  649. // Yes, we have method definition
  650. _scope++;
  651. _token = _scan.Accept();
  652. PutMethod();
  653. return TRUE;
  654. }
  655. // otherwise it was a false alarm
  656. }
  657. break;
  658. case tLParen:
  659. if ( _fParsingTypedef && ( _scope == _typedefScope ))
  660. {
  661. //
  662. // at present we only support fn-ptr typedefs
  663. // of the following type:
  664. //
  665. // typedef void (*FnPtr1) ( int i, float f );
  666. //
  667. //SetName();
  668. //DbgPrint("tLParen: name: %ws, scope: %d\n", _strName, _scope);
  669. _scan.SetIdFound(FALSE);
  670. _token = _scan.Accept();
  671. if ( ( _token == tStar ) && !_scan.IdFound() )
  672. {
  673. _fParsingFnPtrTypedef = TRUE;
  674. }
  675. else
  676. {
  677. //PutFunction();
  678. _fParsingTypedef = FALSE;
  679. _fParsingFnPtrTypedef = FALSE;
  680. }
  681. _token = _scan.Accept();
  682. }
  683. else
  684. {
  685. SetName(); // record procedure name just in case
  686. // It may be an inline constructor
  687. // skip argument list and constructor stuff like
  688. // : Parent(blah), member(blah)
  689. _scan.IgnorePreamble(TRUE);
  690. _token = _scan.Accept();
  691. _scan.IgnorePreamble(FALSE);
  692. if ( _token == tLBrace )
  693. {
  694. // Yes, it's a definition
  695. if ( _inClass )
  696. {
  697. // inline method definition inside class definition
  698. _scope++;
  699. _token = _scan.Accept();
  700. PutInlineMethod();
  701. return TRUE;
  702. }
  703. else if ( _scope == 0 )
  704. {
  705. // function definitions
  706. // in outer scope
  707. _scope++;
  708. PutFunction();
  709. _token = _scan.Accept();
  710. return TRUE;
  711. }
  712. // else continue--false alarm
  713. }
  714. }
  715. break;
  716. case tRParen:
  717. if ( _fParsingFnPtrTypedef && ( _scope == _typedefScope ))
  718. {
  719. SetName();
  720. //DbgPrint("tRParen: name: %ws, scope: %d\n", _strName, _scope);
  721. PutFunction();
  722. _fParsingTypedef = FALSE;
  723. _fParsingFnPtrTypedef = FALSE;
  724. _token = _scan.Accept();
  725. return TRUE;
  726. }
  727. _token = _scan.Accept();
  728. break;
  729. case tEnd:
  730. return FALSE;
  731. case tLBrace:
  732. // keep track of scope
  733. _scope++;
  734. _token = _scan.Accept();
  735. break;
  736. case tRBrace:
  737. // keep track of scope and (nested) class scope
  738. _scope--;
  739. if ( _inClass > _scope )
  740. {
  741. _inClass--;
  742. }
  743. _token = _scan.Accept();
  744. break;
  745. case tDefine:
  746. SetName();
  747. PutFunction();
  748. _scan.EatPrepro();
  749. _token = _scan.Accept();
  750. return TRUE;
  751. case tInclude:
  752. SetName();
  753. PutFunction();
  754. _token = _scan.Accept();
  755. return TRUE;
  756. default:
  757. _token = _scan.Accept();
  758. }
  759. }
  760. if ( _aVal[Lines] == 0 )
  761. {
  762. _aVal[Lines] = new CPropVar;
  763. if ( 0 == _aVal[Lines] )
  764. THROW( CException( E_OUTOFMEMORY ) );
  765. }
  766. _aVal[Lines]->SetUI4( _scan.Lines() );
  767. return FALSE; // we only end up here if _token == tEnd
  768. }
  769. void CxxParser::PutClass ()
  770. {
  771. _tokenType = ttClass;
  772. _attribute.lpwstr = PROP_CLASS;
  773. _strName[0] = L'\0';
  774. #if 0
  775. if ( _aVal[Class] == 0 )
  776. {
  777. _aVal[Class] = new CPropVar;
  778. if ( 0 == _aVal[Class] )
  779. THROW( CException( E_OUTOFMEMORY ) );
  780. }
  781. _aVal[Class]->SetLPWSTR( _strClass, _aVal[Class]->Count() );
  782. #endif
  783. // PROP_CLASS, _strClass
  784. //DbgPrint("PutClass: class: %ws\n", _strClass);
  785. #if CIDBG == 1
  786. if ( _classToken == tClass )
  787. {
  788. cxxDebugOut((DEB_ITRACE,"class %ws\n", _strClass ));
  789. }
  790. else if ( _classToken == tStruct )
  791. {
  792. cxxDebugOut((DEB_ITRACE, "struct %ws\n", _strClass ));
  793. }
  794. else if ( _classToken == tUnion )
  795. {
  796. cxxDebugOut((DEB_ITRACE, "union %ws\n", _strClass ));
  797. }
  798. else if ( _classToken == tInterface )
  799. {
  800. cxxDebugOut((DEB_ITRACE, "interface %ws\n", _strClass ));
  801. }
  802. #endif // CIDBG == 1
  803. }
  804. void CxxParser::PutMethod ()
  805. {
  806. _tokenType = ttMethod;
  807. _attribute.lpwstr = PROP_FUNC;
  808. #if 0
  809. if ( _aVal[Function] == 0 )
  810. {
  811. _aVal[Function] = new CPropVar;
  812. if ( 0 == _aVal[Function] )
  813. THROW( CException( E_OUTOFMEMORY ) );
  814. }
  815. _aVal[Function]->SetLPWSTR( _strName, _aVal[Function]->Count() );
  816. #endif
  817. cxxDebugOut((DEB_ITRACE, "%ws::%ws\n", _strClass, _strName ));
  818. }
  819. void CxxParser::PutInlineMethod ()
  820. {
  821. _tokenType = ttInlineMethod;
  822. _attribute.lpwstr = PROP_FUNC;
  823. #if 0
  824. if ( _aVal[Function] == 0 )
  825. {
  826. _aVal[Function] = new CPropVar;
  827. if ( 0 == _aVal[Function] )
  828. THROW( CException( E_OUTOFMEMORY ) );
  829. }
  830. _aVal[Function]->SetLPWSTR( _strName, _aVal[Function]->Count() );
  831. #endif
  832. cxxDebugOut((DEB_ITRACE, "%ws::%ws\n", _strClass, _strName ));
  833. }
  834. void CxxParser::PutFunction ()
  835. {
  836. _tokenType = ttFunction;
  837. _attribute.lpwstr = PROP_FUNC;
  838. _strClass[0] = L'\0';
  839. #if 0
  840. if ( _aVal[Function] == 0 )
  841. {
  842. _aVal[Function] = new CPropVar;
  843. if ( 0 == _aVal[Function] )
  844. THROW( CException( E_OUTOFMEMORY ) );
  845. }
  846. _aVal[Function]->SetLPWSTR( _strName, _aVal[Function]->Count() );
  847. #endif
  848. //DbgPrint("PutFunction: func: %ws\n", _strName);
  849. cxxDebugOut((DEB_ITRACE, "function %ws\n", _strName ));
  850. }
  851. void CxxParser::GetRegion ( FILTERREGION& region )
  852. {
  853. switch (_tokenType)
  854. {
  855. case ttClass:
  856. region = _regionClass;
  857. break;
  858. case ttFunction:
  859. case ttInlineMethod:
  860. case ttMethod:
  861. region = _regionName;
  862. break;
  863. }
  864. }
  865. BOOL CxxParser::GetTokens ( ULONG * pcwcBuffer, WCHAR * awcBuffer )
  866. {
  867. ULONG cwc = *pcwcBuffer;
  868. *pcwcBuffer = 0;
  869. if (_strClass[0] != L'\0')
  870. {
  871. // We have a class name
  872. WCHAR * strClass = _strClass + _cwcCopiedClass;
  873. ULONG cwcClass = wcslen( strClass );
  874. if ( cwcClass > cwc )
  875. {
  876. wcsncpy( awcBuffer, strClass, cwc );
  877. _cwcCopiedClass += cwc;
  878. return FALSE;
  879. }
  880. wcscpy( awcBuffer, strClass );
  881. *pcwcBuffer = cwcClass;
  882. _cwcCopiedClass += cwcClass;
  883. awcBuffer[(*pcwcBuffer)++] = L' ';
  884. }
  885. if (_strName[0] == L'\0')
  886. {
  887. // it was only a class name
  888. awcBuffer[*pcwcBuffer] = L'\0';
  889. return TRUE;
  890. }
  891. cwc -= *pcwcBuffer;
  892. WCHAR * awc = awcBuffer + *pcwcBuffer;
  893. WCHAR * strName = _strName + _cwcCopiedName;
  894. ULONG cwcName = wcslen( strName );
  895. if ( cwcName > cwc )
  896. {
  897. wcsncpy( awc, strName, cwc );
  898. _cwcCopiedName += cwc;
  899. return FALSE;
  900. }
  901. wcscpy( awc, strName );
  902. *pcwcBuffer += cwcName;
  903. _cwcCopiedName += cwcName;
  904. return TRUE;
  905. }
  906. BOOL CxxParser::GetValueAttribute( PROPSPEC & ps )
  907. {
  908. for ( ; _iVal <= Lines && 0 == _aVal[_iVal]; _iVal++ )
  909. continue;
  910. if ( _iVal > Lines )
  911. return FALSE;
  912. else
  913. {
  914. ps = _psVal[_iVal];
  915. return TRUE;
  916. }
  917. }
  918. PROPVARIANT * CxxParser::GetValue()
  919. {
  920. if ( _iVal > Lines )
  921. return 0;
  922. CPropVar * pTemp = _aVal[_iVal];
  923. _aVal[_iVal] = 0;
  924. _iVal++;
  925. return (PROPVARIANT *)(void *)pTemp;
  926. }