00001 /** @file rutz/demangle_gcc_v2.h hand-rolled demangling of 00002 std::type_info::name() from the g++ 2.x series */ 00003 00004 /////////////////////////////////////////////////////////////////////// 00005 // 00006 // Copyright (c) 2002-2004 California Institute of Technology 00007 // Copyright (c) 2004-2007 University of Southern California 00008 // Rob Peters <rjpeters at usc dot edu> 00009 // 00010 // created: Tue Jun 19 16:58:19 2001 (as gcc_v2_demangle.h) 00011 // commit: $Id: demangle_gcc_v2.h 8249 2007-04-12 06:03:40Z rjpeters $ 00012 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/rutz/demangle_gcc_v2.h $ 00013 // 00014 // -------------------------------------------------------------------- 00015 // 00016 // This file is part of GroovX. 00017 // [http://ilab.usc.edu/rjpeters/groovx/] 00018 // 00019 // GroovX is free software; you can redistribute it and/or modify it 00020 // under the terms of the GNU General Public License as published by 00021 // the Free Software Foundation; either version 2 of the License, or 00022 // (at your option) any later version. 00023 // 00024 // GroovX is distributed in the hope that it will be useful, but 00025 // WITHOUT ANY WARRANTY; without even the implied warranty of 00026 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00027 // General Public License for more details. 00028 // 00029 // You should have received a copy of the GNU General Public License 00030 // along with GroovX; if not, write to the Free Software Foundation, 00031 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 00032 // 00033 /////////////////////////////////////////////////////////////////////// 00034 00035 #ifndef GROOVX_RUTZ_DEMANGLE_GCC_V2_H_UTC20050626084020_DEFINED 00036 #define GROOVX_RUTZ_DEMANGLE_GCC_V2_H_UTC20050626084020_DEFINED 00037 00038 #include <cctype> 00039 #include <cstdlib> 00040 #include <string> 00041 00042 #include "rutz/trace.h" 00043 #include "rutz/debug.h" 00044 GVX_DBG_REGISTER 00045 00046 namespace 00047 { 00048 int munch_int(std::string& str, std::string::size_type pos) 00049 { 00050 int val = 0; 00051 while ( isdigit(str[pos]) ) 00052 { 00053 val *= 10; 00054 val += (str[pos] - '0'); 00055 str.erase(pos, 1); 00056 } 00057 return val; 00058 } 00059 00060 void put_int(int val, std::string& str, std::string::size_type pos) 00061 { 00062 while (val != 0) 00063 { 00064 str.insert(pos, 1, '0' + (val%10)); 00065 val /= 10; 00066 } 00067 } 00068 00069 std::string read_modifiers(std::string& str, std::string::size_type& pos) 00070 { 00071 std::string modifiers(""); 00072 std::string array_dims(""); 00073 00074 while ( isupper(str[pos]) ) 00075 { 00076 switch (str[pos]) 00077 { 00078 case 'A': 00079 str.erase(pos, 1); // we need to also erase the '_' 00080 array_dims.append("["); 00081 if ( isdigit(str[pos]) ) 00082 { 00083 int dim_size = munch_int(str, pos); 00084 put_int(dim_size+1,array_dims,array_dims.length()); 00085 } 00086 array_dims.append("]"); 00087 break; 00088 case 'C': 00089 modifiers.insert(0, " const"); 00090 break; 00091 case 'P': 00092 modifiers.insert(0, "*"); 00093 break; 00094 case 'R': 00095 modifiers.insert(0, "&"); 00096 break; 00097 case 'U': 00098 modifiers.insert(0, " unsigned"); 00099 break; 00100 default: 00101 GVX_ASSERT(0); 00102 } 00103 str.erase(pos, 1); 00104 } 00105 dbg_eval_nl(3, str.c_str()); 00106 00107 modifiers.append(array_dims); 00108 00109 return modifiers; 00110 } 00111 00112 void insert_builtin_typename(std::string& str, std::string::size_type& pos) 00113 { 00114 char typecode = str[pos]; 00115 str.erase(pos, 1); 00116 switch (typecode) 00117 { 00118 case 'b': 00119 str.insert(pos, "bool"); pos += 4; 00120 break; 00121 case 'c': 00122 str.insert(pos, "char"); pos += 4; 00123 break; 00124 case 'd': 00125 str.insert(pos, "double"); pos += 6; 00126 break; 00127 case 'f': 00128 str.insert(pos, "float"); pos += 5; 00129 break; 00130 case 'i': 00131 str.insert(pos, "int"); pos += 3; 00132 break; 00133 case 'l': 00134 str.insert(pos, "long"); pos += 4; 00135 break; 00136 case 's': 00137 str.insert(pos, "short"); pos += 5; 00138 break; 00139 case 'v': 00140 str.insert(pos, "void"); pos += 4; 00141 break; 00142 default: 00143 dbg_eval_nl(3, typecode); 00144 GVX_ASSERT(0); 00145 break; 00146 } 00147 } 00148 00149 std::string demangle_gcc_v2(const std::string& in) 00150 { 00151 GVX_TRACE("demangle_impl"); 00152 std::string out=in; 00153 00154 dbg_eval_nl(3, out.c_str()); 00155 00156 bool isTemplate = false; 00157 00158 if (out.length() == 0) return out; 00159 00160 std::string::size_type pos = 0; 00161 00162 // Check if we have namespace qualifiers... 00163 if (out[0] == 'Q') 00164 { 00165 out.erase(0, 1); 00166 int num_levels = 0; 00167 // get the number of nesting levels... 00168 if (out[0] == '_') 00169 { 00170 out.erase(0, 1); 00171 num_levels = munch_int(out, 0); 00172 dbg_eval_nl(3, num_levels); 00173 GVX_ASSERT(out[0] == '_'); 00174 out.erase(0, 1); 00175 } 00176 else 00177 { 00178 num_levels = out[0] - '0'; 00179 out.erase(0, 1); 00180 } 00181 while (num_levels > 1) 00182 { 00183 // Get the length of the current qualifier 00184 int length = munch_int(out, pos); 00185 // Skip over the qualifier itself 00186 pos += length; 00187 // Insert a scope resolution operator after the qualifier "::" 00188 out.insert(pos, "::"); 00189 // Skip over the just-inserted "::" 00190 pos += 2; 00191 --num_levels; 00192 } 00193 } 00194 00195 dbg_eval_nl(3, out.c_str()); 00196 00197 if (out[pos] == 't') 00198 { 00199 isTemplate = true; 00200 out.erase(pos, 1); 00201 } 00202 00203 if ( !isTemplate ) 00204 { 00205 while ( isdigit(out[pos]) ) 00206 { 00207 out.erase(pos, 1); 00208 } 00209 dbg_eval_nl(3, out.c_str()); 00210 } 00211 else 00212 { 00213 // Read length of template base name and skip over it 00214 int base_length = munch_int(out, pos); 00215 pos += base_length; 00216 00217 // Insert left bracket 00218 out.insert(pos++, 1, '<'); 00219 00220 dbg_eval_nl(3, out.c_str()); 00221 00222 int num_parameters = munch_int(out, pos);; 00223 00224 for (int n = 0; n < num_parameters; ++n) 00225 { 00226 // Template parameters must start with 'Z' 00227 GVX_ASSERT( out[pos] == 'Z' ); 00228 out.erase(pos, 1); 00229 00230 dbg_eval_nl(3, out.c_str()); 00231 00232 // Get the parameter name: 00233 std::string modifiers = read_modifiers(out, pos); 00234 00235 if ( !isdigit(out[pos]) ) 00236 { 00237 insert_builtin_typename(out, pos); 00238 } 00239 else 00240 { 00241 // Read length of template parameter name and skip over it 00242 int param_length = munch_int(out, pos); 00243 pos += param_length; 00244 } 00245 00246 out.insert(pos, modifiers); 00247 pos += modifiers.length(); 00248 00249 // Insert a comma if this is not the last parameter 00250 if (n < (num_parameters-1)) 00251 { 00252 out.insert(pos++, 1, ','); 00253 out.insert(pos++, 1, ' '); 00254 } 00255 00256 dbg_eval_nl(3, out.c_str()); 00257 } 00258 00259 // Insert right bracket 00260 out.insert(pos++, 1, '>'); 00261 } 00262 00263 dbg_eval_nl(3, out.c_str()); 00264 00265 return out; 00266 } 00267 } 00268 00269 static const char __attribute__((used)) vcid_groovx_rutz_demangle_gcc_v2_h_utc20050626084020[] = "$Id: demangle_gcc_v2.h 8249 2007-04-12 06:03:40Z rjpeters $ $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/rutz/demangle_gcc_v2.h $"; 00270 #endif // !GROOVX_RUTZ_DEMANGLE_GCC_V2_H_UTC20050626084020_DEFINED