Coverage Report

Created: 2026-07-25 10:20

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