2022-12-29 12:32:55 +00:00
|
|
|
#include "compiler/Unmangle.h"
|
|
|
|
|
|
|
|
typedef struct UnmangleBuffer {
|
|
|
|
char *buf;
|
|
|
|
size_t remaining;
|
|
|
|
} UnmangleBuffer;
|
|
|
|
|
|
|
|
// forward decls
|
|
|
|
static const char *Unmangle_Type(jmp_buf errorbuf, UnmangleBuffer *ub, const char *p);
|
|
|
|
|
|
|
|
static void Unmangle_Error(jmp_buf errorbuf) {
|
|
|
|
longjmp(errorbuf, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void Unmangle_BufferInit(UnmangleBuffer *ub, char *buf, size_t size) {
|
|
|
|
ub->buf = buf;
|
|
|
|
ub->remaining = size - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void Unmangle_BufferAppendChar(UnmangleBuffer *ub, char ch) {
|
|
|
|
if (ub && ub->remaining) {
|
|
|
|
*(ub->buf++) = ch;
|
|
|
|
ub->remaining--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void Unmangle_BufferAppendString(UnmangleBuffer *ub, const char *str) {
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
if (ub) {
|
|
|
|
len = strlen(str);
|
|
|
|
if (ub->remaining < len)
|
|
|
|
len = ub->remaining;
|
|
|
|
|
|
|
|
memcpy(ub->buf, str, len);
|
|
|
|
ub->buf += len;
|
|
|
|
ub->remaining -= len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void Unmangle_BufferTerminate(UnmangleBuffer *ub) {
|
|
|
|
ub->buf[0] = 0;
|
|
|
|
ub->remaining = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *Unmangle_TemplateParams(jmp_buf errorbuf, UnmangleBuffer *ub, const char *p) {
|
|
|
|
const char *p2;
|
|
|
|
|
|
|
|
Unmangle_BufferAppendChar(ub, '<');
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
switch (*p) {
|
|
|
|
case '&':
|
|
|
|
case '=':
|
|
|
|
if (*(p++) == '&')
|
|
|
|
Unmangle_BufferAppendChar(ub, '&');
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
switch (*p) {
|
|
|
|
case ',':
|
|
|
|
case '>':
|
|
|
|
break;
|
|
|
|
case 0:
|
|
|
|
Unmangle_Error(errorbuf);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Unmangle_BufferAppendChar(ub, *(p++));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '0':
|
|
|
|
case '1':
|
|
|
|
case '2':
|
|
|
|
case '3':
|
|
|
|
case '4':
|
|
|
|
case '5':
|
|
|
|
case '6':
|
|
|
|
case '7':
|
|
|
|
case '8':
|
|
|
|
case '9':
|
|
|
|
p2 = p + 1;
|
|
|
|
while (1) {
|
|
|
|
if (*p2 == 0)
|
|
|
|
Unmangle_Error(errorbuf);
|
|
|
|
|
|
|
|
if (*p2 == ',' || *p2 == '>') {
|
|
|
|
do {
|
|
|
|
Unmangle_BufferAppendChar(ub, *(p++));
|
|
|
|
} while (*p != '>' && *p != ',');
|
|
|
|
break;
|
|
|
|
} else if (!(*p2 >= '0' && *p2 <= '9')) {
|
|
|
|
p = Unmangle_Type(errorbuf, ub, p);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
p2++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
p = Unmangle_Type(errorbuf, ub, p);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*p == '>')
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (*(p++) != ',')
|
|
|
|
Unmangle_Error(errorbuf);
|
|
|
|
|
|
|
|
Unmangle_BufferAppendString(ub, ", ");
|
|
|
|
}
|
|
|
|
|
|
|
|
Unmangle_BufferAppendChar(ub, '>');
|
|
|
|
return p + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *Unmangle_SpecialName(jmp_buf errorbuf, UnmangleBuffer *ub, const char *p) {
|
|
|
|
const char *what;
|
|
|
|
Boolean flag = 0;
|
|
|
|
|
|
|
|
switch (*(p++)) {
|
|
|
|
case 'a':
|
|
|
|
switch (*(p++)) {
|
|
|
|
case 'a':
|
|
|
|
switch (*(p++)) {
|
|
|
|
case '_':
|
|
|
|
what = "operator &&";
|
|
|
|
p--;
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
what = "operator &=";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
switch (*(p++)) {
|
|
|
|
case '_':
|
|
|
|
what = "operator &";
|
|
|
|
p--;
|
|
|
|
break;
|
|
|
|
case 'v':
|
|
|
|
what = "operator /=";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'e':
|
|
|
|
switch (*(p++)) {
|
|
|
|
case 'r':
|
|
|
|
what = "operator ^=";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'l':
|
|
|
|
switch (*(p++)) {
|
|
|
|
case 's':
|
|
|
|
what = "operator <<=";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
switch (*(p++)) {
|
|
|
|
case 'd':
|
|
|
|
what = "operator %=";
|
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
what = "operator -=";
|
|
|
|
break;
|
|
|
|
case 'u':
|
|
|
|
what = "operator *=";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'o':
|
|
|
|
switch (*(p++)) {
|
|
|
|
case 'r':
|
|
|
|
what = "operator |=";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
switch (*(p++)) {
|
|
|
|
case 'l':
|
|
|
|
what = "operator +=";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
switch (*(p++)) {
|
|
|
|
case 's':
|
|
|
|
what = "operator >>=";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
what = "operator =";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
switch (*(p++)) {
|
|
|
|
case 'l':
|
|
|
|
what = "operator ()";
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
what = "operator ,";
|
|
|
|
break;
|
|
|
|
case 'o':
|
|
|
|
what = "operator ~";
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
what = "!";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
switch (*(p++)) {
|
|
|
|
case 'l':
|
|
|
|
if (*p == 'a') {
|
|
|
|
what = "operator delete[]";
|
|
|
|
p++;
|
|
|
|
} else {
|
|
|
|
what = "operator delete";
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
what = "~";
|
|
|
|
break;
|
|
|
|
case 'v':
|
|
|
|
what = "operator /";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'e':
|
|
|
|
switch (*(p++)) {
|
|
|
|
case 'q':
|
|
|
|
what = "operator ==";
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
what = "operator ^";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'g':
|
|
|
|
switch (*(p++)) {
|
|
|
|
case 'e':
|
|
|
|
what = "operator >=";
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
what = "operator >";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'l':
|
|
|
|
switch (*(p++)) {
|
|
|
|
case 'e':
|
|
|
|
what = "operator <=";
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
what = "operator <<";
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
what = "operator <";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
switch (*(p++)) {
|
|
|
|
case 'd':
|
|
|
|
what = "operator %";
|
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
what = "operator -";
|
|
|
|
break;
|
|
|
|
case 'l':
|
|
|
|
what = "operator *";
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
what = "operator --";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
switch (*(p++)) {
|
|
|
|
case 'e':
|
|
|
|
what = "operator !=";
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
what = "operator !";
|
|
|
|
break;
|
|
|
|
case 'w':
|
|
|
|
if (*p == 'a') {
|
|
|
|
what = "operator new[]";
|
|
|
|
p++;
|
|
|
|
} else {
|
|
|
|
what = "operator new";
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'o':
|
|
|
|
switch (*(p++)) {
|
|
|
|
case 'r':
|
|
|
|
what = "operator |";
|
|
|
|
break;
|
|
|
|
case 'o':
|
|
|
|
what = "operator ||";
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
Unmangle_BufferAppendString(ub, "operator ");
|
|
|
|
p = Unmangle_Type(errorbuf, ub, p);
|
|
|
|
flag = 1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
switch (*(p++)) {
|
|
|
|
case 'l':
|
|
|
|
what = "operator +";
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
what = "operator ++";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
switch (*(p++)) {
|
|
|
|
case 'f':
|
|
|
|
what = "operator ->";
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
what = "operator >>";
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
what = "operator ->*";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'v':
|
|
|
|
switch (*(p++)) {
|
|
|
|
case 'c':
|
|
|
|
what = "operator []";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!flag) {
|
|
|
|
if (*p) {
|
|
|
|
Unmangle_BufferAppendString(ub, what);
|
|
|
|
if (*p == '<')
|
|
|
|
p = Unmangle_TemplateParams(errorbuf, ub, p + 1);
|
|
|
|
if (!(*(p++) == '_' && *(p++) == '_'))
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!(*(p++) == '_' && *(p++) == '_'))
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Unmangle_BufferTerminate(ub);
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *Unmangle_ClassName(jmp_buf errorbuf, UnmangleBuffer *ub, const char *p, size_t len, Boolean flag) {
|
|
|
|
int ch;
|
|
|
|
const char *p2;
|
|
|
|
|
|
|
|
while (len--) {
|
|
|
|
ch = *(p++);
|
|
|
|
if (!ch)
|
|
|
|
Unmangle_Error(errorbuf);
|
|
|
|
|
|
|
|
if (ch == '<') {
|
|
|
|
p2 = Unmangle_TemplateParams(errorbuf, flag ? ub : NULL, p);
|
|
|
|
len -= (p2 - p);
|
|
|
|
if (len == 0)
|
|
|
|
return p2;
|
|
|
|
Unmangle_Error(errorbuf);
|
|
|
|
} else {
|
|
|
|
Unmangle_BufferAppendChar(ub, ch);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *Unmangle_QClassName(jmp_buf errorbuf, UnmangleBuffer *ub, const char *p, Boolean flag1, Boolean flag2) {
|
|
|
|
const char *lastPiece;
|
|
|
|
size_t len;
|
|
|
|
int i;
|
|
|
|
int ch;
|
|
|
|
int count;
|
|
|
|
|
|
|
|
if (*p == 'Q') {
|
|
|
|
p++;
|
|
|
|
count = *(p++) - '0';
|
|
|
|
if (count < 1 || count > 9)
|
|
|
|
Unmangle_Error(errorbuf);
|
|
|
|
} else {
|
|
|
|
count = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
if (i && ub)
|
|
|
|
Unmangle_BufferAppendString(ub, "::");
|
|
|
|
|
|
|
|
if (*p < '0' || *p > '9')
|
|
|
|
Unmangle_Error(errorbuf);
|
|
|
|
|
|
|
|
len = 0;
|
|
|
|
while ((ch = *p) >= '0' && ch <= '9') {
|
|
|
|
len = len * 10 + ch - '0';
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (len == 0)
|
|
|
|
Unmangle_Error(errorbuf);
|
|
|
|
|
|
|
|
lastPiece = p;
|
|
|
|
p = Unmangle_ClassName(errorbuf, ub, p, len, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flag1 && ub) {
|
|
|
|
if (flag2)
|
|
|
|
Unmangle_BufferAppendString(ub, "::~");
|
|
|
|
else
|
|
|
|
Unmangle_BufferAppendString(ub, "::");
|
|
|
|
Unmangle_ClassName(errorbuf, ub, lastPiece, len, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *Unmangle_Modifiers(UnmangleBuffer *ub, const char *p) {
|
|
|
|
const char *what;
|
|
|
|
Boolean isFirst = 1;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
switch (*p) {
|
|
|
|
case 'U':
|
|
|
|
what = "unsigned";
|
|
|
|
break;
|
|
|
|
case 'C':
|
|
|
|
what = "const";
|
|
|
|
break;
|
|
|
|
case 'V':
|
|
|
|
what = "volatile";
|
|
|
|
break;
|
|
|
|
case 'S':
|
|
|
|
what = "signed";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isFirst)
|
|
|
|
Unmangle_BufferAppendChar(ub, ' ');
|
|
|
|
Unmangle_BufferAppendString(ub, what);
|
|
|
|
|
|
|
|
isFirst = 0;
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *Unmangle_PointerType(jmp_buf errorbuf, UnmangleBuffer *ub, const char *p) {
|
|
|
|
const char *modifiers;
|
|
|
|
|
|
|
|
modifiers = p;
|
|
|
|
p = Unmangle_Modifiers(NULL, p);
|
|
|
|
if (modifiers == p)
|
|
|
|
modifiers = NULL;
|
|
|
|
|
|
|
|
switch (*p) {
|
|
|
|
case 'P':
|
|
|
|
p = Unmangle_PointerType(errorbuf, ub, p + 1);
|
|
|
|
if (ub) {
|
|
|
|
Unmangle_BufferAppendChar(ub, '*');
|
|
|
|
if (modifiers)
|
|
|
|
Unmangle_Modifiers(ub, modifiers);
|
|
|
|
}
|
|
|
|
return p;
|
|
|
|
case 'R':
|
|
|
|
p = Unmangle_PointerType(errorbuf, ub, p + 1);
|
|
|
|
if (ub) {
|
|
|
|
Unmangle_BufferAppendChar(ub, '&');
|
|
|
|
if (modifiers)
|
|
|
|
Unmangle_Modifiers(ub, modifiers);
|
|
|
|
}
|
|
|
|
return p;
|
|
|
|
case 'M':
|
|
|
|
p = Unmangle_QClassName(errorbuf, ub, p + 1, 0, 0);
|
|
|
|
if (ub) {
|
|
|
|
Unmangle_BufferAppendString(ub, "::*");
|
|
|
|
if (modifiers)
|
|
|
|
Unmangle_Modifiers(ub, modifiers);
|
|
|
|
}
|
|
|
|
return p;
|
|
|
|
default:
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *Unmangle_ArrayType(jmp_buf errorbuf, UnmangleBuffer *ub, const char *p, const char *pointer) {
|
|
|
|
const char *digits;
|
|
|
|
|
|
|
|
digits = ++p;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
switch (*(p++)) {
|
|
|
|
case '0':
|
|
|
|
case '1':
|
|
|
|
case '2':
|
|
|
|
case '3':
|
|
|
|
case '4':
|
|
|
|
case '5':
|
|
|
|
case '6':
|
|
|
|
case '7':
|
|
|
|
case '8':
|
|
|
|
case '9':
|
|
|
|
continue;
|
|
|
|
case '_':
|
|
|
|
if (*p == 'A') {
|
|
|
|
p++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Unmangle_Error(errorbuf);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
p = Unmangle_Type(errorbuf, ub, p);
|
|
|
|
|
|
|
|
if (ub) {
|
|
|
|
if (pointer) {
|
|
|
|
Unmangle_BufferAppendString(ub, " (");
|
|
|
|
Unmangle_PointerType(errorbuf, ub, pointer);
|
|
|
|
Unmangle_BufferAppendChar(ub, ')');
|
|
|
|
}
|
|
|
|
|
|
|
|
Unmangle_BufferAppendChar(ub, '[');
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
switch (*digits) {
|
|
|
|
case '0':
|
|
|
|
case '1':
|
|
|
|
case '2':
|
|
|
|
case '3':
|
|
|
|
case '4':
|
|
|
|
case '5':
|
|
|
|
case '6':
|
|
|
|
case '7':
|
|
|
|
case '8':
|
|
|
|
case '9':
|
|
|
|
Unmangle_BufferAppendChar(ub, *(digits++));
|
|
|
|
continue;
|
|
|
|
case '_':
|
|
|
|
if (digits[1] == 'A') {
|
|
|
|
Unmangle_BufferAppendString(ub, "][");
|
|
|
|
digits += 2;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Unmangle_Error(errorbuf);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
Unmangle_BufferAppendChar(ub, ']');
|
|
|
|
}
|
|
|
|
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *Unmangle_FunctionType(jmp_buf errorbuf, UnmangleBuffer *ub, const char *p, const char *pointer) {
|
|
|
|
const char *returnType;
|
|
|
|
|
|
|
|
returnType = ++p;
|
|
|
|
|
|
|
|
while (*p != '_')
|
|
|
|
p = Unmangle_Type(errorbuf, NULL, p);
|
|
|
|
|
|
|
|
p = Unmangle_Type(errorbuf, ub, p + 1);
|
|
|
|
|
|
|
|
if (ub) {
|
|
|
|
if (pointer) {
|
|
|
|
Unmangle_BufferAppendString(ub, " (");
|
|
|
|
Unmangle_PointerType(errorbuf, ub, pointer);
|
|
|
|
Unmangle_BufferAppendChar(ub, ')');
|
|
|
|
}
|
|
|
|
|
|
|
|
Unmangle_BufferAppendChar(ub, '(');
|
|
|
|
|
|
|
|
if (*returnType != '_') {
|
|
|
|
while (1) {
|
|
|
|
returnType = Unmangle_Type(errorbuf, ub, returnType);
|
|
|
|
if (*returnType == '_')
|
|
|
|
break;
|
|
|
|
Unmangle_BufferAppendString(ub, ", ");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Unmangle_BufferAppendChar(ub, ')');
|
|
|
|
}
|
|
|
|
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *Unmangle_Pointer(jmp_buf errorbuf, UnmangleBuffer *ub, const char *p, const char *modifiers, char c) {
|
|
|
|
const char *pointer;
|
|
|
|
const char *tmp;
|
|
|
|
|
|
|
|
pointer = p;
|
|
|
|
tmp = Unmangle_PointerType(errorbuf, NULL, p);
|
|
|
|
switch (*tmp) {
|
|
|
|
case 'A':
|
|
|
|
if (modifiers)
|
|
|
|
pointer = modifiers;
|
|
|
|
return Unmangle_ArrayType(errorbuf, ub, tmp, pointer);
|
|
|
|
case 'F':
|
|
|
|
if (modifiers)
|
|
|
|
pointer = modifiers;
|
|
|
|
return Unmangle_FunctionType(errorbuf, ub, tmp, pointer);
|
|
|
|
default:
|
|
|
|
if (c == 'M') {
|
|
|
|
p = Unmangle_QClassName(errorbuf, NULL, p + 1, 0, 0);
|
|
|
|
p = Unmangle_Type(errorbuf, ub, p);
|
|
|
|
if (ub) {
|
|
|
|
Unmangle_BufferAppendChar(ub, ' ');
|
|
|
|
Unmangle_QClassName(errorbuf, ub, pointer + 1, 0, 0);
|
|
|
|
Unmangle_BufferAppendString(ub, "::*");
|
|
|
|
if (modifiers)
|
|
|
|
Unmangle_Modifiers(ub, modifiers);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
p = Unmangle_Type(errorbuf, ub, p + 1);
|
|
|
|
if (ub) {
|
|
|
|
Unmangle_BufferAppendChar(ub, c);
|
|
|
|
if (modifiers)
|
|
|
|
Unmangle_Modifiers(ub, modifiers);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *Unmangle_Vector(jmp_buf errorbuf, UnmangleBuffer *ub, const char *p, const char *modifiers) {
|
|
|
|
const char *p2 = p + 2;
|
|
|
|
switch (p[1]) {
|
|
|
|
case 'U':
|
|
|
|
switch (p[2]) {
|
|
|
|
case 'c':
|
|
|
|
p2++;
|
|
|
|
Unmangle_BufferAppendString(ub, "vector unsigned char");
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
p2++;
|
|
|
|
Unmangle_BufferAppendString(ub, "vector unsigned short");
|
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
p2++;
|
|
|
|
Unmangle_BufferAppendString(ub, "vector unsigned int");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
Unmangle_BufferAppendString(ub, "vector signed char");
|
|
|
|
break;
|
|
|
|
case 'C':
|
|
|
|
Unmangle_BufferAppendString(ub, "vector bool char");
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
Unmangle_BufferAppendString(ub, "vector signed short");
|
|
|
|
break;
|
|
|
|
case 'S':
|
|
|
|
Unmangle_BufferAppendString(ub, "vector bool short");
|
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
Unmangle_BufferAppendString(ub, "vector signed int");
|
|
|
|
break;
|
|
|
|
case 'I':
|
|
|
|
Unmangle_BufferAppendString(ub, "vector bool int");
|
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
Unmangle_BufferAppendString(ub, "vector float");
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
Unmangle_BufferAppendString(ub, "vector pixel");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
p2 = p + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return p2;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *Unmangle_Type(jmp_buf errorbuf, UnmangleBuffer *ub, const char *p) {
|
|
|
|
const char *modifiers;
|
|
|
|
const char *what;
|
|
|
|
|
|
|
|
modifiers = p;
|
|
|
|
p = Unmangle_Modifiers(NULL, p);
|
|
|
|
if (modifiers == p)
|
|
|
|
modifiers = NULL;
|
|
|
|
|
|
|
|
switch (*p) {
|
|
|
|
case 'b':
|
|
|
|
what = "bool";
|
|
|
|
break;
|
|
|
|
case 'v':
|
|
|
|
what = "void";
|
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
what = "char";
|
|
|
|
break;
|
|
|
|
case 'w':
|
|
|
|
what = "wchar_t";
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
what = "short";
|
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
what = "int";
|
|
|
|
break;
|
|
|
|
case 'l':
|
|
|
|
what = "long";
|
|
|
|
break;
|
|
|
|
case 'x':
|
|
|
|
what = "long long";
|
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
what = "float";
|
|
|
|
break;
|
|
|
|
case 'D':
|
|
|
|
what = "short double";
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
what = "double";
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
what = "long double";
|
|
|
|
break;
|
|
|
|
case 'X':
|
|
|
|
return Unmangle_Vector(errorbuf, ub, p, modifiers);
|
|
|
|
case 'P':
|
|
|
|
return Unmangle_Pointer(errorbuf, ub, p, modifiers, '*');
|
|
|
|
case 'R':
|
|
|
|
return Unmangle_Pointer(errorbuf, ub, p, modifiers, '&');
|
|
|
|
case 'M':
|
|
|
|
return Unmangle_Pointer(errorbuf, ub, p, modifiers, 'M');
|
|
|
|
case 'A':
|
|
|
|
return Unmangle_ArrayType(errorbuf, ub, p, NULL);
|
|
|
|
case 'F':
|
|
|
|
return Unmangle_FunctionType(errorbuf, ub, p, NULL);
|
|
|
|
case '0':
|
|
|
|
case '1':
|
|
|
|
case '2':
|
|
|
|
case '3':
|
|
|
|
case '4':
|
|
|
|
case '5':
|
|
|
|
case '6':
|
|
|
|
case '7':
|
|
|
|
case '8':
|
|
|
|
case '9':
|
|
|
|
case 'Q':
|
|
|
|
if (modifiers) {
|
|
|
|
Unmangle_Modifiers(ub, modifiers);
|
|
|
|
Unmangle_BufferAppendChar(ub, ' ');
|
|
|
|
}
|
|
|
|
return Unmangle_QClassName(errorbuf, ub, p, 0, 0);
|
|
|
|
default:
|
|
|
|
Unmangle_Error(errorbuf);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (modifiers) {
|
|
|
|
Unmangle_Modifiers(ub, modifiers);
|
|
|
|
Unmangle_BufferAppendChar(ub, ' ');
|
|
|
|
}
|
|
|
|
Unmangle_BufferAppendString(ub, what);
|
|
|
|
|
|
|
|
return p + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void Unmangle_FuncArgList(jmp_buf errorbuf, UnmangleBuffer *ub, const char *p) {
|
|
|
|
Boolean is_volatile;
|
|
|
|
Boolean is_const;
|
|
|
|
|
|
|
|
is_volatile = is_const = 0;
|
|
|
|
|
|
|
|
if (*p == 'C') {
|
|
|
|
is_const = 1;
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
if (*p == 'V') {
|
|
|
|
is_volatile = 1;
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*(p++) != 'F')
|
|
|
|
Unmangle_Error(errorbuf);
|
|
|
|
|
|
|
|
Unmangle_BufferAppendChar(ub, '(');
|
|
|
|
|
|
|
|
if (!(p[0] == 'v' && p[1] == 0)) {
|
|
|
|
while (1) {
|
|
|
|
if (*p == 'e') {
|
|
|
|
if (p[1])
|
|
|
|
Unmangle_Error(errorbuf);
|
|
|
|
Unmangle_BufferAppendString(ub, "...");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*p == '_') {
|
|
|
|
p = Unmangle_Type(errorbuf, NULL, p + 1);
|
|
|
|
if (p[0])
|
|
|
|
Unmangle_Error(errorbuf);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
p = Unmangle_Type(errorbuf, ub, p);
|
|
|
|
if (!*p)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (*p != '_')
|
|
|
|
Unmangle_BufferAppendChar(ub, ',');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Unmangle_BufferAppendChar(ub, ')');
|
|
|
|
|
|
|
|
if (is_const)
|
|
|
|
Unmangle_BufferAppendString(ub, " const");
|
|
|
|
if (is_volatile)
|
|
|
|
Unmangle_BufferAppendString(ub, " volatile");
|
|
|
|
|
|
|
|
Unmangle_BufferTerminate(ub);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MWUnmangleClassName(const char *input, char *output, size_t maxLen) {
|
|
|
|
UnmangleBuffer ub;
|
|
|
|
jmp_buf errorbuf;
|
|
|
|
const char *p;
|
|
|
|
Boolean flag;
|
|
|
|
|
|
|
|
if (input[0] == 'Q' && (input[1] >= '1' && input[1] <= '9')) {
|
|
|
|
if (setjmp(errorbuf) == 0) {
|
|
|
|
Unmangle_BufferInit(&ub, output, maxLen);
|
|
|
|
Unmangle_QClassName(errorbuf, &ub, input, 0, 0);
|
|
|
|
Unmangle_BufferTerminate(&ub);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
p = input;
|
|
|
|
flag = 0;
|
|
|
|
while (1) {
|
|
|
|
switch (*p) {
|
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
case '<':
|
|
|
|
flag = 1;
|
|
|
|
default:
|
|
|
|
p++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flag) {
|
|
|
|
if (setjmp(errorbuf) == 0) {
|
|
|
|
Unmangle_BufferInit(&ub, output, maxLen);
|
|
|
|
Unmangle_ClassName(errorbuf, &ub, input, p - input, 1);
|
|
|
|
Unmangle_BufferTerminate(&ub);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
strncpy(output, input, maxLen);
|
|
|
|
output[maxLen - 1] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MWUnmangle(const char *input, char *output, size_t maxLen) {
|
|
|
|
UnmangleBuffer ub_internal;
|
|
|
|
UnmangleBuffer ub;
|
|
|
|
jmp_buf errorbuf;
|
|
|
|
char mybuf[256];
|
|
|
|
const char *p;
|
|
|
|
Boolean flag;
|
|
|
|
int ch;
|
|
|
|
|
|
|
|
switch (*input) {
|
|
|
|
case '.':
|
|
|
|
if ("_"[0] == '.')
|
|
|
|
input++;
|
|
|
|
break;
|
|
|
|
case '_':
|
|
|
|
if ("_"[0] == '_')
|
|
|
|
input++;
|
|
|
|
switch (input[1]) {
|
|
|
|
case '%':
|
|
|
|
case '#':
|
|
|
|
case '@':
|
|
|
|
input += 2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (setjmp(errorbuf) == 0) {
|
|
|
|
Unmangle_BufferInit(&ub_internal, mybuf, sizeof(mybuf));
|
|
|
|
Unmangle_BufferInit(&ub, output, maxLen);
|
|
|
|
|
|
|
|
if (!(input[0] == '_' && input[1] == '_' && (p = Unmangle_SpecialName(errorbuf, &ub_internal, input + 2)))) {
|
|
|
|
flag = 0;
|
|
|
|
Unmangle_BufferInit(&ub_internal, mybuf, sizeof(mybuf));
|
|
|
|
for (p = input; *p == '_'; p++)
|
|
|
|
Unmangle_BufferAppendChar(&ub_internal, '_');
|
|
|
|
|
|
|
|
while ((ch = *(p++))) {
|
|
|
|
if (ch == '_' && *p == '_') {
|
|
|
|
while (*(++p) == '_')
|
|
|
|
Unmangle_BufferAppendChar(&ub_internal, '_');
|
|
|
|
flag = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Unmangle_BufferAppendChar(&ub_internal, ch);
|
|
|
|
}
|
|
|
|
|
|
|
|
Unmangle_BufferTerminate(&ub_internal);
|
|
|
|
|
|
|
|
if (!flag) {
|
|
|
|
Unmangle_BufferAppendString(&ub, mybuf);
|
|
|
|
Unmangle_BufferTerminate(&ub);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (*p) {
|
|
|
|
case 'F':
|
|
|
|
if (mybuf[1] != 0 || (mybuf[0] != '!' && mybuf[0] != '~')) {
|
|
|
|
Unmangle_BufferAppendString(&ub, mybuf);
|
|
|
|
Unmangle_FuncArgList(errorbuf, &ub, p);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '0':
|
|
|
|
case '1':
|
|
|
|
case '2':
|
|
|
|
case '3':
|
|
|
|
case '4':
|
|
|
|
case '5':
|
|
|
|
case '6':
|
|
|
|
case '7':
|
|
|
|
case '8':
|
|
|
|
case '9':
|
|
|
|
case 'Q':
|
|
|
|
if (mybuf[1] == 0 && (mybuf[0] == '!' || mybuf[0] == '~')) {
|
|
|
|
p = Unmangle_QClassName(errorbuf, &ub, p, 1, mybuf[0] == '~');
|
|
|
|
} else {
|
|
|
|
p = Unmangle_QClassName(errorbuf, &ub, p, 0, 0);
|
|
|
|
Unmangle_BufferAppendString(&ub, "::");
|
|
|
|
Unmangle_BufferAppendString(&ub, mybuf);
|
|
|
|
if (*p == 0) {
|
|
|
|
Unmangle_BufferTerminate(&ub);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Unmangle_FuncArgList(errorbuf, &ub, p);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
strncpy(output, input, maxLen);
|
|
|
|
output[maxLen - 1] = 0;
|
|
|
|
}
|