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

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