Move D demangling routines out of d-lang.c and into d-support.c, which
[deliverable/binutils-gdb.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
This page took 0.056727 seconds and 4 git commands to generate.