]> git.ipfire.org Git - thirdparty/gcc.git/blob - libiberty/d-demangle.c
d74cf47b1a935ee2f03991494769a8e202d3e553
[thirdparty/gcc.git] / libiberty / d-demangle.c
1 /* Demangler for the D programming language
2 Copyright (C) 2014-2021 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
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
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
103 string_init (string *s)
104 {
105 s->b = s->p = s->e = NULL;
106 }
107
108 static int
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
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
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
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
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
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 *
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 *
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
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 *
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 *
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 *
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)
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 *
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
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 == '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 *
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 return dlang_lname (decl, mangled, len);
1048 }
1049
1050 /* Extract the plain identifier from MANGLED and prepend/append it to DECL
1051 with special treatment for some magic compiler generted symbols.
1052 Return the remaining string on success or NULL on failure. */
1053 static const char *
1054 dlang_lname (string *decl, const char *mangled, unsigned long len)
1055 {
1056 switch (len)
1057 {
1058 case 6:
1059 if (strncmp (mangled, "__ctor", len) == 0)
1060 {
1061 /* Constructor symbol for a class/struct. */
1062 string_append (decl, "this");
1063 mangled += len;
1064 return mangled;
1065 }
1066 else if (strncmp (mangled, "__dtor", len) == 0)
1067 {
1068 /* Destructor symbol for a class/struct. */
1069 string_append (decl, "~this");
1070 mangled += len;
1071 return mangled;
1072 }
1073 else if (strncmp (mangled, "__initZ", len + 1) == 0)
1074 {
1075 /* The static initialiser for a given symbol. */
1076 string_prepend (decl, "initializer for ");
1077 string_setlength (decl, string_length (decl) - 1);
1078 mangled += len;
1079 return mangled;
1080 }
1081 else if (strncmp (mangled, "__vtblZ", len + 1) == 0)
1082 {
1083 /* The vtable symbol for a given class. */
1084 string_prepend (decl, "vtable for ");
1085 string_setlength (decl, string_length (decl) - 1);
1086 mangled += len;
1087 return mangled;
1088 }
1089 break;
1090
1091 case 7:
1092 if (strncmp (mangled, "__ClassZ", len + 1) == 0)
1093 {
1094 /* The classinfo symbol for a given class. */
1095 string_prepend (decl, "ClassInfo for ");
1096 string_setlength (decl, string_length (decl) - 1);
1097 mangled += len;
1098 return mangled;
1099 }
1100 break;
1101
1102 case 10:
1103 if (strncmp (mangled, "__postblitMFZ", len + 3) == 0)
1104 {
1105 /* Postblit symbol for a struct. */
1106 string_append (decl, "this(this)");
1107 mangled += len + 3;
1108 return mangled;
1109 }
1110 break;
1111
1112 case 11:
1113 if (strncmp (mangled, "__InterfaceZ", len + 1) == 0)
1114 {
1115 /* The interface symbol for a given class. */
1116 string_prepend (decl, "Interface for ");
1117 string_setlength (decl, string_length (decl) - 1);
1118 mangled += len;
1119 return mangled;
1120 }
1121 break;
1122
1123 case 12:
1124 if (strncmp (mangled, "__ModuleInfoZ", len + 1) == 0)
1125 {
1126 /* The ModuleInfo symbol for a given module. */
1127 string_prepend (decl, "ModuleInfo for ");
1128 string_setlength (decl, string_length (decl) - 1);
1129 mangled += len;
1130 return mangled;
1131 }
1132 break;
1133 }
1134
1135 string_appendn (decl, mangled, len);
1136 mangled += len;
1137
1138 return mangled;
1139 }
1140
1141 /* Extract the integer value from MANGLED and append it to DECL,
1142 where TYPE is the type it should be represented as.
1143 Return the remaining string on success or NULL on failure. */
1144 static const char *
1145 dlang_parse_integer (string *decl, const char *mangled, char type)
1146 {
1147 if (type == 'a' || type == 'u' || type == 'w')
1148 {
1149 /* Parse character value. */
1150 char value[20];
1151 int pos = sizeof(value);
1152 int width = 0;
1153 unsigned long val;
1154
1155 mangled = dlang_number (mangled, &val);
1156 if (mangled == NULL)
1157 return NULL;
1158
1159 string_append (decl, "'");
1160
1161 if (type == 'a' && val >= 0x20 && val < 0x7F)
1162 {
1163 /* Represent as a character literal. */
1164 char c = (char) val;
1165 string_appendn (decl, &c, 1);
1166 }
1167 else
1168 {
1169 /* Represent as a hexadecimal value. */
1170 switch (type)
1171 {
1172 case 'a': /* char */
1173 string_append (decl, "\\x");
1174 width = 2;
1175 break;
1176 case 'u': /* wchar */
1177 string_append (decl, "\\u");
1178 width = 4;
1179 break;
1180 case 'w': /* dchar */
1181 string_append (decl, "\\U");
1182 width = 8;
1183 break;
1184 }
1185
1186 while (val > 0)
1187 {
1188 int digit = val % 16;
1189
1190 if (digit < 10)
1191 value[--pos] = (char)(digit + '0');
1192 else
1193 value[--pos] = (char)((digit - 10) + 'a');
1194
1195 val /= 16;
1196 width--;
1197 }
1198
1199 for (; width > 0; width--)
1200 value[--pos] = '0';
1201
1202 string_appendn (decl, &(value[pos]), sizeof(value) - pos);
1203 }
1204 string_append (decl, "'");
1205 }
1206 else if (type == 'b')
1207 {
1208 /* Parse boolean value. */
1209 unsigned long val;
1210
1211 mangled = dlang_number (mangled, &val);
1212 if (mangled == NULL)
1213 return NULL;
1214
1215 string_append (decl, val ? "true" : "false");
1216 }
1217 else
1218 {
1219 /* Parse integer value. */
1220 const char *numptr = mangled;
1221 size_t num = 0;
1222
1223 if (! ISDIGIT (*mangled))
1224 return NULL;
1225
1226 while (ISDIGIT (*mangled))
1227 {
1228 num++;
1229 mangled++;
1230 }
1231 string_appendn (decl, numptr, num);
1232
1233 /* Append suffix. */
1234 switch (type)
1235 {
1236 case 'h': /* ubyte */
1237 case 't': /* ushort */
1238 case 'k': /* uint */
1239 string_append (decl, "u");
1240 break;
1241 case 'l': /* long */
1242 string_append (decl, "L");
1243 break;
1244 case 'm': /* ulong */
1245 string_append (decl, "uL");
1246 break;
1247 }
1248 }
1249
1250 return mangled;
1251 }
1252
1253 /* Extract the floating-point value from MANGLED and append it to DECL.
1254 Return the remaining string on success or NULL on failure. */
1255 static const char *
1256 dlang_parse_real (string *decl, const char *mangled)
1257 {
1258 /* Handle NAN and +-INF. */
1259 if (strncmp (mangled, "NAN", 3) == 0)
1260 {
1261 string_append (decl, "NaN");
1262 mangled += 3;
1263 return mangled;
1264 }
1265 else if (strncmp (mangled, "INF", 3) == 0)
1266 {
1267 string_append (decl, "Inf");
1268 mangled += 3;
1269 return mangled;
1270 }
1271 else if (strncmp (mangled, "NINF", 4) == 0)
1272 {
1273 string_append (decl, "-Inf");
1274 mangled += 4;
1275 return mangled;
1276 }
1277
1278 /* Hexadecimal prefix and leading bit. */
1279 if (*mangled == 'N')
1280 {
1281 string_append (decl, "-");
1282 mangled++;
1283 }
1284
1285 if (!ISXDIGIT (*mangled))
1286 return NULL;
1287
1288 string_append (decl, "0x");
1289 string_appendn (decl, mangled, 1);
1290 string_append (decl, ".");
1291 mangled++;
1292
1293 /* Significand. */
1294 while (ISXDIGIT (*mangled))
1295 {
1296 string_appendn (decl, mangled, 1);
1297 mangled++;
1298 }
1299
1300 /* Exponent. */
1301 if (*mangled != 'P')
1302 return NULL;
1303
1304 string_append (decl, "p");
1305 mangled++;
1306
1307 if (*mangled == 'N')
1308 {
1309 string_append (decl, "-");
1310 mangled++;
1311 }
1312
1313 while (ISDIGIT (*mangled))
1314 {
1315 string_appendn (decl, mangled, 1);
1316 mangled++;
1317 }
1318
1319 return mangled;
1320 }
1321
1322 /* Extract the string value from MANGLED and append it to DECL.
1323 Return the remaining string on success or NULL on failure. */
1324 static const char *
1325 dlang_parse_string (string *decl, const char *mangled)
1326 {
1327 char type = *mangled;
1328 unsigned long len;
1329
1330 mangled++;
1331 mangled = dlang_number (mangled, &len);
1332 if (mangled == NULL || *mangled != '_')
1333 return NULL;
1334
1335 mangled++;
1336 string_append (decl, "\"");
1337 while (len--)
1338 {
1339 char val;
1340 const char *endptr = dlang_hexdigit (mangled, &val);
1341
1342 if (endptr == NULL)
1343 return NULL;
1344
1345 /* Sanitize white and non-printable characters. */
1346 switch (val)
1347 {
1348 case ' ':
1349 string_append (decl, " ");
1350 break;
1351 case '\t':
1352 string_append (decl, "\\t");
1353 break;
1354 case '\n':
1355 string_append (decl, "\\n");
1356 break;
1357 case '\r':
1358 string_append (decl, "\\r");
1359 break;
1360 case '\f':
1361 string_append (decl, "\\f");
1362 break;
1363 case '\v':
1364 string_append (decl, "\\v");
1365 break;
1366
1367 default:
1368 if (ISPRINT (val))
1369 string_appendn (decl, &val, 1);
1370 else
1371 {
1372 string_append (decl, "\\x");
1373 string_appendn (decl, mangled, 2);
1374 }
1375 }
1376
1377 mangled = endptr;
1378 }
1379 string_append (decl, "\"");
1380
1381 if (type != 'a')
1382 string_appendn (decl, &type, 1);
1383
1384 return mangled;
1385 }
1386
1387 /* Extract the static array value from MANGLED and append it to DECL.
1388 Return the remaining string on success or NULL on failure. */
1389 static const char *
1390 dlang_parse_arrayliteral (string *decl, const char *mangled,
1391 struct dlang_info *info)
1392 {
1393 unsigned long elements;
1394
1395 mangled = dlang_number (mangled, &elements);
1396 if (mangled == NULL)
1397 return NULL;
1398
1399 string_append (decl, "[");
1400 while (elements--)
1401 {
1402 mangled = dlang_value (decl, mangled, NULL, '\0', info);
1403 if (mangled == NULL)
1404 return NULL;
1405
1406 if (elements != 0)
1407 string_append (decl, ", ");
1408 }
1409
1410 string_append (decl, "]");
1411 return mangled;
1412 }
1413
1414 /* Extract the associative array value from MANGLED and append it to DECL.
1415 Return the remaining string on success or NULL on failure. */
1416 static const char *
1417 dlang_parse_assocarray (string *decl, const char *mangled,
1418 struct dlang_info *info)
1419 {
1420 unsigned long elements;
1421
1422 mangled = dlang_number (mangled, &elements);
1423 if (mangled == NULL)
1424 return NULL;
1425
1426 string_append (decl, "[");
1427 while (elements--)
1428 {
1429 mangled = dlang_value (decl, mangled, NULL, '\0', info);
1430 if (mangled == NULL)
1431 return NULL;
1432
1433 string_append (decl, ":");
1434 mangled = dlang_value (decl, mangled, NULL, '\0', info);
1435 if (mangled == NULL)
1436 return NULL;
1437
1438 if (elements != 0)
1439 string_append (decl, ", ");
1440 }
1441
1442 string_append (decl, "]");
1443 return mangled;
1444 }
1445
1446 /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1447 Return the remaining string on success or NULL on failure. */
1448 static const char *
1449 dlang_parse_structlit (string *decl, const char *mangled, const char *name,
1450 struct dlang_info *info)
1451 {
1452 unsigned long args;
1453
1454 mangled = dlang_number (mangled, &args);
1455 if (mangled == NULL)
1456 return NULL;
1457
1458 if (name != NULL)
1459 string_append (decl, name);
1460
1461 string_append (decl, "(");
1462 while (args--)
1463 {
1464 mangled = dlang_value (decl, mangled, NULL, '\0', info);
1465 if (mangled == NULL)
1466 return NULL;
1467
1468 if (args != 0)
1469 string_append (decl, ", ");
1470 }
1471
1472 string_append (decl, ")");
1473 return mangled;
1474 }
1475
1476 /* Extract the value from MANGLED and append it to DECL.
1477 Return the remaining string on success or NULL on failure. */
1478 static const char *
1479 dlang_value (string *decl, const char *mangled, const char *name, char type,
1480 struct dlang_info *info)
1481 {
1482 if (mangled == NULL || *mangled == '\0')
1483 return NULL;
1484
1485 switch (*mangled)
1486 {
1487 /* Null value. */
1488 case 'n':
1489 mangled++;
1490 string_append (decl, "null");
1491 break;
1492
1493 /* Integral values. */
1494 case 'N':
1495 mangled++;
1496 string_append (decl, "-");
1497 mangled = dlang_parse_integer (decl, mangled, type);
1498 break;
1499
1500 case 'i':
1501 mangled++;
1502 /* Fall through */
1503
1504 /* There really should always be an `i' before encoded numbers, but there
1505 wasn't in early versions of D2, so this case range must remain for
1506 backwards compatibility. */
1507 case '0': case '1': case '2': case '3': case '4':
1508 case '5': case '6': case '7': case '8': case '9':
1509 mangled = dlang_parse_integer (decl, mangled, type);
1510 break;
1511
1512 /* Real value. */
1513 case 'e':
1514 mangled++;
1515 mangled = dlang_parse_real (decl, mangled);
1516 break;
1517
1518 /* Complex value. */
1519 case 'c':
1520 mangled++;
1521 mangled = dlang_parse_real (decl, mangled);
1522 string_append (decl, "+");
1523 if (mangled == NULL || *mangled != 'c')
1524 return NULL;
1525 mangled++;
1526 mangled = dlang_parse_real (decl, mangled);
1527 string_append (decl, "i");
1528 break;
1529
1530 /* String values. */
1531 case 'a': /* UTF8 */
1532 case 'w': /* UTF16 */
1533 case 'd': /* UTF32 */
1534 mangled = dlang_parse_string (decl, mangled);
1535 break;
1536
1537 /* Array values. */
1538 case 'A':
1539 mangled++;
1540 if (type == 'H')
1541 mangled = dlang_parse_assocarray (decl, mangled, info);
1542 else
1543 mangled = dlang_parse_arrayliteral (decl, mangled, info);
1544 break;
1545
1546 /* Struct values. */
1547 case 'S':
1548 mangled++;
1549 mangled = dlang_parse_structlit (decl, mangled, name, info);
1550 break;
1551
1552 /* Function literal symbol. */
1553 case 'f':
1554 mangled++;
1555 if (strncmp (mangled, "_D", 2) != 0
1556 || !dlang_symbol_name_p (mangled + 2, info))
1557 return NULL;
1558 mangled = dlang_parse_mangle (decl, mangled, info);
1559 break;
1560
1561 default:
1562 return NULL;
1563 }
1564
1565 return mangled;
1566 }
1567
1568 /* Extract and demangle the symbol in MANGLED and append it to DECL.
1569 Returns the remaining signature on success or NULL on failure. */
1570 static const char *
1571 dlang_parse_mangle (string *decl, const char *mangled, struct dlang_info *info)
1572 {
1573 /* A D mangled symbol is comprised of both scope and type information.
1574
1575 MangleName:
1576 _D QualifiedName Type
1577 _D QualifiedName Z
1578 ^
1579 The caller should have guaranteed that the start pointer is at the
1580 above location.
1581 Note that type is never a function type, but only the return type of
1582 a function or the type of a variable.
1583 */
1584 mangled += 2;
1585
1586 mangled = dlang_parse_qualified (decl, mangled, info, 1);
1587
1588 if (mangled != NULL)
1589 {
1590 /* Artificial symbols end with 'Z' and have no type. */
1591 if (*mangled == 'Z')
1592 mangled++;
1593 else
1594 {
1595 /* Discard the declaration or return type. */
1596 string type;
1597
1598 string_init (&type);
1599 mangled = dlang_type (&type, mangled, info);
1600 string_delete (&type);
1601 }
1602 }
1603
1604 return mangled;
1605 }
1606
1607 /* Extract and demangle the qualified symbol in MANGLED and append it to DECL.
1608 SUFFIX_MODIFIERS is 1 if we are printing modifiers on this after the symbol.
1609 Returns the remaining signature on success or NULL on failure. */
1610 static const char *
1611 dlang_parse_qualified (string *decl, const char *mangled,
1612 struct dlang_info *info, int suffix_modifiers)
1613 {
1614 /* Qualified names are identifiers separated by their encoded length.
1615 Nested functions also encode their argument types without specifying
1616 what they return.
1617
1618 QualifiedName:
1619 SymbolFunctionName
1620 SymbolFunctionName QualifiedName
1621 ^
1622
1623 SymbolFunctionName:
1624 SymbolName
1625 SymbolName TypeFunctionNoReturn
1626 SymbolName M TypeFunctionNoReturn
1627 SymbolName M TypeModifiers TypeFunctionNoReturn
1628
1629 The start pointer should be at the above location.
1630 */
1631 size_t n = 0;
1632 do
1633 {
1634 if (n++)
1635 string_append (decl, ".");
1636
1637 /* Skip over anonymous symbols. */
1638 while (*mangled == '0')
1639 mangled++;
1640
1641 mangled = dlang_identifier (decl, mangled, info);
1642
1643 /* Consume the encoded arguments. However if this is not followed by the
1644 next encoded length or mangle type, then this is not a continuation of
1645 a qualified name, in which case we backtrack and return the current
1646 unconsumed position of the mangled decl. */
1647 if (mangled && (*mangled == 'M' || dlang_call_convention_p (mangled)))
1648 {
1649 string mods;
1650 const char *start = mangled;
1651 int saved = string_length (decl);
1652
1653 /* Save the type modifiers for appending at the end if needed. */
1654 string_init (&mods);
1655
1656 /* Skip over 'this' parameter and type modifiers. */
1657 if (*mangled == 'M')
1658 {
1659 mangled++;
1660 mangled = dlang_type_modifiers (&mods, mangled);
1661 string_setlength (decl, saved);
1662 }
1663
1664 mangled = dlang_function_type_noreturn (decl, NULL, NULL,
1665 mangled, info);
1666 if (suffix_modifiers)
1667 string_appendn (decl, mods.b, string_length (&mods));
1668
1669 if (mangled == NULL || *mangled == '\0')
1670 {
1671 /* Did not match the rule we were looking for. */
1672 mangled = start;
1673 string_setlength (decl, saved);
1674 }
1675
1676 string_delete (&mods);
1677 }
1678 }
1679 while (mangled && dlang_symbol_name_p (mangled, info));
1680
1681 return mangled;
1682 }
1683
1684 /* Demangle the tuple from MANGLED and append it to DECL.
1685 Return the remaining string on success or NULL on failure. */
1686 static const char *
1687 dlang_parse_tuple (string *decl, const char *mangled, struct dlang_info *info)
1688 {
1689 unsigned long elements;
1690
1691 mangled = dlang_number (mangled, &elements);
1692 if (mangled == NULL)
1693 return NULL;
1694
1695 string_append (decl, "Tuple!(");
1696
1697 while (elements--)
1698 {
1699 mangled = dlang_type (decl, mangled, info);
1700 if (mangled == NULL)
1701 return NULL;
1702
1703 if (elements != 0)
1704 string_append (decl, ", ");
1705 }
1706
1707 string_append (decl, ")");
1708 return mangled;
1709 }
1710
1711 /* Demangle the template symbol parameter from MANGLED and append it to DECL.
1712 Return the remaining string on success or NULL on failure. */
1713 static const char *
1714 dlang_template_symbol_param (string *decl, const char *mangled,
1715 struct dlang_info *info)
1716 {
1717 if (strncmp (mangled, "_D", 2) == 0
1718 && dlang_symbol_name_p (mangled + 2, info))
1719 return dlang_parse_mangle (decl, mangled, info);
1720
1721 if (*mangled == 'Q')
1722 return dlang_parse_qualified (decl, mangled, info, 0);
1723
1724 unsigned long len;
1725 const char *endptr = dlang_number (mangled, &len);
1726
1727 if (endptr == NULL || len == 0)
1728 return NULL;
1729
1730 /* In template parameter symbols generated by the frontend up to 2.076,
1731 the symbol length is encoded and the first character of the mangled
1732 name can be a digit. This causes ambiguity issues because the digits
1733 of the two numbers are adjacent. */
1734 long psize = len;
1735 const char *pend;
1736 int saved = string_length (decl);
1737
1738 /* Work backwards until a match is found. */
1739 for (pend = endptr; endptr != NULL; pend--)
1740 {
1741 mangled = pend;
1742
1743 /* Reached the beginning of the pointer to the name length,
1744 try parsing the entire symbol. */
1745 if (psize == 0)
1746 {
1747 psize = len;
1748 pend = endptr;
1749 endptr = NULL;
1750 }
1751
1752 /* Check whether template parameter is a function with a valid
1753 return type or an untyped identifier. */
1754 if (dlang_symbol_name_p (mangled, info))
1755 mangled = dlang_parse_qualified (decl, mangled, info, 0);
1756 else if (strncmp (mangled, "_D", 2) == 0
1757 && dlang_symbol_name_p (mangled + 2, info))
1758 mangled = dlang_parse_mangle (decl, mangled, info);
1759
1760 /* Check for name length mismatch. */
1761 if (mangled && (endptr == NULL || (mangled - pend) == psize))
1762 return mangled;
1763
1764 psize /= 10;
1765 string_setlength (decl, saved);
1766 }
1767
1768 /* No match on any combinations. */
1769 return NULL;
1770 }
1771
1772 /* Demangle the argument list from MANGLED and append it to DECL.
1773 Return the remaining string on success or NULL on failure. */
1774 static const char *
1775 dlang_template_args (string *decl, const char *mangled, struct dlang_info *info)
1776 {
1777 size_t n = 0;
1778
1779 while (mangled && *mangled != '\0')
1780 {
1781 switch (*mangled)
1782 {
1783 case 'Z': /* End of parameter list. */
1784 mangled++;
1785 return mangled;
1786 }
1787
1788 if (n++)
1789 string_append (decl, ", ");
1790
1791 /* Skip over specialised template prefix. */
1792 if (*mangled == 'H')
1793 mangled++;
1794
1795 switch (*mangled)
1796 {
1797 case 'S': /* Symbol parameter. */
1798 mangled++;
1799 mangled = dlang_template_symbol_param (decl, mangled, info);
1800 break;
1801 case 'T': /* Type parameter. */
1802 mangled++;
1803 mangled = dlang_type (decl, mangled, info);
1804 break;
1805 case 'V': /* Value parameter. */
1806 {
1807 string name;
1808 char type;
1809
1810 /* Peek at the type. */
1811 mangled++;
1812 type = *mangled;
1813
1814 if (type == 'Q')
1815 {
1816 /* Value type is a back reference, peek at the real type. */
1817 const char *backref;
1818 if (dlang_backref (mangled, &backref, info) == NULL)
1819 return NULL;
1820
1821 type = *backref;
1822 }
1823
1824 /* In the few instances where the type is actually desired in
1825 the output, it should precede the value from dlang_value. */
1826 string_init (&name);
1827 mangled = dlang_type (&name, mangled, info);
1828 string_need (&name, 1);
1829 *(name.p) = '\0';
1830
1831 mangled = dlang_value (decl, mangled, name.b, type, info);
1832 string_delete (&name);
1833 break;
1834 }
1835 case 'X': /* Externally mangled parameter. */
1836 {
1837 unsigned long len;
1838 const char *endptr;
1839
1840 mangled++;
1841 endptr = dlang_number (mangled, &len);
1842 if (endptr == NULL || strlen (endptr) < len)
1843 return NULL;
1844
1845 string_appendn (decl, endptr, len);
1846 mangled = endptr + len;
1847 break;
1848 }
1849 default:
1850 return NULL;
1851 }
1852 }
1853
1854 return mangled;
1855 }
1856
1857 /* Extract and demangle the template symbol in MANGLED, expected to
1858 be made up of LEN characters (-1 if unknown), and append it to DECL.
1859 Returns the remaining signature on success or NULL on failure. */
1860 static const char *
1861 dlang_parse_template (string *decl, const char *mangled,
1862 struct dlang_info *info, unsigned long len)
1863 {
1864 const char *start = mangled;
1865 string args;
1866
1867 /* Template instance names have the types and values of its parameters
1868 encoded into it.
1869
1870 TemplateInstanceName:
1871 Number __T LName TemplateArgs Z
1872 Number __U LName TemplateArgs Z
1873 ^
1874 The start pointer should be at the above location, and LEN should be
1875 the value of the decoded number.
1876 */
1877
1878 /* Template symbol. */
1879 if (!dlang_symbol_name_p (mangled + 3, info) || mangled[3] == '0')
1880 return NULL;
1881
1882 mangled += 3;
1883
1884 /* Template identifier. */
1885 mangled = dlang_identifier (decl, mangled, info);
1886
1887 /* Template arguments. */
1888 string_init (&args);
1889 mangled = dlang_template_args (&args, mangled, info);
1890
1891 string_append (decl, "!(");
1892 string_appendn (decl, args.b, string_length (&args));
1893 string_append (decl, ")");
1894
1895 string_delete (&args);
1896
1897 /* Check for template name length mismatch. */
1898 if (len != TEMPLATE_LENGTH_UNKNOWN
1899 && mangled
1900 && (unsigned long) (mangled - start) != len)
1901 return NULL;
1902
1903 return mangled;
1904 }
1905
1906 /* Initialize the information structure we use to pass around information. */
1907 static void
1908 dlang_demangle_init_info (const char *mangled, int last_backref,
1909 struct dlang_info *info)
1910 {
1911 info->s = mangled;
1912 info->last_backref = last_backref;
1913 }
1914
1915 /* Extract and demangle the symbol in MANGLED. Returns the demangled
1916 signature on success or NULL on failure. */
1917
1918 char *
1919 dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
1920 {
1921 string decl;
1922 char *demangled = NULL;
1923
1924 if (mangled == NULL || *mangled == '\0')
1925 return NULL;
1926
1927 if (strncmp (mangled, "_D", 2) != 0)
1928 return NULL;
1929
1930 string_init (&decl);
1931
1932 if (strcmp (mangled, "_Dmain") == 0)
1933 {
1934 string_append (&decl, "D main");
1935 }
1936 else
1937 {
1938 struct dlang_info info;
1939
1940 dlang_demangle_init_info (mangled, strlen (mangled), &info);
1941 mangled = dlang_parse_mangle (&decl, mangled, &info);
1942
1943 /* Check that the entire symbol was successfully demangled. */
1944 if (mangled == NULL || *mangled != '\0')
1945 string_delete (&decl);
1946 }
1947
1948 if (string_length (&decl) > 0)
1949 {
1950 string_need (&decl, 1);
1951 *(decl.p) = '\0';
1952 demangled = decl.b;
1953 }
1954
1955 return demangled;
1956 }
1957