plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

manglegcc3.c (5672B)


      1 /*
      2  * gcc3 name demangler.
      3  */
      4 #include <u.h>
      5 #include <libc.h>
      6 #include <bio.h>
      7 #include <mach.h>
      8 
      9 typedef struct Chartab Chartab;
     10 struct Chartab
     11 {
     12 	char c;
     13 	char *s;
     14 };
     15 
     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 }
     24 
     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;
     37 
     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;
     44 
     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 }
     63 
     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 };
     74 
     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 };
     85 
     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",
    141 
    142 	0,0,0
    143 };
    144 
    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)
    152 {
    153 	int i, n;
    154 	char *os, *s, *t, *p;
    155 	Gccstate nstate;
    156 
    157 	s = *ps;
    158 	os = s;
    159 	p = *pp;
    160 
    161 /*	print("\tgccname: %s\n", s); */
    162 
    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;
    171 		}
    172 	}
    173 
    174 	/* basic types */
    175 	if((t = chartabsearch(typetab, *s)) != nil){
    176 		s++;
    177 		strcpy(p, t);
    178 		p += strlen(t);
    179 		goto suffix;
    180 	}
    181 
    182 	switch(*s){
    183 	default:
    184 	bad:
    185 		fprint(2, "bad name: %s\n", s);
    186 		return 0;
    187 
    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;
    195 
    196 	case 'C':	/* C1: constructor? */
    197 		strtol(s+1, &s, 10);
    198 		strcpy(p, "constructor");
    199 		p += strlen(p);
    200 		break;
    201 
    202 	case 'D':	/* D1: destructor? */
    203 		strtol(s+1, &s, 10);
    204 		strcpy(p, "destructor");
    205 		p += strlen(p);
    206 		break;
    207 
    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;
    215 
    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;
    224 		}
    225 		n = strtol(s, &s, 10);
    226 		if(*s != 'E'){
    227 			fprint(2, "bad value2: %s\n", t);
    228 			return 0;
    229 		}
    230 		sprint(p, "=%d", n);
    231 		p += strlen(p);
    232 		s++;
    233 		break;
    234 
    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;
    241 			}
    242 			strcpy(p, "::");
    243 			p += 2;
    244 		}
    245 		p -= 2;
    246 		s++;
    247 		break;
    248 
    249 	case 'P':	/* pointer to */
    250 		s++;
    251 		if(!gccname(&s, &p, state))
    252 			return 0;
    253 		*p++ = '*';
    254 		break;
    255 
    256 	case 'R':	/* reference to */
    257 		s++;
    258 		if(!gccname(&s, &p, state))
    259 			return 0;
    260 		*p++ = '&';
    261 		break;
    262 
    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;
    272 			}
    273 			s++;
    274 			sprint(p, "S%d_", n);
    275 			p += strlen(p);
    276 			break;
    277 		}
    278 		/* SA_ ??? */
    279 		if(*s == 'A' && *(s+1) == '_'){
    280 			strcpy(p, "SA_");
    281 			p += 3;
    282 			s += 2;
    283 			break;
    284 		}
    285 
    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++;
    301 		}
    302 		break;
    303 
    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;
    310 			}
    311 		}
    312 		s++;
    313 		memmove(p, t, s-t);
    314 		p += s-t;
    315 		break;
    316 	}
    317 
    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;
    328 			}
    329 			*p++ = ',';
    330 		}
    331 		*(p-1) = '>';
    332 		s++;
    333 	}
    334 
    335 	*ps = s;
    336 	*pp = p;
    337 	return 1;
    338 }