/[gxemul]/upstream/0.4.6/src/symbol_demangle.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/0.4.6/src/symbol_demangle.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 43 - (show annotations)
Mon Oct 8 16:22:43 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 7101 byte(s)
0.4.6
1 /*
2 * Copyright (C) 2006-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: symbol_demangle.c,v 1.8 2007/06/15 17:02:38 debug Exp $
29 *
30 * C++ symbol name demangling.
31 *
32 * For obvious performance reasons, the external c++filt utility cannot be
33 * used. Also, the host's version of this utility might be incompatible with
34 * the binary being emulated.
35 *
36 * TODO: Constructors, destructors, and lots of other stuff. See
37 * http://www.codesourcery.com/cxx-abi/abi.html#mangling for details.
38 */
39
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <ctype.h>
44
45 #include "symbol.h"
46
47
48 #define MAXLEN 1000
49
50
51 static void add_string(char *p, size_t *curlenp, char *to_add)
52 {
53 size_t curlen = *curlenp;
54 while (curlen < MAXLEN && *to_add)
55 p[curlen++] = *to_add++;
56 *curlenp = curlen;
57 }
58
59
60 /*
61 * symbol_demangle_cplusplus_nested():
62 *
63 * Try to demangle a nested cplusplus name. name points to the first character
64 * after "_ZN".
65 */
66 static char *symbol_demangle_cplusplus_nested(char *name)
67 {
68 char *result;
69 size_t result_len = 0, len;
70 int first = 1, type_added = 0, pointercounter, reference;
71
72 CHECK_ALLOCATION(result = malloc(MAXLEN + 1));
73 result[0] = '\0';
74
75 while (name[0] && name[0] != 'E' && result_len < MAXLEN) {
76 /* Read length of the next part: */
77 len = 0;
78 if (*name == '0') {
79 name ++;
80 } else {
81 while (isdigit((int)*name)) {
82 len *= 10;
83 len += (*name - '0');
84 name ++;
85 }
86 }
87
88 /* Add :: */
89 if (!first)
90 add_string(result, &result_len, "::");
91
92 /* Read the part itself: */
93 while (len-- >= 1 && result_len < MAXLEN)
94 result[result_len ++] = *name++;
95
96 first = 0;
97 }
98
99 if (name[0] != 'E')
100 goto fail;
101
102 name ++;
103
104 if (*name)
105 add_string(result, &result_len, "{");
106
107 /* Type: */
108 pointercounter = reference = 0;
109 while (*name) {
110 int argument_done = 0;
111 char t = *name++;
112 switch (t) {
113 case 'c':
114 add_string(result, &result_len, "char");
115 argument_done = 1;
116 break;
117 case 'a':
118 add_string(result, &result_len, "signed char");
119 argument_done = 1;
120 break;
121 case 'h':
122 add_string(result, &result_len, "unsigned char");
123 argument_done = 1;
124 break;
125 case 'i':
126 add_string(result, &result_len, "int");
127 argument_done = 1;
128 break;
129 case 'j':
130 add_string(result, &result_len, "unsigned int");
131 argument_done = 1;
132 break;
133 case 'w':
134 add_string(result, &result_len, "wchar_t");
135 argument_done = 1;
136 break;
137 case 'b':
138 add_string(result, &result_len, "bool");
139 argument_done = 1;
140 break;
141 case 's':
142 add_string(result, &result_len, "short");
143 argument_done = 1;
144 break;
145 case 't':
146 add_string(result, &result_len, "unsigned short");
147 argument_done = 1;
148 break;
149 case 'l':
150 add_string(result, &result_len, "long");
151 argument_done = 1;
152 break;
153 case 'm':
154 add_string(result, &result_len, "unsigned long");
155 argument_done = 1;
156 break;
157 case 'x':
158 add_string(result, &result_len, "long long");
159 argument_done = 1;
160 break;
161 case 'y':
162 add_string(result, &result_len, "unsigned long long");
163 argument_done = 1;
164 break;
165 case 'n':
166 add_string(result, &result_len, "__int128");
167 argument_done = 1;
168 break;
169 case 'o':
170 add_string(result, &result_len, "unsigned __int128");
171 argument_done = 1;
172 break;
173 case 'f':
174 add_string(result, &result_len, "float");
175 argument_done = 1;
176 break;
177 case 'd':
178 add_string(result, &result_len, "double");
179 argument_done = 1;
180 break;
181 case 'e':
182 add_string(result, &result_len, "__float80");
183 argument_done = 1;
184 break;
185 case 'g':
186 add_string(result, &result_len, "__float128");
187 argument_done = 1;
188 break;
189 case 'z':
190 add_string(result, &result_len, "...");
191 argument_done = 1;
192 break;
193 case 'P':
194 pointercounter ++;
195 break;
196 case 'R':
197 reference ++;
198 break;
199 case 'v': /* void */
200 break;
201 default:/* Unknown */
202 goto fail;
203 }
204 if (argument_done) {
205 while (pointercounter-- > 0)
206 add_string(result, &result_len, "*");
207 while (reference-- > 0)
208 add_string(result, &result_len, "&");
209 if (*name)
210 add_string(result, &result_len, ",");
211 }
212 type_added = 1;
213 }
214
215 if (type_added)
216 add_string(result, &result_len, "}");
217
218 if (result_len == MAXLEN)
219 goto fail;
220
221 result[result_len] = '\0';
222
223 return result;
224
225 fail:
226 free(result);
227 return NULL;
228 }
229
230
231 /*
232 * symbol_demangle_cplusplus():
233 *
234 * Try to demangle name. If name was not a valid/known C++ symbol, then NULL
235 * is returned. Otherwise, a newly allocated string is returned, containing
236 * the demangled name.
237 */
238 char *symbol_demangle_cplusplus(char *name)
239 {
240 /* Only support _Z-style mangled names, for now: */
241 if (strlen(name) < 2 || name[0] != '_' || name[1] != 'Z')
242 return NULL;
243
244 name += 2;
245
246 switch (name[0]) {
247 case 'N':
248 return symbol_demangle_cplusplus_nested(name + 1);
249 break;
250 }
251
252 return NULL;
253 }
254
255
256
257 #ifdef TEST
258
259 void test(char *mangled, char *result)
260 {
261 char *p = symbol_demangle_cplusplus(mangled);
262 if (p == NULL) {
263 if (result == NULL) {
264 return;
265 } else {
266 printf("FAILURE for %s!\n", mangled);
267 exit(1);
268 }
269 }
270 if (strcmp(p, result) == 0)
271 return;
272 printf("FAILURE for %s! (result = %s)\n", mangled, p);
273 exit(1);
274 }
275
276 int main(int argc, char *argv[])
277 {
278 test("monkey", NULL);
279 test("_monkey", NULL);
280 test("_zmonkey", NULL);
281 test("_Zmonkey", NULL);
282 test("_ZQ5abcde", NULL);
283 test("_ZN3abc5defghE", "abc::defgh");
284 test("_ZN05defghEv", "::defgh{}");
285 test("_ZN5defghEv", "defgh{}");
286 test("_ZN3abc5defghEv", "abc::defgh{}");
287 test("_ZN3abc5defghEc", "abc::defgh{char}");
288 test("_ZN1a2bcEjij", "a::bc{unsigned int,int,unsigned int}");
289 printf("OK\n");
290 return 0;
291 }
292
293 #endif
294

  ViewVC Help
Powered by ViewVC 1.1.26