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 
5 This file is part of the libiberty library.
6 Libiberty is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10 
11 In addition to the permissions in the GNU Library General Public
12 License, the Free Software Foundation gives you unlimited permission
13 to link the compiled version of this file into combinations with other
14 programs, and to distribute those combinations without any restriction
15 coming from the use of this file.  (The Library Public License
16 restrictions do apply in other respects; for example, they cover
17 modification of the file, and distribution when not linked into a
18 combined executable.)
19 
20 Libiberty is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23 Library General Public License for more details.
24 
25 You should have received a copy of the GNU Library General Public
26 License along with libiberty; see the file COPYING.LIB.
27 If not, see <http://www.gnu.org/licenses/>.  */
28 
29 /* This file exports one function; dlang_demangle.  */
30 
31 #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 
50 typedef 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 
57 static void
58 string_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 
82 static void
83 string_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 
92 static void
93 string_init (string *s)
94 {
95   s->b = s->p = s->e = NULL;
96 }
97 
98 static int
99 string_length (string *s)
100 {
101   if (s->p == s->b)
102     {
103       return 0;
104     }
105   return s->p - s->b;
106 }
107 
108 static void
109 string_setlength (string *s, int n)
110 {
111   if (n - string_length (s) < 0)
112     {
113       s->p = s->b + n;
114     }
115 }
116 
117 static void
118 string_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 
126 static void
127 string_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 
137 static void
138 string_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 
154 static void
155 string_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.  */
164 enum 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 */
179 static const char *dlang_function_args (string *, const char *);
180 
181 static const char *dlang_type (string *, const char *);
182 
183 static const char *dlang_value (string *, const char *, const char *, char);
184 
185 static const char *dlang_parse_qualified (string *, const char *,
186 					  enum dlang_symbol_kinds);
187 
188 static const char *dlang_parse_mangle (string *, const char *,
189 				       enum dlang_symbol_kinds);
190 
191 static const char *dlang_parse_tuple (string *, const char *);
192 
193 static 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.  */
198 static const char *
199 dlang_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.  */
228 static const char *
229 dlang_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.  */
256 static int
257 dlang_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.  */
272 static const char *
273 dlang_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.  */
312 static const char *
313 dlang_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.  */
350 static const char *
351 dlang_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.  */
419 static const char *
420 dlang_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.  */
468 static const char *
469 dlang_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.  */
530 static const char *
531 dlang_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.  */
783 static const char *
784 dlang_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.  */
936 static const char *
937 dlang_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.  */
1047 static const char *
1048 dlang_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.  */
1116 static const char *
1117 dlang_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.  */
1181 static const char *
1182 dlang_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.  */
1207 static const char *
1208 dlang_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.  */
1238 static const char *
1239 dlang_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.  */
1267 static const char *
1268 dlang_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.  */
1349 static const char *
1350 dlang_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.  */
1422 static const char *
1423 dlang_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.  */
1497 static const char *
1498 dlang_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.  */
1524 static const char *
1525 dlang_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.  */
1587 static const char *
1588 dlang_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 
1627 char *
1628 dlang_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