/** * @file demangle_java_symbol.cpp * Demangle a java symbol * * @remark Copyright 2007 OProfile authors * @remark Read the file COPYING * * @author Philippe Elie */ #include "demangle_java_symbol.h" #include <algorithm> using namespace std; namespace { /** * The grammar we implement: * * field_type: * base_type | object_type | array_type * base_type: * B | C | D | F | I | J | S | Z * object_type: * L<classname>; * array_type: * [field_type * method_descriptor: * ( field_type* ) return_descriptor * return_descriptor: * field_type | V * method_signature: * object_type method_name method_descriptor * */ bool array_type(string & result, string::const_iterator & begin, string::const_iterator end); bool object_type(string & result, string::const_iterator & begin, string::const_iterator end); bool base_type(string & result, string::const_iterator & begin, string::const_iterator end) { bool ret = true; if (begin == end) return false; switch (*begin) { case 'B': result += "byte"; break; case 'C': result += "char"; break; case 'D': result += "double"; break; case 'F': result += "float"; break; case 'I': result += "int"; break; case 'J': result += "long"; break; case 'S': result += "short"; break; case 'Z': result += "boolean"; break; default: ret = false; break; } if (ret) ++begin; return ret; } bool field_type(string & result, string::const_iterator & begin, string::const_iterator end) { if (base_type(result, begin, end)) return true; if (object_type(result, begin, end)) return true; if (array_type(result, begin, end)) return true; return false; } bool array_type(string & result, string::const_iterator & begin, string::const_iterator end) { if (begin == end || *begin != '[') return false; ++begin; if (field_type(result, begin, end)) { result += "[]"; return true; } return false; } bool list_of_field_type(string & result, string::const_iterator & begin, string::const_iterator end) { bool first = false; while (begin != end) { if (first) result += ", "; if (!field_type(result, begin, end)) return false; first = true; } return true; } bool return_descriptor(string & result, string::const_iterator & begin, string::const_iterator end) { if (begin == end) return false; if (*begin == 'V') { ++begin; result = "void " + result; return true; } string temp; if (!field_type(temp, begin, end)) return false; result = temp + " " + result; return true; } bool method_descriptor(string & result, string::const_iterator & begin, string::const_iterator end) { if (begin == end || *begin != '(') return false; ++begin; string::const_iterator pos = find(begin, end, ')'); if (pos == end) return false; result += "("; if (!list_of_field_type(result, begin, pos)) return false; if (begin == end || *begin != ')') return false; ++begin; if (!return_descriptor(result, begin, end)) return false; result += ')'; return true; } bool methode_name(string & result, string::const_iterator & begin, string::const_iterator end) { if (begin == end) return false; string::const_iterator pos = find(begin, end, '('); if (pos == end) return false; result += '.' + string(begin, pos); begin = pos; return true; } bool object_type(string & result, string::const_iterator & begin, string::const_iterator end) { if (begin == end || *begin != 'L') return false; string::const_iterator pos = find(begin, end, ';'); if (pos == end) return false; string temp = string(begin + 1, pos); replace(temp.begin(), temp.end(), '/', '.'); result += temp; begin = pos + 1; return true; } string demangle_symbol(string::const_iterator begin, string::const_iterator end) { string result; if (!object_type(result, begin, end)) return string(); if (!methode_name(result, begin, end)) return string(); if (!method_descriptor(result, begin, end)) return string(); if (begin != end) { if (*begin == '~') { // special case for disambiguated symbol. result += string(begin, end); } else { return string(); } } return result; } } // anonymous namespace string const demangle_java_symbol(string const & name) { return demangle_symbol(name.begin(), name.end()); }