Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6324 serge 1
/* Demangler for the D programming language
2
   Copyright 2014, 2015 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 .  */
28
 
29
/* This file exports one function; dlang_demangle.
30
 
31
   This file imports strtol for decoding mangled literals.  */
32
 
33
#ifdef HAVE_CONFIG_H
34
#include "config.h"
35
#endif
36
 
37
#include "safe-ctype.h"
38
 
39
#include 
40
#include 
41
#include 
42
 
43
#ifdef HAVE_STDLIB_H
44
#include 
45
#else
46
extern long strtol (const char *nptr, char **endptr, int base);
47
#endif
48
 
49
#include 
50
#include "libiberty.h"
51
 
52
/* A mini string-handling package */
53
 
54
typedef struct string		/* Beware: these aren't required to be */
55
{				/*  '\0' terminated.  */
56
  char *b;			/* pointer to start of string */
57
  char *p;			/* pointer after last character */
58
  char *e;			/* pointer after end of allocated space */
59
} string;
60
 
61
static void
62
string_need (string *s, int n)
63
{
64
  int tem;
65
 
66
  if (s->b == NULL)
67
    {
68
      if (n < 32)
69
	{
70
	  n = 32;
71
	}
72
      s->p = s->b = XNEWVEC (char, n);
73
      s->e = s->b + n;
74
    }
75
  else if (s->e - s->p < n)
76
    {
77
      tem = s->p - s->b;
78
      n += tem;
79
      n *= 2;
80
      s->b = XRESIZEVEC (char, s->b, n);
81
      s->p = s->b + tem;
82
      s->e = s->b + n;
83
    }
84
}
85
 
86
static void
87
string_delete (string *s)
88
{
89
  if (s->b != NULL)
90
    {
91
      XDELETEVEC (s->b);
92
      s->b = s->e = s->p = NULL;
93
    }
94
}
95
 
96
static void
97
string_init (string *s)
98
{
99
  s->b = s->p = s->e = NULL;
100
}
101
 
102
static int
103
string_length (string *s)
104
{
105
  if (s->p == s->b)
106
    {
107
      return 0;
108
    }
109
  return s->p - s->b;
110
}
111
 
112
static void
113
string_setlength (string *s, int n)
114
{
115
  if (n - string_length (s) < 0)
116
    {
117
      s->p = s->b + n;
118
    }
119
}
120
 
121
static void
122
string_append (string *p, const char *s)
123
{
124
  int n = strlen (s);
125
  string_need (p, n);
126
  memcpy (p->p, s, n);
127
  p->p += n;
128
}
129
 
130
static void
131
string_appendn (string *p, const char *s, int n)
132
{
133
  if (n != 0)
134
    {
135
      string_need (p, n);
136
      memcpy (p->p, s, n);
137
      p->p += n;
138
    }
139
}
140
 
141
static void
142
string_prependn (string *p, const char *s, int n)
143
{
144
  char *q;
145
 
146
  if (n != 0)
147
    {
148
      string_need (p, n);
149
      for (q = p->p - 1; q >= p->b; q--)
150
	{
151
	  q[n] = q[0];
152
	}
153
      memcpy (p->b, s, n);
154
      p->p += n;
155
    }
156
}
157
 
158
static void
159
string_prepend (string *p, const char *s)
160
{
161
  if (s != NULL && *s != '\0')
162
    {
163
      string_prependn (p, s, strlen (s));
164
    }
165
}
166
 
167
/* What kinds of symbol we could be parsing.  */
168
enum dlang_symbol_kinds
169
{
170
  /* Top-level symbol, needs it's type checked.  */
171
  dlang_top_level,
172
  /* Function symbol, needs it's type checked.   */
173
  dlang_function,
174
  /* Strongly typed name, such as for classes, structs and enums.  */
175
  dlang_type_name,
176
  /* Template identifier.  */
177
  dlang_template_ident,
178
  /* Template symbol parameter.  */
179
  dlang_template_param
180
};
181
 
182
/* Prototypes for forward referenced functions */
183
static const char *dlang_function_args (string *, const char *);
184
 
185
static const char *dlang_type (string *, const char *);
186
 
187
static const char *dlang_value (string *, const char *, const char *, char);
188
 
189
static const char *dlang_parse_symbol (string *, const char *,
190
				       enum dlang_symbol_kinds);
191
 
192
static const char *dlang_parse_tuple (string *, const char *);
193
 
194
static const char *dlang_parse_template (string *, const char *, long);
195
 
196
 
197
/* Demangle the calling convention from MANGLED and append it to DECL.
198
   Return the remaining string on success or NULL on failure.  */
199
static const char *
200
dlang_call_convention (string *decl, const char *mangled)
201
{
202
  if (mangled == NULL || *mangled == '\0')
203
    return NULL;
204
 
205
  switch (*mangled)
206
    {
207
    case 'F': /* (D) */
208
      mangled++;
209
      break;
210
    case 'U': /* (C) */
211
      mangled++;
212
      string_append (decl, "extern(C) ");
213
      break;
214
    case 'W': /* (Windows) */
215
      mangled++;
216
      string_append (decl, "extern(Windows) ");
217
      break;
218
    case 'V': /* (Pascal) */
219
      mangled++;
220
      string_append (decl, "extern(Pascal) ");
221
      break;
222
    case 'R': /* (C++) */
223
      mangled++;
224
      string_append (decl, "extern(C++) ");
225
      break;
226
    default:
227
      return NULL;
228
    }
229
 
230
  return mangled;
231
}
232
 
233
/* Extract the type modifiers from MANGLED and append them to DECL.
234
   Returns the remaining signature on success or NULL on failure.  */
235
static const char *
236
dlang_type_modifiers (string *decl, const char *mangled)
237
{
238
  if (mangled == NULL || *mangled == '\0')
239
    return NULL;
240
 
241
  switch (*mangled)
242
    {
243
    case 'x': /* const */
244
      mangled++;
245
      string_append (decl, " const");
246
      return mangled;
247
    case 'y': /* immutable */
248
      mangled++;
249
      string_append (decl, " immutable");
250
      return mangled;
251
    case 'O': /* shared */
252
      mangled++;
253
      string_append (decl, " shared");
254
      return dlang_type_modifiers (decl, mangled);
255
    case 'N':
256
      mangled++;
257
      if (*mangled == 'g') /* wild */
258
	{
259
	  mangled++;
260
	  string_append (decl, " inout");
261
	  return dlang_type_modifiers (decl, mangled);
262
	}
263
      else
264
	return NULL;
265
 
266
    default:
267
      return mangled;
268
    }
269
}
270
 
271
/* Demangle the D function attributes from MANGLED and append it to DECL.
272
   Return the remaining string on success or NULL on failure.  */
273
static const char *
274
dlang_attributes (string *decl, const char *mangled)
275
{
276
  if (mangled == NULL || *mangled == '\0')
277
    return NULL;
278
 
279
  while (*mangled == 'N')
280
    {
281
      mangled++;
282
      switch (*mangled)
283
	{
284
	case 'a': /* pure */
285
	  mangled++;
286
	  string_append (decl, "pure ");
287
	  continue;
288
	case 'b': /* nothrow */
289
	  mangled++;
290
	  string_append (decl, "nothrow ");
291
	  continue;
292
	case 'c': /* ref */
293
	  mangled++;
294
	  string_append (decl, "ref ");
295
	  continue;
296
	case 'd': /* @property */
297
	  mangled++;
298
	  string_append (decl, "@property ");
299
	  continue;
300
	case 'e': /* @trusted */
301
	  mangled++;
302
	  string_append (decl, "@trusted ");
303
	  continue;
304
	case 'f': /* @safe */
305
	  mangled++;
306
	  string_append (decl, "@safe ");
307
	  continue;
308
	case 'g':
309
	case 'h':
310
	case 'k':
311
	  /* inout parameter is represented as 'Ng'.
312
	     vector parameter is represented as 'Nh'.
313
	     return paramenter is represented as 'Nk'.
314
	     If we see this, then we know we're really in the
315
	     parameter list.  Rewind and break.  */
316
	  mangled--;
317
	  break;
318
	case 'i': /* @nogc */
319
	  mangled++;
320
	  string_append (decl, "@nogc ");
321
	  continue;
322
	case 'j': /* return */
323
	  mangled++;
324
	  string_append (decl, "return ");
325
	  continue;
326
 
327
	default: /* unknown attribute */
328
	  return NULL;
329
	}
330
      break;
331
    }
332
 
333
  return mangled;
334
}
335
 
336
/* Demangle the function type from MANGLED and append it to DECL.
337
   Return the remaining string on success or NULL on failure.  */
338
static const char *
339
dlang_function_type (string *decl, const char *mangled)
340
{
341
  string attr, args, type;
342
  size_t szattr, szargs, sztype;
343
 
344
  if (mangled == NULL || *mangled == '\0')
345
    return NULL;
346
 
347
  /* The order of the mangled string is:
348
	CallConvention FuncAttrs Arguments ArgClose Type
349
 
350
     The demangled string is re-ordered as:
351
	CallConvention Type Arguments FuncAttrs
352
   */
353
  string_init (&attr);
354
  string_init (&args);
355
  string_init (&type);
356
 
357
  /* Function call convention.  */
358
  mangled = dlang_call_convention (decl, mangled);
359
 
360
  /* Function attributes.  */
361
  mangled = dlang_attributes (&attr, mangled);
362
  szattr = string_length (&attr);
363
 
364
  /* Function arguments.  */
365
  mangled = dlang_function_args (&args, mangled);
366
  szargs = string_length (&args);
367
 
368
  /* Function return type.  */
369
  mangled = dlang_type (&type, mangled);
370
  sztype = string_length (&type);
371
 
372
  /* Append to decl in order. */
373
  string_appendn (decl, type.b, sztype);
374
  string_append (decl, "(");
375
  string_appendn (decl, args.b, szargs);
376
  string_append (decl, ") ");
377
  string_appendn (decl, attr.b, szattr);
378
 
379
  string_delete (&attr);
380
  string_delete (&args);
381
  string_delete (&type);
382
  return mangled;
383
}
384
 
385
/* Demangle the argument list from MANGLED and append it to DECL.
386
   Return the remaining string on success or NULL on failure.  */
387
static const char *
388
dlang_function_args (string *decl, const char *mangled)
389
{
390
  size_t n = 0;
391
 
392
  while (mangled && *mangled != '\0')
393
    {
394
      switch (*mangled)
395
	{
396
	case 'X': /* (variadic T t...) style.  */
397
	  mangled++;
398
	  string_append (decl, "...");
399
	  return mangled;
400
	case 'Y': /* (variadic T t, ...) style.  */
401
	  mangled++;
402
	  string_append (decl, ", ...");
403
	  return mangled;
404
	case 'Z': /* Normal function.  */
405
	  mangled++;
406
	  return mangled;
407
	}
408
 
409
      if (n++)
410
	string_append (decl, ", ");
411
 
412
      if (*mangled == 'M') /* scope(T) */
413
	{
414
	  mangled++;
415
	  string_append (decl, "scope ");
416
	}
417
 
418
      if (mangled[0] == 'N' && mangled[1] == 'k') /* return(T) */
419
	{
420
	  mangled += 2;
421
	  string_append (decl, "return ");
422
	}
423
 
424
      switch (*mangled)
425
	{
426
	case 'J': /* out(T) */
427
	  mangled++;
428
	  string_append (decl, "out ");
429
	  break;
430
	case 'K': /* ref(T) */
431
	  mangled++;
432
	  string_append (decl, "ref ");
433
	  break;
434
	case 'L': /* lazy(T) */
435
	  mangled++;
436
	  string_append (decl, "lazy ");
437
	  break;
438
	}
439
      mangled = dlang_type (decl, mangled);
440
    }
441
 
442
  return mangled;
443
}
444
 
445
/* Demangle the type from MANGLED and append it to DECL.
446
   Return the remaining string on success or NULL on failure.  */
447
static const char *
448
dlang_type (string *decl, const char *mangled)
449
{
450
  if (mangled == NULL || *mangled == '\0')
451
    return NULL;
452
 
453
  switch (*mangled)
454
    {
455
    case 'O': /* shared(T) */
456
      mangled++;
457
      string_append (decl, "shared(");
458
      mangled = dlang_type (decl, mangled);
459
      string_append (decl, ")");
460
      return mangled;
461
    case 'x': /* const(T) */
462
      mangled++;
463
      string_append (decl, "const(");
464
      mangled = dlang_type (decl, mangled);
465
      string_append (decl, ")");
466
      return mangled;
467
    case 'y': /* immutable(T) */
468
      mangled++;
469
      string_append (decl, "immutable(");
470
      mangled = dlang_type (decl, mangled);
471
      string_append (decl, ")");
472
      return mangled;
473
    case 'N':
474
      mangled++;
475
      if (*mangled == 'g') /* wild(T) */
476
	{
477
	  mangled++;
478
	  string_append (decl, "inout(");
479
	  mangled = dlang_type (decl, mangled);
480
	  string_append (decl, ")");
481
	  return mangled;
482
	}
483
      else if (*mangled == 'h') /* vector(T) */
484
	{
485
	  mangled++;
486
	  string_append (decl, "__vector(");
487
	  mangled = dlang_type (decl, mangled);
488
	  string_append (decl, ")");
489
	  return mangled;
490
	}
491
      else
492
	return NULL;
493
    case 'A': /* dynamic array (T[]) */
494
      mangled++;
495
      mangled = dlang_type (decl, mangled);
496
      string_append (decl, "[]");
497
      return mangled;
498
    case 'G': /* static array (T[N]) */
499
    {
500
      const char *numptr;
501
      size_t num = 0;
502
      mangled++;
503
 
504
      numptr = mangled;
505
      while (ISDIGIT (*mangled))
506
	{
507
	  num++;
508
	  mangled++;
509
	}
510
      mangled = dlang_type (decl, mangled);
511
      string_append (decl, "[");
512
      string_appendn (decl, numptr, num);
513
      string_append (decl, "]");
514
      return mangled;
515
    }
516
    case 'H': /* associative array (T[T]) */
517
    {
518
      string type;
519
      size_t sztype;
520
      mangled++;
521
 
522
      string_init (&type);
523
      mangled = dlang_type (&type, mangled);
524
      sztype = string_length (&type);
525
 
526
      mangled = dlang_type (decl, mangled);
527
      string_append (decl, "[");
528
      string_appendn (decl, type.b, sztype);
529
      string_append (decl, "]");
530
 
531
      string_delete (&type);
532
      return mangled;
533
    }
534
    case 'P': /* pointer (T*) */
535
      mangled++;
536
      mangled = dlang_type (decl, mangled);
537
      string_append (decl, "*");
538
      return mangled;
539
    case 'I': /* ident T */
540
    case 'C': /* class T */
541
    case 'S': /* struct T */
542
    case 'E': /* enum T */
543
    case 'T': /* typedef T */
544
      mangled++;
545
      return dlang_parse_symbol (decl, mangled, dlang_type_name);
546
    case 'D': /* delegate T */
547
    {
548
      string mods;
549
      size_t szmods;
550
      mangled++;
551
 
552
      string_init (&mods);
553
      mangled = dlang_type_modifiers (&mods, mangled);
554
      szmods = string_length (&mods);
555
 
556
      mangled = dlang_function_type (decl, mangled);
557
      string_append (decl, "delegate");
558
      string_appendn (decl, mods.b, szmods);
559
 
560
      string_delete (&mods);
561
      return mangled;
562
    }
563
    case 'B': /* tuple T */
564
      mangled++;
565
      return dlang_parse_tuple (decl, mangled);
566
 
567
    /* Function types */
568
    case 'F': case 'U': case 'W':
569
    case 'V': case 'R':
570
      mangled = dlang_function_type (decl, mangled);
571
      string_append (decl, "function");
572
      return mangled;
573
 
574
    /* Basic types */
575
    case 'n':
576
      mangled++;
577
      string_append (decl, "none");
578
      return mangled;
579
    case 'v':
580
      mangled++;
581
      string_append (decl, "void");
582
      return mangled;
583
    case 'g':
584
      mangled++;
585
      string_append (decl, "byte");
586
      return mangled;
587
    case 'h':
588
      mangled++;
589
      string_append (decl, "ubyte");
590
      return mangled;
591
    case 's':
592
      mangled++;
593
      string_append (decl, "short");
594
      return mangled;
595
    case 't':
596
      mangled++;
597
      string_append (decl, "ushort");
598
      return mangled;
599
    case 'i':
600
      mangled++;
601
      string_append (decl, "int");
602
      return mangled;
603
    case 'k':
604
      mangled++;
605
      string_append (decl, "uint");
606
      return mangled;
607
    case 'l':
608
      mangled++;
609
      string_append (decl, "long");
610
      return mangled;
611
    case 'm':
612
      mangled++;
613
      string_append (decl, "ulong");
614
      return mangled;
615
    case 'f':
616
      mangled++;
617
      string_append (decl, "float");
618
      return mangled;
619
    case 'd':
620
      mangled++;
621
      string_append (decl, "double");
622
      return mangled;
623
    case 'e':
624
      mangled++;
625
      string_append (decl, "real");
626
      return mangled;
627
 
628
    /* Imaginary and Complex types */
629
    case 'o':
630
      mangled++;
631
      string_append (decl, "ifloat");
632
      return mangled;
633
    case 'p':
634
      mangled++;
635
      string_append (decl, "idouble");
636
      return mangled;
637
    case 'j':
638
      mangled++;
639
      string_append (decl, "ireal");
640
      return mangled;
641
    case 'q':
642
      mangled++;
643
      string_append (decl, "cfloat");
644
      return mangled;
645
    case 'r':
646
      mangled++;
647
      string_append (decl, "cdouble");
648
      return mangled;
649
    case 'c':
650
      mangled++;
651
      string_append (decl, "creal");
652
      return mangled;
653
 
654
    /* Other types */
655
    case 'b':
656
      mangled++;
657
      string_append (decl, "bool");
658
      return mangled;
659
    case 'a':
660
      mangled++;
661
      string_append (decl, "char");
662
      return mangled;
663
    case 'u':
664
      mangled++;
665
      string_append (decl, "wchar");
666
      return mangled;
667
    case 'w':
668
      mangled++;
669
      string_append (decl, "dchar");
670
      return mangled;
671
    case 'z':
672
      mangled++;
673
      switch (*mangled)
674
	{
675
	case 'i':
676
	  mangled++;
677
	  string_append (decl, "cent");
678
	  return mangled;
679
	case 'k':
680
	  mangled++;
681
	  string_append (decl, "ucent");
682
	  return mangled;
683
	}
684
      return NULL;
685
 
686
    default: /* unhandled */
687
      return NULL;
688
    }
689
}
690
 
691
/* Extract the identifier from MANGLED and append it to DECL.
692
   Return the remaining string on success or NULL on failure.  */
693
static const char *
694
dlang_identifier (string *decl, const char *mangled,
695
		  enum dlang_symbol_kinds kind)
696
{
697
  char *endptr;
698
  long len;
699
 
700
  if (mangled == NULL || *mangled == '\0')
701
    return NULL;
702
 
703
  len = strtol (mangled, &endptr, 10);
704
 
705
  if (endptr == NULL || len <= 0)
706
    return NULL;
707
 
708
  /* In template parameter symbols, the first character of the mangled
709
     name can be a digit.  This causes ambiguity issues because the
710
     digits of the two numbers are adjacent.  */
711
  if (kind == dlang_template_param)
712
    {
713
      long psize = len;
714
      char *pend;
715
      int saved = string_length (decl);
716
 
717
      /* Work backwards until a match is found.  */
718
      for (pend = endptr; endptr != NULL; pend--)
719
	{
720
	  mangled = pend;
721
 
722
	  /* Reached the beginning of the pointer to the name length,
723
	     try parsing the entire symbol.  */
724
	  if (psize == 0)
725
	    {
726
	      psize = len;
727
	      pend = endptr;
728
	      endptr = NULL;
729
	    }
730
 
731
	  /* Check whether template parameter is a function with a valid
732
	     return type or an untyped identifier.  */
733
	  if (ISDIGIT (*mangled))
734
	    mangled = dlang_parse_symbol (decl, mangled, dlang_template_ident);
735
	  else if (strncmp (mangled, "_D", 2) == 0)
736
	    {
737
	      mangled += 2;
738
	      mangled = dlang_parse_symbol (decl, mangled, dlang_function);
739
	    }
740
 
741
	  /* Check for name length mismatch.  */
742
	  if (mangled && (mangled - pend) == psize)
743
	    return mangled;
744
 
745
	  psize /= 10;
746
	  string_setlength (decl, saved);
747
	}
748
 
749
      /* No match on any combinations.  */
750
      return NULL;
751
    }
752
  else
753
    {
754
      if (strlen (endptr) < (size_t) len)
755
	return NULL;
756
 
757
      mangled = endptr;
758
 
759
      /* May be a template instance.  */
760
      if (len >= 5 && strncmp (mangled, "__T", 3) == 0)
761
	{
762
	  /* Template symbol.  */
763
	  if (ISDIGIT (mangled[3]) && mangled[3] != '0')
764
	    return dlang_parse_template (decl, mangled, len);
765
 
766
	  return NULL;
767
	}
768
 
769
      switch (len)
770
	{
771
	case 6:
772
	  if (strncmp (mangled, "__ctor", len) == 0)
773
	    {
774
	      /* Constructor symbol for a class/struct.  */
775
	      string_append (decl, "this");
776
	      mangled += len;
777
	      return mangled;
778
	    }
779
	  else if (strncmp (mangled, "__dtor", len) == 0)
780
	    {
781
	      /* Destructor symbol for a class/struct.  */
782
	      string_append (decl, "~this");
783
	      mangled += len;
784
	      return mangled;
785
	    }
786
	  else if (strncmp (mangled, "__initZ", len+1) == 0)
787
	    {
788
	      /* The static initialiser for a given symbol.  */
789
	      string_append (decl, "init$");
790
	      mangled += len;
791
	      return mangled;
792
	    }
793
	  else if (strncmp (mangled, "__vtblZ", len+1) == 0)
794
	    {
795
	      /* The vtable symbol for a given class.  */
796
	      string_prepend (decl, "vtable for ");
797
	      string_setlength (decl, string_length (decl) - 1);
798
	      mangled += len;
799
	      return mangled;
800
	    }
801
	  break;
802
 
803
	case 7:
804
	  if (strncmp (mangled, "__ClassZ", len+1) == 0)
805
	    {
806
	      /* The classinfo symbol for a given class.  */
807
	      string_prepend (decl, "ClassInfo for ");
808
	      string_setlength (decl, string_length (decl) - 1);
809
	      mangled += len;
810
	      return mangled;
811
	    }
812
	  break;
813
 
814
	case 10:
815
	  if (strncmp (mangled, "__postblitMFZ", len+3) == 0)
816
	    {
817
	      /* Postblit symbol for a struct.  */
818
	      string_append (decl, "this(this)");
819
	      mangled += len + 3;
820
	      return mangled;
821
	    }
822
	  break;
823
 
824
	case 11:
825
	  if (strncmp (mangled, "__InterfaceZ", len+1) == 0)
826
	    {
827
	      /* The interface symbol for a given class.  */
828
	      string_prepend (decl, "Interface for ");
829
	      string_setlength (decl, string_length (decl) - 1);
830
	      mangled += len;
831
	      return mangled;
832
	    }
833
	  break;
834
 
835
	case 12:
836
	  if (strncmp (mangled, "__ModuleInfoZ", len+1) == 0)
837
	    {
838
	      /* The ModuleInfo symbol for a given module.  */
839
	      string_prepend (decl, "ModuleInfo for ");
840
	      string_setlength (decl, string_length (decl) - 1);
841
	      mangled += len;
842
	      return mangled;
843
	    }
844
	  break;
845
	}
846
 
847
      string_appendn (decl, mangled, len);
848
      mangled += len;
849
    }
850
 
851
  return mangled;
852
}
853
 
854
/* Extract the integer value from MANGLED and append it to DECL,
855
   where TYPE is the type it should be represented as.
856
   Return the remaining string on success or NULL on failure.  */
857
static const char *
858
dlang_parse_integer (string *decl, const char *mangled, char type)
859
{
860
  if (type == 'a' || type == 'u' || type == 'w')
861
    {
862
      /* Parse character value.  */
863
      char value[10];
864
      int pos = 10;
865
      int width = 0;
866
      char *endptr;
867
      long val = strtol (mangled, &endptr, 10);
868
 
869
      if (endptr == NULL || val < 0)
870
	return NULL;
871
 
872
      string_append (decl, "'");
873
 
874
      if (type == 'a' && val >= 0x20 && val < 0x7F)
875
	{
876
	  /* Represent as a character literal.  */
877
	  char c = (char) val;
878
	  string_appendn (decl, &c, 1);
879
	}
880
      else
881
	{
882
	  /* Represent as a hexadecimal value.  */
883
	  switch (type)
884
	    {
885
	    case 'a': /* char */
886
	      string_append (decl, "\\x");
887
	      width = 2;
888
	      break;
889
	    case 'u': /* wchar */
890
	      string_append (decl, "\\u");
891
	      width = 4;
892
	      break;
893
	    case 'w': /* dchar */
894
	      string_append (decl, "\\U");
895
	      width = 8;
896
	      break;
897
	    }
898
 
899
	  while (val > 0)
900
	    {
901
	      int digit = val % 16;
902
 
903
	      if (digit < 10)
904
		value[--pos] = (char)(digit + '0');
905
	      else
906
		value[--pos] = (char)((digit - 10) + 'a');
907
 
908
	      val /= 16;
909
	      width--;
910
	    }
911
 
912
	  for (; width > 0; width--)
913
	    value[--pos] = '0';
914
 
915
	  string_appendn (decl, &(value[pos]), 10 - pos);
916
	}
917
      string_append (decl, "'");
918
      mangled = endptr;
919
    }
920
  else if (type == 'b')
921
    {
922
      /* Parse boolean value.  */
923
      char *endptr;
924
      long val = strtol (mangled, &endptr, 10);
925
 
926
      if (endptr == NULL || val < 0)
927
	return NULL;
928
 
929
      string_append (decl, val ? "true" : "false");
930
      mangled = endptr;
931
    }
932
  else
933
    {
934
      /* Parse integer value.  */
935
      const char *numptr = mangled;
936
      size_t num = 0;
937
 
938
      while (ISDIGIT (*mangled))
939
	{
940
	  num++;
941
	  mangled++;
942
	}
943
      string_appendn (decl, numptr, num);
944
 
945
      /* Append suffix.  */
946
      switch (type)
947
	{
948
	case 'h': /* ubyte */
949
	case 't': /* ushort */
950
	case 'k': /* uint */
951
	  string_append (decl, "u");
952
	  break;
953
	case 'l': /* long */
954
	  string_append (decl, "L");
955
	  break;
956
	case 'm': /* ulong */
957
	  string_append (decl, "uL");
958
	  break;
959
	}
960
    }
961
 
962
  return mangled;
963
}
964
 
965
/* Extract the floating-point value from MANGLED and append it to DECL.
966
   Return the remaining string on success or NULL on failure.  */
967
static const char *
968
dlang_parse_real (string *decl, const char *mangled)
969
{
970
  char buffer[64];
971
  int len = 0;
972
 
973
  /* Handle NAN and +-INF.  */
974
  if (strncmp (mangled, "NAN", 3) == 0)
975
    {
976
      string_append (decl, "NaN");
977
      mangled += 3;
978
      return mangled;
979
    }
980
  else if (strncmp (mangled, "INF", 3) == 0)
981
    {
982
      string_append (decl, "Inf");
983
      mangled += 3;
984
      return mangled;
985
    }
986
  else if (strncmp (mangled, "NINF", 4) == 0)
987
    {
988
      string_append (decl, "-Inf");
989
      mangled += 4;
990
      return mangled;
991
    }
992
 
993
  /* Hexadecimal prefix and leading bit.  */
994
  if (*mangled == 'N')
995
    {
996
      buffer[len++] = '-';
997
      mangled++;
998
    }
999
 
1000
  if (!ISXDIGIT (*mangled))
1001
    return NULL;
1002
 
1003
  buffer[len++] = '0';
1004
  buffer[len++] = 'x';
1005
  buffer[len++] = *mangled;
1006
  buffer[len++] = '.';
1007
  mangled++;
1008
 
1009
  /* Significand.  */
1010
  while (ISXDIGIT (*mangled))
1011
    {
1012
      buffer[len++] = *mangled;
1013
      mangled++;
1014
    }
1015
 
1016
  /* Exponent.  */
1017
  if (*mangled != 'P')
1018
    return NULL;
1019
 
1020
  buffer[len++] = 'p';
1021
  mangled++;
1022
 
1023
  if (*mangled == 'N')
1024
    {
1025
      buffer[len++] = '-';
1026
      mangled++;
1027
    }
1028
 
1029
  while (ISDIGIT (*mangled))
1030
    {
1031
      buffer[len++] = *mangled;
1032
      mangled++;
1033
    }
1034
 
1035
  /* Write out the demangled hexadecimal, rather than trying to
1036
     convert the buffer into a floating-point value.  */
1037
  buffer[len] = '\0';
1038
  len = strlen (buffer);
1039
  string_appendn (decl, buffer, len);
1040
  return mangled;
1041
}
1042
 
1043
/* Convert VAL from an ascii hexdigit to value.  */
1044
static char
1045
ascii2hex (char val)
1046
{
1047
  if (val >= 'a' && val <= 'f')
1048
    return (val - 'a' + 10);
1049
 
1050
  if (val >= 'A' && val <= 'F')
1051
    return (val - 'A' + 10);
1052
 
1053
  if (val >= '0' && val <= '9')
1054
    return (val - '0');
1055
 
1056
  return 0;
1057
}
1058
 
1059
/* Extract the string value from MANGLED and append it to DECL.
1060
   Return the remaining string on success or NULL on failure.  */
1061
static const char *
1062
dlang_parse_string (string *decl, const char *mangled)
1063
{
1064
  char type = *mangled;
1065
  char *endptr;
1066
  long len;
1067
 
1068
  mangled++;
1069
  len = strtol (mangled, &endptr, 10);
1070
 
1071
  if (endptr == NULL || len < 0)
1072
    return NULL;
1073
 
1074
  mangled = endptr;
1075
  if (*mangled != '_')
1076
    return NULL;
1077
 
1078
  mangled++;
1079
  string_append (decl, "\"");
1080
  while (len--)
1081
    {
1082
      if (ISXDIGIT (mangled[0]) && ISXDIGIT (mangled[1]))
1083
	{
1084
	  char a = ascii2hex (mangled[0]);
1085
	  char b = ascii2hex (mangled[1]);
1086
	  char val = (a << 4) | b;
1087
 
1088
	  /* Sanitize white and non-printable characters.  */
1089
	  switch (val)
1090
	    {
1091
	    case ' ':
1092
	      string_append (decl, " ");
1093
	      break;
1094
	    case '\t':
1095
	      string_append (decl, "\\t");
1096
	      break;
1097
	    case '\n':
1098
	      string_append (decl, "\\n");
1099
	      break;
1100
	    case '\r':
1101
	      string_append (decl, "\\r");
1102
	      break;
1103
	    case '\f':
1104
	      string_append (decl, "\\f");
1105
	      break;
1106
	    case '\v':
1107
	      string_append (decl, "\\v");
1108
	      break;
1109
 
1110
	    default:
1111
	      if (ISPRINT (val))
1112
		string_appendn (decl, &val, 1);
1113
	      else
1114
		{
1115
		  string_append (decl, "\\x");
1116
		  string_appendn (decl, mangled, 2);
1117
		}
1118
	    }
1119
	}
1120
      else
1121
	return NULL;
1122
 
1123
      mangled += 2;
1124
    }
1125
  string_append (decl, "\"");
1126
 
1127
  if (type != 'a')
1128
    string_appendn (decl, &type, 1);
1129
 
1130
  return mangled;
1131
}
1132
 
1133
/* Extract the static array value from MANGLED and append it to DECL.
1134
   Return the remaining string on success or NULL on failure.  */
1135
static const char *
1136
dlang_parse_arrayliteral (string *decl, const char *mangled)
1137
{
1138
  char *endptr;
1139
  long elements = strtol (mangled, &endptr, 10);
1140
 
1141
  if (endptr == NULL || elements < 0)
1142
    return NULL;
1143
 
1144
  mangled = endptr;
1145
  string_append (decl, "[");
1146
  while (elements--)
1147
    {
1148
      mangled = dlang_value (decl, mangled, NULL, '\0');
1149
      if (elements != 0)
1150
	string_append (decl, ", ");
1151
    }
1152
 
1153
  string_append (decl, "]");
1154
  return mangled;
1155
}
1156
 
1157
/* Extract the associative array value from MANGLED and append it to DECL.
1158
   Return the remaining string on success or NULL on failure.  */
1159
static const char *
1160
dlang_parse_assocarray (string *decl, const char *mangled)
1161
{
1162
  char *endptr;
1163
  long elements = strtol (mangled, &endptr, 10);
1164
 
1165
  if (endptr == NULL || elements < 0)
1166
    return NULL;
1167
 
1168
  mangled = endptr;
1169
  string_append (decl, "[");
1170
  while (elements--)
1171
    {
1172
      mangled = dlang_value (decl, mangled, NULL, '\0');
1173
      string_append (decl, ":");
1174
      mangled = dlang_value (decl, mangled, NULL, '\0');
1175
 
1176
      if (elements != 0)
1177
	string_append (decl, ", ");
1178
    }
1179
 
1180
  string_append (decl, "]");
1181
  return mangled;
1182
}
1183
 
1184
/* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1185
   Return the remaining string on success or NULL on failure.  */
1186
static const char *
1187
dlang_parse_structlit (string *decl, const char *mangled, const char *name)
1188
{
1189
  char *endptr;
1190
  long args = strtol (mangled, &endptr, 10);
1191
 
1192
  if (endptr == NULL || args < 0)
1193
    return NULL;
1194
 
1195
  mangled = endptr;
1196
  if (name != NULL)
1197
    string_append (decl, name);
1198
 
1199
  string_append (decl, "(");
1200
  while (args--)
1201
    {
1202
      mangled = dlang_value (decl, mangled, NULL, '\0');
1203
      if (args != 0)
1204
	string_append (decl, ", ");
1205
    }
1206
 
1207
  string_append (decl, ")");
1208
  return mangled;
1209
}
1210
 
1211
/* Extract the value from MANGLED and append it to DECL.
1212
   Return the remaining string on success or NULL on failure.  */
1213
static const char *
1214
dlang_value (string *decl, const char *mangled, const char *name, char type)
1215
{
1216
  if (mangled == NULL || *mangled == '\0')
1217
    return NULL;
1218
 
1219
  switch (*mangled)
1220
    {
1221
      /* Null value.  */
1222
    case 'n':
1223
      mangled++;
1224
      string_append (decl, "null");
1225
      break;
1226
 
1227
      /* Integral values.  */
1228
    case 'N':
1229
      mangled++;
1230
      string_append (decl, "-");
1231
      mangled = dlang_parse_integer (decl, mangled, type);
1232
      break;
1233
 
1234
    case 'i':
1235
      mangled++;
1236
      if (*mangled < '0' || *mangled > '9')
1237
	return NULL;
1238
      /* Fall through */
1239
    case '0': case '1': case '2': case '3': case '4':
1240
    case '5': case '6': case '7': case '8': case '9':
1241
      mangled = dlang_parse_integer (decl, mangled, type);
1242
      break;
1243
 
1244
      /* Real value.  */
1245
    case 'e':
1246
      mangled++;
1247
      mangled = dlang_parse_real (decl, mangled);
1248
      break;
1249
 
1250
      /* Complex value.  */
1251
    case 'c':
1252
      mangled++;
1253
      mangled = dlang_parse_real (decl, mangled);
1254
      string_append (decl, "+");
1255
      if (mangled == NULL || *mangled != 'c')
1256
	return NULL;
1257
      mangled++;
1258
      mangled = dlang_parse_real (decl, mangled);
1259
      string_append (decl, "i");
1260
      break;
1261
 
1262
      /* String values.  */
1263
    case 'a': /* UTF8 */
1264
    case 'w': /* UTF16 */
1265
    case 'd': /* UTF32 */
1266
      mangled = dlang_parse_string (decl, mangled);
1267
      break;
1268
 
1269
      /* Array values.  */
1270
    case 'A':
1271
      mangled++;
1272
      if (type == 'H')
1273
	mangled = dlang_parse_assocarray (decl, mangled);
1274
      else
1275
	mangled = dlang_parse_arrayliteral (decl, mangled);
1276
      break;
1277
 
1278
      /* Struct values.  */
1279
    case 'S':
1280
      mangled++;
1281
      mangled = dlang_parse_structlit (decl, mangled, name);
1282
      break;
1283
 
1284
    default:
1285
      return NULL;
1286
    }
1287
 
1288
  return mangled;
1289
}
1290
 
1291
/* Extract the type modifiers from MANGLED and return the string
1292
   length that it consumes in MANGLED on success or 0 on failure.  */
1293
static int
1294
dlang_type_modifier_p (const char *mangled)
1295
{
1296
  int i;
1297
 
1298
  switch (*mangled)
1299
    {
1300
    case 'x': case 'y':
1301
      return 1;
1302
 
1303
    case 'O':
1304
      mangled++;
1305
      i = dlang_type_modifier_p (mangled);
1306
      return i + 1;
1307
 
1308
    case 'N':
1309
      mangled++;
1310
      if (*mangled == 'g')
1311
	{
1312
	  mangled++;
1313
	  i = dlang_type_modifier_p (mangled);
1314
	  return i + 2;
1315
	}
1316
    }
1317
 
1318
  return 0;
1319
}
1320
 
1321
/* Extract the function calling convention from MANGLED and
1322
   return 1 on success or 0 on failure.  */
1323
static int
1324
dlang_call_convention_p (const char *mangled)
1325
{
1326
  /* Prefix for functions needing 'this' */
1327
  if (*mangled == 'M')
1328
    {
1329
      mangled++;
1330
      /* Also skip over any type modifiers.  */
1331
      mangled += dlang_type_modifier_p (mangled);
1332
    }
1333
 
1334
  switch (*mangled)
1335
    {
1336
    case 'F': case 'U': case 'V':
1337
    case 'W': case 'R':
1338
      return 1;
1339
 
1340
    default:
1341
      return 0;
1342
    }
1343
}
1344
 
1345
/* Extract and demangle the symbol in MANGLED and append it to DECL.
1346
   Returns the remaining signature on success or NULL on failure.  */
1347
static const char *
1348
dlang_parse_symbol (string *decl, const char *mangled,
1349
		    enum dlang_symbol_kinds kind)
1350
{
1351
  int saved;
1352
  size_t n = 0;
1353
  do
1354
    {
1355
      if (n++)
1356
	string_append (decl, ".");
1357
 
1358
      mangled = dlang_identifier (decl, mangled, kind);
1359
 
1360
      if (mangled && dlang_call_convention_p (mangled))
1361
	{
1362
	  string mods;
1363
	  const char *start = NULL;
1364
	  int checkpoint = 0;
1365
 
1366
	  /* Skip over 'this' parameter.  */
1367
	  if (*mangled == 'M')
1368
	    mangled++;
1369
 
1370
	  /* We have reached here because we expect an extern(Pascal) function.
1371
	     However this is so rare, that it is more likely a template value
1372
	     parameter.  Since this can't be assumed, first attempt parsing
1373
	     the symbol as a function, and then back out on failure.  */
1374
	  if (*mangled == 'V')
1375
	    {
1376
	      start = mangled;
1377
	      checkpoint = string_length (decl);
1378
	    }
1379
 
1380
	  /* Save the type modifiers for appending at the end.  */
1381
	  string_init (&mods);
1382
	  mangled = dlang_type_modifiers (&mods, mangled);
1383
 
1384
	  /* Skip over calling convention and attributes in qualified name.  */
1385
	  saved = string_length (decl);
1386
	  mangled = dlang_call_convention (decl, mangled);
1387
	  mangled = dlang_attributes (decl, mangled);
1388
	  string_setlength (decl, saved);
1389
 
1390
	  string_append (decl, "(");
1391
	  mangled = dlang_function_args (decl, mangled);
1392
	  string_append (decl, ")");
1393
 
1394
	  /* Add any const/immutable/shared modifier. */
1395
	  string_appendn (decl, mods.b, string_length (&mods));
1396
	  string_delete (&mods);
1397
 
1398
	  if (mangled == NULL && checkpoint != 0)
1399
	    {
1400
	      mangled = start;
1401
	      string_setlength (decl, checkpoint);
1402
	    }
1403
	}
1404
    }
1405
  while (mangled && ISDIGIT (*mangled));
1406
 
1407
  /* Only top-level symbols or function template parameters have
1408
     a type that needs checking.  */
1409
  if (kind == dlang_top_level || kind == dlang_function)
1410
    {
1411
      /* Artificial symbols end with 'Z' and have no type.  */
1412
      if (mangled && *mangled == 'Z')
1413
	mangled++;
1414
      else
1415
	{
1416
	  saved = string_length (decl);
1417
	  mangled = dlang_type (decl, mangled);
1418
	  string_setlength (decl, saved);
1419
	}
1420
 
1421
      /* Check that the entire symbol was successfully demangled.  */
1422
      if (kind == dlang_top_level)
1423
	{
1424
	  if (mangled == NULL || *mangled != '\0')
1425
	    return NULL;
1426
	}
1427
    }
1428
 
1429
  return mangled;
1430
}
1431
 
1432
/* Demangle the tuple from MANGLED and append it to DECL.
1433
   Return the remaining string on success or NULL on failure.  */
1434
static const char *
1435
dlang_parse_tuple (string *decl, const char *mangled)
1436
{
1437
  char *endptr;
1438
  long elements = strtol (mangled, &endptr, 10);
1439
 
1440
  if (endptr == NULL || elements < 0)
1441
    return NULL;
1442
 
1443
  mangled = endptr;
1444
  string_append (decl, "Tuple!(");
1445
 
1446
  while (elements--)
1447
    {
1448
      mangled = dlang_type (decl, mangled);
1449
      if (elements != 0)
1450
	string_append (decl, ", ");
1451
    }
1452
 
1453
  string_append (decl, ")");
1454
  return mangled;
1455
}
1456
 
1457
/* Demangle the argument list from MANGLED and append it to DECL.
1458
   Return the remaining string on success or NULL on failure.  */
1459
static const char *
1460
dlang_template_args (string *decl, const char *mangled)
1461
{
1462
  size_t n = 0;
1463
 
1464
  while (mangled && *mangled != '\0')
1465
    {
1466
      switch (*mangled)
1467
	{
1468
	case 'Z': /* End of parameter list.  */
1469
	  mangled++;
1470
	  return mangled;
1471
	}
1472
 
1473
      if (n++)
1474
	string_append (decl, ", ");
1475
 
1476
      /* Skip over specialised template prefix.  */
1477
      if (*mangled == 'H')
1478
	mangled++;
1479
 
1480
      switch (*mangled)
1481
	{
1482
	case 'S': /* Symbol parameter.  */
1483
	  mangled++;
1484
	  mangled = dlang_parse_symbol (decl, mangled, dlang_template_param);
1485
	  break;
1486
	case 'T': /* Type parameter.  */
1487
	  mangled++;
1488
	  mangled = dlang_type (decl, mangled);
1489
	  break;
1490
	case 'V': /* Value parameter.  */
1491
	{
1492
	  string name;
1493
	  char type;
1494
 
1495
	  /* Peek at the type.  */
1496
	  mangled++;
1497
	  type = *mangled;
1498
 
1499
	  /* In the few instances where the type is actually desired in
1500
	     the output, it should precede the value from dlang_value.  */
1501
	  string_init (&name);
1502
	  mangled = dlang_type (&name, mangled);
1503
	  string_need (&name, 1);
1504
	  *(name.p) = '\0';
1505
 
1506
	  mangled = dlang_value (decl, mangled, name.b, type);
1507
	  string_delete (&name);
1508
	  break;
1509
	}
1510
 
1511
	default:
1512
	  return NULL;
1513
	}
1514
    }
1515
 
1516
  return mangled;
1517
}
1518
 
1519
/* Extract and demangle the template symbol in MANGLED, expected to
1520
   be made up of LEN characters, and append it to DECL.
1521
   Returns the remaining signature on success or NULL on failure.  */
1522
static const char *
1523
dlang_parse_template (string *decl, const char *mangled, long len)
1524
{
1525
  const char *start = mangled;
1526
 
1527
  /* Template instance names have the types and values of its parameters
1528
     encoded into it.
1529
 
1530
	TemplateInstanceName:
1531
	    Number __T LName TemplateArgs Z
1532
		   ^
1533
     The start pointer should be at the above location, and LEN should be
1534
     the value of the decoded number.
1535
   */
1536
  if (strncmp (mangled, "__T", 3) != 0)
1537
    return NULL;
1538
 
1539
  mangled += 3;
1540
 
1541
  /* Template identifier.  */
1542
  mangled = dlang_identifier (decl, mangled, dlang_template_ident);
1543
 
1544
  /* Template arguments.  */
1545
  string_append (decl, "!(");
1546
  mangled = dlang_template_args (decl, mangled);
1547
  string_append (decl, ")");
1548
 
1549
  /* Check for template name length mismatch.  */
1550
  if (mangled && (mangled - start) != len)
1551
    return NULL;
1552
 
1553
  return mangled;
1554
}
1555
 
1556
/* Extract and demangle the symbol in MANGLED.  Returns the demangled
1557
   signature on success or NULL on failure.  */
1558
 
1559
char *
1560
dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
1561
{
1562
  string decl;
1563
  char *demangled = NULL;
1564
 
1565
  if (mangled == NULL || *mangled == '\0')
1566
    return NULL;
1567
 
1568
  if (strncmp (mangled, "_D", 2) != 0)
1569
    return NULL;
1570
 
1571
  string_init (&decl);
1572
 
1573
  if (strcmp (mangled, "_Dmain") == 0)
1574
    {
1575
      string_append (&decl, "D main");
1576
    }
1577
  else
1578
    {
1579
      mangled += 2;
1580
 
1581
      if (dlang_parse_symbol (&decl, mangled, dlang_top_level) == NULL)
1582
	string_delete (&decl);
1583
    }
1584
 
1585
  if (string_length (&decl) > 0)
1586
    {
1587
      string_need (&decl, 1);
1588
      *(decl.p) = '\0';
1589
      demangled = decl.b;
1590
    }
1591
 
1592
  return demangled;
1593
}
1594