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