// Based on demangle.d: // by James Dunne // Jan. 5 2005 // Placed into the Public Domain. // updated by teqDruid // updated by afb #include #include #include #include #include "d-demangle.h" // extracts a series of dot-separated identifiers: static char *extractidentifiers(char* output, const char **mangled) { char *name, *end; long int i; int first = 1; name = output; while (isdigit(**mangled)) { // Get the length as an integer: i = strtol(*mangled, &end, 10); if (i == 0 || i == LONG_MAX || i == LONG_MIN) return NULL; if (strlen(end) < i) { (*mangled) += strlen(end); return NULL; } *mangled = (const char *) end; if (!first) *output++ = '.'; // Extract the identifier memcpy(output, *mangled, i); (*mangled) += i; output += i; // Dot-separate after this: first = 0; } // Return the identifier string: return name; } // extracts a single definition (like a parameter) static char *extracttypeinfo(char *dest, const char **id) { if (**id == '\0') return NULL; // Extract the type info: switch (*(*id)++) { // array, static array, dynamic array: case 'A': case 'G': case 'H': if (extracttypeinfo(dest, id) == NULL) return NULL; strcat(dest, "[]"); return dest; // pointer: case 'P': if (extracttypeinfo(dest, id) == NULL) return NULL; strcat(dest, "*"); return dest; // reference: case 'R': if (extracttypeinfo(dest, id) == NULL) return NULL; strcat(dest, "&"); return dest; // return value: case 'Z': return extracttypeinfo(dest, id); // out: case 'J': strcat(dest, "out "); return extracttypeinfo(dest, id); // inout: case 'K': strcat(dest, "inout "); return extracttypeinfo(dest, id); // enum: case 'E': // typedef: case 'T': // delegate: case 'D': // class: case 'C': // struct: case 'S': // identifier: case 'I': return extractidentifiers(dest, id); // basic types: case 'n': strcat(dest, "none"); return dest; // ever used? case 'v': strcat(dest, "void"); return dest; case 'g': strcat(dest, "byte"); return dest; case 'h': strcat(dest, "ubyte"); return dest; case 's': strcat(dest, "short"); return dest; case 't': strcat(dest, "ushort"); return dest; case 'i': strcat(dest, "int"); return dest; case 'k': strcat(dest, "uint"); return dest; case 'l': strcat(dest, "long"); return dest; case 'm': strcat(dest, "ulong"); return dest; case 'f': strcat(dest, "float"); return dest; case 'd': strcat(dest, "double"); return dest; case 'e': strcat(dest, "real"); return dest; // imaginary and complex: case 'o': strcat(dest, "ifloat"); return dest; case 'p': strcat(dest, "idouble"); return dest; case 'j': strcat(dest, "ireal"); return dest; case 'q': strcat(dest, "cfloat"); return dest; case 'r': strcat(dest, "cdouble"); return dest; case 'c': strcat(dest, "creal"); return dest; // other types: case 'b': strcat(dest, "bit"); return dest; case 'a': strcat(dest, "char"); return dest; case 'u': strcat(dest, "wchar"); return dest; case 'w': strcat(dest, "dchar"); return dest; // typeinfo, error, instance: case '@': return extractidentifiers(dest, id); // BUG: is this right? default: strcat(dest, "unknown"); return dest; } } #define EXTRA_LENGTH 20 char* d_demangle(const char* mangled) { char *output; int len; if (mangled == NULL) return NULL; len = strlen(mangled)+EXTRA_LENGTH; output = calloc(len,sizeof(char)); if (output == NULL) return NULL; // D linkage: if (mangled == strstr(mangled, "_D")) { char *name; mangled += 2; // is it main? if (strcmp(mangled, "main") == 0) { // aww that's easy: return strdup("int main(char[][])"); } name = calloc(len,sizeof(char)); if (name == NULL) { free(output); return NULL; } // Parse the collection of identifiers: extractidentifiers(name, &mangled); // function: if (*mangled == 'F' && name != NULL) { char *params, *param; int first; params = calloc(len,sizeof(char)); if (params == NULL) { free(output); free(name); return NULL; } // extract all the parameters: mangled++; first = 1; param = params; while (*mangled != '\0') { if (*mangled == 'Z') break; if (!first) { strcat(params, ", "); param += 2; } extracttypeinfo(param, &mangled); param += strlen(param); first = 0; } // extract the return type: extracttypeinfo(output, &mangled); strcat(output, " "); strcat(output, name); strcat(output, "("); strcat(output, params); strcat(output, ")"); free(name); free(params); } else { // should always be a function with _D linkage?!?! free(name); free(output); return NULL; } // Check the type: } else if (mangled == strstr(mangled, "_Class_")) { mangled += 7; strcpy(output, "class "); extractidentifiers(output + 6, &mangled); } else if (mangled == strstr(mangled, "_init_")) { mangled += 6; strcpy(output, "init "); extractidentifiers(output + 5, &mangled); } else if (mangled == strstr(mangled, "_vtbl_")) { mangled += 6; strcpy(output, "vtbl "); extractidentifiers(output + 5, &mangled); } else if (mangled == strstr(mangled, "_modctor_")) { mangled += 9; strcpy(output, "ctor "); extractidentifiers(output + 5, &mangled); } else if (mangled == strstr(mangled, "_moddtor_")) { mangled += 9; strcpy(output, "dtor "); extractidentifiers(output + 5, &mangled); } else if (mangled == strstr(mangled, "_ModuleInfo_")) { mangled += 12; strcpy(output, "module "); extractidentifiers(output + 7, &mangled); } else { free(output); return NULL; } return output; }