gdb/
[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-2012 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 "symtab.h"
22 #include "language.h"
23 #include "d-lang.h"
24 #include "c-lang.h"
25 #include "gdb_string.h"
26 #include "parser-defs.h"
27 #include "gdb_obstack.h"
28
29 #include <ctype.h>
30
31 /* Extract identifiers from MANGLED_STR and append it to TEMPBUF.
32    Return 1 on success or 0 on failure.  */
33 static int
34 extract_identifiers (const char *mangled_str, struct obstack *tempbuf)
35 {
36   long i = 0;
37
38   while (isdigit (*mangled_str))
39     {
40       char *end_ptr;
41
42       i = strtol (mangled_str, &end_ptr, 10);
43       mangled_str = end_ptr;
44       if (i <= 0 || strlen (mangled_str) < i)
45         return 0;
46       obstack_grow (tempbuf, mangled_str, i);
47       mangled_str += i;
48       obstack_grow_str (tempbuf, ".");
49     }
50   if (*mangled_str == '\0' || i == 0)
51     return 0;
52   obstack_blank (tempbuf, -1);
53   return 1;
54 }
55
56 /* Extract and demangle type from MANGLED_STR and append it to TEMPBUF.
57    Return 1 on success or 0 on failure.  */
58 static int
59 extract_type_info (const char *mangled_str, struct obstack *tempbuf)
60 {
61   if (*mangled_str == '\0')
62     return 0;
63   switch (*mangled_str++)
64     {
65       case 'A': /* dynamic array */
66       case 'G': /* static array */
67       case 'H': /* associative array */
68         if (!extract_type_info (mangled_str, tempbuf))
69           return 0;
70         obstack_grow_str (tempbuf, "[]");
71         return 1;
72       case 'P': /* pointer */
73         if (!extract_type_info (mangled_str, tempbuf))
74           return 0;
75         obstack_grow_str (tempbuf, "*");
76         return 1;
77       case 'R': /* reference */
78         if (!extract_type_info (mangled_str, tempbuf))
79           return 0;
80         obstack_grow_str (tempbuf, "&");
81         return 1;
82       case 'Z': /* return value */
83         return extract_type_info (mangled_str, tempbuf);
84       case 'J': /* out */
85         obstack_grow_str (tempbuf, "out ");
86         return extract_type_info (mangled_str, tempbuf);
87       case 'K': /* inout */
88         obstack_grow_str (tempbuf, "inout ");
89         return extract_type_info (mangled_str, tempbuf);
90       case 'E': /* enum */
91       case 'T': /* typedef */
92       case 'D': /* delegate */
93       case 'C': /* class */
94       case 'S': /* struct */
95         return extract_identifiers (mangled_str, tempbuf);
96
97       /* basic types: */
98       case 'n': obstack_grow_str (tempbuf, "none"); return 1;
99       case 'v': obstack_grow_str (tempbuf, "void"); return 1;
100       case 'g': obstack_grow_str (tempbuf, "byte"); return 1;
101       case 'h': obstack_grow_str (tempbuf, "ubyte"); return 1;
102       case 's': obstack_grow_str (tempbuf, "short"); return 1;
103       case 't': obstack_grow_str (tempbuf, "ushort"); return 1;
104       case 'i': obstack_grow_str (tempbuf, "int"); return 1;
105       case 'k': obstack_grow_str (tempbuf, "uint"); return 1;
106       case 'l': obstack_grow_str (tempbuf, "long"); return 1;
107       case 'm': obstack_grow_str (tempbuf, "ulong"); return 1;
108       case 'f': obstack_grow_str (tempbuf, "float"); return 1;
109       case 'd': obstack_grow_str (tempbuf, "double"); return 1;
110       case 'e': obstack_grow_str (tempbuf, "real"); return 1;
111
112       /* imaginary and complex: */
113       case 'o': obstack_grow_str (tempbuf, "ifloat"); return 1;
114       case 'p': obstack_grow_str (tempbuf, "idouble"); return 1;
115       case 'j': obstack_grow_str (tempbuf, "ireal"); return 1;
116       case 'q': obstack_grow_str (tempbuf, "cfloat"); return 1;
117       case 'r': obstack_grow_str (tempbuf, "cdouble"); return 1;
118       case 'c': obstack_grow_str (tempbuf, "creal"); return 1;
119
120       /* other types: */
121       case 'b': obstack_grow_str (tempbuf, "bit"); return 1;
122       case 'a': obstack_grow_str (tempbuf, "char"); return 1;
123       case 'u': obstack_grow_str (tempbuf, "wchar"); return 1;
124       case 'w': obstack_grow_str (tempbuf, "dchar"); return 1;
125
126       default:
127         obstack_grow_str (tempbuf, "unknown");
128         return 1;
129     }
130 }
131
132 /* Implements the la_demangle language_defn routine for language D.  */
133 char *
134 d_demangle (const char *symbol, int options)
135 {
136   struct obstack tempbuf;
137   char *out_str;
138   unsigned char is_func = 0;
139
140   if (symbol == NULL)
141     return NULL;
142   else if (strcmp (symbol, "_Dmain") == 0)
143     return xstrdup ("D main");
144
145   obstack_init (&tempbuf);
146   
147   if (symbol[0] == '_' && symbol[1] == 'D')
148     {
149       symbol += 2;
150       is_func = 1;
151     }
152   else if (strncmp (symbol, "__Class_", 8) == 0)
153     symbol += 8;
154   else if (strncmp (symbol, "__init_", 7) == 0)
155     symbol += 7;
156   else if (strncmp (symbol, "__vtbl_", 7) == 0)
157     symbol += 7;
158   else if (strncmp (symbol, "__modctor_", 10) == 0)
159     symbol += 10;
160   else if (strncmp (symbol, "__moddtor_", 10) == 0)
161     symbol += 10;
162   else if (strncmp (symbol, "__ModuleInfo_", 13) == 0)
163     symbol += 13;
164   else
165     {
166       obstack_free (&tempbuf, NULL);
167       return NULL;
168     }
169   
170   if (!extract_identifiers (symbol, &tempbuf))
171     {
172       obstack_free (&tempbuf, NULL);
173       return NULL;
174     }
175
176   obstack_grow_str (&tempbuf, "(");
177   if (is_func == 1 && *symbol == 'F')
178     {
179       symbol++;
180       while (*symbol != '\0' && *symbol != 'Z')
181         {
182           if (is_func == 1)
183             is_func++;
184           else
185             obstack_grow_str (&tempbuf, ", ");
186           if (!extract_type_info (symbol, &tempbuf))
187             {
188               obstack_free (&tempbuf, NULL);
189               return NULL;
190            }
191         }
192      }
193   obstack_grow_str0 (&tempbuf, ")");
194
195   /* Doesn't display the return type, but wouldn't be too hard to do.  */
196
197   out_str = xstrdup (obstack_finish (&tempbuf));
198   obstack_free (&tempbuf, NULL);
199   return out_str;
200 }
201
202 /* Table mapping opcodes into strings for printing operators
203    and precedences of the operators.  */
204 static const struct op_print d_op_print_tab[] =
205 {
206   {",", BINOP_COMMA, PREC_COMMA, 0},
207   {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
208   {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
209   {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
210   {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
211   {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
212   {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
213   {"==", BINOP_EQUAL, PREC_EQUAL, 0},
214   {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
215   {"<=", BINOP_LEQ, PREC_ORDER, 0},
216   {">=", BINOP_GEQ, PREC_ORDER, 0},
217   {">", BINOP_GTR, PREC_ORDER, 0},
218   {"<", BINOP_LESS, PREC_ORDER, 0},
219   {">>", BINOP_RSH, PREC_SHIFT, 0},
220   {"<<", BINOP_LSH, PREC_SHIFT, 0},
221   {"+", BINOP_ADD, PREC_ADD, 0},
222   {"-", BINOP_SUB, PREC_ADD, 0},
223   {"*", BINOP_MUL, PREC_MUL, 0},
224   {"/", BINOP_DIV, PREC_MUL, 0},
225   {"%", BINOP_REM, PREC_MUL, 0},
226   {"@", BINOP_REPEAT, PREC_REPEAT, 0},
227   {"-", UNOP_NEG, PREC_PREFIX, 0},
228   {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
229   {"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
230   {"*", UNOP_IND, PREC_PREFIX, 0},
231   {"&", UNOP_ADDR, PREC_PREFIX, 0},
232   {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
233   {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
234   {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
235   {NULL, 0, 0, 0}
236 };
237
238 static const struct language_defn d_language_defn =
239 {
240   "d",
241   language_d,
242   range_check_off,
243   type_check_off,
244   case_sensitive_on,
245   array_row_major,
246   macro_expansion_c,
247   &exp_descriptor_c,
248   c_parse,
249   c_error,
250   null_post_parser,
251   c_printchar,                  /* Print a character constant.  */
252   c_printstr,                   /* Function to print string constant.  */
253   c_emit_char,                  /* Print a single char.  */
254   c_print_type,                 /* Print a type using appropriate syntax.  */
255   c_print_typedef,              /* Print a typedef using appropriate
256                                    syntax.  */
257   d_val_print,                  /* Print a value using appropriate syntax.  */
258   c_value_print,                /* Print a top-level value.  */
259   default_read_var_value,       /* la_read_var_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   NULL,                         /* la_get_symbol_name_cmp */
277   iterate_over_symbols,
278   LANG_MAGIC
279 };
280
281 /* Provide a prototype to silence -Wmissing-prototypes.  */
282 extern initialize_file_ftype _initialize_d_language;
283
284 void
285 _initialize_d_language (void)
286 {
287   add_language (&d_language_defn);
288 }