char *
demangle (bfd *abfd, const char *name)
{
- char *res;
- const char *p;
+ char *res, *alloc;
+ const char *pre, *suf;
+ size_t pre_len;
if (abfd != NULL && bfd_get_symbol_leading_char (abfd) == name[0])
++name;
or the MS PE format. These formats have a number of leading '.'s
on at least some symbols, so we remove all dots to avoid
confusing the demangler. */
- p = name;
- while (*p == '.')
- ++p;
+ pre = name;
+ while (*name == '.')
+ ++name;
+ pre_len = pre - name;
- res = cplus_demangle (p, DMGL_ANSI | DMGL_PARAMS);
- if (res)
+ alloc = NULL;
+ suf = strchr (name, '@');
+ if (suf != NULL)
{
- size_t dots = p - name;
+ alloc = xmalloc (suf - name + 1);
+ memcpy (alloc, name, suf - name);
+ alloc[suf - name] = '\0';
+ name = alloc;
+ }
- /* Now put back any stripped dots. */
- if (dots != 0)
+ res = cplus_demangle (name, DMGL_ANSI | DMGL_PARAMS);
+ if (res != NULL)
+ {
+ /* Now put back any suffix, or stripped dots. */
+ if (pre_len != 0 || suf != NULL)
{
- size_t len = strlen (res) + 1;
- char *add_dots = xmalloc (len + dots);
+ size_t len;
+ size_t suf_len;
+ char *final;
+
+ if (alloc != NULL)
+ free (alloc);
- memcpy (add_dots, name, dots);
- memcpy (add_dots + dots, res, len);
+ len = strlen (res);
+ if (suf == NULL)
+ suf = res + len;
+ suf_len = strlen (suf) + 1;
+ final = xmalloc (pre_len + len + suf_len);
+
+ memcpy (final, pre, pre_len);
+ memcpy (final + pre_len, res, len);
+ memcpy (final + pre_len + len, suf, suf_len);
free (res);
- res = add_dots;
+ res = final;
}
+
return res;
}
- return xstrdup (name);
+ if (alloc != NULL)
+ free (alloc);
+
+ return xstrdup (pre);
}