2016-10-04 00:16:22 -06:00
|
|
|
# CodeWarrior-style C++ name mangling
|
|
|
|
|
MANGLED_TYPES = {
|
|
|
|
|
'void': 'v',
|
|
|
|
|
'bool': 'b',
|
|
|
|
|
'char': 'c',
|
2016-10-06 10:00:02 -06:00
|
|
|
'wchar_t': 'w',
|
2016-10-04 00:16:22 -06:00
|
|
|
'short': 's',
|
|
|
|
|
'int': 'i',
|
|
|
|
|
'long': 'l',
|
|
|
|
|
'size_t': 'Ul',
|
|
|
|
|
'long long': 'x',
|
|
|
|
|
'signed char': 'c',
|
|
|
|
|
'unsigned char': 'Uc',
|
|
|
|
|
'signed short': 's',
|
|
|
|
|
'unsigned short': 'Us',
|
|
|
|
|
'signed int': 'i',
|
|
|
|
|
'unsigned int': 'Ui',
|
|
|
|
|
'signed long': 'l',
|
|
|
|
|
'unsigned long': 'Ul',
|
|
|
|
|
'signed long long': 'x',
|
|
|
|
|
'unsigned long long': 'Ux',
|
|
|
|
|
'uint': 'Ui',
|
|
|
|
|
'int8': 'c',
|
|
|
|
|
'uint8': 'Uc',
|
|
|
|
|
'int16': 's',
|
|
|
|
|
'uint16': 'Us',
|
|
|
|
|
'int32': 'l',
|
|
|
|
|
'uint32': 'Ul',
|
|
|
|
|
'int64': 'x',
|
|
|
|
|
'uint64': 'Ux',
|
|
|
|
|
'float': 'f',
|
|
|
|
|
'double': 'd'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def is_basic_type(typeName):
|
|
|
|
|
return typeName in MANGLED_TYPES
|
|
|
|
|
|
|
|
|
|
def mangle_operator(operName):
|
|
|
|
|
# Note: There are some missing operators here (particularly bitwise operators).
|
|
|
|
|
name = operName.replace(' ', '')
|
|
|
|
|
|
|
|
|
|
# Arithmetic
|
|
|
|
|
if name == "operator=":
|
|
|
|
|
return "__as"
|
|
|
|
|
elif name == "operator+":
|
|
|
|
|
return "__pl"
|
|
|
|
|
elif name == "operator+=":
|
|
|
|
|
return "__apl"
|
|
|
|
|
elif name == "operator-":
|
|
|
|
|
return "__mi"
|
|
|
|
|
elif name == "operator-=":
|
|
|
|
|
return "__ami"
|
|
|
|
|
elif name == "operator*":
|
|
|
|
|
return "__ml"
|
|
|
|
|
elif name == "operator*=":
|
|
|
|
|
return "__amu"
|
|
|
|
|
elif name == "operator/":
|
|
|
|
|
return "__dv"
|
|
|
|
|
elif name == "operator/=":
|
|
|
|
|
return "__adv"
|
|
|
|
|
|
|
|
|
|
# Logic
|
|
|
|
|
elif name == "operator<":
|
|
|
|
|
return "__lt"
|
|
|
|
|
elif name == "operator<=":
|
|
|
|
|
return "__le"
|
|
|
|
|
elif name == "operator>":
|
|
|
|
|
return "__gt"
|
|
|
|
|
elif name == "operator>=":
|
|
|
|
|
return "__ge"
|
|
|
|
|
elif name == "operator==":
|
|
|
|
|
return "__eq"
|
|
|
|
|
elif name == "operator!=":
|
|
|
|
|
return "__ne"
|
|
|
|
|
|
|
|
|
|
# Allocation
|
|
|
|
|
elif name == "operatornew":
|
|
|
|
|
return "__nw"
|
|
|
|
|
elif name == "operatornew[]":
|
|
|
|
|
return "__nwa"
|
|
|
|
|
elif name == "operatordelete":
|
|
|
|
|
return "__dl"
|
|
|
|
|
elif name == "operatordelete[]":
|
|
|
|
|
return "__dla"
|
|
|
|
|
|
|
|
|
|
return operName
|
|
|
|
|
|
|
|
|
|
def split_scopes(scopedName):
|
|
|
|
|
isOperatorFunc = False
|
2016-10-06 10:00:02 -06:00
|
|
|
innerDepth = 0
|
2016-10-04 00:16:22 -06:00
|
|
|
lastSplit = -2
|
|
|
|
|
out = []
|
|
|
|
|
|
|
|
|
|
for chrIdx in range(0, len(scopedName)):
|
|
|
|
|
if scopedName[chrIdx:chrIdx+8] == "operator":
|
|
|
|
|
isOperatorFunc = True
|
|
|
|
|
|
2016-10-06 10:00:02 -06:00
|
|
|
elif (scopedName[chrIdx] == '<' or scopedName[chrIdx] == '(') and not isOperatorFunc:
|
|
|
|
|
innerDepth += 1
|
2016-10-04 00:16:22 -06:00
|
|
|
|
2016-10-06 10:00:02 -06:00
|
|
|
elif (scopedName[chrIdx] == '>' or scopedName[chrIdx] == ')') and not isOperatorFunc:
|
|
|
|
|
innerDepth -= 1
|
2016-10-04 00:16:22 -06:00
|
|
|
|
2016-10-06 10:00:02 -06:00
|
|
|
elif scopedName[chrIdx:chrIdx+2] == '::' and innerDepth == 0:
|
2016-10-04 00:16:22 -06:00
|
|
|
out.append(scopedName[lastSplit + 2 : chrIdx])
|
|
|
|
|
lastSplit = chrIdx
|
|
|
|
|
|
|
|
|
|
out.append(scopedName[lastSplit + 2 : len(scopedName)])
|
|
|
|
|
return out
|
|
|
|
|
|
|
|
|
|
def split_params(paramText):
|
|
|
|
|
out = []
|
|
|
|
|
templateDepth = 0
|
|
|
|
|
lastSplit = -1
|
|
|
|
|
|
|
|
|
|
for chrIdx in range(0, len(paramText)):
|
|
|
|
|
chr = paramText[chrIdx]
|
|
|
|
|
|
|
|
|
|
if chr == '<':
|
|
|
|
|
templateDepth += 1
|
|
|
|
|
elif chr == '>':
|
|
|
|
|
templateDepth -= 1
|
|
|
|
|
elif chr == ',' and templateDepth == 0:
|
|
|
|
|
out.append(paramText[lastSplit+1 : chrIdx].strip())
|
|
|
|
|
lastSplit = chrIdx
|
|
|
|
|
|
|
|
|
|
out.append(paramText[lastSplit+1 : len(paramText)].strip())
|
|
|
|
|
return out
|
|
|
|
|
|
|
|
|
|
def mangle_template(templateText):
|
|
|
|
|
assert(templateText.startswith('<') and templateText.endswith('>'))
|
|
|
|
|
templateText = templateText[1:-1]
|
|
|
|
|
params = split_params(templateText)
|
|
|
|
|
mangledParams = []
|
|
|
|
|
|
|
|
|
|
for param in params:
|
|
|
|
|
mangledParams.append( mangle_type(param) )
|
|
|
|
|
|
|
|
|
|
return '<' + ','.join(mangledParams) + '>'
|
|
|
|
|
|
|
|
|
|
def mangle_type(typename):
|
|
|
|
|
if is_basic_type(typename):
|
|
|
|
|
baseTypeName = MANGLED_TYPES[typename]
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
baseTypeName = ""
|
|
|
|
|
scopes = split_scopes(typename)
|
|
|
|
|
|
|
|
|
|
if len(scopes) > 1:
|
|
|
|
|
baseTypeName = "Q%d" % len(scopes)
|
|
|
|
|
|
|
|
|
|
for scope in scopes:
|
|
|
|
|
# Check for template
|
|
|
|
|
templateBegin = scope.find('<')
|
|
|
|
|
|
|
|
|
|
if templateBegin != -1:
|
|
|
|
|
templateEnd = scope.rfind('>')
|
|
|
|
|
assert(templateEnd != -1)
|
|
|
|
|
baseType = scope[0:templateBegin]
|
|
|
|
|
mangledTemplate = mangle_template(scope[templateBegin : templateEnd + 1])
|
|
|
|
|
baseTypeName += '%d%s%s' % (len(baseType) + len(mangledTemplate), baseType, mangledTemplate)
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
baseTypeName += '%d%s' % (len(scope), scope)
|
|
|
|
|
|
|
|
|
|
return baseTypeName
|
|
|
|
|
|
|
|
|
|
def mangle_params(params):
|
|
|
|
|
if not params:
|
|
|
|
|
return 'Fv'
|
|
|
|
|
|
|
|
|
|
# Get list of arguments. Can't use split() due to potential templates with multiple parameters
|
|
|
|
|
args = split_params(params)
|
|
|
|
|
out = ['F']
|
|
|
|
|
|
|
|
|
|
for arg in args:
|
|
|
|
|
type = arg
|
|
|
|
|
qualifiers = ''
|
|
|
|
|
baseTypeName = ''
|
|
|
|
|
|
|
|
|
|
while len(type) > 0:
|
|
|
|
|
if type.endswith('&'):
|
|
|
|
|
qualifiers += 'R'
|
|
|
|
|
type = type[:-1].strip()
|
|
|
|
|
|
|
|
|
|
elif type.endswith('*'):
|
|
|
|
|
qualifiers += 'P'
|
|
|
|
|
type = type[:-1].strip()
|
|
|
|
|
|
|
|
|
|
elif type.endswith('const'):
|
|
|
|
|
qualifiers += 'C'
|
|
|
|
|
type = type[:-5].strip()
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
if type.endswith('>'):
|
|
|
|
|
searchLen = type.find('<')
|
|
|
|
|
else:
|
|
|
|
|
searchLen = len(type)
|
|
|
|
|
|
|
|
|
|
baseBegin = max(type.rfind(chr, 0, searchLen) for chr in " *&") + 1
|
|
|
|
|
|
|
|
|
|
if type[baseBegin - 9 : baseBegin - 1] == "unsigned":
|
|
|
|
|
baseBegin -= 9
|
|
|
|
|
|
|
|
|
|
elif type[baseBegin - 7 : baseBegin - 1] == "signed":
|
|
|
|
|
baseBegin -= 7
|
|
|
|
|
|
|
|
|
|
baseType = type[baseBegin:len(type)]
|
|
|
|
|
baseTypeName = mangle_type(baseType)
|
|
|
|
|
type = type[:-len(baseType)].strip()
|
|
|
|
|
|
|
|
|
|
out.append(qualifiers + baseTypeName)
|
|
|
|
|
|
|
|
|
|
return ''.join(out)
|
|
|
|
|
|
|
|
|
|
def mangle(funcSignature):
|
|
|
|
|
mangled = ''
|
|
|
|
|
|
|
|
|
|
funcName = funcSignature[0:funcSignature.find('(')]
|
|
|
|
|
scopes = split_scopes(funcName)
|
|
|
|
|
isScoped = len(scopes) > 1
|
|
|
|
|
isConst = funcSignature.find('const', funcSignature.rfind(')')) != -1
|
|
|
|
|
baseName = scopes[-1]
|
|
|
|
|
|
|
|
|
|
# Check for operators/templates
|
|
|
|
|
if baseName.startswith("operator"):
|
|
|
|
|
baseName = mangle_operator(baseName)
|
|
|
|
|
|
|
|
|
|
elif '<' in baseName:
|
|
|
|
|
templateBegin = baseName.find('<')
|
|
|
|
|
templateEnd = baseName.rfind('>')
|
|
|
|
|
assert(templateBegin != -1 and templateEnd != -1)
|
|
|
|
|
|
|
|
|
|
baseFuncName = baseName[0:templateBegin]
|
|
|
|
|
mangledTemplate = mangle_template(baseName[templateBegin : templateEnd + 1])
|
|
|
|
|
baseName = baseFuncName + mangledTemplate
|
|
|
|
|
|
|
|
|
|
mangled = baseName + '__'
|
|
|
|
|
|
|
|
|
|
if isScoped:
|
|
|
|
|
del scopes[-1]
|
|
|
|
|
|
|
|
|
|
if len(scopes) > 1:
|
|
|
|
|
mangled += "Q%d" % len(scopes)
|
|
|
|
|
|
|
|
|
|
for name in scopes:
|
|
|
|
|
mangled += "%d%s" % (len(name), name)
|
|
|
|
|
|
|
|
|
|
if isConst:
|
|
|
|
|
mangled += 'C'
|
|
|
|
|
|
|
|
|
|
params = funcSignature[ funcSignature.find('(') + 1 : funcSignature.rfind(')') ]
|
|
|
|
|
return mangled + mangle_params(params)
|