Demangle.cxx
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <cstring>
00012 #include <cstdlib>
00013
00014 #include "Demangle.hxx"
00015
00016 #if defined(__GNUC__)
00017 #include <cxxabi.h>
00018 #elif defined(__SUNPRO_CC)
00019 #include <demangle.h>
00020 #endif
00021
00022 namespace {
00023
00024 bool isalphanum(int i) {
00025 return isalpha(i) || isdigit(i);
00026 }
00027
00028
00029 std::string NormalizeName( const char * nam ) {
00030 std::string norm_name;
00031 char prev = 0;
00032 for (size_t i = 0; nam[i] != 0; i++) {
00033 char curr = nam[i];
00034 if (curr == ' ') {
00035 char next = 0;
00036 while (nam[i] != 0 && (next = nam[i + 1]) == ' ') {
00037 ++i;
00038 }
00039 if (!isalphanum(prev) || !isalpha(next)) {
00040 continue;
00041 }
00042 } else if ((curr == '>' && prev == '>')
00043 || (curr == '(' && prev != ')')) {
00044 norm_name += ' ';
00045 }
00046 norm_name += (prev = curr);
00047 }
00048
00049 return norm_name;
00050 }
00051
00052
00053 std::string NormalizeName( const std::string & nam ) {
00054 return NormalizeName(nam.c_str());
00055 }
00056 }
00057
00058
00059 std::string ND::Tools::Demangle( const std::type_info & ti ) {
00060 #if defined(_WIN32)
00061 static std::vector<std::string> keywords;
00062 if ( 0 == keywords.size() ) {
00063 keywords.push_back("class ");
00064 keywords.push_back("struct ");
00065 keywords.push_back("enum ");
00066 keywords.push_back("union ");
00067 keywords.push_back("__cdecl");
00068 }
00069 std::string r = ti.name();
00070 for ( size_t i = 0; i < keywords.size(); i ++ ) {
00071 while (r.find(keywords[i]) != std::string::npos)
00072 r = r.replace(r.find(keywords[i]), keywords[i].size(), "");
00073 while (r.find(" *") != std::string::npos)
00074 r = r.replace(r.find(" *"), 2, "*");
00075 while (r.find(" &") != std::string::npos)
00076 r = r.replace(r.find(" &"), 2, "&");
00077 }
00078 return r;
00079
00080 #elif defined(__GNUC__)
00081
00082 int status = 0;
00083 bool remove_additional_pointer = false;
00084 std::string mangled = ti.name();
00085
00086
00087
00088 if ( mangled == "Ss" ) return "std::basic_string<char>";
00089
00090 #if __GNUC__ <= 3 && __GNUC_MINOR__ <= 3
00091
00092
00093 if ( mangled[0] == 'F' ) {
00094 mangled.insert(0,"P");
00095 remove_additional_pointer = true;
00096 }
00097 #elif __GNUC__ >= 4
00098
00099 if (mangled.length() == 1) {
00100 switch ( mangled[0] ) {
00101 case 'a': return "signed char"; break;
00102 case 'b': return "bool"; break;
00103 case 'c': return "char"; break;
00104 case 'd': return "double"; break;
00105 case 'e': return "long double"; break;
00106 case 'f': return "float"; break;
00107 case 'g': return "__float128"; break;
00108 case 'h': return "unsigned char"; break;
00109 case 'i': return "int"; break;
00110 case 'j': return "unsigned int"; break;
00111
00112 case 'l': return "long"; break;
00113 case 'm': return "unsigned long"; break;
00114 case 'n': return "__int128"; break;
00115 case 'o': return "unsigned __int128"; break;
00116
00117
00118
00119 case 's': return "short"; break;
00120 case 't': return "unsigned short"; break;
00121
00122 case 'v': return "void"; break;
00123 case 'w': return "wchar_t"; break;
00124 case 'x': return "long long"; break;
00125 case 'y': return "unsigned long long"; break;
00126 case 'z': return "..."; break;
00127 default: break;
00128 }
00129 }
00130 #endif
00131 char * c_demangled = abi::__cxa_demangle( mangled.c_str(), 0, 0, & status );
00132 std::string demangled = c_demangled;
00133 std::free( c_demangled );
00134 if ( remove_additional_pointer ) {
00135 demangled = demangled.replace(demangled.find("(*)"), 3, "");
00136 }
00137 while ( demangled.find(", ") != std::string::npos ) {
00138 demangled = demangled.replace(demangled.find(", "), 2, ",");
00139 }
00140 return demangled;
00141
00142 #elif defined(__SUNPRO_CC)
00143
00144 const char* mangled = ti.name();
00145 size_t buffer = 1024;
00146 char * c_demangled = new char[buffer];
00147 int ret = cplus_demangle( mangled, c_demangled, buffer);
00148 while ( ret == -1 ) {
00149 buffer = buffer*2;
00150 delete[] c_demangled;
00151 c_demangled = new char[buffer];
00152 ret = cplus_demangle( mangled, c_demangled, buffer);
00153 }
00154 if ( ret == 1 ) {
00155 throw RuntimeError(std::string("Symbol ") + mangled + " not mangled correctly");
00156 }
00157 else {
00158 std::string demangled = NormalizeName(c_demangled);
00159 delete[] c_demangled;
00160 return demangled;
00161 }
00162
00163 #elif defined(__IBMCPP__)
00164
00165 return NormalizeName(ti.name());
00166
00167 #endif
00168 return "";
00169 }
00170