/* Demangler for GNU C++
Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2003, 2004, 2010 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.uucp)
Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
int len0;
const char* p;
char *d;
- char *demangled;
+ char *demangled = NULL;
/* Discard leading _ada_, which is used for library level subprograms. */
if (strncmp (mangled, "_ada_", 5) == 0)
/* Most of the demangling will trivially remove chars. Operator names
may add one char but because they are always preceeded by '__' which is
- replaced by '.', they eventually never expand the size. '___elabs' and
- '___elabb' add only 2 chars, but they occur only once. */
- len0 = strlen (mangled) + 2 + 1;
+ replaced by '.', they eventually never expand the size.
+ A few special names such as '___elabs' add a few chars (at most 7), but
+ they occur only once. */
+ len0 = strlen (mangled) + 7 + 1;
demangled = XNEWVEC (char, len0);
d = demangled;
p = mangled;
while (1)
{
- /* Convert name, which is always lower-case. */
+ /* An entity names is expected. */
if (ISLOWER (*p))
{
+ /* An identifier, which is always lower case. */
do
*d++ = *p++;
while (ISLOWER(*p) || ISDIGIT (*p)
}
else if (p[0] == 'O')
{
+ /* An operator name. */
static const char * const operators[][2] =
{{"Oabs", "abs"}, {"Oand", "and"}, {"Omod", "mod"},
{"Onot", "not"}, {"Oor", "or"}, {"Orem", "rem"},
{"Oexpon", "**"}, {NULL, NULL}};
int k;
- for (k = 0; operators[k][0]; k++)
+ for (k = 0; operators[k][0] != NULL; k++)
{
- int l = strlen (operators[k][0]);
- if (!strncmp (p, operators[k][0], l))
+ size_t slen = strlen (operators[k][0]);
+ if (strncmp (p, operators[k][0], slen) == 0)
{
- p += l;
- l = strlen (operators[k][1]);
+ p += slen;
+ slen = strlen (operators[k][1]);
*d++ = '"';
- memcpy (d, operators[k][1], l);
- d += l;
+ memcpy (d, operators[k][1], slen);
+ d += slen;
*d++ = '"';
break;
}
}
/* Operator not found. */
- if (!operators[k][0])
+ if (operators[k][0] == NULL)
goto unknown;
}
else
goto unknown;
}
+ /* The name can be directly followed by some uppercase letters. */
+ if (p[0] == 'T' && p[1] == 'K')
+ {
+ /* Task stuff. */
+ if (p[2] == 'B' && p[3] == 0)
+ {
+ /* Subprogram for task body. */
+ break;
+ }
+ else if (p[2] == '_' && p[3] == '_')
+ {
+ /* Inner declarations in a task. */
+ p += 4;
+ *d++ = '.';
+ continue;
+ }
+ else
+ goto unknown;
+ }
+ if (p[0] == 'E' && p[1] == 0)
+ {
+ /* Exception name. */
+ goto unknown;
+ }
+ if ((p[0] == 'P' || p[0] == 'N') && p[1] == 0)
+ {
+ /* Protected type subprogram. */
+ break;
+ }
+ if ((*p == 'N' || *p == 'S') && p[1] == 0)
+ {
+ /* Enumerated type name table. */
+ goto unknown;
+ }
+ if (p[0] == 'X')
+ {
+ /* Body nested. */
+ p++;
+ while (p[0] == 'n' || p[0] == 'b')
+ p++;
+ }
+ if (p[0] == 'S' && p[1] != 0 && (p[2] == '_' || p[2] == 0))
+ {
+ /* Stream operations. */
+ const char *name;
+ switch (p[1])
+ {
+ case 'R':
+ name = "'Read";
+ break;
+ case 'W':
+ name = "'Write";
+ break;
+ case 'I':
+ name = "'Input";
+ break;
+ case 'O':
+ name = "'Output";
+ break;
+ default:
+ goto unknown;
+ }
+ p += 2;
+ strcpy (d, name);
+ d += strlen (name);
+ }
+ else if (p[0] == 'D')
+ {
+ /* Controlled type operation. */
+ const char *name;
+ switch (p[1])
+ {
+ case 'F':
+ name = ".Finalize";
+ break;
+ case 'A':
+ name = ".Adjust";
+ break;
+ default:
+ goto unknown;
+ }
+ strcpy (d, name);
+ d += strlen (name);
+ break;
+ }
+
if (p[0] == '_')
{
/* Separator. */
{
/* Standard separator. Handled first. */
p += 2;
+
if (ISDIGIT (*p))
{
- /* Overloading. */
+ /* Overloading number. */
do
p++;
while (ISDIGIT (*p) || (p[0] == '_' && ISDIGIT (p[1])));
+ if (*p == 'X')
+ {
+ p++;
+ while (p[0] == 'n' || p[0] == 'b')
+ p++;
+ }
}
- else if (*p == '_' && !strcmp (p + 1, "elabb"))
- {
- memcpy (d, "'Elab_Body", 10);
- d += 10;
- break;
- }
- else if (*p == '_' && !strcmp (p + 1, "elabs"))
+ else if (p[0] == '_' && p[1] != '_')
{
- memcpy (d, "'Elab_Spec", 10);
- d += 10;
- break;
+ /* Special names. */
+ static const char * const special[][2] = {
+ { "_elabb", "'Elab_Body" },
+ { "_elabs", "'Elab_Spec" },
+ { "_size", "'Size" },
+ { "_alignment", "'Alignment" },
+ { "_assign", ".\":=\"" },
+ { NULL, NULL }
+ };
+ int k;
+
+ for (k = 0; special[k][0] != NULL; k++)
+ {
+ size_t slen = strlen (special[k][0]);
+ if (strncmp (p, special[k][0], slen) == 0)
+ {
+ p += slen;
+ slen = strlen (special[k][1]);
+ memcpy (d, special[k][1], slen);
+ d += slen;
+ break;
+ }
+ }
+ if (special[k][0] != NULL)
+ break;
+ else
+ goto unknown;
}
else
{
goto unknown;
}
- if (p[0] == 'T' && p[1] == 'K')
- {
- if (p[2] == 'B' && p[3] == 0)
- {
- /* Subprogram for task body. */
- break;
- }
- else if (p[2] == '_' && p[3] == '_')
- {
- /* Inner declarations in a task. */
- p += 4;
- *d++ = '.';
- continue;
- }
- else
- goto unknown;
- }
- if ((p[0] == 'P' || p[0] == 'N') && p[1] == 0)
- {
- /* Protected type subprogram. */
- break;
- }
- if (p[0] == 'E' && p[1] == 0)
- {
- /* Exception name. */
- goto unknown;
- }
- if (*p == 'N' || *p == 'S')
- {
- /* Enumerated type name table. */
- goto unknown;
- }
- if (p[0] == 'X')
- {
- /* Body nested. */
- if (p[1] == 'n' || p[1] == 'b')
- p += 2;
- else if (p[1] == 0)
- p++;
- }
if (p[0] == '.' && ISDIGIT (p[1]))
{
/* Nested subprogram. */
unknown:
len0 = strlen (mangled);
+ free (demangled);
demangled = XNEWVEC (char, len0 + 3);
if (mangled[0] == '<')
- strcpy (demangled, mangled);
+ strcpy (demangled, mangled);
else
sprintf (demangled, "<%s>", mangled);