implement support for "enum class"
[platform/upstream/binutils.git] / gdb / d-support.c
1 /* Helper routines for D support in GDB.
2
3    Copyright (C) 2014 Free Software Foundation, Inc.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20 #include "defs.h"
21 #include "d-lang.h"
22 #include "gdb_obstack.h"
23
24 #include "safe-ctype.h"
25
26 static const char *parse_function_args (struct obstack *, const char *);
27 static const char *parse_type (struct obstack *, const char *);
28
29
30 /* Demangle the calling convention from MANGLE and append it to TEMPBUF.
31    Return the remaining string on success or NULL on failure.  */
32
33 static const char *
34 parse_call_convention (struct obstack *tempbuf, const char *mangle)
35 {
36   if ((mangle == NULL) || (*mangle == '\0'))
37     return mangle;
38
39   switch (*mangle)
40     {
41     case 'F': /* (D) */
42       mangle++;
43       break;
44     case 'U': /* (C) */
45       mangle++;
46       obstack_grow_str (tempbuf, "extern(C) ");
47       break;
48     case 'W': /* (Windows) */
49       mangle++;
50       obstack_grow_str (tempbuf, "extern(Windows) ");
51       break;
52     case 'V': /* (Pascal) */
53       mangle++;
54       obstack_grow_str (tempbuf, "extern(Pascal) ");
55       break;
56     case 'R': /* (C++) */
57       mangle++;
58       obstack_grow_str (tempbuf, "extern(C++) ");
59       break;
60     default:
61       return NULL;
62     }
63
64   return mangle;
65 }
66
67 /* Demangle the D function attributes from MANGLE and append it to TEMPBUF.
68    Return the remaining string on success or NULL on failure.  */
69
70 static const char *
71 parse_attributes (struct obstack *tempbuf, const char *mangle)
72 {
73   if ((mangle == NULL) || (*mangle == '\0'))
74     return mangle;
75
76   while (*mangle == 'N')
77     {
78       mangle++;
79       switch (*mangle)
80         {
81         case 'a': /* pure */
82           mangle++;
83           obstack_grow_str (tempbuf, "pure ");
84           continue;
85         case 'b': /* nothrow */
86           mangle++;
87           obstack_grow_str (tempbuf, "nothrow ");
88           continue;
89         case 'c': /* ref */
90           mangle++;
91           obstack_grow_str (tempbuf, "ref ");
92           continue;
93         case 'd': /* @property */
94           mangle++;
95           obstack_grow_str (tempbuf, "@property ");
96           continue;
97         case 'e': /* @trusted */
98           mangle++;
99           obstack_grow_str (tempbuf, "@trusted ");
100           continue;
101         case 'f': /* @safe */
102           mangle++;
103           obstack_grow_str (tempbuf, "@safe ");
104           continue;
105         case 'g':
106         case 'h':
107           /* inout parameter is represented as 'Ng'.
108              vector parameter is represented as 'Nh'.
109              If we see this, then we know we're really in the
110              parameter list.  Rewind and break.  */
111           mangle--;
112         }
113       break;
114     }
115   return mangle;
116 }
117
118 /* Demangle the function type from MANGLE and append it to TEMPBUF.
119    Return the remaining string on success or NULL on failure.  */
120
121 static const char *
122 parse_function_type (struct obstack *tempbuf, const char *mangle)
123 {
124   struct obstack obattr, obargs, obtype;
125   char *attr, *args, *type;
126   size_t szattr, szargs, sztype;
127
128   if ((mangle == NULL) || (*mangle == '\0'))
129     return mangle;
130
131   /* The order of the mangled string is:
132      TypeFunction ::
133         CallConvention FuncAttrs Arguments ArgClose Type
134
135      The demangled string is re-ordered as:
136         CallConvention Type Arguments FuncAttrs
137    */
138   obstack_init (&obattr);
139   obstack_init (&obargs);
140   obstack_init (&obtype);
141
142   /* Function call convention.  */
143   mangle = parse_call_convention (tempbuf, mangle);
144
145   /* Function attributes.  */
146   mangle = parse_attributes (&obattr, mangle);
147   szattr = obstack_object_size (&obattr);
148   attr = obstack_finish (&obattr);
149
150   /* Function arguments.  */
151   mangle = parse_function_args (&obargs, mangle);
152   szargs = obstack_object_size (&obargs);
153   args = obstack_finish (&obargs);
154
155   /* Function return type.  */
156   mangle = parse_type (&obtype, mangle);
157   sztype = obstack_object_size (&obtype);
158   type = obstack_finish (&obtype);
159
160   /* Append to buffer in order. */
161   obstack_grow (tempbuf, type, sztype);
162   obstack_grow_str (tempbuf, "(");
163   obstack_grow (tempbuf, args, szargs);
164   obstack_grow_str (tempbuf, ") ");
165   obstack_grow (tempbuf, attr, szattr);
166
167   obstack_free (&obattr, NULL);
168   obstack_free (&obargs, NULL);
169   obstack_free (&obtype, NULL);
170   return mangle;
171 }
172
173 /* Demangle the argument list from MANGLE and append it to TEMPBUF.
174    Return the remaining string on success or NULL on failure.  */
175
176 static const char *
177 parse_function_args (struct obstack *tempbuf, const char *mangle)
178 {
179   size_t n = 0;
180
181   while ((mangle != NULL) && (*mangle != '\0'))
182     {
183       switch (*mangle)
184         {
185         case 'X': /* (variadic T t...) style.  */
186           mangle++;
187           obstack_grow_str (tempbuf, "...");
188           return mangle;
189         case 'Y': /* (variadic T t, ...) style.  */
190           mangle++;
191           obstack_grow_str (tempbuf, ", ...");
192           return mangle;
193         case 'Z': /* Normal function.  */
194           mangle++;
195           return mangle;
196         }
197
198       if (n++)
199         obstack_grow_str (tempbuf, ", ");
200
201       if (*mangle == 'M') /* scope(T) */
202         {
203           mangle++;
204           obstack_grow_str (tempbuf, "scope ");
205         }
206
207       switch (*mangle)
208         {
209         case 'J': /* out(T) */
210           mangle++;
211           obstack_grow_str (tempbuf, "out ");
212           break;
213         case 'K': /* ref(T) */
214           mangle++;
215           obstack_grow_str (tempbuf, "ref ");
216           break;
217         case 'L': /* lazy(T) */
218           mangle++;
219           obstack_grow_str (tempbuf, "lazy ");
220           break;
221         }
222       mangle = parse_type (tempbuf, mangle);
223     }
224   return mangle;
225 }
226
227 /* Demangle the type from MANGLE and append it to TEMPBUF.
228    Return the remaining string on success or NULL on failure.  */
229
230 static const char *
231 parse_type (struct obstack *tempbuf, const char *mangle)
232 {
233   if ((mangle == NULL) || (*mangle == '\0'))
234     return mangle;
235
236   switch (*mangle)
237     {
238     case 'O': /* shared(T) */
239       mangle++;
240       obstack_grow_str (tempbuf, "shared(");
241       mangle = parse_type (tempbuf, mangle);
242       obstack_grow_str (tempbuf, ")");
243       return mangle;
244     case 'x': /* const(T) */
245       mangle++;
246       obstack_grow_str (tempbuf, "const(");
247       mangle = parse_type (tempbuf, mangle);
248       obstack_grow_str (tempbuf, ")");
249       return mangle;
250     case 'y': /* immutable(T) */
251       mangle++;
252       obstack_grow_str (tempbuf, "immutable(");
253       mangle = parse_type (tempbuf, mangle);
254       obstack_grow_str (tempbuf, ")");
255       return mangle;
256     case 'N':
257       mangle++;
258       if (*mangle == 'g') /* wild(T) */
259         {
260           mangle++;
261           obstack_grow_str (tempbuf, "inout(");
262           mangle = parse_type (tempbuf, mangle);
263           obstack_grow_str (tempbuf, ")");
264           return mangle;
265         }
266       else if (*mangle == 'h') /* vector(T) */
267         {
268           mangle++;
269           /* The basetype for vectors are always static arrays.  */
270           if (*mangle != 'G')
271             return NULL;
272           obstack_grow_str (tempbuf, "__vector(");
273           mangle = parse_type (tempbuf, mangle);
274           obstack_grow_str (tempbuf, ")");
275           return mangle;
276         }
277       else
278         return NULL;
279     case 'A': /* dynamic array (T[]) */
280       mangle++;
281       mangle = parse_type (tempbuf, mangle);
282       obstack_grow_str (tempbuf, "[]");
283       return mangle;
284     case 'G': /* static array (T[N]) */
285     {
286       const char *numptr;
287       size_t num = 0;
288       mangle++;
289
290       numptr = mangle;
291       while (ISDIGIT (*mangle))
292         {
293           num++;
294           mangle++;
295         }
296       mangle = parse_type (tempbuf, mangle);
297       obstack_grow_str (tempbuf, "[");
298       obstack_grow (tempbuf, numptr, num);
299       obstack_grow_str (tempbuf, "]");
300       return mangle;
301     }
302     case 'H': /* associative array (T[T]) */
303     {
304       struct obstack obtype;
305       char *type;
306       size_t sztype;
307       mangle++;
308
309       obstack_init (&obtype);
310       mangle = parse_type (&obtype, mangle);
311       sztype = obstack_object_size (&obtype);
312       type = obstack_finish (&obtype);
313
314       mangle = parse_type (tempbuf, mangle);
315       obstack_grow_str (tempbuf, "[");
316       obstack_grow (tempbuf, type, sztype);
317       obstack_grow_str (tempbuf, "]");
318
319       obstack_free (&obtype, NULL);
320       return mangle;
321     }
322     case 'P': /* pointer (T*) */
323       mangle++;
324       mangle = parse_type (tempbuf, mangle);
325       obstack_grow_str (tempbuf, "*");
326       return mangle;
327     case 'I': /* ident T */
328     case 'C': /* class T */
329     case 'S': /* struct T */
330     case 'E': /* enum T */
331     case 'T': /* typedef T */
332       mangle++;
333       return d_parse_symbol (tempbuf, mangle);
334     case 'D': /* delegate T */
335       mangle++;
336       mangle = parse_function_type (tempbuf, mangle);
337       obstack_grow_str (tempbuf, "delegate");
338       return mangle;
339     case 'B': /* tuple T */
340       /* TODO: Handle this.  */
341       return NULL;
342
343     /* Function types */
344     case 'F': case 'U': case 'W':
345     case 'V': case 'R':
346       mangle = parse_function_type (tempbuf, mangle);
347       obstack_grow_str (tempbuf, "function");
348       return mangle;
349
350     /* Basic types */
351     case 'n':
352       mangle++;
353       obstack_grow_str (tempbuf, "none");
354       return mangle;
355     case 'v':
356       mangle++;
357       obstack_grow_str (tempbuf, "void");
358       return mangle;
359     case 'g':
360       mangle++;
361       obstack_grow_str (tempbuf, "byte");
362       return mangle;
363     case 'h':
364       mangle++;
365       obstack_grow_str (tempbuf, "ubyte");
366       return mangle;
367     case 's':
368       mangle++;
369       obstack_grow_str (tempbuf, "short");
370       return mangle;
371     case 't':
372       mangle++;
373       obstack_grow_str (tempbuf, "ushort");
374       return mangle;
375     case 'i':
376       mangle++;
377       obstack_grow_str (tempbuf, "int");
378       return mangle;
379     case 'k':
380       mangle++;
381       obstack_grow_str (tempbuf, "uint");
382       return mangle;
383     case 'l':
384       mangle++;
385       obstack_grow_str (tempbuf, "long");
386       return mangle;
387     case 'm':
388       mangle++;
389       obstack_grow_str (tempbuf, "ulong");
390       return mangle;
391     case 'f':
392       mangle++;
393       obstack_grow_str (tempbuf, "float");
394       return mangle;
395     case 'd':
396       mangle++;
397       obstack_grow_str (tempbuf, "double");
398       return mangle;
399     case 'e':
400       mangle++;
401       obstack_grow_str (tempbuf, "real");
402       return mangle;
403
404     /* Imaginary and Complex types */
405     case 'o':
406       mangle++;
407       obstack_grow_str (tempbuf, "ifloat");
408       return mangle;
409     case 'p':
410       mangle++;
411       obstack_grow_str (tempbuf, "idouble");
412       return mangle;
413     case 'j':
414       mangle++;
415       obstack_grow_str (tempbuf, "ireal");
416       return mangle;
417     case 'q':
418       mangle++;
419       obstack_grow_str (tempbuf, "cfloat");
420       return mangle;
421     case 'r':
422       mangle++;
423       obstack_grow_str (tempbuf, "cdouble");
424       return mangle;
425     case 'c':
426       mangle++;
427       obstack_grow_str (tempbuf, "creal");
428       return mangle;
429
430     /* Other types */
431     case 'b':
432       mangle++;
433       obstack_grow_str (tempbuf, "bool");
434       return mangle;
435     case 'a':
436       mangle++;
437       obstack_grow_str (tempbuf, "char");
438       return mangle;
439     case 'u':
440       mangle++;
441       obstack_grow_str (tempbuf, "wchar");
442       return mangle;
443     case 'w':
444       mangle++;
445       obstack_grow_str (tempbuf, "dchar");
446       return mangle;
447
448     default: /* unhandled */
449       return NULL;
450     }
451 }
452
453 /* Extract the identifier from MANGLE and append it to TEMPBUF.
454    Return the remaining string on success or NULL on failure.  */
455
456 static const char *
457 parse_identifier (struct obstack *tempbuf, const char *mangle)
458 {
459   if ((mangle == NULL) || (*mangle == '\0'))
460     return mangle;
461
462   if (ISDIGIT (*mangle))
463     {
464       char *endptr;
465       long i = strtol (mangle, &endptr, 10);
466
467       if (i <= 0 || strlen (endptr) < i)
468         return NULL;
469
470       mangle = endptr;
471
472       /* No support for demangling templates.  */
473       if (i >= 5 && strncmp (mangle, "__T", 3) == 0)
474         return NULL;
475
476       if (strncmp (mangle, "__ctor", i) == 0)
477         {
478           /* Constructor symbol for a class/struct.  */
479           obstack_grow_str (tempbuf, "this");
480           mangle += i;
481           return mangle;
482         }
483       else if (strncmp (mangle, "__dtor", i) == 0)
484         {
485           /* Destructor symbol for a class/struct.  */
486           obstack_grow_str (tempbuf, "~this");
487           mangle += i;
488           return mangle;
489         }
490       else if (strncmp (mangle, "__postblit", i) == 0)
491         {
492           /* Postblit symbol for a struct.  */
493           obstack_grow_str (tempbuf, "this(this)");
494           mangle += i;
495           return mangle;
496         }
497       else if (strncmp (mangle, "__initZ", i+1) == 0)
498         {
499           /* The static initialiser for a given symbol.  */
500           obstack_grow_str (tempbuf, "init$");
501           mangle += i + 1;
502           return mangle;
503         }
504       else if (strncmp (mangle, "__ClassZ", i+1) == 0)
505         {
506           /* The classinfo symbol for a given class.  */
507           obstack_grow_str (tempbuf, "classinfo$");
508           mangle += i + 1;
509           return mangle;
510         }
511       else if (strncmp (mangle, "__vtblZ", i+1) == 0)
512         {
513           /* The vtable symbol for a given class.  */
514           obstack_grow_str (tempbuf, "vtbl$");
515           mangle += i + 1;
516           return mangle;
517         }
518       else if (strncmp (mangle, "__InterfaceZ", i+1) == 0)
519         {
520           /* The interface symbol for a given class.  */
521           obstack_grow_str (tempbuf, "interface$");
522           mangle += i + 1;
523           return mangle;
524         }
525       else if (strncmp (mangle, "__ModuleInfoZ", i+1) == 0)
526         {
527           /* The ModuleInfo symbol for a given module.  */
528           obstack_grow_str (tempbuf, "moduleinfo$");
529           mangle += i + 1;
530           return mangle;
531         }
532       obstack_grow (tempbuf, mangle, i);
533       mangle += i;
534     }
535   else
536     return NULL;
537
538   return mangle;
539 }
540
541 /* Test whether the current position of MANGLE is pointing to the
542    beginning of a mangled function parameter list, which starts with
543    the calling convention.  Returns 1 on success or 0 on failure.  */
544
545 static int
546 call_convention_p (const char *mangle)
547 {
548   size_t i;
549
550   if ((mangle == NULL) || (*mangle == '\0'))
551     return 0;
552
553   switch (*mangle)
554     {
555     case 'F': case 'U': case 'V':
556     case 'W': case 'R':
557       return 1;
558
559     case 'M': /* Prefix for functions needing 'this'.  */
560       i = 1;
561       if (mangle[i] == 'x')
562         i++;
563
564       switch (mangle[i])
565         {
566         case 'F': case 'U': case 'V':
567         case 'W': case 'R':
568           return 1;
569         }
570
571     default:
572       return 0;
573     }
574 }
575
576 /* Extract and demangle the symbol in MANGLE and append it to TEMPBUF.
577    Return the remaining signature on success or NULL on failure.  */
578
579 const char *
580 d_parse_symbol (struct obstack *tempbuf, const char *mangle)
581 {
582   size_t n = 0;
583   do
584     {
585       if (n++)
586         obstack_grow_str (tempbuf, ".");
587
588       mangle = parse_identifier (tempbuf, mangle);
589
590       if (call_convention_p (mangle))
591         {
592           char *saved;
593
594           /* Skip over 'this' parameter.  */
595           if (*mangle == 'M')
596             mangle += (mangle[1] == 'x') ? 2 : 1;
597
598           /* Skip over calling convention and attributes in qualified name.  */
599           saved = obstack_next_free (tempbuf);
600           mangle = parse_call_convention (tempbuf, mangle);
601           mangle = parse_attributes (tempbuf, mangle);
602           obstack_next_free (tempbuf) = saved;
603
604           obstack_grow_str (tempbuf, "(");
605           mangle = parse_function_args (tempbuf, mangle);
606           obstack_grow_str (tempbuf, ")");
607
608           /* Demangle the function return type as a kind of sanity test.  */
609           if ((mangle != NULL) && !ISDIGIT (*mangle))
610             {
611               saved = obstack_next_free (tempbuf);
612               mangle = parse_type (tempbuf, mangle);
613               obstack_next_free (tempbuf) = saved;
614             }
615         }
616     }
617   while ((mangle != NULL) && ISDIGIT (*mangle));
618
619   return mangle;
620 }
621