Home | History | Annotate | Download | only in m_demangle
      1 /* Demangler for the D programming language
      2    Copyright (C) 2014-2017 Free Software Foundation, Inc.
      3    Written by Iain Buclaw (ibuclaw (at) gdcproject.org)
      4 
      5 This file is part of the libiberty library.
      6 Libiberty is free software; you can redistribute it and/or
      7 modify it under the terms of the GNU Library General Public
      8 License as published by the Free Software Foundation; either
      9 version 2 of the License, or (at your option) any later version.
     10 
     11 In addition to the permissions in the GNU Library General Public
     12 License, the Free Software Foundation gives you unlimited permission
     13 to link the compiled version of this file into combinations with other
     14 programs, and to distribute those combinations without any restriction
     15 coming from the use of this file.  (The Library Public License
     16 restrictions do apply in other respects; for example, they cover
     17 modification of the file, and distribution when not linked into a
     18 combined executable.)
     19 
     20 Libiberty is distributed in the hope that it will be useful,
     21 but WITHOUT ANY WARRANTY; without even the implied warranty of
     22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     23 Library General Public License for more details.
     24 
     25 You should have received a copy of the GNU Library General Public
     26 License along with libiberty; see the file COPYING.LIB.
     27 If not, see <http://www.gnu.org/licenses/>.  */
     28 
     29 /* This file exports one function; dlang_demangle.
     30 
     31    This file imports strtol for decoding mangled literals.  */
     32 
     33 #if 0 /* in valgrind */
     34 #ifdef HAVE_CONFIG_H
     35 #include "config.h"
     36 #endif
     37 #endif /* ! in valgrind */
     38 
     39 #if 0 /* in valgrind */
     40 #include "safe-ctype.h"
     41 #endif /* ! in valgrind */
     42 
     43 #if 0 /* in valgrind */
     44 #include <sys/types.h>
     45 #include <string.h>
     46 #include <stdio.h>
     47 #endif /* ! in valgrind */
     48 
     49 #if 0 /* in valgrind */
     50 #ifdef HAVE_STDLIB_H
     51 #include <stdlib.h>
     52 #else
     53 extern long strtol (const char *nptr, char **endptr, int base);
     54 #endif
     55 #endif /* ! in valgrind */
     56 
     57 #if 0 /* in valgrind */
     58 #include <demangle.h>
     59 #include "libiberty.h"
     60 #endif /* ! in valgrind */
     61 
     62 #include "vg_libciface.h"
     63 
     64 #include "ansidecl.h"
     65 #include "demangle.h"
     66 #include "safe-ctype.h"
     67 
     68 /* A mini string-handling package */
     69 
     70 typedef struct string		/* Beware: these aren't required to be */
     71 {				/*  '\0' terminated.  */
     72   char *b;			/* pointer to start of string */
     73   char *p;			/* pointer after last character */
     74   char *e;			/* pointer after end of allocated space */
     75 } string;
     76 
     77 static void
     78 string_need (string *s, int n)
     79 {
     80   int tem;
     81 
     82   if (s->b == NULL)
     83     {
     84       if (n < 32)
     85 	{
     86 	  n = 32;
     87 	}
     88       s->p = s->b = XNEWVEC (char, n);
     89       s->e = s->b + n;
     90     }
     91   else if (s->e - s->p < n)
     92     {
     93       tem = s->p - s->b;
     94       n += tem;
     95       n *= 2;
     96       s->b = XRESIZEVEC (char, s->b, n);
     97       s->p = s->b + tem;
     98       s->e = s->b + n;
     99     }
    100 }
    101 
    102 static void
    103 string_delete (string *s)
    104 {
    105   if (s->b != NULL)
    106     {
    107       XDELETEVEC (s->b);
    108       s->b = s->e = s->p = NULL;
    109     }
    110 }
    111 
    112 static void
    113 string_init (string *s)
    114 {
    115   s->b = s->p = s->e = NULL;
    116 }
    117 
    118 static int
    119 string_length (string *s)
    120 {
    121   if (s->p == s->b)
    122     {
    123       return 0;
    124     }
    125   return s->p - s->b;
    126 }
    127 
    128 static void
    129 string_setlength (string *s, int n)
    130 {
    131   if (n - string_length (s) < 0)
    132     {
    133       s->p = s->b + n;
    134     }
    135 }
    136 
    137 static void
    138 string_append (string *p, const char *s)
    139 {
    140   int n = strlen (s);
    141   string_need (p, n);
    142   memcpy (p->p, s, n);
    143   p->p += n;
    144 }
    145 
    146 static void
    147 string_appendn (string *p, const char *s, int n)
    148 {
    149   if (n != 0)
    150     {
    151       string_need (p, n);
    152       memcpy (p->p, s, n);
    153       p->p += n;
    154     }
    155 }
    156 
    157 static void
    158 string_prependn (string *p, const char *s, int n)
    159 {
    160   char *q;
    161 
    162   if (n != 0)
    163     {
    164       string_need (p, n);
    165       for (q = p->p - 1; q >= p->b; q--)
    166 	{
    167 	  q[n] = q[0];
    168 	}
    169       memcpy (p->b, s, n);
    170       p->p += n;
    171     }
    172 }
    173 
    174 static void
    175 string_prepend (string *p, const char *s)
    176 {
    177   if (s != NULL && *s != '\0')
    178     {
    179       string_prependn (p, s, strlen (s));
    180     }
    181 }
    182 
    183 /* What kinds of symbol we could be parsing.  */
    184 enum dlang_symbol_kinds
    185 {
    186   /* Top-level symbol, needs it's type checked.  */
    187   dlang_top_level,
    188   /* Function symbol, needs it's type checked.   */
    189   dlang_function,
    190   /* Strongly typed name, such as for classes, structs and enums.  */
    191   dlang_type_name,
    192   /* Template identifier.  */
    193   dlang_template_ident,
    194   /* Template symbol parameter.  */
    195   dlang_template_param
    196 };
    197 
    198 /* Prototypes for forward referenced functions */
    199 static const char *dlang_function_args (string *, const char *);
    200 
    201 static const char *dlang_type (string *, const char *);
    202 
    203 static const char *dlang_value (string *, const char *, const char *, char);
    204 
    205 static const char *dlang_parse_symbol (string *, const char *,
    206 				       enum dlang_symbol_kinds);
    207 
    208 static const char *dlang_parse_tuple (string *, const char *);
    209 
    210 static const char *dlang_parse_template (string *, const char *, long);
    211 
    212 
    213 /* Demangle the calling convention from MANGLED and append it to DECL.
    214    Return the remaining string on success or NULL on failure.  */
    215 static const char *
    216 dlang_call_convention (string *decl, const char *mangled)
    217 {
    218   if (mangled == NULL || *mangled == '\0')
    219     return NULL;
    220 
    221   switch (*mangled)
    222     {
    223     case 'F': /* (D) */
    224       mangled++;
    225       break;
    226     case 'U': /* (C) */
    227       mangled++;
    228       string_append (decl, "extern(C) ");
    229       break;
    230     case 'W': /* (Windows) */
    231       mangled++;
    232       string_append (decl, "extern(Windows) ");
    233       break;
    234     case 'V': /* (Pascal) */
    235       mangled++;
    236       string_append (decl, "extern(Pascal) ");
    237       break;
    238     case 'R': /* (C++) */
    239       mangled++;
    240       string_append (decl, "extern(C++) ");
    241       break;
    242     case 'Y': /* (Objective-C) */
    243       mangled++;
    244       string_append (decl, "extern(Objective-C) ");
    245       break;
    246     default:
    247       return NULL;
    248     }
    249 
    250   return mangled;
    251 }
    252 
    253 /* Extract the type modifiers from MANGLED and append them to DECL.
    254    Returns the remaining signature on success or NULL on failure.  */
    255 static const char *
    256 dlang_type_modifiers (string *decl, const char *mangled)
    257 {
    258   if (mangled == NULL || *mangled == '\0')
    259     return NULL;
    260 
    261   switch (*mangled)
    262     {
    263     case 'x': /* const */
    264       mangled++;
    265       string_append (decl, " const");
    266       return mangled;
    267     case 'y': /* immutable */
    268       mangled++;
    269       string_append (decl, " immutable");
    270       return mangled;
    271     case 'O': /* shared */
    272       mangled++;
    273       string_append (decl, " shared");
    274       return dlang_type_modifiers (decl, mangled);
    275     case 'N':
    276       mangled++;
    277       if (*mangled == 'g') /* wild */
    278 	{
    279 	  mangled++;
    280 	  string_append (decl, " inout");
    281 	  return dlang_type_modifiers (decl, mangled);
    282 	}
    283       else
    284 	return NULL;
    285 
    286     default:
    287       return mangled;
    288     }
    289 }
    290 
    291 /* Demangle the D function attributes from MANGLED and append it to DECL.
    292    Return the remaining string on success or NULL on failure.  */
    293 static const char *
    294 dlang_attributes (string *decl, const char *mangled)
    295 {
    296   if (mangled == NULL || *mangled == '\0')
    297     return NULL;
    298 
    299   while (*mangled == 'N')
    300     {
    301       mangled++;
    302       switch (*mangled)
    303 	{
    304 	case 'a': /* pure */
    305 	  mangled++;
    306 	  string_append (decl, "pure ");
    307 	  continue;
    308 	case 'b': /* nothrow */
    309 	  mangled++;
    310 	  string_append (decl, "nothrow ");
    311 	  continue;
    312 	case 'c': /* ref */
    313 	  mangled++;
    314 	  string_append (decl, "ref ");
    315 	  continue;
    316 	case 'd': /* @property */
    317 	  mangled++;
    318 	  string_append (decl, "@property ");
    319 	  continue;
    320 	case 'e': /* @trusted */
    321 	  mangled++;
    322 	  string_append (decl, "@trusted ");
    323 	  continue;
    324 	case 'f': /* @safe */
    325 	  mangled++;
    326 	  string_append (decl, "@safe ");
    327 	  continue;
    328 	case 'g':
    329 	case 'h':
    330 	case 'k':
    331 	  /* inout parameter is represented as 'Ng'.
    332 	     vector parameter is represented as 'Nh'.
    333 	     return paramenter is represented as 'Nk'.
    334 	     If we see this, then we know we're really in the
    335 	     parameter list.  Rewind and break.  */
    336 	  mangled--;
    337 	  break;
    338 	case 'i': /* @nogc */
    339 	  mangled++;
    340 	  string_append (decl, "@nogc ");
    341 	  continue;
    342 	case 'j': /* return */
    343 	  mangled++;
    344 	  string_append (decl, "return ");
    345 	  continue;
    346 
    347 	default: /* unknown attribute */
    348 	  return NULL;
    349 	}
    350       break;
    351     }
    352 
    353   return mangled;
    354 }
    355 
    356 /* Demangle the function type from MANGLED and append it to DECL.
    357    Return the remaining string on success or NULL on failure.  */
    358 static const char *
    359 dlang_function_type (string *decl, const char *mangled)
    360 {
    361   string attr, args, type;
    362   size_t szattr, szargs, sztype;
    363 
    364   if (mangled == NULL || *mangled == '\0')
    365     return NULL;
    366 
    367   /* The order of the mangled string is:
    368 	CallConvention FuncAttrs Arguments ArgClose Type
    369 
    370      The demangled string is re-ordered as:
    371 	CallConvention Type Arguments FuncAttrs
    372    */
    373   string_init (&attr);
    374   string_init (&args);
    375   string_init (&type);
    376 
    377   /* Function call convention.  */
    378   mangled = dlang_call_convention (decl, mangled);
    379 
    380   /* Function attributes.  */
    381   mangled = dlang_attributes (&attr, mangled);
    382   szattr = string_length (&attr);
    383 
    384   /* Function arguments.  */
    385   mangled = dlang_function_args (&args, mangled);
    386   szargs = string_length (&args);
    387 
    388   /* Function return type.  */
    389   mangled = dlang_type (&type, mangled);
    390   sztype = string_length (&type);
    391 
    392   /* Append to decl in order. */
    393   string_appendn (decl, type.b, sztype);
    394   string_append (decl, "(");
    395   string_appendn (decl, args.b, szargs);
    396   string_append (decl, ") ");
    397   string_appendn (decl, attr.b, szattr);
    398 
    399   string_delete (&attr);
    400   string_delete (&args);
    401   string_delete (&type);
    402   return mangled;
    403 }
    404 
    405 /* Demangle the argument list from MANGLED and append it to DECL.
    406    Return the remaining string on success or NULL on failure.  */
    407 static const char *
    408 dlang_function_args (string *decl, const char *mangled)
    409 {
    410   size_t n = 0;
    411 
    412   while (mangled && *mangled != '\0')
    413     {
    414       switch (*mangled)
    415 	{
    416 	case 'X': /* (variadic T t...) style.  */
    417 	  mangled++;
    418 	  string_append (decl, "...");
    419 	  return mangled;
    420 	case 'Y': /* (variadic T t, ...) style.  */
    421 	  mangled++;
    422 	  if (n != 0)
    423 	    string_append (decl, ", ");
    424 	  string_append (decl, "...");
    425 	  return mangled;
    426 	case 'Z': /* Normal function.  */
    427 	  mangled++;
    428 	  return mangled;
    429 	}
    430 
    431       if (n++)
    432 	string_append (decl, ", ");
    433 
    434       if (*mangled == 'M') /* scope(T) */
    435 	{
    436 	  mangled++;
    437 	  string_append (decl, "scope ");
    438 	}
    439 
    440       if (mangled[0] == 'N' && mangled[1] == 'k') /* return(T) */
    441 	{
    442 	  mangled += 2;
    443 	  string_append (decl, "return ");
    444 	}
    445 
    446       switch (*mangled)
    447 	{
    448 	case 'J': /* out(T) */
    449 	  mangled++;
    450 	  string_append (decl, "out ");
    451 	  break;
    452 	case 'K': /* ref(T) */
    453 	  mangled++;
    454 	  string_append (decl, "ref ");
    455 	  break;
    456 	case 'L': /* lazy(T) */
    457 	  mangled++;
    458 	  string_append (decl, "lazy ");
    459 	  break;
    460 	}
    461       mangled = dlang_type (decl, mangled);
    462     }
    463 
    464   return mangled;
    465 }
    466 
    467 /* Demangle the type from MANGLED and append it to DECL.
    468    Return the remaining string on success or NULL on failure.  */
    469 static const char *
    470 dlang_type (string *decl, const char *mangled)
    471 {
    472   if (mangled == NULL || *mangled == '\0')
    473     return NULL;
    474 
    475   switch (*mangled)
    476     {
    477     case 'O': /* shared(T) */
    478       mangled++;
    479       string_append (decl, "shared(");
    480       mangled = dlang_type (decl, mangled);
    481       string_append (decl, ")");
    482       return mangled;
    483     case 'x': /* const(T) */
    484       mangled++;
    485       string_append (decl, "const(");
    486       mangled = dlang_type (decl, mangled);
    487       string_append (decl, ")");
    488       return mangled;
    489     case 'y': /* immutable(T) */
    490       mangled++;
    491       string_append (decl, "immutable(");
    492       mangled = dlang_type (decl, mangled);
    493       string_append (decl, ")");
    494       return mangled;
    495     case 'N':
    496       mangled++;
    497       if (*mangled == 'g') /* wild(T) */
    498 	{
    499 	  mangled++;
    500 	  string_append (decl, "inout(");
    501 	  mangled = dlang_type (decl, mangled);
    502 	  string_append (decl, ")");
    503 	  return mangled;
    504 	}
    505       else if (*mangled == 'h') /* vector(T) */
    506 	{
    507 	  mangled++;
    508 	  string_append (decl, "__vector(");
    509 	  mangled = dlang_type (decl, mangled);
    510 	  string_append (decl, ")");
    511 	  return mangled;
    512 	}
    513       else
    514 	return NULL;
    515     case 'A': /* dynamic array (T[]) */
    516       mangled++;
    517       mangled = dlang_type (decl, mangled);
    518       string_append (decl, "[]");
    519       return mangled;
    520     case 'G': /* static array (T[N]) */
    521     {
    522       const char *numptr;
    523       size_t num = 0;
    524       mangled++;
    525 
    526       numptr = mangled;
    527       while (ISDIGIT (*mangled))
    528 	{
    529 	  num++;
    530 	  mangled++;
    531 	}
    532       mangled = dlang_type (decl, mangled);
    533       string_append (decl, "[");
    534       string_appendn (decl, numptr, num);
    535       string_append (decl, "]");
    536       return mangled;
    537     }
    538     case 'H': /* associative array (T[T]) */
    539     {
    540       string type;
    541       size_t sztype;
    542       mangled++;
    543 
    544       string_init (&type);
    545       mangled = dlang_type (&type, mangled);
    546       sztype = string_length (&type);
    547 
    548       mangled = dlang_type (decl, mangled);
    549       string_append (decl, "[");
    550       string_appendn (decl, type.b, sztype);
    551       string_append (decl, "]");
    552 
    553       string_delete (&type);
    554       return mangled;
    555     }
    556     case 'P': /* pointer (T*) */
    557       mangled++;
    558       /* Function pointer types don't include the trailing asterisk.  */
    559       switch (*mangled)
    560 	{
    561 	case 'F': case 'U': case 'W':
    562 	case 'V': case 'R': case 'Y':
    563 	  mangled = dlang_function_type (decl, mangled);
    564 	  string_append (decl, "function");
    565 	  return mangled;
    566 	}
    567       mangled = dlang_type (decl, mangled);
    568       string_append (decl, "*");
    569       return mangled;
    570     case 'I': /* ident T */
    571     case 'C': /* class T */
    572     case 'S': /* struct T */
    573     case 'E': /* enum T */
    574     case 'T': /* typedef T */
    575       mangled++;
    576       return dlang_parse_symbol (decl, mangled, dlang_type_name);
    577     case 'D': /* delegate T */
    578     {
    579       string mods;
    580       size_t szmods;
    581       mangled++;
    582 
    583       string_init (&mods);
    584       mangled = dlang_type_modifiers (&mods, mangled);
    585       szmods = string_length (&mods);
    586 
    587       mangled = dlang_function_type (decl, mangled);
    588       string_append (decl, "delegate");
    589       string_appendn (decl, mods.b, szmods);
    590 
    591       string_delete (&mods);
    592       return mangled;
    593     }
    594     case 'B': /* tuple T */
    595       mangled++;
    596       return dlang_parse_tuple (decl, mangled);
    597 
    598     /* Basic types */
    599     case 'n':
    600       mangled++;
    601       string_append (decl, "none");
    602       return mangled;
    603     case 'v':
    604       mangled++;
    605       string_append (decl, "void");
    606       return mangled;
    607     case 'g':
    608       mangled++;
    609       string_append (decl, "byte");
    610       return mangled;
    611     case 'h':
    612       mangled++;
    613       string_append (decl, "ubyte");
    614       return mangled;
    615     case 's':
    616       mangled++;
    617       string_append (decl, "short");
    618       return mangled;
    619     case 't':
    620       mangled++;
    621       string_append (decl, "ushort");
    622       return mangled;
    623     case 'i':
    624       mangled++;
    625       string_append (decl, "int");
    626       return mangled;
    627     case 'k':
    628       mangled++;
    629       string_append (decl, "uint");
    630       return mangled;
    631     case 'l':
    632       mangled++;
    633       string_append (decl, "long");
    634       return mangled;
    635     case 'm':
    636       mangled++;
    637       string_append (decl, "ulong");
    638       return mangled;
    639     case 'f':
    640       mangled++;
    641       string_append (decl, "float");
    642       return mangled;
    643     case 'd':
    644       mangled++;
    645       string_append (decl, "double");
    646       return mangled;
    647     case 'e':
    648       mangled++;
    649       string_append (decl, "real");
    650       return mangled;
    651 
    652     /* Imaginary and Complex types */
    653     case 'o':
    654       mangled++;
    655       string_append (decl, "ifloat");
    656       return mangled;
    657     case 'p':
    658       mangled++;
    659       string_append (decl, "idouble");
    660       return mangled;
    661     case 'j':
    662       mangled++;
    663       string_append (decl, "ireal");
    664       return mangled;
    665     case 'q':
    666       mangled++;
    667       string_append (decl, "cfloat");
    668       return mangled;
    669     case 'r':
    670       mangled++;
    671       string_append (decl, "cdouble");
    672       return mangled;
    673     case 'c':
    674       mangled++;
    675       string_append (decl, "creal");
    676       return mangled;
    677 
    678     /* Other types */
    679     case 'b':
    680       mangled++;
    681       string_append (decl, "bool");
    682       return mangled;
    683     case 'a':
    684       mangled++;
    685       string_append (decl, "char");
    686       return mangled;
    687     case 'u':
    688       mangled++;
    689       string_append (decl, "wchar");
    690       return mangled;
    691     case 'w':
    692       mangled++;
    693       string_append (decl, "dchar");
    694       return mangled;
    695     case 'z':
    696       mangled++;
    697       switch (*mangled)
    698 	{
    699 	case 'i':
    700 	  mangled++;
    701 	  string_append (decl, "cent");
    702 	  return mangled;
    703 	case 'k':
    704 	  mangled++;
    705 	  string_append (decl, "ucent");
    706 	  return mangled;
    707 	}
    708       return NULL;
    709 
    710     default: /* unhandled */
    711       return NULL;
    712     }
    713 }
    714 
    715 /* Extract the identifier from MANGLED and append it to DECL.
    716    Return the remaining string on success or NULL on failure.  */
    717 static const char *
    718 dlang_identifier (string *decl, const char *mangled,
    719 		  enum dlang_symbol_kinds kind)
    720 {
    721   char *endptr;
    722   long len;
    723 
    724   if (mangled == NULL || *mangled == '\0')
    725     return NULL;
    726 
    727   len = strtol (mangled, &endptr, 10);
    728 
    729   if (endptr == NULL || len <= 0)
    730     return NULL;
    731 
    732   /* In template parameter symbols, the first character of the mangled
    733      name can be a digit.  This causes ambiguity issues because the
    734      digits of the two numbers are adjacent.  */
    735   if (kind == dlang_template_param)
    736     {
    737       long psize = len;
    738       char *pend;
    739       int saved = string_length (decl);
    740 
    741       /* Work backwards until a match is found.  */
    742       for (pend = endptr; endptr != NULL; pend--)
    743 	{
    744 	  mangled = pend;
    745 
    746 	  /* Reached the beginning of the pointer to the name length,
    747 	     try parsing the entire symbol.  */
    748 	  if (psize == 0)
    749 	    {
    750 	      psize = len;
    751 	      pend = endptr;
    752 	      endptr = NULL;
    753 	    }
    754 
    755 	  /* Check whether template parameter is a function with a valid
    756 	     return type or an untyped identifier.  */
    757 	  if (ISDIGIT (*mangled))
    758 	    mangled = dlang_parse_symbol (decl, mangled, dlang_template_ident);
    759 	  else if (strncmp (mangled, "_D", 2) == 0)
    760 	    {
    761 	      mangled += 2;
    762 	      mangled = dlang_parse_symbol (decl, mangled, dlang_function);
    763 	    }
    764 
    765 	  /* Check for name length mismatch.  */
    766 	  if (mangled && (mangled - pend) == psize)
    767 	    return mangled;
    768 
    769 	  psize /= 10;
    770 	  string_setlength (decl, saved);
    771 	}
    772 
    773       /* No match on any combinations.  */
    774       return NULL;
    775     }
    776   else
    777     {
    778       if (strlen (endptr) < (size_t) len)
    779 	return NULL;
    780 
    781       mangled = endptr;
    782 
    783       /* May be a template instance.  */
    784       if (len >= 5 && strncmp (mangled, "__T", 3) == 0)
    785 	{
    786 	  /* Template symbol.  */
    787 	  if (ISDIGIT (mangled[3]) && mangled[3] != '0')
    788 	    return dlang_parse_template (decl, mangled, len);
    789 
    790 	  return NULL;
    791 	}
    792 
    793       switch (len)
    794 	{
    795 	case 6:
    796 	  if (strncmp (mangled, "__ctor", len) == 0)
    797 	    {
    798 	      /* Constructor symbol for a class/struct.  */
    799 	      string_append (decl, "this");
    800 	      mangled += len;
    801 	      return mangled;
    802 	    }
    803 	  else if (strncmp (mangled, "__dtor", len) == 0)
    804 	    {
    805 	      /* Destructor symbol for a class/struct.  */
    806 	      string_append (decl, "~this");
    807 	      mangled += len;
    808 	      return mangled;
    809 	    }
    810 	  else if (strncmp (mangled, "__initZ", len+1) == 0)
    811 	    {
    812 	      /* The static initialiser for a given symbol.  */
    813 	      string_append (decl, "init$");
    814 	      mangled += len;
    815 	      return mangled;
    816 	    }
    817 	  else if (strncmp (mangled, "__vtblZ", len+1) == 0)
    818 	    {
    819 	      /* The vtable symbol for a given class.  */
    820 	      string_prepend (decl, "vtable for ");
    821 	      string_setlength (decl, string_length (decl) - 1);
    822 	      mangled += len;
    823 	      return mangled;
    824 	    }
    825 	  break;
    826 
    827 	case 7:
    828 	  if (strncmp (mangled, "__ClassZ", len+1) == 0)
    829 	    {
    830 	      /* The classinfo symbol for a given class.  */
    831 	      string_prepend (decl, "ClassInfo for ");
    832 	      string_setlength (decl, string_length (decl) - 1);
    833 	      mangled += len;
    834 	      return mangled;
    835 	    }
    836 	  break;
    837 
    838 	case 10:
    839 	  if (strncmp (mangled, "__postblitMFZ", len+3) == 0)
    840 	    {
    841 	      /* Postblit symbol for a struct.  */
    842 	      string_append (decl, "this(this)");
    843 	      mangled += len + 3;
    844 	      return mangled;
    845 	    }
    846 	  break;
    847 
    848 	case 11:
    849 	  if (strncmp (mangled, "__InterfaceZ", len+1) == 0)
    850 	    {
    851 	      /* The interface symbol for a given class.  */
    852 	      string_prepend (decl, "Interface for ");
    853 	      string_setlength (decl, string_length (decl) - 1);
    854 	      mangled += len;
    855 	      return mangled;
    856 	    }
    857 	  break;
    858 
    859 	case 12:
    860 	  if (strncmp (mangled, "__ModuleInfoZ", len+1) == 0)
    861 	    {
    862 	      /* The ModuleInfo symbol for a given module.  */
    863 	      string_prepend (decl, "ModuleInfo for ");
    864 	      string_setlength (decl, string_length (decl) - 1);
    865 	      mangled += len;
    866 	      return mangled;
    867 	    }
    868 	  break;
    869 	}
    870 
    871       string_appendn (decl, mangled, len);
    872       mangled += len;
    873     }
    874 
    875   return mangled;
    876 }
    877 
    878 /* Extract the integer value from MANGLED and append it to DECL,
    879    where TYPE is the type it should be represented as.
    880    Return the remaining string on success or NULL on failure.  */
    881 static const char *
    882 dlang_parse_integer (string *decl, const char *mangled, char type)
    883 {
    884   if (type == 'a' || type == 'u' || type == 'w')
    885     {
    886       /* Parse character value.  */
    887       char value[10];
    888       int pos = 10;
    889       int width = 0;
    890       char *endptr;
    891       long val = strtol (mangled, &endptr, 10);
    892 
    893       if (endptr == NULL || val < 0)
    894 	return NULL;
    895 
    896       string_append (decl, "'");
    897 
    898       if (type == 'a' && val >= 0x20 && val < 0x7F)
    899 	{
    900 	  /* Represent as a character literal.  */
    901 	  char c = (char) val;
    902 	  string_appendn (decl, &c, 1);
    903 	}
    904       else
    905 	{
    906 	  /* Represent as a hexadecimal value.  */
    907 	  switch (type)
    908 	    {
    909 	    case 'a': /* char */
    910 	      string_append (decl, "\\x");
    911 	      width = 2;
    912 	      break;
    913 	    case 'u': /* wchar */
    914 	      string_append (decl, "\\u");
    915 	      width = 4;
    916 	      break;
    917 	    case 'w': /* dchar */
    918 	      string_append (decl, "\\U");
    919 	      width = 8;
    920 	      break;
    921 	    }
    922 
    923 	  while (val > 0)
    924 	    {
    925 	      int digit = val % 16;
    926 
    927 	      if (digit < 10)
    928 		value[--pos] = (char)(digit + '0');
    929 	      else
    930 		value[--pos] = (char)((digit - 10) + 'a');
    931 
    932 	      val /= 16;
    933 	      width--;
    934 	    }
    935 
    936 	  for (; width > 0; width--)
    937 	    value[--pos] = '0';
    938 
    939 	  string_appendn (decl, &(value[pos]), 10 - pos);
    940 	}
    941       string_append (decl, "'");
    942       mangled = endptr;
    943     }
    944   else if (type == 'b')
    945     {
    946       /* Parse boolean value.  */
    947       char *endptr;
    948       long val = strtol (mangled, &endptr, 10);
    949 
    950       if (endptr == NULL || val < 0)
    951 	return NULL;
    952 
    953       string_append (decl, val ? "true" : "false");
    954       mangled = endptr;
    955     }
    956   else
    957     {
    958       /* Parse integer value.  */
    959       const char *numptr = mangled;
    960       size_t num = 0;
    961 
    962       while (ISDIGIT (*mangled))
    963 	{
    964 	  num++;
    965 	  mangled++;
    966 	}
    967       string_appendn (decl, numptr, num);
    968 
    969       /* Append suffix.  */
    970       switch (type)
    971 	{
    972 	case 'h': /* ubyte */
    973 	case 't': /* ushort */
    974 	case 'k': /* uint */
    975 	  string_append (decl, "u");
    976 	  break;
    977 	case 'l': /* long */
    978 	  string_append (decl, "L");
    979 	  break;
    980 	case 'm': /* ulong */
    981 	  string_append (decl, "uL");
    982 	  break;
    983 	}
    984     }
    985 
    986   return mangled;
    987 }
    988 
    989 /* Extract the floating-point value from MANGLED and append it to DECL.
    990    Return the remaining string on success or NULL on failure.  */
    991 static const char *
    992 dlang_parse_real (string *decl, const char *mangled)
    993 {
    994   char buffer[64];
    995   int len = 0;
    996 
    997   /* Handle NAN and +-INF.  */
    998   if (strncmp (mangled, "NAN", 3) == 0)
    999     {
   1000       string_append (decl, "NaN");
   1001       mangled += 3;
   1002       return mangled;
   1003     }
   1004   else if (strncmp (mangled, "INF", 3) == 0)
   1005     {
   1006       string_append (decl, "Inf");
   1007       mangled += 3;
   1008       return mangled;
   1009     }
   1010   else if (strncmp (mangled, "NINF", 4) == 0)
   1011     {
   1012       string_append (decl, "-Inf");
   1013       mangled += 4;
   1014       return mangled;
   1015     }
   1016 
   1017   /* Hexadecimal prefix and leading bit.  */
   1018   if (*mangled == 'N')
   1019     {
   1020       buffer[len++] = '-';
   1021       mangled++;
   1022     }
   1023 
   1024   if (!ISXDIGIT (*mangled))
   1025     return NULL;
   1026 
   1027   buffer[len++] = '0';
   1028   buffer[len++] = 'x';
   1029   buffer[len++] = *mangled;
   1030   buffer[len++] = '.';
   1031   mangled++;
   1032 
   1033   /* Significand.  */
   1034   while (ISXDIGIT (*mangled))
   1035     {
   1036       buffer[len++] = *mangled;
   1037       mangled++;
   1038     }
   1039 
   1040   /* Exponent.  */
   1041   if (*mangled != 'P')
   1042     return NULL;
   1043 
   1044   buffer[len++] = 'p';
   1045   mangled++;
   1046 
   1047   if (*mangled == 'N')
   1048     {
   1049       buffer[len++] = '-';
   1050       mangled++;
   1051     }
   1052 
   1053   while (ISDIGIT (*mangled))
   1054     {
   1055       buffer[len++] = *mangled;
   1056       mangled++;
   1057     }
   1058 
   1059   /* Write out the demangled hexadecimal, rather than trying to
   1060      convert the buffer into a floating-point value.  */
   1061   buffer[len] = '\0';
   1062   len = strlen (buffer);
   1063   string_appendn (decl, buffer, len);
   1064   return mangled;
   1065 }
   1066 
   1067 /* Convert VAL from an ascii hexdigit to value.  */
   1068 static char
   1069 ascii2hex (char val)
   1070 {
   1071   if (val >= 'a' && val <= 'f')
   1072     return (val - 'a' + 10);
   1073 
   1074   if (val >= 'A' && val <= 'F')
   1075     return (val - 'A' + 10);
   1076 
   1077   if (val >= '0' && val <= '9')
   1078     return (val - '0');
   1079 
   1080   return 0;
   1081 }
   1082 
   1083 /* Extract the string value from MANGLED and append it to DECL.
   1084    Return the remaining string on success or NULL on failure.  */
   1085 static const char *
   1086 dlang_parse_string (string *decl, const char *mangled)
   1087 {
   1088   char type = *mangled;
   1089   char *endptr;
   1090   long len;
   1091 
   1092   mangled++;
   1093   len = strtol (mangled, &endptr, 10);
   1094 
   1095   if (endptr == NULL || len < 0)
   1096     return NULL;
   1097 
   1098   mangled = endptr;
   1099   if (*mangled != '_')
   1100     return NULL;
   1101 
   1102   mangled++;
   1103   string_append (decl, "\"");
   1104   while (len--)
   1105     {
   1106       if (ISXDIGIT (mangled[0]) && ISXDIGIT (mangled[1]))
   1107 	{
   1108 	  char a = ascii2hex (mangled[0]);
   1109 	  char b = ascii2hex (mangled[1]);
   1110 	  char val = (a << 4) | b;
   1111 
   1112 	  /* Sanitize white and non-printable characters.  */
   1113 	  switch (val)
   1114 	    {
   1115 	    case ' ':
   1116 	      string_append (decl, " ");
   1117 	      break;
   1118 	    case '\t':
   1119 	      string_append (decl, "\\t");
   1120 	      break;
   1121 	    case '\n':
   1122 	      string_append (decl, "\\n");
   1123 	      break;
   1124 	    case '\r':
   1125 	      string_append (decl, "\\r");
   1126 	      break;
   1127 	    case '\f':
   1128 	      string_append (decl, "\\f");
   1129 	      break;
   1130 	    case '\v':
   1131 	      string_append (decl, "\\v");
   1132 	      break;
   1133 
   1134 	    default:
   1135 	      if (ISPRINT (val))
   1136 		string_appendn (decl, &val, 1);
   1137 	      else
   1138 		{
   1139 		  string_append (decl, "\\x");
   1140 		  string_appendn (decl, mangled, 2);
   1141 		}
   1142 	    }
   1143 	}
   1144       else
   1145 	return NULL;
   1146 
   1147       mangled += 2;
   1148     }
   1149   string_append (decl, "\"");
   1150 
   1151   if (type != 'a')
   1152     string_appendn (decl, &type, 1);
   1153 
   1154   return mangled;
   1155 }
   1156 
   1157 /* Extract the static array value from MANGLED and append it to DECL.
   1158    Return the remaining string on success or NULL on failure.  */
   1159 static const char *
   1160 dlang_parse_arrayliteral (string *decl, const char *mangled)
   1161 {
   1162   char *endptr;
   1163   long elements = strtol (mangled, &endptr, 10);
   1164 
   1165   if (endptr == NULL || elements < 0)
   1166     return NULL;
   1167 
   1168   mangled = endptr;
   1169   string_append (decl, "[");
   1170   while (elements--)
   1171     {
   1172       mangled = dlang_value (decl, mangled, NULL, '\0');
   1173       if (elements != 0)
   1174 	string_append (decl, ", ");
   1175     }
   1176 
   1177   string_append (decl, "]");
   1178   return mangled;
   1179 }
   1180 
   1181 /* Extract the associative array value from MANGLED and append it to DECL.
   1182    Return the remaining string on success or NULL on failure.  */
   1183 static const char *
   1184 dlang_parse_assocarray (string *decl, const char *mangled)
   1185 {
   1186   char *endptr;
   1187   long elements = strtol (mangled, &endptr, 10);
   1188 
   1189   if (endptr == NULL || elements < 0)
   1190     return NULL;
   1191 
   1192   mangled = endptr;
   1193   string_append (decl, "[");
   1194   while (elements--)
   1195     {
   1196       mangled = dlang_value (decl, mangled, NULL, '\0');
   1197       string_append (decl, ":");
   1198       mangled = dlang_value (decl, mangled, NULL, '\0');
   1199 
   1200       if (elements != 0)
   1201 	string_append (decl, ", ");
   1202     }
   1203 
   1204   string_append (decl, "]");
   1205   return mangled;
   1206 }
   1207 
   1208 /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
   1209    Return the remaining string on success or NULL on failure.  */
   1210 static const char *
   1211 dlang_parse_structlit (string *decl, const char *mangled, const char *name)
   1212 {
   1213   char *endptr;
   1214   long args = strtol (mangled, &endptr, 10);
   1215 
   1216   if (endptr == NULL || args < 0)
   1217     return NULL;
   1218 
   1219   mangled = endptr;
   1220   if (name != NULL)
   1221     string_append (decl, name);
   1222 
   1223   string_append (decl, "(");
   1224   while (args--)
   1225     {
   1226       mangled = dlang_value (decl, mangled, NULL, '\0');
   1227       if (args != 0)
   1228 	string_append (decl, ", ");
   1229     }
   1230 
   1231   string_append (decl, ")");
   1232   return mangled;
   1233 }
   1234 
   1235 /* Extract the value from MANGLED and append it to DECL.
   1236    Return the remaining string on success or NULL on failure.  */
   1237 static const char *
   1238 dlang_value (string *decl, const char *mangled, const char *name, char type)
   1239 {
   1240   if (mangled == NULL || *mangled == '\0')
   1241     return NULL;
   1242 
   1243   switch (*mangled)
   1244     {
   1245       /* Null value.  */
   1246     case 'n':
   1247       mangled++;
   1248       string_append (decl, "null");
   1249       break;
   1250 
   1251       /* Integral values.  */
   1252     case 'N':
   1253       mangled++;
   1254       string_append (decl, "-");
   1255       mangled = dlang_parse_integer (decl, mangled, type);
   1256       break;
   1257 
   1258     case 'i':
   1259       mangled++;
   1260       if (*mangled < '0' || *mangled > '9')
   1261 	return NULL;
   1262       /* Fall through */
   1263     case '0': case '1': case '2': case '3': case '4':
   1264     case '5': case '6': case '7': case '8': case '9':
   1265       mangled = dlang_parse_integer (decl, mangled, type);
   1266       break;
   1267 
   1268       /* Real value.  */
   1269     case 'e':
   1270       mangled++;
   1271       mangled = dlang_parse_real (decl, mangled);
   1272       break;
   1273 
   1274       /* Complex value.  */
   1275     case 'c':
   1276       mangled++;
   1277       mangled = dlang_parse_real (decl, mangled);
   1278       string_append (decl, "+");
   1279       if (mangled == NULL || *mangled != 'c')
   1280 	return NULL;
   1281       mangled++;
   1282       mangled = dlang_parse_real (decl, mangled);
   1283       string_append (decl, "i");
   1284       break;
   1285 
   1286       /* String values.  */
   1287     case 'a': /* UTF8 */
   1288     case 'w': /* UTF16 */
   1289     case 'd': /* UTF32 */
   1290       mangled = dlang_parse_string (decl, mangled);
   1291       break;
   1292 
   1293       /* Array values.  */
   1294     case 'A':
   1295       mangled++;
   1296       if (type == 'H')
   1297 	mangled = dlang_parse_assocarray (decl, mangled);
   1298       else
   1299 	mangled = dlang_parse_arrayliteral (decl, mangled);
   1300       break;
   1301 
   1302       /* Struct values.  */
   1303     case 'S':
   1304       mangled++;
   1305       mangled = dlang_parse_structlit (decl, mangled, name);
   1306       break;
   1307 
   1308     default:
   1309       return NULL;
   1310     }
   1311 
   1312   return mangled;
   1313 }
   1314 
   1315 /* Extract the type modifiers from MANGLED and return the string
   1316    length that it consumes in MANGLED on success or 0 on failure.  */
   1317 static int
   1318 dlang_type_modifier_p (const char *mangled)
   1319 {
   1320   int i;
   1321 
   1322   switch (*mangled)
   1323     {
   1324     case 'x': case 'y':
   1325       return 1;
   1326 
   1327     case 'O':
   1328       mangled++;
   1329       i = dlang_type_modifier_p (mangled);
   1330       return i + 1;
   1331 
   1332     case 'N':
   1333       mangled++;
   1334       if (*mangled == 'g')
   1335 	{
   1336 	  mangled++;
   1337 	  i = dlang_type_modifier_p (mangled);
   1338 	  return i + 2;
   1339 	}
   1340     }
   1341 
   1342   return 0;
   1343 }
   1344 
   1345 /* Extract the function calling convention from MANGLED and
   1346    return 1 on success or 0 on failure.  */
   1347 static int
   1348 dlang_call_convention_p (const char *mangled)
   1349 {
   1350   /* Prefix for functions needing 'this' */
   1351   if (*mangled == 'M')
   1352     {
   1353       mangled++;
   1354       /* Also skip over any type modifiers.  */
   1355       mangled += dlang_type_modifier_p (mangled);
   1356     }
   1357 
   1358   switch (*mangled)
   1359     {
   1360     case 'F': case 'U': case 'V':
   1361     case 'W': case 'R': case 'Y':
   1362       return 1;
   1363 
   1364     default:
   1365       return 0;
   1366     }
   1367 }
   1368 
   1369 /* Extract and demangle the symbol in MANGLED and append it to DECL.
   1370    Returns the remaining signature on success or NULL on failure.  */
   1371 static const char *
   1372 dlang_parse_symbol (string *decl, const char *mangled,
   1373 		    enum dlang_symbol_kinds kind)
   1374 {
   1375   int saved;
   1376   size_t n = 0;
   1377   do
   1378     {
   1379       if (n++)
   1380 	string_append (decl, ".");
   1381 
   1382       mangled = dlang_identifier (decl, mangled, kind);
   1383 
   1384       if (mangled && dlang_call_convention_p (mangled))
   1385 	{
   1386 	  string mods;
   1387 	  const char *start = NULL;
   1388 	  int checkpoint = 0;
   1389 
   1390 	  /* Skip over 'this' parameter.  */
   1391 	  if (*mangled == 'M')
   1392 	    mangled++;
   1393 
   1394 	  /* We have reached here because we expect an extern(Pascal) function.
   1395 	     However this is so rare, that it is more likely a template value
   1396 	     parameter.  Since this can't be assumed, first attempt parsing
   1397 	     the symbol as a function, and then back out on failure.  */
   1398 	  if (*mangled == 'V')
   1399 	    {
   1400 	      start = mangled;
   1401 	      checkpoint = string_length (decl);
   1402 	    }
   1403 
   1404 	  /* Save the type modifiers for appending at the end.  */
   1405 	  string_init (&mods);
   1406 	  mangled = dlang_type_modifiers (&mods, mangled);
   1407 
   1408 	  /* Skip over calling convention and attributes in qualified name.  */
   1409 	  saved = string_length (decl);
   1410 	  mangled = dlang_call_convention (decl, mangled);
   1411 	  mangled = dlang_attributes (decl, mangled);
   1412 	  string_setlength (decl, saved);
   1413 
   1414 	  string_append (decl, "(");
   1415 	  mangled = dlang_function_args (decl, mangled);
   1416 	  string_append (decl, ")");
   1417 
   1418 	  /* Add any const/immutable/shared modifier. */
   1419 	  string_appendn (decl, mods.b, string_length (&mods));
   1420 	  string_delete (&mods);
   1421 
   1422 	  if (mangled == NULL && checkpoint != 0)
   1423 	    {
   1424 	      mangled = start;
   1425 	      string_setlength (decl, checkpoint);
   1426 	    }
   1427 	}
   1428     }
   1429   while (mangled && ISDIGIT (*mangled));
   1430 
   1431   /* Only top-level symbols or function template parameters have
   1432      a type that needs checking.  */
   1433   if (kind == dlang_top_level || kind == dlang_function)
   1434     {
   1435       /* Artificial symbols end with 'Z' and have no type.  */
   1436       if (mangled && *mangled == 'Z')
   1437 	mangled++;
   1438       else
   1439 	{
   1440 	  saved = string_length (decl);
   1441 	  mangled = dlang_type (decl, mangled);
   1442 	  string_setlength (decl, saved);
   1443 	}
   1444 
   1445       /* Check that the entire symbol was successfully demangled.  */
   1446       if (kind == dlang_top_level)
   1447 	{
   1448 	  if (mangled == NULL || *mangled != '\0')
   1449 	    return NULL;
   1450 	}
   1451     }
   1452 
   1453   return mangled;
   1454 }
   1455 
   1456 /* Demangle the tuple from MANGLED and append it to DECL.
   1457    Return the remaining string on success or NULL on failure.  */
   1458 static const char *
   1459 dlang_parse_tuple (string *decl, const char *mangled)
   1460 {
   1461   char *endptr;
   1462   long elements = strtol (mangled, &endptr, 10);
   1463 
   1464   if (endptr == NULL || elements < 0)
   1465     return NULL;
   1466 
   1467   mangled = endptr;
   1468   string_append (decl, "Tuple!(");
   1469 
   1470   while (elements--)
   1471     {
   1472       mangled = dlang_type (decl, mangled);
   1473       if (elements != 0)
   1474 	string_append (decl, ", ");
   1475     }
   1476 
   1477   string_append (decl, ")");
   1478   return mangled;
   1479 }
   1480 
   1481 /* Demangle the argument list from MANGLED and append it to DECL.
   1482    Return the remaining string on success or NULL on failure.  */
   1483 static const char *
   1484 dlang_template_args (string *decl, const char *mangled)
   1485 {
   1486   size_t n = 0;
   1487 
   1488   while (mangled && *mangled != '\0')
   1489     {
   1490       switch (*mangled)
   1491 	{
   1492 	case 'Z': /* End of parameter list.  */
   1493 	  mangled++;
   1494 	  return mangled;
   1495 	}
   1496 
   1497       if (n++)
   1498 	string_append (decl, ", ");
   1499 
   1500       /* Skip over specialised template prefix.  */
   1501       if (*mangled == 'H')
   1502 	mangled++;
   1503 
   1504       switch (*mangled)
   1505 	{
   1506 	case 'S': /* Symbol parameter.  */
   1507 	  mangled++;
   1508 	  mangled = dlang_parse_symbol (decl, mangled, dlang_template_param);
   1509 	  break;
   1510 	case 'T': /* Type parameter.  */
   1511 	  mangled++;
   1512 	  mangled = dlang_type (decl, mangled);
   1513 	  break;
   1514 	case 'V': /* Value parameter.  */
   1515 	{
   1516 	  string name;
   1517 	  char type;
   1518 
   1519 	  /* Peek at the type.  */
   1520 	  mangled++;
   1521 	  type = *mangled;
   1522 
   1523 	  /* In the few instances where the type is actually desired in
   1524 	     the output, it should precede the value from dlang_value.  */
   1525 	  string_init (&name);
   1526 	  mangled = dlang_type (&name, mangled);
   1527 	  string_need (&name, 1);
   1528 	  *(name.p) = '\0';
   1529 
   1530 	  mangled = dlang_value (decl, mangled, name.b, type);
   1531 	  string_delete (&name);
   1532 	  break;
   1533 	}
   1534 
   1535 	default:
   1536 	  return NULL;
   1537 	}
   1538     }
   1539 
   1540   return mangled;
   1541 }
   1542 
   1543 /* Extract and demangle the template symbol in MANGLED, expected to
   1544    be made up of LEN characters, and append it to DECL.
   1545    Returns the remaining signature on success or NULL on failure.  */
   1546 static const char *
   1547 dlang_parse_template (string *decl, const char *mangled, long len)
   1548 {
   1549   const char *start = mangled;
   1550 
   1551   /* Template instance names have the types and values of its parameters
   1552      encoded into it.
   1553 
   1554 	TemplateInstanceName:
   1555 	    Number __T LName TemplateArgs Z
   1556 		   ^
   1557      The start pointer should be at the above location, and LEN should be
   1558      the value of the decoded number.
   1559    */
   1560   if (strncmp (mangled, "__T", 3) != 0)
   1561     return NULL;
   1562 
   1563   mangled += 3;
   1564 
   1565   /* Template identifier.  */
   1566   mangled = dlang_identifier (decl, mangled, dlang_template_ident);
   1567 
   1568   /* Template arguments.  */
   1569   string_append (decl, "!(");
   1570   mangled = dlang_template_args (decl, mangled);
   1571   string_append (decl, ")");
   1572 
   1573   /* Check for template name length mismatch.  */
   1574   if (mangled && (mangled - start) != len)
   1575     return NULL;
   1576 
   1577   return mangled;
   1578 }
   1579 
   1580 /* Extract and demangle the symbol in MANGLED.  Returns the demangled
   1581    signature on success or NULL on failure.  */
   1582 
   1583 char *
   1584 dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
   1585 {
   1586   string decl;
   1587   char *demangled = NULL;
   1588 
   1589   if (mangled == NULL || *mangled == '\0')
   1590     return NULL;
   1591 
   1592   if (strncmp (mangled, "_D", 2) != 0)
   1593     return NULL;
   1594 
   1595   string_init (&decl);
   1596 
   1597   if (strcmp (mangled, "_Dmain") == 0)
   1598     {
   1599       string_append (&decl, "D main");
   1600     }
   1601   else
   1602     {
   1603       mangled += 2;
   1604 
   1605       if (dlang_parse_symbol (&decl, mangled, dlang_top_level) == NULL)
   1606 	string_delete (&decl);
   1607     }
   1608 
   1609   if (string_length (&decl) > 0)
   1610     {
   1611       string_need (&decl, 1);
   1612       *(decl.p) = '\0';
   1613       demangled = decl.b;
   1614     }
   1615 
   1616   return demangled;
   1617 }
   1618 
   1619