private import std.cstream; private import std.regexp; private import std.string; private import std.ctype; private import std.conv; class Demangle { this() { simpleMangle['v'] = "void"; simpleMangle['g'] = "byte"; simpleMangle['h'] = "ubyte"; simpleMangle['s'] = "short"; simpleMangle['t'] = "ushort"; simpleMangle['i'] = "int"; simpleMangle['k'] = "uint"; simpleMangle['l'] = "long"; simpleMangle['m'] = "ulong"; simpleMangle['f'] = "float"; simpleMangle['d'] = "double"; simpleMangle['e'] = "real"; simpleMangle['o'] = "ifloat"; simpleMangle['p'] = "idouble"; simpleMangle['j'] = "ireal"; simpleMangle['q'] = "cfloat"; simpleMangle['r'] = "cdouble"; simpleMangle['c'] = "creal"; simpleMangle['b'] = "bit"; simpleMangle['a'] = "char"; simpleMangle['u'] = "wchar"; simpleMangle['w'] = "dchar"; simpleMangle['@'] = "???ERROR???"; } void run(Stream ins, Stream outs) { // char[] all = ins.toString(); char[] all = ""; try { int c; while ((c = ins.getc()) != char.init) { all ~= cast(char)c; } } catch (Error e) {} char[][] lines = std.string.split(all, "\n"); foreach (char[] line; lines) { for (int i = 0; i < cast(int)line.length-1; i++) { if (i+2 < line.length && line[i..i+2] == `_D` && (i == 0 || !issym(line[i-1]))) { int j; for (j = i+2; j < line.length; j++) { if (!issym(line[j])) break; } int end = 0; char[] d = demangle(line[i+2..j], end); line = line[0..i] ~ d ~ line[j..line.length]; } if (i+7 < line.length && line[i..i+7] == `_Class_` && (i == 0 || !issym(line[i-1]))) { int j; for (j = i+7; j < line.length; j++) { if (!issym(line[j])) break; } int end = 0; char[] d = demangle(line[i+7..j], end); line = line[0..i] ~ "class " ~ d ~ line[j..line.length]; } } outs.writeLine(line); } } char[] demangle(char[] sym, inout int i) { if (sym.length > i+2 && sym[i..i+2] == "_D") i += 2; char[][] names; while (i < sym.length && std.ctype.isdigit(sym[i])) { int num = getNum(sym, i); char[] now = sym[i..i+num]; if (now == "__anonymous") { } else { // @@@ is it ok? int sep = std.string.rfind(now, "_"); if (sep > 0) { try { int dummy = 0; char[] type = demangle(now[sep+1..now.length], dummy); now = now[0..sep] ~ "!(" ~ type ~ ")"; } catch (Object o) {} } names ~= now; } i += num; } char[] name = join(names, "."); if (sym.length == i) return name; char[] type; TYPE: switch (sym[i]) { case 'A': { // array i++; char[] t = demangle(sym, i); type = t ~ "[]"; break TYPE; } case 'G': { // static array i++; char[] num = getNumStr(sym, i); char[] t = demangle(sym, i); type = t ~ "[" ~ num ~ "]"; break TYPE; } case 'H': { // assoc array i++; char[] t1 = demangle(sym, i); char[] t2 = demangle(sym, i); type = t2 ~ "[" ~ t1 ~ "]"; break TYPE; } case 'P': { // pointer i++; char[] t = demangle(sym, i); type = t ~ "*"; break TYPE; } case 'R': { // reference assert(false); i++; char[] t = demangle(sym, i); type = "inout " ~ t; break TYPE; } case 'F': case 'U': { // (static) function bool isStatic = sym[i] == 'U'; i++; char[][] args; bool nowRet = false; while (1) { char[] t = demangle(sym, i); if (nowRet) { if (isStatic) t = "static " ~ t; return t ~ " " ~ name ~ "(" ~ join(args, ",") ~ ")"; } if (i == sym.length) { args ~= "..."; if (isStatic) t = "static " ~ t; return t ~ " " ~ name ~ "(" ~ join(args, ",") ~ ")"; } args ~= t; if (sym[i] == 'Z') { nowRet = true; i++; } if (sym[i] == 'Y') { i++; } } assert(false); } case 'I': { // @@@ident? assert(false); } case 'C': { // class i++; char[] t = demangle(sym, i); // @@@ type = "class " ~ t; break TYPE; } case 'S': { // struct i++; char[] t = demangle(sym, i); // @@@ type = "struct " ~ t; break TYPE; } case 'E': { // enum i++; char[] t = demangle(sym, i); // @@@ type = "enum " ~ t; break TYPE; } case 'T': { // typedef i++; char[] t = demangle(sym, i); // @@@ type = "typedef " ~ t; break TYPE; } case 'D': { // delegate // @@@ it should be "int delegate()", not "delegate int ()" i++; char[] t = demangle(sym, i); type = "delegate " ~ t; break TYPE; } case 'K': { // inout i++; char[] t = demangle(sym, i); type = "inout " ~ t; break TYPE; } case 'J': { // out i++; char[] t = demangle(sym, i); type = "out " ~ t; break TYPE; } case 'Y': case 'Z': { // separater break TYPE; } default: if (sym[i] in simpleMangle) { type = simpleMangle[sym[i]]; i++; break TYPE; } assert(false); break TYPE; } if (type) { if (name && name.length > 0) { return type ~ " " ~ name; } else { return type; } } else { return name; } } private: bool issym(char c) { return isalnum(c) || c == '_'; } int getNum(char[] str, inout int i) { return toInt(getNumStr(str, i)); } char[] getNumStr(char[] str, inout int i) { char[] numStr = ""; while (std.ctype.isdigit(str[i])) { numStr ~= str[i]; i++; } return numStr; } private: char[][char] simpleMangle; } version (DFILT_NOMAIN) { } else { int main(char[][] args) { Demangle d = new Demangle(); d.run(din, dout); return 0; } }