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