Home | History | Annotate | Line # | Download | only in libiberty
      1       1.1  mrg /* Demangler for the D programming language
      2  1.1.1.10  mrg    Copyright (C) 2014-2024 Free Software Foundation, Inc.
      3       1.1  mrg    Written by Iain Buclaw (ibuclaw (at) gdcproject.org)
      4       1.1  mrg 
      5       1.1  mrg This file is part of the libiberty library.
      6       1.1  mrg Libiberty is free software; you can redistribute it and/or
      7       1.1  mrg modify it under the terms of the GNU Library General Public
      8       1.1  mrg License as published by the Free Software Foundation; either
      9       1.1  mrg version 2 of the License, or (at your option) any later version.
     10       1.1  mrg 
     11       1.1  mrg In addition to the permissions in the GNU Library General Public
     12       1.1  mrg License, the Free Software Foundation gives you unlimited permission
     13       1.1  mrg to link the compiled version of this file into combinations with other
     14       1.1  mrg programs, and to distribute those combinations without any restriction
     15       1.1  mrg coming from the use of this file.  (The Library Public License
     16       1.1  mrg restrictions do apply in other respects; for example, they cover
     17       1.1  mrg modification of the file, and distribution when not linked into a
     18       1.1  mrg combined executable.)
     19       1.1  mrg 
     20       1.1  mrg Libiberty is distributed in the hope that it will be useful,
     21       1.1  mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
     22       1.1  mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     23       1.1  mrg Library General Public License for more details.
     24       1.1  mrg 
     25       1.1  mrg You should have received a copy of the GNU Library General Public
     26       1.1  mrg License along with libiberty; see the file COPYING.LIB.
     27       1.1  mrg If not, see <http://www.gnu.org/licenses/>.  */
     28       1.1  mrg 
     29   1.1.1.6  mrg /* This file exports one function; dlang_demangle.  */
     30       1.1  mrg 
     31       1.1  mrg #ifdef HAVE_CONFIG_H
     32       1.1  mrg #include "config.h"
     33       1.1  mrg #endif
     34   1.1.1.9  mrg #ifdef HAVE_LIMITS_H
     35   1.1.1.9  mrg #include <limits.h>
     36   1.1.1.9  mrg #endif
     37       1.1  mrg 
     38       1.1  mrg #include "safe-ctype.h"
     39       1.1  mrg 
     40       1.1  mrg #include <sys/types.h>
     41       1.1  mrg #include <string.h>
     42       1.1  mrg #include <stdio.h>
     43       1.1  mrg 
     44       1.1  mrg #ifdef HAVE_STDLIB_H
     45       1.1  mrg #include <stdlib.h>
     46       1.1  mrg #endif
     47       1.1  mrg 
     48       1.1  mrg #include <demangle.h>
     49       1.1  mrg #include "libiberty.h"
     50       1.1  mrg 
     51   1.1.1.9  mrg #ifndef ULONG_MAX
     52   1.1.1.9  mrg #define	ULONG_MAX	(~0UL)
     53   1.1.1.9  mrg #endif
     54   1.1.1.9  mrg #ifndef UINT_MAX
     55   1.1.1.9  mrg #define	UINT_MAX	(~0U)
     56   1.1.1.9  mrg #endif
     57   1.1.1.9  mrg 
     58       1.1  mrg /* A mini string-handling package */
     59       1.1  mrg 
     60       1.1  mrg typedef struct string		/* Beware: these aren't required to be */
     61       1.1  mrg {				/*  '\0' terminated.  */
     62       1.1  mrg   char *b;			/* pointer to start of string */
     63       1.1  mrg   char *p;			/* pointer after last character */
     64       1.1  mrg   char *e;			/* pointer after end of allocated space */
     65       1.1  mrg } string;
     66       1.1  mrg 
     67       1.1  mrg static void
     68   1.1.1.9  mrg string_need (string *s, size_t n)
     69       1.1  mrg {
     70   1.1.1.9  mrg   size_t tem;
     71       1.1  mrg 
     72       1.1  mrg   if (s->b == NULL)
     73       1.1  mrg     {
     74       1.1  mrg       if (n < 32)
     75       1.1  mrg 	{
     76       1.1  mrg 	  n = 32;
     77       1.1  mrg 	}
     78       1.1  mrg       s->p = s->b = XNEWVEC (char, n);
     79       1.1  mrg       s->e = s->b + n;
     80       1.1  mrg     }
     81   1.1.1.9  mrg   else if ((size_t) (s->e - s->p) < n)
     82       1.1  mrg     {
     83       1.1  mrg       tem = s->p - s->b;
     84       1.1  mrg       n += tem;
     85       1.1  mrg       n *= 2;
     86       1.1  mrg       s->b = XRESIZEVEC (char, s->b, n);
     87       1.1  mrg       s->p = s->b + tem;
     88       1.1  mrg       s->e = s->b + n;
     89       1.1  mrg     }
     90       1.1  mrg }
     91       1.1  mrg 
     92       1.1  mrg static void
     93       1.1  mrg string_delete (string *s)
     94       1.1  mrg {
     95       1.1  mrg   if (s->b != NULL)
     96       1.1  mrg     {
     97       1.1  mrg       XDELETEVEC (s->b);
     98       1.1  mrg       s->b = s->e = s->p = NULL;
     99       1.1  mrg     }
    100       1.1  mrg }
    101       1.1  mrg 
    102       1.1  mrg static void
    103       1.1  mrg string_init (string *s)
    104       1.1  mrg {
    105       1.1  mrg   s->b = s->p = s->e = NULL;
    106       1.1  mrg }
    107       1.1  mrg 
    108       1.1  mrg static int
    109       1.1  mrg string_length (string *s)
    110       1.1  mrg {
    111       1.1  mrg   if (s->p == s->b)
    112       1.1  mrg     {
    113       1.1  mrg       return 0;
    114       1.1  mrg     }
    115       1.1  mrg   return s->p - s->b;
    116       1.1  mrg }
    117       1.1  mrg 
    118       1.1  mrg static void
    119       1.1  mrg string_setlength (string *s, int n)
    120       1.1  mrg {
    121       1.1  mrg   if (n - string_length (s) < 0)
    122       1.1  mrg     {
    123       1.1  mrg       s->p = s->b + n;
    124       1.1  mrg     }
    125       1.1  mrg }
    126       1.1  mrg 
    127       1.1  mrg static void
    128       1.1  mrg string_append (string *p, const char *s)
    129       1.1  mrg {
    130   1.1.1.9  mrg   size_t n = strlen (s);
    131       1.1  mrg   string_need (p, n);
    132       1.1  mrg   memcpy (p->p, s, n);
    133       1.1  mrg   p->p += n;
    134       1.1  mrg }
    135       1.1  mrg 
    136       1.1  mrg static void
    137   1.1.1.9  mrg string_appendn (string *p, const char *s, size_t n)
    138       1.1  mrg {
    139       1.1  mrg   if (n != 0)
    140       1.1  mrg     {
    141       1.1  mrg       string_need (p, n);
    142       1.1  mrg       memcpy (p->p, s, n);
    143       1.1  mrg       p->p += n;
    144       1.1  mrg     }
    145       1.1  mrg }
    146       1.1  mrg 
    147       1.1  mrg static void
    148   1.1.1.9  mrg string_prependn (string *p, const char *s, size_t n)
    149       1.1  mrg {
    150       1.1  mrg   char *q;
    151       1.1  mrg 
    152       1.1  mrg   if (n != 0)
    153       1.1  mrg     {
    154       1.1  mrg       string_need (p, n);
    155       1.1  mrg       for (q = p->p - 1; q >= p->b; q--)
    156       1.1  mrg 	{
    157       1.1  mrg 	  q[n] = q[0];
    158       1.1  mrg 	}
    159       1.1  mrg       memcpy (p->b, s, n);
    160       1.1  mrg       p->p += n;
    161       1.1  mrg     }
    162       1.1  mrg }
    163       1.1  mrg 
    164       1.1  mrg static void
    165       1.1  mrg string_prepend (string *p, const char *s)
    166       1.1  mrg {
    167       1.1  mrg   if (s != NULL && *s != '\0')
    168       1.1  mrg     {
    169       1.1  mrg       string_prependn (p, s, strlen (s));
    170       1.1  mrg     }
    171       1.1  mrg }
    172       1.1  mrg 
    173   1.1.1.9  mrg /* Demangle information structure we pass around.  */
    174   1.1.1.9  mrg struct dlang_info
    175   1.1.1.2  mrg {
    176   1.1.1.9  mrg   /* The string we are demangling.  */
    177   1.1.1.9  mrg   const char *s;
    178   1.1.1.9  mrg   /* The index of the last back reference.  */
    179   1.1.1.9  mrg   int last_backref;
    180   1.1.1.2  mrg };
    181   1.1.1.2  mrg 
    182   1.1.1.9  mrg /* Pass as the LEN to dlang_parse_template if symbol length is not known.  */
    183   1.1.1.9  mrg #define TEMPLATE_LENGTH_UNKNOWN (-1UL)
    184   1.1.1.9  mrg 
    185       1.1  mrg /* Prototypes for forward referenced functions */
    186   1.1.1.9  mrg static const char *dlang_function_type (string *, const char *,
    187   1.1.1.9  mrg 					struct dlang_info *);
    188   1.1.1.9  mrg 
    189   1.1.1.9  mrg static const char *dlang_function_args (string *, const char *,
    190   1.1.1.9  mrg 					struct dlang_info *);
    191       1.1  mrg 
    192   1.1.1.9  mrg static const char *dlang_type (string *, const char *, struct dlang_info *);
    193       1.1  mrg 
    194   1.1.1.9  mrg static const char *dlang_value (string *, const char *, const char *, char,
    195   1.1.1.9  mrg 				struct dlang_info *);
    196       1.1  mrg 
    197   1.1.1.6  mrg static const char *dlang_parse_qualified (string *, const char *,
    198   1.1.1.9  mrg 					  struct dlang_info *, int);
    199   1.1.1.6  mrg 
    200   1.1.1.6  mrg static const char *dlang_parse_mangle (string *, const char *,
    201   1.1.1.9  mrg 				       struct dlang_info *);
    202       1.1  mrg 
    203   1.1.1.9  mrg static const char *dlang_parse_tuple (string *, const char *,
    204   1.1.1.9  mrg 				      struct dlang_info *);
    205       1.1  mrg 
    206   1.1.1.9  mrg static const char *dlang_parse_template (string *, const char *,
    207   1.1.1.9  mrg 					 struct dlang_info *, unsigned long);
    208   1.1.1.9  mrg 
    209   1.1.1.9  mrg static const char *dlang_lname (string *, const char *, unsigned long);
    210       1.1  mrg 
    211       1.1  mrg 
    212   1.1.1.6  mrg /* Extract the number from MANGLED, and assign the result to RET.
    213   1.1.1.9  mrg    Return the remaining string on success or NULL on failure.
    214   1.1.1.9  mrg    A result larger than UINT_MAX is considered a failure.  */
    215   1.1.1.6  mrg static const char *
    216   1.1.1.9  mrg dlang_number (const char *mangled, unsigned long *ret)
    217   1.1.1.6  mrg {
    218   1.1.1.6  mrg   /* Return NULL if trying to extract something that isn't a digit.  */
    219   1.1.1.6  mrg   if (mangled == NULL || !ISDIGIT (*mangled))
    220   1.1.1.6  mrg     return NULL;
    221   1.1.1.6  mrg 
    222   1.1.1.9  mrg   unsigned long val = 0;
    223   1.1.1.6  mrg 
    224   1.1.1.6  mrg   while (ISDIGIT (*mangled))
    225   1.1.1.6  mrg     {
    226   1.1.1.9  mrg       unsigned long digit = mangled[0] - '0';
    227   1.1.1.6  mrg 
    228   1.1.1.9  mrg       /* Check for overflow.  */
    229   1.1.1.9  mrg       if (val > (UINT_MAX - digit) / 10)
    230   1.1.1.6  mrg 	return NULL;
    231   1.1.1.6  mrg 
    232   1.1.1.9  mrg       val = val * 10 + digit;
    233   1.1.1.6  mrg       mangled++;
    234   1.1.1.6  mrg     }
    235   1.1.1.6  mrg 
    236   1.1.1.9  mrg   if (*mangled == '\0')
    237   1.1.1.6  mrg     return NULL;
    238   1.1.1.6  mrg 
    239   1.1.1.9  mrg   *ret = val;
    240   1.1.1.6  mrg   return mangled;
    241   1.1.1.6  mrg }
    242   1.1.1.6  mrg 
    243   1.1.1.6  mrg /* Extract the hex-digit from MANGLED, and assign the result to RET.
    244   1.1.1.6  mrg    Return the remaining string on success or NULL on failure.  */
    245   1.1.1.6  mrg static const char *
    246   1.1.1.6  mrg dlang_hexdigit (const char *mangled, char *ret)
    247   1.1.1.6  mrg {
    248   1.1.1.6  mrg   char c;
    249   1.1.1.6  mrg 
    250   1.1.1.6  mrg   /* Return NULL if trying to extract something that isn't a hexdigit.  */
    251   1.1.1.6  mrg   if (mangled == NULL || !ISXDIGIT (mangled[0]) || !ISXDIGIT (mangled[1]))
    252   1.1.1.6  mrg     return NULL;
    253   1.1.1.6  mrg 
    254   1.1.1.6  mrg   c = mangled[0];
    255   1.1.1.6  mrg   if (!ISDIGIT (c))
    256   1.1.1.9  mrg     *ret = c - (ISUPPER (c) ? 'A' : 'a') + 10;
    257   1.1.1.6  mrg   else
    258   1.1.1.9  mrg     *ret = c - '0';
    259   1.1.1.6  mrg 
    260   1.1.1.6  mrg   c = mangled[1];
    261   1.1.1.6  mrg   if (!ISDIGIT (c))
    262   1.1.1.9  mrg     *ret = (*ret << 4) | (c - (ISUPPER (c) ? 'A' : 'a') + 10);
    263   1.1.1.6  mrg   else
    264   1.1.1.9  mrg     *ret = (*ret << 4) | (c - '0');
    265   1.1.1.6  mrg 
    266   1.1.1.6  mrg   mangled += 2;
    267   1.1.1.6  mrg 
    268   1.1.1.6  mrg   return mangled;
    269   1.1.1.6  mrg }
    270   1.1.1.6  mrg 
    271   1.1.1.6  mrg /* Extract the function calling convention from MANGLED and
    272   1.1.1.6  mrg    return 1 on success or 0 on failure.  */
    273   1.1.1.6  mrg static int
    274   1.1.1.6  mrg dlang_call_convention_p (const char *mangled)
    275   1.1.1.6  mrg {
    276   1.1.1.6  mrg   switch (*mangled)
    277   1.1.1.6  mrg     {
    278   1.1.1.6  mrg     case 'F': case 'U': case 'V':
    279   1.1.1.6  mrg     case 'W': case 'R': case 'Y':
    280   1.1.1.6  mrg       return 1;
    281   1.1.1.6  mrg 
    282   1.1.1.6  mrg     default:
    283   1.1.1.6  mrg       return 0;
    284   1.1.1.6  mrg     }
    285   1.1.1.6  mrg }
    286   1.1.1.6  mrg 
    287   1.1.1.9  mrg /* Extract the back reference position from MANGLED, and assign the result
    288   1.1.1.9  mrg    to RET.  Return the remaining string on success or NULL on failure.
    289   1.1.1.9  mrg    A result <= 0 is a failure.  */
    290   1.1.1.9  mrg static const char *
    291   1.1.1.9  mrg dlang_decode_backref (const char *mangled, long *ret)
    292   1.1.1.9  mrg {
    293   1.1.1.9  mrg   /* Return NULL if trying to extract something that isn't a digit.  */
    294   1.1.1.9  mrg   if (mangled == NULL || !ISALPHA (*mangled))
    295   1.1.1.9  mrg     return NULL;
    296   1.1.1.9  mrg 
    297   1.1.1.9  mrg   /* Any identifier or non-basic type that has been emitted to the mangled
    298   1.1.1.9  mrg      symbol before will not be emitted again, but is referenced by a special
    299   1.1.1.9  mrg      sequence encoding the relative position of the original occurrence in the
    300   1.1.1.9  mrg      mangled symbol name.
    301   1.1.1.9  mrg 
    302   1.1.1.9  mrg      Numbers in back references are encoded with base 26 by upper case letters
    303   1.1.1.9  mrg      A-Z for higher digits but lower case letters a-z for the last digit.
    304   1.1.1.9  mrg 
    305   1.1.1.9  mrg 	NumberBackRef:
    306   1.1.1.9  mrg 	    [a-z]
    307   1.1.1.9  mrg 	    [A-Z] NumberBackRef
    308   1.1.1.9  mrg 	    ^
    309   1.1.1.9  mrg    */
    310   1.1.1.9  mrg   unsigned long val = 0;
    311   1.1.1.9  mrg 
    312   1.1.1.9  mrg   while (ISALPHA (*mangled))
    313   1.1.1.9  mrg     {
    314   1.1.1.9  mrg       /* Check for overflow.  */
    315   1.1.1.9  mrg       if (val > (ULONG_MAX - 25) / 26)
    316   1.1.1.9  mrg 	break;
    317   1.1.1.9  mrg 
    318   1.1.1.9  mrg       val *= 26;
    319   1.1.1.9  mrg 
    320   1.1.1.9  mrg       if (mangled[0] >= 'a' && mangled[0] <= 'z')
    321   1.1.1.9  mrg 	{
    322   1.1.1.9  mrg 	  val += mangled[0] - 'a';
    323   1.1.1.9  mrg 	  if ((long) val <= 0)
    324   1.1.1.9  mrg 	    break;
    325   1.1.1.9  mrg 	  *ret = val;
    326   1.1.1.9  mrg 	  return mangled + 1;
    327   1.1.1.9  mrg 	}
    328   1.1.1.9  mrg 
    329   1.1.1.9  mrg       val += mangled[0] - 'A';
    330   1.1.1.9  mrg       mangled++;
    331   1.1.1.9  mrg     }
    332   1.1.1.9  mrg 
    333   1.1.1.9  mrg   return NULL;
    334   1.1.1.9  mrg }
    335   1.1.1.9  mrg 
    336   1.1.1.9  mrg /* Extract the symbol pointed at by the back reference and assign the result
    337   1.1.1.9  mrg    to RET.  Return the remaining string on success or NULL on failure.  */
    338   1.1.1.9  mrg static const char *
    339   1.1.1.9  mrg dlang_backref (const char *mangled, const char **ret, struct dlang_info *info)
    340   1.1.1.9  mrg {
    341   1.1.1.9  mrg   *ret = NULL;
    342   1.1.1.9  mrg 
    343   1.1.1.9  mrg   if (mangled == NULL || *mangled != 'Q')
    344   1.1.1.9  mrg     return NULL;
    345   1.1.1.9  mrg 
    346   1.1.1.9  mrg   /* Position of 'Q'.  */
    347   1.1.1.9  mrg   const char *qpos = mangled;
    348   1.1.1.9  mrg   long refpos;
    349   1.1.1.9  mrg   mangled++;
    350   1.1.1.9  mrg 
    351   1.1.1.9  mrg   mangled = dlang_decode_backref (mangled, &refpos);
    352   1.1.1.9  mrg   if (mangled == NULL)
    353   1.1.1.9  mrg     return NULL;
    354   1.1.1.9  mrg 
    355   1.1.1.9  mrg   if (refpos > qpos - info->s)
    356   1.1.1.9  mrg     return NULL;
    357   1.1.1.9  mrg 
    358   1.1.1.9  mrg   /* Set the position of the back reference.  */
    359   1.1.1.9  mrg   *ret = qpos - refpos;
    360   1.1.1.9  mrg 
    361   1.1.1.9  mrg   return mangled;
    362   1.1.1.9  mrg }
    363   1.1.1.9  mrg 
    364   1.1.1.9  mrg /* Demangle a back referenced symbol from MANGLED and append it to DECL.
    365   1.1.1.9  mrg    Return the remaining string on success or NULL on failure.  */
    366   1.1.1.9  mrg static const char *
    367   1.1.1.9  mrg dlang_symbol_backref (string *decl, const char *mangled,
    368   1.1.1.9  mrg 		      struct dlang_info *info)
    369   1.1.1.9  mrg {
    370   1.1.1.9  mrg   /* An identifier back reference always points to a digit 0 to 9.
    371   1.1.1.9  mrg 
    372   1.1.1.9  mrg 	IdentifierBackRef:
    373   1.1.1.9  mrg 	    Q NumberBackRef
    374   1.1.1.9  mrg 	    ^
    375   1.1.1.9  mrg    */
    376   1.1.1.9  mrg   const char *backref;
    377   1.1.1.9  mrg   unsigned long len;
    378   1.1.1.9  mrg 
    379   1.1.1.9  mrg   /* Get position of the back reference.  */
    380   1.1.1.9  mrg   mangled = dlang_backref (mangled, &backref, info);
    381   1.1.1.9  mrg 
    382   1.1.1.9  mrg   /* Must point to a simple identifier.  */
    383   1.1.1.9  mrg   backref = dlang_number (backref, &len);
    384   1.1.1.9  mrg   if (backref == NULL || strlen(backref) < len)
    385   1.1.1.9  mrg     return NULL;
    386   1.1.1.9  mrg 
    387   1.1.1.9  mrg   backref = dlang_lname (decl, backref, len);
    388   1.1.1.9  mrg   if (backref == NULL)
    389   1.1.1.9  mrg     return NULL;
    390   1.1.1.9  mrg 
    391   1.1.1.9  mrg   return mangled;
    392   1.1.1.9  mrg }
    393   1.1.1.9  mrg 
    394   1.1.1.9  mrg /* Demangle a back referenced type from MANGLED and append it to DECL.
    395   1.1.1.9  mrg    IS_FUNCTION is 1 if the back referenced type is expected to be a function.
    396   1.1.1.9  mrg    Return the remaining string on success or NULL on failure.  */
    397   1.1.1.9  mrg static const char *
    398   1.1.1.9  mrg dlang_type_backref (string *decl, const char *mangled, struct dlang_info *info,
    399   1.1.1.9  mrg 		    int is_function)
    400   1.1.1.9  mrg {
    401   1.1.1.9  mrg   /* A type back reference always points to a letter.
    402   1.1.1.9  mrg 
    403   1.1.1.9  mrg 	TypeBackRef:
    404   1.1.1.9  mrg 	    Q NumberBackRef
    405   1.1.1.9  mrg 	    ^
    406   1.1.1.9  mrg    */
    407   1.1.1.9  mrg   const char *backref;
    408   1.1.1.9  mrg 
    409   1.1.1.9  mrg   /* If we appear to be moving backwards through the mangle string, then
    410   1.1.1.9  mrg      bail as this may be a recursive back reference.  */
    411   1.1.1.9  mrg   if (mangled - info->s >= info->last_backref)
    412   1.1.1.9  mrg     return NULL;
    413   1.1.1.9  mrg 
    414   1.1.1.9  mrg   int save_refpos = info->last_backref;
    415   1.1.1.9  mrg   info->last_backref = mangled - info->s;
    416   1.1.1.9  mrg 
    417   1.1.1.9  mrg   /* Get position of the back reference.  */
    418   1.1.1.9  mrg   mangled = dlang_backref (mangled, &backref, info);
    419   1.1.1.9  mrg 
    420   1.1.1.9  mrg   /* Must point to a type.  */
    421   1.1.1.9  mrg   if (is_function)
    422   1.1.1.9  mrg     backref = dlang_function_type (decl, backref, info);
    423   1.1.1.9  mrg   else
    424   1.1.1.9  mrg     backref = dlang_type (decl, backref, info);
    425   1.1.1.9  mrg 
    426   1.1.1.9  mrg   info->last_backref = save_refpos;
    427   1.1.1.9  mrg 
    428   1.1.1.9  mrg   if (backref == NULL)
    429   1.1.1.9  mrg     return NULL;
    430   1.1.1.9  mrg 
    431   1.1.1.9  mrg   return mangled;
    432   1.1.1.9  mrg }
    433   1.1.1.9  mrg 
    434   1.1.1.9  mrg /* Extract the beginning of a symbol name from MANGLED and
    435   1.1.1.9  mrg    return 1 on success or 0 on failure.  */
    436   1.1.1.9  mrg static int
    437   1.1.1.9  mrg dlang_symbol_name_p (const char *mangled, struct dlang_info *info)
    438   1.1.1.9  mrg {
    439   1.1.1.9  mrg   long ret;
    440   1.1.1.9  mrg   const char *qref = mangled;
    441   1.1.1.9  mrg 
    442   1.1.1.9  mrg   if (ISDIGIT (*mangled))
    443   1.1.1.9  mrg     return 1;
    444   1.1.1.9  mrg 
    445   1.1.1.9  mrg   if (mangled[0] == '_' && mangled[1] == '_'
    446   1.1.1.9  mrg       && (mangled[2] == 'T' || mangled[2] == 'U'))
    447   1.1.1.9  mrg     return 1;
    448   1.1.1.9  mrg 
    449   1.1.1.9  mrg   if (*mangled != 'Q')
    450   1.1.1.9  mrg     return 0;
    451   1.1.1.9  mrg 
    452   1.1.1.9  mrg   mangled = dlang_decode_backref (mangled + 1, &ret);
    453   1.1.1.9  mrg   if (mangled == NULL || ret > qref - info->s)
    454   1.1.1.9  mrg     return 0;
    455   1.1.1.9  mrg 
    456   1.1.1.9  mrg   return ISDIGIT (qref[-ret]);
    457   1.1.1.9  mrg }
    458   1.1.1.9  mrg 
    459       1.1  mrg /* Demangle the calling convention from MANGLED and append it to DECL.
    460       1.1  mrg    Return the remaining string on success or NULL on failure.  */
    461       1.1  mrg static const char *
    462       1.1  mrg dlang_call_convention (string *decl, const char *mangled)
    463       1.1  mrg {
    464       1.1  mrg   if (mangled == NULL || *mangled == '\0')
    465   1.1.1.2  mrg     return NULL;
    466       1.1  mrg 
    467       1.1  mrg   switch (*mangled)
    468       1.1  mrg     {
    469       1.1  mrg     case 'F': /* (D) */
    470       1.1  mrg       mangled++;
    471       1.1  mrg       break;
    472       1.1  mrg     case 'U': /* (C) */
    473       1.1  mrg       mangled++;
    474       1.1  mrg       string_append (decl, "extern(C) ");
    475       1.1  mrg       break;
    476       1.1  mrg     case 'W': /* (Windows) */
    477       1.1  mrg       mangled++;
    478       1.1  mrg       string_append (decl, "extern(Windows) ");
    479       1.1  mrg       break;
    480       1.1  mrg     case 'V': /* (Pascal) */
    481       1.1  mrg       mangled++;
    482       1.1  mrg       string_append (decl, "extern(Pascal) ");
    483       1.1  mrg       break;
    484       1.1  mrg     case 'R': /* (C++) */
    485       1.1  mrg       mangled++;
    486       1.1  mrg       string_append (decl, "extern(C++) ");
    487       1.1  mrg       break;
    488   1.1.1.2  mrg     case 'Y': /* (Objective-C) */
    489   1.1.1.2  mrg       mangled++;
    490   1.1.1.2  mrg       string_append (decl, "extern(Objective-C) ");
    491   1.1.1.2  mrg       break;
    492       1.1  mrg     default:
    493       1.1  mrg       return NULL;
    494       1.1  mrg     }
    495       1.1  mrg 
    496       1.1  mrg   return mangled;
    497       1.1  mrg }
    498       1.1  mrg 
    499   1.1.1.2  mrg /* Extract the type modifiers from MANGLED and append them to DECL.
    500   1.1.1.2  mrg    Returns the remaining signature on success or NULL on failure.  */
    501   1.1.1.2  mrg static const char *
    502   1.1.1.2  mrg dlang_type_modifiers (string *decl, const char *mangled)
    503   1.1.1.2  mrg {
    504   1.1.1.2  mrg   if (mangled == NULL || *mangled == '\0')
    505   1.1.1.2  mrg     return NULL;
    506   1.1.1.2  mrg 
    507   1.1.1.2  mrg   switch (*mangled)
    508   1.1.1.2  mrg     {
    509   1.1.1.2  mrg     case 'x': /* const */
    510   1.1.1.2  mrg       mangled++;
    511   1.1.1.2  mrg       string_append (decl, " const");
    512   1.1.1.2  mrg       return mangled;
    513   1.1.1.2  mrg     case 'y': /* immutable */
    514   1.1.1.2  mrg       mangled++;
    515   1.1.1.2  mrg       string_append (decl, " immutable");
    516   1.1.1.2  mrg       return mangled;
    517   1.1.1.2  mrg     case 'O': /* shared */
    518   1.1.1.2  mrg       mangled++;
    519   1.1.1.2  mrg       string_append (decl, " shared");
    520   1.1.1.2  mrg       return dlang_type_modifiers (decl, mangled);
    521   1.1.1.2  mrg     case 'N':
    522   1.1.1.2  mrg       mangled++;
    523   1.1.1.2  mrg       if (*mangled == 'g') /* wild */
    524   1.1.1.2  mrg 	{
    525   1.1.1.2  mrg 	  mangled++;
    526   1.1.1.2  mrg 	  string_append (decl, " inout");
    527   1.1.1.2  mrg 	  return dlang_type_modifiers (decl, mangled);
    528   1.1.1.2  mrg 	}
    529   1.1.1.2  mrg       else
    530   1.1.1.2  mrg 	return NULL;
    531   1.1.1.2  mrg 
    532   1.1.1.2  mrg     default:
    533   1.1.1.2  mrg       return mangled;
    534   1.1.1.2  mrg     }
    535   1.1.1.2  mrg }
    536   1.1.1.2  mrg 
    537       1.1  mrg /* Demangle the D function attributes from MANGLED and append it to DECL.
    538       1.1  mrg    Return the remaining string on success or NULL on failure.  */
    539       1.1  mrg static const char *
    540       1.1  mrg dlang_attributes (string *decl, const char *mangled)
    541       1.1  mrg {
    542       1.1  mrg   if (mangled == NULL || *mangled == '\0')
    543   1.1.1.2  mrg     return NULL;
    544       1.1  mrg 
    545       1.1  mrg   while (*mangled == 'N')
    546       1.1  mrg     {
    547       1.1  mrg       mangled++;
    548       1.1  mrg       switch (*mangled)
    549       1.1  mrg 	{
    550       1.1  mrg 	case 'a': /* pure */
    551       1.1  mrg 	  mangled++;
    552       1.1  mrg 	  string_append (decl, "pure ");
    553       1.1  mrg 	  continue;
    554       1.1  mrg 	case 'b': /* nothrow */
    555       1.1  mrg 	  mangled++;
    556       1.1  mrg 	  string_append (decl, "nothrow ");
    557       1.1  mrg 	  continue;
    558       1.1  mrg 	case 'c': /* ref */
    559       1.1  mrg 	  mangled++;
    560       1.1  mrg 	  string_append (decl, "ref ");
    561       1.1  mrg 	  continue;
    562       1.1  mrg 	case 'd': /* @property */
    563       1.1  mrg 	  mangled++;
    564       1.1  mrg 	  string_append (decl, "@property ");
    565       1.1  mrg 	  continue;
    566       1.1  mrg 	case 'e': /* @trusted */
    567       1.1  mrg 	  mangled++;
    568       1.1  mrg 	  string_append (decl, "@trusted ");
    569       1.1  mrg 	  continue;
    570       1.1  mrg 	case 'f': /* @safe */
    571       1.1  mrg 	  mangled++;
    572       1.1  mrg 	  string_append (decl, "@safe ");
    573       1.1  mrg 	  continue;
    574       1.1  mrg 	case 'g':
    575       1.1  mrg 	case 'h':
    576   1.1.1.2  mrg 	case 'k':
    577   1.1.1.9  mrg 	case 'n':
    578       1.1  mrg 	  /* inout parameter is represented as 'Ng'.
    579       1.1  mrg 	     vector parameter is represented as 'Nh'.
    580   1.1.1.9  mrg 	     return parameter is represented as 'Nk'.
    581   1.1.1.9  mrg 	     typeof(*null) parameter is represented as 'Nn'.
    582       1.1  mrg 	     If we see this, then we know we're really in the
    583       1.1  mrg 	     parameter list.  Rewind and break.  */
    584       1.1  mrg 	  mangled--;
    585       1.1  mrg 	  break;
    586       1.1  mrg 	case 'i': /* @nogc */
    587       1.1  mrg 	  mangled++;
    588       1.1  mrg 	  string_append (decl, "@nogc ");
    589       1.1  mrg 	  continue;
    590   1.1.1.2  mrg 	case 'j': /* return */
    591   1.1.1.2  mrg 	  mangled++;
    592   1.1.1.2  mrg 	  string_append (decl, "return ");
    593   1.1.1.2  mrg 	  continue;
    594   1.1.1.6  mrg 	case 'l': /* scope */
    595   1.1.1.6  mrg 	  mangled++;
    596   1.1.1.6  mrg 	  string_append (decl, "scope ");
    597   1.1.1.6  mrg 	  continue;
    598   1.1.1.9  mrg 	case 'm': /* @live */
    599   1.1.1.9  mrg 	  mangled++;
    600   1.1.1.9  mrg 	  string_append (decl, "@live ");
    601   1.1.1.9  mrg 	  continue;
    602   1.1.1.2  mrg 
    603   1.1.1.2  mrg 	default: /* unknown attribute */
    604   1.1.1.2  mrg 	  return NULL;
    605       1.1  mrg 	}
    606       1.1  mrg       break;
    607       1.1  mrg     }
    608       1.1  mrg 
    609       1.1  mrg   return mangled;
    610       1.1  mrg }
    611       1.1  mrg 
    612   1.1.1.9  mrg /* Demangle the function type from MANGLED without the return type.
    613   1.1.1.9  mrg    The arguments are appended to ARGS, the calling convention is appended
    614   1.1.1.9  mrg    to CALL and attributes are appended to ATTR.  Any of these can be NULL
    615   1.1.1.9  mrg    to throw the information away.  Return the remaining string on success
    616   1.1.1.9  mrg    or NULL on failure.  */
    617   1.1.1.9  mrg static const char *
    618   1.1.1.9  mrg dlang_function_type_noreturn (string *args, string *call, string *attr,
    619   1.1.1.9  mrg 			      const char *mangled, struct dlang_info *info)
    620   1.1.1.9  mrg {
    621   1.1.1.9  mrg   string dump;
    622   1.1.1.9  mrg   string_init (&dump);
    623   1.1.1.9  mrg 
    624   1.1.1.9  mrg   /* Skip over calling convention and attributes.  */
    625   1.1.1.9  mrg   mangled = dlang_call_convention (call ? call : &dump, mangled);
    626   1.1.1.9  mrg   mangled = dlang_attributes (attr ? attr : &dump, mangled);
    627   1.1.1.9  mrg 
    628   1.1.1.9  mrg   if (args)
    629   1.1.1.9  mrg     string_append (args, "(");
    630   1.1.1.9  mrg 
    631   1.1.1.9  mrg   mangled = dlang_function_args (args ? args : &dump, mangled, info);
    632   1.1.1.9  mrg   if (args)
    633   1.1.1.9  mrg     string_append (args, ")");
    634   1.1.1.9  mrg 
    635   1.1.1.9  mrg   string_delete (&dump);
    636   1.1.1.9  mrg   return mangled;
    637   1.1.1.9  mrg }
    638   1.1.1.9  mrg 
    639       1.1  mrg /* Demangle the function type from MANGLED and append it to DECL.
    640       1.1  mrg    Return the remaining string on success or NULL on failure.  */
    641       1.1  mrg static const char *
    642   1.1.1.9  mrg dlang_function_type (string *decl, const char *mangled, struct dlang_info *info)
    643       1.1  mrg {
    644       1.1  mrg   string attr, args, type;
    645       1.1  mrg 
    646       1.1  mrg   if (mangled == NULL || *mangled == '\0')
    647   1.1.1.2  mrg     return NULL;
    648       1.1  mrg 
    649       1.1  mrg   /* The order of the mangled string is:
    650       1.1  mrg 	CallConvention FuncAttrs Arguments ArgClose Type
    651       1.1  mrg 
    652       1.1  mrg      The demangled string is re-ordered as:
    653       1.1  mrg 	CallConvention Type Arguments FuncAttrs
    654       1.1  mrg    */
    655       1.1  mrg   string_init (&attr);
    656       1.1  mrg   string_init (&args);
    657       1.1  mrg   string_init (&type);
    658       1.1  mrg 
    659   1.1.1.9  mrg   mangled = dlang_function_type_noreturn (&args, decl, &attr, mangled, info);
    660       1.1  mrg 
    661       1.1  mrg   /* Function return type.  */
    662   1.1.1.9  mrg   mangled = dlang_type (&type, mangled, info);
    663       1.1  mrg 
    664       1.1  mrg   /* Append to decl in order. */
    665   1.1.1.9  mrg   string_appendn (decl, type.b, string_length (&type));
    666   1.1.1.9  mrg   string_appendn (decl, args.b, string_length (&args));
    667   1.1.1.9  mrg   string_append (decl, " ");
    668   1.1.1.9  mrg   string_appendn (decl, attr.b, string_length (&attr));
    669       1.1  mrg 
    670       1.1  mrg   string_delete (&attr);
    671       1.1  mrg   string_delete (&args);
    672       1.1  mrg   string_delete (&type);
    673       1.1  mrg   return mangled;
    674       1.1  mrg }
    675       1.1  mrg 
    676       1.1  mrg /* Demangle the argument list from MANGLED and append it to DECL.
    677       1.1  mrg    Return the remaining string on success or NULL on failure.  */
    678       1.1  mrg static const char *
    679   1.1.1.9  mrg dlang_function_args (string *decl, const char *mangled, struct dlang_info *info)
    680       1.1  mrg {
    681       1.1  mrg   size_t n = 0;
    682       1.1  mrg 
    683       1.1  mrg   while (mangled && *mangled != '\0')
    684       1.1  mrg     {
    685       1.1  mrg       switch (*mangled)
    686       1.1  mrg 	{
    687       1.1  mrg 	case 'X': /* (variadic T t...) style.  */
    688       1.1  mrg 	  mangled++;
    689       1.1  mrg 	  string_append (decl, "...");
    690       1.1  mrg 	  return mangled;
    691       1.1  mrg 	case 'Y': /* (variadic T t, ...) style.  */
    692       1.1  mrg 	  mangled++;
    693   1.1.1.2  mrg 	  if (n != 0)
    694   1.1.1.2  mrg 	    string_append (decl, ", ");
    695   1.1.1.2  mrg 	  string_append (decl, "...");
    696       1.1  mrg 	  return mangled;
    697       1.1  mrg 	case 'Z': /* Normal function.  */
    698       1.1  mrg 	  mangled++;
    699       1.1  mrg 	  return mangled;
    700       1.1  mrg 	}
    701       1.1  mrg 
    702       1.1  mrg       if (n++)
    703       1.1  mrg 	string_append (decl, ", ");
    704       1.1  mrg 
    705       1.1  mrg       if (*mangled == 'M') /* scope(T) */
    706       1.1  mrg 	{
    707       1.1  mrg 	  mangled++;
    708       1.1  mrg 	  string_append (decl, "scope ");
    709       1.1  mrg 	}
    710       1.1  mrg 
    711   1.1.1.2  mrg       if (mangled[0] == 'N' && mangled[1] == 'k') /* return(T) */
    712   1.1.1.2  mrg 	{
    713   1.1.1.2  mrg 	  mangled += 2;
    714   1.1.1.2  mrg 	  string_append (decl, "return ");
    715   1.1.1.2  mrg 	}
    716   1.1.1.2  mrg 
    717       1.1  mrg       switch (*mangled)
    718       1.1  mrg 	{
    719   1.1.1.9  mrg 	case 'I': /* in(T) */
    720   1.1.1.9  mrg 	  mangled++;
    721   1.1.1.9  mrg 	  string_append (decl, "in ");
    722   1.1.1.9  mrg 	  if (*mangled == 'K') /* in ref(T) */
    723   1.1.1.9  mrg 	    {
    724   1.1.1.9  mrg 	      mangled++;
    725   1.1.1.9  mrg 	      string_append (decl, "ref ");
    726   1.1.1.9  mrg 	    }
    727   1.1.1.9  mrg 	  break;
    728       1.1  mrg 	case 'J': /* out(T) */
    729       1.1  mrg 	  mangled++;
    730       1.1  mrg 	  string_append (decl, "out ");
    731       1.1  mrg 	  break;
    732       1.1  mrg 	case 'K': /* ref(T) */
    733       1.1  mrg 	  mangled++;
    734       1.1  mrg 	  string_append (decl, "ref ");
    735       1.1  mrg 	  break;
    736       1.1  mrg 	case 'L': /* lazy(T) */
    737       1.1  mrg 	  mangled++;
    738       1.1  mrg 	  string_append (decl, "lazy ");
    739       1.1  mrg 	  break;
    740       1.1  mrg 	}
    741   1.1.1.9  mrg       mangled = dlang_type (decl, mangled, info);
    742       1.1  mrg     }
    743       1.1  mrg 
    744       1.1  mrg   return mangled;
    745       1.1  mrg }
    746       1.1  mrg 
    747       1.1  mrg /* Demangle the type from MANGLED and append it to DECL.
    748       1.1  mrg    Return the remaining string on success or NULL on failure.  */
    749       1.1  mrg static const char *
    750   1.1.1.9  mrg dlang_type (string *decl, const char *mangled, struct dlang_info *info)
    751       1.1  mrg {
    752       1.1  mrg   if (mangled == NULL || *mangled == '\0')
    753   1.1.1.2  mrg     return NULL;
    754       1.1  mrg 
    755       1.1  mrg   switch (*mangled)
    756       1.1  mrg     {
    757       1.1  mrg     case 'O': /* shared(T) */
    758       1.1  mrg       mangled++;
    759       1.1  mrg       string_append (decl, "shared(");
    760   1.1.1.9  mrg       mangled = dlang_type (decl, mangled, info);
    761       1.1  mrg       string_append (decl, ")");
    762       1.1  mrg       return mangled;
    763       1.1  mrg     case 'x': /* const(T) */
    764       1.1  mrg       mangled++;
    765       1.1  mrg       string_append (decl, "const(");
    766   1.1.1.9  mrg       mangled = dlang_type (decl, mangled, info);
    767       1.1  mrg       string_append (decl, ")");
    768       1.1  mrg       return mangled;
    769       1.1  mrg     case 'y': /* immutable(T) */
    770       1.1  mrg       mangled++;
    771       1.1  mrg       string_append (decl, "immutable(");
    772   1.1.1.9  mrg       mangled = dlang_type (decl, mangled, info);
    773       1.1  mrg       string_append (decl, ")");
    774       1.1  mrg       return mangled;
    775       1.1  mrg     case 'N':
    776       1.1  mrg       mangled++;
    777       1.1  mrg       if (*mangled == 'g') /* wild(T) */
    778       1.1  mrg 	{
    779       1.1  mrg 	  mangled++;
    780       1.1  mrg 	  string_append (decl, "inout(");
    781   1.1.1.9  mrg 	  mangled = dlang_type (decl, mangled, info);
    782       1.1  mrg 	  string_append (decl, ")");
    783       1.1  mrg 	  return mangled;
    784       1.1  mrg 	}
    785       1.1  mrg       else if (*mangled == 'h') /* vector(T) */
    786       1.1  mrg 	{
    787       1.1  mrg 	  mangled++;
    788       1.1  mrg 	  string_append (decl, "__vector(");
    789   1.1.1.9  mrg 	  mangled = dlang_type (decl, mangled, info);
    790       1.1  mrg 	  string_append (decl, ")");
    791       1.1  mrg 	  return mangled;
    792       1.1  mrg 	}
    793   1.1.1.9  mrg       else if (*mangled == 'n') /* typeof(*null) */
    794   1.1.1.9  mrg 	{
    795   1.1.1.9  mrg 	  mangled++;
    796   1.1.1.9  mrg 	  string_append (decl, "typeof(*null)");
    797   1.1.1.9  mrg 	  return mangled;
    798   1.1.1.9  mrg 	}
    799       1.1  mrg       else
    800       1.1  mrg 	return NULL;
    801       1.1  mrg     case 'A': /* dynamic array (T[]) */
    802       1.1  mrg       mangled++;
    803   1.1.1.9  mrg       mangled = dlang_type (decl, mangled, info);
    804       1.1  mrg       string_append (decl, "[]");
    805       1.1  mrg       return mangled;
    806       1.1  mrg     case 'G': /* static array (T[N]) */
    807       1.1  mrg     {
    808       1.1  mrg       const char *numptr;
    809       1.1  mrg       size_t num = 0;
    810       1.1  mrg       mangled++;
    811       1.1  mrg 
    812       1.1  mrg       numptr = mangled;
    813       1.1  mrg       while (ISDIGIT (*mangled))
    814       1.1  mrg 	{
    815       1.1  mrg 	  num++;
    816       1.1  mrg 	  mangled++;
    817       1.1  mrg 	}
    818   1.1.1.9  mrg       mangled = dlang_type (decl, mangled, info);
    819       1.1  mrg       string_append (decl, "[");
    820       1.1  mrg       string_appendn (decl, numptr, num);
    821       1.1  mrg       string_append (decl, "]");
    822       1.1  mrg       return mangled;
    823       1.1  mrg     }
    824       1.1  mrg     case 'H': /* associative array (T[T]) */
    825       1.1  mrg     {
    826       1.1  mrg       string type;
    827       1.1  mrg       size_t sztype;
    828       1.1  mrg       mangled++;
    829       1.1  mrg 
    830       1.1  mrg       string_init (&type);
    831   1.1.1.9  mrg       mangled = dlang_type (&type, mangled, info);
    832       1.1  mrg       sztype = string_length (&type);
    833       1.1  mrg 
    834   1.1.1.9  mrg       mangled = dlang_type (decl, mangled, info);
    835       1.1  mrg       string_append (decl, "[");
    836       1.1  mrg       string_appendn (decl, type.b, sztype);
    837       1.1  mrg       string_append (decl, "]");
    838       1.1  mrg 
    839       1.1  mrg       string_delete (&type);
    840       1.1  mrg       return mangled;
    841       1.1  mrg     }
    842       1.1  mrg     case 'P': /* pointer (T*) */
    843       1.1  mrg       mangled++;
    844   1.1.1.6  mrg       if (!dlang_call_convention_p (mangled))
    845   1.1.1.2  mrg 	{
    846   1.1.1.9  mrg 	  mangled = dlang_type (decl, mangled, info);
    847   1.1.1.6  mrg 	  string_append (decl, "*");
    848   1.1.1.2  mrg 	  return mangled;
    849   1.1.1.2  mrg 	}
    850   1.1.1.6  mrg       /* Fall through */
    851   1.1.1.6  mrg     case 'F': /* function T (D) */
    852   1.1.1.6  mrg     case 'U': /* function T (C) */
    853   1.1.1.6  mrg     case 'W': /* function T (Windows) */
    854   1.1.1.6  mrg     case 'V': /* function T (Pascal) */
    855   1.1.1.6  mrg     case 'R': /* function T (C++) */
    856   1.1.1.6  mrg     case 'Y': /* function T (Objective-C) */
    857   1.1.1.6  mrg       /* Function pointer types don't include the trailing asterisk.  */
    858   1.1.1.9  mrg       mangled = dlang_function_type (decl, mangled, info);
    859   1.1.1.6  mrg       string_append (decl, "function");
    860       1.1  mrg       return mangled;
    861       1.1  mrg     case 'C': /* class T */
    862       1.1  mrg     case 'S': /* struct T */
    863       1.1  mrg     case 'E': /* enum T */
    864       1.1  mrg     case 'T': /* typedef T */
    865       1.1  mrg       mangled++;
    866   1.1.1.9  mrg       return dlang_parse_qualified (decl, mangled, info, 0);
    867       1.1  mrg     case 'D': /* delegate T */
    868   1.1.1.2  mrg     {
    869   1.1.1.2  mrg       string mods;
    870   1.1.1.2  mrg       size_t szmods;
    871       1.1  mrg       mangled++;
    872   1.1.1.2  mrg 
    873   1.1.1.2  mrg       string_init (&mods);
    874   1.1.1.2  mrg       mangled = dlang_type_modifiers (&mods, mangled);
    875   1.1.1.2  mrg       szmods = string_length (&mods);
    876   1.1.1.2  mrg 
    877   1.1.1.9  mrg       /* Back referenced function type.  */
    878   1.1.1.9  mrg       if (mangled && *mangled == 'Q')
    879   1.1.1.9  mrg 	mangled = dlang_type_backref (decl, mangled, info, 1);
    880   1.1.1.9  mrg       else
    881   1.1.1.9  mrg 	mangled = dlang_function_type (decl, mangled, info);
    882   1.1.1.9  mrg 
    883       1.1  mrg       string_append (decl, "delegate");
    884   1.1.1.2  mrg       string_appendn (decl, mods.b, szmods);
    885   1.1.1.2  mrg 
    886   1.1.1.2  mrg       string_delete (&mods);
    887       1.1  mrg       return mangled;
    888   1.1.1.2  mrg     }
    889       1.1  mrg     case 'B': /* tuple T */
    890       1.1  mrg       mangled++;
    891   1.1.1.9  mrg       return dlang_parse_tuple (decl, mangled, info);
    892       1.1  mrg 
    893       1.1  mrg     /* Basic types */
    894       1.1  mrg     case 'n':
    895       1.1  mrg       mangled++;
    896   1.1.1.9  mrg       string_append (decl, "typeof(null)");
    897       1.1  mrg       return mangled;
    898       1.1  mrg     case 'v':
    899       1.1  mrg       mangled++;
    900       1.1  mrg       string_append (decl, "void");
    901       1.1  mrg       return mangled;
    902       1.1  mrg     case 'g':
    903       1.1  mrg       mangled++;
    904       1.1  mrg       string_append (decl, "byte");
    905       1.1  mrg       return mangled;
    906       1.1  mrg     case 'h':
    907       1.1  mrg       mangled++;
    908       1.1  mrg       string_append (decl, "ubyte");
    909       1.1  mrg       return mangled;
    910       1.1  mrg     case 's':
    911       1.1  mrg       mangled++;
    912       1.1  mrg       string_append (decl, "short");
    913       1.1  mrg       return mangled;
    914       1.1  mrg     case 't':
    915       1.1  mrg       mangled++;
    916       1.1  mrg       string_append (decl, "ushort");
    917       1.1  mrg       return mangled;
    918       1.1  mrg     case 'i':
    919       1.1  mrg       mangled++;
    920       1.1  mrg       string_append (decl, "int");
    921       1.1  mrg       return mangled;
    922       1.1  mrg     case 'k':
    923       1.1  mrg       mangled++;
    924       1.1  mrg       string_append (decl, "uint");
    925       1.1  mrg       return mangled;
    926       1.1  mrg     case 'l':
    927       1.1  mrg       mangled++;
    928       1.1  mrg       string_append (decl, "long");
    929       1.1  mrg       return mangled;
    930       1.1  mrg     case 'm':
    931       1.1  mrg       mangled++;
    932       1.1  mrg       string_append (decl, "ulong");
    933       1.1  mrg       return mangled;
    934       1.1  mrg     case 'f':
    935       1.1  mrg       mangled++;
    936       1.1  mrg       string_append (decl, "float");
    937       1.1  mrg       return mangled;
    938       1.1  mrg     case 'd':
    939       1.1  mrg       mangled++;
    940       1.1  mrg       string_append (decl, "double");
    941       1.1  mrg       return mangled;
    942       1.1  mrg     case 'e':
    943       1.1  mrg       mangled++;
    944       1.1  mrg       string_append (decl, "real");
    945       1.1  mrg       return mangled;
    946       1.1  mrg 
    947       1.1  mrg     /* Imaginary and Complex types */
    948       1.1  mrg     case 'o':
    949       1.1  mrg       mangled++;
    950       1.1  mrg       string_append (decl, "ifloat");
    951       1.1  mrg       return mangled;
    952       1.1  mrg     case 'p':
    953       1.1  mrg       mangled++;
    954       1.1  mrg       string_append (decl, "idouble");
    955       1.1  mrg       return mangled;
    956       1.1  mrg     case 'j':
    957       1.1  mrg       mangled++;
    958       1.1  mrg       string_append (decl, "ireal");
    959       1.1  mrg       return mangled;
    960       1.1  mrg     case 'q':
    961       1.1  mrg       mangled++;
    962       1.1  mrg       string_append (decl, "cfloat");
    963       1.1  mrg       return mangled;
    964       1.1  mrg     case 'r':
    965       1.1  mrg       mangled++;
    966       1.1  mrg       string_append (decl, "cdouble");
    967       1.1  mrg       return mangled;
    968       1.1  mrg     case 'c':
    969       1.1  mrg       mangled++;
    970       1.1  mrg       string_append (decl, "creal");
    971       1.1  mrg       return mangled;
    972       1.1  mrg 
    973       1.1  mrg     /* Other types */
    974       1.1  mrg     case 'b':
    975       1.1  mrg       mangled++;
    976       1.1  mrg       string_append (decl, "bool");
    977       1.1  mrg       return mangled;
    978       1.1  mrg     case 'a':
    979       1.1  mrg       mangled++;
    980       1.1  mrg       string_append (decl, "char");
    981       1.1  mrg       return mangled;
    982       1.1  mrg     case 'u':
    983       1.1  mrg       mangled++;
    984       1.1  mrg       string_append (decl, "wchar");
    985       1.1  mrg       return mangled;
    986       1.1  mrg     case 'w':
    987       1.1  mrg       mangled++;
    988       1.1  mrg       string_append (decl, "dchar");
    989       1.1  mrg       return mangled;
    990   1.1.1.2  mrg     case 'z':
    991   1.1.1.2  mrg       mangled++;
    992   1.1.1.2  mrg       switch (*mangled)
    993   1.1.1.2  mrg 	{
    994   1.1.1.2  mrg 	case 'i':
    995   1.1.1.2  mrg 	  mangled++;
    996   1.1.1.2  mrg 	  string_append (decl, "cent");
    997   1.1.1.2  mrg 	  return mangled;
    998   1.1.1.2  mrg 	case 'k':
    999   1.1.1.2  mrg 	  mangled++;
   1000   1.1.1.2  mrg 	  string_append (decl, "ucent");
   1001   1.1.1.2  mrg 	  return mangled;
   1002   1.1.1.2  mrg 	}
   1003   1.1.1.2  mrg       return NULL;
   1004       1.1  mrg 
   1005   1.1.1.9  mrg     /* Back referenced type.  */
   1006   1.1.1.9  mrg     case 'Q':
   1007   1.1.1.9  mrg       return dlang_type_backref (decl, mangled, info, 0);
   1008   1.1.1.9  mrg 
   1009       1.1  mrg     default: /* unhandled */
   1010       1.1  mrg       return NULL;
   1011       1.1  mrg     }
   1012       1.1  mrg }
   1013       1.1  mrg 
   1014       1.1  mrg /* Extract the identifier from MANGLED and append it to DECL.
   1015       1.1  mrg    Return the remaining string on success or NULL on failure.  */
   1016       1.1  mrg static const char *
   1017   1.1.1.9  mrg dlang_identifier (string *decl, const char *mangled, struct dlang_info *info)
   1018       1.1  mrg {
   1019   1.1.1.9  mrg   unsigned long len;
   1020   1.1.1.9  mrg 
   1021   1.1.1.9  mrg   if (mangled == NULL || *mangled == '\0')
   1022   1.1.1.9  mrg     return NULL;
   1023   1.1.1.9  mrg 
   1024   1.1.1.9  mrg   if (*mangled == 'Q')
   1025   1.1.1.9  mrg     return dlang_symbol_backref (decl, mangled, info);
   1026   1.1.1.9  mrg 
   1027   1.1.1.9  mrg   /* May be a template instance without a length prefix.  */
   1028   1.1.1.9  mrg   if (mangled[0] == '_' && mangled[1] == '_'
   1029   1.1.1.9  mrg       && (mangled[2] == 'T' || mangled[2] == 'U'))
   1030   1.1.1.9  mrg     return dlang_parse_template (decl, mangled, info, TEMPLATE_LENGTH_UNKNOWN);
   1031   1.1.1.9  mrg 
   1032   1.1.1.6  mrg   const char *endptr = dlang_number (mangled, &len);
   1033   1.1.1.2  mrg 
   1034   1.1.1.6  mrg   if (endptr == NULL || len == 0)
   1035   1.1.1.2  mrg     return NULL;
   1036       1.1  mrg 
   1037   1.1.1.9  mrg   if (strlen (endptr) < len)
   1038   1.1.1.9  mrg     return NULL;
   1039   1.1.1.2  mrg 
   1040   1.1.1.9  mrg   mangled = endptr;
   1041   1.1.1.2  mrg 
   1042   1.1.1.9  mrg   /* May be a template instance with a length prefix.  */
   1043   1.1.1.9  mrg   if (len >= 5 && mangled[0] == '_' && mangled[1] == '_'
   1044   1.1.1.9  mrg       && (mangled[2] == 'T' || mangled[2] == 'U'))
   1045   1.1.1.9  mrg     return dlang_parse_template (decl, mangled, info, len);
   1046   1.1.1.2  mrg 
   1047   1.1.1.9  mrg   /* There can be multiple different declarations in the same function that have
   1048   1.1.1.9  mrg      the same mangled name.  To make the mangled names unique, a fake parent in
   1049   1.1.1.9  mrg      the form `__Sddd' is added to the symbol.  */
   1050   1.1.1.9  mrg   if (len >= 4 && mangled[0] == '_' && mangled[1] == '_' && mangled[2] == 'S')
   1051   1.1.1.2  mrg     {
   1052   1.1.1.9  mrg       const char *numptr = mangled + 3;
   1053   1.1.1.9  mrg       while (numptr < (mangled + len) && ISDIGIT (*numptr))
   1054   1.1.1.9  mrg 	numptr++;
   1055       1.1  mrg 
   1056   1.1.1.9  mrg       if (mangled + len == numptr)
   1057   1.1.1.9  mrg 	{
   1058   1.1.1.9  mrg 	  /* Skip over the fake parent.  */
   1059   1.1.1.9  mrg 	  mangled += len;
   1060   1.1.1.9  mrg 	  return dlang_identifier (decl, mangled, info);
   1061   1.1.1.9  mrg 	}
   1062       1.1  mrg 
   1063   1.1.1.9  mrg       /* else demangle it as a plain identifier.  */
   1064   1.1.1.9  mrg     }
   1065       1.1  mrg 
   1066   1.1.1.9  mrg   return dlang_lname (decl, mangled, len);
   1067   1.1.1.9  mrg }
   1068   1.1.1.2  mrg 
   1069   1.1.1.9  mrg /* Extract the plain identifier from MANGLED and prepend/append it to DECL
   1070   1.1.1.9  mrg    with special treatment for some magic compiler generted symbols.
   1071   1.1.1.9  mrg    Return the remaining string on success or NULL on failure.  */
   1072   1.1.1.9  mrg static const char *
   1073   1.1.1.9  mrg dlang_lname (string *decl, const char *mangled, unsigned long len)
   1074   1.1.1.9  mrg {
   1075   1.1.1.9  mrg   switch (len)
   1076   1.1.1.9  mrg     {
   1077   1.1.1.9  mrg     case 6:
   1078   1.1.1.9  mrg       if (strncmp (mangled, "__ctor", len) == 0)
   1079   1.1.1.9  mrg 	{
   1080   1.1.1.9  mrg 	  /* Constructor symbol for a class/struct.  */
   1081   1.1.1.9  mrg 	  string_append (decl, "this");
   1082   1.1.1.9  mrg 	  mangled += len;
   1083   1.1.1.9  mrg 	  return mangled;
   1084   1.1.1.9  mrg 	}
   1085   1.1.1.9  mrg       else if (strncmp (mangled, "__dtor", len) == 0)
   1086   1.1.1.9  mrg 	{
   1087   1.1.1.9  mrg 	  /* Destructor symbol for a class/struct.  */
   1088   1.1.1.9  mrg 	  string_append (decl, "~this");
   1089   1.1.1.9  mrg 	  mangled += len;
   1090   1.1.1.9  mrg 	  return mangled;
   1091   1.1.1.9  mrg 	}
   1092   1.1.1.9  mrg       else if (strncmp (mangled, "__initZ", len + 1) == 0)
   1093   1.1.1.9  mrg 	{
   1094   1.1.1.9  mrg 	  /* The static initialiser for a given symbol.  */
   1095   1.1.1.9  mrg 	  string_prepend (decl, "initializer for ");
   1096   1.1.1.9  mrg 	  string_setlength (decl, string_length (decl) - 1);
   1097   1.1.1.9  mrg 	  mangled += len;
   1098   1.1.1.9  mrg 	  return mangled;
   1099   1.1.1.9  mrg 	}
   1100   1.1.1.9  mrg       else if (strncmp (mangled, "__vtblZ", len + 1) == 0)
   1101   1.1.1.9  mrg 	{
   1102   1.1.1.9  mrg 	  /* The vtable symbol for a given class.  */
   1103   1.1.1.9  mrg 	  string_prepend (decl, "vtable for ");
   1104   1.1.1.9  mrg 	  string_setlength (decl, string_length (decl) - 1);
   1105   1.1.1.9  mrg 	  mangled += len;
   1106   1.1.1.9  mrg 	  return mangled;
   1107   1.1.1.9  mrg 	}
   1108   1.1.1.9  mrg       break;
   1109   1.1.1.2  mrg 
   1110   1.1.1.9  mrg     case 7:
   1111   1.1.1.9  mrg       if (strncmp (mangled, "__ClassZ", len + 1) == 0)
   1112   1.1.1.9  mrg 	{
   1113   1.1.1.9  mrg 	  /* The classinfo symbol for a given class.  */
   1114   1.1.1.9  mrg 	  string_prepend (decl, "ClassInfo for ");
   1115   1.1.1.9  mrg 	  string_setlength (decl, string_length (decl) - 1);
   1116   1.1.1.9  mrg 	  mangled += len;
   1117   1.1.1.9  mrg 	  return mangled;
   1118   1.1.1.9  mrg 	}
   1119   1.1.1.9  mrg       break;
   1120   1.1.1.2  mrg 
   1121   1.1.1.9  mrg     case 10:
   1122   1.1.1.9  mrg       if (strncmp (mangled, "__postblitMFZ", len + 3) == 0)
   1123   1.1.1.9  mrg 	{
   1124   1.1.1.9  mrg 	  /* Postblit symbol for a struct.  */
   1125   1.1.1.9  mrg 	  string_append (decl, "this(this)");
   1126   1.1.1.9  mrg 	  mangled += len + 3;
   1127   1.1.1.9  mrg 	  return mangled;
   1128   1.1.1.9  mrg 	}
   1129   1.1.1.9  mrg       break;
   1130   1.1.1.2  mrg 
   1131   1.1.1.9  mrg     case 11:
   1132   1.1.1.9  mrg       if (strncmp (mangled, "__InterfaceZ", len + 1) == 0)
   1133   1.1.1.9  mrg 	{
   1134   1.1.1.9  mrg 	  /* The interface symbol for a given class.  */
   1135   1.1.1.9  mrg 	  string_prepend (decl, "Interface for ");
   1136   1.1.1.9  mrg 	  string_setlength (decl, string_length (decl) - 1);
   1137   1.1.1.9  mrg 	  mangled += len;
   1138   1.1.1.9  mrg 	  return mangled;
   1139       1.1  mrg 	}
   1140   1.1.1.9  mrg       break;
   1141       1.1  mrg 
   1142   1.1.1.9  mrg     case 12:
   1143   1.1.1.9  mrg       if (strncmp (mangled, "__ModuleInfoZ", len + 1) == 0)
   1144   1.1.1.9  mrg 	{
   1145   1.1.1.9  mrg 	  /* The ModuleInfo symbol for a given module.  */
   1146   1.1.1.9  mrg 	  string_prepend (decl, "ModuleInfo for ");
   1147   1.1.1.9  mrg 	  string_setlength (decl, string_length (decl) - 1);
   1148   1.1.1.9  mrg 	  mangled += len;
   1149   1.1.1.9  mrg 	  return mangled;
   1150   1.1.1.9  mrg 	}
   1151   1.1.1.9  mrg       break;
   1152       1.1  mrg     }
   1153       1.1  mrg 
   1154   1.1.1.9  mrg   string_appendn (decl, mangled, len);
   1155   1.1.1.9  mrg   mangled += len;
   1156   1.1.1.9  mrg 
   1157       1.1  mrg   return mangled;
   1158       1.1  mrg }
   1159       1.1  mrg 
   1160       1.1  mrg /* Extract the integer value from MANGLED and append it to DECL,
   1161       1.1  mrg    where TYPE is the type it should be represented as.
   1162       1.1  mrg    Return the remaining string on success or NULL on failure.  */
   1163       1.1  mrg static const char *
   1164       1.1  mrg dlang_parse_integer (string *decl, const char *mangled, char type)
   1165       1.1  mrg {
   1166       1.1  mrg   if (type == 'a' || type == 'u' || type == 'w')
   1167       1.1  mrg     {
   1168       1.1  mrg       /* Parse character value.  */
   1169   1.1.1.8  mrg       char value[20];
   1170   1.1.1.8  mrg       int pos = sizeof(value);
   1171       1.1  mrg       int width = 0;
   1172   1.1.1.9  mrg       unsigned long val;
   1173       1.1  mrg 
   1174   1.1.1.6  mrg       mangled = dlang_number (mangled, &val);
   1175   1.1.1.6  mrg       if (mangled == NULL)
   1176       1.1  mrg 	return NULL;
   1177       1.1  mrg 
   1178       1.1  mrg       string_append (decl, "'");
   1179       1.1  mrg 
   1180       1.1  mrg       if (type == 'a' && val >= 0x20 && val < 0x7F)
   1181       1.1  mrg 	{
   1182       1.1  mrg 	  /* Represent as a character literal.  */
   1183       1.1  mrg 	  char c = (char) val;
   1184       1.1  mrg 	  string_appendn (decl, &c, 1);
   1185       1.1  mrg 	}
   1186       1.1  mrg       else
   1187       1.1  mrg 	{
   1188       1.1  mrg 	  /* Represent as a hexadecimal value.  */
   1189       1.1  mrg 	  switch (type)
   1190       1.1  mrg 	    {
   1191       1.1  mrg 	    case 'a': /* char */
   1192       1.1  mrg 	      string_append (decl, "\\x");
   1193       1.1  mrg 	      width = 2;
   1194       1.1  mrg 	      break;
   1195       1.1  mrg 	    case 'u': /* wchar */
   1196       1.1  mrg 	      string_append (decl, "\\u");
   1197       1.1  mrg 	      width = 4;
   1198       1.1  mrg 	      break;
   1199       1.1  mrg 	    case 'w': /* dchar */
   1200       1.1  mrg 	      string_append (decl, "\\U");
   1201       1.1  mrg 	      width = 8;
   1202       1.1  mrg 	      break;
   1203       1.1  mrg 	    }
   1204       1.1  mrg 
   1205       1.1  mrg 	  while (val > 0)
   1206       1.1  mrg 	    {
   1207       1.1  mrg 	      int digit = val % 16;
   1208       1.1  mrg 
   1209       1.1  mrg 	      if (digit < 10)
   1210       1.1  mrg 		value[--pos] = (char)(digit + '0');
   1211       1.1  mrg 	      else
   1212       1.1  mrg 		value[--pos] = (char)((digit - 10) + 'a');
   1213       1.1  mrg 
   1214       1.1  mrg 	      val /= 16;
   1215       1.1  mrg 	      width--;
   1216       1.1  mrg 	    }
   1217       1.1  mrg 
   1218       1.1  mrg 	  for (; width > 0; width--)
   1219       1.1  mrg 	    value[--pos] = '0';
   1220       1.1  mrg 
   1221   1.1.1.8  mrg 	  string_appendn (decl, &(value[pos]), sizeof(value) - pos);
   1222       1.1  mrg 	}
   1223       1.1  mrg       string_append (decl, "'");
   1224       1.1  mrg     }
   1225       1.1  mrg   else if (type == 'b')
   1226       1.1  mrg     {
   1227       1.1  mrg       /* Parse boolean value.  */
   1228   1.1.1.9  mrg       unsigned long val;
   1229       1.1  mrg 
   1230   1.1.1.6  mrg       mangled = dlang_number (mangled, &val);
   1231   1.1.1.6  mrg       if (mangled == NULL)
   1232       1.1  mrg 	return NULL;
   1233       1.1  mrg 
   1234       1.1  mrg       string_append (decl, val ? "true" : "false");
   1235       1.1  mrg     }
   1236       1.1  mrg   else
   1237       1.1  mrg     {
   1238       1.1  mrg       /* Parse integer value.  */
   1239       1.1  mrg       const char *numptr = mangled;
   1240       1.1  mrg       size_t num = 0;
   1241       1.1  mrg 
   1242   1.1.1.6  mrg       if (! ISDIGIT (*mangled))
   1243   1.1.1.6  mrg 	return NULL;
   1244   1.1.1.6  mrg 
   1245       1.1  mrg       while (ISDIGIT (*mangled))
   1246       1.1  mrg 	{
   1247       1.1  mrg 	  num++;
   1248       1.1  mrg 	  mangled++;
   1249       1.1  mrg 	}
   1250       1.1  mrg       string_appendn (decl, numptr, num);
   1251       1.1  mrg 
   1252       1.1  mrg       /* Append suffix.  */
   1253       1.1  mrg       switch (type)
   1254       1.1  mrg 	{
   1255       1.1  mrg 	case 'h': /* ubyte */
   1256       1.1  mrg 	case 't': /* ushort */
   1257       1.1  mrg 	case 'k': /* uint */
   1258       1.1  mrg 	  string_append (decl, "u");
   1259       1.1  mrg 	  break;
   1260       1.1  mrg 	case 'l': /* long */
   1261       1.1  mrg 	  string_append (decl, "L");
   1262       1.1  mrg 	  break;
   1263       1.1  mrg 	case 'm': /* ulong */
   1264       1.1  mrg 	  string_append (decl, "uL");
   1265       1.1  mrg 	  break;
   1266       1.1  mrg 	}
   1267       1.1  mrg     }
   1268       1.1  mrg 
   1269       1.1  mrg   return mangled;
   1270       1.1  mrg }
   1271       1.1  mrg 
   1272       1.1  mrg /* Extract the floating-point value from MANGLED and append it to DECL.
   1273       1.1  mrg    Return the remaining string on success or NULL on failure.  */
   1274       1.1  mrg static const char *
   1275       1.1  mrg dlang_parse_real (string *decl, const char *mangled)
   1276       1.1  mrg {
   1277       1.1  mrg   /* Handle NAN and +-INF.  */
   1278       1.1  mrg   if (strncmp (mangled, "NAN", 3) == 0)
   1279       1.1  mrg     {
   1280       1.1  mrg       string_append (decl, "NaN");
   1281       1.1  mrg       mangled += 3;
   1282       1.1  mrg       return mangled;
   1283       1.1  mrg     }
   1284       1.1  mrg   else if (strncmp (mangled, "INF", 3) == 0)
   1285       1.1  mrg     {
   1286       1.1  mrg       string_append (decl, "Inf");
   1287       1.1  mrg       mangled += 3;
   1288       1.1  mrg       return mangled;
   1289       1.1  mrg     }
   1290       1.1  mrg   else if (strncmp (mangled, "NINF", 4) == 0)
   1291       1.1  mrg     {
   1292       1.1  mrg       string_append (decl, "-Inf");
   1293       1.1  mrg       mangled += 4;
   1294       1.1  mrg       return mangled;
   1295       1.1  mrg     }
   1296       1.1  mrg 
   1297       1.1  mrg   /* Hexadecimal prefix and leading bit.  */
   1298       1.1  mrg   if (*mangled == 'N')
   1299       1.1  mrg     {
   1300   1.1.1.6  mrg       string_append (decl, "-");
   1301       1.1  mrg       mangled++;
   1302       1.1  mrg     }
   1303       1.1  mrg 
   1304       1.1  mrg   if (!ISXDIGIT (*mangled))
   1305       1.1  mrg     return NULL;
   1306       1.1  mrg 
   1307   1.1.1.6  mrg   string_append (decl, "0x");
   1308   1.1.1.6  mrg   string_appendn (decl, mangled, 1);
   1309   1.1.1.6  mrg   string_append (decl, ".");
   1310       1.1  mrg   mangled++;
   1311       1.1  mrg 
   1312       1.1  mrg   /* Significand.  */
   1313       1.1  mrg   while (ISXDIGIT (*mangled))
   1314       1.1  mrg     {
   1315   1.1.1.6  mrg       string_appendn (decl, mangled, 1);
   1316       1.1  mrg       mangled++;
   1317       1.1  mrg     }
   1318       1.1  mrg 
   1319       1.1  mrg   /* Exponent.  */
   1320       1.1  mrg   if (*mangled != 'P')
   1321       1.1  mrg     return NULL;
   1322       1.1  mrg 
   1323   1.1.1.6  mrg   string_append (decl, "p");
   1324       1.1  mrg   mangled++;
   1325       1.1  mrg 
   1326       1.1  mrg   if (*mangled == 'N')
   1327       1.1  mrg     {
   1328   1.1.1.6  mrg       string_append (decl, "-");
   1329       1.1  mrg       mangled++;
   1330       1.1  mrg     }
   1331       1.1  mrg 
   1332       1.1  mrg   while (ISDIGIT (*mangled))
   1333       1.1  mrg     {
   1334   1.1.1.6  mrg       string_appendn (decl, mangled, 1);
   1335       1.1  mrg       mangled++;
   1336       1.1  mrg     }
   1337       1.1  mrg 
   1338       1.1  mrg   return mangled;
   1339       1.1  mrg }
   1340       1.1  mrg 
   1341       1.1  mrg /* Extract the string value from MANGLED and append it to DECL.
   1342       1.1  mrg    Return the remaining string on success or NULL on failure.  */
   1343       1.1  mrg static const char *
   1344       1.1  mrg dlang_parse_string (string *decl, const char *mangled)
   1345       1.1  mrg {
   1346       1.1  mrg   char type = *mangled;
   1347   1.1.1.9  mrg   unsigned long len;
   1348       1.1  mrg 
   1349       1.1  mrg   mangled++;
   1350   1.1.1.6  mrg   mangled = dlang_number (mangled, &len);
   1351   1.1.1.6  mrg   if (mangled == NULL || *mangled != '_')
   1352       1.1  mrg     return NULL;
   1353       1.1  mrg 
   1354       1.1  mrg   mangled++;
   1355       1.1  mrg   string_append (decl, "\"");
   1356       1.1  mrg   while (len--)
   1357       1.1  mrg     {
   1358   1.1.1.6  mrg       char val;
   1359   1.1.1.6  mrg       const char *endptr = dlang_hexdigit (mangled, &val);
   1360   1.1.1.6  mrg 
   1361   1.1.1.6  mrg       if (endptr == NULL)
   1362   1.1.1.6  mrg 	return NULL;
   1363   1.1.1.6  mrg 
   1364   1.1.1.6  mrg       /* Sanitize white and non-printable characters.  */
   1365   1.1.1.6  mrg       switch (val)
   1366       1.1  mrg 	{
   1367   1.1.1.6  mrg 	case ' ':
   1368   1.1.1.6  mrg 	  string_append (decl, " ");
   1369   1.1.1.6  mrg 	  break;
   1370   1.1.1.6  mrg 	case '\t':
   1371   1.1.1.6  mrg 	  string_append (decl, "\\t");
   1372   1.1.1.6  mrg 	  break;
   1373   1.1.1.6  mrg 	case '\n':
   1374   1.1.1.6  mrg 	  string_append (decl, "\\n");
   1375   1.1.1.6  mrg 	  break;
   1376   1.1.1.6  mrg 	case '\r':
   1377   1.1.1.6  mrg 	  string_append (decl, "\\r");
   1378   1.1.1.6  mrg 	  break;
   1379   1.1.1.6  mrg 	case '\f':
   1380   1.1.1.6  mrg 	  string_append (decl, "\\f");
   1381   1.1.1.6  mrg 	  break;
   1382   1.1.1.6  mrg 	case '\v':
   1383   1.1.1.6  mrg 	  string_append (decl, "\\v");
   1384   1.1.1.6  mrg 	  break;
   1385   1.1.1.2  mrg 
   1386   1.1.1.6  mrg 	default:
   1387   1.1.1.6  mrg 	  if (ISPRINT (val))
   1388   1.1.1.6  mrg 	    string_appendn (decl, &val, 1);
   1389   1.1.1.6  mrg 	  else
   1390   1.1.1.2  mrg 	    {
   1391   1.1.1.6  mrg 	      string_append (decl, "\\x");
   1392   1.1.1.6  mrg 	      string_appendn (decl, mangled, 2);
   1393   1.1.1.2  mrg 	    }
   1394       1.1  mrg 	}
   1395       1.1  mrg 
   1396   1.1.1.6  mrg       mangled = endptr;
   1397       1.1  mrg     }
   1398       1.1  mrg   string_append (decl, "\"");
   1399       1.1  mrg 
   1400       1.1  mrg   if (type != 'a')
   1401       1.1  mrg     string_appendn (decl, &type, 1);
   1402       1.1  mrg 
   1403       1.1  mrg   return mangled;
   1404       1.1  mrg }
   1405       1.1  mrg 
   1406       1.1  mrg /* Extract the static array value from MANGLED and append it to DECL.
   1407       1.1  mrg    Return the remaining string on success or NULL on failure.  */
   1408       1.1  mrg static const char *
   1409   1.1.1.9  mrg dlang_parse_arrayliteral (string *decl, const char *mangled,
   1410   1.1.1.9  mrg 			  struct dlang_info *info)
   1411       1.1  mrg {
   1412   1.1.1.9  mrg   unsigned long elements;
   1413       1.1  mrg 
   1414   1.1.1.6  mrg   mangled = dlang_number (mangled, &elements);
   1415   1.1.1.6  mrg   if (mangled == NULL)
   1416       1.1  mrg     return NULL;
   1417       1.1  mrg 
   1418       1.1  mrg   string_append (decl, "[");
   1419       1.1  mrg   while (elements--)
   1420       1.1  mrg     {
   1421   1.1.1.9  mrg       mangled = dlang_value (decl, mangled, NULL, '\0', info);
   1422   1.1.1.8  mrg       if (mangled == NULL)
   1423   1.1.1.8  mrg 	return NULL;
   1424   1.1.1.8  mrg 
   1425       1.1  mrg       if (elements != 0)
   1426       1.1  mrg 	string_append (decl, ", ");
   1427       1.1  mrg     }
   1428       1.1  mrg 
   1429       1.1  mrg   string_append (decl, "]");
   1430       1.1  mrg   return mangled;
   1431       1.1  mrg }
   1432       1.1  mrg 
   1433       1.1  mrg /* Extract the associative array value from MANGLED and append it to DECL.
   1434       1.1  mrg    Return the remaining string on success or NULL on failure.  */
   1435       1.1  mrg static const char *
   1436   1.1.1.9  mrg dlang_parse_assocarray (string *decl, const char *mangled,
   1437   1.1.1.9  mrg 			struct dlang_info *info)
   1438       1.1  mrg {
   1439   1.1.1.9  mrg   unsigned long elements;
   1440       1.1  mrg 
   1441   1.1.1.6  mrg   mangled = dlang_number (mangled, &elements);
   1442   1.1.1.6  mrg   if (mangled == NULL)
   1443       1.1  mrg     return NULL;
   1444       1.1  mrg 
   1445       1.1  mrg   string_append (decl, "[");
   1446       1.1  mrg   while (elements--)
   1447       1.1  mrg     {
   1448   1.1.1.9  mrg       mangled = dlang_value (decl, mangled, NULL, '\0', info);
   1449   1.1.1.8  mrg       if (mangled == NULL)
   1450   1.1.1.8  mrg 	return NULL;
   1451   1.1.1.8  mrg 
   1452       1.1  mrg       string_append (decl, ":");
   1453   1.1.1.9  mrg       mangled = dlang_value (decl, mangled, NULL, '\0', info);
   1454   1.1.1.8  mrg       if (mangled == NULL)
   1455   1.1.1.8  mrg 	return NULL;
   1456       1.1  mrg 
   1457       1.1  mrg       if (elements != 0)
   1458       1.1  mrg 	string_append (decl, ", ");
   1459       1.1  mrg     }
   1460       1.1  mrg 
   1461       1.1  mrg   string_append (decl, "]");
   1462       1.1  mrg   return mangled;
   1463       1.1  mrg }
   1464       1.1  mrg 
   1465       1.1  mrg /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
   1466       1.1  mrg    Return the remaining string on success or NULL on failure.  */
   1467       1.1  mrg static const char *
   1468   1.1.1.9  mrg dlang_parse_structlit (string *decl, const char *mangled, const char *name,
   1469   1.1.1.9  mrg 		       struct dlang_info *info)
   1470       1.1  mrg {
   1471   1.1.1.9  mrg   unsigned long args;
   1472       1.1  mrg 
   1473   1.1.1.6  mrg   mangled = dlang_number (mangled, &args);
   1474   1.1.1.6  mrg   if (mangled == NULL)
   1475       1.1  mrg     return NULL;
   1476       1.1  mrg 
   1477       1.1  mrg   if (name != NULL)
   1478       1.1  mrg     string_append (decl, name);
   1479       1.1  mrg 
   1480       1.1  mrg   string_append (decl, "(");
   1481       1.1  mrg   while (args--)
   1482       1.1  mrg     {
   1483   1.1.1.9  mrg       mangled = dlang_value (decl, mangled, NULL, '\0', info);
   1484   1.1.1.8  mrg       if (mangled == NULL)
   1485   1.1.1.8  mrg 	return NULL;
   1486   1.1.1.8  mrg 
   1487       1.1  mrg       if (args != 0)
   1488       1.1  mrg 	string_append (decl, ", ");
   1489       1.1  mrg     }
   1490       1.1  mrg 
   1491       1.1  mrg   string_append (decl, ")");
   1492       1.1  mrg   return mangled;
   1493       1.1  mrg }
   1494       1.1  mrg 
   1495       1.1  mrg /* Extract the value from MANGLED and append it to DECL.
   1496       1.1  mrg    Return the remaining string on success or NULL on failure.  */
   1497       1.1  mrg static const char *
   1498   1.1.1.9  mrg dlang_value (string *decl, const char *mangled, const char *name, char type,
   1499   1.1.1.9  mrg 	     struct dlang_info *info)
   1500       1.1  mrg {
   1501       1.1  mrg   if (mangled == NULL || *mangled == '\0')
   1502   1.1.1.2  mrg     return NULL;
   1503       1.1  mrg 
   1504       1.1  mrg   switch (*mangled)
   1505       1.1  mrg     {
   1506       1.1  mrg       /* Null value.  */
   1507       1.1  mrg     case 'n':
   1508       1.1  mrg       mangled++;
   1509       1.1  mrg       string_append (decl, "null");
   1510       1.1  mrg       break;
   1511       1.1  mrg 
   1512       1.1  mrg       /* Integral values.  */
   1513       1.1  mrg     case 'N':
   1514       1.1  mrg       mangled++;
   1515       1.1  mrg       string_append (decl, "-");
   1516       1.1  mrg       mangled = dlang_parse_integer (decl, mangled, type);
   1517       1.1  mrg       break;
   1518       1.1  mrg 
   1519       1.1  mrg     case 'i':
   1520       1.1  mrg       mangled++;
   1521       1.1  mrg       /* Fall through */
   1522   1.1.1.6  mrg 
   1523   1.1.1.6  mrg       /* There really should always be an `i' before encoded numbers, but there
   1524   1.1.1.6  mrg 	 wasn't in early versions of D2, so this case range must remain for
   1525   1.1.1.6  mrg 	 backwards compatibility.  */
   1526       1.1  mrg     case '0': case '1': case '2': case '3': case '4':
   1527       1.1  mrg     case '5': case '6': case '7': case '8': case '9':
   1528       1.1  mrg       mangled = dlang_parse_integer (decl, mangled, type);
   1529       1.1  mrg       break;
   1530       1.1  mrg 
   1531       1.1  mrg       /* Real value.  */
   1532       1.1  mrg     case 'e':
   1533       1.1  mrg       mangled++;
   1534       1.1  mrg       mangled = dlang_parse_real (decl, mangled);
   1535       1.1  mrg       break;
   1536       1.1  mrg 
   1537       1.1  mrg       /* Complex value.  */
   1538       1.1  mrg     case 'c':
   1539       1.1  mrg       mangled++;
   1540       1.1  mrg       mangled = dlang_parse_real (decl, mangled);
   1541       1.1  mrg       string_append (decl, "+");
   1542       1.1  mrg       if (mangled == NULL || *mangled != 'c')
   1543       1.1  mrg 	return NULL;
   1544       1.1  mrg       mangled++;
   1545       1.1  mrg       mangled = dlang_parse_real (decl, mangled);
   1546       1.1  mrg       string_append (decl, "i");
   1547       1.1  mrg       break;
   1548       1.1  mrg 
   1549       1.1  mrg       /* String values.  */
   1550       1.1  mrg     case 'a': /* UTF8 */
   1551       1.1  mrg     case 'w': /* UTF16 */
   1552       1.1  mrg     case 'd': /* UTF32 */
   1553       1.1  mrg       mangled = dlang_parse_string (decl, mangled);
   1554       1.1  mrg       break;
   1555       1.1  mrg 
   1556       1.1  mrg       /* Array values.  */
   1557       1.1  mrg     case 'A':
   1558       1.1  mrg       mangled++;
   1559       1.1  mrg       if (type == 'H')
   1560   1.1.1.9  mrg 	mangled = dlang_parse_assocarray (decl, mangled, info);
   1561       1.1  mrg       else
   1562   1.1.1.9  mrg 	mangled = dlang_parse_arrayliteral (decl, mangled, info);
   1563       1.1  mrg       break;
   1564       1.1  mrg 
   1565       1.1  mrg       /* Struct values.  */
   1566       1.1  mrg     case 'S':
   1567       1.1  mrg       mangled++;
   1568   1.1.1.9  mrg       mangled = dlang_parse_structlit (decl, mangled, name, info);
   1569   1.1.1.9  mrg       break;
   1570   1.1.1.9  mrg 
   1571   1.1.1.9  mrg       /* Function literal symbol.  */
   1572   1.1.1.9  mrg     case 'f':
   1573   1.1.1.9  mrg       mangled++;
   1574   1.1.1.9  mrg       if (strncmp (mangled, "_D", 2) != 0
   1575   1.1.1.9  mrg 	  || !dlang_symbol_name_p (mangled + 2, info))
   1576   1.1.1.9  mrg 	return NULL;
   1577   1.1.1.9  mrg       mangled = dlang_parse_mangle (decl, mangled, info);
   1578       1.1  mrg       break;
   1579       1.1  mrg 
   1580       1.1  mrg     default:
   1581       1.1  mrg       return NULL;
   1582       1.1  mrg     }
   1583       1.1  mrg 
   1584       1.1  mrg   return mangled;
   1585       1.1  mrg }
   1586       1.1  mrg 
   1587   1.1.1.6  mrg /* Extract and demangle the symbol in MANGLED and append it to DECL.
   1588   1.1.1.6  mrg    Returns the remaining signature on success or NULL on failure.  */
   1589   1.1.1.6  mrg static const char *
   1590   1.1.1.9  mrg dlang_parse_mangle (string *decl, const char *mangled, struct dlang_info *info)
   1591       1.1  mrg {
   1592   1.1.1.6  mrg   /* A D mangled symbol is comprised of both scope and type information.
   1593   1.1.1.2  mrg 
   1594   1.1.1.6  mrg 	MangleName:
   1595   1.1.1.6  mrg 	    _D QualifiedName Type
   1596   1.1.1.6  mrg 	    _D QualifiedName Z
   1597   1.1.1.6  mrg 	    ^
   1598   1.1.1.6  mrg      The caller should have guaranteed that the start pointer is at the
   1599   1.1.1.6  mrg      above location.
   1600   1.1.1.9  mrg      Note that type is never a function type, but only the return type of
   1601   1.1.1.9  mrg      a function or the type of a variable.
   1602   1.1.1.6  mrg    */
   1603   1.1.1.6  mrg   mangled += 2;
   1604   1.1.1.4  mrg 
   1605   1.1.1.9  mrg   mangled = dlang_parse_qualified (decl, mangled, info, 1);
   1606   1.1.1.4  mrg 
   1607   1.1.1.6  mrg   if (mangled != NULL)
   1608   1.1.1.6  mrg     {
   1609   1.1.1.6  mrg       /* Artificial symbols end with 'Z' and have no type.  */
   1610   1.1.1.6  mrg       if (*mangled == 'Z')
   1611   1.1.1.6  mrg 	mangled++;
   1612   1.1.1.6  mrg       else
   1613   1.1.1.5  mrg 	{
   1614   1.1.1.9  mrg 	  /* Discard the declaration or return type.  */
   1615   1.1.1.9  mrg 	  string type;
   1616   1.1.1.6  mrg 
   1617   1.1.1.9  mrg 	  string_init (&type);
   1618   1.1.1.9  mrg 	  mangled = dlang_type (&type, mangled, info);
   1619   1.1.1.9  mrg 	  string_delete (&type);
   1620   1.1.1.6  mrg 	}
   1621       1.1  mrg     }
   1622   1.1.1.4  mrg 
   1623   1.1.1.6  mrg   return mangled;
   1624       1.1  mrg }
   1625       1.1  mrg 
   1626   1.1.1.6  mrg /* Extract and demangle the qualified symbol in MANGLED and append it to DECL.
   1627   1.1.1.9  mrg    SUFFIX_MODIFIERS is 1 if we are printing modifiers on this after the symbol.
   1628       1.1  mrg    Returns the remaining signature on success or NULL on failure.  */
   1629       1.1  mrg static const char *
   1630   1.1.1.6  mrg dlang_parse_qualified (string *decl, const char *mangled,
   1631   1.1.1.9  mrg 		       struct dlang_info *info, int suffix_modifiers)
   1632       1.1  mrg {
   1633   1.1.1.6  mrg   /* Qualified names are identifiers separated by their encoded length.
   1634   1.1.1.6  mrg      Nested functions also encode their argument types without specifying
   1635   1.1.1.6  mrg      what they return.
   1636   1.1.1.6  mrg 
   1637   1.1.1.6  mrg 	QualifiedName:
   1638   1.1.1.9  mrg 	    SymbolFunctionName
   1639   1.1.1.9  mrg 	    SymbolFunctionName QualifiedName
   1640   1.1.1.6  mrg 	    ^
   1641   1.1.1.9  mrg 
   1642   1.1.1.9  mrg 	SymbolFunctionName:
   1643   1.1.1.9  mrg 	    SymbolName
   1644   1.1.1.9  mrg 	    SymbolName TypeFunctionNoReturn
   1645   1.1.1.9  mrg 	    SymbolName M TypeFunctionNoReturn
   1646   1.1.1.9  mrg 	    SymbolName M TypeModifiers TypeFunctionNoReturn
   1647   1.1.1.9  mrg 
   1648   1.1.1.6  mrg      The start pointer should be at the above location.
   1649   1.1.1.6  mrg    */
   1650       1.1  mrg   size_t n = 0;
   1651       1.1  mrg   do
   1652       1.1  mrg     {
   1653   1.1.1.9  mrg       /* Skip over anonymous symbols.  */
   1654   1.1.1.9  mrg       if (*mangled == '0')
   1655   1.1.1.9  mrg       {
   1656   1.1.1.9  mrg 	do
   1657   1.1.1.9  mrg 	  mangled++;
   1658   1.1.1.9  mrg 	while (*mangled == '0');
   1659   1.1.1.9  mrg 
   1660   1.1.1.9  mrg 	continue;
   1661   1.1.1.9  mrg       }
   1662   1.1.1.9  mrg 
   1663       1.1  mrg       if (n++)
   1664       1.1  mrg 	string_append (decl, ".");
   1665       1.1  mrg 
   1666   1.1.1.9  mrg       mangled = dlang_identifier (decl, mangled, info);
   1667       1.1  mrg 
   1668   1.1.1.6  mrg       /* Consume the encoded arguments.  However if this is not followed by the
   1669   1.1.1.9  mrg 	 next encoded length or mangle type, then this is not a continuation of
   1670   1.1.1.9  mrg 	 a qualified name, in which case we backtrack and return the current
   1671   1.1.1.9  mrg 	 unconsumed position of the mangled decl.  */
   1672   1.1.1.6  mrg       if (mangled && (*mangled == 'M' || dlang_call_convention_p (mangled)))
   1673       1.1  mrg 	{
   1674   1.1.1.9  mrg 	  string mods;
   1675   1.1.1.6  mrg 	  const char *start = mangled;
   1676   1.1.1.6  mrg 	  int saved = string_length (decl);
   1677       1.1  mrg 
   1678   1.1.1.9  mrg 	  /* Save the type modifiers for appending at the end if needed.  */
   1679   1.1.1.9  mrg 	  string_init (&mods);
   1680   1.1.1.9  mrg 
   1681   1.1.1.6  mrg 	  /* Skip over 'this' parameter and type modifiers.  */
   1682       1.1  mrg 	  if (*mangled == 'M')
   1683   1.1.1.2  mrg 	    {
   1684   1.1.1.6  mrg 	      mangled++;
   1685   1.1.1.9  mrg 	      mangled = dlang_type_modifiers (&mods, mangled);
   1686   1.1.1.6  mrg 	      string_setlength (decl, saved);
   1687   1.1.1.2  mrg 	    }
   1688   1.1.1.2  mrg 
   1689   1.1.1.9  mrg 	  mangled = dlang_function_type_noreturn (decl, NULL, NULL,
   1690   1.1.1.9  mrg 						  mangled, info);
   1691   1.1.1.9  mrg 	  if (suffix_modifiers)
   1692   1.1.1.9  mrg 	    string_appendn (decl, mods.b, string_length (&mods));
   1693   1.1.1.4  mrg 
   1694   1.1.1.9  mrg 	  if (mangled == NULL || *mangled == '\0')
   1695       1.1  mrg 	    {
   1696   1.1.1.6  mrg 	      /* Did not match the rule we were looking for.  */
   1697   1.1.1.2  mrg 	      mangled = start;
   1698   1.1.1.6  mrg 	      string_setlength (decl, saved);
   1699       1.1  mrg 	    }
   1700   1.1.1.9  mrg 
   1701   1.1.1.9  mrg 	  string_delete (&mods);
   1702       1.1  mrg 	}
   1703       1.1  mrg     }
   1704   1.1.1.9  mrg   while (mangled && dlang_symbol_name_p (mangled, info));
   1705       1.1  mrg 
   1706       1.1  mrg   return mangled;
   1707       1.1  mrg }
   1708       1.1  mrg 
   1709       1.1  mrg /* Demangle the tuple from MANGLED and append it to DECL.
   1710       1.1  mrg    Return the remaining string on success or NULL on failure.  */
   1711       1.1  mrg static const char *
   1712   1.1.1.9  mrg dlang_parse_tuple (string *decl, const char *mangled, struct dlang_info *info)
   1713       1.1  mrg {
   1714   1.1.1.9  mrg   unsigned long elements;
   1715       1.1  mrg 
   1716   1.1.1.6  mrg   mangled = dlang_number (mangled, &elements);
   1717   1.1.1.6  mrg   if (mangled == NULL)
   1718       1.1  mrg     return NULL;
   1719       1.1  mrg 
   1720       1.1  mrg   string_append (decl, "Tuple!(");
   1721       1.1  mrg 
   1722       1.1  mrg   while (elements--)
   1723       1.1  mrg     {
   1724   1.1.1.9  mrg       mangled = dlang_type (decl, mangled, info);
   1725   1.1.1.8  mrg       if (mangled == NULL)
   1726   1.1.1.8  mrg 	return NULL;
   1727   1.1.1.8  mrg 
   1728       1.1  mrg       if (elements != 0)
   1729       1.1  mrg 	string_append (decl, ", ");
   1730       1.1  mrg     }
   1731       1.1  mrg 
   1732       1.1  mrg   string_append (decl, ")");
   1733       1.1  mrg   return mangled;
   1734       1.1  mrg }
   1735       1.1  mrg 
   1736   1.1.1.9  mrg /* Demangle the template symbol parameter from MANGLED and append it to DECL.
   1737   1.1.1.9  mrg    Return the remaining string on success or NULL on failure.  */
   1738   1.1.1.9  mrg static const char *
   1739   1.1.1.9  mrg dlang_template_symbol_param (string *decl, const char *mangled,
   1740   1.1.1.9  mrg 			     struct dlang_info *info)
   1741   1.1.1.9  mrg {
   1742   1.1.1.9  mrg   if (strncmp (mangled, "_D", 2) == 0
   1743   1.1.1.9  mrg       && dlang_symbol_name_p (mangled + 2, info))
   1744   1.1.1.9  mrg     return dlang_parse_mangle (decl, mangled, info);
   1745   1.1.1.9  mrg 
   1746   1.1.1.9  mrg   if (*mangled == 'Q')
   1747   1.1.1.9  mrg     return dlang_parse_qualified (decl, mangled, info, 0);
   1748   1.1.1.9  mrg 
   1749   1.1.1.9  mrg   unsigned long len;
   1750   1.1.1.9  mrg   const char *endptr = dlang_number (mangled, &len);
   1751   1.1.1.9  mrg 
   1752   1.1.1.9  mrg   if (endptr == NULL || len == 0)
   1753   1.1.1.9  mrg     return NULL;
   1754   1.1.1.9  mrg 
   1755   1.1.1.9  mrg   /* In template parameter symbols generated by the frontend up to 2.076,
   1756   1.1.1.9  mrg      the symbol length is encoded and the first character of the mangled
   1757   1.1.1.9  mrg      name can be a digit.  This causes ambiguity issues because the digits
   1758   1.1.1.9  mrg      of the two numbers are adjacent.  */
   1759   1.1.1.9  mrg   long psize = len;
   1760   1.1.1.9  mrg   const char *pend;
   1761   1.1.1.9  mrg   int saved = string_length (decl);
   1762   1.1.1.9  mrg 
   1763   1.1.1.9  mrg   /* Work backwards until a match is found.  */
   1764   1.1.1.9  mrg   for (pend = endptr; endptr != NULL; pend--)
   1765   1.1.1.9  mrg     {
   1766   1.1.1.9  mrg       mangled = pend;
   1767   1.1.1.9  mrg 
   1768   1.1.1.9  mrg       /* Reached the beginning of the pointer to the name length,
   1769   1.1.1.9  mrg 	 try parsing the entire symbol.  */
   1770   1.1.1.9  mrg       if (psize == 0)
   1771   1.1.1.9  mrg 	{
   1772   1.1.1.9  mrg 	  psize = len;
   1773   1.1.1.9  mrg 	  pend = endptr;
   1774   1.1.1.9  mrg 	  endptr = NULL;
   1775   1.1.1.9  mrg 	}
   1776   1.1.1.9  mrg 
   1777   1.1.1.9  mrg       /* Check whether template parameter is a function with a valid
   1778   1.1.1.9  mrg 	 return type or an untyped identifier.  */
   1779   1.1.1.9  mrg       if (dlang_symbol_name_p (mangled, info))
   1780   1.1.1.9  mrg 	mangled = dlang_parse_qualified (decl, mangled, info, 0);
   1781   1.1.1.9  mrg       else if (strncmp (mangled, "_D", 2) == 0
   1782   1.1.1.9  mrg 	       && dlang_symbol_name_p (mangled + 2, info))
   1783   1.1.1.9  mrg 	mangled = dlang_parse_mangle (decl, mangled, info);
   1784   1.1.1.9  mrg 
   1785   1.1.1.9  mrg       /* Check for name length mismatch.  */
   1786   1.1.1.9  mrg       if (mangled && (endptr == NULL || (mangled - pend) == psize))
   1787   1.1.1.9  mrg 	return mangled;
   1788   1.1.1.9  mrg 
   1789   1.1.1.9  mrg       psize /= 10;
   1790   1.1.1.9  mrg       string_setlength (decl, saved);
   1791   1.1.1.9  mrg     }
   1792   1.1.1.9  mrg 
   1793   1.1.1.9  mrg   /* No match on any combinations.  */
   1794   1.1.1.9  mrg   return NULL;
   1795   1.1.1.9  mrg }
   1796   1.1.1.9  mrg 
   1797       1.1  mrg /* Demangle the argument list from MANGLED and append it to DECL.
   1798       1.1  mrg    Return the remaining string on success or NULL on failure.  */
   1799       1.1  mrg static const char *
   1800   1.1.1.9  mrg dlang_template_args (string *decl, const char *mangled, struct dlang_info *info)
   1801       1.1  mrg {
   1802       1.1  mrg   size_t n = 0;
   1803       1.1  mrg 
   1804       1.1  mrg   while (mangled && *mangled != '\0')
   1805       1.1  mrg     {
   1806       1.1  mrg       switch (*mangled)
   1807       1.1  mrg 	{
   1808       1.1  mrg 	case 'Z': /* End of parameter list.  */
   1809       1.1  mrg 	  mangled++;
   1810       1.1  mrg 	  return mangled;
   1811       1.1  mrg 	}
   1812       1.1  mrg 
   1813       1.1  mrg       if (n++)
   1814       1.1  mrg 	string_append (decl, ", ");
   1815       1.1  mrg 
   1816   1.1.1.2  mrg       /* Skip over specialised template prefix.  */
   1817   1.1.1.2  mrg       if (*mangled == 'H')
   1818   1.1.1.2  mrg 	mangled++;
   1819   1.1.1.2  mrg 
   1820       1.1  mrg       switch (*mangled)
   1821       1.1  mrg 	{
   1822       1.1  mrg 	case 'S': /* Symbol parameter.  */
   1823       1.1  mrg 	  mangled++;
   1824   1.1.1.9  mrg 	  mangled = dlang_template_symbol_param (decl, mangled, info);
   1825       1.1  mrg 	  break;
   1826       1.1  mrg 	case 'T': /* Type parameter.  */
   1827       1.1  mrg 	  mangled++;
   1828   1.1.1.9  mrg 	  mangled = dlang_type (decl, mangled, info);
   1829       1.1  mrg 	  break;
   1830       1.1  mrg 	case 'V': /* Value parameter.  */
   1831       1.1  mrg 	{
   1832       1.1  mrg 	  string name;
   1833       1.1  mrg 	  char type;
   1834       1.1  mrg 
   1835       1.1  mrg 	  /* Peek at the type.  */
   1836       1.1  mrg 	  mangled++;
   1837       1.1  mrg 	  type = *mangled;
   1838       1.1  mrg 
   1839   1.1.1.9  mrg 	  if (type == 'Q')
   1840   1.1.1.9  mrg 	    {
   1841   1.1.1.9  mrg 	      /* Value type is a back reference, peek at the real type.  */
   1842   1.1.1.9  mrg 	      const char *backref;
   1843   1.1.1.9  mrg 	      if (dlang_backref (mangled, &backref, info) == NULL)
   1844   1.1.1.9  mrg 		return NULL;
   1845   1.1.1.9  mrg 
   1846   1.1.1.9  mrg 	      type = *backref;
   1847   1.1.1.9  mrg 	    }
   1848   1.1.1.9  mrg 
   1849       1.1  mrg 	  /* In the few instances where the type is actually desired in
   1850       1.1  mrg 	     the output, it should precede the value from dlang_value.  */
   1851       1.1  mrg 	  string_init (&name);
   1852   1.1.1.9  mrg 	  mangled = dlang_type (&name, mangled, info);
   1853       1.1  mrg 	  string_need (&name, 1);
   1854       1.1  mrg 	  *(name.p) = '\0';
   1855       1.1  mrg 
   1856   1.1.1.9  mrg 	  mangled = dlang_value (decl, mangled, name.b, type, info);
   1857       1.1  mrg 	  string_delete (&name);
   1858       1.1  mrg 	  break;
   1859       1.1  mrg 	}
   1860   1.1.1.9  mrg 	case 'X': /* Externally mangled parameter.  */
   1861   1.1.1.9  mrg 	{
   1862   1.1.1.9  mrg 	  unsigned long len;
   1863   1.1.1.9  mrg 	  const char *endptr;
   1864   1.1.1.9  mrg 
   1865   1.1.1.9  mrg 	  mangled++;
   1866   1.1.1.9  mrg 	  endptr = dlang_number (mangled, &len);
   1867   1.1.1.9  mrg 	  if (endptr == NULL || strlen (endptr) < len)
   1868   1.1.1.9  mrg 	    return NULL;
   1869       1.1  mrg 
   1870   1.1.1.9  mrg 	  string_appendn (decl, endptr, len);
   1871   1.1.1.9  mrg 	  mangled = endptr + len;
   1872   1.1.1.9  mrg 	  break;
   1873   1.1.1.9  mrg 	}
   1874       1.1  mrg 	default:
   1875       1.1  mrg 	  return NULL;
   1876       1.1  mrg 	}
   1877       1.1  mrg     }
   1878       1.1  mrg 
   1879       1.1  mrg   return mangled;
   1880       1.1  mrg }
   1881       1.1  mrg 
   1882       1.1  mrg /* Extract and demangle the template symbol in MANGLED, expected to
   1883   1.1.1.9  mrg    be made up of LEN characters (-1 if unknown), and append it to DECL.
   1884       1.1  mrg    Returns the remaining signature on success or NULL on failure.  */
   1885       1.1  mrg static const char *
   1886   1.1.1.9  mrg dlang_parse_template (string *decl, const char *mangled,
   1887   1.1.1.9  mrg 		      struct dlang_info *info, unsigned long len)
   1888       1.1  mrg {
   1889       1.1  mrg   const char *start = mangled;
   1890   1.1.1.9  mrg   string args;
   1891       1.1  mrg 
   1892       1.1  mrg   /* Template instance names have the types and values of its parameters
   1893       1.1  mrg      encoded into it.
   1894       1.1  mrg 
   1895       1.1  mrg 	TemplateInstanceName:
   1896       1.1  mrg 	    Number __T LName TemplateArgs Z
   1897   1.1.1.6  mrg 	    Number __U LName TemplateArgs Z
   1898       1.1  mrg 		   ^
   1899       1.1  mrg      The start pointer should be at the above location, and LEN should be
   1900       1.1  mrg      the value of the decoded number.
   1901       1.1  mrg    */
   1902   1.1.1.6  mrg 
   1903   1.1.1.6  mrg   /* Template symbol.  */
   1904   1.1.1.9  mrg   if (!dlang_symbol_name_p (mangled + 3, info) || mangled[3] == '0')
   1905       1.1  mrg     return NULL;
   1906       1.1  mrg 
   1907       1.1  mrg   mangled += 3;
   1908       1.1  mrg 
   1909       1.1  mrg   /* Template identifier.  */
   1910   1.1.1.9  mrg   mangled = dlang_identifier (decl, mangled, info);
   1911       1.1  mrg 
   1912       1.1  mrg   /* Template arguments.  */
   1913   1.1.1.9  mrg   string_init (&args);
   1914   1.1.1.9  mrg   mangled = dlang_template_args (&args, mangled, info);
   1915   1.1.1.9  mrg 
   1916       1.1  mrg   string_append (decl, "!(");
   1917   1.1.1.9  mrg   string_appendn (decl, args.b, string_length (&args));
   1918       1.1  mrg   string_append (decl, ")");
   1919       1.1  mrg 
   1920   1.1.1.9  mrg   string_delete (&args);
   1921   1.1.1.9  mrg 
   1922       1.1  mrg   /* Check for template name length mismatch.  */
   1923   1.1.1.9  mrg   if (len != TEMPLATE_LENGTH_UNKNOWN
   1924   1.1.1.9  mrg       && mangled
   1925   1.1.1.9  mrg       && (unsigned long) (mangled - start) != len)
   1926       1.1  mrg     return NULL;
   1927       1.1  mrg 
   1928       1.1  mrg   return mangled;
   1929       1.1  mrg }
   1930       1.1  mrg 
   1931   1.1.1.9  mrg /* Initialize the information structure we use to pass around information.  */
   1932   1.1.1.9  mrg static void
   1933   1.1.1.9  mrg dlang_demangle_init_info (const char *mangled, int last_backref,
   1934   1.1.1.9  mrg 			  struct dlang_info *info)
   1935   1.1.1.9  mrg {
   1936   1.1.1.9  mrg   info->s = mangled;
   1937   1.1.1.9  mrg   info->last_backref = last_backref;
   1938   1.1.1.9  mrg }
   1939   1.1.1.9  mrg 
   1940       1.1  mrg /* Extract and demangle the symbol in MANGLED.  Returns the demangled
   1941       1.1  mrg    signature on success or NULL on failure.  */
   1942       1.1  mrg 
   1943       1.1  mrg char *
   1944       1.1  mrg dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
   1945       1.1  mrg {
   1946       1.1  mrg   string decl;
   1947       1.1  mrg   char *demangled = NULL;
   1948       1.1  mrg 
   1949       1.1  mrg   if (mangled == NULL || *mangled == '\0')
   1950       1.1  mrg     return NULL;
   1951       1.1  mrg 
   1952       1.1  mrg   if (strncmp (mangled, "_D", 2) != 0)
   1953       1.1  mrg     return NULL;
   1954       1.1  mrg 
   1955       1.1  mrg   string_init (&decl);
   1956       1.1  mrg 
   1957       1.1  mrg   if (strcmp (mangled, "_Dmain") == 0)
   1958       1.1  mrg     {
   1959       1.1  mrg       string_append (&decl, "D main");
   1960       1.1  mrg     }
   1961       1.1  mrg   else
   1962       1.1  mrg     {
   1963   1.1.1.9  mrg       struct dlang_info info;
   1964   1.1.1.9  mrg 
   1965   1.1.1.9  mrg       dlang_demangle_init_info (mangled, strlen (mangled), &info);
   1966   1.1.1.9  mrg       mangled = dlang_parse_mangle (&decl, mangled, &info);
   1967   1.1.1.9  mrg 
   1968   1.1.1.9  mrg       /* Check that the entire symbol was successfully demangled.  */
   1969   1.1.1.9  mrg       if (mangled == NULL || *mangled != '\0')
   1970       1.1  mrg 	string_delete (&decl);
   1971       1.1  mrg     }
   1972       1.1  mrg 
   1973       1.1  mrg   if (string_length (&decl) > 0)
   1974       1.1  mrg     {
   1975       1.1  mrg       string_need (&decl, 1);
   1976       1.1  mrg       *(decl.p) = '\0';
   1977       1.1  mrg       demangled = decl.b;
   1978       1.1  mrg     }
   1979       1.1  mrg 
   1980       1.1  mrg   return demangled;
   1981       1.1  mrg }
   1982       1.1  mrg 
   1983