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