blob: ab75e6c290b647a0a3883f0b8b7cc05094549a75 [file] [log] [blame]
Mike Dodd8cfa7022010-11-17 11:12:26 -08001/**
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}