windows-nt/Source/XPSP1/NT/sdktools/link16/undname.cxx

3337 lines
108 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
// Make sure all dependent defines exist and have a valid value
#ifndef TUNE
#define TUNE 0
#endif
#ifndef DEBUG
#define DEBUG 0
#endif
#ifndef STANDALONE
#define STANDALONE 0
#endif
#ifndef SPECIAL
#define SPECIAL 0
#endif
#ifndef TARGET_32BIT
#define TARGET_32BIT 1 // DLH set in makefile originally
#endif
#ifndef USE_CRT_HEAP
#define USE_CRT_HEAP 0
#endif
#ifndef NO_COMPILER_NAMES
#define NO_COMPILER_NAMES 0
#endif
#ifndef NO_OPTIONS
#define NO_OPTIONS 0
#endif
#ifndef NO_INLINES
#define NO_INLINES 0
#endif
#ifndef VERS_P3
#define VERS_P3 0
#endif
#ifndef VERS_PWB
#define VERS_PWB 0
#endif
#ifndef VERS_LNK
#define VERS_LNK 1 // DLH set in makefile originally
#endif
#ifndef PACK_SIZE
#define PACK_SIZE 1
#endif
#ifndef inline_p3
#define inline_p3
#endif
#ifndef inline_pwb
#define inline_pwb
#endif
#ifndef inline_lnk
#define inline_lnk
#endif
#ifndef NO_VIRTUAL
#define NO_VIRTUAL 0
#endif
// Check for version inconsistancies, ans setup version flags
#if ( TUNE && STANDALONE )
#error "TUNE and STANDALONE are incompatible"
#endif // TUNE && STANDALONE
#if ( VERS_P3 == 1 )
#if ( VERS_PWB == 1 )
#error "VERS_P3 and VERS_PWB are incompatible"
#endif // VERS_PWB
#if ( VERS_LNK == 1 )
#error "VERS_P3 and VERS_LNK are incompatible"
#endif // VERS_LNK
#undef inline_p3
#define inline_p3 inline
#undef USE_CRT_HEAP
#define USE_CRT_HEAP 1
#undef NO_COMPILER_NAMES
#define NO_COMPILER_NAMES 1
#undef NO_OPTIONS
#define NO_OPTIONS 1
#pragma inline_depth ( 3 )
#pragma pack ( 2 )
#undef PACK_SIZE
#define PACK_SIZE 1
#endif
#if ( VERS_PWB == 1 )
#if ( DEBUG == 1 )
#error "VERS_PWB and DEBUG are incompatible"
#endif // DEBUG
#if ( VERS_LNK == 1 )
#error "VERS_PWB and VERS_LNK are incompatible"
#endif // VERS_LNK
#undef inline_pwb
#define inline_pwb inline
#undef USE_CRT_HEAP
#define USE_CRT_HEAP 0
#undef NO_COMPILER_NAMES
#define NO_COMPILER_NAMES 1
#undef NO_OPTIONS
#define NO_OPTIONS 1
#undef PACK_SIZE
#define PACK_SIZE 2
#undef NO_VIRTUAL
#define NO_VIRTUAL 1
#pragma inline_depth ( 5 )
#pragma pack ( 2 )
#endif // VERS_PWB
#if ( VERS_LNK == 1 )
#if ( VERS_PWB == 1 )
#error "VERS_LNK and VERS_PWB are incompatible"
#endif // VERS_PWB
#undef inline_lnk
#define inline_lnk inline
#if ( DEBUG == 1 )
#if !STANDALONE
#undef USE_CRT_HEAP
#define USE_CRT_HEAP 1
#endif
#else // } else !DEBUG {
#undef USE_CRT_HEAP
#define USE_CRT_HEAP 0
#endif // !DEBUG
#undef NO_COMPILER_NAMES
#define NO_COMPILER_NAMES 0
#undef NO_OPTIONS
#define NO_OPTIONS 0
#undef NO_VIRTUAL
#define NO_VIRTUAL 1
#pragma inline_depth ( 3 )
#pragma pack ( 2 )
#undef PACK_SIZE
#define PACK_SIZE 2
#endif // VERS_LNK
#if ( TARGET_32BIT )
#define __far /* no far */
#define __near /* no near */
#define __pascal /* no pascal */
#if !defined( _WIN32 )
#define __cdecl /* no cdecl */
#endif
#define __loadds /* no loadds */
#endif // TARGET_32BIT
#if ( !NO_VIRTUAL )
#define PURE =0
#else // } elif NO_VIRTUAL {
#define PURE
#define virtual
#endif
#if DEBUG && STANDALONE
#define STDEBUG 1
#endif
#include "undname.hxx"
static unsigned int __near __pascal strlen ( pcchar_t );
static pchar_t __near __pascal strncpy ( pchar_t, pcchar_t, unsigned int );
#if USE_CRT_HEAP
extern "C" void __far * __far __cdecl malloc ( unsigned int );
extern "C" void __far __cdecl free ( void __far * );
#endif // USE_CRT_HEAP
#if STDEBUG
#pragma inline_depth ( 0 )
#pragma pack ( 2 )
#undef PACK_SIZE
#define PACK_SIZE 1
#include <stdio.h>
class DName;
class DNameNode;
class CallTrace
{
private:
enum InOut { out = -1, mark = 0, in = 1 };
pchar_t name;
static int trace;
static FILE * fp;
static char buf[ 512 ];
static int inTrace;
static void indent ( InOut inOut )
{ 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; }}
public:
CallTrace ( pchar_t p )
: name ( p )
{ if(trace&&!inTrace){ indent ( in ); fprintf ( fp, "Entered : '%s'\n", name ); fflush ( fp ); }}
static void On ( pchar_t f )
{ fp = fopen ( f, "wt" ); if(fp) trace = 1; }
void Dump ( const DName &, pcchar_t, int );
void Dump ( const DNameNode &, pcchar_t, int );
void Dump ( unsigned long, pcchar_t, int );
void Dump ( void*, pcchar_t, int );
void Dump ( pcchar_t, pcchar_t, int );
void Message ( pcchar_t, int );
void Track ( pcchar_t, int );
void LogError ( int );
~CallTrace ()
{ if(trace&&!inTrace){ indent ( out ); fprintf ( fp, "Leaving : '%s'\n", name ); fflush ( fp ); }}
};
int CallTrace::trace = 0;
int CallTrace::inTrace = 0;
FILE * CallTrace::fp = 0;
char CallTrace::buf[ 512 ];
#undef NO_INLINES
#define NO_INLINES 1
#define FTRACE(n) CallTrace fName(#n)
#define TRACEON() do{if((argc>=2)&&(*argv[1]!='?')&&((*argv[1]<'0')||(*argv[1]>'9'))){argv++;argc--;CallTrace::On(*argv);}}while(0)
#define DUMP(n) (fName.Dump(n,#n,__LINE__))
#define TRACK() (fName.Track(__FILE__,__LINE__))
#define MESSAGE(m) (fName.Message(#m,__LINE__))
#define ERROR (fName.LogError(__LINE__),DN_error)
#else // } elif !STDEBUG {
#pragma check_stack ( off )
#pragma pack ( 2 )
#undef PACK_SIZE
#define PACK_SIZE 1
#define FTRACE(n)
#define TRACEON()
#define DUMP(n)
#define TRACK()
#define MESSAGE(m) (0)
#define ERROR DN_error
#endif // !STDEBUG
#if ( NO_INLINES )
#undef inline_p3
#undef inline_pwb
#undef inline_lnk
#define inline
#define inline_p3
#define inline_pwb
#define inline_lnk
#endif // NO_INLINES
#if STANDALONE
extern "C" int __far __cdecl printf ( pcchar_t, ... );
extern "C" int __far __cdecl atoi ( pcchar_t );
extern "C" void __far * __far __cdecl malloc ( unsigned int );
extern "C" void __far __cdecl free ( void __far * );
#if STDEBUG
int shallowCopies = 0;
int deepCopies = 0;
int shallowAssigns = 0;
int deepAssigns = 0;
#endif
int actual = 0;
int requested = 0;
int clones = 0;
int __cdecl main ( int argc, pchar_t* argv )
{
TRACEON();
FTRACE(main);
unsigned short flags = 0;
if (( argc > 2 ) && ( *argv[ 1 ] >= '0' ) && ( *argv[ 1 ] <= '9' ))
( flags = atoi ( argv[ 1 ]), argc--, argv++ );
for ( int i = 1; i < argc; i++ )
{
printf ( "Undecoration of :- \"%s\"\n", argv[ i ]);
pchar_t uName = unDName ( 0,
argv[ i ],
0
#if ( !USE_CRT_HEAP )
,&malloc
,&free
#endif // !USE_CRT_HEAP
#if ( !NO_OPTIONS )
,flags
#endif // !NO_OPTIONS
);
if ( uName )
printf ( "is :- \"%s\"\n\n", uName );
else
printf ( "Internal Error in Undecorator\n" );
}
#if STDEBUG
printf ( "%d bytes of memory requested, %d bytes allocated\n", requested, actual );
printf ( "%d shallow copies and %d deep copies\n", shallowCopies, deepCopies );
printf ( "%d shallow assigns and %d deep assigns\n", shallowAssigns, deepAssigns );
printf ( "%d clones\n", clones );
#endif
return 0;
} // End of PROGRAM
#endif // STANDALONE
#if TUNE
void __cdecl main ()
{ (void)unDName ( 0, 0, 0
#if ( !USE_CRT_HEAP )
,0, 0
#endif // !USE_CRT_HEAP
#if ( !NO_OPTIONS )
,0
#endif // !NO_OPTIONS
); }
#endif // TUNE
class DName;
class DNameNode;
class Replicator;
class HeapManager;
class UnDecorator;
const unsigned int memBlockSize = 508; // A '512' byte block including the header
class HeapManager
{
private:
#if ( !USE_CRT_HEAP )
Alloc_t pOpNew;
Free_t pOpDelete;
#endif // !USE_CRT_HEAP
struct Block
{
Block * next;
char memBlock[ memBlockSize ];
__near Block () { next = 0; }
};
Block * head;
Block * tail;
unsigned int blockLeft;
public:
#if ( !USE_CRT_HEAP )
void __near Constructor ( Alloc_t pAlloc, Free_t pFree )
{ pOpNew = pAlloc;
pOpDelete = pFree;
#else // } elif USE_CRT_HEAP {
void __near Constructor ( void )
{
#endif // USE_CRT_HEAP
blockLeft = 0;
head = 0;
tail = 0;
}
void __far * __near getMemory ( size_t, int );
void __near Destructor ( void )
{ while ( tail = head )
{
head = tail->next;
#if ( !USE_CRT_HEAP )
( *pOpDelete )( tail );
#else // } elif USE_CRT_HEAP {
free ( tail );
#endif // USE_CRT_HEAP
} }
#define gnew new(heap,0)
#define rnew new(heap,1)
};
void * __near __pascal operator new ( size_t, HeapManager &, int = 0 );
static HeapManager heap;
#if ( !VERS_PWB )
// The MS Token table
enum Tokens
{
TOK_near,
TOK_nearSp,
TOK_nearP,
TOK_far,
TOK_farSp,
TOK_farP,
TOK_huge,
TOK_hugeSp,
TOK_hugeP,
TOK_basedLp,
TOK_cdecl,
TOK_pascal,
TOK_stdcall,
TOK_syscall,
TOK_fastcall,
TOK_interrupt,
TOK_saveregs,
TOK_self,
TOK_segment,
TOK_segnameLpQ
};
static pcchar_t __near tokenTable[] =
{
"__near", // TOK_near
"__near ", // TOK_nearSp
"__near*", // TOK_nearP
"__far", // TOK_far
"__far ", // TOK_farSp
"__far*", // TOK_farP
"__huge", // TOK_huge
"__huge ", // TOK_hugeSp
"__huge*", // TOK_hugeP
"__based(", // TOK_basedLp
"__cdecl", // TOK_cdecl
"__pascal", // TOK_pascal
"__stdcall", // TOK_stdcall
"__syscall", // TOK_syscall
"__fastcall", // TOK_fastcall
"__interrupt", // TOK_interrupt
"__saveregs", // TOK_saveregs
"__self", // TOK_self
"__segment", // TOK_segment
"__segname(\"" // TOK_segnameLpQ
};
#endif // !VERS_PWB
// The operator mapping table
static pcchar_t __near nameTable[] =
{
" new",
" delete",
"=",
">>",
"<<",
"!",
"==",
"!=",
"[]",
#if VERS_P3
"<UDC>",
#else // } !VERS_P3 {
"operator",
#endif // VERS_P3
"->",
"*",
"++",
"--",
"-",
"+",
"&",
"->*",
"/",
"%",
"<",
"<=",
">",
">=",
",",
"()",
"~",
"^",
"|",
"&&",
"||",
"*=",
"+=",
"-=",
"/=",
"%=",
">>=",
"<<=",
"&=",
"|=",
"^=",
#if ( !NO_COMPILER_NAMES )
"`vftable'",
"`vbtable'",
"`vcall",
"`typeof'",
"`local static guard",
"`reserved'",
"`vbase destructor'",
"`vector deleting destructor'",
"`default constructor closure'",
"`scalar deleting destructor'",
"`vector constructor iterator'",
"`vector destructor iterator'",
"`vector vbase constructor iterator'"
#endif // !NO_COMPILER_NAMES
};
// The following 'enum' should really be nested inside 'class DName', but to
// make the code compile better with Glockenspiel, I have extracted it
enum DNameStatus
{
DN_valid,
DN_invalid,
DN_truncated,
DN_error
};
class DName
{
public:
__near DName ();
__near DName ( char );
#if 1
__near DName ( const DName & ); // Shallow copy
#endif
__near DName ( DNameNode * );
__near DName ( pcchar_t );
__near DName ( pcchar_t&, char );
__near DName ( DNameStatus );
#if ( !VERS_P3 )
__near DName ( DName * );
__near DName ( unsigned long );
#endif // !VERS_P3
int __near isValid () const;
int __near isEmpty () const;
DNameStatus __near status () const;
#if ( !VERS_P3 )
DName & __near setPtrRef ();
int __near isPtrRef () const;
int __near isUDC () const;
void __near setIsUDC ();
#endif // !VERS_P3
int __near length () const;
pchar_t __near getString ( pchar_t, int ) const;
DName __near operator + ( pcchar_t ) const;
DName __near operator + ( const DName & ) const;
#if ( !VERS_P3 )
DName __near operator + ( char ) const;
DName __near operator + ( DName * ) const;
DName __near operator + ( DNameStatus ) const;
DName & __near operator += ( char );
DName & __near operator += ( pcchar_t );
DName & __near operator += ( DName * );
DName & __near operator += ( DNameStatus );
DName & __near operator |= ( const DName & );
#endif // !VERS_P3
DName & __near operator += ( const DName & );
DName & __near operator = ( pcchar_t );
DName & __near operator = ( const DName & );
#if ( !VERS_P3 )
DName & __near operator = ( char );
DName & __near operator = ( DName * );
DName & __near operator = ( DNameStatus );
#endif // !VERS_P3
// Friends :
friend DName __near __pascal operator + ( char, const DName & );
friend DName __near __pascal operator + ( pcchar_t, const DName & );
#if ( !VERS_P3 )
friend DName __near __pascal operator + ( DNameStatus, const DName & );
#endif // !VERS_P3
private:
DNameNode * node;
DNameStatus stat : 4;
unsigned int isIndir : 1;
unsigned int isAUDC : 1;
void __near doPchar ( pcchar_t, int );
};
class Replicator
{
private:
// Declare, in order to suppress automatic generation
void operator = ( const Replicator& );
int index;
DName * dNameBuffer[ 10 ];
const DName ErrorDName;
const DName InvalidDName;
public:
__near Replicator ();
int __near isFull () const;
Replicator & __near operator += ( const DName & );
const DName & __near operator [] ( int ) const;
};
class UnDecorator
{
private:
// Declare, in order to suppress automatic generation
void operator = ( const UnDecorator& );
#if ( !VERS_P3 )
Replicator ArgList;
static Replicator * pArgList;
#endif // !VERS_P3
Replicator ZNameList;
static Replicator * pZNameList;
static pcchar_t gName;
static pcchar_t name;
static pchar_t outputString;
static int maxStringLength;
#if (!NO_OPTIONS)
static unsigned short disableFlags;
#endif // !NO_OPTIONS
static DName __near getDecoratedName ( void );
static DName __near getSymbolName ( void );
static DName __near getZName ( void );
static DName __near getOperatorName ( void );
static DName __near getScope ( void );
#if ( !VERS_P3 )
static DName __near getDimension ( void );
static int __near getNumberOfDimensions ( void );
static DName __near getTemplateName ( void );
static DName __near composeDeclaration ( const DName & );
static int __near getTypeEncoding ( void );
static DName __near getBasedType ( void );
static DName __near getECSUName ( void );
static DName __near getEnumName ( void );
static DName __near getCallingConvention ( void );
static DName __near getReturnType ( DName * = 0 );
static DName __near getDataType ( DName * );
static DName __near getPrimaryDataType ( const DName & );
static DName __near getDataIndirectType ( const DName &, char, const DName &, int = FALSE );
static DName __near getDataIndirectType ();
static DName __near getBasicDataType ( const DName & );
static DName __near getECSUDataType ( int = 0 );
static int __near getECSUDataIndirectType ();
static DName __near getPtrRefType ( const DName &, const DName &, int );
static DName __near getPtrRefDataType ( const DName &, int );
static DName __near getArrayType ( DName * );
static DName __near getArgumentTypes ( void );
static DName __near getArgumentList ( void );
static DName __near getThrowTypes ( void );
static DName __near getLexicalFrame ( void );
static DName __near getStorageConvention ( void );
static DName __near getThisType ( void );
static DName __near getPointerType ( const DName &, const DName & );
static DName __near getReferenceType ( const DName &, const DName & );
static DName __near getExternalDataType ( const DName & );
#if ( !VERS_PWB )
static DName __near getSegmentName ( void );
#endif // !VERS_PWB
#if ( !NO_COMPILER_NAMES )
static DName __near getDisplacement ( void );
static DName __near getCallIndex ( void );
static DName __near getGuardNumber ( void );
static DName __near getVfTableType ( const DName & );
static DName __near getVbTableType ( const DName & );
static DName __near getVCallThunkType ( void );
#endif // !NO_COMPILER_NAMES
#endif // !VERS_P3
public:
#if ( !NO_OPTIONS )
__near UnDecorator ( pchar_t, pcchar_t, int, unsigned short );
static int __near doUnderScore ();
static int __near doMSKeywords ();
static int __near doFunctionReturns ();
static int __near doAllocationModel ();
static int __near doAllocationLanguage ();
#if 0
static int __near doMSThisType ();
static int __near doCVThisType ();
#endif
static int __near doThisTypes ();
static int __near doAccessSpecifiers ();
static int __near doThrowTypes ();
static int __near doMemberTypes ();
static int __near doReturnUDTModel ();
#else // } elif NO_OPTIONS {
__near UnDecorator ( pchar_t, pcchar_t, int );
#endif // NO_OPTIONS
#if ( !VERS_P3 && !VERS_PWB )
static pcchar_t __near UScore ( Tokens );
#endif // !VERS_P3 && !VERS_PWB
__near operator pchar_t ();
};
#if ( !VERS_P3 )
Replicator * UnDecorator::pArgList;
#endif // !VERS_P3
Replicator * UnDecorator::pZNameList = 0;
pcchar_t UnDecorator::gName = 0;
pcchar_t UnDecorator::name = 0;
pchar_t UnDecorator::outputString = 0;
int UnDecorator::maxStringLength = 0;
#if (!NO_OPTIONS)
unsigned short UnDecorator::disableFlags = 0;
#endif // !NO_OPTIONS
pchar_t __far __cdecl __loadds unDName ( pchar_t outputString,
pcchar_t name,
int maxStringLength // Note, COMMA is leading following optional arguments
#if ( !USE_CRT_HEAP )
,Alloc_t pAlloc
,Free_t pFree
#endif // !USE_CRT_HEAP
#if ( !NO_OPTIONS )
,unsigned short disableFlags
#endif // !NO_OPTIONS
)
/*
* This function will undecorate a name, returning the string corresponding to
* the C++ declaration needed to produce the name. Its has a similar interface
* to 'strncpy'.
*
* If the target string 'outputString' is specified to be NULL, a string of
* suitable length will be allocated and its address returned. If the returned
* string is allocated by 'unDName', then it is the programmers responsibility
* to deallocate it. It will have been allocated on the far heap.
*
* If the target string is not NULL, then the parameter 'maxStringLength' will
* specify the maximum number of characters which may be placed in the string.
* In this case, the returned value is the same as 'outputString'.
*
* Both the input parameter 'name' and the returned string are NULL terminated
* strings of characters.
*
* If the returned value is NULL, it indicates that the undecorator ran out of
* memory, or an internal error occurred, and was unable to complete its task.
*/
{
FTRACE(unDName);
#if ( VERS_P3 && !STANDALONE )
// Abort if input is invalid
if ( !outputString || !name || !maxStringLength )
return 0;
#endif // ( VERS_P3 && !STANDALONE )
#if ( !USE_CRT_HEAP )
// Must have an allocator and a deallocator (and we MUST trust them)
if ( !( pAlloc && pFree ))
return 0;
else
heap.Constructor ( pAlloc, pFree );
#else // } elif USE_CRT_HEAP {
heap.Constructor ();
#endif // USE_CRT_HEAP
// Create the undecorator object, and get the result
UnDecorator unDecorate ( outputString,
name,
maxStringLength
#if ( !NO_OPTIONS )
,disableFlags
#endif // !NO_OPTIONS
);
pchar_t unDecoratedName = unDecorate;
// Destruct the heap (would use a destructor, but that causes DLL problems)
heap.Destructor ();
// And return the composed name
return unDecoratedName;
} // End of FUNCTION "unDName"
// The 'UnDecorator' member functions
inline __near UnDecorator::UnDecorator ( pchar_t output,
pcchar_t dName,
int maxLen
#if ( !NO_OPTIONS )
,unsigned short disable
#endif // !NO_OPTIONS
)
{
FTRACE(UnDecorator::UnDecorator);
#if STDEBUG
if ( dName )
{
while ( *dName == ' ' )
dName++;
pchar_t s = gnew char[ strlen ( dName ) + 1 ];
if ( name = s )
do
{
if (( *s = *dName ) != ' ' )
s++;
} while ( *dName++ );
}
else
name = 0;
#else // } elif !STDEBUG {
name = dName;
#endif // !STDEBUG
gName = name;
maxStringLength = maxLen;
outputString = output;
pZNameList = &ZNameList;
#if ( !VERS_P3 )
pArgList = &ArgList;
#endif // !VERS_P3
#if ( !NO_OPTIONS )
disableFlags = disable;
#endif // !NO_OPTIONS
} // End of "UnDecorator" CONSTRUCTOR '()'
inline __near UnDecorator::operator pchar_t ()
{
FTRACE(UnDecorator::pchar_t);
DName result;
DName unDName;
// Find out if the name is a decorated name or not. Could be a reserved
// CodeView variant of a decorated name
if ( name )
{
if (( *name == '?' ) && ( name[ 1 ] == '@' ))
{
#if ( !NO_COMPILER_NAMES )
gName += 2;
result = "CV: " + getDecoratedName ();
#else // } elif NO_COMPILER_NAMES
result = DN_invalid;
#endif // NO_COMPILER_NAMES
} // End of IF then
else
result = getDecoratedName ();
} // End of IF then
// If the name was not a valid name, then make the name the same as the original
// It is also invalid if there are any remaining characters in the name
if ( result.status () == DN_error )
return 0;
#if ( !VERS_P3 )
elif ( *gName || ( result.status () == DN_invalid ))
unDName = name; // Return the original name
#else // } elif VERS_P3 {
elif ( !*gName || ( *gName != '@' ) || ( result.status () == DN_invalid ))
unDName = ""; // Blank
#endif // VERS_P3
else
unDName = result;
#if ( !VERS_P3 || STANDALONE )
// Construct the return string
if ( !outputString )
{
maxStringLength = unDName.length () + 1;
outputString = rnew char[ maxStringLength ];
} // End of IF
if ( outputString )
#endif // ( !VERS_P3 || STANDALONE )
unDName.getString ( outputString, maxStringLength );
// Return the result
return outputString;
} // End of "UnDecorator" OPERATOR 'pchar_t'
DName __near UnDecorator::getDecoratedName ( void )
{
FTRACE(getDecoratedName);
// Ensure that it is intended to be a decorated name
if ( *gName == '?' )
{
// Extract the basic symbol name
gName++; // Advance the original name pointer
DName symbolName = getSymbolName ();
#if ( !VERS_P3 )
int udcSeen = symbolName.isUDC ();
#endif // !VERS_P3
// Abort if the symbol name is invalid
if ( !symbolName.isValid ())
return symbolName;
// Extract, and prefix the scope qualifiers
if ( *gName && ( *gName != '@' ))
symbolName = getScope () + "::" + symbolName;
#if ( !VERS_P3 )
if ( udcSeen )
symbolName.setIsUDC ();
// Now compose declaration
if ( symbolName.isEmpty ())
return symbolName;
elif ( !*gName || ( *gName == '@' ))
{
if ( *gName )
gName++;
return composeDeclaration ( symbolName );
} // End of ELIF then
else
return DN_invalid;
#else // } elif VERS_P3 {
return symbolName;
#endif // VERS_P3
} // End of IF then
elif ( *gName )
return DN_invalid;
else
return DN_truncated;
} // End of "UnDecorator" FUNCTION "getDecoratedName"
inline DName __near UnDecorator::getSymbolName ( void )
{
FTRACE(getSymbolName);
if ( *gName == '?' )
{
gName++;
return getOperatorName ();
} // End of IF then
else
return getZName ();
} // End of "UnDecorator" FUNCTION "getSymbolName"
DName __near UnDecorator::getZName ( void )
{
FTRACE(getZName);
int zNameIndex = *gName - '0';
// Handle 'zname-replicators', otherwise an actual name
if (( zNameIndex >= 0 ) && ( zNameIndex <= 9 ))
{
gName++; // Skip past the replicator
// And return the indexed name
return ( *pZNameList )[ zNameIndex ];
} // End of IF then
else
{
// Extract the 'zname' to the terminator
DName zName ( gName, '@' ); // This constructor updates 'name'
// Add it to the current list of 'zname's
if ( !pZNameList->isFull ())
*pZNameList += zName;
// And return the symbol name
return zName;
} // End of IF else
} // End of "UnDecorator" FUNCTION "getZName"
inline DName __near UnDecorator::getOperatorName ( void )
{
FTRACE(getOperatorName);
DName operatorName;
#if ( !VERS_P3 )
int udcSeen = FALSE;
#endif // VERS_P3
// So what type of operator is it ?
switch ( *gName++ )
{
case 0:
gName--; // End of string, better back-track
return DN_truncated;
case OC_ctor:
case OC_dtor: // The constructor and destructor are special
{
// Use a temporary. Don't want to advance the name pointer
pcchar_t pName = gName;
operatorName = getZName ();
gName = pName;
if ( !operatorName.isEmpty () && ( gName[ -1 ] == OC_dtor ))
operatorName = '~' + operatorName;
return operatorName;
} // End of CASE 'OC_ctor,OC_dtor'
break;
case OC_new:
case OC_delete:
case OC_assign:
case OC_rshift:
case OC_lshift:
case OC_not:
case OC_equal:
case OC_unequal:
operatorName = nameTable[ gName[ -1 ] - OC_new ];
break;
case OC_udc:
#if ( !VERS_P3 )
udcSeen = TRUE;
#endif // !VERS_P3
// No break
case OC_index:
case OC_pointer:
case OC_star:
case OC_incr:
case OC_decr:
case OC_minus:
case OC_plus:
case OC_amper:
case OC_ptrmem:
case OC_divide:
case OC_modulo:
case OC_less:
case OC_leq:
case OC_greater:
case OC_geq:
case OC_comma:
case OC_call:
case OC_compl:
case OC_xor:
case OC_or:
case OC_land:
case OC_lor:
case OC_asmul:
case OC_asadd:
case OC_assub: // Regular operators from the first group
operatorName = nameTable[ gName[ -1 ] - OC_index + ( OC_unequal - OC_new + 1 )];
break;
case '_':
switch ( *gName++ )
{
case 0:
gName--; // End of string, better back-track
return DN_truncated;
case OC_asdiv:
case OC_asmod:
case OC_asrshift:
case OC_aslshift:
case OC_asand:
case OC_asor:
case OC_asxor: // Regular operators from the extended group
operatorName = nameTable[ gName[ -1 ] - OC_asdiv + ( OC_assub - OC_index + 1 ) + ( OC_unequal - OC_new + 1 )];
break;
#if ( !NO_COMPILER_NAMES )
case OC_vftable:
case OC_vbtable:
case OC_vcall:
return nameTable[ gName[ -1 ] - OC_asdiv + ( OC_assub - OC_index + 1 ) + ( OC_unequal - OC_new + 1 )];
case OC_metatype:
case OC_guard:
case OC_uctor:
case OC_udtor:
case OC_vdeldtor:
case OC_defctor:
case OC_sdeldtor:
case OC_vctor:
case OC_vdtor:
case OC_vallctor: // Special purpose names
return nameTable[ gName[ -1 ] - OC_metatype + ( OC_vcall - OC_asdiv + 1 ) + ( OC_assub - OC_index + 1 ) + ( OC_unequal - OC_new + 1 )];
#endif // !NO_COMPILER_NAMES
default:
return DN_invalid;
} // End of SWITCH
break;
default:
return DN_invalid;
} // End of SWITCH
#if ( !VERS_P3 )
// This really is an operator name, so prefix it with 'operator'
if ( udcSeen )
operatorName.setIsUDC ();
elif ( !operatorName.isEmpty ())
#endif // !VERS_P3
operatorName = "operator" + operatorName;
return operatorName;
} // End of "UnDecorator" FUNCTION "getOperatorName"
DName __near UnDecorator::getScope ( void )
{
FTRACE(getScope);
int first = TRUE;
DName scope;
// Get the list of scopes
while (( scope.status () == DN_valid ) && *gName && ( *gName != '@' ))
{ // Insert the scope operator if not the first scope
if ( first )
first = FALSE;
else
scope = "::" + scope;
// Determine what kind of scope it is
if ( *gName == '?' )
#if ( !VERS_P3 )
switch ( *++gName )
{
case '?':
scope = '`' + getDecoratedName () + '\'' + scope;
break;
case '$':
#if ( !VERS_PWB )
gName++;
scope = getTemplateName () + scope;
break;
#else // } elif VERS_PWB {
return DN_invalid;
#endif // VERS_PWB
default:
scope = getLexicalFrame () + scope;
break;
} // End of SWITCH
#else // } elif VERS_P3 {
return DN_invalid;
#endif // VERS_P3
else
scope = getZName () + scope;
} // End of WHILE
// Catch error conditions
switch ( *gName )
{
case 0:
if ( first )
scope = DN_truncated;
else
scope = DName ( DN_truncated ) + "::" + scope;
break;
case '@': // '@' expected to end the scope list
break;
default:
scope = DN_invalid;
break;
} // End of SWITCH
// Return the composed scope
return scope;
} // End of "UnDecorator" FUNCTION "getScope"
#if ( !VERS_P3 )
DName __near UnDecorator::getDimension ( void )
{
FTRACE(getDimension);
if ( !*gName )
return DN_truncated;
elif (( *gName >= '0' ) && ( *gName <= '9' ))
return DName ((unsigned long)( *gName++ - '0' + 1 ));
else
{
unsigned long dim = 0L;
// Don't bother detecting overflow, it's not worth it
while ( *gName != '@' )
{
if ( !*gName )
return DN_truncated;
elif (( *gName >= 'A' ) && ( *gName <= 'P' ))
dim = ( dim << 4 ) + ( *gName - 'A' );
else
return DN_invalid;
gName++;
} // End of WHILE
// Ensure integrity, and return
if ( *gName++ != '@' )
return DN_invalid; // Should never get here
return dim;
} // End of ELIF else
} // End of "UnDecorator" FUNCTION "getDimension"
inline_pwb int __near UnDecorator::getNumberOfDimensions ( void )
{
FTRACE(getNumberOfDimensions);
if ( !*gName )
return 0;
elif (( *gName >= '0' ) && ( *gName <= '9' ))
return (( *gName++ - '0' ) + 1 );
else
{
int dim = 0;
// Don't bother detecting overflow, it's not worth it
while ( *gName != '@' )
{
if ( !*gName )
return 0;
elif (( *gName >= 'A' ) && ( *gName <= 'P' ))
dim = ( dim << 4 ) + ( *gName - 'A' );
else
return -1;
gName++;
} // End of WHILE
// Ensure integrity, and return
if ( *gName++ != '@' )
return -1; // Should never get here
return dim;
} // End of ELIF else
} // End of "UnDecorator" FUNCTION "getNumberOfDimensions"
#if ( !VERS_PWB )
DName __near UnDecorator::getTemplateName ( void )
{
FTRACE(getTemplateName);
DName templateName = "template " + getZName ();
if ( !templateName.isEmpty ())
templateName += '<' + getArgumentList () + '>';
// Return the completed 'template-name'
return templateName;
} // End of "UnDecorator" FUNCTION "getTemplateName"
#endif // !VERS_PWB
#if defined(COFF)
//inline DName __near UnDecorator::composeDeclaration ( const DName & symbol )
//
// The above line was replaced by the line below because the COFF linker
// can't handle COMDATs
//
DName __near UnDecorator::composeDeclaration ( const DName & symbol )
#else
inline DName __near UnDecorator::composeDeclaration ( const DName & symbol )
#endif
{
FTRACE(composeDeclaration);
DName declaration;
unsigned int typeCode = getTypeEncoding ();
int symIsUDC = symbol.isUDC ();
// Handle bad typeCode's, or truncation
if ( TE_isbadtype ( typeCode ))
return DN_invalid;
elif ( TE_istruncated ( typeCode ))
return ( DN_truncated + symbol );
// This is a very complex part. The type of the declaration must be
// determined, and the exact composition must be dictated by this type.
// Is it any type of a function ?
// However, for ease of decoding, treat the 'localdtor' thunk as data, since
// its decoration is a function of the variable to which it belongs and not
// a usual function type of decoration.
#if ( NO_COMPILER_NAMES )
if ( TE_isthunk ( typeCode ))
return DN_invalid;
if ( TE_isfunction ( typeCode ))
#else // } elif !NO_COMPILER_NAMES {
if ( TE_isfunction ( typeCode ) && !( TE_isthunk ( typeCode ) && TE_islocaldtor ( typeCode )))
#endif // !NO_COMPILER_NAMES
{
// If it is based, then compose the 'based' prefix for the name
if ( TE_isbased ( typeCode ))
#if ( !VERS_PWB )
if ( doMSKeywords () && doAllocationModel ())
declaration = ' ' + getBasedType ();
else
#endif // !VERS_PWB
declaration |= getBasedType (); // Just lose the 'based-type'
#if ( !NO_COMPILER_NAMES )
// Check for some of the specially composed 'thunk's
if ( TE_isthunk ( typeCode ) && TE_isvcall ( typeCode ))
{
declaration += symbol + '{' + getCallIndex () + ',';
declaration += getVCallThunkType () + "}' ";
} // End of IF then
else
#endif // !NO_COMPILER_NAMES
{
DName vtorDisp;
DName adjustment;
DName thisType;
#if ( !NO_COMPILER_NAMES )
if ( TE_isthunk ( typeCode ))
{
if ( TE_isvtoradj ( typeCode ))
vtorDisp = getDisplacement ();
adjustment = getDisplacement ();
} // End of IF else
#endif // !NO_COMPILER_NAMES
// Get the 'this-type' for non-static function members
if ( TE_ismember ( typeCode ) && !TE_isstatic ( typeCode ))
#if ( !VERS_PWB )
if ( doThisTypes ())
thisType = getThisType ();
else
#endif // !VERS_PWB
thisType |= getThisType ();
#if ( !VERS_PWB )
if ( doMSKeywords ())
{
// Attach the calling convention
if ( doAllocationLanguage ())
declaration = getCallingConvention () + declaration; // What calling convention ?
else
declaration |= getCallingConvention (); // Just lose the 'calling-convention'
// Any model specifiers ?
if ( doAllocationModel ())
if ( TE_isnear ( typeCode ))
declaration = UScore ( TOK_nearSp ) + declaration;
elif ( TE_isfar ( typeCode ))
declaration = UScore ( TOK_farSp ) + declaration;
} // End of IF
else
#endif // !VERS_PWB
declaration |= getCallingConvention (); // Just lose the 'calling-convention'
// Now put them all together
if ( !symbol.isEmpty ())
if ( !declaration.isEmpty ()) // And the symbol name
declaration += ' ' + symbol;
else
declaration = symbol;
// Compose the return type, catching the UDC case
DName * pDeclarator = 0;
DName returnType;
if ( symIsUDC ) // Is the symbol a UDC operator ?
declaration += "`" + getReturnType () + "' ";
else
{
pDeclarator = gnew DName;
returnType = getReturnType ( pDeclarator );
} // End of IF else
#if ( !NO_COMPILER_NAMES )
// Add the displacements for virtual function thunks
if ( TE_isthunk ( typeCode ))
{
if ( TE_isvtoradj ( typeCode ))
declaration += "`vtordisp{" + vtorDisp + ',';
else
declaration += "`adjustor{";
declaration += adjustment + "}' ";
} // End of IF
#endif // !NO_COMPILER_NAMES
// Add the function argument prototype
declaration += '(' + getArgumentTypes () + ')';
// If this is a non-static member function, append the 'this' modifiers
if ( TE_ismember ( typeCode ) && !TE_isstatic ( typeCode ))
declaration += thisType;
// Add the 'throw' signature
#if ( !VERS_PWB )
if ( doThrowTypes ())
declaration += getThrowTypes ();
else
#endif // !VERS_PWB
declaration |= getThrowTypes (); // Just lose the 'throw-types'
#if ( !VERS_PWB )
// If it has a declarator, then insert it into the declaration,
// sensitive to the return type composition
if ( doFunctionReturns () && pDeclarator )
{
*pDeclarator = declaration;
declaration = returnType;
} // End of IF
#endif // !VERS_PWB
} // End of IF else
} // End of IF then
else
{
declaration += symbol;
// Catch the special handling cases
#if ( !NO_COMPILER_NAMES )
if ( TE_isvftable ( typeCode ))
return getVfTableType ( declaration );
elif ( TE_isvbtable ( typeCode ))
return getVbTableType ( declaration );
elif ( TE_isguard ( typeCode ))
return ( declaration + '{' + getGuardNumber () + "}'" );
elif ( TE_isthunk ( typeCode ) && TE_islocaldtor ( typeCode ))
declaration += "`local static destructor helper'";
elif ( TE_ismetaclass ( typeCode ))
#pragma message ( "NYI: Meta Class" )
#else // } elif NO_COMPILER_NAMES {
if ( TE_isvftable ( typeCode )
|| TE_isvbtable ( typeCode )
|| TE_isguard ( typeCode )
|| TE_ismetaclass ( typeCode ))
#endif // NO_COMPILER_NAMES
return DN_invalid;
// All others are decorated as data symbols
declaration = getExternalDataType ( declaration );
} // End of IF else
#if ( !VERS_PWB )
// Prepend the 'virtual' and 'static' attributes for members
if ( TE_ismember ( typeCode ))
{
if ( doMemberTypes ())
{
if ( TE_isstatic ( typeCode ))
declaration = "static " + declaration;
if ( TE_isvirtual ( typeCode ) || ( TE_isthunk ( typeCode ) && ( TE_isvtoradj ( typeCode ) || TE_isadjustor ( typeCode ))))
declaration = "virtual " + declaration;
} // End of IF
// Prepend the access specifiers
if ( doAccessSpecifiers ())
if ( TE_isprivate ( typeCode ))
declaration = "private: " + declaration;
elif ( TE_isprotected ( typeCode ))
declaration = "protected: " + declaration;
elif ( TE_ispublic ( typeCode ))
declaration = "public: " + declaration;
} // End of IF
#endif // !VERS_PWB
#if ( !NO_COMPILER_NAMES )
// If it is a thunk, mark it appropriately
if ( TE_isthunk ( typeCode ))
declaration = "[thunk]:" + declaration;
#endif // !NO_COMPILER_NAMES
// Return the composed declaration
return declaration;
} // End of "UnDecorator" FUNCTION "composeDeclaration"
inline int __near UnDecorator::getTypeEncoding ( void )
{
FTRACE(getTypeEncoding);
unsigned int typeCode = 0u;
// Strip any leading '_' which indicates that it is based
if ( *gName == '_' )
{
TE_setisbased ( typeCode );
gName++;
} // End of IF
// Now handle the code proper :-
if (( *gName >= 'A' ) && ( *gName <= 'Z' )) // Is it some sort of function ?
{
int code = *gName++ - 'A';
// Now determine the function type
TE_setisfunction ( typeCode ); // All of them are functions ?
// Determine the calling model
if ( code & TE_far )
TE_setisfar ( typeCode );
else
TE_setisnear ( typeCode );
// Is it a member function or not ?
if ( code < TE_external )
{
// Record the fact that it is a member
TE_setismember ( typeCode );
// What access permissions does it have
switch ( code & TE_access )
{
case TE_private:
TE_setisprivate ( typeCode );
break;
case TE_protect:
TE_setisprotected ( typeCode );
break;
case TE_public:
TE_setispublic ( typeCode );
break;
default:
TE_setisbadtype ( typeCode );
return typeCode;
} // End of SWITCH
// What type of a member function is it ?
switch ( code & TE_adjustor )
{
case TE_adjustor:
TE_setisadjustor ( typeCode );
break;
case TE_virtual:
TE_setisvirtual ( typeCode );
break;
case TE_static:
TE_setisstatic ( typeCode );
break;
case TE_member:
break;
default:
TE_setisbadtype ( typeCode );
return typeCode;
} // End of SWITCH
} // End of IF
} // End of IF then
elif ( *gName == '$' ) // Extended set ? Special handling
{
// What type of symbol is it ?
switch ( *( ++gName ))
{
case 'A': // A destructor helper for a local static ?
TE_setislocaldtor ( typeCode );
break;
case 'B': // A VCall-thunk ?
TE_setisvcall ( typeCode );
break;
case 0:
TE_setistruncated ( typeCode );
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5': // Construction displacement adjustor thunks
{
int code = *gName - '0';
// Set up the principal type information
TE_setisfunction ( typeCode );
TE_setismember ( typeCode );
TE_setisvtoradj ( typeCode );
// Is it 'near' or 'far' ?
if ( code & TE_far )
TE_setisfar ( typeCode );
else
TE_setisnear ( typeCode );
// What type of access protection ?
switch ( code & TE_access_vadj )
{
case TE_private_vadj:
TE_setisprivate ( typeCode );
break;
case TE_protect_vadj:
TE_setisprotected ( typeCode );
break;
case TE_public_vadj:
TE_setispublic ( typeCode );
break;
default:
TE_setisbadtype ( typeCode );
return typeCode;
} // End of SWITCH
} // End of CASE '0,1,2,3,4,5'
break;
default:
TE_setisbadtype ( typeCode );
return typeCode;
} // End of SWITCH
// Advance past the code character
gName++;
} // End of ELIF then
elif (( *gName >= TE_static_d ) && ( *gName <= TE_metatype )) // Non function decorations ?
{
int code = *gName++;
TE_setisdata ( typeCode );
// What type of symbol is it ?
switch ( code )
{
case ( TE_static_d | TE_private_d ):
TE_setisstatic ( typeCode );
TE_setisprivate ( typeCode );
break;
case ( TE_static_d | TE_protect_d ):
TE_setisstatic ( typeCode );
TE_setisprotected ( typeCode );
break;
case ( TE_static_d | TE_public_d ):
TE_setisstatic ( typeCode );
TE_setispublic ( typeCode );
break;
case TE_global:
TE_setisglobal ( typeCode );
break;
#if ( !VERS_PWB )
case TE_guard:
TE_setisguard ( typeCode );
break;
case TE_local:
TE_setislocal ( typeCode );
break;
case TE_vftable:
TE_setisvftable ( typeCode );
break;
case TE_vbtable:
TE_setisvbtable ( typeCode );
break;
case TE_metatype:
#pragma message ( "NYI: MetaClass Information" )
#else // } elif VERS_PWB {
case TE_guard:
case TE_local:
case TE_vftable:
case TE_vbtable:
case TE_metatype:
#endif // VERS_PWB
default:
TE_setisbadtype ( typeCode );
return typeCode;
} // End of SWITCH
} // End of ELIF then
elif ( *gName )
TE_setisbadtype ( typeCode );
else
TE_setistruncated ( typeCode );
// Return the composed type code
return typeCode;
} // End of "UnDecorator" FUNCTION "getTypeEncoding"
DName __near UnDecorator::getBasedType ( void )
{
FTRACE(getBasedType);
#if ( !VERS_PWB )
DName basedDecl ( UScore ( TOK_basedLp ));
#else // } elif VERS_PWB {
DName basedDecl;
#endif // VERS_PWB
// What type of 'based' is it ?
if ( *gName )
{
switch ( *gName++ )
{
#if ( !VERS_PWB )
case BT_segname:
basedDecl += UScore ( TOK_segnameLpQ ) + getSegmentName () + "\")";
break;
case BT_segment:
basedDecl += DName ( "NYI:" ) + UScore ( TOK_segment );
break;
case BT_void:
basedDecl += "void";
break;
case BT_self:
basedDecl += UScore ( TOK_self );
break;
case BT_nearptr:
basedDecl += DName ( "NYI:" ) + UScore ( TOK_nearP );
break;
case BT_farptr:
basedDecl += DName ( "NYI:" ) + UScore ( TOK_farP );
break;
case BT_hugeptr:
basedDecl += DName ( "NYI:" ) + UScore ( TOK_hugeP );
break;
case BT_segaddr:
basedDecl += "NYI:<segment-address-of-variable>";
break;
#else // } elif VERS_PWB {
case BT_segname:
basedDecl |= getZName ();
break;
case BT_segment:
case BT_void:
case BT_self:
case BT_nearptr:
case BT_farptr:
case BT_hugeptr:
case BT_segaddr:
break;
#endif // VERS_PWB
case BT_basedptr:
#pragma message ( "NOTE: Reserved. Based pointer to based pointer" )
return DN_invalid;
} // End of SWITCH
} // End of IF else
else
basedDecl += DN_truncated;
#if ( !VERS_PWB )
// Close the based syntax
basedDecl += ") ";
#endif // !VERS_PWB
// Return completed based declaration
return basedDecl;
} // End of "UnDecorator" FUNCTION "getBasedType"
DName __near UnDecorator::getECSUName ( void )
{
FTRACE(getECSUName);
DName ecsuName;
// Get the beginning of the name
if ( *gName == '?' )
{
#if ( !VERS_PWB )
gName++;
ecsuName = getTemplateName ();
#else // } elif VERS_PWB {
return DN_invalid;
#endif // VERS_PWB
} // End of IF then
else
ecsuName = getZName ();
// Now the scope (if any)
if (( ecsuName.status () == DN_valid ) && *gName && ( *gName != '@' ))
ecsuName = getScope () + "::" + ecsuName;
// Skip the trailing '@'
if ( *gName == '@' )
gName++;
elif ( *gName )
ecsuName = DN_invalid;
elif ( ecsuName.isEmpty ())
ecsuName = DN_truncated;
else
ecsuName = DName ( DN_truncated ) + "::" + ecsuName;
// And return the complete name
return ecsuName;
} // End of "UnDecorator" FUNCTION "getECSUName"
inline DName __near UnDecorator::getEnumName ( void )
{
FTRACE(getEnumName);
#if ( !VERS_PWB )
DName ecsuName;
#endif // !VERS_PWB
if ( *gName )
{
#if ( !VERS_PWB )
// What type of an 'enum' is it ?
switch ( *gName )
{
case ET_schar:
case ET_uchar:
ecsuName = "char ";
break;
case ET_sshort:
case ET_ushort:
ecsuName = "short ";
break;
case ET_sint:
break;
case ET_uint:
ecsuName = "int ";
break;
case ET_slong:
case ET_ulong:
ecsuName = "long ";
break;
default:
return DN_invalid;
} // End of SWITCH
// Add the 'unsigned'ness if appropriate
switch ( *gName++ )
{
case ET_uchar:
case ET_ushort:
case ET_uint:
case ET_ulong:
ecsuName = "unsigned " + ecsuName;
break;
} // End of SWITCH
// Now return the composed name
return ecsuName + getECSUName ();
#else // } elif VERS_PWB {
if ( *gName++ == ET_sint )
return getECSUName ();
else
return DN_invalid;
#endif // VERS_PWB
} // End of IF then
else
return DN_truncated;
} // End of "UnDecorator" FUNCTION "getEnumName"
DName __near UnDecorator::getCallingConvention ( void )
{
FTRACE(getCallingConvention);
if ( *gName )
{
unsigned int callCode = ((unsigned int)*gName++ ) - 'A';
// What is the primary calling convention
if (( callCode <= CC_interrupt ))
{
#if ( !VERS_PWB )
DName callType;
// Now, what type of 'calling-convention' is it, 'interrupt' is special ?
if ( doMSKeywords ())
if ( callCode == CC_interrupt )
callType = UScore ( TOK_interrupt );
else
{
switch ( callCode & ~CC_saveregs )
{
case CC_cdecl:
callType = UScore ( TOK_cdecl );
break;
case CC_pascal:
callType = UScore ( TOK_pascal );
break;
case CC_syscall:
callType = UScore ( TOK_syscall );
break;
case CC_stdcall:
callType = UScore ( TOK_stdcall );
break;
case CC_fastcall:
callType = UScore ( TOK_fastcall );
break;
} // End of SWITCH
// Has it also got 'saveregs' marked ?
if ( callCode & CC_saveregs )
callType += ' ' + UScore ( TOK_saveregs );
} // End of IF else
// And return
return callType;
#else // } elif VERS_PWB {
return DN_valid;
#endif // VERS_PWB
} // End of IF then
else
return DN_invalid;
} // End of IF then
else
return DN_truncated;
} // End of "UnDecorator" FUNCTION "getCallingConvention"
DName __near UnDecorator::getReturnType ( DName * pDeclarator )
{
FTRACE(getReturnType);
if ( *gName == '@' ) // Return type for constructors and destructors ?
{
gName++;
return DName ( pDeclarator );
} // End of IF then
else
return getDataType ( pDeclarator );
} // End of "UnDecorator" FUNCTION "getReturnType"
DName __near UnDecorator::getDataType ( DName * pDeclarator )
{
FTRACE(getDataType);
DName superType ( pDeclarator );
// What type is it ?
switch ( *gName )
{
case 0:
return ( DN_truncated + superType );
case DT_void:
gName++;
if ( superType.isEmpty ())
return "void";
else
return "void " + superType;
case '?':
{
int ecsuMods;
gName++; // Skip the '?'
ecsuMods = getECSUDataIndirectType ();
superType = getECSUDataType ( ecsuMods ) + ' ' + superType;
return superType;
} // End of CASE '?'
default:
return getPrimaryDataType ( superType );
} // End of SWITCH
} // End of "UnDecorator" FUNCTION "getDataType"
DName __near UnDecorator::getPrimaryDataType ( const DName & superType )
{
FTRACE(getPrimaryDataType);
DName cvType;
switch ( *gName )
{
case 0:
return ( DN_truncated + superType );
case PDT_volatileReference:
cvType = "volatile";
if ( !superType.isEmpty ())
cvType += ' ';
// No break
case PDT_reference:
{
DName super ( superType );
gName++;
return getReferenceType ( cvType, super.setPtrRef ());
} // End of CASE 'PDT_reference'
default:
return getBasicDataType ( superType );
} // End of SWITCH
} // End of "UnDecorator" FUNCTION "getPrimaryDataType"
DName __near UnDecorator::getArgumentTypes ( void )
{
FTRACE(getArgumentTypes);
switch ( *gName )
{
case AT_ellipsis:
return ( gName++, "..." );
case AT_void:
#if ( !VERS_PWB )
return ( gName++, "void" );
#else // } elif VERS_PWB {
return ( gName++, DName ());
#endif // VERS_PWB
default:
{
DName arguments ( getArgumentList ());
// Now, is it a varargs function or not ?
if ( arguments.status () == DN_valid )
switch ( *gName )
{
case 0:
return arguments;
case AT_ellipsis:
return ( gName++, arguments + ",..." );
case AT_endoflist:
return ( gName++, arguments );
default:
return DN_invalid;
} // End of SWITCH
else
return arguments;
} // End of DEFAULT
} // End of SWITCH
} // End of "UnDecorator" FUNCTION "getArgumentTypes"
inline_pwb DName __near UnDecorator::getArgumentList ( void )
{
FTRACE(getArgumentList);
int first = TRUE;
DName aList;
while (( aList.status () == DN_valid ) && ( *gName != AT_endoflist ) && ( *gName != AT_ellipsis ))
{
// Insert the argument list separator if not the first argument
if ( first )
first = FALSE;
else
aList += ',';
// Get the individual argument type
if ( *gName )
{
int argIndex = *gName - '0';
// Handle 'argument-replicators', otherwise a new argument type
if (( argIndex >= 0 ) && ( argIndex <= 9 ))
{
gName++; // Skip past the replicator
// Append to the argument list
aList += ( *pArgList )[ argIndex ];
} // End of IF then
else
{
// Extract the 'argument' type
DName arg ( getPrimaryDataType ( DName ()));
// Add it to the current list of 'argument's
if ( !pArgList->isFull ())
*pArgList += arg;
// Append to the argument list
aList += arg;
} // End of IF else
} // End of IF then
else
{
aList += DN_truncated;
break;
} // End of IF else
} // End of WHILE
// Return the completed argument list
return aList;
} // End of "UnDecorator" FUNCTION "getArgumentList"
DName __near UnDecorator::getThrowTypes ( void )
{
FTRACE(getThrowTypes);
if ( *gName )
#if ( !VERS_PWB )
if ( *gName == AT_ellipsis ) // Handle ellipsis here to suppress the 'throw' signature
return ( gName++, DName ());
else
return ( " throw(" + getArgumentTypes () + ')' );
else
return ( DName ( " throw(" ) + DN_truncated + ')' );
#else // } elif VERS_PWB {
if ( *gName++ == AT_ellipsis )
return DName ();
else
return DN_invalid;
else
return DN_truncated;
#endif // VERS_PWB
} // End of "UnDecorator" FUNCTION "getThrowTypes"
DName __near UnDecorator::getBasicDataType ( const DName & superType )
{
FTRACE(getBasicDataType);
if ( *gName )
{
unsigned char bdtCode = *gName++;
int pCvCode = -1;
DName basicDataType;
// Extract the principal type information itself, and validate the codes
switch ( bdtCode )
{
case BDT_schar:
case BDT_char:
case ( BDT_char | BDT_unsigned ):
basicDataType = "char";
break;
case BDT_short:
case ( BDT_short | BDT_unsigned ):
basicDataType = "short";
break;
case BDT_int:
case ( BDT_int | BDT_unsigned ):
basicDataType = "int";
break;
case BDT_long:
case ( BDT_long | BDT_unsigned ):
basicDataType = "long";
break;
case BDT_segment:
#if ( !VERS_PWB )
basicDataType = UScore ( TOK_segment );
#else // } elif VERS_PWB {
basicDataType = "__segment";
#endif // VERS_PWB
break;
case BDT_float:
basicDataType = "float";
break;
case BDT_longdouble:
basicDataType = "long ";
// No break
case BDT_double:
basicDataType += "double";
break;
case BDT_pointer:
case ( BDT_pointer | BDT_const ):
case ( BDT_pointer | BDT_volatile ):
case ( BDT_pointer | BDT_const | BDT_volatile ):
pCvCode = ( bdtCode & ( BDT_const | BDT_volatile ));
break;
default:
gName--; // Backup, since 'ecsu-data-type' does it's own decoding
basicDataType = getECSUDataType ();
if ( basicDataType.isEmpty ())
return basicDataType;
break;
} // End of SWITCH
// What type of basic data type composition is involved ?
if ( pCvCode == -1 ) // Simple ?
{
// Determine the 'signed/unsigned'ness
switch ( bdtCode )
{
case ( BDT_char | BDT_unsigned ):
case ( BDT_short | BDT_unsigned ):
case ( BDT_int | BDT_unsigned ):
case ( BDT_long | BDT_unsigned ):
basicDataType = "unsigned " + basicDataType;
break;
case BDT_schar:
basicDataType = "signed " + basicDataType;
break;
} // End of SWITCH
// Add the indirection type to the type
if ( !superType.isEmpty ())
basicDataType += ' ' + superType;
// And return the completed type
return basicDataType;
} // End of IF then
else
{
DName cvType;
DName super ( superType );
// Is it 'const/volatile' qualified ?
if ( pCvCode & BDT_const )
{
cvType = "const";
if ( pCvCode & BDT_volatile )
cvType += " volatile";
} // End of IF then
elif ( pCvCode & BDT_volatile )
cvType = "volatile";
// Construct the appropriate pointer type declaration
return getPointerType ( cvType, super.setPtrRef ());
} // End of IF else
} // End of IF then
else
return ( DN_truncated + superType );
} // End of "UnDecorator" FUNCTION "getBasicDataType"
DName __near UnDecorator::getECSUDataType ( int ecsuMods )
{
FTRACE(getECSUDataType);
DName ecsuDataType;
// Get the 'model' modifiers if applicable
if ( ecsuMods )
if ( ecsuMods == ECSU_invalid )
return DN_invalid;
elif ( ecsuMods == ECSU_truncated )
ecsuDataType = DN_truncated;
#if ( !VERS_PWB )
else
switch ( ecsuMods & ECSU_modelmask )
{
case ECSU_near:
if ( doMSKeywords () && doReturnUDTModel ())
ecsuDataType = UScore ( TOK_nearSp );
break;
case ECSU_far:
if ( doMSKeywords () && doReturnUDTModel ())
ecsuDataType = UScore ( TOK_farSp );
break;
case ECSU_huge:
if ( doMSKeywords () && doReturnUDTModel ())
ecsuDataType = UScore ( TOK_hugeSp );
break;
case ECSU_based:
if ( doMSKeywords () && doReturnUDTModel ())
ecsuDataType = getBasedType ();
else
ecsuDataType |= getBasedType (); // Just lose the 'based-type'
break;
} // End of SWITCH
#else // } elif VERS_PWB {
elif (( ecsuMods & ECSU_modelmask ) == ECSU_based )
ecsuDataType |= getBasedType ();
#endif // VERS_PWB
// Extract the principal type information itself, and validate the codes
switch ( *gName++ )
{
case 0:
gName--; // Backup to permit later error recovery to work safely
return "`unknown ecsu'" + ecsuDataType + DN_truncated;
case BDT_union:
if ( 1 ) // Non-redundant control flow trick
ecsuDataType = "union " + ecsuDataType;
else
case BDT_struct:
if ( 1 ) // Non-redundant control flow trick
ecsuDataType = "struct " + ecsuDataType;
else
case BDT_class:
if ( 1 ) // Non-redundant control flow trick
ecsuDataType = "class " + ecsuDataType;
// Get the UDT 'const/volatile' modifiers if applicable
// Get the 'class/struct/union' name
ecsuDataType += getECSUName ();
break;
case BDT_enum:
ecsuDataType = "enum " + ecsuDataType + getEnumName ();
break;
default:
return DN_invalid;
} // End of SWITCH
// And return the formed 'ecsu-data-type'
return ecsuDataType;
} // End of "UnDecorator" FUNCTION "getECSUDataType"
DName __near UnDecorator::getPtrRefType ( const DName & cvType, const DName & superType, int isPtr )
{
FTRACE(getPtrRefType);
// Doubles up as 'pointer-type' and 'reference-type'
if ( *gName )
if ( IT_isfunction ( *gName )) // Is it a function or data indirection ?
{
// Since I haven't coded a discrete 'function-type', both
// 'function-indirect-type' and 'function-type' are implemented
// inline under this condition.
int fitCode = *gName++ - '6';
if ( fitCode == ( '_' - '6' ))
{
if ( *gName )
{
fitCode = *gName++ - 'A' + FIT_based;
if (( fitCode < FIT_based ) || ( fitCode > ( FIT_based | FIT_far | FIT_member )))
fitCode = -1;
} // End of IF then
else
return ( DN_truncated + superType );
} // End of IF then
elif (( fitCode < FIT_near ) || ( fitCode > ( FIT_far | FIT_member )))
fitCode = -1;
// Return if invalid name
if ( fitCode == -1 )
return DN_invalid;
// Otherwise, what are the function indirect attributes
DName thisType;
DName fitType = ( isPtr ? '*' : '&' );
if ( !cvType.isEmpty () && ( superType.isEmpty () || superType.isPtrRef ()))
fitType += cvType;
if ( !superType.isEmpty ())
fitType += superType;
// Is it a pointer to member function ?
if ( fitCode & FIT_member )
{
fitType = "::" + fitType;
if ( *gName )
fitType = ' ' + getScope ();
else
fitType = DN_truncated + fitType;
if ( *gName )
if ( *gName == '@' )
gName++;
else
return DN_invalid;
else
return ( DN_truncated + fitType );
#if ( !VERS_PWB )
if ( doThisTypes ())
thisType = getThisType ();
else
#endif // !VERS_PWB
thisType |= getThisType ();
} // End of IF
// Is it a based allocated function ?
if ( fitCode & FIT_based )
#if ( !VERS_PWB )
if ( doMSKeywords ())
fitType = ' ' + getBasedType () + fitType;
else
#endif // !VERS_PWB
fitType |= getBasedType (); // Just lose the 'based-type'
// Get the 'calling-convention'
#if ( !VERS_PWB )
if ( doMSKeywords ())
{
fitType = getCallingConvention () + fitType;
// Is it a near or far function pointer
fitType = UScore ((( fitCode & FIT_far ) ? TOK_farSp : TOK_nearSp )) + fitType;
} // End of IF then
else
#endif // !VERS_PWB
fitType |= getCallingConvention (); // Just lose the 'calling-convention'
// Parenthesise the indirection component, and work on the rest
fitType = '(' + fitType + ')';
// Get the rest of the 'function-type' pieces
DName * pDeclarator = gnew DName;
DName returnType ( getReturnType ( pDeclarator ));
fitType += '(' + getArgumentTypes () + ')';
#if ( !VERS_PWB )
if ( doThisTypes () && ( fitCode & FIT_member ))
fitType += thisType;
if ( doThrowTypes ())
fitType += getThrowTypes ();
else
#endif // !VERS_PWB
fitType |= getThrowTypes (); // Just lose the 'throw-types'
// Now insert the indirected declarator, catch the allocation failure here
if ( pDeclarator )
*pDeclarator = fitType;
else
return ERROR;
// And return the composed function type (now in 'returnType' )
return returnType;
} // End of IF then
else
{
// Otherwise, it is either a pointer or a reference to some data type
DName innerType ( getDataIndirectType ( superType, ( isPtr ? '*' : '&' ), cvType ));
return getPtrRefDataType ( innerType, isPtr );
} // End of IF else
else
{
DName trunk ( DN_truncated );
trunk += ( isPtr ? '*' : '&' );
if ( !cvType.isEmpty ())
trunk += cvType;
if ( !superType.isEmpty ())
{
if ( !cvType.isEmpty ())
trunk += ' ';
trunk += superType;
} // End of IF
return trunk;
} // End of IF else
} // End of "UnDecorator" FUNCTION "getPtrRefType"
DName __near UnDecorator::getDataIndirectType ( const DName & superType, char prType, const DName & cvType, int thisFlag )
{
FTRACE(getDataIndirectType);
if ( *gName )
{
unsigned int ditCode = ( *gName - (( *gName >= 'A' ) ? (unsigned int)'A': (unsigned int)( '0' - 26 )));
gName++; // Skip to next character in name
// Is it a valid 'data-indirection-type' ?
if (( ditCode <= ( DIT_const | DIT_volatile | DIT_modelmask | DIT_member )))
{
DName ditType ( prType );
// If it is a member, then these attributes immediately precede the indirection token
if ( ditCode & DIT_member )
{
// If it is really 'this-type', then it cannot be any form of pointer to member
if ( thisFlag )
return DN_invalid;
// Otherwise, extract the scope for the PM
ditType = "::" + ditType;
if ( *gName )
ditType = ' ' + getScope ();
else
ditType = DN_truncated + ditType;
// Now skip the scope terminator
if ( !*gName )
ditType += DN_truncated;
elif ( *gName++ != '@' )
return DN_invalid;
} // End of IF
#if ( !VERS_PWB )
// Add the 'model' attributes (prefixed) as appropriate
if ( doMSKeywords ())
switch ( ditCode & DIT_modelmask )
{
case DIT_near:
ditType = UScore ( TOK_near ) + ditType;
break;
case DIT_far:
ditType = UScore ( TOK_far ) + ditType;
break;
case DIT_huge:
ditType = UScore ( TOK_huge ) + ditType;
break;
case DIT_based:
// The 'this-type' can never be 'based'
if ( thisFlag )
return DN_invalid;
ditType = getBasedType () + ditType;
break;
} // End of SWITCH
elif (( ditCode & DIT_modelmask ) == DIT_based )
#else // } elif VERS_PWB {
if (( ditCode & DIT_modelmask ) == DIT_based )
#endif // VERS_PWB
ditType |= getBasedType (); // Just lose the 'based-type'
// Handle the 'const' and 'volatile' attributes
if ( ditCode & DIT_volatile )
ditType = "volatile " + ditType;
if ( ditCode & DIT_const )
ditType = "const " + ditType;
// Append the supertype, if not 'this-type'
if ( !thisFlag )
if ( !superType.isEmpty ())
{
// Is the super context included 'cv' information, ensure that it is added appropriately
if ( superType.isPtrRef () || cvType.isEmpty ())
ditType += ' ' + superType;
else
ditType += ' ' + cvType + ' ' + superType;
} // End of IF then
elif ( !cvType.isEmpty ())
ditType += ' ' + cvType;
// Finally, return the composed 'data-indirection-type' (with embedded sub-type)
return ditType;
} // End of IF then
else
return DN_invalid;
} // End of IF then
elif ( !thisFlag && !superType.isEmpty ())
{
// Is the super context included 'cv' information, ensure that it is added appropriately
if ( superType.isPtrRef () || cvType.isEmpty ())
return ( DN_truncated + superType );
else
return ( DN_truncated + cvType + ' ' + superType );
} // End of ELIF then
elif ( !thisFlag && !cvType.isEmpty ())
return ( DN_truncated + cvType );
else
return DN_truncated;
} // End of "UnDecorator" FUNCTION "getDataIndirectType"
inline int __near UnDecorator::getECSUDataIndirectType ()
{
FTRACE(getECSUDataIndirectType);
if ( *gName )
{
unsigned int ecsuCode = *gName++ - 'A';
// Is it a valid 'ecsu-data-indirection-type' ?
if (( ecsuCode <= ( ECSU_const | ECSU_volatile | ECSU_modelmask )))
return ( ecsuCode | ECSU_valid );
else
return ECSU_invalid;
} // End of IF then
else
return ECSU_truncated;
} // End of "UnDecorator" FUNCTION "getECSUDataIndirectType"
inline DName __near UnDecorator::getPtrRefDataType ( const DName & superType, int isPtr )
{
FTRACE(getPtrRefDataType);
// Doubles up as 'pointer-data-type' and 'reference-data-type'
if ( *gName )
{
// Is this a 'pointer-data-type' ?
if ( isPtr && ( *gName == PoDT_void ))
{
gName++; // Skip this character
if ( superType.isEmpty ())
return "void";
else
return "void " + superType;
} // End of IF
// Otherwise it may be a 'reference-data-type'
if ( *gName == RDT_array ) // An array ?
{
DName * pDeclarator = gnew DName;
if ( !pDeclarator )
return ERROR;
gName++;
DName theArray ( getArrayType ( pDeclarator ));
if ( !theArray.isEmpty ())
*pDeclarator = superType;
// And return it
return theArray;
} // End of IF
// Otherwise, it is a 'basic-data-type'
return getBasicDataType ( superType );
} // End of IF then
else
return ( DN_truncated + superType );
} // End of "UnDecorator" FUNCTION "getPtrRefDataType"
inline DName __near UnDecorator::getArrayType ( DName * pDeclarator )
{
FTRACE(getArrayType);
DName superType ( pDeclarator );
if ( *gName )
{
int noDimensions = getNumberOfDimensions ();
if ( !noDimensions )
return getBasicDataType ( DName ( '[' ) + DN_truncated + ']' );
else
{
DName arrayType;
while ( noDimensions-- )
arrayType += '[' + getDimension () + ']';
// If it is indirect, then parenthesise the 'super-type'
if ( !superType.isEmpty ())
arrayType = '(' + superType + ')' + arrayType;
// Return the finished array dimension information
return getBasicDataType ( arrayType );
} // End of IF else
} // End of IF
elif ( !superType.isEmpty ())
return getBasicDataType ( '(' + superType + ")[" + DN_truncated + ']' );
else
return getBasicDataType ( DName ( '[' ) + DN_truncated + ']' );
} // End of "UnDecorator" FUNCTION "getArrayType"
inline DName __near UnDecorator::getLexicalFrame ( void ) { return '`' + getDimension () + '\''; }
inline DName __near UnDecorator::getStorageConvention ( void ) { return getDataIndirectType (); }
inline DName __near UnDecorator::getDataIndirectType () { return getDataIndirectType ( DName (), 0, DName ()); }
inline_lnk DName __near UnDecorator::getThisType ( void ) { return getDataIndirectType ( DName (), 0, DName (), TRUE ); }
inline DName __near UnDecorator::getPointerType ( const DName & cv, const DName & name )
{ return getPtrRefType ( cv, name, TRUE ); }
inline DName __near UnDecorator::getReferenceType ( const DName & cv, const DName & name )
{ return getPtrRefType ( cv, name, FALSE ); }
#if ( !VERS_PWB )
inline DName __near UnDecorator::getSegmentName ( void ) { return getZName (); }
#endif // !VERS_PWB
#if ( !NO_COMPILER_NAMES )
inline DName __near UnDecorator::getDisplacement ( void ) { return getDimension (); }
inline DName __near UnDecorator::getCallIndex ( void ) { return getDimension (); }
inline DName __near UnDecorator::getGuardNumber ( void ) { return getDimension (); }
inline DName __near UnDecorator::getVbTableType ( const DName & superType )
{ return getVfTableType ( superType ); }
inline DName __near UnDecorator::getVCallThunkType ( void )
{
FTRACE(UnDecorator::getVCallThunkType);
DName vcallType = '{';
// Get the 'this' model, and validate all values
switch ( *gName )
{
case VMT_nTnCnV:
case VMT_nTfCnV:
case VMT_nTnCfV:
case VMT_nTfCfV:
case VMT_nTnCbV:
case VMT_nTfCbV:
vcallType += UScore ( TOK_nearSp );
break;
case VMT_fTnCnV:
case VMT_fTfCnV:
case VMT_fTnCfV:
case VMT_fTfCfV:
case VMT_fTnCbV:
case VMT_fTfCbV:
vcallType += UScore ( TOK_farSp );
break;
case 0:
return DN_truncated;
default:
return DN_invalid;
} // End of SWITCH
// Always append 'this'
vcallType += "this, ";
// Get the 'call' model
switch ( *gName )
{
case VMT_nTnCnV:
case VMT_fTnCnV:
case VMT_nTnCfV:
case VMT_fTnCfV:
case VMT_nTnCbV:
case VMT_fTnCbV:
vcallType += UScore ( TOK_nearSp );
break;
case VMT_nTfCnV:
case VMT_fTfCnV:
case VMT_nTfCfV:
case VMT_fTfCfV:
case VMT_nTfCbV:
case VMT_fTfCbV:
vcallType += UScore ( TOK_farSp );
break;
} // End of SWITCH
// Always append 'call'
vcallType += "call, ";
// Get the 'vfptr' model
switch ( *gName++ ) // Last time, so advance the pointer
{
case VMT_nTnCnV:
case VMT_nTfCnV:
case VMT_fTnCnV:
case VMT_fTfCnV:
vcallType += UScore ( TOK_nearSp );
break;
case VMT_nTnCfV:
case VMT_nTfCfV:
case VMT_fTnCfV:
case VMT_fTfCfV:
vcallType += UScore ( TOK_farSp );
break;
case VMT_nTnCbV:
case VMT_nTfCbV:
case VMT_fTnCbV:
case VMT_fTfCbV:
vcallType += getBasedType ();
break;
} // End of SWITCH
// Always append 'vfptr'
vcallType += "vfptr}";
// And return the resultant 'vcall-model-type'
return vcallType;
} // End of "UnDecorator" FUNCTION "getVCallThunk"
inline DName __near UnDecorator::getVfTableType ( const DName & superType )
{
FTRACE(UnDecorator::getVfTableType);
DName vxTableName = superType;
if ( vxTableName.isValid () && *gName )
{
vxTableName = getStorageConvention () + ' ' + vxTableName;
if ( vxTableName.isValid ())
{
if ( *gName != '@' )
{
vxTableName += "{for ";
while ( vxTableName.isValid () && *gName && ( *gName != '@' ))
{
vxTableName += '`' + getScope () + '\'';
// Skip the scope delimiter
if ( *gName == '@' )
gName++;
// Close the current scope, and add a conjunction for the next (if any)
if ( vxTableName.isValid () && ( *gName != '@' ))
vxTableName += "s ";
} // End of WHILE
if ( vxTableName.isValid ())
{
if ( !*gName )
vxTableName += DN_truncated;
vxTableName += '}';
} // End of IF
} // End of IF
// Skip the 'vpath-name' terminator
if ( *gName == '@' )
gName++;
} // End of IF
} // End of IF then
elif ( vxTableName.isValid ())
vxTableName = DN_truncated + vxTableName;
return vxTableName;
} // End of "UnDecorator" FUNCTION "getVfTableType"
#endif // !NO_COMPILER_NAMES
inline DName __near UnDecorator::getExternalDataType ( const DName & superType )
{
FTRACE(UnDecorator::getExternalDataType);
// Create an indirect declarator for the the rest
DName * pDeclarator = gnew DName ();
DName declaration = getDataType ( pDeclarator );
// Now insert the declarator into the declaration along with its 'storage-convention'
*pDeclarator = getStorageConvention () + ' ' + superType;
return declaration;
} // End of "UnDecorator" FUNCTION "getExternalDataType"
#endif // !VERS_P3
#if ( !NO_OPTIONS )
inline int __near UnDecorator::doUnderScore () { return !( disableFlags & UNDNAME_NO_LEADING_UNDERSCORES ); }
inline int __near UnDecorator::doMSKeywords () { return !( disableFlags & UNDNAME_NO_MS_KEYWORDS ); }
inline int __near UnDecorator::doFunctionReturns () { return !( disableFlags & UNDNAME_NO_FUNCTION_RETURNS ); }
inline int __near UnDecorator::doAllocationModel () { return !( disableFlags & UNDNAME_NO_ALLOCATION_MODEL ); }
inline int __near UnDecorator::doAllocationLanguage () { return !( disableFlags & UNDNAME_NO_ALLOCATION_LANGUAGE ); }
#if 0
inline int __near UnDecorator::doMSThisType () { return !( disableFlags & UNDNAME_NO_MS_THISTYPE ); }
inline int __near UnDecorator::doCVThisType () { return !( disableFlags & UNDNAME_NO_CV_THISTYPE ); }
#endif
inline int __near UnDecorator::doThisTypes () { return (( disableFlags & UNDNAME_NO_THISTYPE ) != UNDNAME_NO_THISTYPE ); }
inline int __near UnDecorator::doAccessSpecifiers () { return !( disableFlags & UNDNAME_NO_ACCESS_SPECIFIERS ); }
inline int __near UnDecorator::doThrowTypes () { return !( disableFlags & UNDNAME_NO_THROW_SIGNATURES ); }
inline int __near UnDecorator::doMemberTypes () { return !( disableFlags & UNDNAME_NO_MEMBER_TYPE ); }
inline int __near UnDecorator::doReturnUDTModel () { return !( disableFlags & UNDNAME_NO_RETURN_UDT_MODEL ); }
#endif // !NO_OPTIONS
#if ( !VERS_P3 && !VERS_PWB )
pcchar_t __near UnDecorator::UScore ( Tokens tok )
{
FTRACE(UnDecorator::UScore);
#if ( !NO_OPTIONS )
return ( doUnderScore () ? tokenTable[ tok ] : tokenTable[ tok ] + 2 );
#else // } elif NO_OPTIONS {
return tokenTable[ tok ];
#endif // NO_OPTIONS
} // End of "UnDecorator" FUNCTION "UScore"
#endif // !VERS_P3 && !VERS_PWB
#include "undname.inl"