Home | History | Annotate | Download | only in libiberty
      1 /* Demangler for the D programming language
      2    Copyright 2014 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 and strtod for decoding mangled literals.  */
     32 
     33 #ifdef HAVE_CONFIG_H
     34 #include "config.h"
     35 #endif
     36 
     37 #include "safe-ctype.h"
     38 
     39 #include <sys/types.h>
     40 #include <string.h>
     41 #include <stdio.h>
     42 
     43 #ifdef HAVE_STDLIB_H
     44 #include <stdlib.h>
     45 #else
     46 extern long strtol (const char *nptr, char **endptr, int base);
     47 extern double strtod (const char *nptr, char **endptr);
     48 #endif
     49 
     50 #include <demangle.h>
     51 #include "libiberty.h"
     52 
     53 /* A mini string-handling package */
     54 
     55 typedef struct string		/* Beware: these aren't required to be */
     56 {				/*  '\0' terminated.  */
     57   char *b;			/* pointer to start of string */
     58   char *p;			/* pointer after last character */
     59   char *e;			/* pointer after end of allocated space */
     60 } string;
     61 
     62 static void
     63 string_need (string *s, int n)
     64 {
     65   int tem;
     66 
     67   if (s->b == NULL)
     68     {
     69       if (n < 32)
     70 	{
     71 	  n = 32;
     72 	}
     73       s->p = s->b = XNEWVEC (char, n);
     74       s->e = s->b + n;
     75     }
     76   else if (s->e - s->p < n)
     77     {
     78       tem = s->p - s->b;
     79       n += tem;
     80       n *= 2;
     81       s->b = XRESIZEVEC (char, s->b, n);
     82       s->p = s->b + tem;
     83       s->e = s->b + n;
     84     }
     85 }
     86 
     87 static void
     88 string_delete (string *s)
     89 {
     90   if (s->b != NULL)
     91     {
     92       XDELETEVEC (s->b);
     93       s->b = s->e = s->p = NULL;
     94     }
     95 }
     96 
     97 static void
     98 string_init (string *s)
     99 {
    100   s->b = s->p = s->e = NULL;
    101 }
    102 
    103 static int
    104 string_length (string *s)
    105 {
    106   if (s->p == s->b)
    107     {
    108       return 0;
    109     }
    110   return s->p - s->b;
    111 }
    112 
    113 static void
    114 string_setlength (string *s, int n)
    115 {
    116   if (n - string_length (s) < 0)
    117     {
    118       s->p = s->b + n;
    119     }
    120 }
    121 
    122 static void
    123 string_append (string *p, const char *s)
    124 {
    125   int n = strlen (s);
    126   string_need (p, n);
    127   memcpy (p->p, s, n);
    128   p->p += n;
    129 }
    130 
    131 static void
    132 string_appendn (string *p, const char *s, int n)
    133 {
    134   if (n != 0)
    135     {
    136       string_need (p, n);
    137       memcpy (p->p, s, n);
    138       p->p += n;
    139     }
    140 }
    141 
    142 static void
    143 string_prependn (string *p, const char *s, int n)
    144 {
    145   char *q;
    146 
    147   if (n != 0)
    148     {
    149       string_need (p, n);
    150       for (q = p->p - 1; q >= p->b; q--)
    151 	{
    152 	  q[n] = q[0];
    153 	}
    154       memcpy (p->b, s, n);
    155       p->p += n;
    156     }
    157 }
    158 
    159 static void
    160 string_prepend (string *p, const char *s)
    161 {
    162   if (s != NULL && *s != '\0')
    163     {
    164       string_prependn (p, s, strlen (s));
    165     }
    166 }
    167 
    168 /* Prototypes for forward referenced functions */
    169 static const char *dlang_function_args (string *, const char *);
    170 
    171 static const char *dlang_type (string *, const char *);
    172 
    173 static const char *dlang_value (string *, const char *, const char *, char);
    174 
    175 static const char *dlang_parse_symbol (string *, const char *);
    176 
    177 static const char *dlang_parse_tuple (string *, const char *);
    178 
    179 static const char *dlang_parse_template (string *, const char *, long);
    180 
    181 
    182 /* Demangle the calling convention from MANGLED and append it to DECL.
    183    Return the remaining string on success or NULL on failure.  */
    184 static const char *
    185 dlang_call_convention (string *decl, const char *mangled)
    186 {
    187   if (mangled == NULL || *mangled == '\0')
    188     return mangled;
    189 
    190   switch (*mangled)
    191     {
    192     case 'F': /* (D) */
    193       mangled++;
    194       break;
    195     case 'U': /* (C) */
    196       mangled++;
    197       string_append (decl, "extern(C) ");
    198       break;
    199     case 'W': /* (Windows) */
    200       mangled++;
    201       string_append (decl, "extern(Windows) ");
    202       break;
    203     case 'V': /* (Pascal) */
    204       mangled++;
    205       string_append (decl, "extern(Pascal) ");
    206       break;
    207     case 'R': /* (C++) */
    208       mangled++;
    209       string_append (decl, "extern(C++) ");
    210       break;
    211     default:
    212       return NULL;
    213     }
    214 
    215   return mangled;
    216 }
    217 
    218 /* Demangle the D function attributes from MANGLED and append it to DECL.
    219    Return the remaining string on success or NULL on failure.  */
    220 static const char *
    221 dlang_attributes (string *decl, const char *mangled)
    222 {
    223   if (mangled == NULL || *mangled == '\0')
    224     return mangled;
    225 
    226   while (*mangled == 'N')
    227     {
    228       mangled++;
    229       switch (*mangled)
    230 	{
    231 	case 'a': /* pure */
    232 	  mangled++;
    233 	  string_append (decl, "pure ");
    234 	  continue;
    235 	case 'b': /* nothrow */
    236 	  mangled++;
    237 	  string_append (decl, "nothrow ");
    238 	  continue;
    239 	case 'c': /* ref */
    240 	  mangled++;
    241 	  string_append (decl, "ref ");
    242 	  continue;
    243 	case 'd': /* @property */
    244 	  mangled++;
    245 	  string_append (decl, "@property ");
    246 	  continue;
    247 	case 'e': /* @trusted */
    248 	  mangled++;
    249 	  string_append (decl, "@trusted ");
    250 	  continue;
    251 	case 'f': /* @safe */
    252 	  mangled++;
    253 	  string_append (decl, "@safe ");
    254 	  continue;
    255 	case 'g':
    256 	case 'h':
    257 	  /* inout parameter is represented as 'Ng'.
    258 	     vector parameter is represented as 'Nh'.
    259 	     If we see this, then we know we're really in the
    260 	     parameter list.  Rewind and break.  */
    261 	  mangled--;
    262 	  break;
    263 	case 'i': /* @nogc */
    264 	  mangled++;
    265 	  string_append (decl, "@nogc ");
    266 	  continue;
    267 	}
    268       break;
    269     }
    270 
    271   return mangled;
    272 }
    273 
    274 /* Demangle the function type from MANGLED and append it to DECL.
    275    Return the remaining string on success or NULL on failure.  */
    276 static const char *
    277 dlang_function_type (string *decl, const char *mangled)
    278 {
    279   string attr, args, type;
    280   size_t szattr, szargs, sztype;
    281 
    282   if (mangled == NULL || *mangled == '\0')
    283     return mangled;
    284 
    285   /* The order of the mangled string is:
    286 	CallConvention FuncAttrs Arguments ArgClose Type
    287 
    288      The demangled string is re-ordered as:
    289 	CallConvention Type Arguments FuncAttrs
    290    */
    291   string_init (&attr);
    292   string_init (&args);
    293   string_init (&type);
    294 
    295   /* Function call convention.  */
    296   mangled = dlang_call_convention (decl, mangled);
    297 
    298   /* Function attributes.  */
    299   mangled = dlang_attributes (&attr, mangled);
    300   szattr = string_length (&attr);
    301 
    302   /* Function arguments.  */
    303   mangled = dlang_function_args (&args, mangled);
    304   szargs = string_length (&args);
    305 
    306   /* Function return type.  */
    307   mangled = dlang_type (&type, mangled);
    308   sztype = string_length (&type);
    309 
    310   /* Append to decl in order. */
    311   string_appendn (decl, type.b, sztype);
    312   string_append (decl, "(");
    313   string_appendn (decl, args.b, szargs);
    314   string_append (decl, ") ");
    315   string_appendn (decl, attr.b, szattr);
    316 
    317   string_delete (&attr);
    318   string_delete (&args);
    319   string_delete (&type);
    320   return mangled;
    321 }
    322 
    323 /* Demangle the argument list from MANGLED and append it to DECL.
    324    Return the remaining string on success or NULL on failure.  */
    325 static const char *
    326 dlang_function_args (string *decl, const char *mangled)
    327 {
    328   size_t n = 0;
    329 
    330   while (mangled && *mangled != '\0')
    331     {
    332       switch (*mangled)
    333 	{
    334 	case 'X': /* (variadic T t...) style.  */
    335 	  mangled++;
    336 	  string_append (decl, "...");
    337 	  return mangled;
    338 	case 'Y': /* (variadic T t, ...) style.  */
    339 	  mangled++;
    340 	  string_append (decl, ", ...");
    341 	  return mangled;
    342 	case 'Z': /* Normal function.  */
    343 	  mangled++;
    344 	  return mangled;
    345 	}
    346 
    347       if (n++)
    348 	string_append (decl, ", ");
    349 
    350       if (*mangled == 'M') /* scope(T) */
    351 	{
    352 	  mangled++;
    353 	  string_append (decl, "scope ");
    354 	}
    355 
    356       switch (*mangled)
    357 	{
    358 	case 'J': /* out(T) */
    359 	  mangled++;
    360 	  string_append (decl, "out ");
    361 	  break;
    362 	case 'K': /* ref(T) */
    363 	  mangled++;
    364 	  string_append (decl, "ref ");
    365 	  break;
    366 	case 'L': /* lazy(T) */
    367 	  mangled++;
    368 	  string_append (decl, "lazy ");
    369 	  break;
    370 	}
    371       mangled = dlang_type (decl, mangled);
    372     }
    373 
    374   return mangled;
    375 }
    376 
    377 /* Demangle the type from MANGLED and append it to DECL.
    378    Return the remaining string on success or NULL on failure.  */
    379 static const char *
    380 dlang_type (string *decl, const char *mangled)
    381 {
    382   if (mangled == NULL || *mangled == '\0')
    383     return mangled;
    384 
    385   switch (*mangled)
    386     {
    387     case 'O': /* shared(T) */
    388       mangled++;
    389       string_append (decl, "shared(");
    390       mangled = dlang_type (decl, mangled);
    391       string_append (decl, ")");
    392       return mangled;
    393     case 'x': /* const(T) */
    394       mangled++;
    395       string_append (decl, "const(");
    396       mangled = dlang_type (decl, mangled);
    397       string_append (decl, ")");
    398       return mangled;
    399     case 'y': /* immutable(T) */
    400       mangled++;
    401       string_append (decl, "immutable(");
    402       mangled = dlang_type (decl, mangled);
    403       string_append (decl, ")");
    404       return mangled;
    405     case 'N':
    406       mangled++;
    407       if (*mangled == 'g') /* wild(T) */
    408 	{
    409 	  mangled++;
    410 	  string_append (decl, "inout(");
    411 	  mangled = dlang_type (decl, mangled);
    412 	  string_append (decl, ")");
    413 	  return mangled;
    414 	}
    415       else if (*mangled == 'h') /* vector(T) */
    416 	{
    417 	  mangled++;
    418 	  string_append (decl, "__vector(");
    419 	  mangled = dlang_type (decl, mangled);
    420 	  string_append (decl, ")");
    421 	  return mangled;
    422 	}
    423       else
    424 	return NULL;
    425     case 'A': /* dynamic array (T[]) */
    426       mangled++;
    427       mangled = dlang_type (decl, mangled);
    428       string_append (decl, "[]");
    429       return mangled;
    430     case 'G': /* static array (T[N]) */
    431     {
    432       const char *numptr;
    433       size_t num = 0;
    434       mangled++;
    435 
    436       numptr = mangled;
    437       while (ISDIGIT (*mangled))
    438 	{
    439 	  num++;
    440 	  mangled++;
    441 	}
    442       mangled = dlang_type (decl, mangled);
    443       string_append (decl, "[");
    444       string_appendn (decl, numptr, num);
    445       string_append (decl, "]");
    446       return mangled;
    447     }
    448     case 'H': /* associative array (T[T]) */
    449     {
    450       string type;
    451       size_t sztype;
    452       mangled++;
    453 
    454       string_init (&type);
    455       mangled = dlang_type (&type, mangled);
    456       sztype = string_length (&type);
    457 
    458       mangled = dlang_type (decl, mangled);
    459       string_append (decl, "[");
    460       string_appendn (decl, type.b, sztype);
    461       string_append (decl, "]");
    462 
    463       string_delete (&type);
    464       return mangled;
    465     }
    466     case 'P': /* pointer (T*) */
    467       mangled++;
    468       mangled = dlang_type (decl, mangled);
    469       string_append (decl, "*");
    470       return mangled;
    471     case 'I': /* ident T */
    472     case 'C': /* class T */
    473     case 'S': /* struct T */
    474     case 'E': /* enum T */
    475     case 'T': /* typedef T */
    476       mangled++;
    477       return dlang_parse_symbol (decl, mangled);
    478     case 'D': /* delegate T */
    479       mangled++;
    480       mangled = dlang_function_type (decl, mangled);
    481       string_append (decl, "delegate");
    482       return mangled;
    483     case 'B': /* tuple T */
    484       mangled++;
    485       return dlang_parse_tuple (decl, mangled);
    486 
    487     /* Function types */
    488     case 'F': case 'U': case 'W':
    489     case 'V': case 'R':
    490       mangled = dlang_function_type (decl, mangled);
    491       string_append (decl, "function");
    492       return mangled;
    493 
    494     /* Basic types */
    495     case 'n':
    496       mangled++;
    497       string_append (decl, "none");
    498       return mangled;
    499     case 'v':
    500       mangled++;
    501       string_append (decl, "void");
    502       return mangled;
    503     case 'g':
    504       mangled++;
    505       string_append (decl, "byte");
    506       return mangled;
    507     case 'h':
    508       mangled++;
    509       string_append (decl, "ubyte");
    510       return mangled;
    511     case 's':
    512       mangled++;
    513       string_append (decl, "short");
    514       return mangled;
    515     case 't':
    516       mangled++;
    517       string_append (decl, "ushort");
    518       return mangled;
    519     case 'i':
    520       mangled++;
    521       string_append (decl, "int");
    522       return mangled;
    523     case 'k':
    524       mangled++;
    525       string_append (decl, "uint");
    526       return mangled;
    527     case 'l':
    528       mangled++;
    529       string_append (decl, "long");
    530       return mangled;
    531     case 'm':
    532       mangled++;
    533       string_append (decl, "ulong");
    534       return mangled;
    535     case 'f':
    536       mangled++;
    537       string_append (decl, "float");
    538       return mangled;
    539     case 'd':
    540       mangled++;
    541       string_append (decl, "double");
    542       return mangled;
    543     case 'e':
    544       mangled++;
    545       string_append (decl, "real");
    546       return mangled;
    547 
    548     /* Imaginary and Complex types */
    549     case 'o':
    550       mangled++;
    551       string_append (decl, "ifloat");
    552       return mangled;
    553     case 'p':
    554       mangled++;
    555       string_append (decl, "idouble");
    556       return mangled;
    557     case 'j':
    558       mangled++;
    559       string_append (decl, "ireal");
    560       return mangled;
    561     case 'q':
    562       mangled++;
    563       string_append (decl, "cfloat");
    564       return mangled;
    565     case 'r':
    566       mangled++;
    567       string_append (decl, "cdouble");
    568       return mangled;
    569     case 'c':
    570       mangled++;
    571       string_append (decl, "creal");
    572       return mangled;
    573 
    574     /* Other types */
    575     case 'b':
    576       mangled++;
    577       string_append (decl, "bool");
    578       return mangled;
    579     case 'a':
    580       mangled++;
    581       string_append (decl, "char");
    582       return mangled;
    583     case 'u':
    584       mangled++;
    585       string_append (decl, "wchar");
    586       return mangled;
    587     case 'w':
    588       mangled++;
    589       string_append (decl, "dchar");
    590       return mangled;
    591 
    592     default: /* unhandled */
    593       return NULL;
    594     }
    595 }
    596 
    597 /* Extract the identifier from MANGLED and append it to DECL.
    598    Return the remaining string on success or NULL on failure.  */
    599 static const char *
    600 dlang_identifier (string *decl, const char *mangled)
    601 {
    602   if (mangled == NULL || *mangled == '\0')
    603     return mangled;
    604 
    605   if (ISDIGIT (*mangled))
    606     {
    607       char *endptr;
    608       long i = strtol (mangled, &endptr, 10);
    609 
    610       if (endptr == NULL || i <= 0 || strlen (endptr) < (size_t) i)
    611 	return NULL;
    612 
    613       mangled = endptr;
    614 
    615       /* May be a template instance.  */
    616       if (i >= 5 && strncmp (mangled, "__T", 3) == 0)
    617 	{
    618 	  /* Template symbol.  */
    619 	  if (ISDIGIT (mangled[3]) && mangled[3] != '0')
    620 	    return dlang_parse_template (decl, mangled, i);
    621 
    622 	  return NULL;
    623 	}
    624 
    625       if (strncmp (mangled, "__ctor", i) == 0)
    626 	{
    627 	  /* Constructor symbol for a class/struct.  */
    628 	  string_append (decl, "this");
    629 	  mangled += i;
    630 	  return mangled;
    631 	}
    632       else if (strncmp (mangled, "__dtor", i) == 0)
    633 	{
    634 	  /* Destructor symbol for a class/struct.  */
    635 	  string_append (decl, "~this");
    636 	  mangled += i;
    637 	  return mangled;
    638 	}
    639       else if (strncmp (mangled, "__postblit", i) == 0)
    640 	{
    641 	  /* Postblit symbol for a struct.  */
    642 	  string_append (decl, "this(this)");
    643 	  mangled += i;
    644 	  return mangled;
    645 	}
    646       else if (strncmp (mangled, "__initZ", i+1) == 0)
    647 	{
    648 	  /* The static initialiser for a given symbol.  */
    649 	  string_append (decl, "init$");
    650 	  mangled += i + 1;
    651 	  return mangled;
    652 	}
    653       else if (strncmp (mangled, "__ClassZ", i+1) == 0)
    654 	{
    655 	  /* The classinfo symbol for a given class.  */
    656 	  string_prepend (decl, "ClassInfo for ");
    657 	  string_setlength (decl, string_length (decl) - 1);
    658 	  mangled += i + 1;
    659 	  return mangled;
    660 	}
    661       else if (strncmp (mangled, "__vtblZ", i+1) == 0)
    662 	{
    663 	  /* The vtable symbol for a given class.  */
    664 	  string_prepend (decl, "vtable for ");
    665 	  string_setlength (decl, string_length (decl) - 1);
    666 	  mangled += i + 1;
    667 	  return mangled;
    668 	}
    669       else if (strncmp (mangled, "__InterfaceZ", i+1) == 0)
    670 	{
    671 	  /* The interface symbol for a given class.  */
    672 	  string_prepend (decl, "Interface for ");
    673 	  string_setlength (decl, string_length (decl) - 1);
    674 	  mangled += i + 1;
    675 	  return mangled;
    676 	}
    677       else if (strncmp (mangled, "__ModuleInfoZ", i+1) == 0)
    678 	{
    679 	  /* The ModuleInfo symbol for a given module.  */
    680 	  string_prepend (decl, "ModuleInfo for ");
    681 	  string_setlength (decl, string_length (decl) - 1);
    682 	  mangled += i + 1;
    683 	  return mangled;
    684 	}
    685 
    686       string_appendn (decl, mangled, i);
    687       mangled += i;
    688     }
    689   else
    690     return NULL;
    691 
    692   return mangled;
    693 }
    694 
    695 /* Extract the integer value from MANGLED and append it to DECL,
    696    where TYPE is the type it should be represented as.
    697    Return the remaining string on success or NULL on failure.  */
    698 static const char *
    699 dlang_parse_integer (string *decl, const char *mangled, char type)
    700 {
    701   if (type == 'a' || type == 'u' || type == 'w')
    702     {
    703       /* Parse character value.  */
    704       char value[10];
    705       int pos = 10;
    706       int width = 0;
    707       char *endptr;
    708       long val = strtol (mangled, &endptr, 10);
    709 
    710       if (endptr == NULL || val < 0)
    711 	return NULL;
    712 
    713       string_append (decl, "'");
    714 
    715       if (type == 'a' && val >= 0x20 && val < 0x7F)
    716 	{
    717 	  /* Represent as a character literal.  */
    718 	  char c = (char) val;
    719 	  string_appendn (decl, &c, 1);
    720 	}
    721       else
    722 	{
    723 	  /* Represent as a hexadecimal value.  */
    724 	  switch (type)
    725 	    {
    726 	    case 'a': /* char */
    727 	      string_append (decl, "\\x");
    728 	      width = 2;
    729 	      break;
    730 	    case 'u': /* wchar */
    731 	      string_append (decl, "\\u");
    732 	      width = 4;
    733 	      break;
    734 	    case 'w': /* dchar */
    735 	      string_append (decl, "\\U");
    736 	      width = 8;
    737 	      break;
    738 	    }
    739 
    740 	  while (val > 0)
    741 	    {
    742 	      int digit = val % 16;
    743 
    744 	      if (digit < 10)
    745 		value[--pos] = (char)(digit + '0');
    746 	      else
    747 		value[--pos] = (char)((digit - 10) + 'a');
    748 
    749 	      val /= 16;
    750 	      width--;
    751 	    }
    752 
    753 	  for (; width > 0; width--)
    754 	    value[--pos] = '0';
    755 
    756 	  string_appendn (decl, &(value[pos]), 10 - pos);
    757 	}
    758       string_append (decl, "'");
    759       mangled = endptr;
    760     }
    761   else if (type == 'b')
    762     {
    763       /* Parse boolean value.  */
    764       char *endptr;
    765       long val = strtol (mangled, &endptr, 10);
    766 
    767       if (endptr == NULL || val < 0)
    768 	return NULL;
    769 
    770       string_append (decl, val ? "true" : "false");
    771       mangled = endptr;
    772     }
    773   else
    774     {
    775       /* Parse integer value.  */
    776       const char *numptr = mangled;
    777       size_t num = 0;
    778 
    779       while (ISDIGIT (*mangled))
    780 	{
    781 	  num++;
    782 	  mangled++;
    783 	}
    784       string_appendn (decl, numptr, num);
    785 
    786       /* Append suffix.  */
    787       switch (type)
    788 	{
    789 	case 'h': /* ubyte */
    790 	case 't': /* ushort */
    791 	case 'k': /* uint */
    792 	  string_append (decl, "u");
    793 	  break;
    794 	case 'l': /* long */
    795 	  string_append (decl, "L");
    796 	  break;
    797 	case 'm': /* ulong */
    798 	  string_append (decl, "uL");
    799 	  break;
    800 	}
    801     }
    802 
    803   return mangled;
    804 }
    805 
    806 /* Extract the floating-point value from MANGLED and append it to DECL.
    807    Return the remaining string on success or NULL on failure.  */
    808 static const char *
    809 dlang_parse_real (string *decl, const char *mangled)
    810 {
    811   char buffer[64];
    812   int len = 0;
    813   double value;
    814   char *endptr;
    815 
    816   /* Handle NAN and +-INF.  */
    817   if (strncmp (mangled, "NAN", 3) == 0)
    818     {
    819       string_append (decl, "NaN");
    820       mangled += 3;
    821       return mangled;
    822     }
    823   else if (strncmp (mangled, "INF", 3) == 0)
    824     {
    825       string_append (decl, "Inf");
    826       mangled += 3;
    827       return mangled;
    828     }
    829   else if (strncmp (mangled, "NINF", 4) == 0)
    830     {
    831       string_append (decl, "-Inf");
    832       mangled += 4;
    833       return mangled;
    834     }
    835 
    836   /* Hexadecimal prefix and leading bit.  */
    837   if (*mangled == 'N')
    838     {
    839       buffer[len++] = '-';
    840       mangled++;
    841     }
    842 
    843   if (!ISXDIGIT (*mangled))
    844     return NULL;
    845 
    846   buffer[len++] = '0';
    847   buffer[len++] = 'x';
    848   buffer[len++] = *mangled;
    849   buffer[len++] = '.';
    850   mangled++;
    851 
    852   /* Significand.  */
    853   while (ISXDIGIT (*mangled))
    854     {
    855       buffer[len++] = *mangled;
    856       mangled++;
    857     }
    858 
    859   /* Exponent.  */
    860   if (*mangled != 'P')
    861     return NULL;
    862 
    863   buffer[len++] = 'p';
    864   mangled++;
    865 
    866   if (*mangled == 'N')
    867     {
    868       buffer[len++] = '-';
    869       mangled++;
    870     }
    871 
    872   while (ISDIGIT (*mangled))
    873     {
    874       buffer[len++] = *mangled;
    875       mangled++;
    876     }
    877 
    878   /* Convert buffer from hexadecimal to floating-point.  */
    879   buffer[len] = '\0';
    880   value = strtod (buffer, &endptr);
    881 
    882   if (endptr == NULL || endptr != (buffer + len))
    883     return NULL;
    884 
    885   len = snprintf (buffer, sizeof(buffer), "%#g", value);
    886   string_appendn (decl, buffer, len);
    887   return mangled;
    888 }
    889 
    890 /* Convert VAL from an ascii hexdigit to value.  */
    891 static char
    892 ascii2hex (char val)
    893 {
    894   if (val >= 'a' && val <= 'f')
    895     return (val - 'a' + 10);
    896 
    897   if (val >= 'A' && val <= 'F')
    898     return (val - 'A' + 10);
    899 
    900   if (val >= '0' && val <= '9')
    901     return (val - '0');
    902 
    903   return 0;
    904 }
    905 
    906 /* Extract the string value from MANGLED and append it to DECL.
    907    Return the remaining string on success or NULL on failure.  */
    908 static const char *
    909 dlang_parse_string (string *decl, const char *mangled)
    910 {
    911   char type = *mangled;
    912   char *endptr;
    913   long len;
    914 
    915   mangled++;
    916   len = strtol (mangled, &endptr, 10);
    917 
    918   if (endptr == NULL || len < 0)
    919     return NULL;
    920 
    921   mangled = endptr;
    922   if (*mangled != '_')
    923     return NULL;
    924 
    925   mangled++;
    926   string_append (decl, "\"");
    927   while (len--)
    928     {
    929       if (ISXDIGIT (mangled[0]) && ISXDIGIT (mangled[1]))
    930 	{
    931 	  char a = ascii2hex (mangled[0]);
    932 	  char b = ascii2hex (mangled[1]);
    933 	  char val = (a << 4) | b;
    934 	  string_appendn (decl, &val, 1);
    935 	}
    936       else
    937 	return NULL;
    938 
    939       mangled += 2;
    940     }
    941   string_append (decl, "\"");
    942 
    943   if (type != 'a')
    944     string_appendn (decl, &type, 1);
    945 
    946   return mangled;
    947 }
    948 
    949 /* Extract the static array value from MANGLED and append it to DECL.
    950    Return the remaining string on success or NULL on failure.  */
    951 static const char *
    952 dlang_parse_arrayliteral (string *decl, const char *mangled)
    953 {
    954   char *endptr;
    955   long elements = strtol (mangled, &endptr, 10);
    956 
    957   if (endptr == NULL || elements < 0)
    958     return NULL;
    959 
    960   mangled = endptr;
    961   string_append (decl, "[");
    962   while (elements--)
    963     {
    964       mangled = dlang_value (decl, mangled, NULL, '\0');
    965       if (elements != 0)
    966 	string_append (decl, ", ");
    967     }
    968 
    969   string_append (decl, "]");
    970   return mangled;
    971 }
    972 
    973 /* Extract the associative array value from MANGLED and append it to DECL.
    974    Return the remaining string on success or NULL on failure.  */
    975 static const char *
    976 dlang_parse_assocarray (string *decl, const char *mangled)
    977 {
    978   char *endptr;
    979   long elements = strtol (mangled, &endptr, 10);
    980 
    981   if (endptr == NULL || elements < 0)
    982     return NULL;
    983 
    984   mangled = endptr;
    985   string_append (decl, "[");
    986   while (elements--)
    987     {
    988       mangled = dlang_value (decl, mangled, NULL, '\0');
    989       string_append (decl, ":");
    990       mangled = dlang_value (decl, mangled, NULL, '\0');
    991 
    992       if (elements != 0)
    993 	string_append (decl, ", ");
    994     }
    995 
    996   string_append (decl, "]");
    997   return mangled;
    998 }
    999 
   1000 /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
   1001    Return the remaining string on success or NULL on failure.  */
   1002 static const char *
   1003 dlang_parse_structlit (string *decl, const char *mangled, const char *name)
   1004 {
   1005   char *endptr;
   1006   long args = strtol (mangled, &endptr, 10);
   1007 
   1008   if (endptr == NULL || args < 0)
   1009     return NULL;
   1010 
   1011   mangled = endptr;
   1012   if (name != NULL)
   1013     string_append (decl, name);
   1014 
   1015   string_append (decl, "(");
   1016   while (args--)
   1017     {
   1018       mangled = dlang_value (decl, mangled, NULL, '\0');
   1019       if (args != 0)
   1020 	string_append (decl, ", ");
   1021     }
   1022 
   1023   string_append (decl, ")");
   1024   return mangled;
   1025 }
   1026 
   1027 /* Extract the value from MANGLED and append it to DECL.
   1028    Return the remaining string on success or NULL on failure.  */
   1029 static const char *
   1030 dlang_value (string *decl, const char *mangled, const char *name, char type)
   1031 {
   1032   if (mangled == NULL || *mangled == '\0')
   1033     return mangled;
   1034 
   1035   switch (*mangled)
   1036     {
   1037       /* Null value.  */
   1038     case 'n':
   1039       mangled++;
   1040       string_append (decl, "null");
   1041       break;
   1042 
   1043       /* Integral values.  */
   1044     case 'N':
   1045       mangled++;
   1046       string_append (decl, "-");
   1047       mangled = dlang_parse_integer (decl, mangled, type);
   1048       break;
   1049 
   1050     case 'i':
   1051       mangled++;
   1052       if (*mangled < '0' || *mangled > '9')
   1053 	return NULL;
   1054       /* Fall through */
   1055     case '0': case '1': case '2': case '3': case '4':
   1056     case '5': case '6': case '7': case '8': case '9':
   1057       mangled = dlang_parse_integer (decl, mangled, type);
   1058       break;
   1059 
   1060       /* Real value.  */
   1061     case 'e':
   1062       mangled++;
   1063       mangled = dlang_parse_real (decl, mangled);
   1064       break;
   1065 
   1066       /* Complex value.  */
   1067     case 'c':
   1068       mangled++;
   1069       mangled = dlang_parse_real (decl, mangled);
   1070       string_append (decl, "+");
   1071       if (mangled == NULL || *mangled != 'c')
   1072 	return NULL;
   1073       mangled++;
   1074       mangled = dlang_parse_real (decl, mangled);
   1075       string_append (decl, "i");
   1076       break;
   1077 
   1078       /* String values.  */
   1079     case 'a': /* UTF8 */
   1080     case 'w': /* UTF16 */
   1081     case 'd': /* UTF32 */
   1082       mangled = dlang_parse_string (decl, mangled);
   1083       break;
   1084 
   1085       /* Array values.  */
   1086     case 'A':
   1087       mangled++;
   1088       if (type == 'H')
   1089 	mangled = dlang_parse_assocarray (decl, mangled);
   1090       else
   1091 	mangled = dlang_parse_arrayliteral (decl, mangled);
   1092       break;
   1093 
   1094       /* Struct values.  */
   1095     case 'S':
   1096       mangled++;
   1097       mangled = dlang_parse_structlit (decl, mangled, name);
   1098       break;
   1099 
   1100     default:
   1101       return NULL;
   1102     }
   1103 
   1104   return mangled;
   1105 }
   1106 
   1107 static int
   1108 dlang_call_convention_p (const char *mangled)
   1109 {
   1110   size_t i;
   1111 
   1112   switch (*mangled)
   1113     {
   1114     case 'F': case 'U': case 'V':
   1115     case 'W': case 'R':
   1116       return 1;
   1117 
   1118     case 'M': /* Prefix for functions needing 'this' */
   1119       i = 1;
   1120       if (mangled[i] == 'x')
   1121 	i++;
   1122 
   1123       switch (mangled[i])
   1124 	{
   1125 	case 'F': case 'U': case 'V':
   1126 	case 'W': case 'R':
   1127 	  return 1;
   1128 	}
   1129 
   1130     default:
   1131       return 0;
   1132     }
   1133 }
   1134 
   1135 /* Extract and demangle the symbol in MANGLED and append it to DECL.
   1136    Returns the remaining signature on success or NULL on failure.  */
   1137 static const char *
   1138 dlang_parse_symbol (string *decl, const char *mangled)
   1139 {
   1140   size_t n = 0;
   1141   do
   1142     {
   1143       if (n++)
   1144 	string_append (decl, ".");
   1145 
   1146       mangled = dlang_identifier (decl, mangled);
   1147 
   1148       if (mangled && dlang_call_convention_p (mangled))
   1149 	{
   1150 	  int saved;
   1151 
   1152 	  /* Skip over 'this' parameter.  */
   1153 	  if (*mangled == 'M')
   1154 	    mangled += (mangled[1] == 'x') ? 2 : 1;
   1155 
   1156 	  /* Skip over calling convention and attributes in qualified name.  */
   1157 	  saved = string_length (decl);
   1158 	  mangled = dlang_call_convention (decl, mangled);
   1159 	  mangled = dlang_attributes (decl, mangled);
   1160 	  string_setlength (decl, saved);
   1161 
   1162 	  string_append (decl, "(");
   1163 	  mangled = dlang_function_args (decl, mangled);
   1164 	  string_append (decl, ")");
   1165 
   1166 	  /* Demangle the function return type as a kind of sanity test.  */
   1167 	  if (mangled && !ISDIGIT (*mangled))
   1168 	    {
   1169 	      saved = string_length (decl);
   1170 	      mangled = dlang_type (decl, mangled);
   1171 	      string_setlength (decl, saved);
   1172 	    }
   1173 	}
   1174     }
   1175   while (mangled && ISDIGIT (*mangled));
   1176 
   1177   return mangled;
   1178 }
   1179 
   1180 /* Demangle the tuple from MANGLED and append it to DECL.
   1181    Return the remaining string on success or NULL on failure.  */
   1182 static const char *
   1183 dlang_parse_tuple (string *decl, const char *mangled)
   1184 {
   1185   char *endptr;
   1186   long elements = strtol (mangled, &endptr, 10);
   1187 
   1188   if (endptr == NULL || elements < 0)
   1189     return NULL;
   1190 
   1191   mangled = endptr;
   1192   string_append (decl, "Tuple!(");
   1193 
   1194   while (elements--)
   1195     {
   1196       mangled = dlang_type (decl, mangled);
   1197       if (elements != 0)
   1198 	string_append (decl, ", ");
   1199     }
   1200 
   1201   string_append (decl, ")");
   1202   return mangled;
   1203 }
   1204 
   1205 /* Demangle the argument list from MANGLED and append it to DECL.
   1206    Return the remaining string on success or NULL on failure.  */
   1207 static const char *
   1208 dlang_template_args (string *decl, const char *mangled)
   1209 {
   1210   size_t n = 0;
   1211 
   1212   while (mangled && *mangled != '\0')
   1213     {
   1214       switch (*mangled)
   1215 	{
   1216 	case 'Z': /* End of parameter list.  */
   1217 	  mangled++;
   1218 	  return mangled;
   1219 	}
   1220 
   1221       if (n++)
   1222 	string_append (decl, ", ");
   1223 
   1224       switch (*mangled)
   1225 	{
   1226 	case 'S': /* Symbol parameter.  */
   1227 	  mangled++;
   1228 	  mangled = dlang_parse_symbol (decl, mangled);
   1229 	  break;
   1230 	case 'T': /* Type parameter.  */
   1231 	  mangled++;
   1232 	  mangled = dlang_type (decl, mangled);
   1233 	  break;
   1234 	case 'V': /* Value parameter.  */
   1235 	{
   1236 	  string name;
   1237 	  char type;
   1238 
   1239 	  /* Peek at the type.  */
   1240 	  mangled++;
   1241 	  type = *mangled;
   1242 
   1243 	  /* In the few instances where the type is actually desired in
   1244 	     the output, it should precede the value from dlang_value.  */
   1245 	  string_init (&name);
   1246 	  mangled = dlang_type (&name, mangled);
   1247 	  string_need (&name, 1);
   1248 	  *(name.p) = '\0';
   1249 
   1250 	  mangled = dlang_value (decl, mangled, name.b, type);
   1251 	  string_delete (&name);
   1252 	  break;
   1253 	}
   1254 
   1255 	default:
   1256 	  return NULL;
   1257 	}
   1258     }
   1259 
   1260   return mangled;
   1261 }
   1262 
   1263 /* Extract and demangle the template symbol in MANGLED, expected to
   1264    be made up of LEN characters, and append it to DECL.
   1265    Returns the remaining signature on success or NULL on failure.  */
   1266 static const char *
   1267 dlang_parse_template (string *decl, const char *mangled, long len)
   1268 {
   1269   const char *start = mangled;
   1270 
   1271   /* Template instance names have the types and values of its parameters
   1272      encoded into it.
   1273 
   1274 	TemplateInstanceName:
   1275 	    Number __T LName TemplateArgs Z
   1276 		   ^
   1277      The start pointer should be at the above location, and LEN should be
   1278      the value of the decoded number.
   1279    */
   1280   if (strncmp (mangled, "__T", 3) != 0)
   1281     return NULL;
   1282 
   1283   mangled += 3;
   1284 
   1285   /* Template identifier.  */
   1286   mangled = dlang_identifier (decl, mangled);
   1287 
   1288   /* Template arguments.  */
   1289   string_append (decl, "!(");
   1290   mangled = dlang_template_args (decl, mangled);
   1291   string_append (decl, ")");
   1292 
   1293   /* Check for template name length mismatch.  */
   1294   if (mangled && (mangled - start) != len)
   1295     return NULL;
   1296 
   1297   return mangled;
   1298 }
   1299 
   1300 /* Extract and demangle the symbol in MANGLED.  Returns the demangled
   1301    signature on success or NULL on failure.  */
   1302 
   1303 char *
   1304 dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
   1305 {
   1306   string decl;
   1307   char *demangled = NULL;
   1308 
   1309   if (mangled == NULL || *mangled == '\0')
   1310     return NULL;
   1311 
   1312   if (strncmp (mangled, "_D", 2) != 0)
   1313     return NULL;
   1314 
   1315   string_init (&decl);
   1316 
   1317   if (strcmp (mangled, "_Dmain") == 0)
   1318     {
   1319       string_append (&decl, "D main");
   1320     }
   1321   else
   1322     {
   1323       mangled += 2;
   1324 
   1325       if (dlang_parse_symbol (&decl, mangled) == NULL)
   1326 	string_delete (&decl);
   1327     }
   1328 
   1329   if (string_length (&decl) > 0)
   1330     {
   1331       string_need (&decl, 1);
   1332       *(decl.p) = '\0';
   1333       demangled = decl.b;
   1334     }
   1335 
   1336   return demangled;
   1337 }
   1338 
   1339