Home | History | Annotate | Download | only in libregex
      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 
     15 using namespace std;
     16 
     17 namespace {
     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 
     39 bool array_type(string & result,
     40 	string::const_iterator & begin, string::const_iterator end);
     41 bool object_type(string & result,
     42 	string::const_iterator & begin, string::const_iterator end);
     43 
     44 
     45 bool 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 
     71 bool 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 
     87 bool 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 
    103 bool 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 
    121 bool 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 
    141 bool 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 
    170 bool 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 
    187 bool 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 
    206 string 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 
    235 string const demangle_java_symbol(string const & name)
    236 {
    237 	return demangle_symbol(name.begin(), name.end());
    238 }
    239