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.  */
34static int
35extract_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.  */
59static int
60extract_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.  */
134char *
135d_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.  */
205static 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
239static 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
279void
280_initialize_d_language (void)
281{
282  add_language (&d_language_defn);
283}
284