2011-03-11 Michael Snyder <msnyder@vmware.com>
[platform/upstream/binutils.git] / gdb / d-lang.c
1 /* D language support routines for GDB, the GNU debugger.
2
3    Copyright (C) 2005, 2006, 2008, 2009, 2010, 2011
4    Free Software Foundation, Inc.
5
6    This file is part of GDB.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21 #include "defs.h"
22 #include "symtab.h"
23 #include "language.h"
24 #include "d-lang.h"
25 #include "c-lang.h"
26 #include "gdb_string.h"
27 #include "parser-defs.h"
28 #include "gdb_obstack.h"
29
30 #include <ctype.h>
31
32 /* Extract identifiers from MANGLED_STR and append it to TEMPBUF.
33    Return 1 on success or 0 on failure.  */
34 static int
35 extract_identifiers (const char *mangled_str, struct obstack *tempbuf)
36 {
37   long i = 0;
38
39   while (isdigit (*mangled_str))
40     {
41       char *end_ptr;
42
43       i = strtol (mangled_str, &end_ptr, 10);
44       mangled_str = end_ptr;
45       if (i <= 0 || strlen (mangled_str) < i)
46         return 0;
47       obstack_grow (tempbuf, mangled_str, i);
48       mangled_str += i;
49       obstack_grow_str (tempbuf, ".");
50     }
51   if (*mangled_str == '\0' || i == 0)
52     return 0;
53   obstack_blank (tempbuf, -1);
54   return 1;
55 }
56
57 /* Extract and demangle type from MANGLED_STR and append it to TEMPBUF.
58    Return 1 on success or 0 on failure.  */
59 static int
60 extract_type_info (const char *mangled_str, struct obstack *tempbuf)
61 {
62   if (*mangled_str == '\0')
63     return 0;
64   switch (*mangled_str++)
65     {
66       case 'A': /* dynamic array */
67       case 'G': /* static array */
68       case 'H': /* associative array */
69         if (!extract_type_info (mangled_str, tempbuf))
70           return 0;
71         obstack_grow_str (tempbuf, "[]");
72         return 1;
73       case 'P': /* pointer */
74         if (!extract_type_info (mangled_str, tempbuf))
75           return 0;
76         obstack_grow_str (tempbuf, "*");
77         return 1;
78       case 'R': /* reference */
79         if (!extract_type_info (mangled_str, tempbuf))
80           return 0;
81         obstack_grow_str (tempbuf, "&");
82         return 1;
83       case 'Z': /* return value */
84         return extract_type_info (mangled_str, tempbuf);
85       case 'J': /* out */
86         obstack_grow_str (tempbuf, "out ");
87         return extract_type_info (mangled_str, tempbuf);
88       case 'K': /* inout */
89         obstack_grow_str (tempbuf, "inout ");
90         return extract_type_info (mangled_str, tempbuf);
91       case 'E': /* enum */
92       case 'T': /* typedef */
93       case 'D': /* delegate */
94       case 'C': /* class */
95       case 'S': /* struct */
96         return extract_identifiers (mangled_str, tempbuf);
97
98       /* basic types: */
99       case 'n': obstack_grow_str (tempbuf, "none"); return 1;
100       case 'v': obstack_grow_str (tempbuf, "void"); return 1;
101       case 'g': obstack_grow_str (tempbuf, "byte"); return 1;
102       case 'h': obstack_grow_str (tempbuf, "ubyte"); return 1;
103       case 's': obstack_grow_str (tempbuf, "short"); return 1;
104       case 't': obstack_grow_str (tempbuf, "ushort"); return 1;
105       case 'i': obstack_grow_str (tempbuf, "int"); return 1;
106       case 'k': obstack_grow_str (tempbuf, "uint"); return 1;
107       case 'l': obstack_grow_str (tempbuf, "long"); return 1;
108       case 'm': obstack_grow_str (tempbuf, "ulong"); return 1;
109       case 'f': obstack_grow_str (tempbuf, "float"); return 1;
110       case 'd': obstack_grow_str (tempbuf, "double"); return 1;
111       case 'e': obstack_grow_str (tempbuf, "real"); return 1;
112
113       /* imaginary and complex: */
114       case 'o': obstack_grow_str (tempbuf, "ifloat"); return 1;
115       case 'p': obstack_grow_str (tempbuf, "idouble"); return 1;
116       case 'j': obstack_grow_str (tempbuf, "ireal"); return 1;
117       case 'q': obstack_grow_str (tempbuf, "cfloat"); return 1;
118       case 'r': obstack_grow_str (tempbuf, "cdouble"); return 1;
119       case 'c': obstack_grow_str (tempbuf, "creal"); return 1;
120
121       /* other types: */
122       case 'b': obstack_grow_str (tempbuf, "bit"); return 1;
123       case 'a': obstack_grow_str (tempbuf, "char"); return 1;
124       case 'u': obstack_grow_str (tempbuf, "wchar"); return 1;
125       case 'w': obstack_grow_str (tempbuf, "dchar"); return 1;
126
127       default:
128         obstack_grow_str (tempbuf, "unknown");
129         return 1;
130     }
131 }
132
133 /* Implements the la_demangle language_defn routine for language D.  */
134 char *
135 d_demangle (const char *symbol, int options)
136 {
137   struct obstack tempbuf;
138   char *out_str;
139   unsigned char is_func = 0;
140
141   if (symbol == NULL)
142     return NULL;
143   else if (strcmp (symbol, "_Dmain") == 0)
144     return xstrdup ("D main");
145
146   obstack_init (&tempbuf);
147   
148   if (symbol[0] == '_' && symbol[1] == 'D')
149     {
150       symbol += 2;
151       is_func = 1;
152     }
153   else if (strncmp (symbol, "__Class_", 8) == 0)
154     symbol += 8;
155   else if (strncmp (symbol, "__init_", 7) == 0)
156     symbol += 7;
157   else if (strncmp (symbol, "__vtbl_", 7) == 0)
158     symbol += 7;
159   else if (strncmp (symbol, "__modctor_", 10) == 0)
160     symbol += 10;
161   else if (strncmp (symbol, "__moddtor_", 10) == 0)
162     symbol += 10;
163   else if (strncmp (symbol, "__ModuleInfo_", 13) == 0)
164     symbol += 13;
165   else
166     {
167       obstack_free (&tempbuf, NULL);
168       return NULL;
169     }
170   
171   if (!extract_identifiers (symbol, &tempbuf))
172     {
173       obstack_free (&tempbuf, NULL);
174       return NULL;
175     }
176
177   obstack_grow_str (&tempbuf, "(");
178   if (is_func == 1 && *symbol == 'F')
179     {
180       symbol++;
181       while (*symbol != '\0' && *symbol != 'Z')
182         {
183           if (is_func == 1)
184             is_func++;
185           else
186             obstack_grow_str (&tempbuf, ", ");
187           if (!extract_type_info (symbol, &tempbuf))
188             {
189               obstack_free (&tempbuf, NULL);
190               return NULL;
191            }
192         }
193      }
194   obstack_grow_str0 (&tempbuf, ")");
195
196   /* Doesn't display the return type, but wouldn't be too hard to do.  */
197
198   out_str = xstrdup (obstack_finish (&tempbuf));
199   obstack_free (&tempbuf, NULL);
200   return out_str;
201 }
202
203 /* Table mapping opcodes into strings for printing operators
204    and precedences of the operators.  */
205 static const struct op_print d_op_print_tab[] =
206 {
207   {",", BINOP_COMMA, PREC_COMMA, 0},
208   {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
209   {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
210   {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
211   {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
212   {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
213   {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
214   {"==", BINOP_EQUAL, PREC_EQUAL, 0},
215   {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
216   {"<=", BINOP_LEQ, PREC_ORDER, 0},
217   {">=", BINOP_GEQ, PREC_ORDER, 0},
218   {">", BINOP_GTR, PREC_ORDER, 0},
219   {"<", BINOP_LESS, PREC_ORDER, 0},
220   {">>", BINOP_RSH, PREC_SHIFT, 0},
221   {"<<", BINOP_LSH, PREC_SHIFT, 0},
222   {"+", BINOP_ADD, PREC_ADD, 0},
223   {"-", BINOP_SUB, PREC_ADD, 0},
224   {"*", BINOP_MUL, PREC_MUL, 0},
225   {"/", BINOP_DIV, PREC_MUL, 0},
226   {"%", BINOP_REM, PREC_MUL, 0},
227   {"@", BINOP_REPEAT, PREC_REPEAT, 0},
228   {"-", UNOP_NEG, PREC_PREFIX, 0},
229   {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
230   {"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
231   {"*", UNOP_IND, PREC_PREFIX, 0},
232   {"&", UNOP_ADDR, PREC_PREFIX, 0},
233   {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
234   {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
235   {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
236   {NULL, 0, 0, 0}
237 };
238
239 static const struct language_defn d_language_defn =
240 {
241   "d",
242   language_d,
243   range_check_off,
244   type_check_off,
245   case_sensitive_on,
246   array_row_major,
247   macro_expansion_c,
248   &exp_descriptor_c,
249   c_parse,
250   c_error,
251   null_post_parser,
252   c_printchar,                  /* Print a character constant.  */
253   c_printstr,                   /* Function to print string constant.  */
254   c_emit_char,                  /* Print a single char.  */
255   c_print_type,                 /* Print a type using appropriate syntax.  */
256   c_print_typedef,              /* Print a typedef using appropriate
257                                    syntax.  */
258   d_val_print,                  /* Print a value using appropriate syntax.  */
259   c_value_print,                /* Print a top-level value.  */
260   NULL,                         /* Language specific skip_trampoline.  */
261   "this",
262   basic_lookup_symbol_nonlocal, 
263   basic_lookup_transparent_type,
264   d_demangle,                   /* Language specific symbol demangler.  */
265   NULL,                         /* Language specific
266                                    class_name_from_physname.  */
267   d_op_print_tab,               /* Expression operators for printing.  */
268   1,                            /* C-style arrays.  */
269   0,                            /* String lower bound.  */
270   default_word_break_characters,
271   default_make_symbol_completion_list,
272   c_language_arch_info,
273   default_print_array_index,
274   default_pass_by_reference,
275   c_get_string,
276   LANG_MAGIC
277 };
278
279 void
280 _initialize_d_language (void)
281 {
282   add_language (&d_language_defn);
283 }