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