Demangle.cxx

Go to the documentation of this file.
00001 // Author: Stefan Roiser 2004
00002 
00003 // Copyright CERN, CH-1211 Geneva 23, 2004-2006, All rights reserved.
00004 //
00005 // Permission to use, copy, modify, and distribute this software for any
00006 // purpose is hereby granted without fee, provided that this copyright and
00007 // permissions notice appear in all copies and derivatives.
00008 //
00009 // This software is provided "as is" without express or implied warranty.
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     // Return true if char is alpha or digit.
00024     bool isalphanum(int i) {
00025         return isalpha(i) || isdigit(i);
00026     }
00027 
00028     // Normalize a type name.
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; // continue on non-word boundaries
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 // Demangle a type_info object.
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     // if the At Name is string return the final string Name 
00087     // abi::Demangle would return "std::string" instead
00088     if ( mangled == "Ss" ) return "std::basic_string<char>";
00089 
00090 #if __GNUC__ <= 3 && __GNUC_MINOR__ <= 3
00091     // Function types are not decoded at all. We are an extra 'P' to convert it to a pointer
00092     // and remove it at the end.
00093     if ( mangled[0] == 'F' ) {
00094         mangled.insert(0,"P");
00095         remove_additional_pointer = true;
00096     }
00097 #elif __GNUC__ >= 4
00098     // From gcc 4.0 on the fundamental types are not demangled anymore by the dynamic demangler
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             //case 'k': return "";                   break;
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             //case 'p': return "";                   break;
00117             //case 'q': return "";                   break;
00118             //case 'r': return "";                   break;
00119         case 's': return "short";              break;
00120         case 't': return "unsigned short";     break;
00121             //case 'u': return "";                   break;
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 

Generated on 11 Aug 2013 for SKDatabase by  doxygen 1.6.1