1/** 2 * @file demangle_java_symbol.cpp 3 * Demangle a java symbol 4 * 5 * @remark Copyright 2007 OProfile authors 6 * @remark Read the file COPYING 7 * 8 * @author Philippe Elie 9 */ 10 11#include "demangle_java_symbol.h" 12 13#include <algorithm> 14 15using namespace std; 16 17namespace { 18 19/** 20 * The grammar we implement: 21 * 22 * field_type: 23 * base_type | object_type | array_type 24 * base_type: 25 * B | C | D | F | I | J | S | Z 26 * object_type: 27 * L<classname>; 28 * array_type: 29 * [field_type 30 * method_descriptor: 31 * ( field_type* ) return_descriptor 32 * return_descriptor: 33 * field_type | V 34 * method_signature: 35 * object_type method_name method_descriptor 36 * 37 */ 38 39bool array_type(string & result, 40 string::const_iterator & begin, string::const_iterator end); 41bool object_type(string & result, 42 string::const_iterator & begin, string::const_iterator end); 43 44 45bool base_type(string & result, 46 string::const_iterator & begin, string::const_iterator end) 47{ 48 bool ret = true; 49 50 if (begin == end) 51 return false; 52 53 switch (*begin) { 54 case 'B': result += "byte"; break; 55 case 'C': result += "char"; break; 56 case 'D': result += "double"; break; 57 case 'F': result += "float"; break; 58 case 'I': result += "int"; break; 59 case 'J': result += "long"; break; 60 case 'S': result += "short"; break; 61 case 'Z': result += "boolean"; break; 62 default: ret = false; break; 63 } 64 65 if (ret) 66 ++begin; 67 return ret; 68} 69 70 71bool field_type(string & result, 72 string::const_iterator & begin, string::const_iterator end) 73{ 74 if (base_type(result, begin, end)) 75 return true; 76 77 if (object_type(result, begin, end)) 78 return true; 79 80 if (array_type(result, begin, end)) 81 return true; 82 83 return false; 84} 85 86 87bool array_type(string & result, 88 string::const_iterator & begin, string::const_iterator end) 89{ 90 if (begin == end || *begin != '[') 91 return false; 92 93 ++begin; 94 if (field_type(result, begin, end)) { 95 result += "[]"; 96 return true; 97 } 98 99 return false; 100} 101 102 103bool list_of_field_type(string & result, 104 string::const_iterator & begin, string::const_iterator end) 105{ 106 bool first = false; 107 while (begin != end) { 108 if (first) 109 result += ", "; 110 111 if (!field_type(result, begin, end)) 112 return false; 113 114 first = true; 115 } 116 117 return true; 118} 119 120 121bool return_descriptor(string & result, 122 string::const_iterator & begin, string::const_iterator end) 123{ 124 if (begin == end) 125 return false; 126 if (*begin == 'V') { 127 ++begin; 128 result = "void " + result; 129 return true; 130 } 131 132 string temp; 133 if (!field_type(temp, begin, end)) 134 return false; 135 result = temp + " " + result; 136 137 return true; 138} 139 140 141bool method_descriptor(string & result, 142 string::const_iterator & begin, string::const_iterator end) 143{ 144 if (begin == end || *begin != '(') 145 return false; 146 ++begin; 147 string::const_iterator pos = find(begin, end, ')'); 148 if (pos == end) 149 return false; 150 151 result += "("; 152 153 if (!list_of_field_type(result, begin, pos)) 154 return false; 155 156 if (begin == end || *begin != ')') 157 return false; 158 159 ++begin; 160 161 if (!return_descriptor(result, begin, end)) 162 return false; 163 164 result += ')'; 165 166 return true; 167} 168 169 170bool methode_name(string & result, 171 string::const_iterator & begin, string::const_iterator end) 172{ 173 if (begin == end) 174 return false; 175 176 string::const_iterator pos = find(begin, end, '('); 177 if (pos == end) 178 return false; 179 180 result += '.' + string(begin, pos); 181 begin = pos; 182 183 return true; 184} 185 186 187bool object_type(string & result, 188 string::const_iterator & begin, string::const_iterator end) 189{ 190 if (begin == end || *begin != 'L') 191 return false; 192 string::const_iterator pos = find(begin, end, ';'); 193 if (pos == end) 194 return false; 195 196 string temp = string(begin + 1, pos); 197 replace(temp.begin(), temp.end(), '/', '.'); 198 result += temp; 199 200 begin = pos + 1; 201 202 return true; 203} 204 205 206string demangle_symbol(string::const_iterator begin, 207 string::const_iterator end) 208{ 209 string result; 210 211 if (!object_type(result, begin, end)) 212 return string(); 213 214 if (!methode_name(result, begin, end)) 215 return string(); 216 217 if (!method_descriptor(result, begin, end)) 218 return string(); 219 220 if (begin != end) { 221 if (*begin == '~') { 222 // special case for disambiguated symbol. 223 result += string(begin, end); 224 } else { 225 return string(); 226 } 227 } 228 229 return result; 230} 231 232} // anonymous namespace 233 234 235string const demangle_java_symbol(string const & name) 236{ 237 return demangle_symbol(name.begin(), name.end()); 238} 239