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.

3336 lines
108 KiB

  1. // Make sure all dependent defines exist and have a valid value
  2. #ifndef TUNE
  3. #define TUNE 0
  4. #endif
  5. #ifndef DEBUG
  6. #define DEBUG 0
  7. #endif
  8. #ifndef STANDALONE
  9. #define STANDALONE 0
  10. #endif
  11. #ifndef SPECIAL
  12. #define SPECIAL 0
  13. #endif
  14. #ifndef TARGET_32BIT
  15. #define TARGET_32BIT 1 // DLH set in makefile originally
  16. #endif
  17. #ifndef USE_CRT_HEAP
  18. #define USE_CRT_HEAP 0
  19. #endif
  20. #ifndef NO_COMPILER_NAMES
  21. #define NO_COMPILER_NAMES 0
  22. #endif
  23. #ifndef NO_OPTIONS
  24. #define NO_OPTIONS 0
  25. #endif
  26. #ifndef NO_INLINES
  27. #define NO_INLINES 0
  28. #endif
  29. #ifndef VERS_P3
  30. #define VERS_P3 0
  31. #endif
  32. #ifndef VERS_PWB
  33. #define VERS_PWB 0
  34. #endif
  35. #ifndef VERS_LNK
  36. #define VERS_LNK 1 // DLH set in makefile originally
  37. #endif
  38. #ifndef PACK_SIZE
  39. #define PACK_SIZE 1
  40. #endif
  41. #ifndef inline_p3
  42. #define inline_p3
  43. #endif
  44. #ifndef inline_pwb
  45. #define inline_pwb
  46. #endif
  47. #ifndef inline_lnk
  48. #define inline_lnk
  49. #endif
  50. #ifndef NO_VIRTUAL
  51. #define NO_VIRTUAL 0
  52. #endif
  53. // Check for version inconsistancies, ans setup version flags
  54. #if ( TUNE && STANDALONE )
  55. #error "TUNE and STANDALONE are incompatible"
  56. #endif // TUNE && STANDALONE
  57. #if ( VERS_P3 == 1 )
  58. #if ( VERS_PWB == 1 )
  59. #error "VERS_P3 and VERS_PWB are incompatible"
  60. #endif // VERS_PWB
  61. #if ( VERS_LNK == 1 )
  62. #error "VERS_P3 and VERS_LNK are incompatible"
  63. #endif // VERS_LNK
  64. #undef inline_p3
  65. #define inline_p3 inline
  66. #undef USE_CRT_HEAP
  67. #define USE_CRT_HEAP 1
  68. #undef NO_COMPILER_NAMES
  69. #define NO_COMPILER_NAMES 1
  70. #undef NO_OPTIONS
  71. #define NO_OPTIONS 1
  72. #pragma inline_depth ( 3 )
  73. #pragma pack ( 2 )
  74. #undef PACK_SIZE
  75. #define PACK_SIZE 1
  76. #endif
  77. #if ( VERS_PWB == 1 )
  78. #if ( DEBUG == 1 )
  79. #error "VERS_PWB and DEBUG are incompatible"
  80. #endif // DEBUG
  81. #if ( VERS_LNK == 1 )
  82. #error "VERS_PWB and VERS_LNK are incompatible"
  83. #endif // VERS_LNK
  84. #undef inline_pwb
  85. #define inline_pwb inline
  86. #undef USE_CRT_HEAP
  87. #define USE_CRT_HEAP 0
  88. #undef NO_COMPILER_NAMES
  89. #define NO_COMPILER_NAMES 1
  90. #undef NO_OPTIONS
  91. #define NO_OPTIONS 1
  92. #undef PACK_SIZE
  93. #define PACK_SIZE 2
  94. #undef NO_VIRTUAL
  95. #define NO_VIRTUAL 1
  96. #pragma inline_depth ( 5 )
  97. #pragma pack ( 2 )
  98. #endif // VERS_PWB
  99. #if ( VERS_LNK == 1 )
  100. #if ( VERS_PWB == 1 )
  101. #error "VERS_LNK and VERS_PWB are incompatible"
  102. #endif // VERS_PWB
  103. #undef inline_lnk
  104. #define inline_lnk inline
  105. #if ( DEBUG == 1 )
  106. #if !STANDALONE
  107. #undef USE_CRT_HEAP
  108. #define USE_CRT_HEAP 1
  109. #endif
  110. #else // } else !DEBUG {
  111. #undef USE_CRT_HEAP
  112. #define USE_CRT_HEAP 0
  113. #endif // !DEBUG
  114. #undef NO_COMPILER_NAMES
  115. #define NO_COMPILER_NAMES 0
  116. #undef NO_OPTIONS
  117. #define NO_OPTIONS 0
  118. #undef NO_VIRTUAL
  119. #define NO_VIRTUAL 1
  120. #pragma inline_depth ( 3 )
  121. #pragma pack ( 2 )
  122. #undef PACK_SIZE
  123. #define PACK_SIZE 2
  124. #endif // VERS_LNK
  125. #if ( TARGET_32BIT )
  126. #define __far /* no far */
  127. #define __near /* no near */
  128. #define __pascal /* no pascal */
  129. #if !defined( _WIN32 )
  130. #define __cdecl /* no cdecl */
  131. #endif
  132. #define __loadds /* no loadds */
  133. #endif // TARGET_32BIT
  134. #if ( !NO_VIRTUAL )
  135. #define PURE =0
  136. #else // } elif NO_VIRTUAL {
  137. #define PURE
  138. #define virtual
  139. #endif
  140. #if DEBUG && STANDALONE
  141. #define STDEBUG 1
  142. #endif
  143. #include "undname.hxx"
  144. static unsigned int __near __pascal strlen ( pcchar_t );
  145. static pchar_t __near __pascal strncpy ( pchar_t, pcchar_t, unsigned int );
  146. #if USE_CRT_HEAP
  147. extern "C" void __far * __far __cdecl malloc ( unsigned int );
  148. extern "C" void __far __cdecl free ( void __far * );
  149. #endif // USE_CRT_HEAP
  150. #if STDEBUG
  151. #pragma inline_depth ( 0 )
  152. #pragma pack ( 2 )
  153. #undef PACK_SIZE
  154. #define PACK_SIZE 1
  155. #include <stdio.h>
  156. class DName;
  157. class DNameNode;
  158. class CallTrace
  159. {
  160. private:
  161. enum InOut { out = -1, mark = 0, in = 1 };
  162. pchar_t name;
  163. static int trace;
  164. static FILE * fp;
  165. static char buf[ 512 ];
  166. static int inTrace;
  167. static void indent ( InOut inOut )
  168. { static depth = 0; for ( int d = depth - (( inOut == out ) ? 1 : 0 ); d; d-- ) fputc ( '.', fp ); switch ( inOut ) { case in: depth++; break; case out: depth--; break; }}
  169. public:
  170. CallTrace ( pchar_t p )
  171. : name ( p )
  172. { if(trace&&!inTrace){ indent ( in ); fprintf ( fp, "Entered : '%s'\n", name ); fflush ( fp ); }}
  173. static void On ( pchar_t f )
  174. { fp = fopen ( f, "wt" ); if(fp) trace = 1; }
  175. void Dump ( const DName &, pcchar_t, int );
  176. void Dump ( const DNameNode &, pcchar_t, int );
  177. void Dump ( unsigned long, pcchar_t, int );
  178. void Dump ( void*, pcchar_t, int );
  179. void Dump ( pcchar_t, pcchar_t, int );
  180. void Message ( pcchar_t, int );
  181. void Track ( pcchar_t, int );
  182. void LogError ( int );
  183. ~CallTrace ()
  184. { if(trace&&!inTrace){ indent ( out ); fprintf ( fp, "Leaving : '%s'\n", name ); fflush ( fp ); }}
  185. };
  186. int CallTrace::trace = 0;
  187. int CallTrace::inTrace = 0;
  188. FILE * CallTrace::fp = 0;
  189. char CallTrace::buf[ 512 ];
  190. #undef NO_INLINES
  191. #define NO_INLINES 1
  192. #define FTRACE(n) CallTrace fName(#n)
  193. #define TRACEON() do{if((argc>=2)&&(*argv[1]!='?')&&((*argv[1]<'0')||(*argv[1]>'9'))){argv++;argc--;CallTrace::On(*argv);}}while(0)
  194. #define DUMP(n) (fName.Dump(n,#n,__LINE__))
  195. #define TRACK() (fName.Track(__FILE__,__LINE__))
  196. #define MESSAGE(m) (fName.Message(#m,__LINE__))
  197. #define ERROR (fName.LogError(__LINE__),DN_error)
  198. #else // } elif !STDEBUG {
  199. #pragma check_stack ( off )
  200. #pragma pack ( 2 )
  201. #undef PACK_SIZE
  202. #define PACK_SIZE 1
  203. #define FTRACE(n)
  204. #define TRACEON()
  205. #define DUMP(n)
  206. #define TRACK()
  207. #define MESSAGE(m) (0)
  208. #define ERROR DN_error
  209. #endif // !STDEBUG
  210. #if ( NO_INLINES )
  211. #undef inline_p3
  212. #undef inline_pwb
  213. #undef inline_lnk
  214. #define inline
  215. #define inline_p3
  216. #define inline_pwb
  217. #define inline_lnk
  218. #endif // NO_INLINES
  219. #if STANDALONE
  220. extern "C" int __far __cdecl printf ( pcchar_t, ... );
  221. extern "C" int __far __cdecl atoi ( pcchar_t );
  222. extern "C" void __far * __far __cdecl malloc ( unsigned int );
  223. extern "C" void __far __cdecl free ( void __far * );
  224. #if STDEBUG
  225. int shallowCopies = 0;
  226. int deepCopies = 0;
  227. int shallowAssigns = 0;
  228. int deepAssigns = 0;
  229. #endif
  230. int actual = 0;
  231. int requested = 0;
  232. int clones = 0;
  233. int __cdecl main ( int argc, pchar_t* argv )
  234. {
  235. TRACEON();
  236. FTRACE(main);
  237. unsigned short flags = 0;
  238. if (( argc > 2 ) && ( *argv[ 1 ] >= '0' ) && ( *argv[ 1 ] <= '9' ))
  239. ( flags = atoi ( argv[ 1 ]), argc--, argv++ );
  240. for ( int i = 1; i < argc; i++ )
  241. {
  242. printf ( "Undecoration of :- \"%s\"\n", argv[ i ]);
  243. pchar_t uName = unDName ( 0,
  244. argv[ i ],
  245. 0
  246. #if ( !USE_CRT_HEAP )
  247. ,&malloc
  248. ,&free
  249. #endif // !USE_CRT_HEAP
  250. #if ( !NO_OPTIONS )
  251. ,flags
  252. #endif // !NO_OPTIONS
  253. );
  254. if ( uName )
  255. printf ( "is :- \"%s\"\n\n", uName );
  256. else
  257. printf ( "Internal Error in Undecorator\n" );
  258. }
  259. #if STDEBUG
  260. printf ( "%d bytes of memory requested, %d bytes allocated\n", requested, actual );
  261. printf ( "%d shallow copies and %d deep copies\n", shallowCopies, deepCopies );
  262. printf ( "%d shallow assigns and %d deep assigns\n", shallowAssigns, deepAssigns );
  263. printf ( "%d clones\n", clones );
  264. #endif
  265. return 0;
  266. } // End of PROGRAM
  267. #endif // STANDALONE
  268. #if TUNE
  269. void __cdecl main ()
  270. { (void)unDName ( 0, 0, 0
  271. #if ( !USE_CRT_HEAP )
  272. ,0, 0
  273. #endif // !USE_CRT_HEAP
  274. #if ( !NO_OPTIONS )
  275. ,0
  276. #endif // !NO_OPTIONS
  277. ); }
  278. #endif // TUNE
  279. class DName;
  280. class DNameNode;
  281. class Replicator;
  282. class HeapManager;
  283. class UnDecorator;
  284. const unsigned int memBlockSize = 508; // A '512' byte block including the header
  285. class HeapManager
  286. {
  287. private:
  288. #if ( !USE_CRT_HEAP )
  289. Alloc_t pOpNew;
  290. Free_t pOpDelete;
  291. #endif // !USE_CRT_HEAP
  292. struct Block
  293. {
  294. Block * next;
  295. char memBlock[ memBlockSize ];
  296. __near Block () { next = 0; }
  297. };
  298. Block * head;
  299. Block * tail;
  300. unsigned int blockLeft;
  301. public:
  302. #if ( !USE_CRT_HEAP )
  303. void __near Constructor ( Alloc_t pAlloc, Free_t pFree )
  304. { pOpNew = pAlloc;
  305. pOpDelete = pFree;
  306. #else // } elif USE_CRT_HEAP {
  307. void __near Constructor ( void )
  308. {
  309. #endif // USE_CRT_HEAP
  310. blockLeft = 0;
  311. head = 0;
  312. tail = 0;
  313. }
  314. void __far * __near getMemory ( size_t, int );
  315. void __near Destructor ( void )
  316. { while ( tail = head )
  317. {
  318. head = tail->next;
  319. #if ( !USE_CRT_HEAP )
  320. ( *pOpDelete )( tail );
  321. #else // } elif USE_CRT_HEAP {
  322. free ( tail );
  323. #endif // USE_CRT_HEAP
  324. } }
  325. #define gnew new(heap,0)
  326. #define rnew new(heap,1)
  327. };
  328. void * __near __pascal operator new ( size_t, HeapManager &, int = 0 );
  329. static HeapManager heap;
  330. #if ( !VERS_PWB )
  331. // The MS Token table
  332. enum Tokens
  333. {
  334. TOK_near,
  335. TOK_nearSp,
  336. TOK_nearP,
  337. TOK_far,
  338. TOK_farSp,
  339. TOK_farP,
  340. TOK_huge,
  341. TOK_hugeSp,
  342. TOK_hugeP,
  343. TOK_basedLp,
  344. TOK_cdecl,
  345. TOK_pascal,
  346. TOK_stdcall,
  347. TOK_syscall,
  348. TOK_fastcall,
  349. TOK_interrupt,
  350. TOK_saveregs,
  351. TOK_self,
  352. TOK_segment,
  353. TOK_segnameLpQ
  354. };
  355. static pcchar_t __near tokenTable[] =
  356. {
  357. "__near", // TOK_near
  358. "__near ", // TOK_nearSp
  359. "__near*", // TOK_nearP
  360. "__far", // TOK_far
  361. "__far ", // TOK_farSp
  362. "__far*", // TOK_farP
  363. "__huge", // TOK_huge
  364. "__huge ", // TOK_hugeSp
  365. "__huge*", // TOK_hugeP
  366. "__based(", // TOK_basedLp
  367. "__cdecl", // TOK_cdecl
  368. "__pascal", // TOK_pascal
  369. "__stdcall", // TOK_stdcall
  370. "__syscall", // TOK_syscall
  371. "__fastcall", // TOK_fastcall
  372. "__interrupt", // TOK_interrupt
  373. "__saveregs", // TOK_saveregs
  374. "__self", // TOK_self
  375. "__segment", // TOK_segment
  376. "__segname(\"" // TOK_segnameLpQ
  377. };
  378. #endif // !VERS_PWB
  379. // The operator mapping table
  380. static pcchar_t __near nameTable[] =
  381. {
  382. " new",
  383. " delete",
  384. "=",
  385. ">>",
  386. "<<",
  387. "!",
  388. "==",
  389. "!=",
  390. "[]",
  391. #if VERS_P3
  392. "<UDC>",
  393. #else // } !VERS_P3 {
  394. "operator",
  395. #endif // VERS_P3
  396. "->",
  397. "*",
  398. "++",
  399. "--",
  400. "-",
  401. "+",
  402. "&",
  403. "->*",
  404. "/",
  405. "%",
  406. "<",
  407. "<=",
  408. ">",
  409. ">=",
  410. ",",
  411. "()",
  412. "~",
  413. "^",
  414. "|",
  415. "&&",
  416. "||",
  417. "*=",
  418. "+=",
  419. "-=",
  420. "/=",
  421. "%=",
  422. ">>=",
  423. "<<=",
  424. "&=",
  425. "|=",
  426. "^=",
  427. #if ( !NO_COMPILER_NAMES )
  428. "`vftable'",
  429. "`vbtable'",
  430. "`vcall",
  431. "`typeof'",
  432. "`local static guard",
  433. "`reserved'",
  434. "`vbase destructor'",
  435. "`vector deleting destructor'",
  436. "`default constructor closure'",
  437. "`scalar deleting destructor'",
  438. "`vector constructor iterator'",
  439. "`vector destructor iterator'",
  440. "`vector vbase constructor iterator'"
  441. #endif // !NO_COMPILER_NAMES
  442. };
  443. // The following 'enum' should really be nested inside 'class DName', but to
  444. // make the code compile better with Glockenspiel, I have extracted it
  445. enum DNameStatus
  446. {
  447. DN_valid,
  448. DN_invalid,
  449. DN_truncated,
  450. DN_error
  451. };
  452. class DName
  453. {
  454. public:
  455. __near DName ();
  456. __near DName ( char );
  457. #if 1
  458. __near DName ( const DName & ); // Shallow copy
  459. #endif
  460. __near DName ( DNameNode * );
  461. __near DName ( pcchar_t );
  462. __near DName ( pcchar_t&, char );
  463. __near DName ( DNameStatus );
  464. #if ( !VERS_P3 )
  465. __near DName ( DName * );
  466. __near DName ( unsigned long );
  467. #endif // !VERS_P3
  468. int __near isValid () const;
  469. int __near isEmpty () const;
  470. DNameStatus __near status () const;
  471. #if ( !VERS_P3 )
  472. DName & __near setPtrRef ();
  473. int __near isPtrRef () const;
  474. int __near isUDC () const;
  475. void __near setIsUDC ();
  476. #endif // !VERS_P3
  477. int __near length () const;
  478. pchar_t __near getString ( pchar_t, int ) const;
  479. DName __near operator + ( pcchar_t ) const;
  480. DName __near operator + ( const DName & ) const;
  481. #if ( !VERS_P3 )
  482. DName __near operator + ( char ) const;
  483. DName __near operator + ( DName * ) const;
  484. DName __near operator + ( DNameStatus ) const;
  485. DName & __near operator += ( char );
  486. DName & __near operator += ( pcchar_t );
  487. DName & __near operator += ( DName * );
  488. DName & __near operator += ( DNameStatus );
  489. DName & __near operator |= ( const DName & );
  490. #endif // !VERS_P3
  491. DName & __near operator += ( const DName & );
  492. DName & __near operator = ( pcchar_t );
  493. DName & __near operator = ( const DName & );
  494. #if ( !VERS_P3 )
  495. DName & __near operator = ( char );
  496. DName & __near operator = ( DName * );
  497. DName & __near operator = ( DNameStatus );
  498. #endif // !VERS_P3
  499. // Friends :
  500. friend DName __near __pascal operator + ( char, const DName & );
  501. friend DName __near __pascal operator + ( pcchar_t, const DName & );
  502. #if ( !VERS_P3 )
  503. friend DName __near __pascal operator + ( DNameStatus, const DName & );
  504. #endif // !VERS_P3
  505. private:
  506. DNameNode * node;
  507. DNameStatus stat : 4;
  508. unsigned int isIndir : 1;
  509. unsigned int isAUDC : 1;
  510. void __near doPchar ( pcchar_t, int );
  511. };
  512. class Replicator
  513. {
  514. private:
  515. // Declare, in order to suppress automatic generation
  516. void operator = ( const Replicator& );
  517. int index;
  518. DName * dNameBuffer[ 10 ];
  519. const DName ErrorDName;
  520. const DName InvalidDName;
  521. public:
  522. __near Replicator ();
  523. int __near isFull () const;
  524. Replicator & __near operator += ( const DName & );
  525. const DName & __near operator [] ( int ) const;
  526. };
  527. class UnDecorator
  528. {
  529. private:
  530. // Declare, in order to suppress automatic generation
  531. void operator = ( const UnDecorator& );
  532. #if ( !VERS_P3 )
  533. Replicator ArgList;
  534. static Replicator * pArgList;
  535. #endif // !VERS_P3
  536. Replicator ZNameList;
  537. static Replicator * pZNameList;
  538. static pcchar_t gName;
  539. static pcchar_t name;
  540. static pchar_t outputString;
  541. static int maxStringLength;
  542. #if (!NO_OPTIONS)
  543. static unsigned short disableFlags;
  544. #endif // !NO_OPTIONS
  545. static DName __near getDecoratedName ( void );
  546. static DName __near getSymbolName ( void );
  547. static DName __near getZName ( void );
  548. static DName __near getOperatorName ( void );
  549. static DName __near getScope ( void );
  550. #if ( !VERS_P3 )
  551. static DName __near getDimension ( void );
  552. static int __near getNumberOfDimensions ( void );
  553. static DName __near getTemplateName ( void );
  554. static DName __near composeDeclaration ( const DName & );
  555. static int __near getTypeEncoding ( void );
  556. static DName __near getBasedType ( void );
  557. static DName __near getECSUName ( void );
  558. static DName __near getEnumName ( void );
  559. static DName __near getCallingConvention ( void );
  560. static DName __near getReturnType ( DName * = 0 );
  561. static DName __near getDataType ( DName * );
  562. static DName __near getPrimaryDataType ( const DName & );
  563. static DName __near getDataIndirectType ( const DName &, char, const DName &, int = FALSE );
  564. static DName __near getDataIndirectType ();
  565. static DName __near getBasicDataType ( const DName & );
  566. static DName __near getECSUDataType ( int = 0 );
  567. static int __near getECSUDataIndirectType ();
  568. static DName __near getPtrRefType ( const DName &, const DName &, int );
  569. static DName __near getPtrRefDataType ( const DName &, int );
  570. static DName __near getArrayType ( DName * );
  571. static DName __near getArgumentTypes ( void );
  572. static DName __near getArgumentList ( void );
  573. static DName __near getThrowTypes ( void );
  574. static DName __near getLexicalFrame ( void );
  575. static DName __near getStorageConvention ( void );
  576. static DName __near getThisType ( void );
  577. static DName __near getPointerType ( const DName &, const DName & );
  578. static DName __near getReferenceType ( const DName &, const DName & );
  579. static DName __near getExternalDataType ( const DName & );
  580. #if ( !VERS_PWB )
  581. static DName __near getSegmentName ( void );
  582. #endif // !VERS_PWB
  583. #if ( !NO_COMPILER_NAMES )
  584. static DName __near getDisplacement ( void );
  585. static DName __near getCallIndex ( void );
  586. static DName __near getGuardNumber ( void );
  587. static DName __near getVfTableType ( const DName & );
  588. static DName __near getVbTableType ( const DName & );
  589. static DName __near getVCallThunkType ( void );
  590. #endif // !NO_COMPILER_NAMES
  591. #endif // !VERS_P3
  592. public:
  593. #if ( !NO_OPTIONS )
  594. __near UnDecorator ( pchar_t, pcchar_t, int, unsigned short );
  595. static int __near doUnderScore ();
  596. static int __near doMSKeywords ();
  597. static int __near doFunctionReturns ();
  598. static int __near doAllocationModel ();
  599. static int __near doAllocationLanguage ();
  600. #if 0
  601. static int __near doMSThisType ();
  602. static int __near doCVThisType ();
  603. #endif
  604. static int __near doThisTypes ();
  605. static int __near doAccessSpecifiers ();
  606. static int __near doThrowTypes ();
  607. static int __near doMemberTypes ();
  608. static int __near doReturnUDTModel ();
  609. #else // } elif NO_OPTIONS {
  610. __near UnDecorator ( pchar_t, pcchar_t, int );
  611. #endif // NO_OPTIONS
  612. #if ( !VERS_P3 && !VERS_PWB )
  613. static pcchar_t __near UScore ( Tokens );
  614. #endif // !VERS_P3 && !VERS_PWB
  615. __near operator pchar_t ();
  616. };
  617. #if ( !VERS_P3 )
  618. Replicator * UnDecorator::pArgList;
  619. #endif // !VERS_P3
  620. Replicator * UnDecorator::pZNameList = 0;
  621. pcchar_t UnDecorator::gName = 0;
  622. pcchar_t UnDecorator::name = 0;
  623. pchar_t UnDecorator::outputString = 0;
  624. int UnDecorator::maxStringLength = 0;
  625. #if (!NO_OPTIONS)
  626. unsigned short UnDecorator::disableFlags = 0;
  627. #endif // !NO_OPTIONS
  628. pchar_t __far __cdecl __loadds unDName ( pchar_t outputString,
  629. pcchar_t name,
  630. int maxStringLength // Note, COMMA is leading following optional arguments
  631. #if ( !USE_CRT_HEAP )
  632. ,Alloc_t pAlloc
  633. ,Free_t pFree
  634. #endif // !USE_CRT_HEAP
  635. #if ( !NO_OPTIONS )
  636. ,unsigned short disableFlags
  637. #endif // !NO_OPTIONS
  638. )
  639. /*
  640. * This function will undecorate a name, returning the string corresponding to
  641. * the C++ declaration needed to produce the name. Its has a similar interface
  642. * to 'strncpy'.
  643. *
  644. * If the target string 'outputString' is specified to be NULL, a string of
  645. * suitable length will be allocated and its address returned. If the returned
  646. * string is allocated by 'unDName', then it is the programmers responsibility
  647. * to deallocate it. It will have been allocated on the far heap.
  648. *
  649. * If the target string is not NULL, then the parameter 'maxStringLength' will
  650. * specify the maximum number of characters which may be placed in the string.
  651. * In this case, the returned value is the same as 'outputString'.
  652. *
  653. * Both the input parameter 'name' and the returned string are NULL terminated
  654. * strings of characters.
  655. *
  656. * If the returned value is NULL, it indicates that the undecorator ran out of
  657. * memory, or an internal error occurred, and was unable to complete its task.
  658. */
  659. {
  660. FTRACE(unDName);
  661. #if ( VERS_P3 && !STANDALONE )
  662. // Abort if input is invalid
  663. if ( !outputString || !name || !maxStringLength )
  664. return 0;
  665. #endif // ( VERS_P3 && !STANDALONE )
  666. #if ( !USE_CRT_HEAP )
  667. // Must have an allocator and a deallocator (and we MUST trust them)
  668. if ( !( pAlloc && pFree ))
  669. return 0;
  670. else
  671. heap.Constructor ( pAlloc, pFree );
  672. #else // } elif USE_CRT_HEAP {
  673. heap.Constructor ();
  674. #endif // USE_CRT_HEAP
  675. // Create the undecorator object, and get the result
  676. UnDecorator unDecorate ( outputString,
  677. name,
  678. maxStringLength
  679. #if ( !NO_OPTIONS )
  680. ,disableFlags
  681. #endif // !NO_OPTIONS
  682. );
  683. pchar_t unDecoratedName = unDecorate;
  684. // Destruct the heap (would use a destructor, but that causes DLL problems)
  685. heap.Destructor ();
  686. // And return the composed name
  687. return unDecoratedName;
  688. } // End of FUNCTION "unDName"
  689. // The 'UnDecorator' member functions
  690. inline __near UnDecorator::UnDecorator ( pchar_t output,
  691. pcchar_t dName,
  692. int maxLen
  693. #if ( !NO_OPTIONS )
  694. ,unsigned short disable
  695. #endif // !NO_OPTIONS
  696. )
  697. {
  698. FTRACE(UnDecorator::UnDecorator);
  699. #if STDEBUG
  700. if ( dName )
  701. {
  702. while ( *dName == ' ' )
  703. dName++;
  704. pchar_t s = gnew char[ strlen ( dName ) + 1 ];
  705. if ( name = s )
  706. do
  707. {
  708. if (( *s = *dName ) != ' ' )
  709. s++;
  710. } while ( *dName++ );
  711. }
  712. else
  713. name = 0;
  714. #else // } elif !STDEBUG {
  715. name = dName;
  716. #endif // !STDEBUG
  717. gName = name;
  718. maxStringLength = maxLen;
  719. outputString = output;
  720. pZNameList = &ZNameList;
  721. #if ( !VERS_P3 )
  722. pArgList = &ArgList;
  723. #endif // !VERS_P3
  724. #if ( !NO_OPTIONS )
  725. disableFlags = disable;
  726. #endif // !NO_OPTIONS
  727. } // End of "UnDecorator" CONSTRUCTOR '()'
  728. inline __near UnDecorator::operator pchar_t ()
  729. {
  730. FTRACE(UnDecorator::pchar_t);
  731. DName result;
  732. DName unDName;
  733. // Find out if the name is a decorated name or not. Could be a reserved
  734. // CodeView variant of a decorated name
  735. if ( name )
  736. {
  737. if (( *name == '?' ) && ( name[ 1 ] == '@' ))
  738. {
  739. #if ( !NO_COMPILER_NAMES )
  740. gName += 2;
  741. result = "CV: " + getDecoratedName ();
  742. #else // } elif NO_COMPILER_NAMES
  743. result = DN_invalid;
  744. #endif // NO_COMPILER_NAMES
  745. } // End of IF then
  746. else
  747. result = getDecoratedName ();
  748. } // End of IF then
  749. // If the name was not a valid name, then make the name the same as the original
  750. // It is also invalid if there are any remaining characters in the name
  751. if ( result.status () == DN_error )
  752. return 0;
  753. #if ( !VERS_P3 )
  754. elif ( *gName || ( result.status () == DN_invalid ))
  755. unDName = name; // Return the original name
  756. #else // } elif VERS_P3 {
  757. elif ( !*gName || ( *gName != '@' ) || ( result.status () == DN_invalid ))
  758. unDName = ""; // Blank
  759. #endif // VERS_P3
  760. else
  761. unDName = result;
  762. #if ( !VERS_P3 || STANDALONE )
  763. // Construct the return string
  764. if ( !outputString )
  765. {
  766. maxStringLength = unDName.length () + 1;
  767. outputString = rnew char[ maxStringLength ];
  768. } // End of IF
  769. if ( outputString )
  770. #endif // ( !VERS_P3 || STANDALONE )
  771. unDName.getString ( outputString, maxStringLength );
  772. // Return the result
  773. return outputString;
  774. } // End of "UnDecorator" OPERATOR 'pchar_t'
  775. DName __near UnDecorator::getDecoratedName ( void )
  776. {
  777. FTRACE(getDecoratedName);
  778. // Ensure that it is intended to be a decorated name
  779. if ( *gName == '?' )
  780. {
  781. // Extract the basic symbol name
  782. gName++; // Advance the original name pointer
  783. DName symbolName = getSymbolName ();
  784. #if ( !VERS_P3 )
  785. int udcSeen = symbolName.isUDC ();
  786. #endif // !VERS_P3
  787. // Abort if the symbol name is invalid
  788. if ( !symbolName.isValid ())
  789. return symbolName;
  790. // Extract, and prefix the scope qualifiers
  791. if ( *gName && ( *gName != '@' ))
  792. symbolName = getScope () + "::" + symbolName;
  793. #if ( !VERS_P3 )
  794. if ( udcSeen )
  795. symbolName.setIsUDC ();
  796. // Now compose declaration
  797. if ( symbolName.isEmpty ())
  798. return symbolName;
  799. elif ( !*gName || ( *gName == '@' ))
  800. {
  801. if ( *gName )
  802. gName++;
  803. return composeDeclaration ( symbolName );
  804. } // End of ELIF then
  805. else
  806. return DN_invalid;
  807. #else // } elif VERS_P3 {
  808. return symbolName;
  809. #endif // VERS_P3
  810. } // End of IF then
  811. elif ( *gName )
  812. return DN_invalid;
  813. else
  814. return DN_truncated;
  815. } // End of "UnDecorator" FUNCTION "getDecoratedName"
  816. inline DName __near UnDecorator::getSymbolName ( void )
  817. {
  818. FTRACE(getSymbolName);
  819. if ( *gName == '?' )
  820. {
  821. gName++;
  822. return getOperatorName ();
  823. } // End of IF then
  824. else
  825. return getZName ();
  826. } // End of "UnDecorator" FUNCTION "getSymbolName"
  827. DName __near UnDecorator::getZName ( void )
  828. {
  829. FTRACE(getZName);
  830. int zNameIndex = *gName - '0';
  831. // Handle 'zname-replicators', otherwise an actual name
  832. if (( zNameIndex >= 0 ) && ( zNameIndex <= 9 ))
  833. {
  834. gName++; // Skip past the replicator
  835. // And return the indexed name
  836. return ( *pZNameList )[ zNameIndex ];
  837. } // End of IF then
  838. else
  839. {
  840. // Extract the 'zname' to the terminator
  841. DName zName ( gName, '@' ); // This constructor updates 'name'
  842. // Add it to the current list of 'zname's
  843. if ( !pZNameList->isFull ())
  844. *pZNameList += zName;
  845. // And return the symbol name
  846. return zName;
  847. } // End of IF else
  848. } // End of "UnDecorator" FUNCTION "getZName"
  849. inline DName __near UnDecorator::getOperatorName ( void )
  850. {
  851. FTRACE(getOperatorName);
  852. DName operatorName;
  853. #if ( !VERS_P3 )
  854. int udcSeen = FALSE;
  855. #endif // VERS_P3
  856. // So what type of operator is it ?
  857. switch ( *gName++ )
  858. {
  859. case 0:
  860. gName--; // End of string, better back-track
  861. return DN_truncated;
  862. case OC_ctor:
  863. case OC_dtor: // The constructor and destructor are special
  864. {
  865. // Use a temporary. Don't want to advance the name pointer
  866. pcchar_t pName = gName;
  867. operatorName = getZName ();
  868. gName = pName;
  869. if ( !operatorName.isEmpty () && ( gName[ -1 ] == OC_dtor ))
  870. operatorName = '~' + operatorName;
  871. return operatorName;
  872. } // End of CASE 'OC_ctor,OC_dtor'
  873. break;
  874. case OC_new:
  875. case OC_delete:
  876. case OC_assign:
  877. case OC_rshift:
  878. case OC_lshift:
  879. case OC_not:
  880. case OC_equal:
  881. case OC_unequal:
  882. operatorName = nameTable[ gName[ -1 ] - OC_new ];
  883. break;
  884. case OC_udc:
  885. #if ( !VERS_P3 )
  886. udcSeen = TRUE;
  887. #endif // !VERS_P3
  888. // No break
  889. case OC_index:
  890. case OC_pointer:
  891. case OC_star:
  892. case OC_incr:
  893. case OC_decr:
  894. case OC_minus:
  895. case OC_plus:
  896. case OC_amper:
  897. case OC_ptrmem:
  898. case OC_divide:
  899. case OC_modulo:
  900. case OC_less:
  901. case OC_leq:
  902. case OC_greater:
  903. case OC_geq:
  904. case OC_comma:
  905. case OC_call:
  906. case OC_compl:
  907. case OC_xor:
  908. case OC_or:
  909. case OC_land:
  910. case OC_lor:
  911. case OC_asmul:
  912. case OC_asadd:
  913. case OC_assub: // Regular operators from the first group
  914. operatorName = nameTable[ gName[ -1 ] - OC_index + ( OC_unequal - OC_new + 1 )];
  915. break;
  916. case '_':
  917. switch ( *gName++ )
  918. {
  919. case 0:
  920. gName--; // End of string, better back-track
  921. return DN_truncated;
  922. case OC_asdiv:
  923. case OC_asmod:
  924. case OC_asrshift:
  925. case OC_aslshift:
  926. case OC_asand:
  927. case OC_asor:
  928. case OC_asxor: // Regular operators from the extended group
  929. operatorName = nameTable[ gName[ -1 ] - OC_asdiv + ( OC_assub - OC_index + 1 ) + ( OC_unequal - OC_new + 1 )];
  930. break;
  931. #if ( !NO_COMPILER_NAMES )
  932. case OC_vftable:
  933. case OC_vbtable:
  934. case OC_vcall:
  935. return nameTable[ gName[ -1 ] - OC_asdiv + ( OC_assub - OC_index + 1 ) + ( OC_unequal - OC_new + 1 )];
  936. case OC_metatype:
  937. case OC_guard:
  938. case OC_uctor:
  939. case OC_udtor:
  940. case OC_vdeldtor:
  941. case OC_defctor:
  942. case OC_sdeldtor:
  943. case OC_vctor:
  944. case OC_vdtor:
  945. case OC_vallctor: // Special purpose names
  946. return nameTable[ gName[ -1 ] - OC_metatype + ( OC_vcall - OC_asdiv + 1 ) + ( OC_assub - OC_index + 1 ) + ( OC_unequal - OC_new + 1 )];
  947. #endif // !NO_COMPILER_NAMES
  948. default:
  949. return DN_invalid;
  950. } // End of SWITCH
  951. break;
  952. default:
  953. return DN_invalid;
  954. } // End of SWITCH
  955. #if ( !VERS_P3 )
  956. // This really is an operator name, so prefix it with 'operator'
  957. if ( udcSeen )
  958. operatorName.setIsUDC ();
  959. elif ( !operatorName.isEmpty ())
  960. #endif // !VERS_P3
  961. operatorName = "operator" + operatorName;
  962. return operatorName;
  963. } // End of "UnDecorator" FUNCTION "getOperatorName"
  964. DName __near UnDecorator::getScope ( void )
  965. {
  966. FTRACE(getScope);
  967. int first = TRUE;
  968. DName scope;
  969. // Get the list of scopes
  970. while (( scope.status () == DN_valid ) && *gName && ( *gName != '@' ))
  971. { // Insert the scope operator if not the first scope
  972. if ( first )
  973. first = FALSE;
  974. else
  975. scope = "::" + scope;
  976. // Determine what kind of scope it is
  977. if ( *gName == '?' )
  978. #if ( !VERS_P3 )
  979. switch ( *++gName )
  980. {
  981. case '?':
  982. scope = '`' + getDecoratedName () + '\'' + scope;
  983. break;
  984. case '$':
  985. #if ( !VERS_PWB )
  986. gName++;
  987. scope = getTemplateName () + scope;
  988. break;
  989. #else // } elif VERS_PWB {
  990. return DN_invalid;
  991. #endif // VERS_PWB
  992. default:
  993. scope = getLexicalFrame () + scope;
  994. break;
  995. } // End of SWITCH
  996. #else // } elif VERS_P3 {
  997. return DN_invalid;
  998. #endif // VERS_P3
  999. else
  1000. scope = getZName () + scope;
  1001. } // End of WHILE
  1002. // Catch error conditions
  1003. switch ( *gName )
  1004. {
  1005. case 0:
  1006. if ( first )
  1007. scope = DN_truncated;
  1008. else
  1009. scope = DName ( DN_truncated ) + "::" + scope;
  1010. break;
  1011. case '@': // '@' expected to end the scope list
  1012. break;
  1013. default:
  1014. scope = DN_invalid;
  1015. break;
  1016. } // End of SWITCH
  1017. // Return the composed scope
  1018. return scope;
  1019. } // End of "UnDecorator" FUNCTION "getScope"
  1020. #if ( !VERS_P3 )
  1021. DName __near UnDecorator::getDimension ( void )
  1022. {
  1023. FTRACE(getDimension);
  1024. if ( !*gName )
  1025. return DN_truncated;
  1026. elif (( *gName >= '0' ) && ( *gName <= '9' ))
  1027. return DName ((unsigned long)( *gName++ - '0' + 1 ));
  1028. else
  1029. {
  1030. unsigned long dim = 0L;
  1031. // Don't bother detecting overflow, it's not worth it
  1032. while ( *gName != '@' )
  1033. {
  1034. if ( !*gName )
  1035. return DN_truncated;
  1036. elif (( *gName >= 'A' ) && ( *gName <= 'P' ))
  1037. dim = ( dim << 4 ) + ( *gName - 'A' );
  1038. else
  1039. return DN_invalid;
  1040. gName++;
  1041. } // End of WHILE
  1042. // Ensure integrity, and return
  1043. if ( *gName++ != '@' )
  1044. return DN_invalid; // Should never get here
  1045. return dim;
  1046. } // End of ELIF else
  1047. } // End of "UnDecorator" FUNCTION "getDimension"
  1048. inline_pwb int __near UnDecorator::getNumberOfDimensions ( void )
  1049. {
  1050. FTRACE(getNumberOfDimensions);
  1051. if ( !*gName )
  1052. return 0;
  1053. elif (( *gName >= '0' ) && ( *gName <= '9' ))
  1054. return (( *gName++ - '0' ) + 1 );
  1055. else
  1056. {
  1057. int dim = 0;
  1058. // Don't bother detecting overflow, it's not worth it
  1059. while ( *gName != '@' )
  1060. {
  1061. if ( !*gName )
  1062. return 0;
  1063. elif (( *gName >= 'A' ) && ( *gName <= 'P' ))
  1064. dim = ( dim << 4 ) + ( *gName - 'A' );
  1065. else
  1066. return -1;
  1067. gName++;
  1068. } // End of WHILE
  1069. // Ensure integrity, and return
  1070. if ( *gName++ != '@' )
  1071. return -1; // Should never get here
  1072. return dim;
  1073. } // End of ELIF else
  1074. } // End of "UnDecorator" FUNCTION "getNumberOfDimensions"
  1075. #if ( !VERS_PWB )
  1076. DName __near UnDecorator::getTemplateName ( void )
  1077. {
  1078. FTRACE(getTemplateName);
  1079. DName templateName = "template " + getZName ();
  1080. if ( !templateName.isEmpty ())
  1081. templateName += '<' + getArgumentList () + '>';
  1082. // Return the completed 'template-name'
  1083. return templateName;
  1084. } // End of "UnDecorator" FUNCTION "getTemplateName"
  1085. #endif // !VERS_PWB
  1086. #if defined(COFF)
  1087. //inline DName __near UnDecorator::composeDeclaration ( const DName & symbol )
  1088. //
  1089. // The above line was replaced by the line below because the COFF linker
  1090. // can't handle COMDATs
  1091. //
  1092. DName __near UnDecorator::composeDeclaration ( const DName & symbol )
  1093. #else
  1094. inline DName __near UnDecorator::composeDeclaration ( const DName & symbol )
  1095. #endif
  1096. {
  1097. FTRACE(composeDeclaration);
  1098. DName declaration;
  1099. unsigned int typeCode = getTypeEncoding ();
  1100. int symIsUDC = symbol.isUDC ();
  1101. // Handle bad typeCode's, or truncation
  1102. if ( TE_isbadtype ( typeCode ))
  1103. return DN_invalid;
  1104. elif ( TE_istruncated ( typeCode ))
  1105. return ( DN_truncated + symbol );
  1106. // This is a very complex part. The type of the declaration must be
  1107. // determined, and the exact composition must be dictated by this type.
  1108. // Is it any type of a function ?
  1109. // However, for ease of decoding, treat the 'localdtor' thunk as data, since
  1110. // its decoration is a function of the variable to which it belongs and not
  1111. // a usual function type of decoration.
  1112. #if ( NO_COMPILER_NAMES )
  1113. if ( TE_isthunk ( typeCode ))
  1114. return DN_invalid;
  1115. if ( TE_isfunction ( typeCode ))
  1116. #else // } elif !NO_COMPILER_NAMES {
  1117. if ( TE_isfunction ( typeCode ) && !( TE_isthunk ( typeCode ) && TE_islocaldtor ( typeCode )))
  1118. #endif // !NO_COMPILER_NAMES
  1119. {
  1120. // If it is based, then compose the 'based' prefix for the name
  1121. if ( TE_isbased ( typeCode ))
  1122. #if ( !VERS_PWB )
  1123. if ( doMSKeywords () && doAllocationModel ())
  1124. declaration = ' ' + getBasedType ();
  1125. else
  1126. #endif // !VERS_PWB
  1127. declaration |= getBasedType (); // Just lose the 'based-type'
  1128. #if ( !NO_COMPILER_NAMES )
  1129. // Check for some of the specially composed 'thunk's
  1130. if ( TE_isthunk ( typeCode ) && TE_isvcall ( typeCode ))
  1131. {
  1132. declaration += symbol + '{' + getCallIndex () + ',';
  1133. declaration += getVCallThunkType () + "}' ";
  1134. } // End of IF then
  1135. else
  1136. #endif // !NO_COMPILER_NAMES
  1137. {
  1138. DName vtorDisp;
  1139. DName adjustment;
  1140. DName thisType;
  1141. #if ( !NO_COMPILER_NAMES )
  1142. if ( TE_isthunk ( typeCode ))
  1143. {
  1144. if ( TE_isvtoradj ( typeCode ))
  1145. vtorDisp = getDisplacement ();
  1146. adjustment = getDisplacement ();
  1147. } // End of IF else
  1148. #endif // !NO_COMPILER_NAMES
  1149. // Get the 'this-type' for non-static function members
  1150. if ( TE_ismember ( typeCode ) && !TE_isstatic ( typeCode ))
  1151. #if ( !VERS_PWB )
  1152. if ( doThisTypes ())
  1153. thisType = getThisType ();
  1154. else
  1155. #endif // !VERS_PWB
  1156. thisType |= getThisType ();
  1157. #if ( !VERS_PWB )
  1158. if ( doMSKeywords ())
  1159. {
  1160. // Attach the calling convention
  1161. if ( doAllocationLanguage ())
  1162. declaration = getCallingConvention () + declaration; // What calling convention ?
  1163. else
  1164. declaration |= getCallingConvention (); // Just lose the 'calling-convention'
  1165. // Any model specifiers ?
  1166. if ( doAllocationModel ())
  1167. if ( TE_isnear ( typeCode ))
  1168. declaration = UScore ( TOK_nearSp ) + declaration;
  1169. elif ( TE_isfar ( typeCode ))
  1170. declaration = UScore ( TOK_farSp ) + declaration;
  1171. } // End of IF
  1172. else
  1173. #endif // !VERS_PWB
  1174. declaration |= getCallingConvention (); // Just lose the 'calling-convention'
  1175. // Now put them all together
  1176. if ( !symbol.isEmpty ())
  1177. if ( !declaration.isEmpty ()) // And the symbol name
  1178. declaration += ' ' + symbol;
  1179. else
  1180. declaration = symbol;
  1181. // Compose the return type, catching the UDC case
  1182. DName * pDeclarator = 0;
  1183. DName returnType;
  1184. if ( symIsUDC ) // Is the symbol a UDC operator ?
  1185. declaration += "`" + getReturnType () + "' ";
  1186. else
  1187. {
  1188. pDeclarator = gnew DName;
  1189. returnType = getReturnType ( pDeclarator );
  1190. } // End of IF else
  1191. #if ( !NO_COMPILER_NAMES )
  1192. // Add the displacements for virtual function thunks
  1193. if ( TE_isthunk ( typeCode ))
  1194. {
  1195. if ( TE_isvtoradj ( typeCode ))
  1196. declaration += "`vtordisp{" + vtorDisp + ',';
  1197. else
  1198. declaration += "`adjustor{";
  1199. declaration += adjustment + "}' ";
  1200. } // End of IF
  1201. #endif // !NO_COMPILER_NAMES
  1202. // Add the function argument prototype
  1203. declaration += '(' + getArgumentTypes () + ')';
  1204. // If this is a non-static member function, append the 'this' modifiers
  1205. if ( TE_ismember ( typeCode ) && !TE_isstatic ( typeCode ))
  1206. declaration += thisType;
  1207. // Add the 'throw' signature
  1208. #if ( !VERS_PWB )
  1209. if ( doThrowTypes ())
  1210. declaration += getThrowTypes ();
  1211. else
  1212. #endif // !VERS_PWB
  1213. declaration |= getThrowTypes (); // Just lose the 'throw-types'
  1214. #if ( !VERS_PWB )
  1215. // If it has a declarator, then insert it into the declaration,
  1216. // sensitive to the return type composition
  1217. if ( doFunctionReturns () && pDeclarator )
  1218. {
  1219. *pDeclarator = declaration;
  1220. declaration = returnType;
  1221. } // End of IF
  1222. #endif // !VERS_PWB
  1223. } // End of IF else
  1224. } // End of IF then
  1225. else
  1226. {
  1227. declaration += symbol;
  1228. // Catch the special handling cases
  1229. #if ( !NO_COMPILER_NAMES )
  1230. if ( TE_isvftable ( typeCode ))
  1231. return getVfTableType ( declaration );
  1232. elif ( TE_isvbtable ( typeCode ))
  1233. return getVbTableType ( declaration );
  1234. elif ( TE_isguard ( typeCode ))
  1235. return ( declaration + '{' + getGuardNumber () + "}'" );
  1236. elif ( TE_isthunk ( typeCode ) && TE_islocaldtor ( typeCode ))
  1237. declaration += "`local static destructor helper'";
  1238. elif ( TE_ismetaclass ( typeCode ))
  1239. #pragma message ( "NYI: Meta Class" )
  1240. #else // } elif NO_COMPILER_NAMES {
  1241. if ( TE_isvftable ( typeCode )
  1242. || TE_isvbtable ( typeCode )
  1243. || TE_isguard ( typeCode )
  1244. || TE_ismetaclass ( typeCode ))
  1245. #endif // NO_COMPILER_NAMES
  1246. return DN_invalid;
  1247. // All others are decorated as data symbols
  1248. declaration = getExternalDataType ( declaration );
  1249. } // End of IF else
  1250. #if ( !VERS_PWB )
  1251. // Prepend the 'virtual' and 'static' attributes for members
  1252. if ( TE_ismember ( typeCode ))
  1253. {
  1254. if ( doMemberTypes ())
  1255. {
  1256. if ( TE_isstatic ( typeCode ))
  1257. declaration = "static " + declaration;
  1258. if ( TE_isvirtual ( typeCode ) || ( TE_isthunk ( typeCode ) && ( TE_isvtoradj ( typeCode ) || TE_isadjustor ( typeCode ))))
  1259. declaration = "virtual " + declaration;
  1260. } // End of IF
  1261. // Prepend the access specifiers
  1262. if ( doAccessSpecifiers ())
  1263. if ( TE_isprivate ( typeCode ))
  1264. declaration = "private: " + declaration;
  1265. elif ( TE_isprotected ( typeCode ))
  1266. declaration = "protected: " + declaration;
  1267. elif ( TE_ispublic ( typeCode ))
  1268. declaration = "public: " + declaration;
  1269. } // End of IF
  1270. #endif // !VERS_PWB
  1271. #if ( !NO_COMPILER_NAMES )
  1272. // If it is a thunk, mark it appropriately
  1273. if ( TE_isthunk ( typeCode ))
  1274. declaration = "[thunk]:" + declaration;
  1275. #endif // !NO_COMPILER_NAMES
  1276. // Return the composed declaration
  1277. return declaration;
  1278. } // End of "UnDecorator" FUNCTION "composeDeclaration"
  1279. inline int __near UnDecorator::getTypeEncoding ( void )
  1280. {
  1281. FTRACE(getTypeEncoding);
  1282. unsigned int typeCode = 0u;
  1283. // Strip any leading '_' which indicates that it is based
  1284. if ( *gName == '_' )
  1285. {
  1286. TE_setisbased ( typeCode );
  1287. gName++;
  1288. } // End of IF
  1289. // Now handle the code proper :-
  1290. if (( *gName >= 'A' ) && ( *gName <= 'Z' )) // Is it some sort of function ?
  1291. {
  1292. int code = *gName++ - 'A';
  1293. // Now determine the function type
  1294. TE_setisfunction ( typeCode ); // All of them are functions ?
  1295. // Determine the calling model
  1296. if ( code & TE_far )
  1297. TE_setisfar ( typeCode );
  1298. else
  1299. TE_setisnear ( typeCode );
  1300. // Is it a member function or not ?
  1301. if ( code < TE_external )
  1302. {
  1303. // Record the fact that it is a member
  1304. TE_setismember ( typeCode );
  1305. // What access permissions does it have
  1306. switch ( code & TE_access )
  1307. {
  1308. case TE_private:
  1309. TE_setisprivate ( typeCode );
  1310. break;
  1311. case TE_protect:
  1312. TE_setisprotected ( typeCode );
  1313. break;
  1314. case TE_public:
  1315. TE_setispublic ( typeCode );
  1316. break;
  1317. default:
  1318. TE_setisbadtype ( typeCode );
  1319. return typeCode;
  1320. } // End of SWITCH
  1321. // What type of a member function is it ?
  1322. switch ( code & TE_adjustor )
  1323. {
  1324. case TE_adjustor:
  1325. TE_setisadjustor ( typeCode );
  1326. break;
  1327. case TE_virtual:
  1328. TE_setisvirtual ( typeCode );
  1329. break;
  1330. case TE_static:
  1331. TE_setisstatic ( typeCode );
  1332. break;
  1333. case TE_member:
  1334. break;
  1335. default:
  1336. TE_setisbadtype ( typeCode );
  1337. return typeCode;
  1338. } // End of SWITCH
  1339. } // End of IF
  1340. } // End of IF then
  1341. elif ( *gName == '$' ) // Extended set ? Special handling
  1342. {
  1343. // What type of symbol is it ?
  1344. switch ( *( ++gName ))
  1345. {
  1346. case 'A': // A destructor helper for a local static ?
  1347. TE_setislocaldtor ( typeCode );
  1348. break;
  1349. case 'B': // A VCall-thunk ?
  1350. TE_setisvcall ( typeCode );
  1351. break;
  1352. case 0:
  1353. TE_setistruncated ( typeCode );
  1354. break;
  1355. case '0':
  1356. case '1':
  1357. case '2':
  1358. case '3':
  1359. case '4':
  1360. case '5': // Construction displacement adjustor thunks
  1361. {
  1362. int code = *gName - '0';
  1363. // Set up the principal type information
  1364. TE_setisfunction ( typeCode );
  1365. TE_setismember ( typeCode );
  1366. TE_setisvtoradj ( typeCode );
  1367. // Is it 'near' or 'far' ?
  1368. if ( code & TE_far )
  1369. TE_setisfar ( typeCode );
  1370. else
  1371. TE_setisnear ( typeCode );
  1372. // What type of access protection ?
  1373. switch ( code & TE_access_vadj )
  1374. {
  1375. case TE_private_vadj:
  1376. TE_setisprivate ( typeCode );
  1377. break;
  1378. case TE_protect_vadj:
  1379. TE_setisprotected ( typeCode );
  1380. break;
  1381. case TE_public_vadj:
  1382. TE_setispublic ( typeCode );
  1383. break;
  1384. default:
  1385. TE_setisbadtype ( typeCode );
  1386. return typeCode;
  1387. } // End of SWITCH
  1388. } // End of CASE '0,1,2,3,4,5'
  1389. break;
  1390. default:
  1391. TE_setisbadtype ( typeCode );
  1392. return typeCode;
  1393. } // End of SWITCH
  1394. // Advance past the code character
  1395. gName++;
  1396. } // End of ELIF then
  1397. elif (( *gName >= TE_static_d ) && ( *gName <= TE_metatype )) // Non function decorations ?
  1398. {
  1399. int code = *gName++;
  1400. TE_setisdata ( typeCode );
  1401. // What type of symbol is it ?
  1402. switch ( code )
  1403. {
  1404. case ( TE_static_d | TE_private_d ):
  1405. TE_setisstatic ( typeCode );
  1406. TE_setisprivate ( typeCode );
  1407. break;
  1408. case ( TE_static_d | TE_protect_d ):
  1409. TE_setisstatic ( typeCode );
  1410. TE_setisprotected ( typeCode );
  1411. break;
  1412. case ( TE_static_d | TE_public_d ):
  1413. TE_setisstatic ( typeCode );
  1414. TE_setispublic ( typeCode );
  1415. break;
  1416. case TE_global:
  1417. TE_setisglobal ( typeCode );
  1418. break;
  1419. #if ( !VERS_PWB )
  1420. case TE_guard:
  1421. TE_setisguard ( typeCode );
  1422. break;
  1423. case TE_local:
  1424. TE_setislocal ( typeCode );
  1425. break;
  1426. case TE_vftable:
  1427. TE_setisvftable ( typeCode );
  1428. break;
  1429. case TE_vbtable:
  1430. TE_setisvbtable ( typeCode );
  1431. break;
  1432. case TE_metatype:
  1433. #pragma message ( "NYI: MetaClass Information" )
  1434. #else // } elif VERS_PWB {
  1435. case TE_guard:
  1436. case TE_local:
  1437. case TE_vftable:
  1438. case TE_vbtable:
  1439. case TE_metatype:
  1440. #endif // VERS_PWB
  1441. default:
  1442. TE_setisbadtype ( typeCode );
  1443. return typeCode;
  1444. } // End of SWITCH
  1445. } // End of ELIF then
  1446. elif ( *gName )
  1447. TE_setisbadtype ( typeCode );
  1448. else
  1449. TE_setistruncated ( typeCode );
  1450. // Return the composed type code
  1451. return typeCode;
  1452. } // End of "UnDecorator" FUNCTION "getTypeEncoding"
  1453. DName __near UnDecorator::getBasedType ( void )
  1454. {
  1455. FTRACE(getBasedType);
  1456. #if ( !VERS_PWB )
  1457. DName basedDecl ( UScore ( TOK_basedLp ));
  1458. #else // } elif VERS_PWB {
  1459. DName basedDecl;
  1460. #endif // VERS_PWB
  1461. // What type of 'based' is it ?
  1462. if ( *gName )
  1463. {
  1464. switch ( *gName++ )
  1465. {
  1466. #if ( !VERS_PWB )
  1467. case BT_segname:
  1468. basedDecl += UScore ( TOK_segnameLpQ ) + getSegmentName () + "\")";
  1469. break;
  1470. case BT_segment:
  1471. basedDecl += DName ( "NYI:" ) + UScore ( TOK_segment );
  1472. break;
  1473. case BT_void:
  1474. basedDecl += "void";
  1475. break;
  1476. case BT_self:
  1477. basedDecl += UScore ( TOK_self );
  1478. break;
  1479. case BT_nearptr:
  1480. basedDecl += DName ( "NYI:" ) + UScore ( TOK_nearP );
  1481. break;
  1482. case BT_farptr:
  1483. basedDecl += DName ( "NYI:" ) + UScore ( TOK_farP );
  1484. break;
  1485. case BT_hugeptr:
  1486. basedDecl += DName ( "NYI:" ) + UScore ( TOK_hugeP );
  1487. break;
  1488. case BT_segaddr:
  1489. basedDecl += "NYI:<segment-address-of-variable>";
  1490. break;
  1491. #else // } elif VERS_PWB {
  1492. case BT_segname:
  1493. basedDecl |= getZName ();
  1494. break;
  1495. case BT_segment:
  1496. case BT_void:
  1497. case BT_self:
  1498. case BT_nearptr:
  1499. case BT_farptr:
  1500. case BT_hugeptr:
  1501. case BT_segaddr:
  1502. break;
  1503. #endif // VERS_PWB
  1504. case BT_basedptr:
  1505. #pragma message ( "NOTE: Reserved. Based pointer to based pointer" )
  1506. return DN_invalid;
  1507. } // End of SWITCH
  1508. } // End of IF else
  1509. else
  1510. basedDecl += DN_truncated;
  1511. #if ( !VERS_PWB )
  1512. // Close the based syntax
  1513. basedDecl += ") ";
  1514. #endif // !VERS_PWB
  1515. // Return completed based declaration
  1516. return basedDecl;
  1517. } // End of "UnDecorator" FUNCTION "getBasedType"
  1518. DName __near UnDecorator::getECSUName ( void )
  1519. {
  1520. FTRACE(getECSUName);
  1521. DName ecsuName;
  1522. // Get the beginning of the name
  1523. if ( *gName == '?' )
  1524. {
  1525. #if ( !VERS_PWB )
  1526. gName++;
  1527. ecsuName = getTemplateName ();
  1528. #else // } elif VERS_PWB {
  1529. return DN_invalid;
  1530. #endif // VERS_PWB
  1531. } // End of IF then
  1532. else
  1533. ecsuName = getZName ();
  1534. // Now the scope (if any)
  1535. if (( ecsuName.status () == DN_valid ) && *gName && ( *gName != '@' ))
  1536. ecsuName = getScope () + "::" + ecsuName;
  1537. // Skip the trailing '@'
  1538. if ( *gName == '@' )
  1539. gName++;
  1540. elif ( *gName )
  1541. ecsuName = DN_invalid;
  1542. elif ( ecsuName.isEmpty ())
  1543. ecsuName = DN_truncated;
  1544. else
  1545. ecsuName = DName ( DN_truncated ) + "::" + ecsuName;
  1546. // And return the complete name
  1547. return ecsuName;
  1548. } // End of "UnDecorator" FUNCTION "getECSUName"
  1549. inline DName __near UnDecorator::getEnumName ( void )
  1550. {
  1551. FTRACE(getEnumName);
  1552. #if ( !VERS_PWB )
  1553. DName ecsuName;
  1554. #endif // !VERS_PWB
  1555. if ( *gName )
  1556. {
  1557. #if ( !VERS_PWB )
  1558. // What type of an 'enum' is it ?
  1559. switch ( *gName )
  1560. {
  1561. case ET_schar:
  1562. case ET_uchar:
  1563. ecsuName = "char ";
  1564. break;
  1565. case ET_sshort:
  1566. case ET_ushort:
  1567. ecsuName = "short ";
  1568. break;
  1569. case ET_sint:
  1570. break;
  1571. case ET_uint:
  1572. ecsuName = "int ";
  1573. break;
  1574. case ET_slong:
  1575. case ET_ulong:
  1576. ecsuName = "long ";
  1577. break;
  1578. default:
  1579. return DN_invalid;
  1580. } // End of SWITCH
  1581. // Add the 'unsigned'ness if appropriate
  1582. switch ( *gName++ )
  1583. {
  1584. case ET_uchar:
  1585. case ET_ushort:
  1586. case ET_uint:
  1587. case ET_ulong:
  1588. ecsuName = "unsigned " + ecsuName;
  1589. break;
  1590. } // End of SWITCH
  1591. // Now return the composed name
  1592. return ecsuName + getECSUName ();
  1593. #else // } elif VERS_PWB {
  1594. if ( *gName++ == ET_sint )
  1595. return getECSUName ();
  1596. else
  1597. return DN_invalid;
  1598. #endif // VERS_PWB
  1599. } // End of IF then
  1600. else
  1601. return DN_truncated;
  1602. } // End of "UnDecorator" FUNCTION "getEnumName"
  1603. DName __near UnDecorator::getCallingConvention ( void )
  1604. {
  1605. FTRACE(getCallingConvention);
  1606. if ( *gName )
  1607. {
  1608. unsigned int callCode = ((unsigned int)*gName++ ) - 'A';
  1609. // What is the primary calling convention
  1610. if (( callCode <= CC_interrupt ))
  1611. {
  1612. #if ( !VERS_PWB )
  1613. DName callType;
  1614. // Now, what type of 'calling-convention' is it, 'interrupt' is special ?
  1615. if ( doMSKeywords ())
  1616. if ( callCode == CC_interrupt )
  1617. callType = UScore ( TOK_interrupt );
  1618. else
  1619. {
  1620. switch ( callCode & ~CC_saveregs )
  1621. {
  1622. case CC_cdecl:
  1623. callType = UScore ( TOK_cdecl );
  1624. break;
  1625. case CC_pascal:
  1626. callType = UScore ( TOK_pascal );
  1627. break;
  1628. case CC_syscall:
  1629. callType = UScore ( TOK_syscall );
  1630. break;
  1631. case CC_stdcall:
  1632. callType = UScore ( TOK_stdcall );
  1633. break;
  1634. case CC_fastcall:
  1635. callType = UScore ( TOK_fastcall );
  1636. break;
  1637. } // End of SWITCH
  1638. // Has it also got 'saveregs' marked ?
  1639. if ( callCode & CC_saveregs )
  1640. callType += ' ' + UScore ( TOK_saveregs );
  1641. } // End of IF else
  1642. // And return
  1643. return callType;
  1644. #else // } elif VERS_PWB {
  1645. return DN_valid;
  1646. #endif // VERS_PWB
  1647. } // End of IF then
  1648. else
  1649. return DN_invalid;
  1650. } // End of IF then
  1651. else
  1652. return DN_truncated;
  1653. } // End of "UnDecorator" FUNCTION "getCallingConvention"
  1654. DName __near UnDecorator::getReturnType ( DName * pDeclarator )
  1655. {
  1656. FTRACE(getReturnType);
  1657. if ( *gName == '@' ) // Return type for constructors and destructors ?
  1658. {
  1659. gName++;
  1660. return DName ( pDeclarator );
  1661. } // End of IF then
  1662. else
  1663. return getDataType ( pDeclarator );
  1664. } // End of "UnDecorator" FUNCTION "getReturnType"
  1665. DName __near UnDecorator::getDataType ( DName * pDeclarator )
  1666. {
  1667. FTRACE(getDataType);
  1668. DName superType ( pDeclarator );
  1669. // What type is it ?
  1670. switch ( *gName )
  1671. {
  1672. case 0:
  1673. return ( DN_truncated + superType );
  1674. case DT_void:
  1675. gName++;
  1676. if ( superType.isEmpty ())
  1677. return "void";
  1678. else
  1679. return "void " + superType;
  1680. case '?':
  1681. {
  1682. int ecsuMods;
  1683. gName++; // Skip the '?'
  1684. ecsuMods = getECSUDataIndirectType ();
  1685. superType = getECSUDataType ( ecsuMods ) + ' ' + superType;
  1686. return superType;
  1687. } // End of CASE '?'
  1688. default:
  1689. return getPrimaryDataType ( superType );
  1690. } // End of SWITCH
  1691. } // End of "UnDecorator" FUNCTION "getDataType"
  1692. DName __near UnDecorator::getPrimaryDataType ( const DName & superType )
  1693. {
  1694. FTRACE(getPrimaryDataType);
  1695. DName cvType;
  1696. switch ( *gName )
  1697. {
  1698. case 0:
  1699. return ( DN_truncated + superType );
  1700. case PDT_volatileReference:
  1701. cvType = "volatile";
  1702. if ( !superType.isEmpty ())
  1703. cvType += ' ';
  1704. // No break
  1705. case PDT_reference:
  1706. {
  1707. DName super ( superType );
  1708. gName++;
  1709. return getReferenceType ( cvType, super.setPtrRef ());
  1710. } // End of CASE 'PDT_reference'
  1711. default:
  1712. return getBasicDataType ( superType );
  1713. } // End of SWITCH
  1714. } // End of "UnDecorator" FUNCTION "getPrimaryDataType"
  1715. DName __near UnDecorator::getArgumentTypes ( void )
  1716. {
  1717. FTRACE(getArgumentTypes);
  1718. switch ( *gName )
  1719. {
  1720. case AT_ellipsis:
  1721. return ( gName++, "..." );
  1722. case AT_void:
  1723. #if ( !VERS_PWB )
  1724. return ( gName++, "void" );
  1725. #else // } elif VERS_PWB {
  1726. return ( gName++, DName ());
  1727. #endif // VERS_PWB
  1728. default:
  1729. {
  1730. DName arguments ( getArgumentList ());
  1731. // Now, is it a varargs function or not ?
  1732. if ( arguments.status () == DN_valid )
  1733. switch ( *gName )
  1734. {
  1735. case 0:
  1736. return arguments;
  1737. case AT_ellipsis:
  1738. return ( gName++, arguments + ",..." );
  1739. case AT_endoflist:
  1740. return ( gName++, arguments );
  1741. default:
  1742. return DN_invalid;
  1743. } // End of SWITCH
  1744. else
  1745. return arguments;
  1746. } // End of DEFAULT
  1747. } // End of SWITCH
  1748. } // End of "UnDecorator" FUNCTION "getArgumentTypes"
  1749. inline_pwb DName __near UnDecorator::getArgumentList ( void )
  1750. {
  1751. FTRACE(getArgumentList);
  1752. int first = TRUE;
  1753. DName aList;
  1754. while (( aList.status () == DN_valid ) && ( *gName != AT_endoflist ) && ( *gName != AT_ellipsis ))
  1755. {
  1756. // Insert the argument list separator if not the first argument
  1757. if ( first )
  1758. first = FALSE;
  1759. else
  1760. aList += ',';
  1761. // Get the individual argument type
  1762. if ( *gName )
  1763. {
  1764. int argIndex = *gName - '0';
  1765. // Handle 'argument-replicators', otherwise a new argument type
  1766. if (( argIndex >= 0 ) && ( argIndex <= 9 ))
  1767. {
  1768. gName++; // Skip past the replicator
  1769. // Append to the argument list
  1770. aList += ( *pArgList )[ argIndex ];
  1771. } // End of IF then
  1772. else
  1773. {
  1774. // Extract the 'argument' type
  1775. DName arg ( getPrimaryDataType ( DName ()));
  1776. // Add it to the current list of 'argument's
  1777. if ( !pArgList->isFull ())
  1778. *pArgList += arg;
  1779. // Append to the argument list
  1780. aList += arg;
  1781. } // End of IF else
  1782. } // End of IF then
  1783. else
  1784. {
  1785. aList += DN_truncated;
  1786. break;
  1787. } // End of IF else
  1788. } // End of WHILE
  1789. // Return the completed argument list
  1790. return aList;
  1791. } // End of "UnDecorator" FUNCTION "getArgumentList"
  1792. DName __near UnDecorator::getThrowTypes ( void )
  1793. {
  1794. FTRACE(getThrowTypes);
  1795. if ( *gName )
  1796. #if ( !VERS_PWB )
  1797. if ( *gName == AT_ellipsis ) // Handle ellipsis here to suppress the 'throw' signature
  1798. return ( gName++, DName ());
  1799. else
  1800. return ( " throw(" + getArgumentTypes () + ')' );
  1801. else
  1802. return ( DName ( " throw(" ) + DN_truncated + ')' );
  1803. #else // } elif VERS_PWB {
  1804. if ( *gName++ == AT_ellipsis )
  1805. return DName ();
  1806. else
  1807. return DN_invalid;
  1808. else
  1809. return DN_truncated;
  1810. #endif // VERS_PWB
  1811. } // End of "UnDecorator" FUNCTION "getThrowTypes"
  1812. DName __near UnDecorator::getBasicDataType ( const DName & superType )
  1813. {
  1814. FTRACE(getBasicDataType);
  1815. if ( *gName )
  1816. {
  1817. unsigned char bdtCode = *gName++;
  1818. int pCvCode = -1;
  1819. DName basicDataType;
  1820. // Extract the principal type information itself, and validate the codes
  1821. switch ( bdtCode )
  1822. {
  1823. case BDT_schar:
  1824. case BDT_char:
  1825. case ( BDT_char | BDT_unsigned ):
  1826. basicDataType = "char";
  1827. break;
  1828. case BDT_short:
  1829. case ( BDT_short | BDT_unsigned ):
  1830. basicDataType = "short";
  1831. break;
  1832. case BDT_int:
  1833. case ( BDT_int | BDT_unsigned ):
  1834. basicDataType = "int";
  1835. break;
  1836. case BDT_long:
  1837. case ( BDT_long | BDT_unsigned ):
  1838. basicDataType = "long";
  1839. break;
  1840. case BDT_segment:
  1841. #if ( !VERS_PWB )
  1842. basicDataType = UScore ( TOK_segment );
  1843. #else // } elif VERS_PWB {
  1844. basicDataType = "__segment";
  1845. #endif // VERS_PWB
  1846. break;
  1847. case BDT_float:
  1848. basicDataType = "float";
  1849. break;
  1850. case BDT_longdouble:
  1851. basicDataType = "long ";
  1852. // No break
  1853. case BDT_double:
  1854. basicDataType += "double";
  1855. break;
  1856. case BDT_pointer:
  1857. case ( BDT_pointer | BDT_const ):
  1858. case ( BDT_pointer | BDT_volatile ):
  1859. case ( BDT_pointer | BDT_const | BDT_volatile ):
  1860. pCvCode = ( bdtCode & ( BDT_const | BDT_volatile ));
  1861. break;
  1862. default:
  1863. gName--; // Backup, since 'ecsu-data-type' does it's own decoding
  1864. basicDataType = getECSUDataType ();
  1865. if ( basicDataType.isEmpty ())
  1866. return basicDataType;
  1867. break;
  1868. } // End of SWITCH
  1869. // What type of basic data type composition is involved ?
  1870. if ( pCvCode == -1 ) // Simple ?
  1871. {
  1872. // Determine the 'signed/unsigned'ness
  1873. switch ( bdtCode )
  1874. {
  1875. case ( BDT_char | BDT_unsigned ):
  1876. case ( BDT_short | BDT_unsigned ):
  1877. case ( BDT_int | BDT_unsigned ):
  1878. case ( BDT_long | BDT_unsigned ):
  1879. basicDataType = "unsigned " + basicDataType;
  1880. break;
  1881. case BDT_schar:
  1882. basicDataType = "signed " + basicDataType;
  1883. break;
  1884. } // End of SWITCH
  1885. // Add the indirection type to the type
  1886. if ( !superType.isEmpty ())
  1887. basicDataType += ' ' + superType;
  1888. // And return the completed type
  1889. return basicDataType;
  1890. } // End of IF then
  1891. else
  1892. {
  1893. DName cvType;
  1894. DName super ( superType );
  1895. // Is it 'const/volatile' qualified ?
  1896. if ( pCvCode & BDT_const )
  1897. {
  1898. cvType = "const";
  1899. if ( pCvCode & BDT_volatile )
  1900. cvType += " volatile";
  1901. } // End of IF then
  1902. elif ( pCvCode & BDT_volatile )
  1903. cvType = "volatile";
  1904. // Construct the appropriate pointer type declaration
  1905. return getPointerType ( cvType, super.setPtrRef ());
  1906. } // End of IF else
  1907. } // End of IF then
  1908. else
  1909. return ( DN_truncated + superType );
  1910. } // End of "UnDecorator" FUNCTION "getBasicDataType"
  1911. DName __near UnDecorator::getECSUDataType ( int ecsuMods )
  1912. {
  1913. FTRACE(getECSUDataType);
  1914. DName ecsuDataType;
  1915. // Get the 'model' modifiers if applicable
  1916. if ( ecsuMods )
  1917. if ( ecsuMods == ECSU_invalid )
  1918. return DN_invalid;
  1919. elif ( ecsuMods == ECSU_truncated )
  1920. ecsuDataType = DN_truncated;
  1921. #if ( !VERS_PWB )
  1922. else
  1923. switch ( ecsuMods & ECSU_modelmask )
  1924. {
  1925. case ECSU_near:
  1926. if ( doMSKeywords () && doReturnUDTModel ())
  1927. ecsuDataType = UScore ( TOK_nearSp );
  1928. break;
  1929. case ECSU_far:
  1930. if ( doMSKeywords () && doReturnUDTModel ())
  1931. ecsuDataType = UScore ( TOK_farSp );
  1932. break;
  1933. case ECSU_huge:
  1934. if ( doMSKeywords () && doReturnUDTModel ())
  1935. ecsuDataType = UScore ( TOK_hugeSp );
  1936. break;
  1937. case ECSU_based:
  1938. if ( doMSKeywords () && doReturnUDTModel ())
  1939. ecsuDataType = getBasedType ();
  1940. else
  1941. ecsuDataType |= getBasedType (); // Just lose the 'based-type'
  1942. break;
  1943. } // End of SWITCH
  1944. #else // } elif VERS_PWB {
  1945. elif (( ecsuMods & ECSU_modelmask ) == ECSU_based )
  1946. ecsuDataType |= getBasedType ();
  1947. #endif // VERS_PWB
  1948. // Extract the principal type information itself, and validate the codes
  1949. switch ( *gName++ )
  1950. {
  1951. case 0:
  1952. gName--; // Backup to permit later error recovery to work safely
  1953. return "`unknown ecsu'" + ecsuDataType + DN_truncated;
  1954. case BDT_union:
  1955. if ( 1 ) // Non-redundant control flow trick
  1956. ecsuDataType = "union " + ecsuDataType;
  1957. else
  1958. case BDT_struct:
  1959. if ( 1 ) // Non-redundant control flow trick
  1960. ecsuDataType = "struct " + ecsuDataType;
  1961. else
  1962. case BDT_class:
  1963. if ( 1 ) // Non-redundant control flow trick
  1964. ecsuDataType = "class " + ecsuDataType;
  1965. // Get the UDT 'const/volatile' modifiers if applicable
  1966. // Get the 'class/struct/union' name
  1967. ecsuDataType += getECSUName ();
  1968. break;
  1969. case BDT_enum:
  1970. ecsuDataType = "enum " + ecsuDataType + getEnumName ();
  1971. break;
  1972. default:
  1973. return DN_invalid;
  1974. } // End of SWITCH
  1975. // And return the formed 'ecsu-data-type'
  1976. return ecsuDataType;
  1977. } // End of "UnDecorator" FUNCTION "getECSUDataType"
  1978. DName __near UnDecorator::getPtrRefType ( const DName & cvType, const DName & superType, int isPtr )
  1979. {
  1980. FTRACE(getPtrRefType);
  1981. // Doubles up as 'pointer-type' and 'reference-type'
  1982. if ( *gName )
  1983. if ( IT_isfunction ( *gName )) // Is it a function or data indirection ?
  1984. {
  1985. // Since I haven't coded a discrete 'function-type', both
  1986. // 'function-indirect-type' and 'function-type' are implemented
  1987. // inline under this condition.
  1988. int fitCode = *gName++ - '6';
  1989. if ( fitCode == ( '_' - '6' ))
  1990. {
  1991. if ( *gName )
  1992. {
  1993. fitCode = *gName++ - 'A' + FIT_based;
  1994. if (( fitCode < FIT_based ) || ( fitCode > ( FIT_based | FIT_far | FIT_member )))
  1995. fitCode = -1;
  1996. } // End of IF then
  1997. else
  1998. return ( DN_truncated + superType );
  1999. } // End of IF then
  2000. elif (( fitCode < FIT_near ) || ( fitCode > ( FIT_far | FIT_member )))
  2001. fitCode = -1;
  2002. // Return if invalid name
  2003. if ( fitCode == -1 )
  2004. return DN_invalid;
  2005. // Otherwise, what are the function indirect attributes
  2006. DName thisType;
  2007. DName fitType = ( isPtr ? '*' : '&' );
  2008. if ( !cvType.isEmpty () && ( superType.isEmpty () || superType.isPtrRef ()))
  2009. fitType += cvType;
  2010. if ( !superType.isEmpty ())
  2011. fitType += superType;
  2012. // Is it a pointer to member function ?
  2013. if ( fitCode & FIT_member )
  2014. {
  2015. fitType = "::" + fitType;
  2016. if ( *gName )
  2017. fitType = ' ' + getScope ();
  2018. else
  2019. fitType = DN_truncated + fitType;
  2020. if ( *gName )
  2021. if ( *gName == '@' )
  2022. gName++;
  2023. else
  2024. return DN_invalid;
  2025. else
  2026. return ( DN_truncated + fitType );
  2027. #if ( !VERS_PWB )
  2028. if ( doThisTypes ())
  2029. thisType = getThisType ();
  2030. else
  2031. #endif // !VERS_PWB
  2032. thisType |= getThisType ();
  2033. } // End of IF
  2034. // Is it a based allocated function ?
  2035. if ( fitCode & FIT_based )
  2036. #if ( !VERS_PWB )
  2037. if ( doMSKeywords ())
  2038. fitType = ' ' + getBasedType () + fitType;
  2039. else
  2040. #endif // !VERS_PWB
  2041. fitType |= getBasedType (); // Just lose the 'based-type'
  2042. // Get the 'calling-convention'
  2043. #if ( !VERS_PWB )
  2044. if ( doMSKeywords ())
  2045. {
  2046. fitType = getCallingConvention () + fitType;
  2047. // Is it a near or far function pointer
  2048. fitType = UScore ((( fitCode & FIT_far ) ? TOK_farSp : TOK_nearSp )) + fitType;
  2049. } // End of IF then
  2050. else
  2051. #endif // !VERS_PWB
  2052. fitType |= getCallingConvention (); // Just lose the 'calling-convention'
  2053. // Parenthesise the indirection component, and work on the rest
  2054. fitType = '(' + fitType + ')';
  2055. // Get the rest of the 'function-type' pieces
  2056. DName * pDeclarator = gnew DName;
  2057. DName returnType ( getReturnType ( pDeclarator ));
  2058. fitType += '(' + getArgumentTypes () + ')';
  2059. #if ( !VERS_PWB )
  2060. if ( doThisTypes () && ( fitCode & FIT_member ))
  2061. fitType += thisType;
  2062. if ( doThrowTypes ())
  2063. fitType += getThrowTypes ();
  2064. else
  2065. #endif // !VERS_PWB
  2066. fitType |= getThrowTypes (); // Just lose the 'throw-types'
  2067. // Now insert the indirected declarator, catch the allocation failure here
  2068. if ( pDeclarator )
  2069. *pDeclarator = fitType;
  2070. else
  2071. return ERROR;
  2072. // And return the composed function type (now in 'returnType' )
  2073. return returnType;
  2074. } // End of IF then
  2075. else
  2076. {
  2077. // Otherwise, it is either a pointer or a reference to some data type
  2078. DName innerType ( getDataIndirectType ( superType, ( isPtr ? '*' : '&' ), cvType ));
  2079. return getPtrRefDataType ( innerType, isPtr );
  2080. } // End of IF else
  2081. else
  2082. {
  2083. DName trunk ( DN_truncated );
  2084. trunk += ( isPtr ? '*' : '&' );
  2085. if ( !cvType.isEmpty ())
  2086. trunk += cvType;
  2087. if ( !superType.isEmpty ())
  2088. {
  2089. if ( !cvType.isEmpty ())
  2090. trunk += ' ';
  2091. trunk += superType;
  2092. } // End of IF
  2093. return trunk;
  2094. } // End of IF else
  2095. } // End of "UnDecorator" FUNCTION "getPtrRefType"
  2096. DName __near UnDecorator::getDataIndirectType ( const DName & superType, char prType, const DName & cvType, int thisFlag )
  2097. {
  2098. FTRACE(getDataIndirectType);
  2099. if ( *gName )
  2100. {
  2101. unsigned int ditCode = ( *gName - (( *gName >= 'A' ) ? (unsigned int)'A': (unsigned int)( '0' - 26 )));
  2102. gName++; // Skip to next character in name
  2103. // Is it a valid 'data-indirection-type' ?
  2104. if (( ditCode <= ( DIT_const | DIT_volatile | DIT_modelmask | DIT_member )))
  2105. {
  2106. DName ditType ( prType );
  2107. // If it is a member, then these attributes immediately precede the indirection token
  2108. if ( ditCode & DIT_member )
  2109. {
  2110. // If it is really 'this-type', then it cannot be any form of pointer to member
  2111. if ( thisFlag )
  2112. return DN_invalid;
  2113. // Otherwise, extract the scope for the PM
  2114. ditType = "::" + ditType;
  2115. if ( *gName )
  2116. ditType = ' ' + getScope ();
  2117. else
  2118. ditType = DN_truncated + ditType;
  2119. // Now skip the scope terminator
  2120. if ( !*gName )
  2121. ditType += DN_truncated;
  2122. elif ( *gName++ != '@' )
  2123. return DN_invalid;
  2124. } // End of IF
  2125. #if ( !VERS_PWB )
  2126. // Add the 'model' attributes (prefixed) as appropriate
  2127. if ( doMSKeywords ())
  2128. switch ( ditCode & DIT_modelmask )
  2129. {
  2130. case DIT_near:
  2131. ditType = UScore ( TOK_near ) + ditType;
  2132. break;
  2133. case DIT_far:
  2134. ditType = UScore ( TOK_far ) + ditType;
  2135. break;
  2136. case DIT_huge:
  2137. ditType = UScore ( TOK_huge ) + ditType;
  2138. break;
  2139. case DIT_based:
  2140. // The 'this-type' can never be 'based'
  2141. if ( thisFlag )
  2142. return DN_invalid;
  2143. ditType = getBasedType () + ditType;
  2144. break;
  2145. } // End of SWITCH
  2146. elif (( ditCode & DIT_modelmask ) == DIT_based )
  2147. #else // } elif VERS_PWB {
  2148. if (( ditCode & DIT_modelmask ) == DIT_based )
  2149. #endif // VERS_PWB
  2150. ditType |= getBasedType (); // Just lose the 'based-type'
  2151. // Handle the 'const' and 'volatile' attributes
  2152. if ( ditCode & DIT_volatile )
  2153. ditType = "volatile " + ditType;
  2154. if ( ditCode & DIT_const )
  2155. ditType = "const " + ditType;
  2156. // Append the supertype, if not 'this-type'
  2157. if ( !thisFlag )
  2158. if ( !superType.isEmpty ())
  2159. {
  2160. // Is the super context included 'cv' information, ensure that it is added appropriately
  2161. if ( superType.isPtrRef () || cvType.isEmpty ())
  2162. ditType += ' ' + superType;
  2163. else
  2164. ditType += ' ' + cvType + ' ' + superType;
  2165. } // End of IF then
  2166. elif ( !cvType.isEmpty ())
  2167. ditType += ' ' + cvType;
  2168. // Finally, return the composed 'data-indirection-type' (with embedded sub-type)
  2169. return ditType;
  2170. } // End of IF then
  2171. else
  2172. return DN_invalid;
  2173. } // End of IF then
  2174. elif ( !thisFlag && !superType.isEmpty ())
  2175. {
  2176. // Is the super context included 'cv' information, ensure that it is added appropriately
  2177. if ( superType.isPtrRef () || cvType.isEmpty ())
  2178. return ( DN_truncated + superType );
  2179. else
  2180. return ( DN_truncated + cvType + ' ' + superType );
  2181. } // End of ELIF then
  2182. elif ( !thisFlag && !cvType.isEmpty ())
  2183. return ( DN_truncated + cvType );
  2184. else
  2185. return DN_truncated;
  2186. } // End of "UnDecorator" FUNCTION "getDataIndirectType"
  2187. inline int __near UnDecorator::getECSUDataIndirectType ()
  2188. {
  2189. FTRACE(getECSUDataIndirectType);
  2190. if ( *gName )
  2191. {
  2192. unsigned int ecsuCode = *gName++ - 'A';
  2193. // Is it a valid 'ecsu-data-indirection-type' ?
  2194. if (( ecsuCode <= ( ECSU_const | ECSU_volatile | ECSU_modelmask )))
  2195. return ( ecsuCode | ECSU_valid );
  2196. else
  2197. return ECSU_invalid;
  2198. } // End of IF then
  2199. else
  2200. return ECSU_truncated;
  2201. } // End of "UnDecorator" FUNCTION "getECSUDataIndirectType"
  2202. inline DName __near UnDecorator::getPtrRefDataType ( const DName & superType, int isPtr )
  2203. {
  2204. FTRACE(getPtrRefDataType);
  2205. // Doubles up as 'pointer-data-type' and 'reference-data-type'
  2206. if ( *gName )
  2207. {
  2208. // Is this a 'pointer-data-type' ?
  2209. if ( isPtr && ( *gName == PoDT_void ))
  2210. {
  2211. gName++; // Skip this character
  2212. if ( superType.isEmpty ())
  2213. return "void";
  2214. else
  2215. return "void " + superType;
  2216. } // End of IF
  2217. // Otherwise it may be a 'reference-data-type'
  2218. if ( *gName == RDT_array ) // An array ?
  2219. {
  2220. DName * pDeclarator = gnew DName;
  2221. if ( !pDeclarator )
  2222. return ERROR;
  2223. gName++;
  2224. DName theArray ( getArrayType ( pDeclarator ));
  2225. if ( !theArray.isEmpty ())
  2226. *pDeclarator = superType;
  2227. // And return it
  2228. return theArray;
  2229. } // End of IF
  2230. // Otherwise, it is a 'basic-data-type'
  2231. return getBasicDataType ( superType );
  2232. } // End of IF then
  2233. else
  2234. return ( DN_truncated + superType );
  2235. } // End of "UnDecorator" FUNCTION "getPtrRefDataType"
  2236. inline DName __near UnDecorator::getArrayType ( DName * pDeclarator )
  2237. {
  2238. FTRACE(getArrayType);
  2239. DName superType ( pDeclarator );
  2240. if ( *gName )
  2241. {
  2242. int noDimensions = getNumberOfDimensions ();
  2243. if ( !noDimensions )
  2244. return getBasicDataType ( DName ( '[' ) + DN_truncated + ']' );
  2245. else
  2246. {
  2247. DName arrayType;
  2248. while ( noDimensions-- )
  2249. arrayType += '[' + getDimension () + ']';
  2250. // If it is indirect, then parenthesise the 'super-type'
  2251. if ( !superType.isEmpty ())
  2252. arrayType = '(' + superType + ')' + arrayType;
  2253. // Return the finished array dimension information
  2254. return getBasicDataType ( arrayType );
  2255. } // End of IF else
  2256. } // End of IF
  2257. elif ( !superType.isEmpty ())
  2258. return getBasicDataType ( '(' + superType + ")[" + DN_truncated + ']' );
  2259. else
  2260. return getBasicDataType ( DName ( '[' ) + DN_truncated + ']' );
  2261. } // End of "UnDecorator" FUNCTION "getArrayType"
  2262. inline DName __near UnDecorator::getLexicalFrame ( void ) { return '`' + getDimension () + '\''; }
  2263. inline DName __near UnDecorator::getStorageConvention ( void ) { return getDataIndirectType (); }
  2264. inline DName __near UnDecorator::getDataIndirectType () { return getDataIndirectType ( DName (), 0, DName ()); }
  2265. inline_lnk DName __near UnDecorator::getThisType ( void ) { return getDataIndirectType ( DName (), 0, DName (), TRUE ); }
  2266. inline DName __near UnDecorator::getPointerType ( const DName & cv, const DName & name )
  2267. { return getPtrRefType ( cv, name, TRUE ); }
  2268. inline DName __near UnDecorator::getReferenceType ( const DName & cv, const DName & name )
  2269. { return getPtrRefType ( cv, name, FALSE ); }
  2270. #if ( !VERS_PWB )
  2271. inline DName __near UnDecorator::getSegmentName ( void ) { return getZName (); }
  2272. #endif // !VERS_PWB
  2273. #if ( !NO_COMPILER_NAMES )
  2274. inline DName __near UnDecorator::getDisplacement ( void ) { return getDimension (); }
  2275. inline DName __near UnDecorator::getCallIndex ( void ) { return getDimension (); }
  2276. inline DName __near UnDecorator::getGuardNumber ( void ) { return getDimension (); }
  2277. inline DName __near UnDecorator::getVbTableType ( const DName & superType )
  2278. { return getVfTableType ( superType ); }
  2279. inline DName __near UnDecorator::getVCallThunkType ( void )
  2280. {
  2281. FTRACE(UnDecorator::getVCallThunkType);
  2282. DName vcallType = '{';
  2283. // Get the 'this' model, and validate all values
  2284. switch ( *gName )
  2285. {
  2286. case VMT_nTnCnV:
  2287. case VMT_nTfCnV:
  2288. case VMT_nTnCfV:
  2289. case VMT_nTfCfV:
  2290. case VMT_nTnCbV:
  2291. case VMT_nTfCbV:
  2292. vcallType += UScore ( TOK_nearSp );
  2293. break;
  2294. case VMT_fTnCnV:
  2295. case VMT_fTfCnV:
  2296. case VMT_fTnCfV:
  2297. case VMT_fTfCfV:
  2298. case VMT_fTnCbV:
  2299. case VMT_fTfCbV:
  2300. vcallType += UScore ( TOK_farSp );
  2301. break;
  2302. case 0:
  2303. return DN_truncated;
  2304. default:
  2305. return DN_invalid;
  2306. } // End of SWITCH
  2307. // Always append 'this'
  2308. vcallType += "this, ";
  2309. // Get the 'call' model
  2310. switch ( *gName )
  2311. {
  2312. case VMT_nTnCnV:
  2313. case VMT_fTnCnV:
  2314. case VMT_nTnCfV:
  2315. case VMT_fTnCfV:
  2316. case VMT_nTnCbV:
  2317. case VMT_fTnCbV:
  2318. vcallType += UScore ( TOK_nearSp );
  2319. break;
  2320. case VMT_nTfCnV:
  2321. case VMT_fTfCnV:
  2322. case VMT_nTfCfV:
  2323. case VMT_fTfCfV:
  2324. case VMT_nTfCbV:
  2325. case VMT_fTfCbV:
  2326. vcallType += UScore ( TOK_farSp );
  2327. break;
  2328. } // End of SWITCH
  2329. // Always append 'call'
  2330. vcallType += "call, ";
  2331. // Get the 'vfptr' model
  2332. switch ( *gName++ ) // Last time, so advance the pointer
  2333. {
  2334. case VMT_nTnCnV:
  2335. case VMT_nTfCnV:
  2336. case VMT_fTnCnV:
  2337. case VMT_fTfCnV:
  2338. vcallType += UScore ( TOK_nearSp );
  2339. break;
  2340. case VMT_nTnCfV:
  2341. case VMT_nTfCfV:
  2342. case VMT_fTnCfV:
  2343. case VMT_fTfCfV:
  2344. vcallType += UScore ( TOK_farSp );
  2345. break;
  2346. case VMT_nTnCbV:
  2347. case VMT_nTfCbV:
  2348. case VMT_fTnCbV:
  2349. case VMT_fTfCbV:
  2350. vcallType += getBasedType ();
  2351. break;
  2352. } // End of SWITCH
  2353. // Always append 'vfptr'
  2354. vcallType += "vfptr}";
  2355. // And return the resultant 'vcall-model-type'
  2356. return vcallType;
  2357. } // End of "UnDecorator" FUNCTION "getVCallThunk"
  2358. inline DName __near UnDecorator::getVfTableType ( const DName & superType )
  2359. {
  2360. FTRACE(UnDecorator::getVfTableType);
  2361. DName vxTableName = superType;
  2362. if ( vxTableName.isValid () && *gName )
  2363. {
  2364. vxTableName = getStorageConvention () + ' ' + vxTableName;
  2365. if ( vxTableName.isValid ())
  2366. {
  2367. if ( *gName != '@' )
  2368. {
  2369. vxTableName += "{for ";
  2370. while ( vxTableName.isValid () && *gName && ( *gName != '@' ))
  2371. {
  2372. vxTableName += '`' + getScope () + '\'';
  2373. // Skip the scope delimiter
  2374. if ( *gName == '@' )
  2375. gName++;
  2376. // Close the current scope, and add a conjunction for the next (if any)
  2377. if ( vxTableName.isValid () && ( *gName != '@' ))
  2378. vxTableName += "s ";
  2379. } // End of WHILE
  2380. if ( vxTableName.isValid ())
  2381. {
  2382. if ( !*gName )
  2383. vxTableName += DN_truncated;
  2384. vxTableName += '}';
  2385. } // End of IF
  2386. } // End of IF
  2387. // Skip the 'vpath-name' terminator
  2388. if ( *gName == '@' )
  2389. gName++;
  2390. } // End of IF
  2391. } // End of IF then
  2392. elif ( vxTableName.isValid ())
  2393. vxTableName = DN_truncated + vxTableName;
  2394. return vxTableName;
  2395. } // End of "UnDecorator" FUNCTION "getVfTableType"
  2396. #endif // !NO_COMPILER_NAMES
  2397. inline DName __near UnDecorator::getExternalDataType ( const DName & superType )
  2398. {
  2399. FTRACE(UnDecorator::getExternalDataType);
  2400. // Create an indirect declarator for the the rest
  2401. DName * pDeclarator = gnew DName ();
  2402. DName declaration = getDataType ( pDeclarator );
  2403. // Now insert the declarator into the declaration along with its 'storage-convention'
  2404. *pDeclarator = getStorageConvention () + ' ' + superType;
  2405. return declaration;
  2406. } // End of "UnDecorator" FUNCTION "getExternalDataType"
  2407. #endif // !VERS_P3
  2408. #if ( !NO_OPTIONS )
  2409. inline int __near UnDecorator::doUnderScore () { return !( disableFlags & UNDNAME_NO_LEADING_UNDERSCORES ); }
  2410. inline int __near UnDecorator::doMSKeywords () { return !( disableFlags & UNDNAME_NO_MS_KEYWORDS ); }
  2411. inline int __near UnDecorator::doFunctionReturns () { return !( disableFlags & UNDNAME_NO_FUNCTION_RETURNS ); }
  2412. inline int __near UnDecorator::doAllocationModel () { return !( disableFlags & UNDNAME_NO_ALLOCATION_MODEL ); }
  2413. inline int __near UnDecorator::doAllocationLanguage () { return !( disableFlags & UNDNAME_NO_ALLOCATION_LANGUAGE ); }
  2414. #if 0
  2415. inline int __near UnDecorator::doMSThisType () { return !( disableFlags & UNDNAME_NO_MS_THISTYPE ); }
  2416. inline int __near UnDecorator::doCVThisType () { return !( disableFlags & UNDNAME_NO_CV_THISTYPE ); }
  2417. #endif
  2418. inline int __near UnDecorator::doThisTypes () { return (( disableFlags & UNDNAME_NO_THISTYPE ) != UNDNAME_NO_THISTYPE ); }
  2419. inline int __near UnDecorator::doAccessSpecifiers () { return !( disableFlags & UNDNAME_NO_ACCESS_SPECIFIERS ); }
  2420. inline int __near UnDecorator::doThrowTypes () { return !( disableFlags & UNDNAME_NO_THROW_SIGNATURES ); }
  2421. inline int __near UnDecorator::doMemberTypes () { return !( disableFlags & UNDNAME_NO_MEMBER_TYPE ); }
  2422. inline int __near UnDecorator::doReturnUDTModel () { return !( disableFlags & UNDNAME_NO_RETURN_UDT_MODEL ); }
  2423. #endif // !NO_OPTIONS
  2424. #if ( !VERS_P3 && !VERS_PWB )
  2425. pcchar_t __near UnDecorator::UScore ( Tokens tok )
  2426. {
  2427. FTRACE(UnDecorator::UScore);
  2428. #if ( !NO_OPTIONS )
  2429. return ( doUnderScore () ? tokenTable[ tok ] : tokenTable[ tok ] + 2 );
  2430. #else // } elif NO_OPTIONS {
  2431. return tokenTable[ tok ];
  2432. #endif // NO_OPTIONS
  2433. } // End of "UnDecorator" FUNCTION "UScore"
  2434. #endif // !VERS_P3 && !VERS_PWB
  2435. #include "undname.inl"