1 /* Helper routines for D support in GDB.
3 Copyright (C) 2014 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
22 #include "gdb_obstack.h"
24 #include "safe-ctype.h"
26 static const char *parse_function_args (struct obstack
*, const char *);
27 static const char *parse_type (struct obstack
*, const char *);
30 /* Demangle the calling convention from MANGLE and append it to TEMPBUF.
31 Return the remaining string on success or NULL on failure. */
34 parse_call_convention (struct obstack
*tempbuf
, const char *mangle
)
36 if ((mangle
== NULL
) || (*mangle
== '\0'))
46 obstack_grow_str (tempbuf
, "extern(C) ");
48 case 'W': /* (Windows) */
50 obstack_grow_str (tempbuf
, "extern(Windows) ");
52 case 'V': /* (Pascal) */
54 obstack_grow_str (tempbuf
, "extern(Pascal) ");
58 obstack_grow_str (tempbuf
, "extern(C++) ");
67 /* Demangle the D function attributes from MANGLE and append it to TEMPBUF.
68 Return the remaining string on success or NULL on failure. */
71 parse_attributes (struct obstack
*tempbuf
, const char *mangle
)
73 if ((mangle
== NULL
) || (*mangle
== '\0'))
76 while (*mangle
== 'N')
83 obstack_grow_str (tempbuf
, "pure ");
85 case 'b': /* nothrow */
87 obstack_grow_str (tempbuf
, "nothrow ");
91 obstack_grow_str (tempbuf
, "ref ");
93 case 'd': /* @property */
95 obstack_grow_str (tempbuf
, "@property ");
97 case 'e': /* @trusted */
99 obstack_grow_str (tempbuf
, "@trusted ");
101 case 'f': /* @safe */
103 obstack_grow_str (tempbuf
, "@safe ");
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. */
118 /* Demangle the function type from MANGLE and append it to TEMPBUF.
119 Return the remaining string on success or NULL on failure. */
122 parse_function_type (struct obstack
*tempbuf
, const char *mangle
)
124 struct obstack obattr
, obargs
, obtype
;
125 char *attr
, *args
, *type
;
126 size_t szattr
, szargs
, sztype
;
128 if ((mangle
== NULL
) || (*mangle
== '\0'))
131 /* The order of the mangled string is:
133 CallConvention FuncAttrs Arguments ArgClose Type
135 The demangled string is re-ordered as:
136 CallConvention Type Arguments FuncAttrs
138 obstack_init (&obattr
);
139 obstack_init (&obargs
);
140 obstack_init (&obtype
);
142 /* Function call convention. */
143 mangle
= parse_call_convention (tempbuf
, mangle
);
145 /* Function attributes. */
146 mangle
= parse_attributes (&obattr
, mangle
);
147 szattr
= obstack_object_size (&obattr
);
148 attr
= obstack_finish (&obattr
);
150 /* Function arguments. */
151 mangle
= parse_function_args (&obargs
, mangle
);
152 szargs
= obstack_object_size (&obargs
);
153 args
= obstack_finish (&obargs
);
155 /* Function return type. */
156 mangle
= parse_type (&obtype
, mangle
);
157 sztype
= obstack_object_size (&obtype
);
158 type
= obstack_finish (&obtype
);
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
);
167 obstack_free (&obattr
, NULL
);
168 obstack_free (&obargs
, NULL
);
169 obstack_free (&obtype
, NULL
);
173 /* Demangle the argument list from MANGLE and append it to TEMPBUF.
174 Return the remaining string on success or NULL on failure. */
177 parse_function_args (struct obstack
*tempbuf
, const char *mangle
)
181 while ((mangle
!= NULL
) && (*mangle
!= '\0'))
185 case 'X': /* (variadic T t...) style. */
187 obstack_grow_str (tempbuf
, "...");
189 case 'Y': /* (variadic T t, ...) style. */
191 obstack_grow_str (tempbuf
, ", ...");
193 case 'Z': /* Normal function. */
199 obstack_grow_str (tempbuf
, ", ");
201 if (*mangle
== 'M') /* scope(T) */
204 obstack_grow_str (tempbuf
, "scope ");
209 case 'J': /* out(T) */
211 obstack_grow_str (tempbuf
, "out ");
213 case 'K': /* ref(T) */
215 obstack_grow_str (tempbuf
, "ref ");
217 case 'L': /* lazy(T) */
219 obstack_grow_str (tempbuf
, "lazy ");
222 mangle
= parse_type (tempbuf
, mangle
);
227 /* Demangle the type from MANGLE and append it to TEMPBUF.
228 Return the remaining string on success or NULL on failure. */
231 parse_type (struct obstack
*tempbuf
, const char *mangle
)
233 if ((mangle
== NULL
) || (*mangle
== '\0'))
238 case 'O': /* shared(T) */
240 obstack_grow_str (tempbuf
, "shared(");
241 mangle
= parse_type (tempbuf
, mangle
);
242 obstack_grow_str (tempbuf
, ")");
244 case 'x': /* const(T) */
246 obstack_grow_str (tempbuf
, "const(");
247 mangle
= parse_type (tempbuf
, mangle
);
248 obstack_grow_str (tempbuf
, ")");
250 case 'y': /* immutable(T) */
252 obstack_grow_str (tempbuf
, "immutable(");
253 mangle
= parse_type (tempbuf
, mangle
);
254 obstack_grow_str (tempbuf
, ")");
258 if (*mangle
== 'g') /* wild(T) */
261 obstack_grow_str (tempbuf
, "inout(");
262 mangle
= parse_type (tempbuf
, mangle
);
263 obstack_grow_str (tempbuf
, ")");
266 else if (*mangle
== 'h') /* vector(T) */
269 /* The basetype for vectors are always static arrays. */
272 obstack_grow_str (tempbuf
, "__vector(");
273 mangle
= parse_type (tempbuf
, mangle
);
274 obstack_grow_str (tempbuf
, ")");
279 case 'A': /* dynamic array (T[]) */
281 mangle
= parse_type (tempbuf
, mangle
);
282 obstack_grow_str (tempbuf
, "[]");
284 case 'G': /* static array (T[N]) */
291 while (ISDIGIT (*mangle
))
296 mangle
= parse_type (tempbuf
, mangle
);
297 obstack_grow_str (tempbuf
, "[");
298 obstack_grow (tempbuf
, numptr
, num
);
299 obstack_grow_str (tempbuf
, "]");
302 case 'H': /* associative array (T[T]) */
304 struct obstack obtype
;
309 obstack_init (&obtype
);
310 mangle
= parse_type (&obtype
, mangle
);
311 sztype
= obstack_object_size (&obtype
);
312 type
= obstack_finish (&obtype
);
314 mangle
= parse_type (tempbuf
, mangle
);
315 obstack_grow_str (tempbuf
, "[");
316 obstack_grow (tempbuf
, type
, sztype
);
317 obstack_grow_str (tempbuf
, "]");
319 obstack_free (&obtype
, NULL
);
322 case 'P': /* pointer (T*) */
324 mangle
= parse_type (tempbuf
, mangle
);
325 obstack_grow_str (tempbuf
, "*");
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 */
333 return d_parse_symbol (tempbuf
, mangle
);
334 case 'D': /* delegate T */
336 mangle
= parse_function_type (tempbuf
, mangle
);
337 obstack_grow_str (tempbuf
, "delegate");
339 case 'B': /* tuple T */
340 /* TODO: Handle this. */
344 case 'F': case 'U': case 'W':
346 mangle
= parse_function_type (tempbuf
, mangle
);
347 obstack_grow_str (tempbuf
, "function");
353 obstack_grow_str (tempbuf
, "none");
357 obstack_grow_str (tempbuf
, "void");
361 obstack_grow_str (tempbuf
, "byte");
365 obstack_grow_str (tempbuf
, "ubyte");
369 obstack_grow_str (tempbuf
, "short");
373 obstack_grow_str (tempbuf
, "ushort");
377 obstack_grow_str (tempbuf
, "int");
381 obstack_grow_str (tempbuf
, "uint");
385 obstack_grow_str (tempbuf
, "long");
389 obstack_grow_str (tempbuf
, "ulong");
393 obstack_grow_str (tempbuf
, "float");
397 obstack_grow_str (tempbuf
, "double");
401 obstack_grow_str (tempbuf
, "real");
404 /* Imaginary and Complex types */
407 obstack_grow_str (tempbuf
, "ifloat");
411 obstack_grow_str (tempbuf
, "idouble");
415 obstack_grow_str (tempbuf
, "ireal");
419 obstack_grow_str (tempbuf
, "cfloat");
423 obstack_grow_str (tempbuf
, "cdouble");
427 obstack_grow_str (tempbuf
, "creal");
433 obstack_grow_str (tempbuf
, "bool");
437 obstack_grow_str (tempbuf
, "char");
441 obstack_grow_str (tempbuf
, "wchar");
445 obstack_grow_str (tempbuf
, "dchar");
448 default: /* unhandled */
453 /* Extract the identifier from MANGLE and append it to TEMPBUF.
454 Return the remaining string on success or NULL on failure. */
457 parse_identifier (struct obstack
*tempbuf
, const char *mangle
)
459 if ((mangle
== NULL
) || (*mangle
== '\0'))
462 if (ISDIGIT (*mangle
))
465 long i
= strtol (mangle
, &endptr
, 10);
467 if (i
<= 0 || strlen (endptr
) < i
)
472 /* No support for demangling templates. */
473 if (i
>= 5 && strncmp (mangle
, "__T", 3) == 0)
476 if (strncmp (mangle
, "__ctor", i
) == 0)
478 /* Constructor symbol for a class/struct. */
479 obstack_grow_str (tempbuf
, "this");
483 else if (strncmp (mangle
, "__dtor", i
) == 0)
485 /* Destructor symbol for a class/struct. */
486 obstack_grow_str (tempbuf
, "~this");
490 else if (strncmp (mangle
, "__postblit", i
) == 0)
492 /* Postblit symbol for a struct. */
493 obstack_grow_str (tempbuf
, "this(this)");
497 else if (strncmp (mangle
, "__initZ", i
+1) == 0)
499 /* The static initialiser for a given symbol. */
500 obstack_grow_str (tempbuf
, "init$");
504 else if (strncmp (mangle
, "__ClassZ", i
+1) == 0)
506 /* The classinfo symbol for a given class. */
507 obstack_grow_str (tempbuf
, "classinfo$");
511 else if (strncmp (mangle
, "__vtblZ", i
+1) == 0)
513 /* The vtable symbol for a given class. */
514 obstack_grow_str (tempbuf
, "vtbl$");
518 else if (strncmp (mangle
, "__InterfaceZ", i
+1) == 0)
520 /* The interface symbol for a given class. */
521 obstack_grow_str (tempbuf
, "interface$");
525 else if (strncmp (mangle
, "__ModuleInfoZ", i
+1) == 0)
527 /* The ModuleInfo symbol for a given module. */
528 obstack_grow_str (tempbuf
, "moduleinfo$");
532 obstack_grow (tempbuf
, mangle
, i
);
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. */
546 call_convention_p (const char *mangle
)
550 if ((mangle
== NULL
) || (*mangle
== '\0'))
555 case 'F': case 'U': case 'V':
559 case 'M': /* Prefix for functions needing 'this'. */
561 if (mangle
[i
] == 'x')
566 case 'F': case 'U': case 'V':
576 /* Extract and demangle the symbol in MANGLE and append it to TEMPBUF.
577 Return the remaining signature on success or NULL on failure. */
580 d_parse_symbol (struct obstack
*tempbuf
, const char *mangle
)
586 obstack_grow_str (tempbuf
, ".");
588 mangle
= parse_identifier (tempbuf
, mangle
);
590 if (call_convention_p (mangle
))
594 /* Skip over 'this' parameter. */
596 mangle
+= (mangle
[1] == 'x') ? 2 : 1;
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
;
604 obstack_grow_str (tempbuf
, "(");
605 mangle
= parse_function_args (tempbuf
, mangle
);
606 obstack_grow_str (tempbuf
, ")");
608 /* Demangle the function return type as a kind of sanity test. */
609 if ((mangle
!= NULL
) && !ISDIGIT (*mangle
))
611 saved
= obstack_next_free (tempbuf
);
612 mangle
= parse_type (tempbuf
, mangle
);
613 obstack_next_free (tempbuf
) = saved
;
617 while ((mangle
!= NULL
) && ISDIGIT (*mangle
));
This page took 0.041589 seconds and 4 git commands to generate.