You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4049 lines
91 KiB
4049 lines
91 KiB
|
|
// Make sure all dependent defines exist and have a valid value
|
|
|
|
#ifndef NO_COMPILER_NAMES
|
|
#define NO_COMPILER_NAMES 0
|
|
#endif
|
|
|
|
#ifndef VERS_32BIT
|
|
#define VERS_32BIT 1
|
|
#endif
|
|
|
|
#ifndef PACK_SIZE
|
|
#ifdef _CRTBLD
|
|
#define PACK_SIZE 8
|
|
#elif !VERS_32BIT
|
|
#define PACK_SIZE 2
|
|
#elif defined(_X86_)
|
|
#define PACK_SIZE 4
|
|
#else
|
|
#define PACK_SIZE 8
|
|
#endif
|
|
#endif
|
|
|
|
// Check for version inconsistancies, and setup version flags
|
|
|
|
#ifdef VERS_BSC
|
|
#undef NO_COMPILER_NAMES
|
|
#define NO_COMPILER_NAMES 1
|
|
|
|
#pragma inline_depth ( 3 )
|
|
#pragma check_stack ( off )
|
|
#else
|
|
#pragma inline_depth ( 3 )
|
|
#pragma check_stack ( off )
|
|
#endif
|
|
|
|
|
|
#define PURE = 0
|
|
|
|
#ifndef CC_COR
|
|
#define CC_COR 1
|
|
#endif
|
|
|
|
#include "undname.hxx"
|
|
|
|
#if !defined(_CRTBLD) && (!VERSP_RELEASE || defined(_DEBUG))
|
|
#include <assert.h>
|
|
#define DASSERT(x) assert(x)
|
|
#else
|
|
#define DASSERT(x)
|
|
#endif
|
|
|
|
#if (defined(_CRTBLD) && defined(_MT))
|
|
#include <mtdll.h>
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <windows.h>
|
|
#include "utf8.h"
|
|
|
|
#pragma warning(disable:4291) // No matching operator delete
|
|
|
|
static unsigned int und_strlen ( pcchar_t );
|
|
static pchar_t und_strncpy ( pchar_t, pcchar_t, unsigned int );
|
|
static unsigned int und_strncmp ( pcchar_t, pcchar_t, unsigned int );
|
|
|
|
class DName;
|
|
class DNameNode;
|
|
class Replicator;
|
|
class HeapManager;
|
|
class UnDecorator;
|
|
|
|
|
|
// A '512' byte block including the header
|
|
const unsigned int memBlockSize = 512 - sizeof(void*);
|
|
|
|
|
|
class HeapManager
|
|
{
|
|
private:
|
|
Alloc_t pOpNew;
|
|
Free_t pOpDelete;
|
|
|
|
struct Block
|
|
{
|
|
Block * next;
|
|
char memBlock[ memBlockSize ];
|
|
|
|
__near Block () { next = 0; }
|
|
|
|
};
|
|
|
|
Block * head;
|
|
Block * tail;
|
|
size_t blockLeft;
|
|
|
|
public:
|
|
void __near Constructor ( Alloc_t pAlloc, Free_t pFree )
|
|
{ pOpNew = pAlloc;
|
|
pOpDelete = pFree;
|
|
blockLeft = 0;
|
|
head = 0;
|
|
tail = 0;
|
|
}
|
|
|
|
void __far * __near getMemory ( size_t, int );
|
|
|
|
void __near Destructor ( void )
|
|
{ if ( pOpDelete != 0 )
|
|
while ( tail = head )
|
|
{
|
|
head = tail->next;
|
|
|
|
( *pOpDelete )( tail );
|
|
|
|
}
|
|
}
|
|
|
|
#define gnew new(heap,0)
|
|
#define rnew new(heap,1)
|
|
|
|
};
|
|
|
|
|
|
|
|
void * operator new ( size_t, HeapManager &, int = 0 );
|
|
|
|
|
|
|
|
static HeapManager heap;
|
|
|
|
|
|
// The MS Token table
|
|
|
|
enum Tokens
|
|
{
|
|
#if !VERS_32BIT
|
|
TOK_near,
|
|
TOK_nearSp,
|
|
TOK_nearP,
|
|
TOK_far,
|
|
TOK_farSp,
|
|
TOK_farP,
|
|
TOK_huge,
|
|
TOK_hugeSp,
|
|
TOK_hugeP,
|
|
#endif
|
|
TOK_basedLp,
|
|
TOK_cdecl,
|
|
TOK_pascal,
|
|
TOK_stdcall,
|
|
TOK_thiscall,
|
|
TOK_fastcall,
|
|
TOK_cocall,
|
|
TOK_ptr64,
|
|
TOK_restrict,
|
|
TOK_unaligned,
|
|
#if !VERS_32BIT
|
|
TOK_interrupt,
|
|
TOK_saveregs,
|
|
TOK_self,
|
|
TOK_segment,
|
|
TOK_segnameLpQ,
|
|
#endif
|
|
TOK__last
|
|
};
|
|
|
|
|
|
static const pcchar_t __near tokenTable[] =
|
|
{
|
|
#if !VERS_32BIT
|
|
"__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
|
|
#endif
|
|
"__based(", // TOK_basedLp
|
|
"__cdecl", // TOK_cdecl
|
|
"__pascal", // TOK_pascal
|
|
"__stdcall", // TOK_stdcall
|
|
"__thiscall", // TOK_thiscall
|
|
"__fastcall", // TOK_fastcall
|
|
"__clrcall", // TOK_cocall
|
|
"__ptr64", // TOK_ptr64
|
|
"__restrict", // TOK_restrict
|
|
"__unaligned", // TOK_unaligned
|
|
#if !VERS_32BIT
|
|
"__interrupt", // TOK_interrupt
|
|
"__saveregs", // TOK_saveregs
|
|
"__self", // TOK_self
|
|
"__segment", // TOK_segment
|
|
"__segname(\"", // TOK_segnameLpQ
|
|
#endif
|
|
""
|
|
};
|
|
|
|
|
|
// The operator mapping table
|
|
|
|
static const pcchar_t __near nameTable[] =
|
|
{
|
|
" new",
|
|
" delete",
|
|
"=",
|
|
">>",
|
|
"<<",
|
|
"!",
|
|
"==",
|
|
"!=",
|
|
"[]",
|
|
"operator",
|
|
"->",
|
|
"*",
|
|
"++",
|
|
"--",
|
|
"-",
|
|
"+",
|
|
"&",
|
|
"->*",
|
|
"/",
|
|
"%",
|
|
"<",
|
|
"<=",
|
|
">",
|
|
">=",
|
|
",",
|
|
"()",
|
|
"~",
|
|
"^",
|
|
"|",
|
|
"&&",
|
|
"||",
|
|
"*=",
|
|
"+=",
|
|
"-=",
|
|
"/=",
|
|
"%=",
|
|
">>=",
|
|
"<<=",
|
|
"&=",
|
|
"|=",
|
|
"^=",
|
|
|
|
#if ( !NO_COMPILER_NAMES )
|
|
"`vftable'",
|
|
"`vbtable'",
|
|
"`vcall'",
|
|
"`typeof'",
|
|
"`local static guard'",
|
|
"`string'",
|
|
"`vbase destructor'",
|
|
"`vector deleting destructor'",
|
|
"`default constructor closure'",
|
|
"`scalar deleting destructor'",
|
|
"`vector constructor iterator'",
|
|
"`vector destructor iterator'",
|
|
"`vector vbase constructor iterator'",
|
|
"`virtual displacement map'",
|
|
"`eh vector constructor iterator'",
|
|
"`eh vector destructor iterator'",
|
|
"`eh vector vbase constructor iterator'",
|
|
"`copy constructor closure'",
|
|
"`udt returning'",
|
|
"`EH", //eh initialized struct
|
|
"`RTTI", //rtti initialized struct
|
|
"`local vftable'",
|
|
"`local vftable constructor closure'",
|
|
#endif // !NO_COMPILER_NAMES
|
|
|
|
" new[]",
|
|
" delete[]",
|
|
|
|
#if ( !NO_COMPILER_NAMES )
|
|
"`omni callsig'",
|
|
"`placement delete closure'",
|
|
"`placement delete[] closure'",
|
|
"`managed vector constructor iterator'",
|
|
"`managed vector destructor iterator'",
|
|
"`eh vector copy constructor iterator'",
|
|
"`eh vector vbase copy constructor iterator'",
|
|
#endif
|
|
|
|
""
|
|
};
|
|
|
|
static const pcchar_t ehTable[] =
|
|
{
|
|
" Ptr to Member Data'",
|
|
" Catchable Type'",
|
|
" Catchable Type Array'",
|
|
" ThrowInfo'",
|
|
};
|
|
|
|
static const pcchar_t rttiTable[] =
|
|
{
|
|
" Type Descriptor'",
|
|
" Base Class Descriptor at (",
|
|
" Base Class Array'",
|
|
" Class Hierarchy Descriptor'",
|
|
" Complete Object Locator'",
|
|
};
|
|
|
|
|
|
// 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:
|
|
DName ();
|
|
DName ( char );
|
|
|
|
DName ( const DName & ); // Shallow copy
|
|
|
|
DName ( DNameNode * );
|
|
DName ( pcchar_t );
|
|
DName ( pcchar_t&, char );
|
|
DName ( DNameStatus );
|
|
DName ( DName * );
|
|
DName ( unsigned __int64 );
|
|
DName ( __int64 );
|
|
|
|
int isValid () const;
|
|
int isEmpty () const;
|
|
DNameStatus status () const;
|
|
void clearStatus ();
|
|
|
|
DName & setPtrRef ();
|
|
int isPtrRef () const;
|
|
int isUDC () const;
|
|
void setIsUDC ();
|
|
int isUDTThunk () const;
|
|
void setIsUDTThunk ();
|
|
int isArray() const;
|
|
void setIsArray();
|
|
int isNoTE () const;
|
|
void setIsNoTE ();
|
|
|
|
int length () const;
|
|
char getLastChar () const;
|
|
pchar_t getString ( pchar_t, int ) const;
|
|
|
|
DName operator + ( pcchar_t ) const;
|
|
DName operator + ( const DName & ) const;
|
|
DName operator + ( char ) const;
|
|
DName operator + ( DName * ) const;
|
|
DName operator + ( DNameStatus ) const;
|
|
|
|
DName & operator += ( char );
|
|
DName & operator += ( pcchar_t );
|
|
DName & operator += ( DName * );
|
|
DName & operator += ( DNameStatus );
|
|
DName & operator += ( const DName & );
|
|
|
|
DName & operator |= ( const DName & );
|
|
|
|
DName & operator = ( pcchar_t );
|
|
DName & operator = ( const DName & );
|
|
DName & operator = ( char );
|
|
DName & operator = ( DName * );
|
|
DName & operator = ( DNameStatus );
|
|
|
|
// Friends :
|
|
|
|
friend DName operator + ( char, const DName & );
|
|
friend DName operator + ( pcchar_t, const DName & );
|
|
friend DName operator + ( DNameStatus, const DName & );
|
|
|
|
private:
|
|
DNameNode * node;
|
|
|
|
DNameStatus stat : 4;
|
|
unsigned int isIndir : 1;
|
|
unsigned int isAUDC : 1;
|
|
unsigned int isAUDTThunk : 1;
|
|
unsigned int isArrayType : 1;
|
|
unsigned int NoTE : 1;
|
|
|
|
void 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:
|
|
Replicator ();
|
|
|
|
int isFull () const;
|
|
|
|
Replicator & operator += ( const DName & );
|
|
const DName & operator [] ( int ) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
class UnDecorator
|
|
{
|
|
private:
|
|
// Declare, in order to suppress automatic generation
|
|
void operator = ( const UnDecorator& );
|
|
|
|
Replicator ArgList;
|
|
static Replicator * pArgList;
|
|
|
|
Replicator ZNameList;
|
|
static Replicator * pZNameList;
|
|
|
|
static Replicator * pTemplateArgList;
|
|
|
|
static pcchar_t gName;
|
|
static pcchar_t name;
|
|
static pchar_t outputString;
|
|
static int maxStringLength;
|
|
static unsigned long disableFlags;
|
|
static bool fExplicitTemplateParams;
|
|
static bool fGetTemplateArgumentList;
|
|
|
|
static DName getDecoratedName ( void );
|
|
static DName getSymbolName ( void );
|
|
static DName getZName ( bool fUpdateCachedNames );
|
|
static DName getOperatorName ( bool fIsTemplate, bool *pfReadTemplateArguments );
|
|
static DName getScope ( void );
|
|
static DName getScopedName ( void );
|
|
static DName getSignedDimension ( void );
|
|
static DName getDimension ( bool fSigned = false );
|
|
static int getNumberOfDimensions ( void );
|
|
static DName getTemplateName ( bool );
|
|
static DName getTemplateArgumentList( void );
|
|
static DName getTemplateConstant( void );
|
|
static DName composeDeclaration ( const DName & );
|
|
static int getTypeEncoding ( void );
|
|
static DName getBasedType ( void );
|
|
static DName getECSUName ( void );
|
|
static DName getEnumType ( void );
|
|
static DName getCallingConvention ( void );
|
|
static DName getReturnType ( DName * = 0 );
|
|
static DName getDataType ( DName * );
|
|
static DName getPrimaryDataType ( const DName & );
|
|
static DName getDataIndirectType ( const DName &, char, const DName &, int = FALSE );
|
|
static DName getDataIndirectType ();
|
|
static DName getBasicDataType ( const DName & );
|
|
static DName getECSUDataType ( void );
|
|
static DName getPtrRefType ( const DName &, const DName &, char );
|
|
static DName getPtrRefDataType ( const DName &, int );
|
|
static DName getArrayType ( const DName& );
|
|
static DName getFunctionIndirectType( const DName & superType );
|
|
static DName getArgumentTypes ( void );
|
|
static DName getArgumentList ( void );
|
|
static DName getThrowTypes ( void );
|
|
static DName getLexicalFrame ( void );
|
|
static DName getStorageConvention ( void );
|
|
static DName getThisType ( void );
|
|
static DName getPointerType ( const DName &, const DName & );
|
|
static DName getPointerTypeArray ( const DName &, const DName & );
|
|
static DName getReferenceType ( const DName &, const DName & );
|
|
static DName getExternalDataType ( const DName & );
|
|
static DName getSegmentName ( void );
|
|
|
|
#if ( !NO_COMPILER_NAMES )
|
|
static DName getDisplacement ( void );
|
|
static DName getCallIndex ( void );
|
|
static DName getGuardNumber ( void );
|
|
static DName getVfTableType ( const DName & );
|
|
static DName getVbTableType ( const DName & );
|
|
static DName getVdispMapType ( const DName & );
|
|
static DName getVCallThunkType ( void );
|
|
#endif // !NO_COMPILER_NAMES
|
|
|
|
static DName getStringEncoding ( char *prefix, int wantBody );
|
|
|
|
static GetParameter_t m_pGetParameter;
|
|
|
|
public:
|
|
UnDecorator ( pchar_t, pcchar_t, int, GetParameter_t, unsigned long );
|
|
|
|
static int doUnderScore ();
|
|
static int doMSKeywords ();
|
|
static int doPtr64 ();
|
|
static int doFunctionReturns ();
|
|
static int doAllocationModel ();
|
|
static int doAllocationLanguage ();
|
|
|
|
#if 0
|
|
static int doMSThisType ();
|
|
static int doCVThisType ();
|
|
#endif
|
|
|
|
static int doThisTypes ();
|
|
static int doAccessSpecifiers ();
|
|
static int doThrowTypes ();
|
|
static int doMemberTypes ();
|
|
static int doReturnUDTModel ();
|
|
|
|
static int do32BitNear ();
|
|
|
|
static int doNameOnly ();
|
|
static int doTypeOnly ();
|
|
static int haveTemplateParameters ();
|
|
static int doEcsu ();
|
|
static int doNoIdentCharCheck ();
|
|
|
|
static pcchar_t UScore ( Tokens );
|
|
|
|
operator pchar_t ();
|
|
|
|
};
|
|
|
|
|
|
|
|
Replicator * UnDecorator::pArgList;
|
|
Replicator * UnDecorator::pZNameList = 0;
|
|
Replicator * UnDecorator::pTemplateArgList = 0;
|
|
pcchar_t UnDecorator::gName = 0;
|
|
pcchar_t UnDecorator::name = 0;
|
|
pchar_t UnDecorator::outputString = 0;
|
|
int UnDecorator::maxStringLength = 0;
|
|
unsigned long UnDecorator::disableFlags = 0;
|
|
GetParameter_t UnDecorator::m_pGetParameter = 0;
|
|
bool UnDecorator::fExplicitTemplateParams = false;
|
|
bool UnDecorator::fGetTemplateArgumentList = false;
|
|
|
|
|
|
#ifdef _CRTBLD
|
|
pchar_t __far _CRTIMP __loadds __unDName ( pchar_t outputString,
|
|
#else
|
|
pchar_t __far __cdecl __loadds unDName ( pchar_t outputString,
|
|
#endif
|
|
pcchar_t name,
|
|
int maxStringLength, // Note, COMMA is leading following optional arguments
|
|
Alloc_t pAlloc,
|
|
Free_t pFree,
|
|
unsigned short disableFlags
|
|
|
|
)
|
|
/*
|
|
* 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.
|
|
*/
|
|
|
|
{
|
|
// Must have an allocator and a deallocator (and we MUST trust them)
|
|
if ( !( pAlloc ))
|
|
return 0;
|
|
|
|
pchar_t unDecoratedName;
|
|
|
|
#if (defined(_CRTBLD) && defined(_MT))
|
|
if (!_mtinitlocknum(_UNDNAME_LOCK))
|
|
return 0;
|
|
_mlock(_UNDNAME_LOCK);
|
|
__try {
|
|
#endif
|
|
|
|
heap.Constructor ( pAlloc, pFree );
|
|
|
|
// Create the undecorator object, and get the result
|
|
|
|
UnDecorator unDecorate ( outputString,
|
|
name,
|
|
maxStringLength,
|
|
0,
|
|
disableFlags
|
|
);
|
|
unDecoratedName = unDecorate;
|
|
|
|
|
|
// Destruct the heap (would use a destructor, but that causes DLL problems)
|
|
|
|
heap.Destructor ();
|
|
|
|
#if (defined(_CRTBLD) && defined(_MT))
|
|
} __finally {
|
|
_munlock(_UNDNAME_LOCK);
|
|
}
|
|
#endif
|
|
|
|
// And return the composed name
|
|
|
|
return unDecoratedName;
|
|
|
|
} // End of FUNCTION "unDName"
|
|
|
|
|
|
|
|
|
|
#ifdef _CRTBLD
|
|
pchar_t __far _CRTIMP __loadds __unDNameEx ( pchar_t outputString,
|
|
#else
|
|
pchar_t __far __cdecl __loadds unDNameEx ( pchar_t outputString,
|
|
#endif
|
|
pcchar_t name,
|
|
int maxStringLength, // Note, COMMA is leading following optional arguments
|
|
Alloc_t pAlloc,
|
|
Free_t pFree,
|
|
GetParameter_t pGetParameter,
|
|
unsigned long disableFlags
|
|
|
|
)
|
|
/*
|
|
* 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.
|
|
*/
|
|
|
|
{
|
|
// Must have an allocator and a deallocator (and we MUST trust them)
|
|
|
|
if ( !( pAlloc ))
|
|
return 0;
|
|
|
|
pchar_t unDecoratedName;
|
|
|
|
#if (defined(_CRTBLD) && defined(_MT))
|
|
if (!_mtinitlocknum(_UNDNAME_LOCK))
|
|
return 0;
|
|
_mlock(_UNDNAME_LOCK);
|
|
__try {
|
|
#endif
|
|
|
|
heap.Constructor ( pAlloc, pFree );
|
|
|
|
// Create the undecorator object, and get the result
|
|
|
|
UnDecorator unDecorate ( outputString,
|
|
name,
|
|
maxStringLength,
|
|
pGetParameter,
|
|
disableFlags
|
|
);
|
|
unDecoratedName = unDecorate;
|
|
|
|
|
|
// Destruct the heap (would use a destructor, but that causes DLL problems)
|
|
|
|
heap.Destructor ();
|
|
|
|
#if (defined(_CRTBLD) && defined(_MT))
|
|
} __finally {
|
|
_munlock(_UNDNAME_LOCK);
|
|
}
|
|
#endif
|
|
|
|
// And return the composed name
|
|
|
|
return unDecoratedName;
|
|
|
|
} // End of FUNCTION "unDName"
|
|
|
|
// The 'UnDecorator' member functions
|
|
|
|
inline UnDecorator::UnDecorator ( pchar_t output,
|
|
pcchar_t dName,
|
|
int maxLen,
|
|
GetParameter_t pGetParameter,
|
|
unsigned long disable
|
|
)
|
|
{
|
|
name = dName;
|
|
gName = name;
|
|
|
|
if ( output ) {
|
|
maxStringLength = maxLen - 1; // The algorithm in getString doesn't leave room
|
|
// for terminating NULL; be paranoid and leave one
|
|
// extra char.
|
|
// It's a lot easier to fix this here....
|
|
outputString = output;
|
|
}
|
|
else {
|
|
outputString = 0;
|
|
maxStringLength = 0;
|
|
}
|
|
|
|
pZNameList = &ZNameList;
|
|
pArgList = &ArgList;
|
|
disableFlags = disable;
|
|
m_pGetParameter = pGetParameter;
|
|
fExplicitTemplateParams = false;
|
|
|
|
} // End of "UnDecorator" CONSTRUCTOR '()'
|
|
|
|
|
|
inline UnDecorator::operator 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 if (( *name == '?' ) && ( name[1] == '$' )) {
|
|
result = getTemplateName( false );
|
|
|
|
if ( result.status () == DN_invalid ) {
|
|
//
|
|
// What harm could there be to try again ?
|
|
// Repro:
|
|
// ?$S1@?1??VTFromRegType@CRegParser@ATL@@KAHPBGAAG@Z@4IA
|
|
// ---> unsigned int `protected: static int __cdecl ATL::CRegParser::VTFromRegType(unsigned short const *,unsigned short &)'::`2'::$S1
|
|
//
|
|
// This is a compiler generated symbol for a local static array init.
|
|
//
|
|
gName = name;
|
|
result.clearStatus();
|
|
result = getDecoratedName ();
|
|
}
|
|
} 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 (except when
|
|
// we're giving the name only)
|
|
|
|
if ( result.status () == DN_error )
|
|
return 0;
|
|
elif ( (*gName && !doNameOnly ()) || ( result.status () == DN_invalid ))
|
|
unDName = name; // Return the original name
|
|
else
|
|
unDName = result;
|
|
|
|
// Construct the return string
|
|
|
|
if ( !outputString )
|
|
{
|
|
maxStringLength = unDName.length () + 1;
|
|
outputString = rnew char[ maxStringLength ];
|
|
|
|
} // End of IF
|
|
|
|
if ( outputString ) {
|
|
unDName.getString ( outputString, maxStringLength );
|
|
|
|
// strip extra whitespace out of name
|
|
pchar_t pRead = outputString;
|
|
pchar_t pWrite = pRead;
|
|
while (*pRead) {
|
|
if (*pRead == ' ') {
|
|
pRead++;
|
|
*pWrite++ = ' ';
|
|
while ( *pRead == ' ' ) {
|
|
pRead++;
|
|
}
|
|
}
|
|
else
|
|
*pWrite++ = *pRead++;
|
|
}
|
|
*pWrite = *pRead;
|
|
}
|
|
|
|
// Return the result
|
|
|
|
return outputString;
|
|
|
|
} // End of "UnDecorator" OPERATOR 'pchar_t'
|
|
|
|
|
|
|
|
DName UnDecorator::getDecoratedName ( void )
|
|
{
|
|
// Ensure that it is intended to be a decorated name
|
|
|
|
if ( doTypeOnly() )
|
|
{
|
|
// Disable the type-only flag, so that if we get here recursively, eg.
|
|
// in a template tag, we do full name undecoration.
|
|
disableFlags &= ~UNDNAME_TYPE_ONLY;
|
|
|
|
// If we're decoding just a type, process it as the type for an abstract
|
|
// declarator, by giving an empty symbol name.
|
|
|
|
DName result = getDataType ( NULL );
|
|
disableFlags |= UNDNAME_TYPE_ONLY;
|
|
|
|
return result;
|
|
}
|
|
elif ( *gName == '?' )
|
|
{
|
|
// Extract the basic symbol name
|
|
|
|
gName++; // Advance the original name pointer
|
|
|
|
|
|
DName symbolName = getSymbolName ();
|
|
int udcSeen = symbolName.isUDC ();
|
|
|
|
// Abort if the symbol name is invalid
|
|
|
|
if ( !symbolName.isValid ())
|
|
return symbolName;
|
|
|
|
// Extract, and prefix the scope qualifiers
|
|
|
|
if ( *gName && ( *gName != '@' )) {
|
|
DName scope = getScope ();
|
|
|
|
if ( !scope.isEmpty() )
|
|
if (fExplicitTemplateParams) {
|
|
fExplicitTemplateParams = false;
|
|
symbolName = symbolName + scope;
|
|
if (*gName != '@') {
|
|
scope = getScope();
|
|
symbolName = scope + "::" + symbolName;
|
|
}
|
|
} else {
|
|
symbolName = scope + "::" + symbolName;
|
|
}
|
|
}
|
|
|
|
if ( udcSeen )
|
|
symbolName.setIsUDC ();
|
|
|
|
// Now compose declaration
|
|
|
|
if ( symbolName.isEmpty () || symbolName.isNoTE() )
|
|
{
|
|
return symbolName;
|
|
}
|
|
elif ( !*gName || ( *gName == '@' ) )
|
|
{
|
|
if ( *gName )
|
|
gName++;
|
|
|
|
if (doNameOnly () && !udcSeen) {
|
|
// Eat the rest of the dname, in case this is a recursive invocation,
|
|
// such as for a template argument.
|
|
(void)composeDeclaration( DName() );
|
|
return symbolName;
|
|
}
|
|
else {
|
|
return composeDeclaration ( symbolName );
|
|
}
|
|
|
|
} // End of ELIF then
|
|
else
|
|
return DN_invalid;
|
|
|
|
} // End of IF then
|
|
elif ( *gName )
|
|
return DN_invalid;
|
|
else
|
|
return DN_truncated;
|
|
|
|
} // End of "UnDecorator" FUNCTION "getDecoratedName"
|
|
|
|
|
|
|
|
inline DName UnDecorator::getSymbolName()
|
|
{
|
|
if (gName[0] == '?') {
|
|
if (gName[1] == '$') {
|
|
return getTemplateName(true);
|
|
}
|
|
else {
|
|
gName += 1;
|
|
|
|
return getOperatorName(false, NULL);
|
|
}
|
|
}
|
|
else {
|
|
return getZName(true);
|
|
}
|
|
}
|
|
|
|
|
|
DName UnDecorator::getZName ( bool fUpdateCachedNames )
|
|
{
|
|
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
|
|
{
|
|
DName zName;
|
|
|
|
if ( *gName == '?' )
|
|
{
|
|
zName = getTemplateName( false );
|
|
|
|
if ( *gName++ != '@' )
|
|
zName = *--gName ? DN_invalid : DN_truncated;
|
|
}
|
|
else {
|
|
#define TEMPLATE_PARAMETER "template-parameter-"
|
|
#define TEMPLATE_PARAMETER_LEN 19
|
|
#define GENERIC_TYPE "generic-type-"
|
|
#define GENERIC_TYPE_LEN 13
|
|
|
|
pchar_t genericType;
|
|
if (und_strncmp(gName, TEMPLATE_PARAMETER, TEMPLATE_PARAMETER_LEN) == 0) {
|
|
genericType = TEMPLATE_PARAMETER;
|
|
gName += TEMPLATE_PARAMETER_LEN;
|
|
} else if (und_strncmp(gName, GENERIC_TYPE, GENERIC_TYPE_LEN) == 0) {
|
|
genericType = GENERIC_TYPE;
|
|
gName += GENERIC_TYPE_LEN;
|
|
} else {
|
|
genericType = NULL;
|
|
}
|
|
|
|
if (genericType) {
|
|
DName dimension = getSignedDimension();
|
|
|
|
if ( haveTemplateParameters()) {
|
|
char buffer[16];
|
|
|
|
dimension.getString( buffer, 16 );
|
|
|
|
char *str = (*m_pGetParameter)(atol(buffer));
|
|
|
|
if ( str != NULL ) {
|
|
zName = str;
|
|
}
|
|
else {
|
|
zName = "`";
|
|
zName += genericType + dimension + "'";
|
|
}
|
|
}
|
|
else {
|
|
zName = "`";
|
|
zName += genericType + dimension + "'";
|
|
}
|
|
}
|
|
else {
|
|
// Extract the 'zname' to the terminator
|
|
|
|
zName = DName( gName, '@' ); // This constructor updates 'name'
|
|
}
|
|
}
|
|
|
|
|
|
// Add it to the current list of 'zname's
|
|
|
|
if ( fUpdateCachedNames && !pZNameList->isFull ())
|
|
*pZNameList += zName;
|
|
|
|
// And return the symbol name
|
|
return zName;
|
|
|
|
} // End of IF else
|
|
} // End of "UnDecorator" FUNCTION "getZName"
|
|
|
|
|
|
|
|
inline DName UnDecorator::getOperatorName ( bool fIsTemplate, bool *pfReadTemplateArguments )
|
|
{
|
|
DName operatorName;
|
|
DName tmpName;
|
|
int udcSeen = FALSE;
|
|
|
|
|
|
// 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:
|
|
// Their operator name is the name of their first enclosing scope, which
|
|
// will always be a tag, which may be a template specialization!
|
|
//
|
|
{
|
|
//
|
|
// Is this a specialization of a member function template? If it is
|
|
// then we will actually have the template arguments between the "name"
|
|
// of the operator and the scope: so we need to read the template
|
|
// arguments before we try to read the name of the class
|
|
//
|
|
DName templateArguments;
|
|
|
|
if ( fIsTemplate ) {
|
|
templateArguments += '<' + getTemplateArgumentList();
|
|
|
|
if ( templateArguments.getLastChar () == '>' ) {
|
|
templateArguments += ' ';
|
|
}
|
|
|
|
templateArguments += '>';
|
|
|
|
gName += 1;
|
|
|
|
if ( pfReadTemplateArguments != NULL ) {
|
|
*pfReadTemplateArguments = true;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Use a temporary. Don't want to advance the name pointer
|
|
//
|
|
pcchar_t pName = gName;
|
|
|
|
operatorName = getZName ( false );
|
|
|
|
gName = pName; // Undo our lookahead
|
|
|
|
if ( !operatorName.isEmpty () && ( gName[ -1 ] == OC_dtor ))
|
|
operatorName = '~' + operatorName;
|
|
|
|
//
|
|
// Append the template argumentsa (if there are any)
|
|
//
|
|
if ( !templateArguments.isEmpty()) {
|
|
operatorName += templateArguments;
|
|
}
|
|
|
|
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:
|
|
udcSeen = TRUE;
|
|
|
|
// 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_string:
|
|
{
|
|
DName result = getStringEncoding( "`string'", TRUE );
|
|
result.setIsNoTE();
|
|
return result;
|
|
}
|
|
|
|
case OC_metatype:
|
|
case OC_guard:
|
|
case OC_vbdtor:
|
|
case OC_vdeldtor:
|
|
case OC_defctor:
|
|
case OC_sdeldtor:
|
|
case OC_vctor:
|
|
case OC_vdtor:
|
|
case OC_vallctor:
|
|
case OC_vdispmap:
|
|
case OC_ehvctor:
|
|
case OC_ehvdtor:
|
|
case OC_ehvctorvb:
|
|
case OC_copyctorclosure:
|
|
case OC_locvfctorclosure:
|
|
case OC_locvftable: // Special purpose names
|
|
case OC_placementDeleteClosure:
|
|
case OC_placementArrayDeleteClosure:
|
|
return nameTable[ gName[ -1 ] - OC_metatype + ( OC_vcall - OC_asdiv + 1 ) + ( OC_assub - OC_index + 1 ) + ( OC_unequal - OC_new + 1 )];
|
|
|
|
case OC_udtthunk:
|
|
operatorName = nameTable[ gName[ -1 ] - OC_metatype + ( OC_vcall - OC_asdiv + 1 ) + ( OC_assub - OC_index + 1 ) + ( OC_unequal - OC_new + 1 )];
|
|
tmpName = getOperatorName( false, NULL );
|
|
if ( !tmpName.isEmpty() && tmpName.isUDTThunk() )
|
|
return DN_invalid;
|
|
return operatorName + tmpName;
|
|
break;
|
|
case OC_eh_init:
|
|
break;
|
|
case OC_rtti_init:
|
|
operatorName = nameTable[ gName[ -1 ] - OC_metatype + ( OC_vcall - OC_asdiv + 1 ) + ( OC_assub - OC_index + 1 ) + ( OC_unequal - OC_new + 1 )];
|
|
tmpName = rttiTable[ gName[0] - OC_rtti_TD ];
|
|
switch ( *gName++ )
|
|
{
|
|
case OC_rtti_TD:
|
|
{
|
|
DName result = getDataType ( NULL );
|
|
return result + ' ' + operatorName + tmpName;
|
|
}
|
|
break;
|
|
case OC_rtti_BCD:
|
|
{
|
|
DName result = operatorName + tmpName;
|
|
result += getSignedDimension() + ',';
|
|
result += getSignedDimension() + ',';
|
|
result += getSignedDimension() + ',';
|
|
result += getDimension() + ')';
|
|
return result + '\'';
|
|
}
|
|
break;
|
|
case OC_rtti_BCA:
|
|
case OC_rtti_CHD:
|
|
case OC_rtti_COL:
|
|
return operatorName + tmpName;
|
|
break;
|
|
default:
|
|
gName--;
|
|
return DN_truncated;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
#endif // !NO_COMPILER_NAMES
|
|
|
|
case OC_arrayNew:
|
|
case OC_arrayDelete:
|
|
operatorName = nameTable[ gName[ -1 ] - OC_metatype + ( OC_vcall - OC_asdiv + 1 ) + ( OC_assub - OC_index + 1 ) + ( OC_unequal - OC_new + 1 )
|
|
#if NO_COMPILER_NAMES
|
|
- ( OC_locvfctorclosure - OC_vftable + 1 ) // discount names not in table
|
|
#endif
|
|
];
|
|
break;
|
|
|
|
// Yet another level of nested encodings....
|
|
case '?':
|
|
switch( *gName++ ) {
|
|
|
|
case 0:
|
|
gName--; // End of string, better back-track
|
|
|
|
return DN_truncated;
|
|
|
|
case OC_anonymousNamespace:
|
|
//
|
|
// Anonymous namespace (new-style) is a string encoding of the
|
|
// machine name and the translation unit name. Since the remainder
|
|
// of the name doesn't really fit the dname grammar, skip it.
|
|
// There are two '@' markers in the name....
|
|
//
|
|
{
|
|
DName result = getStringEncoding( "`anonymous namespace'", FALSE );
|
|
result.setIsNoTE();
|
|
return result;
|
|
}
|
|
|
|
default:
|
|
return DN_invalid;
|
|
}
|
|
break;
|
|
|
|
//
|
|
// A double extended operator
|
|
//
|
|
case '_':
|
|
switch (*gName++) {
|
|
case OC_man_vec_ctor:
|
|
case OC_man_vec_dtor:
|
|
case OC_ehvcctor:
|
|
case OC_ehvcctorvb:
|
|
return nameTable[ gName[ -1 ] - OC_man_vec_ctor + ( OC_placementArrayDeleteClosure - OC_metatype + 1) + ( OC_vcall - OC_asdiv + 1 ) + ( OC_assub - OC_index + 1 ) + ( OC_unequal - OC_new + 1 )];
|
|
|
|
default:
|
|
return DN_invalid;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return DN_invalid;
|
|
|
|
} // End of SWITCH
|
|
break;
|
|
|
|
default:
|
|
return DN_invalid;
|
|
|
|
} // End of SWITCH
|
|
|
|
// This really is an operator name, so prefix it with 'operator'
|
|
|
|
if ( udcSeen )
|
|
operatorName.setIsUDC ();
|
|
elif ( !operatorName.isEmpty ())
|
|
operatorName = "operator" + operatorName;
|
|
|
|
return operatorName;
|
|
|
|
} // End of "UnDecorator" FUNCTION "getOperatorName"
|
|
|
|
DName UnDecorator::getStringEncoding ( char *prefix, int wantBody )
|
|
{
|
|
DName result = prefix;
|
|
|
|
// First @ comes right after operator code
|
|
if ( *gName++ != '@' || *gName++ != '_' ) {
|
|
return DN_invalid;
|
|
}
|
|
|
|
// Skip the string kind
|
|
gName++;
|
|
|
|
// Get (& discard) the length
|
|
getDimension();
|
|
|
|
// Get (& discart) the checksum
|
|
getDimension();
|
|
|
|
while ( *gName && *gName != '@' ) {
|
|
// For now, we'll just skip it
|
|
gName++;
|
|
}
|
|
|
|
if ( !*gName ) {
|
|
gName--;
|
|
return DN_truncated;
|
|
}
|
|
|
|
// Eat the terminating '@'
|
|
gName++;
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
DName UnDecorator::getScope ( void )
|
|
{
|
|
DName scope;
|
|
bool fNeedBracket = false;
|
|
|
|
|
|
// Get the list of scopes
|
|
|
|
while (( scope.status () == DN_valid ) && *gName && ( *gName != '@' ))
|
|
{ // Insert the scope operator if not the first scope
|
|
|
|
if (fExplicitTemplateParams && !fGetTemplateArgumentList) {
|
|
return scope;
|
|
}
|
|
if ( !scope.isEmpty() ) {
|
|
scope = "::" + scope;
|
|
|
|
if (fNeedBracket) {
|
|
scope = '[' + scope;
|
|
fNeedBracket = false;
|
|
}
|
|
}
|
|
|
|
// Determine what kind of scope it is
|
|
|
|
if ( *gName == '?' )
|
|
switch ( *++gName )
|
|
{
|
|
case '?':
|
|
if ( gName[1] == '_' && gName[2] == '?' ) {
|
|
//
|
|
// Anonymous namespace name (new style)
|
|
//
|
|
gName++;
|
|
scope = getOperatorName ( false, NULL ) + scope;
|
|
|
|
// There should be a zname termination @...
|
|
if ( *gName == '@' ) {
|
|
gName++;
|
|
}
|
|
}
|
|
else
|
|
scope = '`' + getDecoratedName () + '\'' + scope;
|
|
break;
|
|
|
|
case '$':
|
|
// It's a template name, which is a kind of zname; back up
|
|
// and handle like a zname.
|
|
gName--;
|
|
scope = getZName ( true ) + scope;
|
|
break;
|
|
|
|
case 'A':
|
|
//
|
|
// This is a new-new encoding for anonymous namespaces
|
|
//
|
|
// fall-through
|
|
|
|
case '%':
|
|
//
|
|
// It an anonymous namespace (old-style);
|
|
// skip the (unreadable) name and instead insert
|
|
// an appropriate string
|
|
//
|
|
while ( *gName != '@' ) {
|
|
gName++;
|
|
}
|
|
|
|
gName++;
|
|
|
|
scope = "`anonymous namespace'" + scope;
|
|
break;
|
|
case 'I':
|
|
//
|
|
// This is the interface whose method the class is
|
|
// implementing
|
|
//
|
|
gName++;
|
|
scope = getZName ( true ) + ']' + scope;
|
|
fNeedBracket = true;
|
|
break;
|
|
|
|
default:
|
|
scope = getLexicalFrame () + scope;
|
|
break;
|
|
|
|
} // End of SWITCH
|
|
else
|
|
scope = getZName ( true ) + scope;
|
|
|
|
} // End of WHILE
|
|
|
|
// Catch error conditions
|
|
|
|
switch ( *gName )
|
|
{
|
|
case 0:
|
|
if ( scope.isEmpty() )
|
|
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"
|
|
|
|
|
|
DName UnDecorator::getSignedDimension ( void )
|
|
{
|
|
if ( !*gName )
|
|
return DN_truncated;
|
|
elif ( *gName == '?' ) {
|
|
gName++; // skip the '?'
|
|
return '-' + getDimension();
|
|
}
|
|
else
|
|
return getDimension();
|
|
} // End of "Undecorator" FUNCTION "getSignedDimension"
|
|
|
|
|
|
DName UnDecorator::getDimension ( bool fSigned )
|
|
{
|
|
char* prefix = 0;
|
|
if (*gName == TC_nontype_dummy) {
|
|
prefix = "`non-type-template-parameter";
|
|
++gName;
|
|
}
|
|
|
|
if ( !*gName )
|
|
return DN_truncated;
|
|
elif (( *gName >= '0' ) && ( *gName <= '9' ))
|
|
return prefix ? (prefix + DName ((unsigned __int64)( *gName++ - '0' + 1 ))) : DName ((unsigned __int64)( *gName++ - '0' + 1 ));
|
|
else
|
|
{
|
|
unsigned __int64 dim = 0ui64;
|
|
|
|
|
|
// 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
|
|
|
|
if (fSigned) {
|
|
return prefix ? (prefix + DName((__int64)dim)) : DName((__int64)dim);
|
|
} else {
|
|
return prefix ? (prefix + DName(dim)) : dim;
|
|
}
|
|
|
|
} // End of ELIF else
|
|
} // End of "UnDecorator" FUNCTION "getDimension"
|
|
|
|
|
|
int UnDecorator::getNumberOfDimensions ( void )
|
|
{
|
|
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"
|
|
|
|
|
|
DName UnDecorator::getTemplateName( bool fReadTerminator )
|
|
{
|
|
//
|
|
// First make sure we're really looking at a template name
|
|
//
|
|
if ( gName[0] != '?' || gName[1] != '$' )
|
|
return DN_invalid;
|
|
|
|
gName += 2; // Skip the marker characters
|
|
|
|
//
|
|
// Stack the replicators, since template names are their own replicator scope:
|
|
//
|
|
Replicator * pSaveArgList = pArgList;
|
|
Replicator * pSaveZNameList = pZNameList;
|
|
Replicator * pSaveTemplateArgList = pTemplateArgList;
|
|
|
|
Replicator localArgList, localZNameList, localTemplateArgList;
|
|
|
|
pArgList = &localArgList;
|
|
pZNameList = &localZNameList;
|
|
pTemplateArgList = &localTemplateArgList;
|
|
|
|
//
|
|
// Crack the template name:
|
|
//
|
|
DName templateName;
|
|
DName templateArguments;
|
|
bool fReadTemplateArguments = false;
|
|
|
|
if ( *gName == '?' ) {
|
|
gName += 1;
|
|
|
|
templateName = getOperatorName( true, &fReadTemplateArguments );
|
|
}
|
|
else {
|
|
templateName = getZName( true );
|
|
}
|
|
|
|
if (templateName.isEmpty ()) {
|
|
fExplicitTemplateParams = true;
|
|
}
|
|
|
|
//
|
|
// If we haven't already read the template arguments then
|
|
// now is the time to read them
|
|
//
|
|
if ( !fReadTemplateArguments ) {
|
|
templateName += '<' + getTemplateArgumentList ();
|
|
|
|
if ( templateName.getLastChar () == '>' ) {
|
|
templateName += ' ';
|
|
}
|
|
|
|
templateName += '>';
|
|
|
|
if ( fReadTerminator ) {
|
|
gName += 1;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Restore the previous replicators:
|
|
//
|
|
pArgList = pSaveArgList;
|
|
pZNameList = pSaveZNameList;
|
|
pTemplateArgList = pSaveTemplateArgList;
|
|
|
|
// Return the completed 'template-name'
|
|
|
|
return templateName;
|
|
|
|
} // End of "UnDecorator" FUNCTION "getTemplateName"
|
|
|
|
|
|
DName UnDecorator::getTemplateArgumentList ( void )
|
|
{
|
|
int first = TRUE;
|
|
DName aList;
|
|
fGetTemplateArgumentList = true;
|
|
|
|
|
|
while (( aList.status () == DN_valid ) && *gName && ( *gName != AT_endoflist ))
|
|
{
|
|
// Insert the argument list separator if not the first argument
|
|
|
|
if ( first )
|
|
first = FALSE;
|
|
else
|
|
aList += ',';
|
|
|
|
|
|
// Get the individual argument type
|
|
|
|
int argIndex = *gName - '0';
|
|
|
|
|
|
// Handle 'template-argument-replicators', otherwise a new argument type
|
|
|
|
if (( argIndex >= 0 ) && ( argIndex <= 9 ))
|
|
{
|
|
gName++; // Skip past the replicator
|
|
|
|
// Append to the argument list
|
|
|
|
aList += ( *pTemplateArgList )[ argIndex ];
|
|
|
|
} // End of IF then
|
|
else
|
|
{
|
|
pcchar_t oldGName = gName;
|
|
DName arg;
|
|
|
|
//
|
|
// Extract the 'argument' type
|
|
//
|
|
|
|
if ( *gName == DT_void ) {
|
|
gName++;
|
|
arg = "void";
|
|
}
|
|
elif ( (*gName == '$') && (gName[1] != '$')) {
|
|
gName++;
|
|
arg = getTemplateConstant();
|
|
}
|
|
elif ( *gName == '?' ) {
|
|
//
|
|
// This is a template-parameter, i.e. we have a "specialization" of
|
|
// X<T>. so get the template-parameter-index and use a "generic" name
|
|
// for this parameter
|
|
//
|
|
DName dimension = getSignedDimension();
|
|
|
|
if ( haveTemplateParameters()) {
|
|
char buffer[16];
|
|
|
|
dimension.getString( buffer, 16 );
|
|
|
|
char *str = (*m_pGetParameter)(atol(buffer));
|
|
|
|
if ( str != NULL ) {
|
|
arg = str;
|
|
}
|
|
else {
|
|
arg = "`template-parameter" + dimension + "'";
|
|
}
|
|
}
|
|
else {
|
|
arg = "`template-parameter" + dimension + "'";
|
|
}
|
|
}
|
|
else {
|
|
arg = getPrimaryDataType ( DName() );
|
|
}
|
|
|
|
|
|
// Add it to the current list of 'template-argument's, if it is bigger than a one byte encoding
|
|
|
|
if ((( gName - oldGName ) > 1 ) && !pTemplateArgList->isFull ())
|
|
*pTemplateArgList += arg;
|
|
|
|
// Append to the argument list
|
|
|
|
aList += arg;
|
|
|
|
} // End of IF else
|
|
} // End of WHILE
|
|
|
|
// Return the completed template argument list
|
|
|
|
fGetTemplateArgumentList = false;
|
|
|
|
return aList;
|
|
|
|
} // End of "UnDecorator" FUNCTION "getTemplateArgumentList"
|
|
|
|
|
|
DName UnDecorator::getTemplateConstant(void)
|
|
{
|
|
//
|
|
// template-constant ::=
|
|
// '0' <template-integral-constant>
|
|
// '1' <template-address-constant>
|
|
// '2' <template-floating-point-constant>
|
|
//
|
|
char type_category = *gName++;
|
|
switch ( type_category )
|
|
{
|
|
//
|
|
// template-integral-constant ::=
|
|
// <signed-dimension>
|
|
//
|
|
case TC_integral:
|
|
return getSignedDimension ();
|
|
|
|
//
|
|
// template-address-constant ::=
|
|
// '@' // Null pointer
|
|
// <decorated-name>
|
|
//
|
|
case TC_address:
|
|
if ( *gName == TC_nullptr )
|
|
{
|
|
gName++;
|
|
return "NULL";
|
|
}
|
|
else
|
|
return DName("&") + getDecoratedName ();
|
|
|
|
//
|
|
// template-name ::=
|
|
// <docorated-name>
|
|
//
|
|
case TC_name:
|
|
return getDecoratedName ();
|
|
|
|
//
|
|
// template-floating-point-constant ::=
|
|
// <normalized-mantissa><exponent>
|
|
//
|
|
case TC_fp:
|
|
{
|
|
DName mantissa ( getSignedDimension () );
|
|
DName exponent ( getSignedDimension () );
|
|
|
|
if ( mantissa.isValid() && exponent.isValid() )
|
|
{
|
|
//
|
|
// Get string representation of mantissa
|
|
//
|
|
char buf[100]; // Way overkill for a compiler generated fp constant
|
|
|
|
if ( !mantissa.getString( &(buf[1]), 100 ) )
|
|
return DN_invalid;
|
|
|
|
//
|
|
// Insert decimal point
|
|
//
|
|
buf[0] = buf[1];
|
|
|
|
if ( buf[0] == '-' )
|
|
{
|
|
buf[1] = buf[2];
|
|
buf[2] = '.';
|
|
}
|
|
else
|
|
buf[1] = '.';
|
|
|
|
//
|
|
// String it all together
|
|
//
|
|
return DName( buf ) + 'e' + exponent;
|
|
|
|
} // End of IF then
|
|
else
|
|
return DN_truncated;
|
|
|
|
} // End of BLOCK case TC_fp
|
|
|
|
case TC_dummy:
|
|
case TC_nontype_dummy:
|
|
{
|
|
//
|
|
// This is a template-parameter, i.e. we have a "specialization" of
|
|
// X<n>. so get the template-parameter-index and use a "generic" name
|
|
// for this parameter
|
|
//
|
|
DName dimension = getSignedDimension();
|
|
|
|
if ( haveTemplateParameters()) {
|
|
char buffer[16];
|
|
|
|
dimension.getString( buffer, 16 );
|
|
|
|
char *str = (*m_pGetParameter)(atol(buffer));
|
|
|
|
if ( str != NULL ) {
|
|
return str;
|
|
}
|
|
}
|
|
|
|
if (type_category == TC_dummy) {
|
|
return "`template-parameter" + dimension + "'";
|
|
} else {
|
|
return "`non-type-template-parameter" + dimension + "'";
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TC_vptmd:
|
|
case TC_gptmd:
|
|
case TC_mptmf:
|
|
case TC_vptmf:
|
|
case TC_gptmf:
|
|
{
|
|
DName ptm = '{';
|
|
|
|
switch (type_category) {
|
|
case TC_mptmf:
|
|
case TC_vptmf:
|
|
case TC_gptmf:
|
|
ptm += getDecoratedName();
|
|
ptm += ',';
|
|
break;
|
|
}
|
|
|
|
switch (type_category) {
|
|
case TC_gptmf:
|
|
case TC_gptmd:
|
|
ptm += getSignedDimension();
|
|
ptm += ',';
|
|
// fallthrough
|
|
|
|
case TC_vptmd:
|
|
case TC_vptmf:
|
|
ptm += getSignedDimension();
|
|
ptm += ',';
|
|
// fallthrough
|
|
|
|
case TC_mptmf:
|
|
ptm += getSignedDimension();
|
|
}
|
|
|
|
return ptm + '}';
|
|
}
|
|
break;
|
|
|
|
case '\0':
|
|
--gName;
|
|
return DN_truncated;
|
|
|
|
default:
|
|
return DN_invalid;
|
|
|
|
} // End of SWITCH
|
|
} // End of "UnDecorator" FUNCTION "getTemplateConstant"
|
|
|
|
|
|
inline DName UnDecorator::composeDeclaration ( const DName & symbol )
|
|
{
|
|
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 );
|
|
elif ( TE_isCident ( typeCode ))
|
|
return 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 )) ||
|
|
( TE_isthunk ( typeCode ) && ( TE_istemplatector ( typeCode ) || TE_istemplatedtor ( typeCode )))))
|
|
#endif // !NO_COMPILER_NAMES
|
|
|
|
{
|
|
// If it is based, then compose the 'based' prefix for the name
|
|
|
|
if ( TE_isbased ( typeCode ))
|
|
if ( doMSKeywords () && doAllocationModel ())
|
|
declaration = ' ' + getBasedType ();
|
|
else
|
|
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 () + "}' ";
|
|
if ( doMSKeywords () && doAllocationLanguage ())
|
|
declaration = ' ' + getCallingConvention () + ' ' + declaration; // What calling convention ?
|
|
else
|
|
declaration |= getCallingConvention (); // Just lose the 'calling-convention'
|
|
|
|
} // 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 ( doThisTypes ())
|
|
thisType = getThisType ();
|
|
else
|
|
thisType |= getThisType ();
|
|
|
|
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 !VERS_32BIT
|
|
if ( doAllocationModel ())
|
|
if ( TE_isnear ( typeCode ))
|
|
declaration = UScore ( TOK_nearSp ) + declaration;
|
|
elif ( TE_isfar ( typeCode ))
|
|
declaration = UScore ( TOK_farSp ) + declaration;
|
|
#endif
|
|
|
|
} // End of IF
|
|
else
|
|
declaration |= getCallingConvention (); // Just lose the 'calling-convention'
|
|
|
|
// Now put them all together
|
|
|
|
if ( !symbol.isEmpty ())
|
|
if ( !declaration.isEmpty () && !doNameOnly() ) // 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 ();
|
|
|
|
if ( doNameOnly() )
|
|
return declaration;
|
|
}
|
|
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 ( doThrowTypes ())
|
|
declaration += getThrowTypes ();
|
|
else
|
|
declaration |= getThrowTypes (); // Just lose the 'throw-types'
|
|
|
|
// 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
|
|
} // 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_isvdispmap ( typeCode ))
|
|
return getVdispMapType ( declaration );
|
|
elif ( TE_isthunk ( typeCode ) && TE_islocaldtor ( typeCode ))
|
|
declaration += "`local static destructor helper'";
|
|
elif ( TE_isthunk ( typeCode ) && TE_istemplatector ( typeCode ))
|
|
declaration += "`template static data member constructor helper'";
|
|
elif ( TE_isthunk ( typeCode ) && TE_istemplatedtor ( typeCode ))
|
|
declaration += "`template static data member destructor helper'";
|
|
elif ( TE_ismetaclass ( typeCode ))
|
|
//
|
|
// Meta-class information has its information in its operator id
|
|
//
|
|
return declaration;
|
|
#else // } elif NO_COMPILER_NAMES {
|
|
if ( TE_isvftable ( typeCode )
|
|
|| TE_isvbtable ( typeCode )
|
|
|| TE_isguard ( typeCode )
|
|
|| TE_ismetaclass ( typeCode ))
|
|
return DN_invalid;
|
|
#endif // NO_COMPILER_NAMES
|
|
|
|
if ( TE_isthunk( typeCode ) && ( TE_istemplatector( typeCode ) || TE_istemplatedtor( typeCode ))) {
|
|
//
|
|
// Insert a space before the declaration
|
|
//
|
|
declaration = " " + declaration;
|
|
}
|
|
else {
|
|
// All others are decorated as data symbols
|
|
declaration = getExternalDataType ( declaration );
|
|
}
|
|
|
|
} // End of IF else
|
|
|
|
// 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
|
|
|
|
#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 UnDecorator::getTypeEncoding ( void )
|
|
{
|
|
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 SHF_localdtor: // A destructor helper for a local static ?
|
|
TE_setislocaldtor ( typeCode );
|
|
break;
|
|
|
|
case SHF_vcall: // A VCall-thunk ?
|
|
TE_setisvcall ( typeCode );
|
|
break;
|
|
|
|
case SHF_templateStaticDataMemberCtor: // A constructor helper for template static data members
|
|
TE_setistemplatector ( typeCode );
|
|
break;
|
|
|
|
case SHF_templateStaticDataMemberDtor: // A destructor helper for template static data members
|
|
TE_setistemplatedtor ( typeCode );
|
|
break;
|
|
case SHF_vdispmap:
|
|
TE_setvdispmap ( typeCode );
|
|
break;
|
|
|
|
case '$':
|
|
{
|
|
if ( * ( gName + 1 ) == SHF_AnyDLLImportMethod ) {
|
|
gName += 1;
|
|
}
|
|
|
|
switch ( *( ++gName )) {
|
|
case SHF_CPPManagedILFunction: // C++ managed-IL function
|
|
case SHF_CPPManagedNativeFunction: // C++ managed-native function
|
|
case SHF_CPPManagedILMain: // C++ managed-IL main
|
|
case SHF_CPPManagedNativeMain: // C++ managed-native main
|
|
case SHF_CPPManagedILDLLImportData: // C++ managed-IL DLL-import function
|
|
case SHF_CPPManagedNativeDLLImportData: // C++ managed-native DLL-import function
|
|
//
|
|
// Skip the encoding
|
|
//
|
|
gName += 1;
|
|
return getTypeEncoding();
|
|
|
|
case SHF_CManagedILFunction: // C (or extern "C") managed-IL function
|
|
case SHF_CManagedNativeFunction: // C (or extern "C") managed-native function
|
|
case SHF_CManagedILDLLImportData: // C (or extern "C") managed-IL DLL-import function
|
|
case SHF_CManagedNativeDLLImportData: // C (or extern "C") managed-native DLL-import function
|
|
//
|
|
// Skip the encoding
|
|
//
|
|
gName += 1;
|
|
|
|
//
|
|
// The next character should be the number of characters
|
|
// in the byte-count
|
|
//
|
|
if (( *gName >= '0' ) && ( *gName <= '9' )) {
|
|
//
|
|
// Skip the character count and the byte-count
|
|
// itself
|
|
//
|
|
gName += (( *gName - '0' ) + 1 );
|
|
|
|
return getTypeEncoding();
|
|
}
|
|
else {
|
|
TE_setisbadtype( typeCode );
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
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;
|
|
|
|
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:
|
|
TE_setismetaclass ( typeCode );
|
|
break;
|
|
|
|
default:
|
|
TE_setisbadtype ( typeCode );
|
|
|
|
return typeCode;
|
|
|
|
} // End of SWITCH
|
|
} // End of ELIF then
|
|
elif ( *gName == '9' ) {
|
|
gName++;
|
|
|
|
TE_setisCident ( typeCode );
|
|
}
|
|
elif ( *gName )
|
|
TE_setisbadtype ( typeCode );
|
|
else
|
|
TE_setistruncated ( typeCode );
|
|
|
|
// Return the composed type code
|
|
|
|
return typeCode;
|
|
|
|
} // End of "UnDecorator" FUNCTION "getTypeEncoding"
|
|
|
|
|
|
|
|
DName UnDecorator::getBasedType ( void )
|
|
{
|
|
DName basedDecl ( UScore ( TOK_basedLp ));
|
|
|
|
|
|
// What type of 'based' is it ?
|
|
|
|
if ( *gName )
|
|
{
|
|
switch ( *gName++ )
|
|
{
|
|
#if !VERS_32BIT
|
|
case BT_segname:
|
|
basedDecl += UScore ( TOK_segnameLpQ ) + getSegmentName () + "\")";
|
|
break;
|
|
|
|
case BT_segment:
|
|
basedDecl += DName ( "NYI:" ) + UScore ( TOK_segment );
|
|
break;
|
|
#endif
|
|
|
|
case BT_void:
|
|
basedDecl += "void";
|
|
break;
|
|
|
|
#if !VERS_32BIT
|
|
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
|
|
case BT_nearptr:
|
|
basedDecl += getScopedName();
|
|
break;
|
|
#endif
|
|
|
|
case BT_basedptr:
|
|
//
|
|
// Note: based pointer on based pointer is reserved
|
|
//
|
|
return DN_invalid;
|
|
|
|
} // End of SWITCH
|
|
} // End of IF else
|
|
else
|
|
basedDecl += DN_truncated;
|
|
|
|
// Close the based syntax
|
|
|
|
basedDecl += ") ";
|
|
|
|
// Return completed based declaration
|
|
|
|
return basedDecl;
|
|
|
|
} // End of "UnDecorator" FUNCTION "getBasedType"
|
|
|
|
|
|
|
|
DName UnDecorator::getScopedName ( void )
|
|
{
|
|
DName name;
|
|
|
|
|
|
// Get the beginning of the name
|
|
|
|
name = getZName ( true );
|
|
|
|
// Now the scope (if any)
|
|
|
|
if (( name.status () == DN_valid ) && *gName && ( *gName != '@' ))
|
|
name = getScope () + "::" + name;
|
|
|
|
// Skip the trailing '@'
|
|
|
|
if ( *gName == '@' )
|
|
gName++;
|
|
elif ( *gName )
|
|
name = DN_invalid;
|
|
elif ( name.isEmpty ())
|
|
name = DN_truncated;
|
|
else
|
|
name = DName ( DN_truncated ) + "::" + name;
|
|
|
|
// And return the complete name
|
|
|
|
return name;
|
|
|
|
} // End of "UnDecorator" FUNCTION "getECSUName"
|
|
|
|
|
|
inline DName UnDecorator::getECSUName ( void ) { return getScopedName(); }
|
|
|
|
|
|
inline DName UnDecorator::getEnumType ( void )
|
|
{
|
|
DName ecsuName;
|
|
|
|
|
|
if ( *gName )
|
|
{
|
|
// 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;
|
|
|
|
} // End of IF then
|
|
else
|
|
return DN_truncated;
|
|
|
|
} // End of "UnDecorator" FUNCTION "getEnumType"
|
|
|
|
|
|
|
|
DName UnDecorator::getCallingConvention ( void )
|
|
{
|
|
if ( *gName )
|
|
{
|
|
unsigned int callCode = ((unsigned int)*gName++ ) - 'A';
|
|
|
|
|
|
// What is the primary calling convention
|
|
|
|
DASSERT(CC_cdecl == 0);
|
|
#if CC_COR
|
|
if (/*( callCode >= CC_cdecl ) &&*/( callCode <= CC_cocall ))
|
|
#else // CC_COR
|
|
if (/*( callCode >= CC_cdecl ) &&*/( callCode <= CC_interrupt ))
|
|
#endif // CC_COR
|
|
{
|
|
DName callType;
|
|
|
|
|
|
// Now, what type of 'calling-convention' is it, 'interrupt' is special ?
|
|
|
|
if ( doMSKeywords ())
|
|
#if !VERS_32BIT
|
|
if ( callCode == CC_interrupt )
|
|
callType = UScore ( TOK_interrupt );
|
|
else
|
|
#endif
|
|
{
|
|
switch ( callCode & ~CC_saveregs )
|
|
{
|
|
case CC_cdecl:
|
|
callType = UScore ( TOK_cdecl );
|
|
break;
|
|
|
|
case CC_pascal:
|
|
callType = UScore ( TOK_pascal );
|
|
break;
|
|
|
|
case CC_thiscall:
|
|
callType = UScore ( TOK_thiscall );
|
|
break;
|
|
|
|
case CC_stdcall:
|
|
callType = UScore ( TOK_stdcall );
|
|
break;
|
|
|
|
case CC_fastcall:
|
|
callType = UScore ( TOK_fastcall );
|
|
break;
|
|
|
|
case CC_cocall:
|
|
callType = UScore ( TOK_cocall );
|
|
break;
|
|
|
|
} // End of SWITCH
|
|
|
|
// Has it also got 'saveregs' marked ?
|
|
|
|
#if !VERS_32BIT
|
|
if ( callCode & CC_saveregs )
|
|
callType += ' ' + UScore ( TOK_saveregs );
|
|
#endif
|
|
|
|
} // End of IF else
|
|
|
|
// And return
|
|
|
|
return callType;
|
|
|
|
} // End of IF then
|
|
else
|
|
return DN_invalid;
|
|
|
|
} // End of IF then
|
|
else
|
|
return DN_truncated;
|
|
|
|
} // End of "UnDecorator" FUNCTION "getCallingConvention"
|
|
|
|
|
|
|
|
DName UnDecorator::getReturnType ( DName * pDeclarator )
|
|
{
|
|
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 UnDecorator::getDataType ( DName * pDeclarator )
|
|
{
|
|
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 '?':
|
|
{
|
|
|
|
gName++; // Skip the '?'
|
|
|
|
superType = getDataIndirectType ( superType, 0, DName (), 0);
|
|
return getPrimaryDataType ( superType );
|
|
|
|
return superType;
|
|
|
|
} // End of CASE '?'
|
|
|
|
default:
|
|
return getPrimaryDataType ( superType );
|
|
|
|
} // End of SWITCH
|
|
} // End of "UnDecorator" FUNCTION "getDataType"
|
|
|
|
|
|
|
|
DName UnDecorator::getPrimaryDataType ( const DName & superType )
|
|
{
|
|
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 superName ( superType );
|
|
|
|
|
|
gName++;
|
|
|
|
return getReferenceType ( cvType, superName.setPtrRef ());
|
|
|
|
} // End of CASE 'PDT_reference'
|
|
|
|
case PDT_extend:
|
|
{
|
|
//
|
|
// Extended Primary Data Type (items overlooked in original design):
|
|
// prefixed by '$$'.
|
|
//
|
|
if ( gName[1] != PDT_extend )
|
|
if ( gName[1] == '\0' )
|
|
return DN_truncated + superType;
|
|
else
|
|
return DN_invalid;
|
|
|
|
gName += 2;
|
|
|
|
switch ( *gName )
|
|
{
|
|
case PDT_ex_function:
|
|
gName++;
|
|
return getFunctionIndirectType( superType );
|
|
|
|
case PDT_ex_other:
|
|
gName++;
|
|
return getPtrRefDataType( superType, /* isPtr = */ TRUE );
|
|
|
|
case PDT_ex_qualified:
|
|
gName++;
|
|
return(getBasicDataType(getDataIndirectType ( superType, 0, DName (), 0)));
|
|
|
|
case 0:
|
|
return ( DN_truncated + superType );
|
|
|
|
default:
|
|
return DN_invalid;
|
|
}
|
|
}
|
|
|
|
default:
|
|
return getBasicDataType ( superType );
|
|
|
|
} // End of SWITCH
|
|
} // End of "UnDecorator" FUNCTION "getPrimaryDataType"
|
|
|
|
|
|
|
|
DName UnDecorator::getArgumentTypes ( void )
|
|
{
|
|
switch ( *gName )
|
|
{
|
|
case AT_ellipsis:
|
|
return ( gName++, "..." );
|
|
|
|
case AT_void:
|
|
return ( gName++, "void" );
|
|
|
|
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"
|
|
|
|
|
|
DName UnDecorator::getArgumentList ( void )
|
|
{
|
|
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
|
|
{
|
|
pcchar_t oldGName = gName;
|
|
|
|
|
|
// Extract the 'argument' type
|
|
|
|
DName arg ( getPrimaryDataType ( DName ()));
|
|
|
|
|
|
// Add it to the current list of 'argument's, if it is bigger than a one byte encoding
|
|
|
|
if ((( gName - oldGName ) > 1 ) && !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 UnDecorator::getThrowTypes ( void )
|
|
{
|
|
if ( *gName )
|
|
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 + ')' );
|
|
|
|
} // End of "UnDecorator" FUNCTION "getThrowTypes"
|
|
|
|
|
|
|
|
DName UnDecorator::getBasicDataType ( const DName & superType )
|
|
{
|
|
if ( *gName )
|
|
{
|
|
unsigned char bdtCode = *gName++;
|
|
unsigned char extended_bdtCode;
|
|
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;
|
|
|
|
#if !VERS_32BIT
|
|
case BDT_segment:
|
|
basicDataType = UScore ( TOK_segment );
|
|
break;
|
|
#endif
|
|
|
|
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;
|
|
case BDT_extend:
|
|
switch(extended_bdtCode = *gName++) {
|
|
case BDT_array:
|
|
pCvCode = -2;
|
|
break;
|
|
case BDT_bool:
|
|
basicDataType = "bool";
|
|
break;
|
|
case BDT_int8:
|
|
case ( BDT_int8 | BDT_unsigned ):
|
|
basicDataType = "__int8";
|
|
break;
|
|
case BDT_int16:
|
|
case ( BDT_int16 | BDT_unsigned ):
|
|
basicDataType = "__int16";
|
|
break;
|
|
case BDT_int32:
|
|
case ( BDT_int32 | BDT_unsigned ):
|
|
basicDataType = "__int32";
|
|
break;
|
|
case BDT_int64:
|
|
case ( BDT_int64 | BDT_unsigned ):
|
|
basicDataType = "__int64";
|
|
break;
|
|
case BDT_int128:
|
|
case ( BDT_int128 | BDT_unsigned ):
|
|
basicDataType = "__int128";
|
|
break;
|
|
case BDT_wchar_t:
|
|
basicDataType = "wchar_t";
|
|
break;
|
|
#if CC_COR
|
|
case BDT_coclass:
|
|
case BDT_cointerface:
|
|
{
|
|
gName--; // Backup, since 'ecsu-data-type' does it's own decoding
|
|
|
|
basicDataType = getECSUDataType();
|
|
|
|
if ( basicDataType.isEmpty()) {
|
|
return basicDataType;
|
|
}
|
|
}
|
|
break;
|
|
#endif // CC_COR
|
|
case '$':
|
|
return "__w64 " + getBasicDataType (superType);
|
|
default:
|
|
basicDataType = "UNKNOWN";
|
|
break;
|
|
}
|
|
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;
|
|
case BDT_extend:
|
|
switch ( extended_bdtCode )
|
|
{
|
|
|
|
case ( BDT_int8 | BDT_unsigned ):
|
|
case ( BDT_int16 | BDT_unsigned ):
|
|
case ( BDT_int32 | BDT_unsigned ):
|
|
case ( BDT_int64 | BDT_unsigned ):
|
|
case ( BDT_int128 | BDT_unsigned ):
|
|
basicDataType = "unsigned " + basicDataType;
|
|
break;
|
|
|
|
} // End of SWITCH
|
|
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 superName ( superType );
|
|
|
|
if ( pCvCode == -2 )
|
|
{
|
|
superName.setIsArray();
|
|
DName arType = getPointerTypeArray ( cvType, superName );
|
|
// if we didn't get back an array, append.
|
|
// A multidimensional array sticks the braces in before the
|
|
// other dimensions at sets isArray on it's return type.
|
|
if (!arType.isArray()) {
|
|
arType += "[]";
|
|
}
|
|
return arType;
|
|
}
|
|
|
|
// Is it 'const/volatile' qualified ?
|
|
|
|
if ( superType . isEmpty() )
|
|
{
|
|
//
|
|
// const/volatile are redundantly encoded, except at the start
|
|
// of a "type only" context. In such a context, the super-type
|
|
// is empty.
|
|
//
|
|
if ( pCvCode & BDT_const )
|
|
{
|
|
cvType = "const";
|
|
|
|
if ( pCvCode & BDT_volatile )
|
|
cvType += " volatile";
|
|
} // End of IF then
|
|
elif ( pCvCode & BDT_volatile )
|
|
cvType = "volatile";
|
|
} // End of IF then
|
|
|
|
// Construct the appropriate pointer type declaration
|
|
|
|
return getPointerType ( cvType, superName );
|
|
|
|
} // End of IF else
|
|
} // End of IF then
|
|
else
|
|
return ( DN_truncated + superType );
|
|
|
|
} // End of "UnDecorator" FUNCTION "getBasicDataType"
|
|
|
|
|
|
|
|
DName UnDecorator::getECSUDataType ( void )
|
|
{
|
|
// Extract the principal type information itself, and validate the codes
|
|
|
|
int fPrefix = doEcsu() && !doNameOnly();
|
|
|
|
DName Prefix;
|
|
|
|
switch ( *gName++ )
|
|
{
|
|
case 0:
|
|
gName--; // Backup to permit later error recovery to work safely
|
|
|
|
return "`unknown ecsu'" + DN_truncated;
|
|
|
|
case BDT_union:
|
|
Prefix = "union ";
|
|
break;
|
|
|
|
case BDT_struct:
|
|
Prefix = "struct ";
|
|
break;
|
|
|
|
case BDT_class:
|
|
Prefix = "class ";
|
|
break;
|
|
|
|
#if CC_COR
|
|
case BDT_coclass:
|
|
Prefix = "coclass ";
|
|
break;
|
|
|
|
case BDT_cointerface:
|
|
Prefix = "cointerface ";
|
|
break;
|
|
#endif // CC_COR
|
|
|
|
case BDT_enum:
|
|
fPrefix = doEcsu();
|
|
|
|
Prefix = "enum " + getEnumType ();
|
|
break;
|
|
|
|
// default:
|
|
// return DN_invalid;
|
|
|
|
} // End of SWITCH
|
|
|
|
DName ecsuDataType;
|
|
|
|
if ( fPrefix )
|
|
ecsuDataType = Prefix;
|
|
|
|
// Get the 'class/struct/union' name
|
|
|
|
ecsuDataType += getECSUName ();
|
|
|
|
// And return the formed 'ecsu-data-type'
|
|
|
|
return ecsuDataType;
|
|
|
|
} // End of "UnDecorator" FUNCTION "getECSUDataType"
|
|
|
|
|
|
//
|
|
// Undecorator::getFunctionIndirectType
|
|
//
|
|
// Note: this function gets both the function-indirect-type and the function-type.
|
|
//
|
|
DName UnDecorator::getFunctionIndirectType( const DName & superType )
|
|
{
|
|
if ( ! *gName )
|
|
return DN_truncated + superType;
|
|
|
|
if ( ! IT_isfunction( *gName ))
|
|
return DN_invalid;
|
|
|
|
|
|
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 = superType;
|
|
|
|
// Is it a pointer to member function ?
|
|
|
|
if ( fitCode & FIT_member )
|
|
{
|
|
fitType = "::" + fitType;
|
|
|
|
if ( *gName )
|
|
fitType = ' ' + getScope () + fitType;
|
|
else
|
|
fitType = DN_truncated + fitType;
|
|
|
|
if ( *gName )
|
|
if ( *gName == '@' )
|
|
gName++;
|
|
else
|
|
return DN_invalid;
|
|
else
|
|
return ( DN_truncated + fitType );
|
|
|
|
if ( doThisTypes ())
|
|
thisType = getThisType ();
|
|
else
|
|
thisType |= getThisType ();
|
|
|
|
} // End of IF
|
|
|
|
// Is it a based allocated function ?
|
|
|
|
if ( fitCode & FIT_based )
|
|
if ( doMSKeywords ())
|
|
fitType = ' ' + getBasedType () + fitType;
|
|
else
|
|
fitType |= getBasedType (); // Just lose the 'based-type'
|
|
|
|
// Get the 'calling-convention'
|
|
|
|
if ( doMSKeywords ())
|
|
{
|
|
fitType = getCallingConvention () + fitType;
|
|
|
|
// Is it a near or far function pointer
|
|
|
|
#if !VERS_32BIT
|
|
fitType = UScore ((( fitCode & FIT_far ) ? TOK_farSp : TOK_nearSp )) + fitType;
|
|
#endif
|
|
|
|
} // End of IF then
|
|
else
|
|
fitType |= getCallingConvention (); // Just lose the 'calling-convention'
|
|
|
|
// Parenthesise the indirection component, and work on the rest
|
|
|
|
if ( ! superType . isEmpty() ) {
|
|
fitType = '(' + fitType + ')';
|
|
}
|
|
|
|
// Get the rest of the 'function-type' pieces
|
|
|
|
DName * pDeclarator = gnew DName;
|
|
DName returnType ( getReturnType ( pDeclarator ));
|
|
|
|
|
|
fitType += '(' + getArgumentTypes () + ')';
|
|
|
|
if ( doThisTypes () && ( fitCode & FIT_member ))
|
|
fitType += thisType;
|
|
|
|
if ( doThrowTypes ())
|
|
fitType += getThrowTypes ();
|
|
else
|
|
fitType |= getThrowTypes (); // Just lose the 'throw-types'
|
|
|
|
// Now insert the indirected declarator, catch the allocation failure here
|
|
|
|
if ( pDeclarator )
|
|
*pDeclarator = fitType;
|
|
else
|
|
return DN_error;
|
|
|
|
// And return the composed function type (now in 'returnType' )
|
|
|
|
return returnType;
|
|
}
|
|
|
|
|
|
DName UnDecorator::getPtrRefType ( const DName & cvType, const DName & superType, char ptrChar )
|
|
{
|
|
// Doubles up as 'pointer-type' and 'reference-type'
|
|
|
|
if ( *gName )
|
|
if ( IT_isfunction ( *gName )) // Is it a function or data indirection ?
|
|
{
|
|
DName fitType = ptrChar;
|
|
|
|
|
|
if ( !cvType.isEmpty () && ( superType.isEmpty () || !superType.isPtrRef ()))
|
|
fitType += cvType;
|
|
|
|
if ( !superType.isEmpty ())
|
|
fitType += superType;
|
|
|
|
return getFunctionIndirectType( fitType );
|
|
} // End of IF then
|
|
else
|
|
{
|
|
// Otherwise, it is either a pointer or a reference to some data type
|
|
|
|
DName innerType ( getDataIndirectType ( superType, ptrChar, cvType ));
|
|
|
|
return getPtrRefDataType ( innerType, ptrChar == '*' );
|
|
} // End of IF else
|
|
else
|
|
{
|
|
DName trunk ( DN_truncated );
|
|
|
|
|
|
trunk += ptrChar;
|
|
|
|
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 UnDecorator::getDataIndirectType ( const DName & superType, char prType, const DName & cvType, int thisFlag )
|
|
{
|
|
DName szComPlusIndirSpecifier;
|
|
|
|
if ( *gName )
|
|
{
|
|
if( gName[0] == '$' )
|
|
{
|
|
gName++; // swallow up the dollar
|
|
|
|
switch( *gName )
|
|
{
|
|
case PDT_GCPointer:
|
|
szComPlusIndirSpecifier = "__gc ";
|
|
gName++;
|
|
break;
|
|
|
|
case PDT_PinnedPointer:
|
|
szComPlusIndirSpecifier = "__pin ";
|
|
gName++;
|
|
break;
|
|
default:
|
|
unsigned int nRank = ((gName[0]-'0') << 4) + (gName[1]-'0');
|
|
gName += 2;
|
|
|
|
DASSERT( nRank < 256 );
|
|
|
|
szComPlusIndirSpecifier = "__gc[";
|
|
|
|
for( unsigned int i=1; i<nRank; i++ )
|
|
{
|
|
szComPlusIndirSpecifier = szComPlusIndirSpecifier + ",";
|
|
}
|
|
|
|
szComPlusIndirSpecifier = szComPlusIndirSpecifier + "] ";
|
|
|
|
if ( !superType.isEmpty () )
|
|
if ( superType.isArray() )
|
|
szComPlusIndirSpecifier = superType + szComPlusIndirSpecifier;
|
|
else
|
|
szComPlusIndirSpecifier = '(' + superType + ')' + szComPlusIndirSpecifier;
|
|
|
|
gName++;
|
|
|
|
return szComPlusIndirSpecifier;
|
|
}
|
|
}
|
|
|
|
unsigned int ditCode = ( *gName - (( *gName >= 'A' ) ? (unsigned int)'A': (unsigned int)( '0' - 26 )));
|
|
|
|
DName msExtension;
|
|
DName msExtensionPre;
|
|
|
|
int fContinue = TRUE;
|
|
|
|
do
|
|
{
|
|
switch ( ditCode )
|
|
{
|
|
case DIT_ptr64:
|
|
if ( doMSKeywords () && doPtr64() ) {
|
|
if ( !msExtension.isEmpty())
|
|
msExtension = msExtension + ' ' + UScore( TOK_ptr64 );
|
|
else
|
|
msExtension = UScore( TOK_ptr64 );
|
|
}
|
|
gName++;
|
|
ditCode = ( *gName - (( *gName >= 'A' ) ? (unsigned int)'A': (unsigned int)( '0' - 26 )));
|
|
break;
|
|
case DIT_unaligned:
|
|
if ( doMSKeywords ()) {
|
|
if ( !msExtensionPre.isEmpty())
|
|
msExtensionPre = msExtensionPre + ' ' + UScore( TOK_unaligned );
|
|
else
|
|
msExtensionPre = UScore( TOK_unaligned );
|
|
}
|
|
gName++;
|
|
ditCode = ( *gName - (( *gName >= 'A' ) ? (unsigned int)'A': (unsigned int)( '0' - 26 )));
|
|
break;
|
|
case DIT_restrict:
|
|
if ( doMSKeywords ()) {
|
|
if ( !msExtension.isEmpty())
|
|
msExtension = msExtension + ' ' + UScore( TOK_restrict );
|
|
else
|
|
msExtension = UScore( TOK_restrict );
|
|
}
|
|
gName++;
|
|
ditCode = ( *gName - (( *gName >= 'A' ) ? (unsigned int)'A': (unsigned int)( '0' - 26 )));
|
|
break;
|
|
|
|
default:
|
|
|
|
fContinue = FALSE;
|
|
break;
|
|
}
|
|
} while (fContinue);
|
|
|
|
gName++; // Skip to next character in name
|
|
|
|
// Is it a valid 'data-indirection-type' ?
|
|
|
|
DASSERT(DIT_near == 0);
|
|
if (( ditCode <= ( DIT_const | DIT_volatile | DIT_modelmask | DIT_member )))
|
|
{
|
|
DName ditType ( prType );
|
|
|
|
ditType = szComPlusIndirSpecifier + ditType;
|
|
|
|
if ( !msExtension.isEmpty())
|
|
ditType = ditType + ' ' + msExtension;
|
|
|
|
if ( !msExtensionPre.isEmpty())
|
|
ditType = msExtensionPre + ' ' + ditType;
|
|
|
|
// 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
|
|
|
|
if ( prType != '\0' )
|
|
{
|
|
ditType = "::" + ditType;
|
|
|
|
if ( *gName )
|
|
ditType = getScope () + ditType;
|
|
else
|
|
ditType = DN_truncated + ditType;
|
|
}
|
|
elif ( *gName )
|
|
{
|
|
//
|
|
// The scope is ignored for special uses of data-indirect-type, such
|
|
// as storage-convention. I think it's a bug that we ever mark things
|
|
// with Member storage convention, as that is already covered in the
|
|
// scope of the name. However, we don't want to change the dname scheme,
|
|
// so we're stuck with it.
|
|
//
|
|
ditType |= getScope ();
|
|
}
|
|
|
|
// Now skip the scope terminator
|
|
|
|
if ( !*gName )
|
|
ditType += DN_truncated;
|
|
elif ( *gName++ != '@' )
|
|
return DN_invalid;
|
|
|
|
} // End of IF
|
|
|
|
// Add the 'model' attributes (prefixed) as appropriate
|
|
|
|
if ( doMSKeywords ()) {
|
|
switch ( ditCode & DIT_modelmask )
|
|
{
|
|
#if !VERS_32BIT
|
|
case DIT_near:
|
|
if ( do32BitNear ())
|
|
ditType = UScore ( TOK_near ) + ditType;
|
|
break;
|
|
|
|
case DIT_far:
|
|
ditType = UScore ( TOK_far ) + ditType;
|
|
break;
|
|
|
|
case DIT_huge:
|
|
ditType = UScore ( TOK_huge ) + ditType;
|
|
break;
|
|
#endif
|
|
|
|
case DIT_based:
|
|
// The 'this-type' can never be 'based'
|
|
|
|
if ( thisFlag )
|
|
return DN_invalid;
|
|
|
|
ditType = getBasedType () + ditType;
|
|
break;
|
|
|
|
} // End of SWITCH
|
|
} // End of IF
|
|
elif (( ditCode & DIT_modelmask ) == DIT_based )
|
|
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 ())
|
|
if (superType.isArray())
|
|
ditType = superType; // array type, skip space
|
|
else
|
|
ditType += ' ' + superType;
|
|
else
|
|
ditType += ' ' + cvType + ' ' + superType;
|
|
|
|
} // End of IF then
|
|
elif ( !cvType.isEmpty ())
|
|
ditType += ' ' + cvType;
|
|
|
|
// Make sure qualifiers aren't re-applied
|
|
ditType.setPtrRef ();
|
|
|
|
// 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 DName UnDecorator::getPtrRefDataType ( const DName & superType, int isPtr )
|
|
{
|
|
// 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 ?
|
|
{
|
|
gName++;
|
|
|
|
return getArrayType( superType );
|
|
|
|
} // End of IF
|
|
|
|
// Otherwise, it is a 'basic-data-type'
|
|
|
|
if ( *gName == '_' && gName[1] == 'Z' ) // A boxed type ?
|
|
{
|
|
gName += 2;
|
|
return "__box " + getBasicDataType ( superType );
|
|
}
|
|
|
|
return getBasicDataType ( superType );
|
|
|
|
} // End of IF then
|
|
else
|
|
return ( DN_truncated + superType );
|
|
|
|
} // End of "UnDecorator" FUNCTION "getPtrRefDataType"
|
|
|
|
|
|
inline DName UnDecorator::getArrayType ( const DName & superType )
|
|
{
|
|
if ( *gName )
|
|
{
|
|
int noDimensions = getNumberOfDimensions ();
|
|
|
|
if ( noDimensions < 0 )
|
|
noDimensions = 0;
|
|
|
|
if ( !noDimensions )
|
|
return getBasicDataType ( DName ( '[' ) + DN_truncated + ']' );
|
|
else
|
|
{
|
|
DName arrayType;
|
|
|
|
if ( superType.isArray() ) {
|
|
arrayType += "[]";
|
|
}
|
|
|
|
while ( noDimensions-- )
|
|
arrayType += '[' + getDimension () + ']';
|
|
|
|
// If it is indirect, then parenthesise the 'super-type'
|
|
|
|
if ( !superType.isEmpty () )
|
|
if ( superType.isArray() )
|
|
arrayType = superType + arrayType;
|
|
else
|
|
arrayType = '(' + superType + ')' + arrayType;
|
|
|
|
// Return the finished array dimension information
|
|
|
|
DName newType = getPrimaryDataType ( arrayType );
|
|
newType.setIsArray();
|
|
return newType;
|
|
|
|
} // 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 UnDecorator::getLexicalFrame ( void ) { return '`' + getDimension () + '\''; }
|
|
inline DName UnDecorator::getStorageConvention ( void ) { return getDataIndirectType (); }
|
|
inline DName UnDecorator::getDataIndirectType () { return getDataIndirectType ( DName (), 0, DName ()); }
|
|
inline DName UnDecorator::getThisType ( void ) { return getDataIndirectType ( DName (), 0, DName (), TRUE ); }
|
|
|
|
inline DName UnDecorator::getPointerType ( const DName & cv, const DName & name )
|
|
{ return getPtrRefType ( cv, name, '*' ); }
|
|
|
|
inline DName UnDecorator::getPointerTypeArray ( const DName & cv, const DName & name )
|
|
{ return getPtrRefType ( cv, name, '\0' ); }
|
|
|
|
inline DName UnDecorator::getReferenceType ( const DName & cv, const DName & name )
|
|
{ return getPtrRefType ( cv, name, '&' ); }
|
|
|
|
inline DName UnDecorator::getSegmentName ( void ) { return getZName ( true ); }
|
|
|
|
#if ( !NO_COMPILER_NAMES )
|
|
inline DName UnDecorator::getDisplacement ( void ) { return getDimension ( true ); }
|
|
inline DName UnDecorator::getCallIndex ( void ) { return getDimension (); }
|
|
inline DName UnDecorator::getGuardNumber ( void ) { return getDimension (); }
|
|
|
|
inline DName UnDecorator::getVbTableType ( const DName & superType )
|
|
{ return getVfTableType ( superType ); }
|
|
|
|
|
|
inline DName UnDecorator::getVCallThunkType ( void )
|
|
{
|
|
#if VERS_32BIT
|
|
switch (*gName) {
|
|
case VMT_nTnCnV:
|
|
++gName;
|
|
return DName("{flat}");
|
|
case 0:
|
|
return DN_truncated;
|
|
default:
|
|
return DN_invalid;
|
|
}
|
|
#else
|
|
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_nTfCbV:
|
|
case VMT_fTnCbV:
|
|
case VMT_fTfCbV:
|
|
case VMT_nTnCbV:
|
|
vcallType += getBasedType ();
|
|
break;
|
|
|
|
} // End of SWITCH
|
|
|
|
// Always append 'vfptr'
|
|
|
|
vcallType += "vfptr}";
|
|
|
|
// And return the resultant 'vcall-model-type'
|
|
|
|
return vcallType;
|
|
#endif
|
|
|
|
} // End of "UnDecorator" FUNCTION "getVCallThunk"
|
|
|
|
|
|
inline DName UnDecorator::getVfTableType ( const DName & superType )
|
|
{
|
|
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"
|
|
|
|
|
|
inline DName UnDecorator::getVdispMapType ( const DName & superType )
|
|
{
|
|
DName vdispMapName = superType;
|
|
vdispMapName += "{for ";
|
|
vdispMapName += getScope();
|
|
vdispMapName += '}';
|
|
|
|
if ( *gName == '@' )
|
|
gName++;
|
|
return vdispMapName;
|
|
}
|
|
#endif // !NO_COMPILER_NAMES
|
|
|
|
|
|
inline DName UnDecorator::getExternalDataType ( const DName & superType )
|
|
{
|
|
// 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"
|
|
|
|
inline int UnDecorator::doUnderScore () { return !( disableFlags & UNDNAME_NO_LEADING_UNDERSCORES ); }
|
|
inline int UnDecorator::doMSKeywords () { return !( disableFlags & UNDNAME_NO_MS_KEYWORDS ); }
|
|
inline int UnDecorator::doPtr64 () { return !( disableFlags & UNDNAME_NO_PTR64 ); }
|
|
inline int UnDecorator::doFunctionReturns () { return !( disableFlags & UNDNAME_NO_FUNCTION_RETURNS ); }
|
|
inline int UnDecorator::doAllocationModel () { return !( disableFlags & UNDNAME_NO_ALLOCATION_MODEL ); }
|
|
inline int UnDecorator::doAllocationLanguage () { return !( disableFlags & UNDNAME_NO_ALLOCATION_LANGUAGE ); }
|
|
|
|
#if 0
|
|
inline int UnDecorator::doMSThisType () { return !( disableFlags & UNDNAME_NO_MS_THISTYPE ); }
|
|
inline int UnDecorator::doCVThisType () { return !( disableFlags & UNDNAME_NO_CV_THISTYPE ); }
|
|
#endif
|
|
|
|
inline int UnDecorator::doThisTypes () { return (( disableFlags & UNDNAME_NO_THISTYPE ) != UNDNAME_NO_THISTYPE ); }
|
|
inline int UnDecorator::doAccessSpecifiers () { return !( disableFlags & UNDNAME_NO_ACCESS_SPECIFIERS ); }
|
|
inline int UnDecorator::doThrowTypes () { return !( disableFlags & UNDNAME_NO_THROW_SIGNATURES ); }
|
|
inline int UnDecorator::doMemberTypes () { return !( disableFlags & UNDNAME_NO_MEMBER_TYPE ); }
|
|
inline int UnDecorator::doReturnUDTModel () { return !( disableFlags & UNDNAME_NO_RETURN_UDT_MODEL ); }
|
|
|
|
inline int UnDecorator::do32BitNear () { return !( disableFlags & UNDNAME_32_BIT_DECODE ); }
|
|
|
|
inline int UnDecorator::doNameOnly () { return ( disableFlags & UNDNAME_NAME_ONLY ); }
|
|
inline int UnDecorator::doTypeOnly () { return ( disableFlags & UNDNAME_TYPE_ONLY ); }
|
|
inline int UnDecorator::haveTemplateParameters () { return ( disableFlags & UNDNAME_HAVE_PARAMETERS); }
|
|
inline int UnDecorator::doEcsu () { return !( disableFlags & UNDNAME_NO_ECSU ); }
|
|
inline int UnDecorator::doNoIdentCharCheck () { return ( disableFlags & UNDNAME_NO_IDENT_CHAR_CHECK ); }
|
|
|
|
|
|
pcchar_t UnDecorator::UScore ( Tokens tok )
|
|
{
|
|
#if !VERS_32BIT
|
|
if ((( tok == TOK_nearSp ) || ( tok == TOK_nearP )) && !do32BitNear ())
|
|
return tokenTable[ tok ] + 6; // Skip '__near'
|
|
#endif
|
|
if ( doUnderScore ())
|
|
return tokenTable[ tok ];
|
|
else
|
|
return tokenTable[ tok ] + 2 ;
|
|
|
|
} // End of "UnDecorator" FUNCTION "UScore"
|
|
|
|
|
|
// Include the string composition support classes. Mostly inline stuff, and
|
|
// not important to the algorithm.
|
|
|
|
#include "undname.inl"
|