Blob


1 /*
2 * gcc3 name demangler.
3 */
4 #include <u.h>
5 #include <libc.h>
6 #include <bio.h>
7 #include <mach.h>
9 typedef struct Chartab Chartab;
10 struct Chartab
11 {
12 char c;
13 char *s;
14 };
16 static char*
17 chartabsearch(Chartab *ct, int c)
18 {
19 for(; ct->c; ct++)
20 if(ct->c == c)
21 return ct->s;
22 return nil;
23 }
25 typedef struct Gccstate Gccstate;
26 struct Gccstate
27 {
28 char *name[128];
29 int nname;
30 };
31 static int gccname(char**, char**, Gccstate*);
32 char*
33 demanglegcc3(char *s, char *buf)
34 {
35 char *p, *os;
36 Gccstate state;
38 state.nname = 0;
39 os = s;
40 /* mangled names always start with _Z */
41 if(s[0] != '_' || s[1] != 'Z')
42 return s;
43 s += 2;
45 p = buf;
46 if(!gccname(&s, &p, &state)){
47 if(strchr(os, '@') == nil)
48 fprint(2, "demangle: %s\n");
49 return os;
50 }
51 if(*s){
52 /* the rest of the name is the argument types */
53 *p++ = '(';
54 while(*s != 0 && gccname(&s, &p, &state))
55 *p++ = ',';
56 if(*(p-1) == ',')
57 p--;
58 *p++ = ')';
59 }
60 *p = 0;
61 return buf;
62 }
64 static Chartab stdnames[] =
65 {
66 'a', "std::allocator",
67 'b', "std::basic_string",
68 'd', "std::iostream",
69 'i', "std::istream",
70 'o', "std::ostream",
71 's', "std::string",
72 0, 0
73 };
75 static Chartab typetab[] =
76 {
77 'b', "bool",
78 'c', "char",
79 'd', "double",
80 'i', "int",
81 'j', "uint",
82 'v', "void",
83 0, 0
84 };
86 static struct {
87 char *shrt;
88 char *actual;
89 char *lng;
90 } operators[] =
91 {
92 "aN", "&=", "andeq",
93 "aS", "=", "assign",
94 "aa", "&&", "andand",
95 "ad", "&", "and",
96 "an", "&", "and",
97 "cl", "()", "construct",
98 "cm", ",", "comma",
99 "co", "~", "twiddle",
100 "dV", "/=", "diveq",
101 "da", "delete[]", "deletearray",
102 "de", "*", "star",
103 "dl", "delete", "delete",
104 "dv", "/", "div",
105 "eO", "^=", "xoreq",
106 "eo", "^", "xor",
107 "eq", "==", "eq",
108 "ge", ">=", "geq",
109 "gt", ">", "gt",
110 "ix", "[]", "index",
111 "IS", "<<=", "lsheq",
112 "le", "<=", "leq",
113 "ls", "<<", "lsh",
114 "lt", "<", "lt",
115 "ml", "-=", "subeq",
116 "mL", "*=", "muleq",
117 "mi", "-", "sub",
118 "mI", "*", "mul",
119 "mm", "--", "dec",
120 "na", "new[]", "newarray",
121 "ne", "!=", "neq",
122 "ng", "-", "neg",
123 "nt", "!", "not",
124 "nw", "new", "new",
125 "oR", "|=", "oreq",
126 "oo", "||", "oror",
127 "or", "|", "or",
128 "pL", "+=", "addeq",
129 "pl", "+", "add",
130 "pm", "->*", "pointstoderef",
131 "pp", "++", "inc",
132 "ps", "+", "pos",
133 "pt", "->", "pointsto",
134 "qu", "?", "question",
135 "rM", "%=", "modeq",
136 "rS", ">>=", "rsheq",
137 "rm", "%", "mod",
138 "rs", ">>", "rsh",
139 "st", "sizeof", "sizeoftype",
140 "sz", "sizeof", "sizeofexpr",
142 0,0,0
143 };
145 /*
146 * Pick apart the next mangled name section.
147 * Names and types are treated as the same.
148 * Let's see how far we can go before that becomes a problem.
149 */
150 static int
151 gccname(char **ps, char **pp, Gccstate *state)
153 int i, n;
154 char *os, *s, *t, *p;
155 Gccstate nstate;
157 s = *ps;
158 os = s;
159 p = *pp;
161 /* print("\tgccname: %s\n", s); */
163 /* overloaded operators */
164 for(i=0; operators[i].shrt; i++){
165 if(memcmp(operators[i].shrt, s, 2) == 0){
166 strcpy(p, "operator$");
167 strcat(p, operators[i].lng);
168 p += strlen(p);
169 s += 2;
170 goto suffix;
174 /* basic types */
175 if((t = chartabsearch(typetab, *s)) != nil){
176 s++;
177 strcpy(p, t);
178 p += strlen(t);
179 goto suffix;
182 switch(*s){
183 default:
184 bad:
185 fprint(2, "bad name: %s\n", s);
186 return 0;
188 case '1': case '2': case '3': case '4': /* name length */
189 case '5': case '6': case '7': case '8': case '9':
190 n = strtol(s, &s, 10);
191 memmove(p, s, n);
192 p += n;
193 s += n;
194 break;
196 case 'C': /* C1: constructor? */
197 strtol(s+1, &s, 10);
198 strcpy(p, "constructor");
199 p += strlen(p);
200 break;
202 case 'D': /* D1: destructor? */
203 strtol(s+1, &s, 10);
204 strcpy(p, "destructor");
205 p += strlen(p);
206 break;
208 case 'K': /* const */
209 s++;
210 strcpy(p, "const ");
211 p += strlen(p);
212 if(!gccname(&s, &p, state))
213 return 0;
214 break;
216 case 'L': /* default value */
217 t = s;
218 s++;
219 if(!gccname(&s, &p, state))
220 return 0;
221 if(!isdigit((uchar)*s)){
222 fprint(2, "bad value: %s\n", t);
223 return 0;
225 n = strtol(s, &s, 10);
226 if(*s != 'E'){
227 fprint(2, "bad value2: %s\n", t);
228 return 0;
230 sprint(p, "=%d", n);
231 p += strlen(p);
232 s++;
233 break;
235 case 'N': /* hierarchical name */
236 s++;
237 while(*s != 'E'){
238 if(!gccname(&s, &p, state)){
239 fprint(2, "bad name in hierarchy: %s in %s\n", s, os);
240 return 0;
242 strcpy(p, "::");
243 p += 2;
245 p -= 2;
246 s++;
247 break;
249 case 'P': /* pointer to */
250 s++;
251 if(!gccname(&s, &p, state))
252 return 0;
253 *p++ = '*';
254 break;
256 case 'R': /* reference to */
257 s++;
258 if(!gccname(&s, &p, state))
259 return 0;
260 *p++ = '&';
261 break;
263 case 'S': /* standard or previously-seen name */
264 s++;
265 if('0' <= *s && *s <= '9'){
266 /* previously seen */
267 t = s-1;
268 n = strtol(s, &s, 10);
269 if(*s != '_'){
270 fprint(2, "bad S: %s\n", t);
271 return 0;
273 s++;
274 sprint(p, "S%d_", n);
275 p += strlen(p);
276 break;
278 /* SA_ ??? */
279 if(*s == 'A' && *(s+1) == '_'){
280 strcpy(p, "SA_");
281 p += 3;
282 s += 2;
283 break;
286 /* standard name */
287 if(*s == 't'){
288 strcpy(p, "std::");
289 p += 5;
290 s++;
291 if(!gccname(&s, &p, state))
292 return 0;
293 }else if((t = chartabsearch(stdnames, *s)) != nil){
294 strcpy(p, t);
295 p += strlen(p);
296 s++;
297 }else{
298 strcpy(p, "std::");
299 p += 5;
300 *p++ = *s++;
302 break;
304 case 'T': /* previously-seen type??? T0_ also T_*/
305 t = s;
306 for(; *s != '_'; s++){
307 if(*s == 0){
308 s = t;
309 goto bad;
312 s++;
313 memmove(p, t, s-t);
314 p += s-t;
315 break;
318 suffix:
319 if(*s == 'I'){
320 /* template suffix */
321 nstate.nname = 0;
322 *p++ = '<';
323 s++;
324 while(*s != 'E'){
325 if(!gccname(&s, &p, &nstate)){
326 fprint(2, "bad name in template: %s\n", s);
327 return 0;
329 *p++ = ',';
331 *(p-1) = '>';
332 s++;
335 *ps = s;
336 *pp = p;
337 return 1;