diff options
author | rsc <devnull@localhost> | 2005-11-28 00:40:04 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2005-11-28 00:40:04 +0000 |
commit | 7d6f5677c1ce9bdce141dea16364478216d0f4cc (patch) | |
tree | 03daffa36e5693eed2573b05816a0b1bf6a3db82 /src/libmach/manglegcc3.c | |
parent | 689be541258e9e701a600d6bd2fc3e5241726867 (diff) | |
download | plan9port-7d6f5677c1ce9bdce141dea16364478216d0f4cc.tar.gz plan9port-7d6f5677c1ce9bdce141dea16364478216d0f4cc.tar.bz2 plan9port-7d6f5677c1ce9bdce141dea16364478216d0f4cc.zip |
name mangling, process control
Diffstat (limited to 'src/libmach/manglegcc3.c')
-rw-r--r-- | src/libmach/manglegcc3.c | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/src/libmach/manglegcc3.c b/src/libmach/manglegcc3.c new file mode 100644 index 00000000..eca26eb1 --- /dev/null +++ b/src/libmach/manglegcc3.c @@ -0,0 +1,339 @@ +/* + * gcc3 name demangler. + */ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> + +typedef struct Chartab Chartab; +struct Chartab +{ + char c; + char *s; +}; + +static char* +chartabsearch(Chartab *ct, int c) +{ + for(; ct->c; ct++) + if(ct->c == c) + return ct->s; + return nil; +} + +typedef struct Gccstate Gccstate; +struct Gccstate +{ + char *name[128]; + int nname; +}; +static int gccname(char**, char**, Gccstate*); +char* +demanglegcc3(char *s, char *buf) +{ + char *p, *os; + Gccstate state; + + state.nname = 0; + os = s; + /* mangled names always start with _Z */ + if(s[0] != '_' || s[1] != 'Z') + return s; + s += 2; + + p = buf; + if(!gccname(&s, &p, &state)){ + if(strchr(os, '@') == nil) + fprint(2, "demangle: %s\n"); + return os; + } + if(*s){ + /* the rest of the name is the argument types */ + *p++ = '('; + while(*s != 0 && gccname(&s, &p, &state)) + *p++ = ','; + if(*(p-1) == ',') + p--; + *p++ = ')'; + } + *p = 0; + return buf; +} + +static Chartab stdnames[] = +{ + 'a', "std::allocator", + 'b', "std::basic_string", + 'd', "std::iostream", + 'i', "std::istream", + 'o', "std::ostream", + 's', "std::string", + 0, 0 +}; + +static Chartab typetab[] = +{ + 'b', "bool", + 'c', "char", + 'd', "double", + 'i', "int", + 'j', "uint", + 'v', "void", + 0, 0 +}; + +static struct { + char *shrt; + char *actual; + char *lng; +} operators[] = +{ + "aN", "&=", "andeq", + "aS", "=", "assign", + "aa", "&&", "andand", + "ad", "&", "and", + "an", "&", "and", + "cl", "()", "construct", + "cm", ",", "comma", + "co", "~", "twiddle", + "dV", "/=", "diveq", + "da", "delete[]", "deletearray", + "de", "*", "star", + "dl", "delete", "delete", + "dv", "/", "div", + "eO", "^=", "xoreq", + "eo", "^", "xor", + "eq", "==", "eq", + "ge", ">=", "geq", + "gt", ">", "gt", + "ix", "[]", "index", + "IS", "<<=", "lsheq", + "le", "<=", "leq", + "ls", "<<", "lsh", + "lt", "<", "lt", + "ml", "-=", "subeq", + "mL", "*=", "muleq", + "mi", "-", "sub", + "mI", "*", "mul", + "mm", "--", "dec", + "na", "new[]", "newarray", + "ne", "!=", "neq", + "ng", "-", "neg", + "nt", "!", "not", + "nw", "new", "new", + "oR", "|=", "oreq", + "oo", "||", "oror", + "or", "|", "or", + "pL", "+=", "addeq", + "pl", "+", "add", + "pm", "->*", "pointstoderef", + "pp", "++", "inc", + "ps", "+", "pos", + "pt", "->", "pointsto", + "qu", "?", "question", + "rM", "%=", "modeq", + "rS", ">>=", "rsheq", + "rm", "%", "mod", + "rs", ">>", "rsh", + "st", "sizeof", "sizeoftype", + "sz", "sizeof", "sizeofexpr", + + 0,0,0 +}; + +/* + * Pick apart the next mangled name section. + * Names and types are treated as the same. + * Let's see how far we can go before that becomes a problem. + */ +static int +gccname(char **ps, char **pp, Gccstate *state) +{ + int i, n; + char *os, *s, *t, *p; + Gccstate nstate; + + s = *ps; + os = s; + p = *pp; + +/* print("\tgccname: %s\n", s); */ + + /* overloaded operators */ + for(i=0; operators[i].shrt; i++){ + if(memcmp(operators[i].shrt, s, 2) == 0){ + strcpy(p, "operator$"); + strcat(p, operators[i].lng); + p += strlen(p); + s += 2; + goto suffix; + } + } + + /* basic types */ + if((t = chartabsearch(typetab, *s)) != nil){ + s++; + strcpy(p, t); + p += strlen(t); + goto suffix; + } + + switch(*s){ + default: + bad: + fprint(2, "bad name: %s\n", s); + return 0; + + case '1': case '2': case '3': case '4': /* name length */ + case '5': case '6': case '7': case '8': case '9': + n = strtol(s, &s, 10); + memmove(p, s, n); + p += n; + s += n; + break; + + case 'C': /* C1: constructor? */ + strtol(s+1, &s, 10); + strcpy(p, "constructor"); + p += strlen(p); + break; + + case 'D': /* D1: destructor? */ + strtol(s+1, &s, 10); + strcpy(p, "destructor"); + p += strlen(p); + break; + + case 'K': /* const */ + s++; + strcpy(p, "const "); + p += strlen(p); + if(!gccname(&s, &p, state)) + return 0; + break; + + case 'L': /* default value */ + t = s; + s++; + if(!gccname(&s, &p, state)) + return 0; + if(!isdigit((uchar)*s)){ + fprint(2, "bad value: %s\n", t); + return 0; + } + n = strtol(s, &s, 10); + if(*s != 'E'){ + fprint(2, "bad value2: %s\n", t); + return 0; + } + sprint(p, "=%d", n); + p += strlen(p); + s++; + break; + + case 'N': /* hierarchical name */ + s++; + while(*s != 'E'){ + if(!gccname(&s, &p, state)){ + fprint(2, "bad name in hierarchy: %s in %s\n", s, os); + return 0; + } + strcpy(p, "::"); + p += 2; + } + p -= 2; + s++; + break; + + case 'P': /* pointer to */ + s++; + if(!gccname(&s, &p, state)) + return 0; + *p++ = '*'; + break; + + case 'R': /* reference to */ + s++; + if(!gccname(&s, &p, state)) + return 0; + *p++ = '&'; + break; + + case 'S': /* standard or previously-seen name */ + s++; + if('0' <= *s && *s <= '9'){ + /* previously seen */ + t = s-1; + n = strtol(s, &s, 10); + if(*s != '_'){ + fprint(2, "bad S: %s\n", t); + return 0; + } + s++; + sprint(p, "S%d_", n); + p += strlen(p); + break; + } + /* SA_ ??? */ + if(*s == 'A' && *(s+1) == '_'){ + strcpy(p, "SA_"); + p += 3; + s += 2; + break; + } + + /* standard name */ + if(*s == 't'){ + strcpy(p, "std::"); + p += 5; + s++; + if(!gccname(&s, &p, state)) + return 0; + }else if((t = chartabsearch(stdnames, *s)) != nil){ + strcpy(p, t); + p += strlen(p); + s++; + }else{ + strcpy(p, "std::"); + p += 5; + *p++ = *s++; + } + break; + + case 'T': /* previously-seen type??? T0_ also T_*/ + t = s; + for(; *s != '_'; s++){ + if(*s == 0){ + s = t; + goto bad; + } + } + s++; + memmove(p, t, s-t); + p += s-t; + break; + } + +suffix: + if(*s == 'I'){ + /* template suffix */ + nstate.nname = 0; + *p++ = '<'; + s++; + while(*s != 'E'){ + if(!gccname(&s, &p, &nstate)){ + fprint(2, "bad name in template: %s\n", s); + return 0; + } + *p++ = ','; + } + *(p-1) = '>'; + s++; + } + + *ps = s; + *pp = p; + return 1; +} + |