]> git.ipfire.org Git - thirdparty/gcc.git/blame - libiberty/d-demangle.c
Daily bump.
[thirdparty/gcc.git] / libiberty / d-demangle.c
CommitLineData
43b1b9ed 1/* Demangler for the D programming language
8d9254fc 2 Copyright (C) 2014-2020 Free Software Foundation, Inc.
43b1b9ed
IB
3 Written by Iain Buclaw (ibuclaw@gdcproject.org)
4
5This file is part of the libiberty library.
6Libiberty is free software; you can redistribute it and/or
7modify it under the terms of the GNU Library General Public
8License as published by the Free Software Foundation; either
9version 2 of the License, or (at your option) any later version.
10
11In addition to the permissions in the GNU Library General Public
12License, the Free Software Foundation gives you unlimited permission
13to link the compiled version of this file into combinations with other
14programs, and to distribute those combinations without any restriction
15coming from the use of this file. (The Library Public License
16restrictions do apply in other respects; for example, they cover
17modification of the file, and distribution when not linked into a
18combined executable.)
19
20Libiberty is distributed in the hope that it will be useful,
21but WITHOUT ANY WARRANTY; without even the implied warranty of
22MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23Library General Public License for more details.
24
25You should have received a copy of the GNU Library General Public
26License along with libiberty; see the file COPYING.LIB.
27If not, see <http://www.gnu.org/licenses/>. */
28
dbe65f77 29/* This file exports one function; dlang_demangle. */
43b1b9ed
IB
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>
43b1b9ed
IB
43#endif
44
45#include <demangle.h>
46#include "libiberty.h"
47
48/* A mini string-handling package */
49
50typedef struct string /* Beware: these aren't required to be */
51{ /* '\0' terminated. */
52 char *b; /* pointer to start of string */
53 char *p; /* pointer after last character */
54 char *e; /* pointer after end of allocated space */
55} string;
56
57static void
58string_need (string *s, int n)
59{
60 int tem;
61
62 if (s->b == NULL)
63 {
64 if (n < 32)
65 {
66 n = 32;
67 }
68 s->p = s->b = XNEWVEC (char, n);
69 s->e = s->b + n;
70 }
71 else if (s->e - s->p < n)
72 {
73 tem = s->p - s->b;
74 n += tem;
75 n *= 2;
76 s->b = XRESIZEVEC (char, s->b, n);
77 s->p = s->b + tem;
78 s->e = s->b + n;
79 }
80}
81
82static void
83string_delete (string *s)
84{
85 if (s->b != NULL)
86 {
87 XDELETEVEC (s->b);
88 s->b = s->e = s->p = NULL;
89 }
90}
91
92static void
93string_init (string *s)
94{
95 s->b = s->p = s->e = NULL;
96}
97
98static int
99string_length (string *s)
100{
101 if (s->p == s->b)
102 {
103 return 0;
104 }
105 return s->p - s->b;
106}
107
108static void
109string_setlength (string *s, int n)
110{
111 if (n - string_length (s) < 0)
112 {
113 s->p = s->b + n;
114 }
115}
116
117static void
118string_append (string *p, const char *s)
119{
120 int n = strlen (s);
121 string_need (p, n);
122 memcpy (p->p, s, n);
123 p->p += n;
124}
125
126static void
127string_appendn (string *p, const char *s, int n)
128{
129 if (n != 0)
130 {
131 string_need (p, n);
132 memcpy (p->p, s, n);
133 p->p += n;
134 }
135}
136
137static void
138string_prependn (string *p, const char *s, int n)
139{
140 char *q;
141
142 if (n != 0)
143 {
144 string_need (p, n);
145 for (q = p->p - 1; q >= p->b; q--)
146 {
147 q[n] = q[0];
148 }
149 memcpy (p->b, s, n);
150 p->p += n;
151 }
152}
153
154static void
155string_prepend (string *p, const char *s)
156{
157 if (s != NULL && *s != '\0')
158 {
159 string_prependn (p, s, strlen (s));
160 }
161}
162
3f30a274
IB
163/* Demangle information structure we pass around. */
164struct dlang_info
7e865541 165{
3f30a274
IB
166 /* The string we are demangling. */
167 const char *s;
168 /* The index of the last back reference. */
169 int last_backref;
7e865541
IB
170};
171
3f30a274
IB
172/* Pass as the LEN to dlang_parse_template if symbol length is not known. */
173enum { TEMPLATE_LENGTH_UNKNOWN = -1 };
174
43b1b9ed 175/* Prototypes for forward referenced functions */
3f30a274
IB
176static const char *dlang_function_type (string *, const char *,
177 struct dlang_info *);
43b1b9ed 178
3f30a274
IB
179static const char *dlang_function_args (string *, const char *,
180 struct dlang_info *);
181
182static const char *dlang_type (string *, const char *, struct dlang_info *);
43b1b9ed
IB
183
184static const char *dlang_value (string *, const char *, const char *, char);
185
5a4dbf7d 186static const char *dlang_parse_qualified (string *, const char *,
3f30a274 187 struct dlang_info *, int);
5a4dbf7d
IB
188
189static const char *dlang_parse_mangle (string *, const char *,
3f30a274
IB
190 struct dlang_info *);
191
192static const char *dlang_parse_tuple (string *, const char *,
193 struct dlang_info *);
43b1b9ed 194
3f30a274
IB
195static const char *dlang_parse_template (string *, const char *,
196 struct dlang_info *, long);
43b1b9ed 197
3f30a274 198static const char *dlang_lname (string *, const char *, long);
43b1b9ed
IB
199
200
dbe65f77
IB
201/* Extract the number from MANGLED, and assign the result to RET.
202 Return the remaining string on success or NULL on failure. */
203static const char *
204dlang_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
5398cab9
IB
231/* Extract the hex-digit from MANGLED, and assign the result to RET.
232 Return the remaining string on success or NULL on failure. */
233static const char *
234dlang_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
0e3712f6
IB
259/* Extract the function calling convention from MANGLED and
260 return 1 on success or 0 on failure. */
261static int
262dlang_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
3f30a274
IB
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. */
277static const char *
278dlang_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. */
323static const char *
324dlang_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. */
351static const char *
352dlang_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. */
382static const char *
383dlang_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. */
421static int
422dlang_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
43b1b9ed
IB
444/* Demangle the calling convention from MANGLED and append it to DECL.
445 Return the remaining string on success or NULL on failure. */
446static const char *
447dlang_call_convention (string *decl, const char *mangled)
448{
449 if (mangled == NULL || *mangled == '\0')
76b41cad 450 return NULL;
43b1b9ed
IB
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;
13617162
IB
473 case 'Y': /* (Objective-C) */
474 mangled++;
475 string_append (decl, "extern(Objective-C) ");
476 break;
43b1b9ed
IB
477 default:
478 return NULL;
479 }
480
481 return mangled;
482}
483
fa66ced4
IB
484/* Extract the type modifiers from MANGLED and append them to DECL.
485 Returns the remaining signature on success or NULL on failure. */
486static const char *
487dlang_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
43b1b9ed
IB
522/* Demangle the D function attributes from MANGLED and append it to DECL.
523 Return the remaining string on success or NULL on failure. */
524static const char *
525dlang_attributes (string *decl, const char *mangled)
526{
527 if (mangled == NULL || *mangled == '\0')
76b41cad 528 return NULL;
43b1b9ed
IB
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':
7ce4461f 561 case 'k':
43b1b9ed
IB
562 /* inout parameter is represented as 'Ng'.
563 vector parameter is represented as 'Nh'.
7ce4461f 564 return paramenter is represented as 'Nk'.
43b1b9ed
IB
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;
7ce4461f
IB
573 case 'j': /* return */
574 mangled++;
575 string_append (decl, "return ");
576 continue;
ec89d258
IB
577 case 'l': /* scope */
578 mangled++;
579 string_append (decl, "scope ");
580 continue;
3a55774f
IB
581 case 'm': /* @live */
582 mangled++;
583 string_append (decl, "@live ");
584 continue;
7ce4461f
IB
585
586 default: /* unknown attribute */
587 return NULL;
43b1b9ed
IB
588 }
589 break;
590 }
591
592 return mangled;
593}
594
3f30a274
IB
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. */
600static const char *
601dlang_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
43b1b9ed
IB
622/* Demangle the function type from MANGLED and append it to DECL.
623 Return the remaining string on success or NULL on failure. */
624static const char *
3f30a274 625dlang_function_type (string *decl, const char *mangled, struct dlang_info *info)
43b1b9ed
IB
626{
627 string attr, args, type;
43b1b9ed
IB
628
629 if (mangled == NULL || *mangled == '\0')
76b41cad 630 return NULL;
43b1b9ed
IB
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
3f30a274 642 mangled = dlang_function_type_noreturn (&args, decl, &attr, mangled, info);
43b1b9ed
IB
643
644 /* Function return type. */
3f30a274 645 mangled = dlang_type (&type, mangled, info);
43b1b9ed
IB
646
647 /* Append to decl in order. */
3f30a274
IB
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));
43b1b9ed
IB
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. */
661static const char *
3f30a274 662dlang_function_args (string *decl, const char *mangled, struct dlang_info *info)
43b1b9ed
IB
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++;
acf1f7da
IB
676 if (n != 0)
677 string_append (decl, ", ");
678 string_append (decl, "...");
43b1b9ed
IB
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
7ce4461f
IB
694 if (mangled[0] == 'N' && mangled[1] == 'k') /* return(T) */
695 {
696 mangled += 2;
697 string_append (decl, "return ");
698 }
699
43b1b9ed
IB
700 switch (*mangled)
701 {
387d0773
IB
702 case 'I': /* in(T) */
703 mangled++;
704 string_append (decl, "in ");
705 if (*mangled == 'K') /* in ref(T) */
706 {
707 mangled++;
708 string_append (decl, "ref ");
709 }
710 break;
43b1b9ed
IB
711 case 'J': /* out(T) */
712 mangled++;
713 string_append (decl, "out ");
714 break;
715 case 'K': /* ref(T) */
716 mangled++;
717 string_append (decl, "ref ");
718 break;
719 case 'L': /* lazy(T) */
720 mangled++;
721 string_append (decl, "lazy ");
722 break;
723 }
3f30a274 724 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
725 }
726
727 return mangled;
728}
729
730/* Demangle the type from MANGLED and append it to DECL.
731 Return the remaining string on success or NULL on failure. */
732static const char *
3f30a274 733dlang_type (string *decl, const char *mangled, struct dlang_info *info)
43b1b9ed
IB
734{
735 if (mangled == NULL || *mangled == '\0')
76b41cad 736 return NULL;
43b1b9ed
IB
737
738 switch (*mangled)
739 {
740 case 'O': /* shared(T) */
741 mangled++;
742 string_append (decl, "shared(");
3f30a274 743 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
744 string_append (decl, ")");
745 return mangled;
746 case 'x': /* const(T) */
747 mangled++;
748 string_append (decl, "const(");
3f30a274 749 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
750 string_append (decl, ")");
751 return mangled;
752 case 'y': /* immutable(T) */
753 mangled++;
754 string_append (decl, "immutable(");
3f30a274 755 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
756 string_append (decl, ")");
757 return mangled;
758 case 'N':
759 mangled++;
760 if (*mangled == 'g') /* wild(T) */
761 {
762 mangled++;
763 string_append (decl, "inout(");
3f30a274 764 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
765 string_append (decl, ")");
766 return mangled;
767 }
768 else if (*mangled == 'h') /* vector(T) */
769 {
770 mangled++;
771 string_append (decl, "__vector(");
3f30a274 772 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
773 string_append (decl, ")");
774 return mangled;
775 }
776 else
777 return NULL;
778 case 'A': /* dynamic array (T[]) */
779 mangled++;
3f30a274 780 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
781 string_append (decl, "[]");
782 return mangled;
783 case 'G': /* static array (T[N]) */
784 {
785 const char *numptr;
786 size_t num = 0;
787 mangled++;
788
789 numptr = mangled;
790 while (ISDIGIT (*mangled))
791 {
792 num++;
793 mangled++;
794 }
3f30a274 795 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
796 string_append (decl, "[");
797 string_appendn (decl, numptr, num);
798 string_append (decl, "]");
799 return mangled;
800 }
801 case 'H': /* associative array (T[T]) */
802 {
803 string type;
804 size_t sztype;
805 mangled++;
806
807 string_init (&type);
3f30a274 808 mangled = dlang_type (&type, mangled, info);
43b1b9ed
IB
809 sztype = string_length (&type);
810
3f30a274 811 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
812 string_append (decl, "[");
813 string_appendn (decl, type.b, sztype);
814 string_append (decl, "]");
815
816 string_delete (&type);
817 return mangled;
818 }
819 case 'P': /* pointer (T*) */
820 mangled++;
0e3712f6 821 if (!dlang_call_convention_p (mangled))
0f4b8b31 822 {
3f30a274 823 mangled = dlang_type (decl, mangled, info);
0e3712f6 824 string_append (decl, "*");
0f4b8b31
IB
825 return mangled;
826 }
0e3712f6
IB
827 /* Fall through */
828 case 'F': /* function T (D) */
829 case 'U': /* function T (C) */
830 case 'W': /* function T (Windows) */
831 case 'V': /* function T (Pascal) */
832 case 'R': /* function T (C++) */
833 case 'Y': /* function T (Objective-C) */
834 /* Function pointer types don't include the trailing asterisk. */
3f30a274 835 mangled = dlang_function_type (decl, mangled, info);
0e3712f6 836 string_append (decl, "function");
43b1b9ed 837 return mangled;
43b1b9ed
IB
838 case 'C': /* class T */
839 case 'S': /* struct T */
840 case 'E': /* enum T */
841 case 'T': /* typedef T */
842 mangled++;
3f30a274 843 return dlang_parse_qualified (decl, mangled, info, 0);
43b1b9ed 844 case 'D': /* delegate T */
fa66ced4
IB
845 {
846 string mods;
847 size_t szmods;
43b1b9ed 848 mangled++;
fa66ced4
IB
849
850 string_init (&mods);
851 mangled = dlang_type_modifiers (&mods, mangled);
852 szmods = string_length (&mods);
853
3f30a274
IB
854 /* Back referenced function type. */
855 if (*mangled == 'Q')
856 mangled = dlang_type_backref (decl, mangled, info, 1);
857 else
858 mangled = dlang_function_type (decl, mangled, info);
859
43b1b9ed 860 string_append (decl, "delegate");
fa66ced4
IB
861 string_appendn (decl, mods.b, szmods);
862
863 string_delete (&mods);
43b1b9ed 864 return mangled;
fa66ced4 865 }
43b1b9ed
IB
866 case 'B': /* tuple T */
867 mangled++;
3f30a274 868 return dlang_parse_tuple (decl, mangled, info);
43b1b9ed 869
43b1b9ed
IB
870 /* Basic types */
871 case 'n':
872 mangled++;
873 string_append (decl, "none");
874 return mangled;
875 case 'v':
876 mangled++;
877 string_append (decl, "void");
878 return mangled;
879 case 'g':
880 mangled++;
881 string_append (decl, "byte");
882 return mangled;
883 case 'h':
884 mangled++;
885 string_append (decl, "ubyte");
886 return mangled;
887 case 's':
888 mangled++;
889 string_append (decl, "short");
890 return mangled;
891 case 't':
892 mangled++;
893 string_append (decl, "ushort");
894 return mangled;
895 case 'i':
896 mangled++;
897 string_append (decl, "int");
898 return mangled;
899 case 'k':
900 mangled++;
901 string_append (decl, "uint");
902 return mangled;
903 case 'l':
904 mangled++;
905 string_append (decl, "long");
906 return mangled;
907 case 'm':
908 mangled++;
909 string_append (decl, "ulong");
910 return mangled;
911 case 'f':
912 mangled++;
913 string_append (decl, "float");
914 return mangled;
915 case 'd':
916 mangled++;
917 string_append (decl, "double");
918 return mangled;
919 case 'e':
920 mangled++;
921 string_append (decl, "real");
922 return mangled;
923
924 /* Imaginary and Complex types */
925 case 'o':
926 mangled++;
927 string_append (decl, "ifloat");
928 return mangled;
929 case 'p':
930 mangled++;
931 string_append (decl, "idouble");
932 return mangled;
933 case 'j':
934 mangled++;
935 string_append (decl, "ireal");
936 return mangled;
937 case 'q':
938 mangled++;
939 string_append (decl, "cfloat");
940 return mangled;
941 case 'r':
942 mangled++;
943 string_append (decl, "cdouble");
944 return mangled;
945 case 'c':
946 mangled++;
947 string_append (decl, "creal");
948 return mangled;
949
950 /* Other types */
951 case 'b':
952 mangled++;
953 string_append (decl, "bool");
954 return mangled;
955 case 'a':
956 mangled++;
957 string_append (decl, "char");
958 return mangled;
959 case 'u':
960 mangled++;
961 string_append (decl, "wchar");
962 return mangled;
963 case 'w':
964 mangled++;
965 string_append (decl, "dchar");
966 return mangled;
59251a73
IB
967 case 'z':
968 mangled++;
969 switch (*mangled)
970 {
971 case 'i':
972 mangled++;
973 string_append (decl, "cent");
974 return mangled;
975 case 'k':
976 mangled++;
977 string_append (decl, "ucent");
978 return mangled;
979 }
980 return NULL;
43b1b9ed 981
3f30a274
IB
982 /* Back referenced type. */
983 case 'Q':
984 return dlang_type_backref (decl, mangled, info, 0);
985
43b1b9ed
IB
986 default: /* unhandled */
987 return NULL;
988 }
989}
990
991/* Extract the identifier from MANGLED and append it to DECL.
992 Return the remaining string on success or NULL on failure. */
993static const char *
3f30a274 994dlang_identifier (string *decl, const char *mangled, struct dlang_info *info)
43b1b9ed 995{
7e865541
IB
996 long len;
997
3f30a274 998 if (mangled == NULL || *mangled == '\0')
7e865541
IB
999 return NULL;
1000
3f30a274
IB
1001 if (*mangled == 'Q')
1002 return dlang_symbol_backref (decl, mangled, info);
43b1b9ed 1003
3f30a274
IB
1004 /* May be a template instance without a length prefix. */
1005 if (mangled[0] == '_' && mangled[1] == '_'
1006 && (mangled[2] == 'T' || mangled[2] == 'U'))
1007 return dlang_parse_template (decl, mangled, info, TEMPLATE_LENGTH_UNKNOWN);
7e865541 1008
3f30a274 1009 const char *endptr = dlang_number (mangled, &len);
7e865541 1010
3f30a274
IB
1011 if (endptr == NULL || len == 0)
1012 return NULL;
7e865541 1013
3f30a274
IB
1014 if (strlen (endptr) < (size_t) len)
1015 return NULL;
7e865541 1016
3f30a274 1017 mangled = endptr;
43b1b9ed 1018
3f30a274
IB
1019 /* May be a template instance with a length prefix. */
1020 if (len >= 5 && mangled[0] == '_' && mangled[1] == '_'
1021 && (mangled[2] == 'T' || mangled[2] == 'U'))
1022 return dlang_parse_template (decl, mangled, info, len);
43b1b9ed 1023
3f30a274
IB
1024 return dlang_lname (decl, mangled, len);
1025}
43b1b9ed 1026
3f30a274
IB
1027/* Extract the plain identifier from MANGLED and prepend/append it to DECL
1028 with special treatment for some magic compiler generted symbols.
1029 Return the remaining string on success or NULL on failure. */
1030static const char *
1031dlang_lname (string *decl, const char *mangled, long len)
1032{
1033 switch (len)
1034 {
1035 case 6:
1036 if (strncmp (mangled, "__ctor", len) == 0)
43b1b9ed 1037 {
3f30a274
IB
1038 /* Constructor symbol for a class/struct. */
1039 string_append (decl, "this");
1040 mangled += len;
1041 return mangled;
1042 }
1043 else if (strncmp (mangled, "__dtor", len) == 0)
1044 {
1045 /* Destructor symbol for a class/struct. */
1046 string_append (decl, "~this");
1047 mangled += len;
1048 return mangled;
1049 }
1050 else if (strncmp (mangled, "__initZ", len + 1) == 0)
1051 {
1052 /* The static initialiser for a given symbol. */
1053 string_prepend (decl, "initializer for ");
1054 string_setlength (decl, string_length (decl) - 1);
1055 mangled += len;
1056 return mangled;
1057 }
1058 else if (strncmp (mangled, "__vtblZ", len + 1) == 0)
1059 {
1060 /* The vtable symbol for a given class. */
1061 string_prepend (decl, "vtable for ");
1062 string_setlength (decl, string_length (decl) - 1);
1063 mangled += len;
1064 return mangled;
1065 }
1066 break;
5cc158e9 1067
3f30a274
IB
1068 case 7:
1069 if (strncmp (mangled, "__ClassZ", len + 1) == 0)
1070 {
1071 /* The classinfo symbol for a given class. */
1072 string_prepend (decl, "ClassInfo for ");
1073 string_setlength (decl, string_length (decl) - 1);
1074 mangled += len;
1075 return mangled;
1076 }
1077 break;
5cc158e9 1078
3f30a274
IB
1079 case 10:
1080 if (strncmp (mangled, "__postblitMFZ", len + 3) == 0)
1081 {
1082 /* Postblit symbol for a struct. */
1083 string_append (decl, "this(this)");
1084 mangled += len + 3;
1085 return mangled;
1086 }
1087 break;
5cc158e9 1088
3f30a274
IB
1089 case 11:
1090 if (strncmp (mangled, "__InterfaceZ", len + 1) == 0)
1091 {
1092 /* The interface symbol for a given class. */
1093 string_prepend (decl, "Interface for ");
1094 string_setlength (decl, string_length (decl) - 1);
1095 mangled += len;
1096 return mangled;
43b1b9ed 1097 }
3f30a274 1098 break;
43b1b9ed 1099
3f30a274
IB
1100 case 12:
1101 if (strncmp (mangled, "__ModuleInfoZ", len + 1) == 0)
1102 {
1103 /* The ModuleInfo symbol for a given module. */
1104 string_prepend (decl, "ModuleInfo for ");
1105 string_setlength (decl, string_length (decl) - 1);
1106 mangled += len;
1107 return mangled;
1108 }
1109 break;
43b1b9ed 1110 }
43b1b9ed 1111
3f30a274
IB
1112 string_appendn (decl, mangled, len);
1113 mangled += len;
1114
43b1b9ed
IB
1115 return mangled;
1116}
1117
1118/* Extract the integer value from MANGLED and append it to DECL,
1119 where TYPE is the type it should be represented as.
1120 Return the remaining string on success or NULL on failure. */
1121static const char *
1122dlang_parse_integer (string *decl, const char *mangled, char type)
1123{
1124 if (type == 'a' || type == 'u' || type == 'w')
1125 {
1126 /* Parse character value. */
81adfd10
B
1127 char value[20];
1128 int pos = sizeof(value);
43b1b9ed 1129 int width = 0;
dbe65f77 1130 long val;
43b1b9ed 1131
dbe65f77
IB
1132 mangled = dlang_number (mangled, &val);
1133 if (mangled == NULL)
43b1b9ed
IB
1134 return NULL;
1135
1136 string_append (decl, "'");
1137
1138 if (type == 'a' && val >= 0x20 && val < 0x7F)
1139 {
1140 /* Represent as a character literal. */
1141 char c = (char) val;
1142 string_appendn (decl, &c, 1);
1143 }
1144 else
1145 {
1146 /* Represent as a hexadecimal value. */
1147 switch (type)
1148 {
1149 case 'a': /* char */
1150 string_append (decl, "\\x");
1151 width = 2;
1152 break;
1153 case 'u': /* wchar */
1154 string_append (decl, "\\u");
1155 width = 4;
1156 break;
1157 case 'w': /* dchar */
1158 string_append (decl, "\\U");
1159 width = 8;
1160 break;
1161 }
1162
1163 while (val > 0)
1164 {
1165 int digit = val % 16;
1166
1167 if (digit < 10)
1168 value[--pos] = (char)(digit + '0');
1169 else
1170 value[--pos] = (char)((digit - 10) + 'a');
1171
1172 val /= 16;
1173 width--;
1174 }
1175
1176 for (; width > 0; width--)
1177 value[--pos] = '0';
1178
81adfd10 1179 string_appendn (decl, &(value[pos]), sizeof(value) - pos);
43b1b9ed
IB
1180 }
1181 string_append (decl, "'");
43b1b9ed
IB
1182 }
1183 else if (type == 'b')
1184 {
1185 /* Parse boolean value. */
dbe65f77 1186 long val;
43b1b9ed 1187
dbe65f77
IB
1188 mangled = dlang_number (mangled, &val);
1189 if (mangled == NULL)
43b1b9ed
IB
1190 return NULL;
1191
1192 string_append (decl, val ? "true" : "false");
43b1b9ed
IB
1193 }
1194 else
1195 {
1196 /* Parse integer value. */
1197 const char *numptr = mangled;
1198 size_t num = 0;
1199
dbe65f77
IB
1200 if (! ISDIGIT (*mangled))
1201 return NULL;
1202
43b1b9ed
IB
1203 while (ISDIGIT (*mangled))
1204 {
1205 num++;
1206 mangled++;
1207 }
1208 string_appendn (decl, numptr, num);
1209
1210 /* Append suffix. */
1211 switch (type)
1212 {
1213 case 'h': /* ubyte */
1214 case 't': /* ushort */
1215 case 'k': /* uint */
1216 string_append (decl, "u");
1217 break;
1218 case 'l': /* long */
1219 string_append (decl, "L");
1220 break;
1221 case 'm': /* ulong */
1222 string_append (decl, "uL");
1223 break;
1224 }
1225 }
1226
1227 return mangled;
1228}
1229
1230/* Extract the floating-point value from MANGLED and append it to DECL.
1231 Return the remaining string on success or NULL on failure. */
1232static const char *
1233dlang_parse_real (string *decl, const char *mangled)
1234{
43b1b9ed
IB
1235 /* Handle NAN and +-INF. */
1236 if (strncmp (mangled, "NAN", 3) == 0)
1237 {
1238 string_append (decl, "NaN");
1239 mangled += 3;
1240 return mangled;
1241 }
1242 else if (strncmp (mangled, "INF", 3) == 0)
1243 {
1244 string_append (decl, "Inf");
1245 mangled += 3;
1246 return mangled;
1247 }
1248 else if (strncmp (mangled, "NINF", 4) == 0)
1249 {
1250 string_append (decl, "-Inf");
1251 mangled += 4;
1252 return mangled;
1253 }
1254
1255 /* Hexadecimal prefix and leading bit. */
1256 if (*mangled == 'N')
1257 {
1a122a71 1258 string_append (decl, "-");
43b1b9ed
IB
1259 mangled++;
1260 }
1261
1262 if (!ISXDIGIT (*mangled))
1263 return NULL;
1264
1a122a71
IB
1265 string_append (decl, "0x");
1266 string_appendn (decl, mangled, 1);
1267 string_append (decl, ".");
43b1b9ed
IB
1268 mangled++;
1269
1270 /* Significand. */
1271 while (ISXDIGIT (*mangled))
1272 {
1a122a71 1273 string_appendn (decl, mangled, 1);
43b1b9ed
IB
1274 mangled++;
1275 }
1276
1277 /* Exponent. */
1278 if (*mangled != 'P')
1279 return NULL;
1280
1a122a71 1281 string_append (decl, "p");
43b1b9ed
IB
1282 mangled++;
1283
1284 if (*mangled == 'N')
1285 {
1a122a71 1286 string_append (decl, "-");
43b1b9ed
IB
1287 mangled++;
1288 }
1289
1290 while (ISDIGIT (*mangled))
1291 {
1a122a71 1292 string_appendn (decl, mangled, 1);
43b1b9ed
IB
1293 mangled++;
1294 }
1295
43b1b9ed
IB
1296 return mangled;
1297}
1298
43b1b9ed
IB
1299/* Extract the string value from MANGLED and append it to DECL.
1300 Return the remaining string on success or NULL on failure. */
1301static const char *
1302dlang_parse_string (string *decl, const char *mangled)
1303{
1304 char type = *mangled;
43b1b9ed
IB
1305 long len;
1306
1307 mangled++;
dbe65f77
IB
1308 mangled = dlang_number (mangled, &len);
1309 if (mangled == NULL || *mangled != '_')
43b1b9ed
IB
1310 return NULL;
1311
1312 mangled++;
1313 string_append (decl, "\"");
1314 while (len--)
1315 {
5398cab9
IB
1316 char val;
1317 const char *endptr = dlang_hexdigit (mangled, &val);
1318
1319 if (endptr == NULL)
1320 return NULL;
1321
1322 /* Sanitize white and non-printable characters. */
1323 switch (val)
43b1b9ed 1324 {
5398cab9
IB
1325 case ' ':
1326 string_append (decl, " ");
1327 break;
1328 case '\t':
1329 string_append (decl, "\\t");
1330 break;
1331 case '\n':
1332 string_append (decl, "\\n");
1333 break;
1334 case '\r':
1335 string_append (decl, "\\r");
1336 break;
1337 case '\f':
1338 string_append (decl, "\\f");
1339 break;
1340 case '\v':
1341 string_append (decl, "\\v");
1342 break;
eb058b7d 1343
5398cab9
IB
1344 default:
1345 if (ISPRINT (val))
1346 string_appendn (decl, &val, 1);
1347 else
eb058b7d 1348 {
5398cab9
IB
1349 string_append (decl, "\\x");
1350 string_appendn (decl, mangled, 2);
eb058b7d 1351 }
43b1b9ed 1352 }
43b1b9ed 1353
5398cab9 1354 mangled = endptr;
43b1b9ed
IB
1355 }
1356 string_append (decl, "\"");
1357
1358 if (type != 'a')
1359 string_appendn (decl, &type, 1);
1360
1361 return mangled;
1362}
1363
1364/* Extract the static array value from MANGLED and append it to DECL.
1365 Return the remaining string on success or NULL on failure. */
1366static const char *
1367dlang_parse_arrayliteral (string *decl, const char *mangled)
1368{
dbe65f77 1369 long elements;
43b1b9ed 1370
dbe65f77
IB
1371 mangled = dlang_number (mangled, &elements);
1372 if (mangled == NULL)
43b1b9ed
IB
1373 return NULL;
1374
43b1b9ed
IB
1375 string_append (decl, "[");
1376 while (elements--)
1377 {
1378 mangled = dlang_value (decl, mangled, NULL, '\0');
80b1ab15
B
1379 if (mangled == NULL)
1380 return NULL;
1381
43b1b9ed
IB
1382 if (elements != 0)
1383 string_append (decl, ", ");
1384 }
1385
1386 string_append (decl, "]");
1387 return mangled;
1388}
1389
1390/* Extract the associative array value from MANGLED and append it to DECL.
1391 Return the remaining string on success or NULL on failure. */
1392static const char *
1393dlang_parse_assocarray (string *decl, const char *mangled)
1394{
dbe65f77 1395 long elements;
43b1b9ed 1396
dbe65f77
IB
1397 mangled = dlang_number (mangled, &elements);
1398 if (mangled == NULL)
43b1b9ed
IB
1399 return NULL;
1400
43b1b9ed
IB
1401 string_append (decl, "[");
1402 while (elements--)
1403 {
1404 mangled = dlang_value (decl, mangled, NULL, '\0');
6c8dbbfe
B
1405 if (mangled == NULL)
1406 return NULL;
1407
43b1b9ed
IB
1408 string_append (decl, ":");
1409 mangled = dlang_value (decl, mangled, NULL, '\0');
6c8dbbfe
B
1410 if (mangled == NULL)
1411 return NULL;
43b1b9ed
IB
1412
1413 if (elements != 0)
1414 string_append (decl, ", ");
1415 }
1416
1417 string_append (decl, "]");
1418 return mangled;
1419}
1420
1421/* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1422 Return the remaining string on success or NULL on failure. */
1423static const char *
1424dlang_parse_structlit (string *decl, const char *mangled, const char *name)
1425{
dbe65f77 1426 long args;
43b1b9ed 1427
dbe65f77
IB
1428 mangled = dlang_number (mangled, &args);
1429 if (mangled == NULL)
43b1b9ed
IB
1430 return NULL;
1431
43b1b9ed
IB
1432 if (name != NULL)
1433 string_append (decl, name);
1434
1435 string_append (decl, "(");
1436 while (args--)
1437 {
1438 mangled = dlang_value (decl, mangled, NULL, '\0');
dba20a51
B
1439 if (mangled == NULL)
1440 return NULL;
1441
43b1b9ed
IB
1442 if (args != 0)
1443 string_append (decl, ", ");
1444 }
1445
1446 string_append (decl, ")");
1447 return mangled;
1448}
1449
1450/* Extract the value from MANGLED and append it to DECL.
1451 Return the remaining string on success or NULL on failure. */
1452static const char *
1453dlang_value (string *decl, const char *mangled, const char *name, char type)
1454{
1455 if (mangled == NULL || *mangled == '\0')
76b41cad 1456 return NULL;
43b1b9ed
IB
1457
1458 switch (*mangled)
1459 {
1460 /* Null value. */
1461 case 'n':
1462 mangled++;
1463 string_append (decl, "null");
1464 break;
1465
1466 /* Integral values. */
1467 case 'N':
1468 mangled++;
1469 string_append (decl, "-");
1470 mangled = dlang_parse_integer (decl, mangled, type);
1471 break;
1472
1473 case 'i':
1474 mangled++;
43b1b9ed 1475 /* Fall through */
dd03444b
IB
1476
1477 /* There really should always be an `i' before encoded numbers, but there
1478 wasn't in early versions of D2, so this case range must remain for
1479 backwards compatibility. */
43b1b9ed
IB
1480 case '0': case '1': case '2': case '3': case '4':
1481 case '5': case '6': case '7': case '8': case '9':
1482 mangled = dlang_parse_integer (decl, mangled, type);
1483 break;
1484
1485 /* Real value. */
1486 case 'e':
1487 mangled++;
1488 mangled = dlang_parse_real (decl, mangled);
1489 break;
1490
1491 /* Complex value. */
1492 case 'c':
1493 mangled++;
1494 mangled = dlang_parse_real (decl, mangled);
1495 string_append (decl, "+");
1496 if (mangled == NULL || *mangled != 'c')
1497 return NULL;
1498 mangled++;
1499 mangled = dlang_parse_real (decl, mangled);
1500 string_append (decl, "i");
1501 break;
1502
1503 /* String values. */
1504 case 'a': /* UTF8 */
1505 case 'w': /* UTF16 */
1506 case 'd': /* UTF32 */
1507 mangled = dlang_parse_string (decl, mangled);
1508 break;
1509
1510 /* Array values. */
1511 case 'A':
1512 mangled++;
1513 if (type == 'H')
1514 mangled = dlang_parse_assocarray (decl, mangled);
1515 else
1516 mangled = dlang_parse_arrayliteral (decl, mangled);
1517 break;
1518
1519 /* Struct values. */
1520 case 'S':
1521 mangled++;
1522 mangled = dlang_parse_structlit (decl, mangled, name);
1523 break;
1524
1525 default:
1526 return NULL;
1527 }
1528
1529 return mangled;
1530}
1531
43b1b9ed
IB
1532/* Extract and demangle the symbol in MANGLED and append it to DECL.
1533 Returns the remaining signature on success or NULL on failure. */
1534static const char *
3f30a274 1535dlang_parse_mangle (string *decl, const char *mangled, struct dlang_info *info)
43b1b9ed 1536{
5a4dbf7d
IB
1537 /* A D mangled symbol is comprised of both scope and type information.
1538
1539 MangleName:
1540 _D QualifiedName Type
5a4dbf7d
IB
1541 _D QualifiedName Z
1542 ^
1543 The caller should have guaranteed that the start pointer is at the
1544 above location.
3f30a274
IB
1545 Note that type is never a function type, but only the return type of
1546 a function or the type of a variable.
5a4dbf7d
IB
1547 */
1548 mangled += 2;
1549
3f30a274 1550 mangled = dlang_parse_qualified (decl, mangled, info, 1);
5a4dbf7d
IB
1551
1552 if (mangled != NULL)
1553 {
1554 /* Artificial symbols end with 'Z' and have no type. */
1555 if (*mangled == 'Z')
1556 mangled++;
1557 else
1558 {
3f30a274
IB
1559 /* Discard the declaration or return type. */
1560 string type;
5a4dbf7d 1561
3f30a274
IB
1562 string_init (&type);
1563 mangled = dlang_type (&type, mangled, info);
1564 string_delete (&type);
5a4dbf7d
IB
1565 }
1566 }
1567
5a4dbf7d
IB
1568 return mangled;
1569}
1570
1571/* Extract and demangle the qualified symbol in MANGLED and append it to DECL.
3f30a274 1572 SUFFIX_MODIFIERS is 1 if we are printing modifiers on this after the symbol.
5a4dbf7d
IB
1573 Returns the remaining signature on success or NULL on failure. */
1574static const char *
1575dlang_parse_qualified (string *decl, const char *mangled,
3f30a274 1576 struct dlang_info *info, int suffix_modifiers)
5a4dbf7d
IB
1577{
1578 /* Qualified names are identifiers separated by their encoded length.
1579 Nested functions also encode their argument types without specifying
1580 what they return.
1581
1582 QualifiedName:
3f30a274
IB
1583 SymbolFunctionName
1584 SymbolFunctionName QualifiedName
5a4dbf7d 1585 ^
3f30a274
IB
1586
1587 SymbolFunctionName:
1588 SymbolName
1589 SymbolName TypeFunctionNoReturn
1590 SymbolName M TypeFunctionNoReturn
1591 SymbolName M TypeModifiers TypeFunctionNoReturn
1592
5a4dbf7d
IB
1593 The start pointer should be at the above location.
1594 */
43b1b9ed
IB
1595 size_t n = 0;
1596 do
1597 {
1598 if (n++)
1599 string_append (decl, ".");
1600
98bb7ee2
IB
1601 /* Skip over anonymous symbols. */
1602 while (*mangled == '0')
1603 mangled++;
1604
3f30a274 1605 mangled = dlang_identifier (decl, mangled, info);
43b1b9ed 1606
5a4dbf7d 1607 /* Consume the encoded arguments. However if this is not followed by the
3f30a274
IB
1608 next encoded length or mangle type, then this is not a continuation of
1609 a qualified name, in which case we backtrack and return the current
1610 unconsumed position of the mangled decl. */
5a4dbf7d 1611 if (mangled && (*mangled == 'M' || dlang_call_convention_p (mangled)))
43b1b9ed 1612 {
3f30a274 1613 string mods;
5a4dbf7d
IB
1614 const char *start = mangled;
1615 int saved = string_length (decl);
43b1b9ed 1616
3f30a274
IB
1617 /* Save the type modifiers for appending at the end if needed. */
1618 string_init (&mods);
1619
5a4dbf7d 1620 /* Skip over 'this' parameter and type modifiers. */
43b1b9ed 1621 if (*mangled == 'M')
7e865541 1622 {
5a4dbf7d 1623 mangled++;
3f30a274 1624 mangled = dlang_type_modifiers (&mods, mangled);
5a4dbf7d 1625 string_setlength (decl, saved);
7e865541
IB
1626 }
1627
3f30a274
IB
1628 mangled = dlang_function_type_noreturn (decl, NULL, NULL,
1629 mangled, info);
1630 if (suffix_modifiers)
1631 string_appendn (decl, mods.b, string_length (&mods));
43b1b9ed 1632
3f30a274 1633 if (mangled == NULL || *mangled == '\0')
7e865541 1634 {
5a4dbf7d 1635 /* Did not match the rule we were looking for. */
7e865541 1636 mangled = start;
5a4dbf7d 1637 string_setlength (decl, saved);
7e865541 1638 }
3f30a274
IB
1639
1640 string_delete (&mods);
43b1b9ed
IB
1641 }
1642 }
3f30a274 1643 while (mangled && dlang_symbol_name_p (mangled, info));
43b1b9ed
IB
1644
1645 return mangled;
1646}
1647
1648/* Demangle the tuple from MANGLED and append it to DECL.
1649 Return the remaining string on success or NULL on failure. */
1650static const char *
3f30a274 1651dlang_parse_tuple (string *decl, const char *mangled, struct dlang_info *info)
43b1b9ed 1652{
dbe65f77 1653 long elements;
43b1b9ed 1654
dbe65f77
IB
1655 mangled = dlang_number (mangled, &elements);
1656 if (mangled == NULL)
43b1b9ed
IB
1657 return NULL;
1658
43b1b9ed
IB
1659 string_append (decl, "Tuple!(");
1660
1661 while (elements--)
1662 {
3f30a274 1663 mangled = dlang_type (decl, mangled, info);
f181b8e7
B
1664 if (mangled == NULL)
1665 return NULL;
1666
43b1b9ed
IB
1667 if (elements != 0)
1668 string_append (decl, ", ");
1669 }
1670
1671 string_append (decl, ")");
1672 return mangled;
1673}
1674
3f30a274
IB
1675/* Demangle the template symbol parameter from MANGLED and append it to DECL.
1676 Return the remaining string on success or NULL on failure. */
1677static const char *
1678dlang_template_symbol_param (string *decl, const char *mangled,
1679 struct dlang_info *info)
1680{
1681 if (strncmp (mangled, "_D", 2) == 0
1682 && dlang_symbol_name_p (mangled + 2, info))
1683 return dlang_parse_mangle (decl, mangled, info);
1684
1685 if (*mangled == 'Q')
1686 return dlang_parse_qualified (decl, mangled, info, 0);
1687
1688 long len;
1689 const char *endptr = dlang_number (mangled, &len);
1690
1691 if (endptr == NULL || len == 0)
1692 return NULL;
1693
1694 /* In template parameter symbols generated by the frontend up to 2.076,
1695 the symbol length is encoded and the first character of the mangled
1696 name can be a digit. This causes ambiguity issues because the digits
1697 of the two numbers are adjacent. */
1698 long psize = len;
1699 const char *pend;
1700 int saved = string_length (decl);
1701
1702 /* Work backwards until a match is found. */
1703 for (pend = endptr; endptr != NULL; pend--)
1704 {
1705 mangled = pend;
1706
1707 /* Reached the beginning of the pointer to the name length,
1708 try parsing the entire symbol. */
1709 if (psize == 0)
1710 {
1711 psize = len;
1712 pend = endptr;
1713 endptr = NULL;
1714 }
1715
1716 /* Check whether template parameter is a function with a valid
1717 return type or an untyped identifier. */
1718 if (dlang_symbol_name_p (mangled, info))
1719 mangled = dlang_parse_qualified (decl, mangled, info, 0);
1720 else if (strncmp (mangled, "_D", 2) == 0
1721 && dlang_symbol_name_p (mangled + 2, info))
1722 mangled = dlang_parse_mangle (decl, mangled, info);
1723
1724 /* Check for name length mismatch. */
1725 if (mangled && (endptr == NULL || (mangled - pend) == psize))
1726 return mangled;
1727
1728 psize /= 10;
1729 string_setlength (decl, saved);
1730 }
1731
1732 /* No match on any combinations. */
1733 return NULL;
1734}
1735
43b1b9ed
IB
1736/* Demangle the argument list from MANGLED and append it to DECL.
1737 Return the remaining string on success or NULL on failure. */
1738static const char *
3f30a274 1739dlang_template_args (string *decl, const char *mangled, struct dlang_info *info)
43b1b9ed
IB
1740{
1741 size_t n = 0;
1742
1743 while (mangled && *mangled != '\0')
1744 {
1745 switch (*mangled)
1746 {
1747 case 'Z': /* End of parameter list. */
1748 mangled++;
1749 return mangled;
1750 }
1751
1752 if (n++)
1753 string_append (decl, ", ");
1754
ed4cdb85
IB
1755 /* Skip over specialised template prefix. */
1756 if (*mangled == 'H')
1757 mangled++;
1758
43b1b9ed
IB
1759 switch (*mangled)
1760 {
1761 case 'S': /* Symbol parameter. */
1762 mangled++;
3f30a274 1763 mangled = dlang_template_symbol_param (decl, mangled, info);
43b1b9ed
IB
1764 break;
1765 case 'T': /* Type parameter. */
1766 mangled++;
3f30a274 1767 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
1768 break;
1769 case 'V': /* Value parameter. */
1770 {
1771 string name;
1772 char type;
1773
1774 /* Peek at the type. */
1775 mangled++;
1776 type = *mangled;
1777
3f30a274
IB
1778 if (type == 'Q')
1779 {
1780 /* Value type is a back reference, peek at the real type. */
1781 const char *backref;
1782 if (dlang_backref (mangled, &backref, info) == NULL)
1783 return NULL;
1784
1785 type = *backref;
1786 }
1787
43b1b9ed
IB
1788 /* In the few instances where the type is actually desired in
1789 the output, it should precede the value from dlang_value. */
1790 string_init (&name);
3f30a274 1791 mangled = dlang_type (&name, mangled, info);
43b1b9ed
IB
1792 string_need (&name, 1);
1793 *(name.p) = '\0';
1794
1795 mangled = dlang_value (decl, mangled, name.b, type);
1796 string_delete (&name);
1797 break;
1798 }
3f30a274
IB
1799 case 'X': /* Externally mangled parameter. */
1800 {
1801 long len;
1802 const char *endptr;
43b1b9ed 1803
3f30a274
IB
1804 mangled++;
1805 endptr = dlang_number (mangled, &len);
1806 if (endptr == NULL || strlen (endptr) < (size_t) len)
1807 return NULL;
1808
1809 string_appendn (decl, endptr, len);
1810 mangled = endptr + len;
1811 break;
1812 }
43b1b9ed
IB
1813 default:
1814 return NULL;
1815 }
1816 }
1817
1818 return mangled;
1819}
1820
1821/* Extract and demangle the template symbol in MANGLED, expected to
3f30a274 1822 be made up of LEN characters (-1 if unknown), and append it to DECL.
43b1b9ed
IB
1823 Returns the remaining signature on success or NULL on failure. */
1824static const char *
3f30a274
IB
1825dlang_parse_template (string *decl, const char *mangled,
1826 struct dlang_info *info, long len)
43b1b9ed
IB
1827{
1828 const char *start = mangled;
3f30a274 1829 string args;
43b1b9ed
IB
1830
1831 /* Template instance names have the types and values of its parameters
1832 encoded into it.
1833
1834 TemplateInstanceName:
1835 Number __T LName TemplateArgs Z
c6f44bae 1836 Number __U LName TemplateArgs Z
43b1b9ed
IB
1837 ^
1838 The start pointer should be at the above location, and LEN should be
1839 the value of the decoded number.
1840 */
c6f44bae
IB
1841
1842 /* Template symbol. */
3f30a274 1843 if (!dlang_symbol_name_p (mangled + 3, info) || mangled[3] == '0')
43b1b9ed
IB
1844 return NULL;
1845
1846 mangled += 3;
1847
1848 /* Template identifier. */
3f30a274 1849 mangled = dlang_identifier (decl, mangled, info);
43b1b9ed
IB
1850
1851 /* Template arguments. */
3f30a274
IB
1852 string_init (&args);
1853 mangled = dlang_template_args (&args, mangled, info);
1854
43b1b9ed 1855 string_append (decl, "!(");
3f30a274 1856 string_appendn (decl, args.b, string_length (&args));
43b1b9ed
IB
1857 string_append (decl, ")");
1858
3f30a274
IB
1859 string_delete (&args);
1860
43b1b9ed 1861 /* Check for template name length mismatch. */
3f30a274 1862 if (len != TEMPLATE_LENGTH_UNKNOWN && mangled && (mangled - start) != len)
43b1b9ed
IB
1863 return NULL;
1864
1865 return mangled;
1866}
1867
3f30a274
IB
1868/* Initialize the information structure we use to pass around information. */
1869static void
1870dlang_demangle_init_info (const char *mangled, int last_backref,
1871 struct dlang_info *info)
1872{
1873 info->s = mangled;
1874 info->last_backref = last_backref;
1875}
1876
43b1b9ed
IB
1877/* Extract and demangle the symbol in MANGLED. Returns the demangled
1878 signature on success or NULL on failure. */
1879
1880char *
1881dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
1882{
1883 string decl;
1884 char *demangled = NULL;
1885
1886 if (mangled == NULL || *mangled == '\0')
1887 return NULL;
1888
1889 if (strncmp (mangled, "_D", 2) != 0)
1890 return NULL;
1891
1892 string_init (&decl);
1893
1894 if (strcmp (mangled, "_Dmain") == 0)
1895 {
1896 string_append (&decl, "D main");
1897 }
1898 else
1899 {
3f30a274
IB
1900 struct dlang_info info;
1901
1902 dlang_demangle_init_info (mangled, strlen (mangled), &info);
1903 mangled = dlang_parse_mangle (&decl, mangled, &info);
1904
1905 /* Check that the entire symbol was successfully demangled. */
1906 if (mangled == NULL || *mangled != '\0')
43b1b9ed
IB
1907 string_delete (&decl);
1908 }
1909
1910 if (string_length (&decl) > 0)
1911 {
1912 string_need (&decl, 1);
1913 *(decl.p) = '\0';
1914 demangled = decl.b;
1915 }
1916
1917 return demangled;
1918}
1919