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.

4049 lines
91 KiB

  1. // Make sure all dependent defines exist and have a valid value
  2. #ifndef NO_COMPILER_NAMES
  3. #define NO_COMPILER_NAMES 0
  4. #endif
  5. #ifndef VERS_32BIT
  6. #define VERS_32BIT 1
  7. #endif
  8. #ifndef PACK_SIZE
  9. #ifdef _CRTBLD
  10. #define PACK_SIZE 8
  11. #elif !VERS_32BIT
  12. #define PACK_SIZE 2
  13. #elif defined(_X86_)
  14. #define PACK_SIZE 4
  15. #else
  16. #define PACK_SIZE 8
  17. #endif
  18. #endif
  19. // Check for version inconsistancies, and setup version flags
  20. #ifdef VERS_BSC
  21. #undef NO_COMPILER_NAMES
  22. #define NO_COMPILER_NAMES 1
  23. #pragma inline_depth ( 3 )
  24. #pragma check_stack ( off )
  25. #else
  26. #pragma inline_depth ( 3 )
  27. #pragma check_stack ( off )
  28. #endif
  29. #define PURE = 0
  30. #ifndef CC_COR
  31. #define CC_COR 1
  32. #endif
  33. #include "undname.hxx"
  34. #if !defined(_CRTBLD) && (!VERSP_RELEASE || defined(_DEBUG))
  35. #include <assert.h>
  36. #define DASSERT(x) assert(x)
  37. #else
  38. #define DASSERT(x)
  39. #endif
  40. #if (defined(_CRTBLD) && defined(_MT))
  41. #include <mtdll.h>
  42. #endif
  43. #include <stdio.h>
  44. #include <windows.h>
  45. #include "utf8.h"
  46. #pragma warning(disable:4291) // No matching operator delete
  47. static unsigned int und_strlen ( pcchar_t );
  48. static pchar_t und_strncpy ( pchar_t, pcchar_t, unsigned int );
  49. static unsigned int und_strncmp ( pcchar_t, pcchar_t, unsigned int );
  50. class DName;
  51. class DNameNode;
  52. class Replicator;
  53. class HeapManager;
  54. class UnDecorator;
  55. // A '512' byte block including the header
  56. const unsigned int memBlockSize = 512 - sizeof(void*);
  57. class HeapManager
  58. {
  59. private:
  60. Alloc_t pOpNew;
  61. Free_t pOpDelete;
  62. struct Block
  63. {
  64. Block * next;
  65. char memBlock[ memBlockSize ];
  66. __near Block () { next = 0; }
  67. };
  68. Block * head;
  69. Block * tail;
  70. size_t blockLeft;
  71. public:
  72. void __near Constructor ( Alloc_t pAlloc, Free_t pFree )
  73. { pOpNew = pAlloc;
  74. pOpDelete = pFree;
  75. blockLeft = 0;
  76. head = 0;
  77. tail = 0;
  78. }
  79. void __far * __near getMemory ( size_t, int );
  80. void __near Destructor ( void )
  81. { if ( pOpDelete != 0 )
  82. while ( tail = head )
  83. {
  84. head = tail->next;
  85. ( *pOpDelete )( tail );
  86. }
  87. }
  88. #define gnew new(heap,0)
  89. #define rnew new(heap,1)
  90. };
  91. void * operator new ( size_t, HeapManager &, int = 0 );
  92. static HeapManager heap;
  93. // The MS Token table
  94. enum Tokens
  95. {
  96. #if !VERS_32BIT
  97. TOK_near,
  98. TOK_nearSp,
  99. TOK_nearP,
  100. TOK_far,
  101. TOK_farSp,
  102. TOK_farP,
  103. TOK_huge,
  104. TOK_hugeSp,
  105. TOK_hugeP,
  106. #endif
  107. TOK_basedLp,
  108. TOK_cdecl,
  109. TOK_pascal,
  110. TOK_stdcall,
  111. TOK_thiscall,
  112. TOK_fastcall,
  113. TOK_cocall,
  114. TOK_ptr64,
  115. TOK_restrict,
  116. TOK_unaligned,
  117. #if !VERS_32BIT
  118. TOK_interrupt,
  119. TOK_saveregs,
  120. TOK_self,
  121. TOK_segment,
  122. TOK_segnameLpQ,
  123. #endif
  124. TOK__last
  125. };
  126. static const pcchar_t __near tokenTable[] =
  127. {
  128. #if !VERS_32BIT
  129. "__near", // TOK_near
  130. "__near ", // TOK_nearSp
  131. "__near*", // TOK_nearP
  132. "__far", // TOK_far
  133. "__far ", // TOK_farSp
  134. "__far*", // TOK_farP
  135. "__huge", // TOK_huge
  136. "__huge ", // TOK_hugeSp
  137. "__huge*", // TOK_hugeP
  138. #endif
  139. "__based(", // TOK_basedLp
  140. "__cdecl", // TOK_cdecl
  141. "__pascal", // TOK_pascal
  142. "__stdcall", // TOK_stdcall
  143. "__thiscall", // TOK_thiscall
  144. "__fastcall", // TOK_fastcall
  145. "__clrcall", // TOK_cocall
  146. "__ptr64", // TOK_ptr64
  147. "__restrict", // TOK_restrict
  148. "__unaligned", // TOK_unaligned
  149. #if !VERS_32BIT
  150. "__interrupt", // TOK_interrupt
  151. "__saveregs", // TOK_saveregs
  152. "__self", // TOK_self
  153. "__segment", // TOK_segment
  154. "__segname(\"", // TOK_segnameLpQ
  155. #endif
  156. ""
  157. };
  158. // The operator mapping table
  159. static const pcchar_t __near nameTable[] =
  160. {
  161. " new",
  162. " delete",
  163. "=",
  164. ">>",
  165. "<<",
  166. "!",
  167. "==",
  168. "!=",
  169. "[]",
  170. "operator",
  171. "->",
  172. "*",
  173. "++",
  174. "--",
  175. "-",
  176. "+",
  177. "&",
  178. "->*",
  179. "/",
  180. "%",
  181. "<",
  182. "<=",
  183. ">",
  184. ">=",
  185. ",",
  186. "()",
  187. "~",
  188. "^",
  189. "|",
  190. "&&",
  191. "||",
  192. "*=",
  193. "+=",
  194. "-=",
  195. "/=",
  196. "%=",
  197. ">>=",
  198. "<<=",
  199. "&=",
  200. "|=",
  201. "^=",
  202. #if ( !NO_COMPILER_NAMES )
  203. "`vftable'",
  204. "`vbtable'",
  205. "`vcall'",
  206. "`typeof'",
  207. "`local static guard'",
  208. "`string'",
  209. "`vbase destructor'",
  210. "`vector deleting destructor'",
  211. "`default constructor closure'",
  212. "`scalar deleting destructor'",
  213. "`vector constructor iterator'",
  214. "`vector destructor iterator'",
  215. "`vector vbase constructor iterator'",
  216. "`virtual displacement map'",
  217. "`eh vector constructor iterator'",
  218. "`eh vector destructor iterator'",
  219. "`eh vector vbase constructor iterator'",
  220. "`copy constructor closure'",
  221. "`udt returning'",
  222. "`EH", //eh initialized struct
  223. "`RTTI", //rtti initialized struct
  224. "`local vftable'",
  225. "`local vftable constructor closure'",
  226. #endif // !NO_COMPILER_NAMES
  227. " new[]",
  228. " delete[]",
  229. #if ( !NO_COMPILER_NAMES )
  230. "`omni callsig'",
  231. "`placement delete closure'",
  232. "`placement delete[] closure'",
  233. "`managed vector constructor iterator'",
  234. "`managed vector destructor iterator'",
  235. "`eh vector copy constructor iterator'",
  236. "`eh vector vbase copy constructor iterator'",
  237. #endif
  238. ""
  239. };
  240. static const pcchar_t ehTable[] =
  241. {
  242. " Ptr to Member Data'",
  243. " Catchable Type'",
  244. " Catchable Type Array'",
  245. " ThrowInfo'",
  246. };
  247. static const pcchar_t rttiTable[] =
  248. {
  249. " Type Descriptor'",
  250. " Base Class Descriptor at (",
  251. " Base Class Array'",
  252. " Class Hierarchy Descriptor'",
  253. " Complete Object Locator'",
  254. };
  255. // The following 'enum' should really be nested inside 'class DName', but to
  256. // make the code compile better with Glockenspiel, I have extracted it
  257. enum DNameStatus
  258. {
  259. DN_valid,
  260. DN_invalid,
  261. DN_truncated,
  262. DN_error
  263. };
  264. class DName
  265. {
  266. public:
  267. DName ();
  268. DName ( char );
  269. DName ( const DName & ); // Shallow copy
  270. DName ( DNameNode * );
  271. DName ( pcchar_t );
  272. DName ( pcchar_t&, char );
  273. DName ( DNameStatus );
  274. DName ( DName * );
  275. DName ( unsigned __int64 );
  276. DName ( __int64 );
  277. int isValid () const;
  278. int isEmpty () const;
  279. DNameStatus status () const;
  280. void clearStatus ();
  281. DName & setPtrRef ();
  282. int isPtrRef () const;
  283. int isUDC () const;
  284. void setIsUDC ();
  285. int isUDTThunk () const;
  286. void setIsUDTThunk ();
  287. int isArray() const;
  288. void setIsArray();
  289. int isNoTE () const;
  290. void setIsNoTE ();
  291. int length () const;
  292. char getLastChar () const;
  293. pchar_t getString ( pchar_t, int ) const;
  294. DName operator + ( pcchar_t ) const;
  295. DName operator + ( const DName & ) const;
  296. DName operator + ( char ) const;
  297. DName operator + ( DName * ) const;
  298. DName operator + ( DNameStatus ) const;
  299. DName & operator += ( char );
  300. DName & operator += ( pcchar_t );
  301. DName & operator += ( DName * );
  302. DName & operator += ( DNameStatus );
  303. DName & operator += ( const DName & );
  304. DName & operator |= ( const DName & );
  305. DName & operator = ( pcchar_t );
  306. DName & operator = ( const DName & );
  307. DName & operator = ( char );
  308. DName & operator = ( DName * );
  309. DName & operator = ( DNameStatus );
  310. // Friends :
  311. friend DName operator + ( char, const DName & );
  312. friend DName operator + ( pcchar_t, const DName & );
  313. friend DName operator + ( DNameStatus, const DName & );
  314. private:
  315. DNameNode * node;
  316. DNameStatus stat : 4;
  317. unsigned int isIndir : 1;
  318. unsigned int isAUDC : 1;
  319. unsigned int isAUDTThunk : 1;
  320. unsigned int isArrayType : 1;
  321. unsigned int NoTE : 1;
  322. void doPchar ( pcchar_t, int );
  323. };
  324. class Replicator
  325. {
  326. private:
  327. // Declare, in order to suppress automatic generation
  328. void operator = ( const Replicator& );
  329. int index;
  330. DName * dNameBuffer[ 10 ];
  331. const DName ErrorDName;
  332. const DName InvalidDName;
  333. public:
  334. Replicator ();
  335. int isFull () const;
  336. Replicator & operator += ( const DName & );
  337. const DName & operator [] ( int ) const;
  338. };
  339. class UnDecorator
  340. {
  341. private:
  342. // Declare, in order to suppress automatic generation
  343. void operator = ( const UnDecorator& );
  344. Replicator ArgList;
  345. static Replicator * pArgList;
  346. Replicator ZNameList;
  347. static Replicator * pZNameList;
  348. static Replicator * pTemplateArgList;
  349. static pcchar_t gName;
  350. static pcchar_t name;
  351. static pchar_t outputString;
  352. static int maxStringLength;
  353. static unsigned long disableFlags;
  354. static bool fExplicitTemplateParams;
  355. static bool fGetTemplateArgumentList;
  356. static DName getDecoratedName ( void );
  357. static DName getSymbolName ( void );
  358. static DName getZName ( bool fUpdateCachedNames );
  359. static DName getOperatorName ( bool fIsTemplate, bool *pfReadTemplateArguments );
  360. static DName getScope ( void );
  361. static DName getScopedName ( void );
  362. static DName getSignedDimension ( void );
  363. static DName getDimension ( bool fSigned = false );
  364. static int getNumberOfDimensions ( void );
  365. static DName getTemplateName ( bool );
  366. static DName getTemplateArgumentList( void );
  367. static DName getTemplateConstant( void );
  368. static DName composeDeclaration ( const DName & );
  369. static int getTypeEncoding ( void );
  370. static DName getBasedType ( void );
  371. static DName getECSUName ( void );
  372. static DName getEnumType ( void );
  373. static DName getCallingConvention ( void );
  374. static DName getReturnType ( DName * = 0 );
  375. static DName getDataType ( DName * );
  376. static DName getPrimaryDataType ( const DName & );
  377. static DName getDataIndirectType ( const DName &, char, const DName &, int = FALSE );
  378. static DName getDataIndirectType ();
  379. static DName getBasicDataType ( const DName & );
  380. static DName getECSUDataType ( void );
  381. static DName getPtrRefType ( const DName &, const DName &, char );
  382. static DName getPtrRefDataType ( const DName &, int );
  383. static DName getArrayType ( const DName& );
  384. static DName getFunctionIndirectType( const DName & superType );
  385. static DName getArgumentTypes ( void );
  386. static DName getArgumentList ( void );
  387. static DName getThrowTypes ( void );
  388. static DName getLexicalFrame ( void );
  389. static DName getStorageConvention ( void );
  390. static DName getThisType ( void );
  391. static DName getPointerType ( const DName &, const DName & );
  392. static DName getPointerTypeArray ( const DName &, const DName & );
  393. static DName getReferenceType ( const DName &, const DName & );
  394. static DName getExternalDataType ( const DName & );
  395. static DName getSegmentName ( void );
  396. #if ( !NO_COMPILER_NAMES )
  397. static DName getDisplacement ( void );
  398. static DName getCallIndex ( void );
  399. static DName getGuardNumber ( void );
  400. static DName getVfTableType ( const DName & );
  401. static DName getVbTableType ( const DName & );
  402. static DName getVdispMapType ( const DName & );
  403. static DName getVCallThunkType ( void );
  404. #endif // !NO_COMPILER_NAMES
  405. static DName getStringEncoding ( char *prefix, int wantBody );
  406. static GetParameter_t m_pGetParameter;
  407. public:
  408. UnDecorator ( pchar_t, pcchar_t, int, GetParameter_t, unsigned long );
  409. static int doUnderScore ();
  410. static int doMSKeywords ();
  411. static int doPtr64 ();
  412. static int doFunctionReturns ();
  413. static int doAllocationModel ();
  414. static int doAllocationLanguage ();
  415. #if 0
  416. static int doMSThisType ();
  417. static int doCVThisType ();
  418. #endif
  419. static int doThisTypes ();
  420. static int doAccessSpecifiers ();
  421. static int doThrowTypes ();
  422. static int doMemberTypes ();
  423. static int doReturnUDTModel ();
  424. static int do32BitNear ();
  425. static int doNameOnly ();
  426. static int doTypeOnly ();
  427. static int haveTemplateParameters ();
  428. static int doEcsu ();
  429. static int doNoIdentCharCheck ();
  430. static pcchar_t UScore ( Tokens );
  431. operator pchar_t ();
  432. };
  433. Replicator * UnDecorator::pArgList;
  434. Replicator * UnDecorator::pZNameList = 0;
  435. Replicator * UnDecorator::pTemplateArgList = 0;
  436. pcchar_t UnDecorator::gName = 0;
  437. pcchar_t UnDecorator::name = 0;
  438. pchar_t UnDecorator::outputString = 0;
  439. int UnDecorator::maxStringLength = 0;
  440. unsigned long UnDecorator::disableFlags = 0;
  441. GetParameter_t UnDecorator::m_pGetParameter = 0;
  442. bool UnDecorator::fExplicitTemplateParams = false;
  443. bool UnDecorator::fGetTemplateArgumentList = false;
  444. #ifdef _CRTBLD
  445. pchar_t __far _CRTIMP __loadds __unDName ( pchar_t outputString,
  446. #else
  447. pchar_t __far __cdecl __loadds unDName ( pchar_t outputString,
  448. #endif
  449. pcchar_t name,
  450. int maxStringLength, // Note, COMMA is leading following optional arguments
  451. Alloc_t pAlloc,
  452. Free_t pFree,
  453. unsigned short disableFlags
  454. )
  455. /*
  456. * This function will undecorate a name, returning the string corresponding to
  457. * the C++ declaration needed to produce the name. Its has a similar interface
  458. * to 'strncpy'.
  459. *
  460. * If the target string 'outputString' is specified to be NULL, a string of
  461. * suitable length will be allocated and its address returned. If the returned
  462. * string is allocated by 'unDName', then it is the programmers responsibility
  463. * to deallocate it. It will have been allocated on the far heap.
  464. *
  465. * If the target string is not NULL, then the parameter 'maxStringLength' will
  466. * specify the maximum number of characters which may be placed in the string.
  467. * In this case, the returned value is the same as 'outputString'.
  468. *
  469. * Both the input parameter 'name' and the returned string are NULL terminated
  470. * strings of characters.
  471. *
  472. * If the returned value is NULL, it indicates that the undecorator ran out of
  473. * memory, or an internal error occurred, and was unable to complete its task.
  474. */
  475. {
  476. // Must have an allocator and a deallocator (and we MUST trust them)
  477. if ( !( pAlloc ))
  478. return 0;
  479. pchar_t unDecoratedName;
  480. #if (defined(_CRTBLD) && defined(_MT))
  481. if (!_mtinitlocknum(_UNDNAME_LOCK))
  482. return 0;
  483. _mlock(_UNDNAME_LOCK);
  484. __try {
  485. #endif
  486. heap.Constructor ( pAlloc, pFree );
  487. // Create the undecorator object, and get the result
  488. UnDecorator unDecorate ( outputString,
  489. name,
  490. maxStringLength,
  491. 0,
  492. disableFlags
  493. );
  494. unDecoratedName = unDecorate;
  495. // Destruct the heap (would use a destructor, but that causes DLL problems)
  496. heap.Destructor ();
  497. #if (defined(_CRTBLD) && defined(_MT))
  498. } __finally {
  499. _munlock(_UNDNAME_LOCK);
  500. }
  501. #endif
  502. // And return the composed name
  503. return unDecoratedName;
  504. } // End of FUNCTION "unDName"
  505. #ifdef _CRTBLD
  506. pchar_t __far _CRTIMP __loadds __unDNameEx ( pchar_t outputString,
  507. #else
  508. pchar_t __far __cdecl __loadds unDNameEx ( pchar_t outputString,
  509. #endif
  510. pcchar_t name,
  511. int maxStringLength, // Note, COMMA is leading following optional arguments
  512. Alloc_t pAlloc,
  513. Free_t pFree,
  514. GetParameter_t pGetParameter,
  515. unsigned long disableFlags
  516. )
  517. /*
  518. * This function will undecorate a name, returning the string corresponding to
  519. * the C++ declaration needed to produce the name. Its has a similar interface
  520. * to 'strncpy'.
  521. *
  522. * If the target string 'outputString' is specified to be NULL, a string of
  523. * suitable length will be allocated and its address returned. If the returned
  524. * string is allocated by 'unDName', then it is the programmers responsibility
  525. * to deallocate it. It will have been allocated on the far heap.
  526. *
  527. * If the target string is not NULL, then the parameter 'maxStringLength' will
  528. * specify the maximum number of characters which may be placed in the string.
  529. * In this case, the returned value is the same as 'outputString'.
  530. *
  531. * Both the input parameter 'name' and the returned string are NULL terminated
  532. * strings of characters.
  533. *
  534. * If the returned value is NULL, it indicates that the undecorator ran out of
  535. * memory, or an internal error occurred, and was unable to complete its task.
  536. */
  537. {
  538. // Must have an allocator and a deallocator (and we MUST trust them)
  539. if ( !( pAlloc ))
  540. return 0;
  541. pchar_t unDecoratedName;
  542. #if (defined(_CRTBLD) && defined(_MT))
  543. if (!_mtinitlocknum(_UNDNAME_LOCK))
  544. return 0;
  545. _mlock(_UNDNAME_LOCK);
  546. __try {
  547. #endif
  548. heap.Constructor ( pAlloc, pFree );
  549. // Create the undecorator object, and get the result
  550. UnDecorator unDecorate ( outputString,
  551. name,
  552. maxStringLength,
  553. pGetParameter,
  554. disableFlags
  555. );
  556. unDecoratedName = unDecorate;
  557. // Destruct the heap (would use a destructor, but that causes DLL problems)
  558. heap.Destructor ();
  559. #if (defined(_CRTBLD) && defined(_MT))
  560. } __finally {
  561. _munlock(_UNDNAME_LOCK);
  562. }
  563. #endif
  564. // And return the composed name
  565. return unDecoratedName;
  566. } // End of FUNCTION "unDName"
  567. // The 'UnDecorator' member functions
  568. inline UnDecorator::UnDecorator ( pchar_t output,
  569. pcchar_t dName,
  570. int maxLen,
  571. GetParameter_t pGetParameter,
  572. unsigned long disable
  573. )
  574. {
  575. name = dName;
  576. gName = name;
  577. if ( output ) {
  578. maxStringLength = maxLen - 1; // The algorithm in getString doesn't leave room
  579. // for terminating NULL; be paranoid and leave one
  580. // extra char.
  581. // It's a lot easier to fix this here....
  582. outputString = output;
  583. }
  584. else {
  585. outputString = 0;
  586. maxStringLength = 0;
  587. }
  588. pZNameList = &ZNameList;
  589. pArgList = &ArgList;
  590. disableFlags = disable;
  591. m_pGetParameter = pGetParameter;
  592. fExplicitTemplateParams = false;
  593. } // End of "UnDecorator" CONSTRUCTOR '()'
  594. inline UnDecorator::operator pchar_t ()
  595. {
  596. DName result;
  597. DName unDName;
  598. // Find out if the name is a decorated name or not. Could be a reserved
  599. // CodeView variant of a decorated name
  600. if ( name )
  601. {
  602. if (( *name == '?' ) && ( name[ 1 ] == '@' ))
  603. {
  604. #if ( !NO_COMPILER_NAMES )
  605. gName += 2;
  606. result = "CV: " + getDecoratedName ();
  607. #else // } elif NO_COMPILER_NAMES
  608. result = DN_invalid;
  609. #endif // NO_COMPILER_NAMES
  610. } // End of IF then
  611. else if (( *name == '?' ) && ( name[1] == '$' )) {
  612. result = getTemplateName( false );
  613. if ( result.status () == DN_invalid ) {
  614. //
  615. // What harm could there be to try again ?
  616. // Repro:
  617. // ?$S1@?1??VTFromRegType@CRegParser@ATL@@KAHPBGAAG@Z@4IA
  618. // ---> unsigned int `protected: static int __cdecl ATL::CRegParser::VTFromRegType(unsigned short const *,unsigned short &)'::`2'::$S1
  619. //
  620. // This is a compiler generated symbol for a local static array init.
  621. //
  622. gName = name;
  623. result.clearStatus();
  624. result = getDecoratedName ();
  625. }
  626. } else {
  627. result = getDecoratedName ();
  628. }
  629. } // End of IF then
  630. // If the name was not a valid name, then make the name the same as the original
  631. // It is also invalid if there are any remaining characters in the name (except when
  632. // we're giving the name only)
  633. if ( result.status () == DN_error )
  634. return 0;
  635. elif ( (*gName && !doNameOnly ()) || ( result.status () == DN_invalid ))
  636. unDName = name; // Return the original name
  637. else
  638. unDName = result;
  639. // Construct the return string
  640. if ( !outputString )
  641. {
  642. maxStringLength = unDName.length () + 1;
  643. outputString = rnew char[ maxStringLength ];
  644. } // End of IF
  645. if ( outputString ) {
  646. unDName.getString ( outputString, maxStringLength );
  647. // strip extra whitespace out of name
  648. pchar_t pRead = outputString;
  649. pchar_t pWrite = pRead;
  650. while (*pRead) {
  651. if (*pRead == ' ') {
  652. pRead++;
  653. *pWrite++ = ' ';
  654. while ( *pRead == ' ' ) {
  655. pRead++;
  656. }
  657. }
  658. else
  659. *pWrite++ = *pRead++;
  660. }
  661. *pWrite = *pRead;
  662. }
  663. // Return the result
  664. return outputString;
  665. } // End of "UnDecorator" OPERATOR 'pchar_t'
  666. DName UnDecorator::getDecoratedName ( void )
  667. {
  668. // Ensure that it is intended to be a decorated name
  669. if ( doTypeOnly() )
  670. {
  671. // Disable the type-only flag, so that if we get here recursively, eg.
  672. // in a template tag, we do full name undecoration.
  673. disableFlags &= ~UNDNAME_TYPE_ONLY;
  674. // If we're decoding just a type, process it as the type for an abstract
  675. // declarator, by giving an empty symbol name.
  676. DName result = getDataType ( NULL );
  677. disableFlags |= UNDNAME_TYPE_ONLY;
  678. return result;
  679. }
  680. elif ( *gName == '?' )
  681. {
  682. // Extract the basic symbol name
  683. gName++; // Advance the original name pointer
  684. DName symbolName = getSymbolName ();
  685. int udcSeen = symbolName.isUDC ();
  686. // Abort if the symbol name is invalid
  687. if ( !symbolName.isValid ())
  688. return symbolName;
  689. // Extract, and prefix the scope qualifiers
  690. if ( *gName && ( *gName != '@' )) {
  691. DName scope = getScope ();
  692. if ( !scope.isEmpty() )
  693. if (fExplicitTemplateParams) {
  694. fExplicitTemplateParams = false;
  695. symbolName = symbolName + scope;
  696. if (*gName != '@') {
  697. scope = getScope();
  698. symbolName = scope + "::" + symbolName;
  699. }
  700. } else {
  701. symbolName = scope + "::" + symbolName;
  702. }
  703. }
  704. if ( udcSeen )
  705. symbolName.setIsUDC ();
  706. // Now compose declaration
  707. if ( symbolName.isEmpty () || symbolName.isNoTE() )
  708. {
  709. return symbolName;
  710. }
  711. elif ( !*gName || ( *gName == '@' ) )
  712. {
  713. if ( *gName )
  714. gName++;
  715. if (doNameOnly () && !udcSeen) {
  716. // Eat the rest of the dname, in case this is a recursive invocation,
  717. // such as for a template argument.
  718. (void)composeDeclaration( DName() );
  719. return symbolName;
  720. }
  721. else {
  722. return composeDeclaration ( symbolName );
  723. }
  724. } // End of ELIF then
  725. else
  726. return DN_invalid;
  727. } // End of IF then
  728. elif ( *gName )
  729. return DN_invalid;
  730. else
  731. return DN_truncated;
  732. } // End of "UnDecorator" FUNCTION "getDecoratedName"
  733. inline DName UnDecorator::getSymbolName()
  734. {
  735. if (gName[0] == '?') {
  736. if (gName[1] == '$') {
  737. return getTemplateName(true);
  738. }
  739. else {
  740. gName += 1;
  741. return getOperatorName(false, NULL);
  742. }
  743. }
  744. else {
  745. return getZName(true);
  746. }
  747. }
  748. DName UnDecorator::getZName ( bool fUpdateCachedNames )
  749. {
  750. int zNameIndex = *gName - '0';
  751. // Handle 'zname-replicators', otherwise an actual name
  752. if (( zNameIndex >= 0 ) && ( zNameIndex <= 9 ))
  753. {
  754. gName++; // Skip past the replicator
  755. // And return the indexed name
  756. return ( *pZNameList )[ zNameIndex ];
  757. } // End of IF then
  758. else
  759. {
  760. DName zName;
  761. if ( *gName == '?' )
  762. {
  763. zName = getTemplateName( false );
  764. if ( *gName++ != '@' )
  765. zName = *--gName ? DN_invalid : DN_truncated;
  766. }
  767. else {
  768. #define TEMPLATE_PARAMETER "template-parameter-"
  769. #define TEMPLATE_PARAMETER_LEN 19
  770. #define GENERIC_TYPE "generic-type-"
  771. #define GENERIC_TYPE_LEN 13
  772. pchar_t genericType;
  773. if (und_strncmp(gName, TEMPLATE_PARAMETER, TEMPLATE_PARAMETER_LEN) == 0) {
  774. genericType = TEMPLATE_PARAMETER;
  775. gName += TEMPLATE_PARAMETER_LEN;
  776. } else if (und_strncmp(gName, GENERIC_TYPE, GENERIC_TYPE_LEN) == 0) {
  777. genericType = GENERIC_TYPE;
  778. gName += GENERIC_TYPE_LEN;
  779. } else {
  780. genericType = NULL;
  781. }
  782. if (genericType) {
  783. DName dimension = getSignedDimension();
  784. if ( haveTemplateParameters()) {
  785. char buffer[16];
  786. dimension.getString( buffer, 16 );
  787. char *str = (*m_pGetParameter)(atol(buffer));
  788. if ( str != NULL ) {
  789. zName = str;
  790. }
  791. else {
  792. zName = "`";
  793. zName += genericType + dimension + "'";
  794. }
  795. }
  796. else {
  797. zName = "`";
  798. zName += genericType + dimension + "'";
  799. }
  800. }
  801. else {
  802. // Extract the 'zname' to the terminator
  803. zName = DName( gName, '@' ); // This constructor updates 'name'
  804. }
  805. }
  806. // Add it to the current list of 'zname's
  807. if ( fUpdateCachedNames && !pZNameList->isFull ())
  808. *pZNameList += zName;
  809. // And return the symbol name
  810. return zName;
  811. } // End of IF else
  812. } // End of "UnDecorator" FUNCTION "getZName"
  813. inline DName UnDecorator::getOperatorName ( bool fIsTemplate, bool *pfReadTemplateArguments )
  814. {
  815. DName operatorName;
  816. DName tmpName;
  817. int udcSeen = FALSE;
  818. // So what type of operator is it ?
  819. switch ( *gName++ )
  820. {
  821. case 0:
  822. gName--; // End of string, better back-track
  823. return DN_truncated;
  824. case OC_ctor:
  825. case OC_dtor:
  826. //
  827. // The constructor and destructor are special:
  828. // Their operator name is the name of their first enclosing scope, which
  829. // will always be a tag, which may be a template specialization!
  830. //
  831. {
  832. //
  833. // Is this a specialization of a member function template? If it is
  834. // then we will actually have the template arguments between the "name"
  835. // of the operator and the scope: so we need to read the template
  836. // arguments before we try to read the name of the class
  837. //
  838. DName templateArguments;
  839. if ( fIsTemplate ) {
  840. templateArguments += '<' + getTemplateArgumentList();
  841. if ( templateArguments.getLastChar () == '>' ) {
  842. templateArguments += ' ';
  843. }
  844. templateArguments += '>';
  845. gName += 1;
  846. if ( pfReadTemplateArguments != NULL ) {
  847. *pfReadTemplateArguments = true;
  848. }
  849. }
  850. //
  851. // Use a temporary. Don't want to advance the name pointer
  852. //
  853. pcchar_t pName = gName;
  854. operatorName = getZName ( false );
  855. gName = pName; // Undo our lookahead
  856. if ( !operatorName.isEmpty () && ( gName[ -1 ] == OC_dtor ))
  857. operatorName = '~' + operatorName;
  858. //
  859. // Append the template argumentsa (if there are any)
  860. //
  861. if ( !templateArguments.isEmpty()) {
  862. operatorName += templateArguments;
  863. }
  864. return operatorName;
  865. } // End of CASE 'OC_ctor,OC_dtor'
  866. break;
  867. case OC_new:
  868. case OC_delete:
  869. case OC_assign:
  870. case OC_rshift:
  871. case OC_lshift:
  872. case OC_not:
  873. case OC_equal:
  874. case OC_unequal:
  875. operatorName = nameTable[ gName[ -1 ] - OC_new ];
  876. break;
  877. case OC_udc:
  878. udcSeen = TRUE;
  879. // No break
  880. case OC_index:
  881. case OC_pointer:
  882. case OC_star:
  883. case OC_incr:
  884. case OC_decr:
  885. case OC_minus:
  886. case OC_plus:
  887. case OC_amper:
  888. case OC_ptrmem:
  889. case OC_divide:
  890. case OC_modulo:
  891. case OC_less:
  892. case OC_leq:
  893. case OC_greater:
  894. case OC_geq:
  895. case OC_comma:
  896. case OC_call:
  897. case OC_compl:
  898. case OC_xor:
  899. case OC_or:
  900. case OC_land:
  901. case OC_lor:
  902. case OC_asmul:
  903. case OC_asadd:
  904. case OC_assub: // Regular operators from the first group
  905. operatorName = nameTable[ gName[ -1 ] - OC_index + ( OC_unequal - OC_new + 1 )];
  906. break;
  907. case '_':
  908. switch ( *gName++ )
  909. {
  910. case 0:
  911. gName--; // End of string, better back-track
  912. return DN_truncated;
  913. case OC_asdiv:
  914. case OC_asmod:
  915. case OC_asrshift:
  916. case OC_aslshift:
  917. case OC_asand:
  918. case OC_asor:
  919. case OC_asxor: // Regular operators from the extended group
  920. operatorName = nameTable[ gName[ -1 ] - OC_asdiv + ( OC_assub - OC_index + 1 ) + ( OC_unequal - OC_new + 1 )];
  921. break;
  922. #if ( !NO_COMPILER_NAMES )
  923. case OC_vftable:
  924. case OC_vbtable:
  925. case OC_vcall:
  926. return nameTable[ gName[ -1 ] - OC_asdiv + ( OC_assub - OC_index + 1 ) + ( OC_unequal - OC_new + 1 )];
  927. case OC_string:
  928. {
  929. DName result = getStringEncoding( "`string'", TRUE );
  930. result.setIsNoTE();
  931. return result;
  932. }
  933. case OC_metatype:
  934. case OC_guard:
  935. case OC_vbdtor:
  936. case OC_vdeldtor:
  937. case OC_defctor:
  938. case OC_sdeldtor:
  939. case OC_vctor:
  940. case OC_vdtor:
  941. case OC_vallctor:
  942. case OC_vdispmap:
  943. case OC_ehvctor:
  944. case OC_ehvdtor:
  945. case OC_ehvctorvb:
  946. case OC_copyctorclosure:
  947. case OC_locvfctorclosure:
  948. case OC_locvftable: // Special purpose names
  949. case OC_placementDeleteClosure:
  950. case OC_placementArrayDeleteClosure:
  951. return nameTable[ gName[ -1 ] - OC_metatype + ( OC_vcall - OC_asdiv + 1 ) + ( OC_assub - OC_index + 1 ) + ( OC_unequal - OC_new + 1 )];
  952. case OC_udtthunk:
  953. operatorName = nameTable[ gName[ -1 ] - OC_metatype + ( OC_vcall - OC_asdiv + 1 ) + ( OC_assub - OC_index + 1 ) + ( OC_unequal - OC_new + 1 )];
  954. tmpName = getOperatorName( false, NULL );
  955. if ( !tmpName.isEmpty() && tmpName.isUDTThunk() )
  956. return DN_invalid;
  957. return operatorName + tmpName;
  958. break;
  959. case OC_eh_init:
  960. break;
  961. case OC_rtti_init:
  962. operatorName = nameTable[ gName[ -1 ] - OC_metatype + ( OC_vcall - OC_asdiv + 1 ) + ( OC_assub - OC_index + 1 ) + ( OC_unequal - OC_new + 1 )];
  963. tmpName = rttiTable[ gName[0] - OC_rtti_TD ];
  964. switch ( *gName++ )
  965. {
  966. case OC_rtti_TD:
  967. {
  968. DName result = getDataType ( NULL );
  969. return result + ' ' + operatorName + tmpName;
  970. }
  971. break;
  972. case OC_rtti_BCD:
  973. {
  974. DName result = operatorName + tmpName;
  975. result += getSignedDimension() + ',';
  976. result += getSignedDimension() + ',';
  977. result += getSignedDimension() + ',';
  978. result += getDimension() + ')';
  979. return result + '\'';
  980. }
  981. break;
  982. case OC_rtti_BCA:
  983. case OC_rtti_CHD:
  984. case OC_rtti_COL:
  985. return operatorName + tmpName;
  986. break;
  987. default:
  988. gName--;
  989. return DN_truncated;
  990. break;
  991. }
  992. break;
  993. #endif // !NO_COMPILER_NAMES
  994. case OC_arrayNew:
  995. case OC_arrayDelete:
  996. operatorName = nameTable[ gName[ -1 ] - OC_metatype + ( OC_vcall - OC_asdiv + 1 ) + ( OC_assub - OC_index + 1 ) + ( OC_unequal - OC_new + 1 )
  997. #if NO_COMPILER_NAMES
  998. - ( OC_locvfctorclosure - OC_vftable + 1 ) // discount names not in table
  999. #endif
  1000. ];
  1001. break;
  1002. // Yet another level of nested encodings....
  1003. case '?':
  1004. switch( *gName++ ) {
  1005. case 0:
  1006. gName--; // End of string, better back-track
  1007. return DN_truncated;
  1008. case OC_anonymousNamespace:
  1009. //
  1010. // Anonymous namespace (new-style) is a string encoding of the
  1011. // machine name and the translation unit name. Since the remainder
  1012. // of the name doesn't really fit the dname grammar, skip it.
  1013. // There are two '@' markers in the name....
  1014. //
  1015. {
  1016. DName result = getStringEncoding( "`anonymous namespace'", FALSE );
  1017. result.setIsNoTE();
  1018. return result;
  1019. }
  1020. default:
  1021. return DN_invalid;
  1022. }
  1023. break;
  1024. //
  1025. // A double extended operator
  1026. //
  1027. case '_':
  1028. switch (*gName++) {
  1029. case OC_man_vec_ctor:
  1030. case OC_man_vec_dtor:
  1031. case OC_ehvcctor:
  1032. case OC_ehvcctorvb:
  1033. return nameTable[ gName[ -1 ] - OC_man_vec_ctor + ( OC_placementArrayDeleteClosure - OC_metatype + 1) + ( OC_vcall - OC_asdiv + 1 ) + ( OC_assub - OC_index + 1 ) + ( OC_unequal - OC_new + 1 )];
  1034. default:
  1035. return DN_invalid;
  1036. }
  1037. break;
  1038. default:
  1039. return DN_invalid;
  1040. } // End of SWITCH
  1041. break;
  1042. default:
  1043. return DN_invalid;
  1044. } // End of SWITCH
  1045. // This really is an operator name, so prefix it with 'operator'
  1046. if ( udcSeen )
  1047. operatorName.setIsUDC ();
  1048. elif ( !operatorName.isEmpty ())
  1049. operatorName = "operator" + operatorName;
  1050. return operatorName;
  1051. } // End of "UnDecorator" FUNCTION "getOperatorName"
  1052. DName UnDecorator::getStringEncoding ( char *prefix, int wantBody )
  1053. {
  1054. DName result = prefix;
  1055. // First @ comes right after operator code
  1056. if ( *gName++ != '@' || *gName++ != '_' ) {
  1057. return DN_invalid;
  1058. }
  1059. // Skip the string kind
  1060. gName++;
  1061. // Get (& discard) the length
  1062. getDimension();
  1063. // Get (& discart) the checksum
  1064. getDimension();
  1065. while ( *gName && *gName != '@' ) {
  1066. // For now, we'll just skip it
  1067. gName++;
  1068. }
  1069. if ( !*gName ) {
  1070. gName--;
  1071. return DN_truncated;
  1072. }
  1073. // Eat the terminating '@'
  1074. gName++;
  1075. return result;
  1076. }
  1077. DName UnDecorator::getScope ( void )
  1078. {
  1079. DName scope;
  1080. bool fNeedBracket = false;
  1081. // Get the list of scopes
  1082. while (( scope.status () == DN_valid ) && *gName && ( *gName != '@' ))
  1083. { // Insert the scope operator if not the first scope
  1084. if (fExplicitTemplateParams && !fGetTemplateArgumentList) {
  1085. return scope;
  1086. }
  1087. if ( !scope.isEmpty() ) {
  1088. scope = "::" + scope;
  1089. if (fNeedBracket) {
  1090. scope = '[' + scope;
  1091. fNeedBracket = false;
  1092. }
  1093. }
  1094. // Determine what kind of scope it is
  1095. if ( *gName == '?' )
  1096. switch ( *++gName )
  1097. {
  1098. case '?':
  1099. if ( gName[1] == '_' && gName[2] == '?' ) {
  1100. //
  1101. // Anonymous namespace name (new style)
  1102. //
  1103. gName++;
  1104. scope = getOperatorName ( false, NULL ) + scope;
  1105. // There should be a zname termination @...
  1106. if ( *gName == '@' ) {
  1107. gName++;
  1108. }
  1109. }
  1110. else
  1111. scope = '`' + getDecoratedName () + '\'' + scope;
  1112. break;
  1113. case '$':
  1114. // It's a template name, which is a kind of zname; back up
  1115. // and handle like a zname.
  1116. gName--;
  1117. scope = getZName ( true ) + scope;
  1118. break;
  1119. case 'A':
  1120. //
  1121. // This is a new-new encoding for anonymous namespaces
  1122. //
  1123. // fall-through
  1124. case '%':
  1125. //
  1126. // It an anonymous namespace (old-style);
  1127. // skip the (unreadable) name and instead insert
  1128. // an appropriate string
  1129. //
  1130. while ( *gName != '@' ) {
  1131. gName++;
  1132. }
  1133. gName++;
  1134. scope = "`anonymous namespace'" + scope;
  1135. break;
  1136. case 'I':
  1137. //
  1138. // This is the interface whose method the class is
  1139. // implementing
  1140. //
  1141. gName++;
  1142. scope = getZName ( true ) + ']' + scope;
  1143. fNeedBracket = true;
  1144. break;
  1145. default:
  1146. scope = getLexicalFrame () + scope;
  1147. break;
  1148. } // End of SWITCH
  1149. else
  1150. scope = getZName ( true ) + scope;
  1151. } // End of WHILE
  1152. // Catch error conditions
  1153. switch ( *gName )
  1154. {
  1155. case 0:
  1156. if ( scope.isEmpty() )
  1157. scope = DN_truncated;
  1158. else
  1159. scope = DName ( DN_truncated ) + "::" + scope;
  1160. break;
  1161. case '@': // '@' expected to end the scope list
  1162. break;
  1163. default:
  1164. scope = DN_invalid;
  1165. break;
  1166. } // End of SWITCH
  1167. // Return the composed scope
  1168. return scope;
  1169. } // End of "UnDecorator" FUNCTION "getScope"
  1170. DName UnDecorator::getSignedDimension ( void )
  1171. {
  1172. if ( !*gName )
  1173. return DN_truncated;
  1174. elif ( *gName == '?' ) {
  1175. gName++; // skip the '?'
  1176. return '-' + getDimension();
  1177. }
  1178. else
  1179. return getDimension();
  1180. } // End of "Undecorator" FUNCTION "getSignedDimension"
  1181. DName UnDecorator::getDimension ( bool fSigned )
  1182. {
  1183. char* prefix = 0;
  1184. if (*gName == TC_nontype_dummy) {
  1185. prefix = "`non-type-template-parameter";
  1186. ++gName;
  1187. }
  1188. if ( !*gName )
  1189. return DN_truncated;
  1190. elif (( *gName >= '0' ) && ( *gName <= '9' ))
  1191. return prefix ? (prefix + DName ((unsigned __int64)( *gName++ - '0' + 1 ))) : DName ((unsigned __int64)( *gName++ - '0' + 1 ));
  1192. else
  1193. {
  1194. unsigned __int64 dim = 0ui64;
  1195. // Don't bother detecting overflow, it's not worth it
  1196. while ( *gName != '@' )
  1197. {
  1198. if ( !*gName )
  1199. return DN_truncated;
  1200. elif (( *gName >= 'A' ) && ( *gName <= 'P' ))
  1201. dim = ( dim << 4 ) + ( *gName - 'A' );
  1202. else
  1203. return DN_invalid;
  1204. gName++;
  1205. } // End of WHILE
  1206. // Ensure integrity, and return
  1207. if ( *gName++ != '@' )
  1208. return DN_invalid; // Should never get here
  1209. if (fSigned) {
  1210. return prefix ? (prefix + DName((__int64)dim)) : DName((__int64)dim);
  1211. } else {
  1212. return prefix ? (prefix + DName(dim)) : dim;
  1213. }
  1214. } // End of ELIF else
  1215. } // End of "UnDecorator" FUNCTION "getDimension"
  1216. int UnDecorator::getNumberOfDimensions ( void )
  1217. {
  1218. if ( !*gName )
  1219. return 0;
  1220. elif (( *gName >= '0' ) && ( *gName <= '9' ))
  1221. return (( *gName++ - '0' ) + 1 );
  1222. else
  1223. {
  1224. int dim = 0;
  1225. // Don't bother detecting overflow, it's not worth it
  1226. while ( *gName != '@' )
  1227. {
  1228. if ( !*gName )
  1229. return 0;
  1230. elif (( *gName >= 'A' ) && ( *gName <= 'P' ))
  1231. dim = ( dim << 4 ) + ( *gName - 'A' );
  1232. else
  1233. return -1;
  1234. gName++;
  1235. } // End of WHILE
  1236. // Ensure integrity, and return
  1237. if ( *gName++ != '@' )
  1238. return -1; // Should never get here
  1239. return dim;
  1240. } // End of ELIF else
  1241. } // End of "UnDecorator" FUNCTION "getNumberOfDimensions"
  1242. DName UnDecorator::getTemplateName( bool fReadTerminator )
  1243. {
  1244. //
  1245. // First make sure we're really looking at a template name
  1246. //
  1247. if ( gName[0] != '?' || gName[1] != '$' )
  1248. return DN_invalid;
  1249. gName += 2; // Skip the marker characters
  1250. //
  1251. // Stack the replicators, since template names are their own replicator scope:
  1252. //
  1253. Replicator * pSaveArgList = pArgList;
  1254. Replicator * pSaveZNameList = pZNameList;
  1255. Replicator * pSaveTemplateArgList = pTemplateArgList;
  1256. Replicator localArgList, localZNameList, localTemplateArgList;
  1257. pArgList = &localArgList;
  1258. pZNameList = &localZNameList;
  1259. pTemplateArgList = &localTemplateArgList;
  1260. //
  1261. // Crack the template name:
  1262. //
  1263. DName templateName;
  1264. DName templateArguments;
  1265. bool fReadTemplateArguments = false;
  1266. if ( *gName == '?' ) {
  1267. gName += 1;
  1268. templateName = getOperatorName( true, &fReadTemplateArguments );
  1269. }
  1270. else {
  1271. templateName = getZName( true );
  1272. }
  1273. if (templateName.isEmpty ()) {
  1274. fExplicitTemplateParams = true;
  1275. }
  1276. //
  1277. // If we haven't already read the template arguments then
  1278. // now is the time to read them
  1279. //
  1280. if ( !fReadTemplateArguments ) {
  1281. templateName += '<' + getTemplateArgumentList ();
  1282. if ( templateName.getLastChar () == '>' ) {
  1283. templateName += ' ';
  1284. }
  1285. templateName += '>';
  1286. if ( fReadTerminator ) {
  1287. gName += 1;
  1288. }
  1289. }
  1290. //
  1291. // Restore the previous replicators:
  1292. //
  1293. pArgList = pSaveArgList;
  1294. pZNameList = pSaveZNameList;
  1295. pTemplateArgList = pSaveTemplateArgList;
  1296. // Return the completed 'template-name'
  1297. return templateName;
  1298. } // End of "UnDecorator" FUNCTION "getTemplateName"
  1299. DName UnDecorator::getTemplateArgumentList ( void )
  1300. {
  1301. int first = TRUE;
  1302. DName aList;
  1303. fGetTemplateArgumentList = true;
  1304. while (( aList.status () == DN_valid ) && *gName && ( *gName != AT_endoflist ))
  1305. {
  1306. // Insert the argument list separator if not the first argument
  1307. if ( first )
  1308. first = FALSE;
  1309. else
  1310. aList += ',';
  1311. // Get the individual argument type
  1312. int argIndex = *gName - '0';
  1313. // Handle 'template-argument-replicators', otherwise a new argument type
  1314. if (( argIndex >= 0 ) && ( argIndex <= 9 ))
  1315. {
  1316. gName++; // Skip past the replicator
  1317. // Append to the argument list
  1318. aList += ( *pTemplateArgList )[ argIndex ];
  1319. } // End of IF then
  1320. else
  1321. {
  1322. pcchar_t oldGName = gName;
  1323. DName arg;
  1324. //
  1325. // Extract the 'argument' type
  1326. //
  1327. if ( *gName == DT_void ) {
  1328. gName++;
  1329. arg = "void";
  1330. }
  1331. elif ( (*gName == '$') && (gName[1] != '$')) {
  1332. gName++;
  1333. arg = getTemplateConstant();
  1334. }
  1335. elif ( *gName == '?' ) {
  1336. //
  1337. // This is a template-parameter, i.e. we have a "specialization" of
  1338. // X<T>. so get the template-parameter-index and use a "generic" name
  1339. // for this parameter
  1340. //
  1341. DName dimension = getSignedDimension();
  1342. if ( haveTemplateParameters()) {
  1343. char buffer[16];
  1344. dimension.getString( buffer, 16 );
  1345. char *str = (*m_pGetParameter)(atol(buffer));
  1346. if ( str != NULL ) {
  1347. arg = str;
  1348. }
  1349. else {
  1350. arg = "`template-parameter" + dimension + "'";
  1351. }
  1352. }
  1353. else {
  1354. arg = "`template-parameter" + dimension + "'";
  1355. }
  1356. }
  1357. else {
  1358. arg = getPrimaryDataType ( DName() );
  1359. }
  1360. // Add it to the current list of 'template-argument's, if it is bigger than a one byte encoding
  1361. if ((( gName - oldGName ) > 1 ) && !pTemplateArgList->isFull ())
  1362. *pTemplateArgList += arg;
  1363. // Append to the argument list
  1364. aList += arg;
  1365. } // End of IF else
  1366. } // End of WHILE
  1367. // Return the completed template argument list
  1368. fGetTemplateArgumentList = false;
  1369. return aList;
  1370. } // End of "UnDecorator" FUNCTION "getTemplateArgumentList"
  1371. DName UnDecorator::getTemplateConstant(void)
  1372. {
  1373. //
  1374. // template-constant ::=
  1375. // '0' <template-integral-constant>
  1376. // '1' <template-address-constant>
  1377. // '2' <template-floating-point-constant>
  1378. //
  1379. char type_category = *gName++;
  1380. switch ( type_category )
  1381. {
  1382. //
  1383. // template-integral-constant ::=
  1384. // <signed-dimension>
  1385. //
  1386. case TC_integral:
  1387. return getSignedDimension ();
  1388. //
  1389. // template-address-constant ::=
  1390. // '@' // Null pointer
  1391. // <decorated-name>
  1392. //
  1393. case TC_address:
  1394. if ( *gName == TC_nullptr )
  1395. {
  1396. gName++;
  1397. return "NULL";
  1398. }
  1399. else
  1400. return DName("&") + getDecoratedName ();
  1401. //
  1402. // template-name ::=
  1403. // <docorated-name>
  1404. //
  1405. case TC_name:
  1406. return getDecoratedName ();
  1407. //
  1408. // template-floating-point-constant ::=
  1409. // <normalized-mantissa><exponent>
  1410. //
  1411. case TC_fp:
  1412. {
  1413. DName mantissa ( getSignedDimension () );
  1414. DName exponent ( getSignedDimension () );
  1415. if ( mantissa.isValid() && exponent.isValid() )
  1416. {
  1417. //
  1418. // Get string representation of mantissa
  1419. //
  1420. char buf[100]; // Way overkill for a compiler generated fp constant
  1421. if ( !mantissa.getString( &(buf[1]), 100 ) )
  1422. return DN_invalid;
  1423. //
  1424. // Insert decimal point
  1425. //
  1426. buf[0] = buf[1];
  1427. if ( buf[0] == '-' )
  1428. {
  1429. buf[1] = buf[2];
  1430. buf[2] = '.';
  1431. }
  1432. else
  1433. buf[1] = '.';
  1434. //
  1435. // String it all together
  1436. //
  1437. return DName( buf ) + 'e' + exponent;
  1438. } // End of IF then
  1439. else
  1440. return DN_truncated;
  1441. } // End of BLOCK case TC_fp
  1442. case TC_dummy:
  1443. case TC_nontype_dummy:
  1444. {
  1445. //
  1446. // This is a template-parameter, i.e. we have a "specialization" of
  1447. // X<n>. so get the template-parameter-index and use a "generic" name
  1448. // for this parameter
  1449. //
  1450. DName dimension = getSignedDimension();
  1451. if ( haveTemplateParameters()) {
  1452. char buffer[16];
  1453. dimension.getString( buffer, 16 );
  1454. char *str = (*m_pGetParameter)(atol(buffer));
  1455. if ( str != NULL ) {
  1456. return str;
  1457. }
  1458. }
  1459. if (type_category == TC_dummy) {
  1460. return "`template-parameter" + dimension + "'";
  1461. } else {
  1462. return "`non-type-template-parameter" + dimension + "'";
  1463. }
  1464. }
  1465. break;
  1466. case TC_vptmd:
  1467. case TC_gptmd:
  1468. case TC_mptmf:
  1469. case TC_vptmf:
  1470. case TC_gptmf:
  1471. {
  1472. DName ptm = '{';
  1473. switch (type_category) {
  1474. case TC_mptmf:
  1475. case TC_vptmf:
  1476. case TC_gptmf:
  1477. ptm += getDecoratedName();
  1478. ptm += ',';
  1479. break;
  1480. }
  1481. switch (type_category) {
  1482. case TC_gptmf:
  1483. case TC_gptmd:
  1484. ptm += getSignedDimension();
  1485. ptm += ',';
  1486. // fallthrough
  1487. case TC_vptmd:
  1488. case TC_vptmf:
  1489. ptm += getSignedDimension();
  1490. ptm += ',';
  1491. // fallthrough
  1492. case TC_mptmf:
  1493. ptm += getSignedDimension();
  1494. }
  1495. return ptm + '}';
  1496. }
  1497. break;
  1498. case '\0':
  1499. --gName;
  1500. return DN_truncated;
  1501. default:
  1502. return DN_invalid;
  1503. } // End of SWITCH
  1504. } // End of "UnDecorator" FUNCTION "getTemplateConstant"
  1505. inline DName UnDecorator::composeDeclaration ( const DName & symbol )
  1506. {
  1507. DName declaration;
  1508. unsigned int typeCode = getTypeEncoding ();
  1509. int symIsUDC = symbol.isUDC ();
  1510. // Handle bad typeCode's, or truncation
  1511. if ( TE_isbadtype ( typeCode ))
  1512. return DN_invalid;
  1513. elif ( TE_istruncated ( typeCode ))
  1514. return ( DN_truncated + symbol );
  1515. elif ( TE_isCident ( typeCode ))
  1516. return symbol;
  1517. // This is a very complex part. The type of the declaration must be
  1518. // determined, and the exact composition must be dictated by this type.
  1519. // Is it any type of a function ?
  1520. // However, for ease of decoding, treat the 'localdtor' thunk as data, since
  1521. // its decoration is a function of the variable to which it belongs and not
  1522. // a usual function type of decoration.
  1523. #if ( NO_COMPILER_NAMES )
  1524. if ( TE_isthunk ( typeCode ))
  1525. return DN_invalid;
  1526. if ( TE_isfunction ( typeCode ))
  1527. #else // } elif !NO_COMPILER_NAMES {
  1528. if ( TE_isfunction ( typeCode ) && !(( TE_isthunk ( typeCode ) && TE_islocaldtor ( typeCode )) ||
  1529. ( TE_isthunk ( typeCode ) && ( TE_istemplatector ( typeCode ) || TE_istemplatedtor ( typeCode )))))
  1530. #endif // !NO_COMPILER_NAMES
  1531. {
  1532. // If it is based, then compose the 'based' prefix for the name
  1533. if ( TE_isbased ( typeCode ))
  1534. if ( doMSKeywords () && doAllocationModel ())
  1535. declaration = ' ' + getBasedType ();
  1536. else
  1537. declaration |= getBasedType (); // Just lose the 'based-type'
  1538. #if ( !NO_COMPILER_NAMES )
  1539. // Check for some of the specially composed 'thunk's
  1540. if ( TE_isthunk ( typeCode ) && TE_isvcall ( typeCode ))
  1541. {
  1542. declaration += symbol + '{' + getCallIndex () + ',';
  1543. declaration += getVCallThunkType () + "}' ";
  1544. if ( doMSKeywords () && doAllocationLanguage ())
  1545. declaration = ' ' + getCallingConvention () + ' ' + declaration; // What calling convention ?
  1546. else
  1547. declaration |= getCallingConvention (); // Just lose the 'calling-convention'
  1548. } // End of IF then
  1549. else
  1550. #endif // !NO_COMPILER_NAMES
  1551. {
  1552. DName vtorDisp;
  1553. DName adjustment;
  1554. DName thisType;
  1555. #if ( !NO_COMPILER_NAMES )
  1556. if ( TE_isthunk ( typeCode ))
  1557. {
  1558. if ( TE_isvtoradj ( typeCode ))
  1559. vtorDisp = getDisplacement ();
  1560. adjustment = getDisplacement ();
  1561. } // End of IF else
  1562. #endif // !NO_COMPILER_NAMES
  1563. // Get the 'this-type' for non-static function members
  1564. if ( TE_ismember ( typeCode ) && !TE_isstatic ( typeCode ))
  1565. if ( doThisTypes ())
  1566. thisType = getThisType ();
  1567. else
  1568. thisType |= getThisType ();
  1569. if ( doMSKeywords ())
  1570. {
  1571. // Attach the calling convention
  1572. if ( doAllocationLanguage ())
  1573. declaration = getCallingConvention () + declaration; // What calling convention ?
  1574. else
  1575. declaration |= getCallingConvention (); // Just lose the 'calling-convention'
  1576. // Any model specifiers ?
  1577. #if !VERS_32BIT
  1578. if ( doAllocationModel ())
  1579. if ( TE_isnear ( typeCode ))
  1580. declaration = UScore ( TOK_nearSp ) + declaration;
  1581. elif ( TE_isfar ( typeCode ))
  1582. declaration = UScore ( TOK_farSp ) + declaration;
  1583. #endif
  1584. } // End of IF
  1585. else
  1586. declaration |= getCallingConvention (); // Just lose the 'calling-convention'
  1587. // Now put them all together
  1588. if ( !symbol.isEmpty ())
  1589. if ( !declaration.isEmpty () && !doNameOnly() ) // And the symbol name
  1590. declaration += ' ' + symbol;
  1591. else
  1592. declaration = symbol;
  1593. // Compose the return type, catching the UDC case
  1594. DName * pDeclarator = 0;
  1595. DName returnType;
  1596. if ( symIsUDC ) // Is the symbol a UDC operator ?
  1597. {
  1598. declaration += " " + getReturnType ();
  1599. if ( doNameOnly() )
  1600. return declaration;
  1601. }
  1602. else
  1603. {
  1604. pDeclarator = gnew DName;
  1605. returnType = getReturnType ( pDeclarator );
  1606. } // End of IF else
  1607. #if ( !NO_COMPILER_NAMES )
  1608. // Add the displacements for virtual function thunks
  1609. if ( TE_isthunk ( typeCode ))
  1610. {
  1611. if ( TE_isvtoradj ( typeCode ))
  1612. declaration += "`vtordisp{" + vtorDisp + ',';
  1613. else
  1614. declaration += "`adjustor{";
  1615. declaration += adjustment + "}' ";
  1616. } // End of IF
  1617. #endif // !NO_COMPILER_NAMES
  1618. // Add the function argument prototype
  1619. declaration += '(' + getArgumentTypes () + ')';
  1620. // If this is a non-static member function, append the 'this' modifiers
  1621. if ( TE_ismember ( typeCode ) && !TE_isstatic ( typeCode ))
  1622. declaration += thisType;
  1623. // Add the 'throw' signature
  1624. if ( doThrowTypes ())
  1625. declaration += getThrowTypes ();
  1626. else
  1627. declaration |= getThrowTypes (); // Just lose the 'throw-types'
  1628. // If it has a declarator, then insert it into the declaration,
  1629. // sensitive to the return type composition
  1630. if ( doFunctionReturns () && pDeclarator )
  1631. {
  1632. *pDeclarator = declaration;
  1633. declaration = returnType;
  1634. } // End of IF
  1635. } // End of IF else
  1636. } // End of IF then
  1637. else
  1638. {
  1639. declaration += symbol;
  1640. // Catch the special handling cases
  1641. #if ( !NO_COMPILER_NAMES )
  1642. if ( TE_isvftable ( typeCode ))
  1643. return getVfTableType ( declaration );
  1644. elif ( TE_isvbtable ( typeCode ))
  1645. return getVbTableType ( declaration );
  1646. elif ( TE_isguard ( typeCode ))
  1647. return ( declaration + '{' + getGuardNumber () + "}'" );
  1648. elif ( TE_isvdispmap ( typeCode ))
  1649. return getVdispMapType ( declaration );
  1650. elif ( TE_isthunk ( typeCode ) && TE_islocaldtor ( typeCode ))
  1651. declaration += "`local static destructor helper'";
  1652. elif ( TE_isthunk ( typeCode ) && TE_istemplatector ( typeCode ))
  1653. declaration += "`template static data member constructor helper'";
  1654. elif ( TE_isthunk ( typeCode ) && TE_istemplatedtor ( typeCode ))
  1655. declaration += "`template static data member destructor helper'";
  1656. elif ( TE_ismetaclass ( typeCode ))
  1657. //
  1658. // Meta-class information has its information in its operator id
  1659. //
  1660. return declaration;
  1661. #else // } elif NO_COMPILER_NAMES {
  1662. if ( TE_isvftable ( typeCode )
  1663. || TE_isvbtable ( typeCode )
  1664. || TE_isguard ( typeCode )
  1665. || TE_ismetaclass ( typeCode ))
  1666. return DN_invalid;
  1667. #endif // NO_COMPILER_NAMES
  1668. if ( TE_isthunk( typeCode ) && ( TE_istemplatector( typeCode ) || TE_istemplatedtor( typeCode ))) {
  1669. //
  1670. // Insert a space before the declaration
  1671. //
  1672. declaration = " " + declaration;
  1673. }
  1674. else {
  1675. // All others are decorated as data symbols
  1676. declaration = getExternalDataType ( declaration );
  1677. }
  1678. } // End of IF else
  1679. // Prepend the 'virtual' and 'static' attributes for members
  1680. if ( TE_ismember ( typeCode ))
  1681. {
  1682. if ( doMemberTypes ())
  1683. {
  1684. if ( TE_isstatic ( typeCode ))
  1685. declaration = "static " + declaration;
  1686. if ( TE_isvirtual ( typeCode ) || ( TE_isthunk ( typeCode ) && ( TE_isvtoradj ( typeCode ) || TE_isadjustor ( typeCode ))))
  1687. declaration = "virtual " + declaration;
  1688. } // End of IF
  1689. // Prepend the access specifiers
  1690. if ( doAccessSpecifiers ())
  1691. if ( TE_isprivate ( typeCode ))
  1692. declaration = "private: " + declaration;
  1693. elif ( TE_isprotected ( typeCode ))
  1694. declaration = "protected: " + declaration;
  1695. elif ( TE_ispublic ( typeCode ))
  1696. declaration = "public: " + declaration;
  1697. } // End of IF
  1698. #if ( !NO_COMPILER_NAMES )
  1699. // If it is a thunk, mark it appropriately
  1700. if ( TE_isthunk ( typeCode ))
  1701. declaration = "[thunk]:" + declaration;
  1702. #endif // !NO_COMPILER_NAMES
  1703. // Return the composed declaration
  1704. return declaration;
  1705. } // End of "UnDecorator" FUNCTION "composeDeclaration"
  1706. inline int UnDecorator::getTypeEncoding ( void )
  1707. {
  1708. unsigned int typeCode = 0u;
  1709. // Strip any leading '_' which indicates that it is based
  1710. if ( *gName == '_' )
  1711. {
  1712. TE_setisbased ( typeCode );
  1713. gName++;
  1714. } // End of IF
  1715. // Now handle the code proper :-
  1716. if (( *gName >= 'A' ) && ( *gName <= 'Z' )) // Is it some sort of function ?
  1717. {
  1718. int code = *gName++ - 'A';
  1719. // Now determine the function type
  1720. TE_setisfunction ( typeCode ); // All of them are functions ?
  1721. // Determine the calling model
  1722. if ( code & TE_far )
  1723. TE_setisfar ( typeCode );
  1724. else
  1725. TE_setisnear ( typeCode );
  1726. // Is it a member function or not ?
  1727. if ( code < TE_external )
  1728. {
  1729. // Record the fact that it is a member
  1730. TE_setismember ( typeCode );
  1731. // What access permissions does it have
  1732. switch ( code & TE_access )
  1733. {
  1734. case TE_private:
  1735. TE_setisprivate ( typeCode );
  1736. break;
  1737. case TE_protect:
  1738. TE_setisprotected ( typeCode );
  1739. break;
  1740. case TE_public:
  1741. TE_setispublic ( typeCode );
  1742. break;
  1743. default:
  1744. TE_setisbadtype ( typeCode );
  1745. return typeCode;
  1746. } // End of SWITCH
  1747. // What type of a member function is it ?
  1748. switch ( code & TE_adjustor )
  1749. {
  1750. case TE_adjustor:
  1751. TE_setisadjustor ( typeCode );
  1752. break;
  1753. case TE_virtual:
  1754. TE_setisvirtual ( typeCode );
  1755. break;
  1756. case TE_static:
  1757. TE_setisstatic ( typeCode );
  1758. break;
  1759. case TE_member:
  1760. break;
  1761. default:
  1762. TE_setisbadtype ( typeCode );
  1763. return typeCode;
  1764. } // End of SWITCH
  1765. } // End of IF
  1766. } // End of IF then
  1767. elif ( *gName == '$' ) // Extended set ? Special handling
  1768. {
  1769. // What type of symbol is it ?
  1770. switch ( *( ++gName ))
  1771. {
  1772. case SHF_localdtor: // A destructor helper for a local static ?
  1773. TE_setislocaldtor ( typeCode );
  1774. break;
  1775. case SHF_vcall: // A VCall-thunk ?
  1776. TE_setisvcall ( typeCode );
  1777. break;
  1778. case SHF_templateStaticDataMemberCtor: // A constructor helper for template static data members
  1779. TE_setistemplatector ( typeCode );
  1780. break;
  1781. case SHF_templateStaticDataMemberDtor: // A destructor helper for template static data members
  1782. TE_setistemplatedtor ( typeCode );
  1783. break;
  1784. case SHF_vdispmap:
  1785. TE_setvdispmap ( typeCode );
  1786. break;
  1787. case '$':
  1788. {
  1789. if ( * ( gName + 1 ) == SHF_AnyDLLImportMethod ) {
  1790. gName += 1;
  1791. }
  1792. switch ( *( ++gName )) {
  1793. case SHF_CPPManagedILFunction: // C++ managed-IL function
  1794. case SHF_CPPManagedNativeFunction: // C++ managed-native function
  1795. case SHF_CPPManagedILMain: // C++ managed-IL main
  1796. case SHF_CPPManagedNativeMain: // C++ managed-native main
  1797. case SHF_CPPManagedILDLLImportData: // C++ managed-IL DLL-import function
  1798. case SHF_CPPManagedNativeDLLImportData: // C++ managed-native DLL-import function
  1799. //
  1800. // Skip the encoding
  1801. //
  1802. gName += 1;
  1803. return getTypeEncoding();
  1804. case SHF_CManagedILFunction: // C (or extern "C") managed-IL function
  1805. case SHF_CManagedNativeFunction: // C (or extern "C") managed-native function
  1806. case SHF_CManagedILDLLImportData: // C (or extern "C") managed-IL DLL-import function
  1807. case SHF_CManagedNativeDLLImportData: // C (or extern "C") managed-native DLL-import function
  1808. //
  1809. // Skip the encoding
  1810. //
  1811. gName += 1;
  1812. //
  1813. // The next character should be the number of characters
  1814. // in the byte-count
  1815. //
  1816. if (( *gName >= '0' ) && ( *gName <= '9' )) {
  1817. //
  1818. // Skip the character count and the byte-count
  1819. // itself
  1820. //
  1821. gName += (( *gName - '0' ) + 1 );
  1822. return getTypeEncoding();
  1823. }
  1824. else {
  1825. TE_setisbadtype( typeCode );
  1826. }
  1827. break;
  1828. default:
  1829. break;
  1830. }
  1831. }
  1832. break;
  1833. case 0:
  1834. TE_setistruncated ( typeCode );
  1835. break;
  1836. case '0':
  1837. case '1':
  1838. case '2':
  1839. case '3':
  1840. case '4':
  1841. case '5': // Construction displacement adjustor thunks
  1842. {
  1843. int code = *gName - '0';
  1844. // Set up the principal type information
  1845. TE_setisfunction ( typeCode );
  1846. TE_setismember ( typeCode );
  1847. TE_setisvtoradj ( typeCode );
  1848. // Is it 'near' or 'far' ?
  1849. if ( code & TE_far )
  1850. TE_setisfar ( typeCode );
  1851. else
  1852. TE_setisnear ( typeCode );
  1853. // What type of access protection ?
  1854. switch ( code & TE_access_vadj )
  1855. {
  1856. case TE_private_vadj:
  1857. TE_setisprivate ( typeCode );
  1858. break;
  1859. case TE_protect_vadj:
  1860. TE_setisprotected ( typeCode );
  1861. break;
  1862. case TE_public_vadj:
  1863. TE_setispublic ( typeCode );
  1864. break;
  1865. default:
  1866. TE_setisbadtype ( typeCode );
  1867. return typeCode;
  1868. } // End of SWITCH
  1869. } // End of CASE '0,1,2,3,4,5'
  1870. break;
  1871. default:
  1872. TE_setisbadtype ( typeCode );
  1873. return typeCode;
  1874. } // End of SWITCH
  1875. // Advance past the code character
  1876. gName++;
  1877. } // End of ELIF then
  1878. elif (( *gName >= TE_static_d ) && ( *gName <= TE_metatype )) // Non function decorations ?
  1879. {
  1880. int code = *gName++;
  1881. TE_setisdata ( typeCode );
  1882. // What type of symbol is it ?
  1883. switch ( code )
  1884. {
  1885. case ( TE_static_d | TE_private_d ):
  1886. TE_setisstatic ( typeCode );
  1887. TE_setisprivate ( typeCode );
  1888. break;
  1889. case ( TE_static_d | TE_protect_d ):
  1890. TE_setisstatic ( typeCode );
  1891. TE_setisprotected ( typeCode );
  1892. break;
  1893. case ( TE_static_d | TE_public_d ):
  1894. TE_setisstatic ( typeCode );
  1895. TE_setispublic ( typeCode );
  1896. break;
  1897. case TE_global:
  1898. TE_setisglobal ( typeCode );
  1899. break;
  1900. case TE_guard:
  1901. TE_setisguard ( typeCode );
  1902. break;
  1903. case TE_local:
  1904. TE_setislocal ( typeCode );
  1905. break;
  1906. case TE_vftable:
  1907. TE_setisvftable ( typeCode );
  1908. break;
  1909. case TE_vbtable:
  1910. TE_setisvbtable ( typeCode );
  1911. break;
  1912. case TE_metatype:
  1913. TE_setismetaclass ( typeCode );
  1914. break;
  1915. default:
  1916. TE_setisbadtype ( typeCode );
  1917. return typeCode;
  1918. } // End of SWITCH
  1919. } // End of ELIF then
  1920. elif ( *gName == '9' ) {
  1921. gName++;
  1922. TE_setisCident ( typeCode );
  1923. }
  1924. elif ( *gName )
  1925. TE_setisbadtype ( typeCode );
  1926. else
  1927. TE_setistruncated ( typeCode );
  1928. // Return the composed type code
  1929. return typeCode;
  1930. } // End of "UnDecorator" FUNCTION "getTypeEncoding"
  1931. DName UnDecorator::getBasedType ( void )
  1932. {
  1933. DName basedDecl ( UScore ( TOK_basedLp ));
  1934. // What type of 'based' is it ?
  1935. if ( *gName )
  1936. {
  1937. switch ( *gName++ )
  1938. {
  1939. #if !VERS_32BIT
  1940. case BT_segname:
  1941. basedDecl += UScore ( TOK_segnameLpQ ) + getSegmentName () + "\")";
  1942. break;
  1943. case BT_segment:
  1944. basedDecl += DName ( "NYI:" ) + UScore ( TOK_segment );
  1945. break;
  1946. #endif
  1947. case BT_void:
  1948. basedDecl += "void";
  1949. break;
  1950. #if !VERS_32BIT
  1951. case BT_self:
  1952. basedDecl += UScore ( TOK_self );
  1953. break;
  1954. case BT_nearptr:
  1955. basedDecl += DName ( "NYI:" ) + UScore ( TOK_nearP );
  1956. break;
  1957. case BT_farptr:
  1958. basedDecl += DName ( "NYI:" ) + UScore ( TOK_farP );
  1959. break;
  1960. case BT_hugeptr:
  1961. basedDecl += DName ( "NYI:" ) + UScore ( TOK_hugeP );
  1962. break;
  1963. case BT_segaddr:
  1964. basedDecl += "NYI:<segment-address-of-variable>";
  1965. break;
  1966. #else
  1967. case BT_nearptr:
  1968. basedDecl += getScopedName();
  1969. break;
  1970. #endif
  1971. case BT_basedptr:
  1972. //
  1973. // Note: based pointer on based pointer is reserved
  1974. //
  1975. return DN_invalid;
  1976. } // End of SWITCH
  1977. } // End of IF else
  1978. else
  1979. basedDecl += DN_truncated;
  1980. // Close the based syntax
  1981. basedDecl += ") ";
  1982. // Return completed based declaration
  1983. return basedDecl;
  1984. } // End of "UnDecorator" FUNCTION "getBasedType"
  1985. DName UnDecorator::getScopedName ( void )
  1986. {
  1987. DName name;
  1988. // Get the beginning of the name
  1989. name = getZName ( true );
  1990. // Now the scope (if any)
  1991. if (( name.status () == DN_valid ) && *gName && ( *gName != '@' ))
  1992. name = getScope () + "::" + name;
  1993. // Skip the trailing '@'
  1994. if ( *gName == '@' )
  1995. gName++;
  1996. elif ( *gName )
  1997. name = DN_invalid;
  1998. elif ( name.isEmpty ())
  1999. name = DN_truncated;
  2000. else
  2001. name = DName ( DN_truncated ) + "::" + name;
  2002. // And return the complete name
  2003. return name;
  2004. } // End of "UnDecorator" FUNCTION "getECSUName"
  2005. inline DName UnDecorator::getECSUName ( void ) { return getScopedName(); }
  2006. inline DName UnDecorator::getEnumType ( void )
  2007. {
  2008. DName ecsuName;
  2009. if ( *gName )
  2010. {
  2011. // What type of an 'enum' is it ?
  2012. switch ( *gName )
  2013. {
  2014. case ET_schar:
  2015. case ET_uchar:
  2016. ecsuName = "char ";
  2017. break;
  2018. case ET_sshort:
  2019. case ET_ushort:
  2020. ecsuName = "short ";
  2021. break;
  2022. case ET_sint:
  2023. break;
  2024. case ET_uint:
  2025. ecsuName = "int ";
  2026. break;
  2027. case ET_slong:
  2028. case ET_ulong:
  2029. ecsuName = "long ";
  2030. break;
  2031. default:
  2032. return DN_invalid;
  2033. } // End of SWITCH
  2034. // Add the 'unsigned'ness if appropriate
  2035. switch ( *gName++ )
  2036. {
  2037. case ET_uchar:
  2038. case ET_ushort:
  2039. case ET_uint:
  2040. case ET_ulong:
  2041. ecsuName = "unsigned " + ecsuName;
  2042. break;
  2043. } // End of SWITCH
  2044. // Now return the composed name
  2045. return ecsuName;
  2046. } // End of IF then
  2047. else
  2048. return DN_truncated;
  2049. } // End of "UnDecorator" FUNCTION "getEnumType"
  2050. DName UnDecorator::getCallingConvention ( void )
  2051. {
  2052. if ( *gName )
  2053. {
  2054. unsigned int callCode = ((unsigned int)*gName++ ) - 'A';
  2055. // What is the primary calling convention
  2056. DASSERT(CC_cdecl == 0);
  2057. #if CC_COR
  2058. if (/*( callCode >= CC_cdecl ) &&*/( callCode <= CC_cocall ))
  2059. #else // CC_COR
  2060. if (/*( callCode >= CC_cdecl ) &&*/( callCode <= CC_interrupt ))
  2061. #endif // CC_COR
  2062. {
  2063. DName callType;
  2064. // Now, what type of 'calling-convention' is it, 'interrupt' is special ?
  2065. if ( doMSKeywords ())
  2066. #if !VERS_32BIT
  2067. if ( callCode == CC_interrupt )
  2068. callType = UScore ( TOK_interrupt );
  2069. else
  2070. #endif
  2071. {
  2072. switch ( callCode & ~CC_saveregs )
  2073. {
  2074. case CC_cdecl:
  2075. callType = UScore ( TOK_cdecl );
  2076. break;
  2077. case CC_pascal:
  2078. callType = UScore ( TOK_pascal );
  2079. break;
  2080. case CC_thiscall:
  2081. callType = UScore ( TOK_thiscall );
  2082. break;
  2083. case CC_stdcall:
  2084. callType = UScore ( TOK_stdcall );
  2085. break;
  2086. case CC_fastcall:
  2087. callType = UScore ( TOK_fastcall );
  2088. break;
  2089. case CC_cocall:
  2090. callType = UScore ( TOK_cocall );
  2091. break;
  2092. } // End of SWITCH
  2093. // Has it also got 'saveregs' marked ?
  2094. #if !VERS_32BIT
  2095. if ( callCode & CC_saveregs )
  2096. callType += ' ' + UScore ( TOK_saveregs );
  2097. #endif
  2098. } // End of IF else
  2099. // And return
  2100. return callType;
  2101. } // End of IF then
  2102. else
  2103. return DN_invalid;
  2104. } // End of IF then
  2105. else
  2106. return DN_truncated;
  2107. } // End of "UnDecorator" FUNCTION "getCallingConvention"
  2108. DName UnDecorator::getReturnType ( DName * pDeclarator )
  2109. {
  2110. if ( *gName == '@' ) // Return type for constructors and destructors ?
  2111. {
  2112. gName++;
  2113. return DName ( pDeclarator );
  2114. } // End of IF then
  2115. else
  2116. return getDataType ( pDeclarator );
  2117. } // End of "UnDecorator" FUNCTION "getReturnType"
  2118. DName UnDecorator::getDataType ( DName * pDeclarator )
  2119. {
  2120. DName superType ( pDeclarator );
  2121. // What type is it ?
  2122. switch ( *gName )
  2123. {
  2124. case 0:
  2125. return ( DN_truncated + superType );
  2126. case DT_void:
  2127. gName++;
  2128. if ( superType.isEmpty ())
  2129. return "void";
  2130. else
  2131. return "void " + superType;
  2132. case '?':
  2133. {
  2134. gName++; // Skip the '?'
  2135. superType = getDataIndirectType ( superType, 0, DName (), 0);
  2136. return getPrimaryDataType ( superType );
  2137. return superType;
  2138. } // End of CASE '?'
  2139. default:
  2140. return getPrimaryDataType ( superType );
  2141. } // End of SWITCH
  2142. } // End of "UnDecorator" FUNCTION "getDataType"
  2143. DName UnDecorator::getPrimaryDataType ( const DName & superType )
  2144. {
  2145. DName cvType;
  2146. switch ( *gName )
  2147. {
  2148. case 0:
  2149. return ( DN_truncated + superType );
  2150. case PDT_volatileReference:
  2151. cvType = "volatile";
  2152. if ( !superType.isEmpty ())
  2153. cvType += ' ';
  2154. // No break
  2155. case PDT_reference:
  2156. {
  2157. DName superName ( superType );
  2158. gName++;
  2159. return getReferenceType ( cvType, superName.setPtrRef ());
  2160. } // End of CASE 'PDT_reference'
  2161. case PDT_extend:
  2162. {
  2163. //
  2164. // Extended Primary Data Type (items overlooked in original design):
  2165. // prefixed by '$$'.
  2166. //
  2167. if ( gName[1] != PDT_extend )
  2168. if ( gName[1] == '\0' )
  2169. return DN_truncated + superType;
  2170. else
  2171. return DN_invalid;
  2172. gName += 2;
  2173. switch ( *gName )
  2174. {
  2175. case PDT_ex_function:
  2176. gName++;
  2177. return getFunctionIndirectType( superType );
  2178. case PDT_ex_other:
  2179. gName++;
  2180. return getPtrRefDataType( superType, /* isPtr = */ TRUE );
  2181. case PDT_ex_qualified:
  2182. gName++;
  2183. return(getBasicDataType(getDataIndirectType ( superType, 0, DName (), 0)));
  2184. case 0:
  2185. return ( DN_truncated + superType );
  2186. default:
  2187. return DN_invalid;
  2188. }
  2189. }
  2190. default:
  2191. return getBasicDataType ( superType );
  2192. } // End of SWITCH
  2193. } // End of "UnDecorator" FUNCTION "getPrimaryDataType"
  2194. DName UnDecorator::getArgumentTypes ( void )
  2195. {
  2196. switch ( *gName )
  2197. {
  2198. case AT_ellipsis:
  2199. return ( gName++, "..." );
  2200. case AT_void:
  2201. return ( gName++, "void" );
  2202. default:
  2203. {
  2204. DName arguments ( getArgumentList ());
  2205. // Now, is it a varargs function or not ?
  2206. if ( arguments.status () == DN_valid )
  2207. switch ( *gName )
  2208. {
  2209. case 0:
  2210. return arguments;
  2211. case AT_ellipsis:
  2212. return ( gName++, arguments + ",..." );
  2213. case AT_endoflist:
  2214. return ( gName++, arguments );
  2215. default:
  2216. return DN_invalid;
  2217. } // End of SWITCH
  2218. else
  2219. return arguments;
  2220. } // End of DEFAULT
  2221. } // End of SWITCH
  2222. } // End of "UnDecorator" FUNCTION "getArgumentTypes"
  2223. DName UnDecorator::getArgumentList ( void )
  2224. {
  2225. int first = TRUE;
  2226. DName aList;
  2227. while (( aList.status () == DN_valid ) && ( *gName != AT_endoflist ) && ( *gName != AT_ellipsis ))
  2228. {
  2229. // Insert the argument list separator if not the first argument
  2230. if ( first )
  2231. first = FALSE;
  2232. else
  2233. aList += ',';
  2234. // Get the individual argument type
  2235. if ( *gName )
  2236. {
  2237. int argIndex = *gName - '0';
  2238. // Handle 'argument-replicators', otherwise a new argument type
  2239. if (( argIndex >= 0 ) && ( argIndex <= 9 ))
  2240. {
  2241. gName++; // Skip past the replicator
  2242. // Append to the argument list
  2243. aList += ( *pArgList )[ argIndex ];
  2244. } // End of IF then
  2245. else
  2246. {
  2247. pcchar_t oldGName = gName;
  2248. // Extract the 'argument' type
  2249. DName arg ( getPrimaryDataType ( DName ()));
  2250. // Add it to the current list of 'argument's, if it is bigger than a one byte encoding
  2251. if ((( gName - oldGName ) > 1 ) && !pArgList->isFull ())
  2252. *pArgList += arg;
  2253. // Append to the argument list
  2254. aList += arg;
  2255. } // End of IF else
  2256. } // End of IF then
  2257. else
  2258. {
  2259. aList += DN_truncated;
  2260. break;
  2261. } // End of IF else
  2262. } // End of WHILE
  2263. // Return the completed argument list
  2264. return aList;
  2265. } // End of "UnDecorator" FUNCTION "getArgumentList"
  2266. DName UnDecorator::getThrowTypes ( void )
  2267. {
  2268. if ( *gName )
  2269. if ( *gName == AT_ellipsis ) // Handle ellipsis here to suppress the 'throw' signature
  2270. return ( gName++, DName ());
  2271. else
  2272. return ( " throw(" + getArgumentTypes () + ')' );
  2273. else
  2274. return ( DName ( " throw(" ) + DN_truncated + ')' );
  2275. } // End of "UnDecorator" FUNCTION "getThrowTypes"
  2276. DName UnDecorator::getBasicDataType ( const DName & superType )
  2277. {
  2278. if ( *gName )
  2279. {
  2280. unsigned char bdtCode = *gName++;
  2281. unsigned char extended_bdtCode;
  2282. int pCvCode = -1;
  2283. DName basicDataType;
  2284. // Extract the principal type information itself, and validate the codes
  2285. switch ( bdtCode )
  2286. {
  2287. case BDT_schar:
  2288. case BDT_char:
  2289. case ( BDT_char | BDT_unsigned ):
  2290. basicDataType = "char";
  2291. break;
  2292. case BDT_short:
  2293. case ( BDT_short | BDT_unsigned ):
  2294. basicDataType = "short";
  2295. break;
  2296. case BDT_int:
  2297. case ( BDT_int | BDT_unsigned ):
  2298. basicDataType = "int";
  2299. break;
  2300. case BDT_long:
  2301. case ( BDT_long | BDT_unsigned ):
  2302. basicDataType = "long";
  2303. break;
  2304. #if !VERS_32BIT
  2305. case BDT_segment:
  2306. basicDataType = UScore ( TOK_segment );
  2307. break;
  2308. #endif
  2309. case BDT_float:
  2310. basicDataType = "float";
  2311. break;
  2312. case BDT_longdouble:
  2313. basicDataType = "long ";
  2314. // No break
  2315. case BDT_double:
  2316. basicDataType += "double";
  2317. break;
  2318. case BDT_pointer:
  2319. case ( BDT_pointer | BDT_const ):
  2320. case ( BDT_pointer | BDT_volatile ):
  2321. case ( BDT_pointer | BDT_const | BDT_volatile ):
  2322. pCvCode = ( bdtCode & ( BDT_const | BDT_volatile ));
  2323. break;
  2324. case BDT_extend:
  2325. switch(extended_bdtCode = *gName++) {
  2326. case BDT_array:
  2327. pCvCode = -2;
  2328. break;
  2329. case BDT_bool:
  2330. basicDataType = "bool";
  2331. break;
  2332. case BDT_int8:
  2333. case ( BDT_int8 | BDT_unsigned ):
  2334. basicDataType = "__int8";
  2335. break;
  2336. case BDT_int16:
  2337. case ( BDT_int16 | BDT_unsigned ):
  2338. basicDataType = "__int16";
  2339. break;
  2340. case BDT_int32:
  2341. case ( BDT_int32 | BDT_unsigned ):
  2342. basicDataType = "__int32";
  2343. break;
  2344. case BDT_int64:
  2345. case ( BDT_int64 | BDT_unsigned ):
  2346. basicDataType = "__int64";
  2347. break;
  2348. case BDT_int128:
  2349. case ( BDT_int128 | BDT_unsigned ):
  2350. basicDataType = "__int128";
  2351. break;
  2352. case BDT_wchar_t:
  2353. basicDataType = "wchar_t";
  2354. break;
  2355. #if CC_COR
  2356. case BDT_coclass:
  2357. case BDT_cointerface:
  2358. {
  2359. gName--; // Backup, since 'ecsu-data-type' does it's own decoding
  2360. basicDataType = getECSUDataType();
  2361. if ( basicDataType.isEmpty()) {
  2362. return basicDataType;
  2363. }
  2364. }
  2365. break;
  2366. #endif // CC_COR
  2367. case '$':
  2368. return "__w64 " + getBasicDataType (superType);
  2369. default:
  2370. basicDataType = "UNKNOWN";
  2371. break;
  2372. }
  2373. break;
  2374. default:
  2375. gName--; // Backup, since 'ecsu-data-type' does it's own decoding
  2376. basicDataType = getECSUDataType ();
  2377. if ( basicDataType.isEmpty ())
  2378. return basicDataType;
  2379. break;
  2380. } // End of SWITCH
  2381. // What type of basic data type composition is involved ?
  2382. if ( pCvCode == -1 ) // Simple ?
  2383. {
  2384. // Determine the 'signed/unsigned'ness
  2385. switch ( bdtCode )
  2386. {
  2387. case ( BDT_char | BDT_unsigned ):
  2388. case ( BDT_short | BDT_unsigned ):
  2389. case ( BDT_int | BDT_unsigned ):
  2390. case ( BDT_long | BDT_unsigned ):
  2391. basicDataType = "unsigned " + basicDataType;
  2392. break;
  2393. case BDT_schar:
  2394. basicDataType = "signed " + basicDataType;
  2395. break;
  2396. case BDT_extend:
  2397. switch ( extended_bdtCode )
  2398. {
  2399. case ( BDT_int8 | BDT_unsigned ):
  2400. case ( BDT_int16 | BDT_unsigned ):
  2401. case ( BDT_int32 | BDT_unsigned ):
  2402. case ( BDT_int64 | BDT_unsigned ):
  2403. case ( BDT_int128 | BDT_unsigned ):
  2404. basicDataType = "unsigned " + basicDataType;
  2405. break;
  2406. } // End of SWITCH
  2407. break;
  2408. } // End of SWITCH
  2409. // Add the indirection type to the type
  2410. if ( !superType.isEmpty () )
  2411. basicDataType += ' ' + superType;
  2412. // And return the completed type
  2413. return basicDataType;
  2414. } // End of IF then
  2415. else
  2416. {
  2417. DName cvType;
  2418. DName superName ( superType );
  2419. if ( pCvCode == -2 )
  2420. {
  2421. superName.setIsArray();
  2422. DName arType = getPointerTypeArray ( cvType, superName );
  2423. // if we didn't get back an array, append.
  2424. // A multidimensional array sticks the braces in before the
  2425. // other dimensions at sets isArray on it's return type.
  2426. if (!arType.isArray()) {
  2427. arType += "[]";
  2428. }
  2429. return arType;
  2430. }
  2431. // Is it 'const/volatile' qualified ?
  2432. if ( superType . isEmpty() )
  2433. {
  2434. //
  2435. // const/volatile are redundantly encoded, except at the start
  2436. // of a "type only" context. In such a context, the super-type
  2437. // is empty.
  2438. //
  2439. if ( pCvCode & BDT_const )
  2440. {
  2441. cvType = "const";
  2442. if ( pCvCode & BDT_volatile )
  2443. cvType += " volatile";
  2444. } // End of IF then
  2445. elif ( pCvCode & BDT_volatile )
  2446. cvType = "volatile";
  2447. } // End of IF then
  2448. // Construct the appropriate pointer type declaration
  2449. return getPointerType ( cvType, superName );
  2450. } // End of IF else
  2451. } // End of IF then
  2452. else
  2453. return ( DN_truncated + superType );
  2454. } // End of "UnDecorator" FUNCTION "getBasicDataType"
  2455. DName UnDecorator::getECSUDataType ( void )
  2456. {
  2457. // Extract the principal type information itself, and validate the codes
  2458. int fPrefix = doEcsu() && !doNameOnly();
  2459. DName Prefix;
  2460. switch ( *gName++ )
  2461. {
  2462. case 0:
  2463. gName--; // Backup to permit later error recovery to work safely
  2464. return "`unknown ecsu'" + DN_truncated;
  2465. case BDT_union:
  2466. Prefix = "union ";
  2467. break;
  2468. case BDT_struct:
  2469. Prefix = "struct ";
  2470. break;
  2471. case BDT_class:
  2472. Prefix = "class ";
  2473. break;
  2474. #if CC_COR
  2475. case BDT_coclass:
  2476. Prefix = "coclass ";
  2477. break;
  2478. case BDT_cointerface:
  2479. Prefix = "cointerface ";
  2480. break;
  2481. #endif // CC_COR
  2482. case BDT_enum:
  2483. fPrefix = doEcsu();
  2484. Prefix = "enum " + getEnumType ();
  2485. break;
  2486. // default:
  2487. // return DN_invalid;
  2488. } // End of SWITCH
  2489. DName ecsuDataType;
  2490. if ( fPrefix )
  2491. ecsuDataType = Prefix;
  2492. // Get the 'class/struct/union' name
  2493. ecsuDataType += getECSUName ();
  2494. // And return the formed 'ecsu-data-type'
  2495. return ecsuDataType;
  2496. } // End of "UnDecorator" FUNCTION "getECSUDataType"
  2497. //
  2498. // Undecorator::getFunctionIndirectType
  2499. //
  2500. // Note: this function gets both the function-indirect-type and the function-type.
  2501. //
  2502. DName UnDecorator::getFunctionIndirectType( const DName & superType )
  2503. {
  2504. if ( ! *gName )
  2505. return DN_truncated + superType;
  2506. if ( ! IT_isfunction( *gName ))
  2507. return DN_invalid;
  2508. int fitCode = *gName++ - '6';
  2509. if ( fitCode == ( '_' - '6' ))
  2510. {
  2511. if ( *gName )
  2512. {
  2513. fitCode = *gName++ - 'A' + FIT_based;
  2514. if (( fitCode < FIT_based ) || ( fitCode > ( FIT_based | FIT_far | FIT_member )))
  2515. fitCode = -1;
  2516. } // End of IF then
  2517. else
  2518. return ( DN_truncated + superType );
  2519. } // End of IF then
  2520. elif (( fitCode < FIT_near ) || ( fitCode > ( FIT_far | FIT_member )))
  2521. fitCode = -1;
  2522. // Return if invalid name
  2523. if ( fitCode == -1 )
  2524. return DN_invalid;
  2525. // Otherwise, what are the function indirect attributes
  2526. DName thisType;
  2527. DName fitType = superType;
  2528. // Is it a pointer to member function ?
  2529. if ( fitCode & FIT_member )
  2530. {
  2531. fitType = "::" + fitType;
  2532. if ( *gName )
  2533. fitType = ' ' + getScope () + fitType;
  2534. else
  2535. fitType = DN_truncated + fitType;
  2536. if ( *gName )
  2537. if ( *gName == '@' )
  2538. gName++;
  2539. else
  2540. return DN_invalid;
  2541. else
  2542. return ( DN_truncated + fitType );
  2543. if ( doThisTypes ())
  2544. thisType = getThisType ();
  2545. else
  2546. thisType |= getThisType ();
  2547. } // End of IF
  2548. // Is it a based allocated function ?
  2549. if ( fitCode & FIT_based )
  2550. if ( doMSKeywords ())
  2551. fitType = ' ' + getBasedType () + fitType;
  2552. else
  2553. fitType |= getBasedType (); // Just lose the 'based-type'
  2554. // Get the 'calling-convention'
  2555. if ( doMSKeywords ())
  2556. {
  2557. fitType = getCallingConvention () + fitType;
  2558. // Is it a near or far function pointer
  2559. #if !VERS_32BIT
  2560. fitType = UScore ((( fitCode & FIT_far ) ? TOK_farSp : TOK_nearSp )) + fitType;
  2561. #endif
  2562. } // End of IF then
  2563. else
  2564. fitType |= getCallingConvention (); // Just lose the 'calling-convention'
  2565. // Parenthesise the indirection component, and work on the rest
  2566. if ( ! superType . isEmpty() ) {
  2567. fitType = '(' + fitType + ')';
  2568. }
  2569. // Get the rest of the 'function-type' pieces
  2570. DName * pDeclarator = gnew DName;
  2571. DName returnType ( getReturnType ( pDeclarator ));
  2572. fitType += '(' + getArgumentTypes () + ')';
  2573. if ( doThisTypes () && ( fitCode & FIT_member ))
  2574. fitType += thisType;
  2575. if ( doThrowTypes ())
  2576. fitType += getThrowTypes ();
  2577. else
  2578. fitType |= getThrowTypes (); // Just lose the 'throw-types'
  2579. // Now insert the indirected declarator, catch the allocation failure here
  2580. if ( pDeclarator )
  2581. *pDeclarator = fitType;
  2582. else
  2583. return DN_error;
  2584. // And return the composed function type (now in 'returnType' )
  2585. return returnType;
  2586. }
  2587. DName UnDecorator::getPtrRefType ( const DName & cvType, const DName & superType, char ptrChar )
  2588. {
  2589. // Doubles up as 'pointer-type' and 'reference-type'
  2590. if ( *gName )
  2591. if ( IT_isfunction ( *gName )) // Is it a function or data indirection ?
  2592. {
  2593. DName fitType = ptrChar;
  2594. if ( !cvType.isEmpty () && ( superType.isEmpty () || !superType.isPtrRef ()))
  2595. fitType += cvType;
  2596. if ( !superType.isEmpty ())
  2597. fitType += superType;
  2598. return getFunctionIndirectType( fitType );
  2599. } // End of IF then
  2600. else
  2601. {
  2602. // Otherwise, it is either a pointer or a reference to some data type
  2603. DName innerType ( getDataIndirectType ( superType, ptrChar, cvType ));
  2604. return getPtrRefDataType ( innerType, ptrChar == '*' );
  2605. } // End of IF else
  2606. else
  2607. {
  2608. DName trunk ( DN_truncated );
  2609. trunk += ptrChar;
  2610. if ( !cvType.isEmpty ())
  2611. trunk += cvType;
  2612. if ( !superType.isEmpty ())
  2613. {
  2614. if ( !cvType.isEmpty ())
  2615. trunk += ' ';
  2616. trunk += superType;
  2617. } // End of IF
  2618. return trunk;
  2619. } // End of IF else
  2620. } // End of "UnDecorator" FUNCTION "getPtrRefType"
  2621. DName UnDecorator::getDataIndirectType ( const DName & superType, char prType, const DName & cvType, int thisFlag )
  2622. {
  2623. DName szComPlusIndirSpecifier;
  2624. if ( *gName )
  2625. {
  2626. if( gName[0] == '$' )
  2627. {
  2628. gName++; // swallow up the dollar
  2629. switch( *gName )
  2630. {
  2631. case PDT_GCPointer:
  2632. szComPlusIndirSpecifier = "__gc ";
  2633. gName++;
  2634. break;
  2635. case PDT_PinnedPointer:
  2636. szComPlusIndirSpecifier = "__pin ";
  2637. gName++;
  2638. break;
  2639. default:
  2640. unsigned int nRank = ((gName[0]-'0') << 4) + (gName[1]-'0');
  2641. gName += 2;
  2642. DASSERT( nRank < 256 );
  2643. szComPlusIndirSpecifier = "__gc[";
  2644. for( unsigned int i=1; i<nRank; i++ )
  2645. {
  2646. szComPlusIndirSpecifier = szComPlusIndirSpecifier + ",";
  2647. }
  2648. szComPlusIndirSpecifier = szComPlusIndirSpecifier + "] ";
  2649. if ( !superType.isEmpty () )
  2650. if ( superType.isArray() )
  2651. szComPlusIndirSpecifier = superType + szComPlusIndirSpecifier;
  2652. else
  2653. szComPlusIndirSpecifier = '(' + superType + ')' + szComPlusIndirSpecifier;
  2654. gName++;
  2655. return szComPlusIndirSpecifier;
  2656. }
  2657. }
  2658. unsigned int ditCode = ( *gName - (( *gName >= 'A' ) ? (unsigned int)'A': (unsigned int)( '0' - 26 )));
  2659. DName msExtension;
  2660. DName msExtensionPre;
  2661. int fContinue = TRUE;
  2662. do
  2663. {
  2664. switch ( ditCode )
  2665. {
  2666. case DIT_ptr64:
  2667. if ( doMSKeywords () && doPtr64() ) {
  2668. if ( !msExtension.isEmpty())
  2669. msExtension = msExtension + ' ' + UScore( TOK_ptr64 );
  2670. else
  2671. msExtension = UScore( TOK_ptr64 );
  2672. }
  2673. gName++;
  2674. ditCode = ( *gName - (( *gName >= 'A' ) ? (unsigned int)'A': (unsigned int)( '0' - 26 )));
  2675. break;
  2676. case DIT_unaligned:
  2677. if ( doMSKeywords ()) {
  2678. if ( !msExtensionPre.isEmpty())
  2679. msExtensionPre = msExtensionPre + ' ' + UScore( TOK_unaligned );
  2680. else
  2681. msExtensionPre = UScore( TOK_unaligned );
  2682. }
  2683. gName++;
  2684. ditCode = ( *gName - (( *gName >= 'A' ) ? (unsigned int)'A': (unsigned int)( '0' - 26 )));
  2685. break;
  2686. case DIT_restrict:
  2687. if ( doMSKeywords ()) {
  2688. if ( !msExtension.isEmpty())
  2689. msExtension = msExtension + ' ' + UScore( TOK_restrict );
  2690. else
  2691. msExtension = UScore( TOK_restrict );
  2692. }
  2693. gName++;
  2694. ditCode = ( *gName - (( *gName >= 'A' ) ? (unsigned int)'A': (unsigned int)( '0' - 26 )));
  2695. break;
  2696. default:
  2697. fContinue = FALSE;
  2698. break;
  2699. }
  2700. } while (fContinue);
  2701. gName++; // Skip to next character in name
  2702. // Is it a valid 'data-indirection-type' ?
  2703. DASSERT(DIT_near == 0);
  2704. if (( ditCode <= ( DIT_const | DIT_volatile | DIT_modelmask | DIT_member )))
  2705. {
  2706. DName ditType ( prType );
  2707. ditType = szComPlusIndirSpecifier + ditType;
  2708. if ( !msExtension.isEmpty())
  2709. ditType = ditType + ' ' + msExtension;
  2710. if ( !msExtensionPre.isEmpty())
  2711. ditType = msExtensionPre + ' ' + ditType;
  2712. // If it is a member, then these attributes immediately precede the indirection token
  2713. if ( ditCode & DIT_member )
  2714. {
  2715. // If it is really 'this-type', then it cannot be any form of pointer to member
  2716. if ( thisFlag )
  2717. return DN_invalid;
  2718. // Otherwise, extract the scope for the PM
  2719. if ( prType != '\0' )
  2720. {
  2721. ditType = "::" + ditType;
  2722. if ( *gName )
  2723. ditType = getScope () + ditType;
  2724. else
  2725. ditType = DN_truncated + ditType;
  2726. }
  2727. elif ( *gName )
  2728. {
  2729. //
  2730. // The scope is ignored for special uses of data-indirect-type, such
  2731. // as storage-convention. I think it's a bug that we ever mark things
  2732. // with Member storage convention, as that is already covered in the
  2733. // scope of the name. However, we don't want to change the dname scheme,
  2734. // so we're stuck with it.
  2735. //
  2736. ditType |= getScope ();
  2737. }
  2738. // Now skip the scope terminator
  2739. if ( !*gName )
  2740. ditType += DN_truncated;
  2741. elif ( *gName++ != '@' )
  2742. return DN_invalid;
  2743. } // End of IF
  2744. // Add the 'model' attributes (prefixed) as appropriate
  2745. if ( doMSKeywords ()) {
  2746. switch ( ditCode & DIT_modelmask )
  2747. {
  2748. #if !VERS_32BIT
  2749. case DIT_near:
  2750. if ( do32BitNear ())
  2751. ditType = UScore ( TOK_near ) + ditType;
  2752. break;
  2753. case DIT_far:
  2754. ditType = UScore ( TOK_far ) + ditType;
  2755. break;
  2756. case DIT_huge:
  2757. ditType = UScore ( TOK_huge ) + ditType;
  2758. break;
  2759. #endif
  2760. case DIT_based:
  2761. // The 'this-type' can never be 'based'
  2762. if ( thisFlag )
  2763. return DN_invalid;
  2764. ditType = getBasedType () + ditType;
  2765. break;
  2766. } // End of SWITCH
  2767. } // End of IF
  2768. elif (( ditCode & DIT_modelmask ) == DIT_based )
  2769. ditType |= getBasedType (); // Just lose the 'based-type'
  2770. // Handle the 'const' and 'volatile' attributes
  2771. if ( ditCode & DIT_volatile )
  2772. ditType = "volatile " + ditType;
  2773. if ( ditCode & DIT_const )
  2774. ditType = "const " + ditType;
  2775. // Append the supertype, if not 'this-type'
  2776. if ( !thisFlag )
  2777. if ( !superType.isEmpty ())
  2778. {
  2779. // Is the super context included 'cv' information, ensure that it is added appropriately
  2780. if ( superType.isPtrRef () || cvType.isEmpty ())
  2781. if (superType.isArray())
  2782. ditType = superType; // array type, skip space
  2783. else
  2784. ditType += ' ' + superType;
  2785. else
  2786. ditType += ' ' + cvType + ' ' + superType;
  2787. } // End of IF then
  2788. elif ( !cvType.isEmpty ())
  2789. ditType += ' ' + cvType;
  2790. // Make sure qualifiers aren't re-applied
  2791. ditType.setPtrRef ();
  2792. // Finally, return the composed 'data-indirection-type' (with embedded sub-type)
  2793. return ditType;
  2794. } // End of IF then
  2795. else
  2796. return DN_invalid;
  2797. } // End of IF then
  2798. elif ( !thisFlag && !superType.isEmpty ())
  2799. {
  2800. // Is the super context included 'cv' information, ensure that it is added appropriately
  2801. if ( superType.isPtrRef () || cvType.isEmpty ())
  2802. return ( DN_truncated + superType );
  2803. else
  2804. return ( DN_truncated + cvType + ' ' + superType );
  2805. } // End of ELIF then
  2806. elif ( !thisFlag && !cvType.isEmpty ())
  2807. return ( DN_truncated + cvType );
  2808. else
  2809. return DN_truncated;
  2810. } // End of "UnDecorator" FUNCTION "getDataIndirectType"
  2811. inline DName UnDecorator::getPtrRefDataType ( const DName & superType, int isPtr )
  2812. {
  2813. // Doubles up as 'pointer-data-type' and 'reference-data-type'
  2814. if ( *gName )
  2815. {
  2816. // Is this a 'pointer-data-type' ?
  2817. if ( isPtr && ( *gName == PoDT_void ))
  2818. {
  2819. gName++; // Skip this character
  2820. if ( superType.isEmpty ())
  2821. return "void";
  2822. else
  2823. return "void " + superType;
  2824. } // End of IF
  2825. // Otherwise it may be a 'reference-data-type'
  2826. if ( *gName == RDT_array ) // An array ?
  2827. {
  2828. gName++;
  2829. return getArrayType( superType );
  2830. } // End of IF
  2831. // Otherwise, it is a 'basic-data-type'
  2832. if ( *gName == '_' && gName[1] == 'Z' ) // A boxed type ?
  2833. {
  2834. gName += 2;
  2835. return "__box " + getBasicDataType ( superType );
  2836. }
  2837. return getBasicDataType ( superType );
  2838. } // End of IF then
  2839. else
  2840. return ( DN_truncated + superType );
  2841. } // End of "UnDecorator" FUNCTION "getPtrRefDataType"
  2842. inline DName UnDecorator::getArrayType ( const DName & superType )
  2843. {
  2844. if ( *gName )
  2845. {
  2846. int noDimensions = getNumberOfDimensions ();
  2847. if ( noDimensions < 0 )
  2848. noDimensions = 0;
  2849. if ( !noDimensions )
  2850. return getBasicDataType ( DName ( '[' ) + DN_truncated + ']' );
  2851. else
  2852. {
  2853. DName arrayType;
  2854. if ( superType.isArray() ) {
  2855. arrayType += "[]";
  2856. }
  2857. while ( noDimensions-- )
  2858. arrayType += '[' + getDimension () + ']';
  2859. // If it is indirect, then parenthesise the 'super-type'
  2860. if ( !superType.isEmpty () )
  2861. if ( superType.isArray() )
  2862. arrayType = superType + arrayType;
  2863. else
  2864. arrayType = '(' + superType + ')' + arrayType;
  2865. // Return the finished array dimension information
  2866. DName newType = getPrimaryDataType ( arrayType );
  2867. newType.setIsArray();
  2868. return newType;
  2869. } // End of IF else
  2870. } // End of IF
  2871. elif ( !superType.isEmpty ())
  2872. return getBasicDataType ( '(' + superType + ")[" + DN_truncated + ']' );
  2873. else
  2874. return getBasicDataType ( DName ( '[' ) + DN_truncated + ']' );
  2875. } // End of "UnDecorator" FUNCTION "getArrayType"
  2876. inline DName UnDecorator::getLexicalFrame ( void ) { return '`' + getDimension () + '\''; }
  2877. inline DName UnDecorator::getStorageConvention ( void ) { return getDataIndirectType (); }
  2878. inline DName UnDecorator::getDataIndirectType () { return getDataIndirectType ( DName (), 0, DName ()); }
  2879. inline DName UnDecorator::getThisType ( void ) { return getDataIndirectType ( DName (), 0, DName (), TRUE ); }
  2880. inline DName UnDecorator::getPointerType ( const DName & cv, const DName & name )
  2881. { return getPtrRefType ( cv, name, '*' ); }
  2882. inline DName UnDecorator::getPointerTypeArray ( const DName & cv, const DName & name )
  2883. { return getPtrRefType ( cv, name, '\0' ); }
  2884. inline DName UnDecorator::getReferenceType ( const DName & cv, const DName & name )
  2885. { return getPtrRefType ( cv, name, '&' ); }
  2886. inline DName UnDecorator::getSegmentName ( void ) { return getZName ( true ); }
  2887. #if ( !NO_COMPILER_NAMES )
  2888. inline DName UnDecorator::getDisplacement ( void ) { return getDimension ( true ); }
  2889. inline DName UnDecorator::getCallIndex ( void ) { return getDimension (); }
  2890. inline DName UnDecorator::getGuardNumber ( void ) { return getDimension (); }
  2891. inline DName UnDecorator::getVbTableType ( const DName & superType )
  2892. { return getVfTableType ( superType ); }
  2893. inline DName UnDecorator::getVCallThunkType ( void )
  2894. {
  2895. #if VERS_32BIT
  2896. switch (*gName) {
  2897. case VMT_nTnCnV:
  2898. ++gName;
  2899. return DName("{flat}");
  2900. case 0:
  2901. return DN_truncated;
  2902. default:
  2903. return DN_invalid;
  2904. }
  2905. #else
  2906. DName vcallType = '{';
  2907. // Get the 'this' model, and validate all values
  2908. switch ( *gName )
  2909. {
  2910. case VMT_nTnCnV:
  2911. case VMT_nTfCnV:
  2912. case VMT_nTnCfV:
  2913. case VMT_nTfCfV:
  2914. case VMT_nTnCbV:
  2915. case VMT_nTfCbV:
  2916. vcallType += UScore ( TOK_nearSp );
  2917. break;
  2918. case VMT_fTnCnV:
  2919. case VMT_fTfCnV:
  2920. case VMT_fTnCfV:
  2921. case VMT_fTfCfV:
  2922. case VMT_fTnCbV:
  2923. case VMT_fTfCbV:
  2924. vcallType += UScore ( TOK_farSp );
  2925. break;
  2926. case 0:
  2927. return DN_truncated;
  2928. default:
  2929. return DN_invalid;
  2930. } // End of SWITCH
  2931. // Always append 'this'
  2932. vcallType += "this, ";
  2933. // Get the 'call' model
  2934. switch ( *gName )
  2935. {
  2936. case VMT_nTnCnV:
  2937. case VMT_fTnCnV:
  2938. case VMT_nTnCfV:
  2939. case VMT_fTnCfV:
  2940. case VMT_nTnCbV:
  2941. case VMT_fTnCbV:
  2942. vcallType += UScore ( TOK_nearSp );
  2943. break;
  2944. case VMT_nTfCnV:
  2945. case VMT_fTfCnV:
  2946. case VMT_nTfCfV:
  2947. case VMT_fTfCfV:
  2948. case VMT_nTfCbV:
  2949. case VMT_fTfCbV:
  2950. vcallType += UScore ( TOK_farSp );
  2951. break;
  2952. } // End of SWITCH
  2953. // Always append 'call'
  2954. vcallType += "call, ";
  2955. // Get the 'vfptr' model
  2956. switch ( *gName++ ) // Last time, so advance the pointer
  2957. {
  2958. case VMT_nTnCnV:
  2959. case VMT_nTfCnV:
  2960. case VMT_fTnCnV:
  2961. case VMT_fTfCnV:
  2962. vcallType += UScore ( TOK_nearSp );
  2963. break;
  2964. case VMT_nTnCfV:
  2965. case VMT_nTfCfV:
  2966. case VMT_fTnCfV:
  2967. case VMT_fTfCfV:
  2968. vcallType += UScore ( TOK_farSp );
  2969. break;
  2970. case VMT_nTfCbV:
  2971. case VMT_fTnCbV:
  2972. case VMT_fTfCbV:
  2973. case VMT_nTnCbV:
  2974. vcallType += getBasedType ();
  2975. break;
  2976. } // End of SWITCH
  2977. // Always append 'vfptr'
  2978. vcallType += "vfptr}";
  2979. // And return the resultant 'vcall-model-type'
  2980. return vcallType;
  2981. #endif
  2982. } // End of "UnDecorator" FUNCTION "getVCallThunk"
  2983. inline DName UnDecorator::getVfTableType ( const DName & superType )
  2984. {
  2985. DName vxTableName = superType;
  2986. if ( vxTableName.isValid () && *gName )
  2987. {
  2988. vxTableName = getStorageConvention () + ' ' + vxTableName;
  2989. if ( vxTableName.isValid ())
  2990. {
  2991. if ( *gName != '@' )
  2992. {
  2993. vxTableName += "{for ";
  2994. while ( vxTableName.isValid () && *gName && ( *gName != '@' ))
  2995. {
  2996. vxTableName += '`' + getScope () + '\'';
  2997. // Skip the scope delimiter
  2998. if ( *gName == '@' )
  2999. gName++;
  3000. // Close the current scope, and add a conjunction for the next (if any)
  3001. if ( vxTableName.isValid () && ( *gName != '@' ))
  3002. vxTableName += "s ";
  3003. } // End of WHILE
  3004. if ( vxTableName.isValid ())
  3005. {
  3006. if ( !*gName )
  3007. vxTableName += DN_truncated;
  3008. vxTableName += '}';
  3009. } // End of IF
  3010. } // End of IF
  3011. // Skip the 'vpath-name' terminator
  3012. if ( *gName == '@' )
  3013. gName++;
  3014. } // End of IF
  3015. } // End of IF then
  3016. elif ( vxTableName.isValid ())
  3017. vxTableName = DN_truncated + vxTableName;
  3018. return vxTableName;
  3019. } // End of "UnDecorator" FUNCTION "getVfTableType"
  3020. inline DName UnDecorator::getVdispMapType ( const DName & superType )
  3021. {
  3022. DName vdispMapName = superType;
  3023. vdispMapName += "{for ";
  3024. vdispMapName += getScope();
  3025. vdispMapName += '}';
  3026. if ( *gName == '@' )
  3027. gName++;
  3028. return vdispMapName;
  3029. }
  3030. #endif // !NO_COMPILER_NAMES
  3031. inline DName UnDecorator::getExternalDataType ( const DName & superType )
  3032. {
  3033. // Create an indirect declarator for the the rest
  3034. DName * pDeclarator = gnew DName ();
  3035. DName declaration = getDataType ( pDeclarator );
  3036. // Now insert the declarator into the declaration along with its 'storage-convention'
  3037. *pDeclarator = getStorageConvention () + ' ' + superType;
  3038. return declaration;
  3039. } // End of "UnDecorator" FUNCTION "getExternalDataType"
  3040. inline int UnDecorator::doUnderScore () { return !( disableFlags & UNDNAME_NO_LEADING_UNDERSCORES ); }
  3041. inline int UnDecorator::doMSKeywords () { return !( disableFlags & UNDNAME_NO_MS_KEYWORDS ); }
  3042. inline int UnDecorator::doPtr64 () { return !( disableFlags & UNDNAME_NO_PTR64 ); }
  3043. inline int UnDecorator::doFunctionReturns () { return !( disableFlags & UNDNAME_NO_FUNCTION_RETURNS ); }
  3044. inline int UnDecorator::doAllocationModel () { return !( disableFlags & UNDNAME_NO_ALLOCATION_MODEL ); }
  3045. inline int UnDecorator::doAllocationLanguage () { return !( disableFlags & UNDNAME_NO_ALLOCATION_LANGUAGE ); }
  3046. #if 0
  3047. inline int UnDecorator::doMSThisType () { return !( disableFlags & UNDNAME_NO_MS_THISTYPE ); }
  3048. inline int UnDecorator::doCVThisType () { return !( disableFlags & UNDNAME_NO_CV_THISTYPE ); }
  3049. #endif
  3050. inline int UnDecorator::doThisTypes () { return (( disableFlags & UNDNAME_NO_THISTYPE ) != UNDNAME_NO_THISTYPE ); }
  3051. inline int UnDecorator::doAccessSpecifiers () { return !( disableFlags & UNDNAME_NO_ACCESS_SPECIFIERS ); }
  3052. inline int UnDecorator::doThrowTypes () { return !( disableFlags & UNDNAME_NO_THROW_SIGNATURES ); }
  3053. inline int UnDecorator::doMemberTypes () { return !( disableFlags & UNDNAME_NO_MEMBER_TYPE ); }
  3054. inline int UnDecorator::doReturnUDTModel () { return !( disableFlags & UNDNAME_NO_RETURN_UDT_MODEL ); }
  3055. inline int UnDecorator::do32BitNear () { return !( disableFlags & UNDNAME_32_BIT_DECODE ); }
  3056. inline int UnDecorator::doNameOnly () { return ( disableFlags & UNDNAME_NAME_ONLY ); }
  3057. inline int UnDecorator::doTypeOnly () { return ( disableFlags & UNDNAME_TYPE_ONLY ); }
  3058. inline int UnDecorator::haveTemplateParameters () { return ( disableFlags & UNDNAME_HAVE_PARAMETERS); }
  3059. inline int UnDecorator::doEcsu () { return !( disableFlags & UNDNAME_NO_ECSU ); }
  3060. inline int UnDecorator::doNoIdentCharCheck () { return ( disableFlags & UNDNAME_NO_IDENT_CHAR_CHECK ); }
  3061. pcchar_t UnDecorator::UScore ( Tokens tok )
  3062. {
  3063. #if !VERS_32BIT
  3064. if ((( tok == TOK_nearSp ) || ( tok == TOK_nearP )) && !do32BitNear ())
  3065. return tokenTable[ tok ] + 6; // Skip '__near'
  3066. #endif
  3067. if ( doUnderScore ())
  3068. return tokenTable[ tok ];
  3069. else
  3070. return tokenTable[ tok ] + 2 ;
  3071. } // End of "UnDecorator" FUNCTION "UScore"
  3072. // Include the string composition support classes. Mostly inline stuff, and
  3073. // not important to the algorithm.
  3074. #include "undname.inl"