Initial port
This commit is contained in:
parent
57b1234feb
commit
c62b236627
|
@ -209,12 +209,41 @@ static std::string_view StripEnclosingChars(std::string_view str, T chars)
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static std::string_view StripStartChars(std::string_view str, T chars)
|
||||||
|
{
|
||||||
|
const size_t s = str.find_first_not_of(chars);
|
||||||
|
|
||||||
|
if (str.npos != s)
|
||||||
|
return str.substr(s);
|
||||||
|
else
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static std::string_view StripEndChars(std::string_view str, T chars)
|
||||||
|
{
|
||||||
|
return str.substr(0, str.find_last_not_of(chars) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
// Turns "\n\r\t hello " into "hello" (trims at the start and end but not inside).
|
// Turns "\n\r\t hello " into "hello" (trims at the start and end but not inside).
|
||||||
std::string_view StripWhitespace(std::string_view str)
|
std::string_view StripWhitespace(std::string_view str)
|
||||||
{
|
{
|
||||||
return StripEnclosingChars(str, " \t\r\n");
|
return StripEnclosingChars(str, " \t\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Turns "\n\r\t hello " into "hello " (trims at the start).
|
||||||
|
std::string_view StripWhitespaceStart(std::string_view str)
|
||||||
|
{
|
||||||
|
return StripStartChars(str, " \t\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Turns "\n\r\t hello " into "\n\r\t hello" (trims at the end).
|
||||||
|
std::string_view StripWhitespaceEnd(std::string_view str)
|
||||||
|
{
|
||||||
|
return StripEndChars(str, " \t\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
std::string_view StripSpaces(std::string_view str)
|
std::string_view StripSpaces(std::string_view str)
|
||||||
{
|
{
|
||||||
return StripEnclosingChars(str, ' ');
|
return StripEnclosingChars(str, ' ');
|
||||||
|
|
|
@ -61,6 +61,8 @@ inline void CharArrayFromFormat(char (&out)[Count], const char* format, ...)
|
||||||
std::string ArrayToString(const u8* data, u32 size, int line_len = 20, bool spaces = true);
|
std::string ArrayToString(const u8* data, u32 size, int line_len = 20, bool spaces = true);
|
||||||
|
|
||||||
std::string_view StripWhitespace(std::string_view s);
|
std::string_view StripWhitespace(std::string_view s);
|
||||||
|
std::string_view StripWhitespaceStart(std::string_view s);
|
||||||
|
std::string_view StripWhitespaceEnd(std::string_view s);
|
||||||
std::string_view StripSpaces(std::string_view s);
|
std::string_view StripSpaces(std::string_view s);
|
||||||
std::string_view StripQuotes(std::string_view s);
|
std::string_view StripQuotes(std::string_view s);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,849 @@
|
||||||
|
#include "Core/PowerPC/CWDemangler.h"
|
||||||
|
|
||||||
|
#include <cctype>
|
||||||
|
#include <map>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#include "common/StringUtil.h"
|
||||||
|
|
||||||
|
static const std::map<std::string, std::string> operators = {
|
||||||
|
{"nw", "operator new"},
|
||||||
|
{"nwa", "operator new[]"},
|
||||||
|
{"dl", "operator delete"},
|
||||||
|
{"dla", "operator delete[]"},
|
||||||
|
{"pl", "operator+"},
|
||||||
|
{"mi", "operator-"},
|
||||||
|
{"ml", "operator*"},
|
||||||
|
{"dv", "operator/"},
|
||||||
|
{"md", "operator%"},
|
||||||
|
{"er", "operator^"},
|
||||||
|
{"ad", "operator&"},
|
||||||
|
{"or", "operator|"},
|
||||||
|
{"co", "operator~"},
|
||||||
|
{"nt", "operator!"},
|
||||||
|
{"as", "operator="},
|
||||||
|
{"lt", "operator<"},
|
||||||
|
{"gt", "operator>"},
|
||||||
|
{"apl", "operator+="},
|
||||||
|
{"ami", "operator-="},
|
||||||
|
{"amu", "operator*="},
|
||||||
|
{"adv", "operator/="},
|
||||||
|
{"amd", "operator%="},
|
||||||
|
{"aer", "operator^="},
|
||||||
|
{"aad", "operator&="},
|
||||||
|
{"aor", "operator|="},
|
||||||
|
{"ls", "operator<<"},
|
||||||
|
{"rs", "operator>>"},
|
||||||
|
{"ars", "operator>>="},
|
||||||
|
{"als", "operator<<="},
|
||||||
|
{"eq", "operator=="},
|
||||||
|
{"ne", "operator!="},
|
||||||
|
{"le", "operator<="},
|
||||||
|
{"ge", "operator>="},
|
||||||
|
{"aa", "operator&&"},
|
||||||
|
{"oo", "operator||"},
|
||||||
|
{"pp", "operator++"},
|
||||||
|
{"mm", "operator--"},
|
||||||
|
{"cm", "operator,"},
|
||||||
|
{"rm", "operator->*"},
|
||||||
|
{"rf", "operator->"},
|
||||||
|
{"cl", "operator()"},
|
||||||
|
{"vc", "operator[]"},
|
||||||
|
{"vt", "__vtable"}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::tuple<std::string, std::string, std::string> CWDemangler::parse_qualifiers(std::string str)
|
||||||
|
{
|
||||||
|
std::string pre = "";
|
||||||
|
std::string post = "";
|
||||||
|
for (char c : str)
|
||||||
|
{
|
||||||
|
bool foundNonQualifier = false;
|
||||||
|
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 'P':
|
||||||
|
if (pre == "")
|
||||||
|
{
|
||||||
|
post = post.insert(0, "*");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
post = post.insert(0, fmt::format("* {0}", StripWhitespaceEnd(pre)));
|
||||||
|
pre = "";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'R':
|
||||||
|
if (pre == "")
|
||||||
|
{
|
||||||
|
post = post.insert(0, "&");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
post = post.insert(0, fmt::format("& {0}", StripWhitespaceEnd(pre)));
|
||||||
|
pre = "";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
pre += "const ";
|
||||||
|
break;
|
||||||
|
case 'V':
|
||||||
|
pre += "volatile ";
|
||||||
|
break;
|
||||||
|
case 'U':
|
||||||
|
pre += "unsigned ";
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
pre += "signed ";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
foundNonQualifier = true;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (foundNonQualifier)
|
||||||
|
break;
|
||||||
|
str = str.substr(1);
|
||||||
|
}
|
||||||
|
post = StripWhitespaceEnd(post);
|
||||||
|
return {pre, post, str};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::tuple<int, std::string>> CWDemangler::parse_digits(std::string str)
|
||||||
|
{
|
||||||
|
bool containsNonDigit = false;
|
||||||
|
int idx = 0;
|
||||||
|
while (idx < str.length())
|
||||||
|
{
|
||||||
|
if (!std::isdigit(str[idx]))
|
||||||
|
{
|
||||||
|
containsNonDigit = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int val = 0;
|
||||||
|
|
||||||
|
if (containsNonDigit)
|
||||||
|
{
|
||||||
|
std::istringstream iss(str.substr(0, idx));
|
||||||
|
iss >> val;
|
||||||
|
|
||||||
|
if (!iss)
|
||||||
|
return {};
|
||||||
|
return {{val, str.substr(idx)}};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// all digits!
|
||||||
|
std::istringstream iss(str);
|
||||||
|
iss >> val;
|
||||||
|
|
||||||
|
if (!iss)
|
||||||
|
return {};
|
||||||
|
return {{val, ""}};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::tuple<std::string, std::string>>
|
||||||
|
CWDemangler::demangle_template_args(std::string str, DemangleOptions options)
|
||||||
|
{
|
||||||
|
size_t start_idx = str.find('<');
|
||||||
|
std::string tmpl_args;
|
||||||
|
|
||||||
|
if (start_idx != std::string::npos)
|
||||||
|
{
|
||||||
|
size_t end_idx = str.rfind('>');
|
||||||
|
if (end_idx == std::string::npos || end_idx < start_idx)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string args = str.substr(start_idx + 1, end_idx - (start_idx + 1));
|
||||||
|
str = str.substr(0, start_idx);
|
||||||
|
tmpl_args = "<";
|
||||||
|
|
||||||
|
while (args != "")
|
||||||
|
{
|
||||||
|
auto result = demangle_arg(args, options);
|
||||||
|
if (!result)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::string arg;
|
||||||
|
std::string arg_post;
|
||||||
|
std::string rest;
|
||||||
|
|
||||||
|
std::tie(arg, arg_post, rest) = result.value();
|
||||||
|
tmpl_args += arg;
|
||||||
|
tmpl_args += arg_post;
|
||||||
|
|
||||||
|
if (rest == "")
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tmpl_args += ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
args = rest.substr(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpl_args += ">";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tmpl_args = "";
|
||||||
|
};
|
||||||
|
return {{str, tmpl_args}};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::tuple<std::string, std::string, std::string>>
|
||||||
|
CWDemangler::demangle_name(std::string str, DemangleOptions options)
|
||||||
|
{
|
||||||
|
auto result = parse_digits(str);
|
||||||
|
if (!result)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
int size;
|
||||||
|
std::string rest;
|
||||||
|
std::tie(size, rest) = result.value();
|
||||||
|
|
||||||
|
if (rest.length() < size)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result1 = demangle_template_args(rest.substr(0, size), options);
|
||||||
|
if (!result1)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::string name, args;
|
||||||
|
std::tie(name, args) = result1.value();
|
||||||
|
return {{name, fmt::format("{0}{1}", name, args), rest.substr(size)}};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::tuple<std::string, std::string, std::string>>
|
||||||
|
CWDemangler::demangle_qualified_name(std::string str, DemangleOptions options)
|
||||||
|
{
|
||||||
|
if (str.starts_with('Q'))
|
||||||
|
{
|
||||||
|
if (str.length() < 3)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
int count;
|
||||||
|
|
||||||
|
if (!(std::istringstream(str.substr(1,1)) >> count))
|
||||||
|
return {};
|
||||||
|
str = str.substr(2);
|
||||||
|
|
||||||
|
std::string last_class = "";
|
||||||
|
std::string qualified = "";
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
auto result = demangle_name(str, options);
|
||||||
|
if (!result)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::string class_name, full, rest;
|
||||||
|
|
||||||
|
std::tie(class_name, full, rest) = result.value();
|
||||||
|
qualified += full;
|
||||||
|
last_class = class_name;
|
||||||
|
str = rest;
|
||||||
|
if (i < count - 1)
|
||||||
|
{
|
||||||
|
qualified += "::";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {{last_class, qualified, str}};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return demangle_name(str, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::tuple<std::string, std::string, std::string>>
|
||||||
|
CWDemangler::demangle_arg(std::string str, DemangleOptions options)
|
||||||
|
{
|
||||||
|
// Negative constant
|
||||||
|
if (str.starts_with('-'))
|
||||||
|
{
|
||||||
|
auto parseResult = parse_digits(str.substr(1));
|
||||||
|
if (!parseResult)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
int size;
|
||||||
|
std::string restVal;
|
||||||
|
|
||||||
|
std::tie(size, restVal) = parseResult.value();
|
||||||
|
std::string outVal = fmt::format("-{}", size);
|
||||||
|
return {{outVal, "", restVal}};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string result = "";
|
||||||
|
|
||||||
|
std::string pre, post, rest;
|
||||||
|
std::tie(pre, post, rest) = parse_qualifiers(str);
|
||||||
|
result += pre;
|
||||||
|
str = rest;
|
||||||
|
|
||||||
|
// Disambiguate arguments starting with a number
|
||||||
|
if (str.length() > 0 && std::isdigit(str[0]))
|
||||||
|
{
|
||||||
|
auto parseResult = parse_digits(str);
|
||||||
|
if (!parseResult)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
int num;
|
||||||
|
|
||||||
|
std::tie(num, rest) = parseResult.value();
|
||||||
|
// If the number is followed by a comma or the end of the string, it's a template argument
|
||||||
|
if (rest == "" || rest.starts_with(','))
|
||||||
|
{
|
||||||
|
// ...or a Metrowerks extension type
|
||||||
|
if (options.mw_extensions)
|
||||||
|
{
|
||||||
|
std::string t = num == 1 ? "__int128" : num == 2 ? "__vec2x32float__" : "";
|
||||||
|
|
||||||
|
if (t != "")
|
||||||
|
{
|
||||||
|
result += t;
|
||||||
|
return {{result, post, rest}};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result += std::to_string(num);
|
||||||
|
result += post;
|
||||||
|
return {{result, "", rest}};
|
||||||
|
}
|
||||||
|
// Otherwise, it's (probably) the size of a type
|
||||||
|
auto demangleNameResult = demangle_name(str, options);
|
||||||
|
if (!demangleNameResult)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::string qualified;
|
||||||
|
std::tie(std::ignore, qualified, rest) = demangleNameResult.value();
|
||||||
|
result += qualified;
|
||||||
|
result += post;
|
||||||
|
return {{result, "", rest}};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle qualified names
|
||||||
|
if (str.starts_with('Q'))
|
||||||
|
{
|
||||||
|
auto demangleQualResult = demangle_qualified_name(str, options);
|
||||||
|
if (!demangleQualResult)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::string qualified;
|
||||||
|
std::tie(std::ignore, qualified, rest) = demangleQualResult.value();
|
||||||
|
result += qualified;
|
||||||
|
result += post;
|
||||||
|
return {{result, "", rest}};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_member = false;
|
||||||
|
bool const_member = false;
|
||||||
|
if (str.starts_with('M'))
|
||||||
|
{
|
||||||
|
is_member = true;
|
||||||
|
auto demangleQualResult = demangle_qualified_name(str.substr(1), options);
|
||||||
|
if (!demangleQualResult)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::string member;
|
||||||
|
std::tie(std::ignore, member, rest) = demangleQualResult.value();
|
||||||
|
pre = fmt::format("{}::*{}", member, pre);
|
||||||
|
if (!rest.starts_with('F'))
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
str = rest;
|
||||||
|
}
|
||||||
|
if (is_member || str.starts_with('F'))
|
||||||
|
{
|
||||||
|
str = str.substr(1);
|
||||||
|
if (is_member)
|
||||||
|
{
|
||||||
|
// "const void*, const void*" or "const void*, void*"
|
||||||
|
if (str.starts_with("PCvPCv"))
|
||||||
|
{
|
||||||
|
const_member = true;
|
||||||
|
str = str.substr(6);
|
||||||
|
}
|
||||||
|
else if (str.starts_with("PCvPv"))
|
||||||
|
{
|
||||||
|
str = str.substr(5);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (post.starts_with('*'))
|
||||||
|
{
|
||||||
|
post = StripWhitespaceStart(post.substr(1));
|
||||||
|
pre = fmt::format("*{}", pre);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto demangleFuncArgsResult = demangle_function_args(str, options);
|
||||||
|
if (!demangleFuncArgsResult)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::string args;
|
||||||
|
std::tie(args, rest) = demangleFuncArgsResult.value();
|
||||||
|
|
||||||
|
if (!rest.starts_with('_'))
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto demangleArgResult = demangle_arg(rest.substr(1), options);
|
||||||
|
if (!demangleArgResult)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::string ret_pre, ret_post;
|
||||||
|
std::tie(ret_pre, ret_post, rest) = demangleArgResult.value();
|
||||||
|
std::string const_str = const_member ? " const" : "";
|
||||||
|
std::string res_pre = fmt::format("{} ({}{})", ret_pre, pre, post);
|
||||||
|
std::string res_post = fmt::format(")({}){}{}", res_pre, res_post, rest);
|
||||||
|
return {{res_pre, res_post, rest}};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str.starts_with('A'))
|
||||||
|
{
|
||||||
|
auto parseResult = parse_digits(str.substr(1));
|
||||||
|
if (!parseResult)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
int count;
|
||||||
|
std::tie(count, rest) = parseResult.value();
|
||||||
|
|
||||||
|
if (!rest.starts_with('_'))
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto demangleArgResult = demangle_arg(rest.substr(1), options);
|
||||||
|
if (!demangleArgResult)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::string arg_pre, arg_post;
|
||||||
|
std::tie(arg_pre, arg_post, rest) = demangleArgResult.value();
|
||||||
|
|
||||||
|
if (post != "")
|
||||||
|
{
|
||||||
|
post = fmt::format("({})", post);
|
||||||
|
}
|
||||||
|
result = fmt::format("{}{}{}", pre, arg_pre, post);
|
||||||
|
std::string ret_post = fmt::format("[{}]{}", count, arg_post);
|
||||||
|
return {{result, ret_post, rest}};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str.length() == 0)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::string type = "";
|
||||||
|
|
||||||
|
switch (str[0])
|
||||||
|
{
|
||||||
|
case 'i':
|
||||||
|
type = "int";
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
type = "bool";
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
type = "char";
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
type = "short";
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
type = "long";
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
type = "long long";
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
type = "float";
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
type = "double";
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
type = "wchar_t";
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
type = "void";
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
type = "...";
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
if (options.mw_extensions)
|
||||||
|
type = "__int128";
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
if (options.mw_extensions)
|
||||||
|
type = "__vec2x32float__";
|
||||||
|
break;
|
||||||
|
case '_':
|
||||||
|
return {{result, "", rest}};
|
||||||
|
default:
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
result += type;
|
||||||
|
|
||||||
|
result += post;
|
||||||
|
return {{result, "", str.substr(1)}};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::tuple<std::string, std::string>>
|
||||||
|
CWDemangler::demangle_function_args(std::string str, DemangleOptions options)
|
||||||
|
{
|
||||||
|
std::string result = "";
|
||||||
|
|
||||||
|
while (str != "")
|
||||||
|
{
|
||||||
|
if (result != "")
|
||||||
|
{
|
||||||
|
result += ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
auto demangleArgResult = demangle_arg(str, options);
|
||||||
|
if (!demangleArgResult)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::string arg, arg_post, rest;
|
||||||
|
|
||||||
|
std::tie(arg, arg_post, rest) = demangleArgResult.value();
|
||||||
|
|
||||||
|
result += arg;
|
||||||
|
result += arg_post;
|
||||||
|
str = rest;
|
||||||
|
|
||||||
|
if (str.starts_with('_') || str.starts_with(','))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {{result, str}};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> CWDemangler::demangle_special_function(std::string str, std::string class_name, DemangleOptions options)
|
||||||
|
{
|
||||||
|
if (str.starts_with("op"))
|
||||||
|
{
|
||||||
|
std::string rest = str.substr(2);
|
||||||
|
auto demangleArgResult = demangle_arg(rest, options);
|
||||||
|
if (!demangleArgResult)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::string arg_pre, arg_post;
|
||||||
|
|
||||||
|
std::tie(arg_pre, arg_post, std::ignore) = demangleArgResult.value();
|
||||||
|
return fmt::format("operator {}{}", arg_pre, arg_post);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = demangle_template_args(str, options);
|
||||||
|
if (!result)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::string op, args;
|
||||||
|
|
||||||
|
std::tie(op, args) = result.value();
|
||||||
|
|
||||||
|
std::string funcName;
|
||||||
|
|
||||||
|
if (op == "dt")
|
||||||
|
{
|
||||||
|
return fmt::format("~{}{}", class_name, args);
|
||||||
|
}
|
||||||
|
else if (op == "ct")
|
||||||
|
{
|
||||||
|
funcName = class_name;
|
||||||
|
}
|
||||||
|
else if (operators.contains(op))
|
||||||
|
{
|
||||||
|
funcName = operators.at(op);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return fmt::format("__{}{}", op, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt::format("{0}{1}", funcName, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Demangle a symbol name.
|
||||||
|
///
|
||||||
|
/// Returns `null` if the input is not a valid mangled name.
|
||||||
|
std::optional<std::string> CWDemangler::demangle(std::string str, DemangleOptions options)
|
||||||
|
{
|
||||||
|
if (!IsAscii(str))
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool special = false;
|
||||||
|
bool cnst = false;
|
||||||
|
std::string fn_name;
|
||||||
|
std::string return_type_pre = "";
|
||||||
|
std::string return_type_post = "";
|
||||||
|
std::string qualified = "";
|
||||||
|
std::string static_var = "";
|
||||||
|
|
||||||
|
// Handle new static function variables (Wii CW)
|
||||||
|
bool guard = str.starts_with("@GUARD@");
|
||||||
|
if (guard || str.starts_with("@LOCAL@"))
|
||||||
|
{
|
||||||
|
str = str.substr(7);
|
||||||
|
size_t idx = str.rfind('@');
|
||||||
|
if (idx == std::string::npos)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::string rest = str.substr(0, idx);
|
||||||
|
std::string var = str.substr(idx);
|
||||||
|
|
||||||
|
if (guard)
|
||||||
|
{
|
||||||
|
static_var = fmt::format("{0} guard", var.substr(1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static_var = var.substr(1);
|
||||||
|
}
|
||||||
|
str = rest;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str.starts_with("__"))
|
||||||
|
{
|
||||||
|
special = true;
|
||||||
|
str = str.substr(2);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto idxTemp = find_split(str, special, options);
|
||||||
|
if (!idxTemp)
|
||||||
|
return {};
|
||||||
|
size_t idx = idxTemp.value();
|
||||||
|
// Handle any trailing underscores in the function name
|
||||||
|
while (str[idx + 2] == '_')
|
||||||
|
{
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string fn_name_out = str.substr(0, idx);
|
||||||
|
std::string rest = str.substr(idx);
|
||||||
|
|
||||||
|
if (special)
|
||||||
|
{
|
||||||
|
if (fn_name_out == "init")
|
||||||
|
{
|
||||||
|
// Special case for double __
|
||||||
|
size_t rest_idx = rest.substr(2).find("__");
|
||||||
|
if (rest_idx == std::string::npos)
|
||||||
|
return {};
|
||||||
|
fn_name = str.substr(0, rest_idx + 6);
|
||||||
|
rest = rest.substr(rest_idx + 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fn_name = fn_name_out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto result = demangle_template_args(fn_name_out, options);
|
||||||
|
if (!result)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
std::string args;
|
||||||
|
|
||||||
|
std::tie(name, args) = result.value();
|
||||||
|
fn_name = fmt::format("{}{}", name, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle old static function variables (GC CW)
|
||||||
|
size_t first_idx = fn_name.find('$');
|
||||||
|
if (first_idx != std::string::npos)
|
||||||
|
{
|
||||||
|
size_t second_idx = fn_name.substr(first_idx + 1).find('$');
|
||||||
|
if (second_idx == std::string::npos)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::string var = fn_name.substr(0, first_idx);
|
||||||
|
std::string restTemp = fn_name.substr(first_idx);
|
||||||
|
|
||||||
|
restTemp = restTemp.substr(1);
|
||||||
|
std::string var_type = restTemp.substr(0, second_idx);
|
||||||
|
restTemp = restTemp.substr(second_idx);
|
||||||
|
|
||||||
|
if (!var_type.starts_with("localstatic"))
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (var == "init")
|
||||||
|
{
|
||||||
|
// Sadly, $localstatic doesn't provide the variable name in guard/init
|
||||||
|
static_var = fmt::format("{} guard", var_type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static_var = var;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn_name = restTemp.substr(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
str = rest.substr(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string class_name = "";
|
||||||
|
if (!str.starts_with('F'))
|
||||||
|
{
|
||||||
|
auto result = demangle_qualified_name(str, options);
|
||||||
|
if (!result)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
std::string qualified_name;
|
||||||
|
std::string rest;
|
||||||
|
|
||||||
|
std::tie(name, qualified_name, rest) = result.value();
|
||||||
|
class_name = name;
|
||||||
|
qualified = qualified_name;
|
||||||
|
str = rest;
|
||||||
|
}
|
||||||
|
if (special)
|
||||||
|
{
|
||||||
|
auto result = demangle_special_function(fn_name, class_name, options);
|
||||||
|
if (!result)
|
||||||
|
return {};
|
||||||
|
fn_name = result.value();
|
||||||
|
}
|
||||||
|
if (str.starts_with('C'))
|
||||||
|
{
|
||||||
|
str = str.substr(1);
|
||||||
|
cnst = true;
|
||||||
|
}
|
||||||
|
if (str.starts_with('F'))
|
||||||
|
{
|
||||||
|
str = str.substr(1);
|
||||||
|
auto result = demangle_function_args(str, options);
|
||||||
|
if (!result)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::string args;
|
||||||
|
std::string rest;
|
||||||
|
|
||||||
|
std::tie(args, rest) = result.value();
|
||||||
|
if (options.omit_empty_parameters && args == "void")
|
||||||
|
{
|
||||||
|
fn_name = fmt::format("{}()", fn_name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fn_name = fmt::format("{}({})", fn_name, args);
|
||||||
|
}
|
||||||
|
str = rest;
|
||||||
|
}
|
||||||
|
if (str.starts_with('_'))
|
||||||
|
{
|
||||||
|
str = str.substr(1);
|
||||||
|
auto result = demangle_arg(str, options);
|
||||||
|
if (!result)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::string ret_pre;
|
||||||
|
std::string ret_post;
|
||||||
|
std::string rest;
|
||||||
|
|
||||||
|
std::tie(ret_pre, ret_post, rest) = result.value();
|
||||||
|
return_type_pre = ret_pre;
|
||||||
|
return_type_post = ret_post;
|
||||||
|
str = rest;
|
||||||
|
}
|
||||||
|
if (str != "")
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (cnst)
|
||||||
|
{
|
||||||
|
fn_name = fmt::format("{} const", fn_name);
|
||||||
|
}
|
||||||
|
if (qualified != "")
|
||||||
|
{
|
||||||
|
fn_name = fmt::format("{}::{}", qualified, fn_name);
|
||||||
|
}
|
||||||
|
if (return_type_pre != "")
|
||||||
|
{
|
||||||
|
fn_name = fmt::format("{} {}{}", return_type_pre, fn_name, return_type_post);
|
||||||
|
}
|
||||||
|
if (static_var != "")
|
||||||
|
{
|
||||||
|
fn_name = fmt::format("{}::{}", fn_name, static_var);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fn_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Finds the first double underscore in the string, excluding any that are part of a
|
||||||
|
/// template argument list or operator name.
|
||||||
|
std::optional<size_t> CWDemangler::find_split(std::string s, bool special,
|
||||||
|
DemangleOptions options)
|
||||||
|
{
|
||||||
|
size_t start = 0;
|
||||||
|
|
||||||
|
if (special && s.starts_with("op"))
|
||||||
|
{
|
||||||
|
auto result = demangle_arg(s.substr(2), options);
|
||||||
|
if (!result)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::string rest;
|
||||||
|
|
||||||
|
std::tie(std::ignore, std::ignore, rest) = result.value();
|
||||||
|
start = s.length() - rest.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
int depth = 0;
|
||||||
|
|
||||||
|
for (size_t i = start; i < s.length(); i++)
|
||||||
|
{
|
||||||
|
switch (s[i])
|
||||||
|
{
|
||||||
|
case '<':
|
||||||
|
depth++;
|
||||||
|
break;
|
||||||
|
case '>':
|
||||||
|
depth--;
|
||||||
|
break;
|
||||||
|
case '_':
|
||||||
|
if (s[i + 1] == '_' && depth == 0)
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
#include "Common/CommonTypes.h"
|
||||||
|
|
||||||
|
/// Options for [demangle].
|
||||||
|
struct DemangleOptions
|
||||||
|
{
|
||||||
|
/// Replace `(void)` function parameters with `()`
|
||||||
|
bool omit_empty_parameters;
|
||||||
|
/// Enable Metrowerks extension types (`__int128`, `__vec2x32float__`, etc.)
|
||||||
|
///
|
||||||
|
/// Disabled by default since they conflict with template argument literals
|
||||||
|
/// and can't always be demangled correctly.
|
||||||
|
bool mw_extensions;
|
||||||
|
|
||||||
|
DemangleOptions()
|
||||||
|
{
|
||||||
|
omit_empty_parameters = true;
|
||||||
|
mw_extensions = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DemangleOptions(bool omit_empty_parameters, bool mw_extensions)
|
||||||
|
{
|
||||||
|
this->omit_empty_parameters = omit_empty_parameters;
|
||||||
|
this->mw_extensions = mw_extensions;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CWDemangler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static std::optional<std::tuple<std::string, std::string>>
|
||||||
|
demangle_template_args(std::string str, DemangleOptions options);
|
||||||
|
static std::optional<std::tuple<std::string, std::string, std::string>>
|
||||||
|
demangle_name(std::string str, DemangleOptions options);
|
||||||
|
static std::optional<std::tuple<std::string, std::string, std::string>>
|
||||||
|
demangle_qualified_name(std::string str, DemangleOptions options);
|
||||||
|
static std::optional<std::tuple<std::string, std::string, std::string>>
|
||||||
|
demangle_arg(std::string str, DemangleOptions options);
|
||||||
|
static std::optional<std::tuple<std::string, std::string>>
|
||||||
|
demangle_function_args(std::string str, DemangleOptions options);
|
||||||
|
static std::optional<std::string>
|
||||||
|
demangle_special_function(std::string str, std::string class_name, DemangleOptions options);
|
||||||
|
static std::optional<std::string> demangle(std::string str, DemangleOptions options);
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline static bool IsAscii(std::string s)
|
||||||
|
{
|
||||||
|
for (char c : s)
|
||||||
|
{
|
||||||
|
if (static_cast<u8>(c) > 127)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static std::tuple<std::string, std::string, std::string> parse_qualifiers(std::string str);
|
||||||
|
static std::optional<std::tuple<int, std::string>> parse_digits(std::string str);
|
||||||
|
static std::optional<size_t> find_split(std::string s, bool special, DemangleOptions options);
|
||||||
|
};
|
|
@ -71,20 +71,22 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Text Include="$(BuildInfoTemplate)" />
|
<Text Include="$(BuildInfoTemplate)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<UsingTask TaskName="GetProductVersion"
|
<ItemGroup>
|
||||||
TaskFactory="CodeTaskFactory"
|
<ClInclude Include="Core\PowerPC\CWDemangler.h" />
|
||||||
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="Core\PowerPC\CWDemangler.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<UsingTask TaskName="GetProductVersion" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
|
||||||
<ParameterGroup>
|
<ParameterGroup>
|
||||||
<Path ParameterType="System.String" Required="true" />
|
<Path ParameterType="System.String" Required="true" />
|
||||||
<ProductVersion ParameterType="System.String" Output="true" />
|
<ProductVersion ParameterType="System.String" Output="true" />
|
||||||
</ParameterGroup>
|
</ParameterGroup>
|
||||||
<Task>
|
<Task>
|
||||||
<Using Namespace="System.Diagnostics"/>
|
<Using Namespace="System.Diagnostics" />
|
||||||
<Code Type="Fragment" Language="cs">
|
<Code Type="Fragment" Language="cs"><![CDATA[
|
||||||
<![CDATA[
|
|
||||||
ProductVersion = FileVersionInfo.GetVersionInfo(Path).ProductVersion;
|
ProductVersion = FileVersionInfo.GetVersionInfo(Path).ProductVersion;
|
||||||
]]>
|
]]></Code>
|
||||||
</Code>
|
|
||||||
</Task>
|
</Task>
|
||||||
</UsingTask>
|
</UsingTask>
|
||||||
<Target Name="WriteBuildInfo" AfterTargets="Build" Inputs="$(BuildInfoTemplate)" Outputs="$(BuildInfoOutput)">
|
<Target Name="WriteBuildInfo" AfterTargets="Build" Inputs="$(BuildInfoTemplate)" Outputs="$(BuildInfoOutput)">
|
||||||
|
@ -92,10 +94,6 @@
|
||||||
<Output PropertyName="VCToolsProductVersion" TaskParameter="ProductVersion" />
|
<Output PropertyName="VCToolsProductVersion" TaskParameter="ProductVersion" />
|
||||||
</GetProductVersion>
|
</GetProductVersion>
|
||||||
<Message Text="VCToolsProductVersion $(VCToolsProductVersion)" Importance="High" />
|
<Message Text="VCToolsProductVersion $(VCToolsProductVersion)" Importance="High" />
|
||||||
<WriteLinesToFile
|
<WriteLinesToFile File="$(BuildInfoOutput)" Lines="$([System.IO.File]::ReadAllText($(BuildInfoTemplate)).Replace('${VC_TOOLS_VERSION}', $(VCToolsProductVersion)))" Overwrite="true" />
|
||||||
File="$(BuildInfoOutput)"
|
|
||||||
Lines="$([System.IO.File]::ReadAllText($(BuildInfoTemplate)).Replace('${VC_TOOLS_VERSION}', $(VCToolsProductVersion)))"
|
|
||||||
Overwrite="true"
|
|
||||||
/>
|
|
||||||
</Target>
|
</Target>
|
||||||
</Project>
|
</Project>
|
|
@ -0,0 +1,443 @@
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
#include "Core/PowerPC/CWDemangler.h"
|
||||||
|
|
||||||
|
void DoDemangleTemplateArgsTest(std::string mangled, std::string name, std::string templateArgs)
|
||||||
|
{
|
||||||
|
DemangleOptions options = DemangleOptions();
|
||||||
|
|
||||||
|
auto result = CWDemangler::demangle_template_args(mangled, options);
|
||||||
|
std::optional<std::tuple<std::string, std::string>> expected = {{name, templateArgs}};
|
||||||
|
|
||||||
|
EXPECT_EQ(result, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoDemangleNameTest(std::string mangled, std::string name, std::string fullName)
|
||||||
|
{
|
||||||
|
DemangleOptions options = DemangleOptions();
|
||||||
|
|
||||||
|
auto result = CWDemangler::demangle_name(mangled, options);
|
||||||
|
std::optional<std::tuple<std::string, std::string, std::string>> expected = {
|
||||||
|
{name, fullName, ""}};
|
||||||
|
|
||||||
|
EXPECT_EQ(result, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoDemangleQualifiedNameTest(std::string mangled, std::string baseName, std::string fullName)
|
||||||
|
{
|
||||||
|
DemangleOptions options = DemangleOptions();
|
||||||
|
|
||||||
|
auto result = CWDemangler::demangle_qualified_name(mangled, options);
|
||||||
|
std::optional<std::tuple<std::string, std::string, std::string>> expected = {
|
||||||
|
{baseName, fullName, ""}};
|
||||||
|
|
||||||
|
EXPECT_EQ(result, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoDemangleArgTest(std::string mangled, std::string typePre, std::string typePost, std::string remainder)
|
||||||
|
{
|
||||||
|
DemangleOptions options = DemangleOptions();
|
||||||
|
|
||||||
|
auto result = CWDemangler::demangle_arg(mangled, options);
|
||||||
|
std::optional<std::tuple<std::string, std::string, std::string>> expected = {
|
||||||
|
{typePre, typePost, remainder}};
|
||||||
|
|
||||||
|
EXPECT_EQ(result, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoDemangleFunctionArgsTest(std::string mangled, std::string args, std::string remainder)
|
||||||
|
{
|
||||||
|
DemangleOptions options = DemangleOptions();
|
||||||
|
|
||||||
|
auto result = CWDemangler::demangle_function_args(mangled, options);
|
||||||
|
std::optional<std::tuple<std::string, std::string>> expected = {{args, remainder}};
|
||||||
|
|
||||||
|
EXPECT_EQ(result, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoDemangleTest(std::string mangled, std::string demangled)
|
||||||
|
{
|
||||||
|
DemangleOptions options = DemangleOptions();
|
||||||
|
|
||||||
|
auto result = CWDemangler::demangle(mangled, options);
|
||||||
|
std::optional<std::string> expected = {demangled};
|
||||||
|
if (demangled == "")
|
||||||
|
expected = std::nullopt;
|
||||||
|
|
||||||
|
EXPECT_EQ(result, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoDemangleOptionsTest(bool omitEmptyParams, bool mwExtensions, std::string mangled, std::string demangled)
|
||||||
|
{
|
||||||
|
DemangleOptions options = DemangleOptions(omitEmptyParams, mwExtensions);
|
||||||
|
|
||||||
|
auto result = CWDemangler::demangle(mangled, options);
|
||||||
|
std::optional<std::string> expected = {demangled};
|
||||||
|
|
||||||
|
EXPECT_EQ(result, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CWDemangler, TestDemangleTemplateArgs)
|
||||||
|
{
|
||||||
|
DoDemangleTemplateArgsTest("single_ptr<10CModelData>", "single_ptr", "<CModelData>");
|
||||||
|
DoDemangleTemplateArgsTest("basic_string<w,Q24rstl14char_traits<w>,Q24rstl17rmemory_allocator>",
|
||||||
|
"basic_string",
|
||||||
|
"<wchar_t, rstl::char_traits<wchar_t>, rstl::rmemory_allocator>");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CWDemangler, TestDemangleName)
|
||||||
|
{
|
||||||
|
DoDemangleNameTest("24single_ptr<10CModelData>", "single_ptr", "single_ptr<CModelData>");
|
||||||
|
DoDemangleNameTest("66basic_string<w,Q24rstl14char_traits<w>,Q24rstl17rmemory_allocator>",
|
||||||
|
"basic_string",
|
||||||
|
"basic_string<wchar_t, rstl::char_traits<wchar_t>, rstl::rmemory_allocator>");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CWDemangler, TestDemangleQualifiedName)
|
||||||
|
{
|
||||||
|
DoDemangleQualifiedNameTest("6CActor", "CActor", "CActor");
|
||||||
|
DoDemangleQualifiedNameTest("Q29CVector3f4EDim", "EDim", "CVector3f::EDim");
|
||||||
|
DoDemangleQualifiedNameTest(
|
||||||
|
"Q24rstl66basic_string<w,Q24rstl14char_traits<w>,Q24rstl17rmemory_allocator>", "basic_string",
|
||||||
|
"rstl::basic_string<wchar_t, rstl::char_traits<wchar_t>, rstl::rmemory_allocator>");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CWDemangler, TestDemangleArg)
|
||||||
|
{
|
||||||
|
DoDemangleArgTest("v", "void", "", "");
|
||||||
|
DoDemangleArgTest("b", "bool", "", "");
|
||||||
|
DoDemangleArgTest("RC9CVector3fUc", "const CVector3f&", "", "Uc");
|
||||||
|
DoDemangleArgTest("Q24rstl14char_traits<w>,", "rstl::char_traits<wchar_t>", "", ",");
|
||||||
|
DoDemangleArgTest("PFPCcPCc_v", "void (*", ")(const char*, const char*)", "");
|
||||||
|
DoDemangleArgTest("RCPCVPCVUi", "const volatile unsigned int* const volatile* const&", "", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CWDemangler, TestDemangleFunctionArgs)
|
||||||
|
{
|
||||||
|
DoDemangleFunctionArgsTest("v", "void", "");
|
||||||
|
DoDemangleFunctionArgsTest("b", "bool", "");
|
||||||
|
DoDemangleFunctionArgsTest("RC9CVector3fUc_x", "const CVector3f&, unsigned char", "_x");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CWDemangler, TestDemangle)
|
||||||
|
{
|
||||||
|
DoDemangleTest("__dt__6CActorFv", "CActor::~CActor()");
|
||||||
|
DoDemangleTest("GetSfxHandle__6CActorCFv", "CActor::GetSfxHandle() const");
|
||||||
|
DoDemangleTest(
|
||||||
|
"mNull__Q24rstl66basic_string<w,Q24rstl14char_traits<w>,Q24rstl17rmemory_allocator>",
|
||||||
|
"rstl::basic_string<wchar_t, rstl::char_traits<wchar_t>, "
|
||||||
|
"rstl::rmemory_allocator>::mNull");
|
||||||
|
DoDemangleTest(
|
||||||
|
"__ct__Q34rstl495red_black_tree<Ux,Q24rstl194pair<Ux,Q24rstl175auto_ptr<Q24rstl155map<s,"
|
||||||
|
"Q24rstl96auto_ptr<Q24rstl77list<Q24rstl35auto_ptr<23CGuiFrameMessageMapNode>,"
|
||||||
|
"Q24rstl17rmemory_allocator>>,Q24rstl7less<s>,Q24rstl17rmemory_allocator>>>,0,"
|
||||||
|
"Q24rstl215select1st<Q24rstl194pair<Ux,Q24rstl175auto_ptr<Q24rstl155map<s,Q24rstl96auto_"
|
||||||
|
"ptr<Q24rstl77list<Q24rstl35auto_ptr<23CGuiFrameMessageMapNode>,Q24rstl17rmemory_"
|
||||||
|
"allocator>>,Q24rstl7less<s>,Q24rstl17rmemory_allocator>>>>,Q24rstl8less<Ux>,"
|
||||||
|
"Q24rstl17rmemory_allocator>8iteratorFPQ34rstl495red_black_tree<Ux,Q24rstl194pair<Ux,"
|
||||||
|
"Q24rstl175auto_ptr<Q24rstl155map<s,Q24rstl96auto_ptr<Q24rstl77list<Q24rstl35auto_ptr<"
|
||||||
|
"23CGuiFrameMessageMapNode>,Q24rstl17rmemory_allocator>>,Q24rstl7less<s>,"
|
||||||
|
"Q24rstl17rmemory_allocator>>>,0,Q24rstl215select1st<Q24rstl194pair<Ux,Q24rstl175auto_"
|
||||||
|
"ptr<Q24rstl155map<s,Q24rstl96auto_ptr<Q24rstl77list<Q24rstl35auto_ptr<"
|
||||||
|
"23CGuiFrameMessageMapNode>,Q24rstl17rmemory_allocator>>,Q24rstl7less<s>,"
|
||||||
|
"Q24rstl17rmemory_allocator>>>>,Q24rstl8less<Ux>,Q24rstl17rmemory_allocator>"
|
||||||
|
"4nodePCQ34rstl495red_black_tree<Ux,Q24rstl194pair<Ux,Q24rstl175auto_ptr<Q24rstl155map<s,"
|
||||||
|
"Q24rstl96auto_ptr<Q24rstl77list<Q24rstl35auto_ptr<23CGuiFrameMessageMapNode>,"
|
||||||
|
"Q24rstl17rmemory_allocator>>,Q24rstl7less<s>,Q24rstl17rmemory_allocator>>>,0,"
|
||||||
|
"Q24rstl215select1st<Q24rstl194pair<Ux,Q24rstl175auto_ptr<Q24rstl155map<s,Q24rstl96auto_"
|
||||||
|
"ptr<Q24rstl77list<Q24rstl35auto_ptr<23CGuiFrameMessageMapNode>,Q24rstl17rmemory_"
|
||||||
|
"allocator>>,Q24rstl7less<s>,Q24rstl17rmemory_allocator>>>>,Q24rstl8less<Ux>,"
|
||||||
|
"Q24rstl17rmemory_allocator>6header",
|
||||||
|
"rstl::red_black_tree<unsigned long long, rstl::pair<unsigned long long, "
|
||||||
|
"rstl::auto_ptr<rstl::map<short, "
|
||||||
|
"rstl::auto_ptr<rstl::list<rstl::auto_ptr<CGuiFrameMessageMapNode>, "
|
||||||
|
"rstl::rmemory_allocator>>, rstl::less<short>, rstl::rmemory_allocator>>>, 0, "
|
||||||
|
"rstl::select1st<rstl::pair<unsigned long long, rstl::auto_ptr<rstl::map<short, "
|
||||||
|
"rstl::auto_ptr<rstl::list<rstl::auto_ptr<CGuiFrameMessageMapNode>, "
|
||||||
|
"rstl::rmemory_allocator>>, rstl::less<short>, rstl::rmemory_allocator>>>>, "
|
||||||
|
"rstl::less<unsigned long long>, "
|
||||||
|
"rstl::rmemory_allocator>::iterator::iterator(rstl::red_black_tree<unsigned long long, "
|
||||||
|
"rstl::pair<unsigned long long, rstl::auto_ptr<rstl::map<short, "
|
||||||
|
"rstl::auto_ptr<rstl::list<rstl::auto_ptr<CGuiFrameMessageMapNode>, "
|
||||||
|
"rstl::rmemory_allocator>>, rstl::less<short>, rstl::rmemory_allocator>>>, 0, "
|
||||||
|
"rstl::select1st<rstl::pair<unsigned long long, rstl::auto_ptr<rstl::map<short, "
|
||||||
|
"rstl::auto_ptr<rstl::list<rstl::auto_ptr<CGuiFrameMessageMapNode>, "
|
||||||
|
"rstl::rmemory_allocator>>, rstl::less<short>, rstl::rmemory_allocator>>>>, "
|
||||||
|
"rstl::less<unsigned long long>, rstl::rmemory_allocator>::node*, const "
|
||||||
|
"rstl::red_black_tree<unsigned long long, rstl::pair<unsigned long long, "
|
||||||
|
"rstl::auto_ptr<rstl::map<short, "
|
||||||
|
"rstl::auto_ptr<rstl::list<rstl::auto_ptr<CGuiFrameMessageMapNode>, "
|
||||||
|
"rstl::rmemory_allocator>>, rstl::less<short>, rstl::rmemory_allocator>>>, 0, "
|
||||||
|
"rstl::select1st<rstl::pair<unsigned long long, rstl::auto_ptr<rstl::map<short, "
|
||||||
|
"rstl::auto_ptr<rstl::list<rstl::auto_ptr<CGuiFrameMessageMapNode>, "
|
||||||
|
"rstl::rmemory_allocator>>, rstl::less<short>, rstl::rmemory_allocator>>>>, "
|
||||||
|
"rstl::less<unsigned long long>, rstl::rmemory_allocator>::header*)");
|
||||||
|
DoDemangleTest(
|
||||||
|
"for_each<PP12MultiEmitter,Q23std51binder2nd<Q23std30mem_fun1_t<v,12MultiEmitter,l>,"
|
||||||
|
"l>>__3stdFPP12MultiEmitterPP12MultiEmitterQ23std51binder2nd<Q23std30mem_fun1_t<v,"
|
||||||
|
"12MultiEmitter,l>,l>_Q23std51binder2nd<Q23std30mem_fun1_t<v,12MultiEmitter,l>,l>",
|
||||||
|
"std::binder2nd<std::mem_fun1_t<void, MultiEmitter, long>, long> "
|
||||||
|
"std::for_each<MultiEmitter**, std::binder2nd<std::mem_fun1_t<void, MultiEmitter, "
|
||||||
|
"long>, long>>(MultiEmitter**, MultiEmitter**, std::binder2nd<std::mem_fun1_t<void, "
|
||||||
|
"MultiEmitter, long>, long>)");
|
||||||
|
DoDemangleTest(
|
||||||
|
"__ct__Q43std3tr16detail383function_imp<PFPCcPCc_v,Q43std3tr16detail334bound_func<v,"
|
||||||
|
"Q43std3tr16detail59mem_fn_2<v,Q53scn4step7gimmick9shipevent9ShipEvent,PCc,PCc>,"
|
||||||
|
"Q33std3tr1228tuple<PQ53scn4step7gimmick9shipevent9ShipEvent,"
|
||||||
|
"Q53std3tr112placeholders6detail5ph<1>,Q53std3tr112placeholders6detail5ph<2>,"
|
||||||
|
"Q33std3tr13nat,Q33std3tr13nat,Q33std3tr13nat,Q33std3tr13nat,Q33std3tr13nat,"
|
||||||
|
"Q33std3tr13nat,Q33std3tr13nat>>,0,1>FRCQ43std3tr16detail383function_imp<PFPCcPCc_v,"
|
||||||
|
"Q43std3tr16detail334bound_func<v,Q43std3tr16detail59mem_fn_2<v,"
|
||||||
|
"Q53scn4step7gimmick9shipevent9ShipEvent,PCc,PCc>,Q33std3tr1228tuple<"
|
||||||
|
"PQ53scn4step7gimmick9shipevent9ShipEvent,Q53std3tr112placeholders6detail5ph<1>,"
|
||||||
|
"Q53std3tr112placeholders6detail5ph<2>,Q33std3tr13nat,Q33std3tr13nat,Q33std3tr13nat,"
|
||||||
|
"Q33std3tr13nat,Q33std3tr13nat,Q33std3tr13nat,Q33std3tr13nat>>,0,1>",
|
||||||
|
"std::tr1::detail::function_imp<void (*)(const char*, const char*), "
|
||||||
|
"std::tr1::detail::bound_func<void, std::tr1::detail::mem_fn_2<void, "
|
||||||
|
"scn::step::gimmick::shipevent::ShipEvent, const char*, const char*>, "
|
||||||
|
"std::tr1::tuple<scn::step::gimmick::shipevent::ShipEvent*, "
|
||||||
|
"std::tr1::placeholders::detail::ph<1>, std::tr1::placeholders::detail::ph<2>, "
|
||||||
|
"std::tr1::nat, std::tr1::nat, std::tr1::nat, std::tr1::nat, std::tr1::nat, "
|
||||||
|
"std::tr1::nat, std::tr1::nat>>, 0, 1>::function_imp(const "
|
||||||
|
"std::tr1::detail::function_imp<void (*)(const char*, const char*), "
|
||||||
|
"std::tr1::detail::bound_func<void, std::tr1::detail::mem_fn_2<void, "
|
||||||
|
"scn::step::gimmick::shipevent::ShipEvent, const char*, const char*>, "
|
||||||
|
"std::tr1::tuple<scn::step::gimmick::shipevent::ShipEvent*, "
|
||||||
|
"std::tr1::placeholders::detail::ph<1>, std::tr1::placeholders::detail::ph<2>, "
|
||||||
|
"std::tr1::nat, std::tr1::nat, std::tr1::nat, std::tr1::nat, std::tr1::nat, "
|
||||||
|
"std::tr1::nat, std::tr1::nat>>, 0, 1>&)");
|
||||||
|
DoDemangleTest(
|
||||||
|
"createJointController<11IKJointCtrl>__"
|
||||||
|
"2MRFP11IKJointCtrlPC9LiveActorUsM11IKJointCtrlFPCvPvPQ29JGeometry64TPosition3<"
|
||||||
|
"Q29JGeometry38TMatrix34<Q29JGeometry13SMatrix34C<f>>>RC19JointControllerInfo_"
|
||||||
|
"bM11IKJointCtrlFPCvPvPQ29JGeometry64TPosition3<Q29JGeometry38TMatrix34<"
|
||||||
|
"Q29JGeometry13SMatrix34C<f>>>RC19JointControllerInfo_b_P15JointController",
|
||||||
|
"JointController* MR::createJointController<IKJointCtrl>(IKJointCtrl*, const "
|
||||||
|
"LiveActor*, unsigned short, bool "
|
||||||
|
"(IKJointCtrl::*)(JGeometry::TPosition3<JGeometry::TMatrix34<JGeometry::SMatrix34C<"
|
||||||
|
"float>>>*, const JointControllerInfo&), bool "
|
||||||
|
"(IKJointCtrl::*)(JGeometry::TPosition3<JGeometry::TMatrix34<JGeometry::SMatrix34C<"
|
||||||
|
"float>>>*, const JointControllerInfo&))");
|
||||||
|
DoDemangleTest("execCommand__12JASSeqParserFP8JASTrackM12JASSeqParserFPCvPvP8JASTrackPUl_lUlPUl",
|
||||||
|
"JASSeqParser::execCommand(JASTrack*, long (JASSeqParser::*)(JASTrack*, unsigned "
|
||||||
|
"long*), unsigned long, unsigned long*)");
|
||||||
|
DoDemangleTest("AddWidgetFnMap__"
|
||||||
|
"10CGuiWidgetFiM10CGuiWidgetFPCvPvP15CGuiFunctionDefP18CGuiControllerInfo_i",
|
||||||
|
"CGuiWidget::AddWidgetFnMap(int, int (CGuiWidget::*)(CGuiFunctionDef*, "
|
||||||
|
"CGuiControllerInfo*))");
|
||||||
|
DoDemangleTest("BareFn__FPFPCcPv_v_v", "void BareFn(void (*)(const char*, void*))");
|
||||||
|
DoDemangleTest("BareFn__FPFPCcPv_v_PFPCvPv_v",
|
||||||
|
"void (* BareFn(void (*)(const char*, void*)))(const void*, void*)");
|
||||||
|
DoDemangleTest(
|
||||||
|
"SomeFn__FRCPFPFPCvPv_v_RCPFPCvPv_v",
|
||||||
|
"SomeFn(void (*const& (*const&)(void (*)(const void*, void*)))(const void*, void*))");
|
||||||
|
DoDemangleTest(
|
||||||
|
"SomeFn__Q29Namespace5ClassCFRCMQ29Namespace5ClassFPCvPCvMQ29Namespace5ClassFPCvPCvPCvPv_"
|
||||||
|
"v_RCMQ29Namespace5ClassFPCvPCvPCvPv_v",
|
||||||
|
"Namespace::Class::SomeFn(void (Namespace::Class::*const & (Namespace::Class::*const "
|
||||||
|
"&)(void (Namespace::Class::*)(const void*, void*) const) const)(const void*, void*) "
|
||||||
|
"const) const");
|
||||||
|
DoDemangleTest("__pl__FRC9CRelAngleRC9CRelAngle",
|
||||||
|
"operator+(const CRelAngle&, const CRelAngle&)");
|
||||||
|
DoDemangleTest("destroy<PUi>__4rstlFPUiPUi",
|
||||||
|
"rstl::destroy<unsigned int*>(unsigned int*, unsigned int*)");
|
||||||
|
DoDemangleTest("__opb__33TFunctor2<CP15CGuiSliderGroup,Cf>CFv",
|
||||||
|
"TFunctor2<CGuiSliderGroup* const, const float>::operator bool() const");
|
||||||
|
DoDemangleTest("__opRC25TToken<15CCharLayoutInfo>__31TLockedToken<15CCharLayoutInfo>CFv",
|
||||||
|
"TLockedToken<CCharLayoutInfo>::operator const TToken<CCharLayoutInfo>&() const");
|
||||||
|
DoDemangleTest(
|
||||||
|
"uninitialized_copy<Q24rstl198pointer_iterator<"
|
||||||
|
"Q224CSpawnSystemKeyframeData24CSpawnSystemKeyframeInfo,Q24rstl89vector<"
|
||||||
|
"Q224CSpawnSystemKeyframeData24CSpawnSystemKeyframeInfo,Q24rstl17rmemory_allocator>,"
|
||||||
|
"Q24rstl17rmemory_allocator>,PQ224CSpawnSystemKeyframeData24CSpawnSystemKeyframeInfo>__"
|
||||||
|
"4rstlFQ24rstl198pointer_iterator<Q224CSpawnSystemKeyframeData24CSpawnSystemKeyframeInfo,"
|
||||||
|
"Q24rstl89vector<Q224CSpawnSystemKeyframeData24CSpawnSystemKeyframeInfo,Q24rstl17rmemory_"
|
||||||
|
"allocator>,Q24rstl17rmemory_allocator>Q24rstl198pointer_iterator<"
|
||||||
|
"Q224CSpawnSystemKeyframeData24CSpawnSystemKeyframeInfo,Q24rstl89vector<"
|
||||||
|
"Q224CSpawnSystemKeyframeData24CSpawnSystemKeyframeInfo,Q24rstl17rmemory_allocator>,"
|
||||||
|
"Q24rstl17rmemory_allocator>PQ224CSpawnSystemKeyframeData24CSpawnSystemKeyframeInfo",
|
||||||
|
"rstl::uninitialized_copy<rstl::pointer_iterator<CSpawnSystemKeyframeData::"
|
||||||
|
"CSpawnSystemKeyframeInfo, "
|
||||||
|
"rstl::vector<CSpawnSystemKeyframeData::CSpawnSystemKeyframeInfo, "
|
||||||
|
"rstl::rmemory_allocator>, rstl::rmemory_allocator>, "
|
||||||
|
"CSpawnSystemKeyframeData::CSpawnSystemKeyframeInfo*>(rstl::pointer_iterator<"
|
||||||
|
"CSpawnSystemKeyframeData::CSpawnSystemKeyframeInfo, "
|
||||||
|
"rstl::vector<CSpawnSystemKeyframeData::CSpawnSystemKeyframeInfo, "
|
||||||
|
"rstl::rmemory_allocator>, rstl::rmemory_allocator>, "
|
||||||
|
"rstl::pointer_iterator<CSpawnSystemKeyframeData::CSpawnSystemKeyframeInfo, "
|
||||||
|
"rstl::vector<CSpawnSystemKeyframeData::CSpawnSystemKeyframeInfo, "
|
||||||
|
"rstl::rmemory_allocator>, rstl::rmemory_allocator>, "
|
||||||
|
"CSpawnSystemKeyframeData::CSpawnSystemKeyframeInfo*)");
|
||||||
|
DoDemangleTest(
|
||||||
|
"__rf__Q34rstl120list<Q24rstl78pair<i,PFRC10SObjectTagR12CInputStreamRC15CVParamTransfer_"
|
||||||
|
"C16CFactoryFnReturn>,Q24rstl17rmemory_allocator>14const_iteratorCFv",
|
||||||
|
"rstl::list<rstl::pair<int, const CFactoryFnReturn (*)(const SObjectTag&, CInputStream&, "
|
||||||
|
"const CVParamTransfer&)>, rstl::rmemory_allocator>::const_iterator::operator->() const");
|
||||||
|
DoDemangleTest(
|
||||||
|
"ApplyRipples__FRC14CRippleManagerRA43_A43_Q220CFluidPlaneCPURender13SHFieldSampleRA22_"
|
||||||
|
"A22_UcRA256_CfRQ220CFluidPlaneCPURender10SPatchInfo",
|
||||||
|
"ApplyRipples(const CRippleManager&, CFluidPlaneCPURender::SHFieldSample(&)[43][43], "
|
||||||
|
"unsigned char(&)[22][22], const float(&)[256], CFluidPlaneCPURender::SPatchInfo&)");
|
||||||
|
DoDemangleTest("CalculateFluidTextureOffset__14CFluidUVMotionCFfPA2_f",
|
||||||
|
"CFluidUVMotion::CalculateFluidTextureOffset(float, float(*)[2]) const");
|
||||||
|
DoDemangleTest(
|
||||||
|
"RenderNormals__FRA43_A43_CQ220CFluidPlaneCPURender13SHFieldSampleRA22_A22_"
|
||||||
|
"CUcRCQ220CFluidPlaneCPURender10SPatchInfo",
|
||||||
|
"RenderNormals(const CFluidPlaneCPURender::SHFieldSample(&)[43][43], const unsigned "
|
||||||
|
"char(&)[22][22], const CFluidPlaneCPURender::SPatchInfo&)");
|
||||||
|
DoDemangleTest("Matrix__FfPA2_A3_f", "Matrix(float, float(*)[2][3])");
|
||||||
|
DoDemangleTest("__ct<12CStringTable>__31CObjOwnerDerivedFromIObjUntypedFRCQ24rstl24auto_ptr<"
|
||||||
|
"12CStringTable>",
|
||||||
|
"CObjOwnerDerivedFromIObjUntyped::CObjOwnerDerivedFromIObjUntyped<CStringTable>("
|
||||||
|
"const rstl::auto_ptr<CStringTable>&)");
|
||||||
|
DoDemangleTest("__vt__40TObjOwnerDerivedFromIObj<12CStringTable>",
|
||||||
|
"TObjOwnerDerivedFromIObj<CStringTable>::__vtable");
|
||||||
|
DoDemangleTest("__RTTI__40TObjOwnerDerivedFromIObj<12CStringTable>",
|
||||||
|
"TObjOwnerDerivedFromIObj<CStringTable>::__RTTI");
|
||||||
|
DoDemangleTest("__init__mNull__Q24rstl66basic_string<c,Q24rstl14char_traits<c>,Q24rstl17rmemory_"
|
||||||
|
"allocator>",
|
||||||
|
"rstl::basic_string<char, rstl::char_traits<char>, "
|
||||||
|
"rstl::rmemory_allocator>::__init__mNull");
|
||||||
|
DoDemangleTest("__dt__26__partial_array_destructorFv",
|
||||||
|
"__partial_array_destructor::~__partial_array_destructor()");
|
||||||
|
DoDemangleTest(
|
||||||
|
"__distance<Q34rstl195red_black_tree<13TGameScriptId,Q24rstl32pair<13TGameScriptId,"
|
||||||
|
"9TUniqueId>,1,Q24rstl52select1st<Q24rstl32pair<13TGameScriptId,9TUniqueId>>,"
|
||||||
|
"Q24rstl21less<13TGameScriptId>,Q24rstl17rmemory_allocator>14const_iterator>__"
|
||||||
|
"4rstlFQ34rstl195red_black_tree<13TGameScriptId,Q24rstl32pair<13TGameScriptId,9TUniqueId>"
|
||||||
|
",1,Q24rstl52select1st<Q24rstl32pair<13TGameScriptId,9TUniqueId>>,Q24rstl21less<"
|
||||||
|
"13TGameScriptId>,Q24rstl17rmemory_allocator>14const_iteratorQ34rstl195red_black_tree<"
|
||||||
|
"13TGameScriptId,Q24rstl32pair<13TGameScriptId,9TUniqueId>,1,Q24rstl52select1st<"
|
||||||
|
"Q24rstl32pair<13TGameScriptId,9TUniqueId>>,Q24rstl21less<13TGameScriptId>,"
|
||||||
|
"Q24rstl17rmemory_allocator>14const_iteratorQ24rstl20forward_iterator_tag",
|
||||||
|
"rstl::__distance<rstl::red_black_tree<TGameScriptId, rstl::pair<TGameScriptId, "
|
||||||
|
"TUniqueId>, 1, rstl::select1st<rstl::pair<TGameScriptId, TUniqueId>>, "
|
||||||
|
"rstl::less<TGameScriptId>, "
|
||||||
|
"rstl::rmemory_allocator>::const_iterator>(rstl::red_black_tree<TGameScriptId, "
|
||||||
|
"rstl::pair<TGameScriptId, TUniqueId>, 1, rstl::select1st<rstl::pair<TGameScriptId, "
|
||||||
|
"TUniqueId>>, rstl::less<TGameScriptId>, rstl::rmemory_allocator>::const_iterator, "
|
||||||
|
"rstl::red_black_tree<TGameScriptId, rstl::pair<TGameScriptId, TUniqueId>, 1, "
|
||||||
|
"rstl::select1st<rstl::pair<TGameScriptId, TUniqueId>>, rstl::less<TGameScriptId>, "
|
||||||
|
"rstl::rmemory_allocator>::const_iterator, rstl::forward_iterator_tag)");
|
||||||
|
DoDemangleTest(
|
||||||
|
"__ct__Q210Metrowerks683compressed_pair<RQ23std301allocator<Q33std276__tree_deleter<"
|
||||||
|
"Q23std34pair<Ci,Q212petfurniture8Instance>,Q33std131__multimap_do_transform<i,"
|
||||||
|
"Q212petfurniture8Instance,Q23std7less<i>,Q23std53allocator<Q23std34pair<Ci,"
|
||||||
|
"Q212petfurniture8Instance>>,0>13value_compare,Q23std53allocator<Q23std34pair<Ci,"
|
||||||
|
"Q212petfurniture8Instance>>>4node>,Q210Metrowerks337compressed_pair<"
|
||||||
|
"Q210Metrowerks12number<Ul,1>,PQ33std276__tree_deleter<Q23std34pair<Ci,"
|
||||||
|
"Q212petfurniture8Instance>,Q33std131__multimap_do_transform<i,Q212petfurniture8Instance,"
|
||||||
|
"Q23std7less<i>,Q23std53allocator<Q23std34pair<Ci,Q212petfurniture8Instance>>,0>13value_"
|
||||||
|
"compare,Q23std53allocator<Q23std34pair<Ci,Q212petfurniture8Instance>>>4node>>"
|
||||||
|
"FRQ23std301allocator<Q33std276__tree_deleter<Q23std34pair<Ci,Q212petfurniture8Instance>,"
|
||||||
|
"Q33std131__multimap_do_transform<i,Q212petfurniture8Instance,Q23std7less<i>,"
|
||||||
|
"Q23std53allocator<Q23std34pair<Ci,Q212petfurniture8Instance>>,0>13value_compare,"
|
||||||
|
"Q23std53allocator<Q23std34pair<Ci,Q212petfurniture8Instance>>>4node>"
|
||||||
|
"Q210Metrowerks337compressed_pair<Q210Metrowerks12number<Ul,1>,PQ33std276__tree_deleter<"
|
||||||
|
"Q23std34pair<Ci,Q212petfurniture8Instance>,Q33std131__multimap_do_transform<i,"
|
||||||
|
"Q212petfurniture8Instance,Q23std7less<i>,Q23std53allocator<Q23std34pair<Ci,"
|
||||||
|
"Q212petfurniture8Instance>>,0>13value_compare,Q23std53allocator<Q23std34pair<Ci,"
|
||||||
|
"Q212petfurniture8Instance>>>4node>",
|
||||||
|
"Metrowerks::compressed_pair<std::allocator<std::__tree_deleter<std::pair<const int, "
|
||||||
|
"petfurniture::Instance>, std::__multimap_do_transform<int, petfurniture::Instance, "
|
||||||
|
"std::less<int>, std::allocator<std::pair<const int, petfurniture::Instance>>, "
|
||||||
|
"0>::value_compare, std::allocator<std::pair<const int, "
|
||||||
|
"petfurniture::Instance>>>::node>&, "
|
||||||
|
"Metrowerks::compressed_pair<Metrowerks::number<unsigned long, 1>, "
|
||||||
|
"std::__tree_deleter<std::pair<const int, petfurniture::Instance>, "
|
||||||
|
"std::__multimap_do_transform<int, petfurniture::Instance, std::less<int>, "
|
||||||
|
"std::allocator<std::pair<const int, petfurniture::Instance>>, 0>::value_compare, "
|
||||||
|
"std::allocator<std::pair<const int, "
|
||||||
|
"petfurniture::Instance>>>::node*>>::compressed_pair(std::allocator<std::__tree_deleter<"
|
||||||
|
"std::pair<const int, petfurniture::Instance>, std::__multimap_do_transform<int, "
|
||||||
|
"petfurniture::Instance, std::less<int>, std::allocator<std::pair<const int, "
|
||||||
|
"petfurniture::Instance>>, 0>::value_compare, std::allocator<std::pair<const int, "
|
||||||
|
"petfurniture::Instance>>>::node>&, "
|
||||||
|
"Metrowerks::compressed_pair<Metrowerks::number<unsigned long, 1>, "
|
||||||
|
"std::__tree_deleter<std::pair<const int, petfurniture::Instance>, "
|
||||||
|
"std::__multimap_do_transform<int, petfurniture::Instance, std::less<int>, "
|
||||||
|
"std::allocator<std::pair<const int, petfurniture::Instance>>, 0>::value_compare, "
|
||||||
|
"std::allocator<std::pair<const int, petfurniture::Instance>>>::node*>)");
|
||||||
|
DoDemangleTest(
|
||||||
|
"skBadString$localstatic3$GetNameByToken__31TTokenSet<18EScriptObjectState>"
|
||||||
|
"CF18EScriptObjectState",
|
||||||
|
"TTokenSet<EScriptObjectState>::GetNameByToken(EScriptObjectState) const::skBadString");
|
||||||
|
DoDemangleTest("init$localstatic4$GetNameByToken__31TTokenSet<18EScriptObjectState>"
|
||||||
|
"CF18EScriptObjectState",
|
||||||
|
"TTokenSet<EScriptObjectState>::GetNameByToken(EScriptObjectState) "
|
||||||
|
"const::localstatic4 guard");
|
||||||
|
DoDemangleTest("@LOCAL@GetAnmPlayPolicy__Q24nw4r3g3dFQ34nw4r3g3d9AnmPolicy@policyTable",
|
||||||
|
"nw4r::g3d::GetAnmPlayPolicy(nw4r::g3d::AnmPolicy)::policyTable");
|
||||||
|
DoDemangleTest("@GUARD@GetAnmPlayPolicy__Q24nw4r3g3dFQ34nw4r3g3d9AnmPolicy@policyTable",
|
||||||
|
"nw4r::g3d::GetAnmPlayPolicy(nw4r::g3d::AnmPolicy)::policyTable guard");
|
||||||
|
DoDemangleTest(
|
||||||
|
"lower_bound<Q24rstl180const_pointer_iterator<Q24rstl33pair<Ui,22CAdditiveAnimationInfo>,"
|
||||||
|
"Q24rstl77vector<Q24rstl33pair<Ui,22CAdditiveAnimationInfo>,Q24rstl17rmemory_allocator>,"
|
||||||
|
"Q24rstl17rmemory_allocator>,Ui,Q24rstl79pair_sorter_finder<Q24rstl33pair<Ui,"
|
||||||
|
"22CAdditiveAnimationInfo>,Q24rstl8less<Ui>>>__4rstlFQ24rstl180const_pointer_iterator<"
|
||||||
|
"Q24rstl33pair<Ui,22CAdditiveAnimationInfo>,Q24rstl77vector<Q24rstl33pair<Ui,"
|
||||||
|
"22CAdditiveAnimationInfo>,Q24rstl17rmemory_allocator>,Q24rstl17rmemory_allocator>"
|
||||||
|
"Q24rstl180const_p",
|
||||||
|
"");
|
||||||
|
DoDemangleTest("test__FRCPCPCi", "test(const int* const* const&)");
|
||||||
|
DoDemangleTest("__ct__Q34nw4r2ut14CharStrmReaderFMQ34nw4r2ut14CharStrmReaderFPCvPv_Us",
|
||||||
|
"nw4r::ut::CharStrmReader::CharStrmReader(unsigned short "
|
||||||
|
"(nw4r::ut::CharStrmReader::*)())");
|
||||||
|
DoDemangleTest("QuerySymbolToMapFile___Q24nw4r2dbFPUcPC12OSModuleInfoUlPUcUl",
|
||||||
|
"nw4r::db::QuerySymbolToMapFile_(unsigned char*, const OSModuleInfo*, unsigned "
|
||||||
|
"long, unsigned char*, unsigned long)");
|
||||||
|
DoDemangleTest("__ct__Q37JGadget27TLinkList<10JUTConsole,-24>"
|
||||||
|
"8iteratorFQ37JGadget13TNodeLinkList8iterator",
|
||||||
|
"JGadget::TLinkList<JUTConsole, "
|
||||||
|
"-24>::iterator::iterator(JGadget::TNodeLinkList::iterator)");
|
||||||
|
DoDemangleTest(
|
||||||
|
"do_assign<Q23std126__convert_iterator<PP16GAM_eEngineState,Q33std68__cdeque<P16GAM_"
|
||||||
|
"eEngineState,36ubiSTLAllocator<P16GAM_eEngineState>>8iterator>>__Q23std36__cdeque<PCv,"
|
||||||
|
"20ubiSTLAllocator<PCv>>FQ23std126__convert_iterator<PP16GAM_eEngineState,Q33std68__"
|
||||||
|
"cdeque<P16GAM_eEngineState,36ubiSTLAllocator<P16GAM_eEngineState>>8iterator>Q23std126__"
|
||||||
|
"convert_iterator<PP16GAM_eEngineState,Q33std68__cdeque<P16GAM_eEngineState,"
|
||||||
|
"36ubiSTLAllocator<P16GAM_eEngineState>>8iterator>Q23std20forward_iterator_tag",
|
||||||
|
"std::__cdeque<const void*, ubiSTLAllocator<const "
|
||||||
|
"void*>>::do_assign<std::__convert_iterator<GAM_eEngineState**, "
|
||||||
|
"std::__cdeque<GAM_eEngineState*, "
|
||||||
|
"ubiSTLAllocator<GAM_eEngineState*>>::iterator>>(std::__convert_iterator<GAM_"
|
||||||
|
"eEngineState**, std::__cdeque<GAM_eEngineState*, "
|
||||||
|
"ubiSTLAllocator<GAM_eEngineState*>>::iterator>, "
|
||||||
|
"std::__convert_iterator<GAM_eEngineState**, std::__cdeque<GAM_eEngineState*, "
|
||||||
|
"ubiSTLAllocator<GAM_eEngineState*>>::iterator>, std::forward_iterator_tag)");
|
||||||
|
DoDemangleTest(
|
||||||
|
"__opPCQ23std15__locale_imp<1>__Q23std80_RefCountedPtr<Q23std15__locale_imp<1>,"
|
||||||
|
"Q23std32_Single<Q23std15__locale_imp<1>>>CFv",
|
||||||
|
"std::_RefCountedPtr<std::__locale_imp<1>, "
|
||||||
|
"std::_Single<std::__locale_imp<1>>>::operator const std::__locale_imp<1>*() const");
|
||||||
|
DoDemangleTest("__partition_const_ref<PP12CSpaceObject,Q23std74unary_negate<Q23std52__binder1st_"
|
||||||
|
"const_ref<Q23std21less<P12CSpaceObject>>>>__"
|
||||||
|
"3stdFPP12CSpaceObjectPP12CSpaceObjectRCQ23std74unary_negate<Q23std52__binder1st_"
|
||||||
|
"const_ref<Q23std21less<P12CSpaceObject>>>",
|
||||||
|
"std::__partition_const_ref<CSpaceObject**, "
|
||||||
|
"std::unary_negate<std::__binder1st_const_ref<std::less<CSpaceObject*>>>>("
|
||||||
|
"CSpaceObject**, CSpaceObject**, const "
|
||||||
|
"std::unary_negate<std::__binder1st_const_ref<std::less<CSpaceObject*>>>&)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CWDemangler, TestDemangleOptions)
|
||||||
|
{
|
||||||
|
DoDemangleOptionsTest(true, false, "__dt__26__partial_array_destructorFv",
|
||||||
|
"__partial_array_destructor::~__partial_array_destructor()");
|
||||||
|
DoDemangleOptionsTest(false, false, "__dt__26__partial_array_destructorFv",
|
||||||
|
"__partial_array_destructor::~__partial_array_destructor(void)");
|
||||||
|
DoDemangleOptionsTest(true, true,
|
||||||
|
"__opPCQ23std15__locale_imp<1>__Q23std80_RefCountedPtr<Q23std15__locale_"
|
||||||
|
"imp<1>,Q23std32_Single<Q23std15__locale_imp<1>>>CFv",
|
||||||
|
"std::_RefCountedPtr<std::__locale_imp<__int128>, "
|
||||||
|
"std::_Single<std::__locale_imp<__int128>>>::operator const "
|
||||||
|
"std::__locale_imp<__int128>*() const");
|
||||||
|
DoDemangleOptionsTest(true, true, "fn<3,PV2>__FPC2",
|
||||||
|
"fn<3, volatile __vec2x32float__*>(const __vec2x32float__*)");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,7 @@
|
||||||
<ClCompile Include="Core\MMIOTest.cpp" />
|
<ClCompile Include="Core\MMIOTest.cpp" />
|
||||||
<ClCompile Include="Core\PageFaultTest.cpp" />
|
<ClCompile Include="Core\PageFaultTest.cpp" />
|
||||||
<ClCompile Include="Core\PatchAllowlistTest.cpp" />
|
<ClCompile Include="Core\PatchAllowlistTest.cpp" />
|
||||||
|
<ClCompile Include="Core\PowerPC\CWDemanglerTest.cpp" />
|
||||||
<ClCompile Include="Core\PowerPC\DivUtilsTest.cpp" />
|
<ClCompile Include="Core\PowerPC\DivUtilsTest.cpp" />
|
||||||
<ClCompile Include="VideoCommon\VertexLoaderTest.cpp" />
|
<ClCompile Include="VideoCommon\VertexLoaderTest.cpp" />
|
||||||
<ClCompile Include="StubHost.cpp" />
|
<ClCompile Include="StubHost.cpp" />
|
||||||
|
|
Loading…
Reference in New Issue