Coverage Report

Created: 2025-06-24 06:45

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