URI:
       tmanglegcc3.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tmanglegcc3.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 }