📄 undname.cpp
字号:
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;
else
heap.Constructor ( pAlloc, pFree );
// Create the undecorator object, and get the result
UnDecorator unDecorate ( outputString,
name,
maxStringLength,
pGetParameter,
disableFlags
);
pchar_t unDecoratedName = unDecorate;
// Destruct the heap (would use a destructor, but that causes DLL problems)
heap.Destructor ();
// And return the composed name
return unDecoratedName;
} // End of FUNCTION "unDName"
// The 'UnDecorator' member functions
inline __near UnDecorator::UnDecorator ( pchar_t output,
pcchar_t dName,
int maxLen,
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;
} // End of "UnDecorator" CONSTRUCTOR '()'
inline __near 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
elif (( *name == '?' ) && ( name[1] == '$' ))
result = getTemplateName ();
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 );
// Return the result
return outputString;
} // End of "UnDecorator" OPERATOR 'pchar_t'
DName __near 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() )
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 __near UnDecorator::getSymbolName ( void )
{
if ( *gName == '?' )
{
gName++;
return getOperatorName ();
} // End of IF then
else
return getZName ();
} // End of "UnDecorator" FUNCTION "getSymbolName"
DName __near UnDecorator::getZName ( void )
{
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 ();
if ( *gName++ != '@' )
zName = *--gName ? DN_invalid : DN_truncated;
}
else
// Extract the 'zname' to the terminator
zName = DName( gName, '@' ); // This constructor updates 'name'
// Add it to the current list of 'zname's
if ( !pZNameList->isFull ())
*pZNameList += zName;
// And return the symbol name
return zName;
} // End of IF else
} // End of "UnDecorator" FUNCTION "getZName"
inline DName __near UnDecorator::getOperatorName ( void )
{
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!
//
{
// Use a temporary. Don't want to advance the name pointer
pcchar_t pName = gName;
operatorName = getZName ();
gName = pName; // Undo our lookahead
if ( !operatorName.isEmpty () && ( gName[ -1 ] == OC_dtor ))
operatorName = '~' + operatorName;
return operatorName;
} // End of CASE 'OC_ctor,OC_dtor'
break;
case OC_new:
case OC_delete:
case OC_assign:
case OC_rshift:
case OC_lshift:
case OC_not:
case OC_equal:
case OC_unequal:
operatorName = nameTable[ gName[ -1 ] - OC_new ];
break;
case OC_udc:
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_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();
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;
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 __near 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 ( !scope.isEmpty() ) {
scope = "::" + scope;
if (fNeedBracket) {
scope = '[' + scope;
fNeedBracket = false;
}
}
// Determine what kind of scope it is
if ( *gName == '?' )
switch ( *++gName )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -