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