4 * gcc2 follows the C++ Annotated Reference Manual section 7.2.1
5 * name mangling description with a few changes.
6 * See gpcompare.texi, gxxint_15.html in this directory for the changes.
10 * renaming of operator functions
15 _10CycleTimer.cycles_per_ms_ => CycleTimer::cycles_per_ms_
26 typedef struct Chartab Chartab;
34 chartabsearch(Chartab *ct, int c)
42 static Chartab typetab[] =
60 static Chartab modifiertab[] =
63 'S', "signed", /* means static for member functions */
67 'G', "garbage", /* no idea what this is */
71 static char constructor[] = "constructor";
72 static char destructor[] = "destructor";
73 static char gconstructor[] = "$gconstructor"; /* global destructor */
74 static char gdestructor[] = "$gdestructor"; /* global destructor */
76 static char manglestarts[] = "123456789CFHQSUVt";
78 static int gccname(char**, char**);
79 static char *demanglegcc2a(char*, char*);
80 static char *demanglegcc2b(char*, char*);
81 static char *demanglegcc2c(char*, char*);
82 static int gccnumber(char**, int*, int);
85 demanglegcc2(char *s, char *buf)
87 char *name, *os, *p, *t;
92 * Pick off some cases that seem not to fit the pattern.
94 if((t = demanglegcc2a(s, buf)) != nil)
96 if((t = demanglegcc2b(s, buf)) != nil)
98 if((t = demanglegcc2c(s, buf)) != nil)
102 * First, figure out whether this is a mangled name.
103 * The name begins with a short version of the name, then __.
104 * Of course, some C names begin with __ too, so the ultimate
105 * test is whether what follows __ looks reasonable.
106 * We use a test on the first letter instead.
108 * Constructors have no name - they begin __ (double underscore).
109 * Destructors break the rule - they begin _._ (underscore, dot, underscore).
113 if(memcmp(s, "_._", 3) == 0){
116 namelen = strlen(name);
118 }else if(memcmp(s, "_GLOBAL_.D.__", 13) == 0){
121 namelen = strlen(name);
123 }else if(memcmp(s, "_GLOBAL_.D._", 12) == 0){
126 namelen = strlen(name);
128 }else if(memcmp(s, "_GLOBAL_.I.__", 13) == 0){
131 namelen = strlen(name);
133 }else if(memcmp(s, "_GLOBAL_.I._", 12) == 0){
136 namelen = strlen(name);
139 t = strstr(os, "__");
144 if(strchr(manglestarts, *(s+2)))
146 }while((t = strstr(s+1, "__")) != nil);
153 namelen = strlen(name);
159 * Now s points at the mangled crap (maybe).
160 * and name is the final element of the name.
162 if(strchr(manglestarts, *s) == nil)
167 /* global function, no extra name pieces, just types */
170 /* parse extra name pieces */
171 if(!gccname(&s, &p)){
173 fprint(2, "parsename %s: %r\n", s);
177 /* if we have a constructor or destructor, try to use the C++ name */
179 if(name == constructor || name == destructor){
181 t = strrchr(buf, ':');
190 namelen = strlen(t)-2;
191 if(name == destructor)
196 if(p >= buf+2 && memcmp(p-2, "::", 2) == 0 && *(p-3) == ')')
198 memmove(p, name, namelen);
202 /* might be from above, or might follow name pieces */
207 /* the rest of the name is argument types - could skip this */
210 while(*s != 0 && *s != '_'){
221 /* return type (left over from H) */
229 * _10CycleTimer.cycles_per_ms_ => CycleTimer::cycles_per_ms_
230 * _t12basic_string3ZcZt11char_traits1ZcZt9allocator1Zc.npos
231 * (maybe the funny syntax means they are private)
234 demanglegcc2a(char *s, char *buf)
238 if(*s != '_' || strchr(manglestarts, *(s+1)) == nil)
254 * _tfb => type info for bool
255 * __vt_7ostream => vtbl for ostream
258 demanglegcc2b(char *s, char *buf)
263 if(memcmp(s, "__ti", 4) == 0){
266 }else if(memcmp(s, "__tf", 4) == 0){
269 }else if(memcmp(s, "__vt_", 5) == 0){
277 if(*s == 0 || !gccname(&s, &p))
281 if(*s != '.' && *s != '$')
294 * __thunk_176__._Q210LogMessage9LogStream => thunk (offset -176) for LogMessage::LogStream
297 demanglegcc2c(char *s, char *buf)
302 if(memcmp(s, "__thunk_", 8) != 0)
305 if(!gccnumber(&s, &n, 1))
307 if(memcmp(s, "__._", 4) != 0) /* might as well be morse code */
313 strcpy(p, "::$thunk");
318 * Parse a number, a non-empty run of digits.
319 * If many==0, then only one digit is used, even
320 * if it is followed by more. When we need a big
321 * number in a one-digit slot, it gets bracketed by underscores.
324 gccnumber(char **ps, int *pn, int many)
327 int n, eatunderscore;
331 if(!many && *s == '_'){
336 if(!isdigit((uchar)*s)){
338 werrstr("bad number %.20s", *ps);
342 n = strtol(s, &s, 10);
356 * Pick apart the next mangled name section.
357 * Names and types are treated as the same.
358 * Let's see how far we can go before that becomes a problem.
361 gccname(char **ps, char **pp)
364 char *os, *s, *t, *p, *p0, *p1;
370 /* print("\tgccname: %s\n", s); */
373 if((t = chartabsearch(typetab, *s)) != nil){
381 if((t = chartabsearch(modifiertab, *s)) != nil){
386 * These don't end up in the right place
387 * and i don't care anyway
388 * (AssertHeld__C17ReaderWriterMutex)
402 fprint(2, "gccname: %s (%s)\n", os, s);
403 werrstr("bad name %.20s", s);
406 case '1': case '2': case '3': case '4': /* length-prefixed string */
407 case '5': case '6': case '7': case '8': case '9':
408 if(!gccnumber(&s, &n, 1))
415 case 'A': /* array */
418 if(!gccnumber(&s, &n, 1))
421 werrstr("bad array %.20s", t);
425 sprint(p, "array[%d] ", n);
429 case 'F': /* function */
435 while(*s && *s != '_')
439 werrstr("unexpected end in function: %s", t);
451 case 'H': /* template specialization */
452 if(memcmp(s-2, "__", 2) != 0)
453 fprint(2, "wow: %s\n", s-2);
456 if(!gccnumber(&s, &n, 0))
459 /* template arguments */
463 if(*s == 'Z'){ /* argument is a type, not value */
470 if(!gccnumber(&s, &m, 1)) /* gccnumber: 1 or 0? */
480 werrstr("bad template %s", t);
486 * Can't seem to tell difference between a qualifying name
487 * and arguments. Not sure which is which. It appears that if
488 * you get a name, use it, otherwise look for types.
489 * The G type qualifier appears to have no effect other than
490 * turning an ambiguous name into a definite type.
492 * SetFlag__H1Zb_P15FlagSettingMode_v
493 * => void SetFlag<bool>(FlagSettingMode *)
494 * SetFlag__H1Zb_15FlagSettingMode_v
495 * => void FlagSettingMode::SetFlag<bool>()
496 * SetFlag__H1Zb_G15FlagSettingMode_v
497 * => void SetFlag<bool>(FlagSettingMode)
499 if(strchr("ACFGPRSUVX", *s)){
505 if(*s == 0 || !gccname(&s, &p)){
506 werrstr("bad H args: %s", t);
519 * Need to do some rearrangement of <> () and names here.
520 * Doesn't matter since we strip out the <> and () anyway.
524 case 'M': /* M1S: pointer to member */
525 if(*(s+1) != '1' || *(s+2) != 'S')
534 case 'N': /* multiply-repeated type */
536 if(!gccnumber(&s, &n, 0) || !gccnumber(&s, &m, 0))
538 sprint(p, "T%dx%d", m, n);
542 case 'P': /* pointer */
550 case 'Q': /* qualified name */
552 if(!gccnumber(&s, &n, 0))
555 if(!gccname(&s, &p)){
556 werrstr("in hierarchy: %r");
566 case 'R': /* reference */
574 case 't': /* class template instantiation */
575 /* should share code with case 'H' */
580 if(!gccnumber(&s, &n, 0))
583 /* template arguments */
587 if(*s == 'Z'){ /* argument is a type, not value */
594 if(!gccnumber(&s, &m, 1)) /* gccnumber: 1 or 0? */
605 case 'T': /* once-repeated type */
607 if(!gccnumber(&s, &n, 0))
613 case 'X': /* type parameter in 'H' */
614 if(!isdigit((uchar)*(s+1)) || !isdigit((uchar)*(s+2)))