/[gxemul]/upstream/0.4.5/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

Annotation of /upstream/0.4.5/src/symbol_demangle.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 39 - (hide annotations)
Mon Oct 8 16:22:02 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 7074 byte(s)
0.4.5
1 dpavlin 24 /*
2 dpavlin 34 * Copyright (C) 2006-2007 Anders Gavare. All rights reserved.
3 dpavlin 24 *
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 dpavlin 34 * $Id: symbol_demangle.c,v 1.7 2006/12/30 13:30:53 debug Exp $
29 dpavlin 24 *
30     * C++ symbol name demangling.
31     *
32 dpavlin 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 dpavlin 24 *
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 = malloc(MAXLEN + 1);
69     size_t result_len = 0, len;
70     int first = 1, type_added = 0, pointercounter, reference;
71    
72     result[0] = '\0';
73    
74     while (name[0] && name[0] != 'E' && result_len < MAXLEN) {
75     /* Read length of the next part: */
76     len = 0;
77     if (*name == '0') {
78     name ++;
79     } else {
80     while (isdigit((int)*name)) {
81     len *= 10;
82     len += (*name - '0');
83     name ++;
84     }
85     }
86    
87     /* Add :: */
88     if (!first)
89     add_string(result, &result_len, "::");
90    
91     /* Read the part itself: */
92     while (len-- >= 1 && result_len < MAXLEN)
93     result[result_len ++] = *name++;
94    
95     first = 0;
96     }
97    
98     if (name[0] != 'E')
99     goto fail;
100    
101     name ++;
102    
103     if (*name)
104     add_string(result, &result_len, "{");
105    
106     /* Type: */
107     pointercounter = reference = 0;
108     while (*name) {
109     int argument_done = 0;
110     char t = *name++;
111     switch (t) {
112     case 'c':
113     add_string(result, &result_len, "char");
114     argument_done = 1;
115     break;
116     case 'a':
117     add_string(result, &result_len, "signed char");
118     argument_done = 1;
119     break;
120     case 'h':
121     add_string(result, &result_len, "unsigned char");
122     argument_done = 1;
123     break;
124     case 'i':
125     add_string(result, &result_len, "int");
126     argument_done = 1;
127     break;
128     case 'j':
129     add_string(result, &result_len, "unsigned int");
130     argument_done = 1;
131     break;
132     case 'w':
133     add_string(result, &result_len, "wchar_t");
134     argument_done = 1;
135     break;
136     case 'b':
137     add_string(result, &result_len, "bool");
138     argument_done = 1;
139     break;
140     case 's':
141     add_string(result, &result_len, "short");
142     argument_done = 1;
143     break;
144     case 't':
145     add_string(result, &result_len, "unsigned short");
146     argument_done = 1;
147     break;
148     case 'l':
149     add_string(result, &result_len, "long");
150     argument_done = 1;
151     break;
152     case 'm':
153     add_string(result, &result_len, "unsigned long");
154     argument_done = 1;
155     break;
156     case 'x':
157     add_string(result, &result_len, "long long");
158     argument_done = 1;
159     break;
160     case 'y':
161     add_string(result, &result_len, "unsigned long long");
162     argument_done = 1;
163     break;
164     case 'n':
165     add_string(result, &result_len, "__int128");
166     argument_done = 1;
167     break;
168     case 'o':
169     add_string(result, &result_len, "unsigned __int128");
170     argument_done = 1;
171     break;
172     case 'f':
173     add_string(result, &result_len, "float");
174     argument_done = 1;
175     break;
176     case 'd':
177     add_string(result, &result_len, "double");
178     argument_done = 1;
179     break;
180     case 'e':
181     add_string(result, &result_len, "__float80");
182     argument_done = 1;
183     break;
184     case 'g':
185     add_string(result, &result_len, "__float128");
186     argument_done = 1;
187     break;
188     case 'z':
189     add_string(result, &result_len, "...");
190     argument_done = 1;
191     break;
192     case 'P':
193     pointercounter ++;
194     break;
195     case 'R':
196     reference ++;
197     break;
198     case 'v': /* void */
199     break;
200     default:/* Unknown */
201     goto fail;
202     }
203     if (argument_done) {
204     while (pointercounter-- > 0)
205     add_string(result, &result_len, "*");
206     while (reference-- > 0)
207     add_string(result, &result_len, "&");
208     if (*name)
209     add_string(result, &result_len, ",");
210     }
211     type_added = 1;
212     }
213    
214     if (type_added)
215     add_string(result, &result_len, "}");
216    
217     if (result_len == MAXLEN)
218     goto fail;
219    
220     result[result_len] = '\0';
221    
222     return result;
223    
224     fail:
225     free(result);
226     return NULL;
227     }
228    
229    
230     /*
231     * symbol_demangle_cplusplus():
232     *
233     * Try to demangle name. If name was not a valid/known C++ symbol, then NULL
234     * is returned. Otherwise, a newly allocated string is returned, containing
235     * the demangled name.
236     */
237     char *symbol_demangle_cplusplus(char *name)
238     {
239     /* Only support _Z-style mangled names, for now: */
240     if (strlen(name) < 2 || name[0] != '_' || name[1] != 'Z')
241     return NULL;
242    
243     name += 2;
244    
245     switch (name[0]) {
246     case 'N':
247     return symbol_demangle_cplusplus_nested(name + 1);
248     break;
249     }
250    
251     return NULL;
252     }
253    
254    
255    
256     #ifdef TEST
257    
258     void test(char *mangled, char *result)
259     {
260     char *p = symbol_demangle_cplusplus(mangled);
261     if (p == NULL) {
262     if (result == NULL) {
263     return;
264     } else {
265     printf("FAILURE for %s!\n", mangled);
266     exit(1);
267     }
268     }
269     if (strcmp(p, result) == 0)
270     return;
271     printf("FAILURE for %s! (result = %s)\n", mangled, p);
272     exit(1);
273     }
274    
275     int main(int argc, char *argv[])
276     {
277     test("monkey", NULL);
278     test("_monkey", NULL);
279     test("_zmonkey", NULL);
280     test("_Zmonkey", NULL);
281     test("_ZQ5abcde", NULL);
282     test("_ZN3abc5defghE", "abc::defgh");
283     test("_ZN05defghEv", "::defgh{}");
284     test("_ZN5defghEv", "defgh{}");
285     test("_ZN3abc5defghEv", "abc::defgh{}");
286     test("_ZN3abc5defghEc", "abc::defgh{char}");
287     test("_ZN1a2bcEjij", "a::bc{unsigned int,int,unsigned int}");
288     printf("OK\n");
289     return 0;
290     }
291    
292     #endif
293    

  ViewVC Help
Powered by ViewVC 1.1.26