public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* Re: D language support
       [not found] ` <20091230125539.GF2788@adacore.com>
@ 2010-01-09  6:25   ` Mihail Zenkov
  2010-01-09  6:29     ` Mihail Zenkov
  0 siblings, 1 reply; 33+ messages in thread
From: Mihail Zenkov @ 2010-01-09  6:25 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: gdb-patches

On Wed, 30 Dec 2009 16:55:39 +0400
Joel Brobecker <brobecker@adacore.com> wrote:

> Mihail,
> 
> Not bad :). There were a lot of little things, so I focused on the obvious
> (procedural) ones for now, and I will review the contents of your code
> again more carefully on the next revision.
> 
> Before I go into the details, I have a question, though: Are you the sole
> author of this patch? I am asking because there are really two distinctive
> coding styles used in this case. One is very different from the style
> used in GDB (and other GNU projects written in C), and the other one
> is pretty spot on in terms of the coding style.  Hard to believe that
> the same person wrote both parts! It's very important to know, because
> only the author may assign the copyright to the FSF (IANAL, but I believe
> this to be true).

You right. Initial author is John Demme. I update his patch and add
dynamic array support. AFAIK John Demme also assign copyright papers.

http://sourceware.org/bugzilla/show_bug.cgi?id=10142
http://sourceware.org/ml/gdb-patches/2005-04/msg00074.html
http://sourceware.org/ml/gdb-patches/2009-08/msg00264.html

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-01-09  6:25   ` D language support Mihail Zenkov
@ 2010-01-09  6:29     ` Mihail Zenkov
  2010-01-09 14:23       ` Joel Brobecker
  0 siblings, 1 reply; 33+ messages in thread
From: Mihail Zenkov @ 2010-01-09  6:29 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 1306 bytes --]

On Sat, 9 Jan 2010 08:25:24 +0200
Mihail Zenkov <mihai.zenkov@gmail.com> wrote:

> On Wed, 30 Dec 2009 16:55:39 +0400
> Joel Brobecker <brobecker@adacore.com> wrote:
> 
> > Mihail,
> > 
> > Not bad :). There were a lot of little things, so I focused on the obvious
> > (procedural) ones for now, and I will review the contents of your code
> > again more carefully on the next revision.
> > 
> > Before I go into the details, I have a question, though: Are you the sole
> > author of this patch? I am asking because there are really two distinctive
> > coding styles used in this case. One is very different from the style
> > used in GDB (and other GNU projects written in C), and the other one
> > is pretty spot on in terms of the coding style.  Hard to believe that
> > the same person wrote both parts! It's very important to know, because
> > only the author may assign the copyright to the FSF (IANAL, but I believe
> > this to be true).
> 
> You right. Initial author is John Demme. I update his patch and add
> dynamic array support. AFAIK John Demme also assign copyright papers.
> 
> http://sourceware.org/bugzilla/show_bug.cgi?id=10142
> http://sourceware.org/ml/gdb-patches/2005-04/msg00074.html
> http://sourceware.org/ml/gdb-patches/2009-08/msg00264.html
> 

Sorry, forget attach new patch.

[-- Attachment #2: gdb-100109-d.patch --]
[-- Type: application/octet-stream, Size: 26744 bytes --]

gdb/ChangeLog:
        D language support.
        * Makefile.in (SFILES): Add d-lang.c d-valprint.c.
                      (COMMON_OBS): Add d-lang.o d-valprint.o.
                      (HFILES_NO_SRCDIR): Add d-lang.h.
        * c-alng.c: Make c_emit_char and exp_descriptor_c public.
	* c-lang.h: Add declaration c_emit_char and exp_descriptor_c.
	* d-lang.c: New file.
	* d-lang.h: New file.
	* d-valprint.c: New file.
	* defs.h (enum language): Add language_d.
	* doc/gdb.texinfo: Add mention about D language support.
	* dwarf2read.c (set_cu_language): Add DW_LANG_D.
	* language.c (binop_result_type): Add language_d.
		     (integral_type): Add language_d. 
		     (character_type): Add language_d. 
		     (string_type): Add language_d. 
		     (boolean_type): Add language_d. 
		     (structured_type): Add language_d.
	* symfile.c (init_filename_language_table): Add language_d.
	* symtab.c Include d-lang.h.
		   (symbol_init_language_specific): Add language_d.
		   (symbol_find_demangled_name): Add language_d.
		   (symbol_natural_name): Add language_d.
		   (symbol_demangled_name): Add language_d.
		   (lookup_symbol_in_language): Add language_d.
		   (symbol_matches_domain): Add language_d.


diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 4d3e02a..7acd968 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -641,6 +641,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	charset.c cli-out.c coffread.c coff-pe-read.c \
 	complaints.c completer.c corefile.c \
 	cp-abi.c cp-support.c cp-namespace.c cp-valprint.c \
+	d-lang.c d-valprint.c \
 	cp-name-parser.y \
 	dbxread.c demangle.c dictionary.c disasm.c doublest.c dummy-frame.c \
 	dwarf2expr.c dwarf2loc.c dwarf2read.c dwarf2-frame.c \
@@ -707,7 +708,7 @@ cli-out.h gdb_expat.h breakpoint.h infcall.h obsd-tdep.h gnu-v2-abi.h \
 exec.h m32r-tdep.h osabi.h gdbcore.h solib-som.h \
 i386bsd-nat.h xml-support.h xml-tdesc.h alphabsd-tdep.h gdb_obstack.h \
 ia64-tdep.h ada-lang.h varobj.h frv-tdep.h nto-tdep.h serial.h \
-c-lang.h frame.h event-loop.h block.h cli/cli-setshow.h	\
+c-lang.h d-lang.h frame.h event-loop.h block.h cli/cli-setshow.h	\
 cli/cli-decode.h cli/cli-cmds.h cli/cli-dump.h \
 cli/cli-script.h macrotab.h symtab.h version.h gnulib/wchar.in.h \
 gnulib/string.in.h gnulib/str-two-way.h gnulib/extra/link-warning.h \
@@ -810,7 +811,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	dbxread.o coffread.o coff-pe-read.o \
 	dwarf2read.o mipsread.o stabsread.o corefile.o \
 	dwarf2expr.o dwarf2loc.o dwarf2-frame.o \
-	ada-lang.o c-lang.o f-lang.o objc-lang.o \
+	ada-lang.o c-lang.o d-lang.o f-lang.o objc-lang.o \
 	ada-tasks.o \
 	ui-out.o cli-out.o \
 	varobj.o vec.o wrapper.o \
@@ -820,7 +821,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	sentinel-frame.o \
 	complaints.o typeprint.o \
 	ada-typeprint.o c-typeprint.o f-typeprint.o m2-typeprint.o \
-	ada-valprint.o c-valprint.o cp-valprint.o f-valprint.o m2-valprint.o \
+	ada-valprint.o c-valprint.o cp-valprint.o d-valprint.o f-valprint.o \
+	m2-valprint.o \
 	serial.o mdebugread.o top.o utils.o \
 	ui-file.o \
 	user-regs.o \
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 66a9901..7b7e5da 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -253,7 +253,7 @@ print_wchar (gdb_wint_t w, const gdb_byte *orig, int orig_len,
    string whose delimiter is QUOTER.  Note that that format for printing
    characters and strings is language specific. */
 
-static void
+void
 c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
@@ -1133,7 +1133,7 @@ c_language_arch_info (struct gdbarch *gdbarch,
   lai->bool_type_default = builtin->builtin_int;
 }
 
-static const struct exp_descriptor exp_descriptor_c = 
+const struct exp_descriptor exp_descriptor_c = 
 {
   print_subexp_standard,
   operator_length_standard,
diff --git a/gdb/c-lang.h b/gdb/c-lang.h
index c2c5252..4d23364 100644
--- a/gdb/c-lang.h
+++ b/gdb/c-lang.h
@@ -87,6 +87,10 @@ extern void c_printstr (struct ui_file * stream, struct type *elttype,
 extern void c_language_arch_info (struct gdbarch *gdbarch,
 				  struct language_arch_info *lai);
 
+extern const struct exp_descriptor exp_descriptor_c;
+
+extern void c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter);
+
 /* These are in c-typeprint.c: */
 
 extern void c_type_print_base (struct type *, struct ui_file *, int, int);
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
new file mode 100644
index 0000000..6211b02
--- /dev/null
+++ b/gdb/d-lang.c
@@ -0,0 +1,326 @@
+/* D language support routines for GDB, the GNU debugger.
+
+   Copyright (C) 2005, 2006, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "symtab.h"
+#include "language.h"
+#include "d-lang.h"
+#include "c-lang.h"
+#include "gdb_string.h"
+#include "parser-defs.h"
+
+#include <ctype.h>
+
+typedef struct
+{
+  size_t len;
+  char* str;
+  char* pos;
+} unbounded_string;
+
+/* Resize unbounded string STR. NEW_SIZE is the new length of STR.  */
+static void
+str_resize (unbounded_string* str, size_t new_size)
+{
+  int pos = str->pos - str->str;
+  if (new_size == 0)
+    new_size = strlen(str->str) + 1;
+  str->str = xrealloc(str->str, new_size);
+  str->len = new_size;
+  str->pos = str->str + pos;
+}
+
+/* Append string SRC to the end of unbounded string STR.
+   LEN is the length of SRC.  */
+static void
+append_len (unbounded_string* str, char* src, size_t len)
+{
+  size_t amnt = str->len - (str->pos - str->str);
+  if (len > amnt)
+    str_resize(str, str->len + len + 20);
+  memcpy(str->pos, src, len);
+  str->pos += len;
+}
+
+/* Append string SRC to the end of unbounded string STR.  */
+static void
+append (unbounded_string* str, char* src)
+{
+  append_len(str, src, strlen(src));
+}
+
+/* Extract identifiers from MANGLED and append it to OUTPUT.
+   Return 1 on success or -1 on failure.  */
+static int
+extractidentifiers (unbounded_string* output, unbounded_string* mangled)
+{
+  long i = 0;
+  while (isdigit(*mangled->pos))
+    {
+      i = strtol(mangled->pos, &mangled->pos, 10);
+      if (i == 0 || i == LONG_MAX || i == LONG_MIN)
+        return -1;
+      if (strlen(mangled->pos) < i)
+        return -1;
+      append_len(output, mangled->pos, i);
+      mangled->pos += i;
+      append(output, ".");
+    }
+  if (*mangled->pos == '\0' || i == 0)
+    return -1;
+  output->pos--;
+  return 1;
+}
+
+/* Extract and demangle type from ID and append it to DEST.
+   Return 1 on success or -1 on failure.  */
+static int
+extracttypeinfo (unbounded_string* dest, unbounded_string* id)
+{
+  if (*id->pos == '\0')
+    return -1;
+  switch (*id->pos++)
+    {
+      case 'A': /* dynamic array */
+      case 'G': /* static array */
+      case 'H': /* associative array */
+	if (extracttypeinfo(dest, id) == -1)
+	  return -1;
+	append(dest, "[]");
+	return 1;
+      case 'P': /* pointer */
+	if (extracttypeinfo(dest, id) == -1)
+	  return -1;
+	append(dest, "*");
+	return 1;
+      case 'R': /* reference */
+	if (extracttypeinfo(dest, id) == -1)
+	  return -1;
+	append(dest, "&");
+	return 1;
+      case 'Z': /* return value */
+	return extracttypeinfo(dest, id);
+      case 'J': /* out */
+	append(dest, "out ");
+	return extracttypeinfo(dest, id);
+      case 'K': /* inout */
+	append(dest, "inout ");
+	return extracttypeinfo(dest, id);
+      case 'E': /* enum */
+      case 'T': /* typedef */
+      case 'D': /* delegate */
+      case 'C': /* class */
+      case 'S': /* struct */
+	return extractidentifiers(dest, id);
+
+      /* basic types: */
+      case 'n': append(dest, "none"); return 1;
+      case 'v': append(dest, "void"); return 1;
+      case 'g': append(dest, "byte"); return 1;
+      case 'h': append(dest, "ubyte"); return 1;
+      case 's': append(dest, "short"); return 1;
+      case 't': append(dest, "ushort"); return 1;
+      case 'i': append(dest, "int"); return 1;
+      case 'k': append(dest, "uint"); return 1;
+      case 'l': append(dest, "long"); return 1;
+      case 'm': append(dest, "ulong"); return 1;
+      case 'f': append(dest, "float"); return 1;
+      case 'd': append(dest, "double"); return 1;
+      case 'e': append(dest, "real"); return 1;
+
+      /* imaginary and complex: */
+      case 'o': append(dest, "ifloat"); return 1;
+      case 'p': append(dest, "idouble"); return 1;
+      case 'j': append(dest, "ireal"); return 1;
+      case 'q': append(dest, "cfloat"); return 1;
+      case 'r': append(dest, "cdouble"); return 1;
+      case 'c': append(dest, "creal"); return 1;
+
+      /* other types: */
+      case 'b': append(dest, "bit"); return 1;
+      case 'a': append(dest, "char"); return 1;
+      case 'u': append(dest, "wchar"); return 1;
+      case 'w': append(dest, "dchar"); return 1;
+
+      default:
+	append(dest, "unknown");
+	return 1;
+    }
+}
+
+/* D specific symbol demangler. SYMBOL_ is a mangled name.
+   OPTIONS is demangler options. Return demangled name or NULL on failure.  */
+char*
+d_demangle (const char* symbol_, int options)
+{
+  unbounded_string output;
+  unbounded_string mangled;
+  unsigned char isFunc = 0;
+  char* symbol;
+  if (symbol_ == NULL)
+    return NULL;
+  else if (strcmp(symbol_, "_Dmain") == 0)
+    return strdup("D main");
+
+  symbol = xstrdup(symbol_);
+  mangled.len = strlen(symbol);
+  mangled.str = symbol;
+  mangled.pos = symbol;
+
+  output.len = 2;
+  output.str = xmalloc(output.len);
+  output.pos = output.str;
+
+  if (symbol == strstr(symbol, "_D"))
+    {
+      mangled.pos += 2;
+      isFunc = 1;
+    } else if (symbol == strstr(symbol, "__Class_"))
+      mangled.pos += 8;
+    else if (symbol == strstr(symbol, "__init_"))
+      mangled.pos += 7;
+    else if (symbol == strstr(symbol, "__vtbl_"))
+      mangled.pos += 7;
+    else if (symbol == strstr(symbol, "__modctor_"))
+      mangled.pos += 10;
+    else if (symbol == strstr(symbol, "__moddtor_"))
+      mangled.pos += 10;
+    else if (symbol == strstr(symbol, "__ModuleInfo_"))
+      mangled.pos += 13;
+    else
+      {
+	xfree(output.str);
+	xfree(symbol);
+	return NULL;
+      }
+  
+  if (extractidentifiers(&output, &mangled) < 0)
+    {
+      xfree(output.str);
+      xfree(symbol);
+      return NULL;
+    }
+
+  append(&output, "(");
+  if (isFunc == 1 && *mangled.pos == 'F')
+    {
+      mangled.pos++;
+      while (*mangled.pos != '\0' && *mangled.pos != 'Z')
+	{
+	  if (isFunc == 1)
+	    isFunc++;
+	  else
+	    append(&output, ", ");
+	  if (extracttypeinfo(&output, &mangled) < 0)
+	    {
+	      xfree(output.str);
+	      xfree(symbol);
+	      return NULL;
+	   }
+	}
+     }
+  append(&output, ")");
+
+  /* Doesn't display the return type, but wouldn't be too hard to do.  */
+
+  append_len(&output, "", 1);
+  str_resize(&output, 0);
+  xfree(symbol);
+  return output.str;
+}
+
+/* Table mapping opcodes into strings for printing operators
+   and precedences of the operators.  */
+const struct op_print d_op_print_tab[] =
+{
+  {",", BINOP_COMMA, PREC_COMMA, 0},
+  {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
+  {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
+  {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
+  {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
+  {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
+  {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
+  {"==", BINOP_EQUAL, PREC_EQUAL, 0},
+  {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
+  {"<=", BINOP_LEQ, PREC_ORDER, 0},
+  {">=", BINOP_GEQ, PREC_ORDER, 0},
+  {">", BINOP_GTR, PREC_ORDER, 0},
+  {"<", BINOP_LESS, PREC_ORDER, 0},
+  {">>", BINOP_RSH, PREC_SHIFT, 0},
+  {"<<", BINOP_LSH, PREC_SHIFT, 0},
+  {"+", BINOP_ADD, PREC_ADD, 0},
+  {"-", BINOP_SUB, PREC_ADD, 0},
+  {"*", BINOP_MUL, PREC_MUL, 0},
+  {"/", BINOP_DIV, PREC_MUL, 0},
+  {"%", BINOP_REM, PREC_MUL, 0},
+  {"@", BINOP_REPEAT, PREC_REPEAT, 0},
+  {"-", UNOP_NEG, PREC_PREFIX, 0},
+  {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
+  {"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
+  {"*", UNOP_IND, PREC_PREFIX, 0},
+  {"&", UNOP_ADDR, PREC_PREFIX, 0},
+  {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
+  {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
+  {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
+  {NULL, 0, 0, 0}
+};
+
+const struct language_defn d_language_defn =
+{
+  "d",			/* Language name */
+  language_d,
+  range_check_off,
+  type_check_off,
+  case_sensitive_on,
+  array_row_major,
+  macro_expansion_c,
+  &exp_descriptor_c,
+  c_parse,
+  c_error,
+  null_post_parser,
+  c_printchar,		/* Print a character constant */
+  c_printstr,		/* Function to print string constant */
+  c_emit_char,		/* Print a single char */
+  c_print_type,		/* Print a type using appropriate syntax */
+  c_print_typedef,	/* Print a typedef using appropriate syntax */
+  d_val_print,		/* Print a value using appropriate syntax */
+  c_value_print,	/* Print a top-level value */
+  NULL,			/* Language specific skip_trampoline */
+  "this",		/* name_of_this */
+  basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
+  basic_lookup_transparent_type,/* lookup_transparent_type */
+  d_demangle,		/* Language specific symbol demangler */
+  NULL,			/* Language specific class_name_from_physname */
+  d_op_print_tab,	/* expression operators for printing */
+  1,			/* c-style arrays */
+  0,			/* String lower bound */
+  default_word_break_characters,
+  default_make_symbol_completion_list,
+  c_language_arch_info,
+  default_print_array_index,
+  default_pass_by_reference,
+  c_get_string,
+  LANG_MAGIC
+};
+
+void
+_initialize_d_language (void)
+{
+  add_language (&d_language_defn);
+}
diff --git a/gdb/d-lang.h b/gdb/d-lang.h
new file mode 100644
index 0000000..cb4c450
--- /dev/null
+++ b/gdb/d-lang.h
@@ -0,0 +1,31 @@
+/* D language support definitions for GDB, the GNU debugger.
+
+   Copyright (C) 2005, 2006, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#if !defined (D_LANG_H)
+#define D_LANG_H 1
+
+#include "symtab.h"
+
+extern char* d_demangle(const char* mangled, int options);
+
+extern int d_val_print (struct type *type, const gdb_byte *valaddr,
+			int embedded_offset, CORE_ADDR address,
+			struct ui_file *stream, int recurse,
+			const struct value_print_options *options);
+#endif /* !defined (D_LANG_H) */
diff --git a/gdb/d-valprint.c b/gdb/d-valprint.c
new file mode 100644
index 0000000..3f1793e
--- /dev/null
+++ b/gdb/d-valprint.c
@@ -0,0 +1,94 @@
+/* Support for printing D values for GDB, the GNU debugger.
+
+   Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "gdbcore.h"
+#include "d-lang.h"
+#include "c-lang.h"
+
+/* Detect dynamic array and print his contents. Returns the number of string
+   characters printed or -1 if TYPE not dynamic array.  */
+static int
+dynamic_array_type (struct type *type, const gdb_byte *valaddr,
+		    int embedded_offset, CORE_ADDR address,
+		    struct ui_file *stream, int recurse,
+		    const struct value_print_options *options)
+{
+  if (TYPE_NFIELDS (type) == 2
+      && TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_INT
+      && strcmp (TYPE_FIELD_NAME (type, 0), "length") == 0
+      && strcmp (TYPE_FIELD_NAME (type, 1), "ptr") == 0)
+    {
+      CORE_ADDR addr;
+      struct type *elttype;
+      struct type *true_type;
+      struct type *ptr_type;
+      struct type *range_type;
+      const gdb_byte *ptraddr;
+      struct value *val;
+      int length;
+
+      length = unpack_field_as_long (type, valaddr + embedded_offset, 0);
+
+      ptr_type = TYPE_FIELD_TYPE (type, 1);
+      elttype = check_typedef (TYPE_TARGET_TYPE (ptr_type));
+      addr = unpack_pointer (ptr_type,
+			     valaddr + TYPE_FIELD_BITPOS (type, 1) / 8
+			     + embedded_offset);
+      true_type = check_typedef (elttype);
+
+      true_type = lookup_array_range_type (true_type, 0, length - 1);
+      val = value_at(true_type, addr);
+      ptraddr = value_contents(val);
+
+      return d_val_print (true_type, ptraddr, 0, addr, stream, recurse + 1,
+			  options);
+    }
+  return -1;
+}
+
+/* Print data of type TYPE located at VALADDR (within GDB), which came from
+   the inferior at address ADDRESS, onto stdio stream STREAM according to
+   OPTIONS.  The data at VALADDR is in target byte order.
+
+   If the data are a string pointer, returns the number of string characters
+   printed.  */
+int
+d_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
+             CORE_ADDR address, struct ui_file *stream, int recurse,
+             const struct value_print_options *options)
+{
+  int ret;
+
+  CHECK_TYPEDEF (type);
+  switch (TYPE_CODE (type))
+    {
+      case TYPE_CODE_STRUCT:
+        ret = dynamic_array_type (type, valaddr, embedded_offset, address,
+				  stream, recurse, options);
+	if (ret != -1)
+	   break;
+      default:
+	ret = c_val_print (type, valaddr, embedded_offset, address, stream,
+			   recurse, options);
+    }
+
+  return ret;
+}
diff --git a/gdb/defs.h b/gdb/defs.h
index 5d251b5..2c14c80 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -188,6 +188,7 @@ enum language
     language_auto,		/* Placeholder for automatic setting */
     language_c,			/* C */
     language_cplus,		/* C++ */
+    language_d,			/* D */
     language_objc,		/* Objective-C */
     language_java,		/* Java */
     language_fortran,		/* Fortran */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 5b78f50..d203649 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -213,6 +213,10 @@ You can use @value{GDBN} to debug programs written in C and C@t{++}.
 For more information, see @ref{Supported Languages,,Supported Languages}.
 For more information, see @ref{C,,C and C++}.
 
+@cindex D
+Support for D is partial.  For information on D, see
+@ref{D,,D}.
+
 @cindex Modula-2
 Support for Modula-2 is partial.  For information on Modula-2, see
 @ref{Modula-2,,Modula-2}.
@@ -10554,6 +10558,9 @@ C source file
 @itemx .c++
 C@t{++} source file
 
+@item .d
+D source file
+
 @item .m
 Objective-C source file
 
@@ -10831,7 +10838,7 @@ being set automatically by @value{GDBN}.
 @node Supported Languages
 @section Supported Languages
 
-@value{GDBN} supports C, C@t{++}, Objective-C, Fortran, Java, Pascal,
+@value{GDBN} supports C, C@t{++}, D, Objective-C, Fortran, Java, Pascal,
 assembly, Modula-2, and Ada.
 @c This is false ...
 Some @value{GDBN} features may be used in expressions regardless of the
@@ -10850,6 +10857,7 @@ language reference or tutorial.
 
 @menu
 * C::                           C and C@t{++}
+* D::                           D
 * Objective-C::                 Objective-C
 * Fortran::                     Fortran
 * Pascal::                      Pascal
@@ -11387,6 +11395,14 @@ In the PowerPC architecture, @value{GDBN} provides a set of pseudo-registers
 to inspect @code{_Decimal128} values stored in floating point registers.
 See @ref{PowerPC,,PowerPC} for more details.
 
+@node D
+@subsection D
+
+@cindex D
+@value{GDBN} can be used to debug programs written in D and compiled with
+GDC, LDC or DMD. Currently @value{GDBN} supports only one D specific
+features - dynamic arrays.
+
 @node Objective-C
 @subsection Objective-C
 
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 7623035..4eafdc5 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -7515,6 +7515,9 @@ set_cu_language (unsigned int lang, struct dwarf2_cu *cu)
     case DW_LANG_C_plus_plus:
       cu->language = language_cplus;
       break;
+    case DW_LANG_D:
+      cu->language = language_d;
+      break;
     case DW_LANG_Fortran77:
     case DW_LANG_Fortran90:
     case DW_LANG_Fortran95:
diff --git a/gdb/language.c b/gdb/language.c
index 3500a97..6aa8f0e 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -486,6 +486,7 @@ binop_result_type (struct value *v1, struct value *v2)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       if (TYPE_CODE (t1) == TYPE_CODE_FLT)
 	return TYPE_CODE (t2) == TYPE_CODE_FLT && l2 > l1 ?
@@ -597,6 +598,7 @@ integral_type (struct type *type)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) != TYPE_CODE_INT) &&
 	(TYPE_CODE (type) != TYPE_CODE_ENUM) ? 0 : 1;
@@ -637,6 +639,7 @@ character_type (struct type *type)
 
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) == TYPE_CODE_INT) &&
 	TYPE_LENGTH (type) == sizeof (char)
@@ -659,6 +662,7 @@ string_type (struct type *type)
 
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       /* C does not have distinct string type. */
       return (0);
@@ -678,6 +682,7 @@ boolean_type (struct type *type)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       /* Might be more cleanly handled by having a
          TYPE_CODE_INT_NOT_BOOL for (the deleted) CHILL and such
@@ -717,6 +722,7 @@ structured_type (struct type *type)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) == TYPE_CODE_STRUCT) ||
 	(TYPE_CODE (type) == TYPE_CODE_UNION) ||
diff --git a/gdb/symfile.c b/gdb/symfile.c
index cee84db..48d23da 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -2534,6 +2534,7 @@ init_filename_language_table (void)
       filename_language_table =
 	xmalloc (fl_table_size * sizeof (*filename_language_table));
       add_filename_language (".c", language_c);
+      add_filename_language (".d", language_d);
       add_filename_language (".C", language_cplus);
       add_filename_language (".cc", language_cplus);
       add_filename_language (".cp", language_cplus);
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 7f5dabd..be6f23a 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -39,6 +39,7 @@
 #include "source.h"
 #include "filenames.h"		/* for FILENAME_CMP */
 #include "objc-lang.h"
+#include "d-lang.h"
 #include "ada-lang.h"
 #include "p-lang.h"
 #include "addrmap.h"
@@ -413,6 +414,7 @@ symbol_init_language_specific (struct general_symbol_info *gsymbol,
 {
   gsymbol->language = language;
   if (gsymbol->language == language_cplus
+      || gsymbol->language == language_d
       || gsymbol->language == language_java
       || gsymbol->language == language_objc)
     {
@@ -516,6 +518,16 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
 	  return demangled;
 	}
     }
+  if (gsymbol->language == language_d
+      || gsymbol->language == language_auto)
+    {
+      demangled = d_demangle(mangled, 0);
+      if (demangled != NULL)
+        {
+          gsymbol->language = language_d;
+          return demangled;
+        }
+    }
   return NULL;
 }
 
@@ -693,6 +705,7 @@ symbol_natural_name (const struct general_symbol_info *gsymbol)
   switch (gsymbol->language)
     {
     case language_cplus:
+    case language_d:
     case language_java:
     case language_objc:
       if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
@@ -718,6 +731,7 @@ symbol_demangled_name (const struct general_symbol_info *gsymbol)
   switch (gsymbol->language)
     {
     case language_cplus:
+    case language_d:
     case language_java:
     case language_objc:
       if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
@@ -1263,7 +1277,7 @@ lookup_symbol_in_language (const char *name, const struct block *block,
 
   modified_name = name;
 
-  /* If we are using C++ or Java, demangle the name before doing a lookup, so
+  /* If we are using C++, D, or Java, demangle the name before doing a lookup, so
      we can always binary search. */
   if (lang == language_cplus)
     {
@@ -1286,6 +1300,16 @@ lookup_symbol_in_language (const char *name, const struct block *block,
 	    }
 	}
     }
+  else if (current_language->la_language == language_d)
+    {
+      demangled_name = d_demangle (name, 0);
+      if (demangled_name)
+	{
+	  mangled_name = name;
+	  modified_name = demangled_name;
+	  make_cleanup (xfree, demangled_name);
+	}
+    }
   else if (lang == language_java)
     {
       demangled_name = cplus_demangle (name,
@@ -1734,6 +1758,7 @@ symbol_matches_domain (enum language symbol_language,
      A Java class declaration also defines a typedef for the class.
      Similarly, any Ada type declaration implicitly defines a typedef.  */
   if (symbol_language == language_cplus
+      || symbol_language == language_d
       || symbol_language == language_java
       || symbol_language == language_ada)
     {

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-01-09  6:29     ` Mihail Zenkov
@ 2010-01-09 14:23       ` Joel Brobecker
  2010-01-13  4:42         ` Mihail Zenkov
  0 siblings, 1 reply; 33+ messages in thread
From: Joel Brobecker @ 2010-01-09 14:23 UTC (permalink / raw)
  To: Mihail Zenkov; +Cc: gdb-patches

> > You right. Initial author is John Demme. I update his patch and add
> > dynamic array support. AFAIK John Demme also assign copyright papers.

Confirmed, I found his copyright assignment on file.

I think you're very close to having something acceptable. If you hurry,
you might even make the gdb 7.1 release :). There are still quite a few
nits here and there, so comments below.

Please also make sure that you patch does not introduce any regression
in our testsuite. Do you know how to test it? Basically, we run the
testsuite before and after applying your patch, and verify that it
does not introduce any new failures by comparing the gdb.sum files
produced before and after.  Please also make sure to mention which
architecture this was tested on (typically x86-linux or x86_64-linux).

> gdb/ChangeLog:
>         D language support.
>         * Makefile.in (SFILES): Add d-lang.c d-valprint.c.
>                       (COMMON_OBS): Add d-lang.o d-valprint.o.
>                       (HFILES_NO_SRCDIR): Add d-lang.h.

Small nit on the ChangeLog format: Everything is aligned to the first
tab on the left. For instance:

        * Makefile.in (SFILES): Add d-lang.c d-valprint.c.
        (COMMON_OBS): Add d-lang.o d-valprint.o.
        (HFILES_NO_SRCDIR): Add d-lang.h.

(make sure to use tabs, not spaces)

>         * c-alng.c: Make c_emit_char and exp_descriptor_c public.
              ^^^^^^

> 	* doc/gdb.texinfo: Add mention about D language support.

This part will need to be approved by Eli, our documentation maintainer.

> 	* language.c (binop_result_type): Add language_d.
> 		     (integral_type): Add language_d. 
> 		     (character_type): Add language_d. 
> 		     (string_type): Add language_d. 
> 		     (boolean_type): Add language_d. 
> 		     (structured_type): Add language_d.

Small note: If you want, you can write the above as:

        * language.c (binop_result_type, integral_type, character_type)
        (string_type, boolean_type, structured_type): Add language_d.

You're also allowed to use "Likewise", "Ditto", etc.

> +/* Resize unbounded string STR. NEW_SIZE is the new length of STR.  */
                                 ^^^ Missing second space after period.

You need to describe what this function does when NEW_SIZE is zero.

> +static void
> +str_resize (unbounded_string* str, size_t new_size)
> +{
> +  int pos = str->pos - str->str;
> +  if (new_size == 0)

Formatting nit: Can you add an empty line after declaration blocks.
It's sort of an unwritten convention that most developers follow.
Can you fix that in all of your patch?

> +    new_size = strlen(str->str) + 1;
> +  str->str = xrealloc(str->str, new_size);

You need to add a space before the opening parenthesis in function calls.
Can you fix your code throughout?

> +/* Extract identifiers from MANGLED and append it to OUTPUT.
> +   Return 1 on success or -1 on failure.  */
> +static int
> +extractidentifiers (unbounded_string* output, unbounded_string* mangled)

Can you rename your function to extract_identifiers, please?
Entity name conventions for GNU projects in C is to put underscores
between words... Likewise elsewhere in your patch.

> +{
> +  long i = 0;
> +  while (isdigit(*mangled->pos))
> +    {
> +      i = strtol(mangled->pos, &mangled->pos, 10);
> +      if (i == 0 || i == LONG_MAX || i == LONG_MIN)
> +        return -1;

Aren't you supposed to check errno when the returned value is LONG_MAX
and/or LONG_MIN.  Otherwise, you exclude these values as invalid.
Perhaps these values can never happen, and your test is sufficient,
but a comment would be welcome.

> +/* Extract and demangle type from ID and append it to DEST.
> +   Return 1 on success or -1 on failure.  */

Usual conventions are to return non-zero on success, and zero
otherwise. I recommend you follow this practice, as this allows
you to write:

    if (!extract_type_info (dest, id))
      return 0;

> +      case 'n': append(dest, "none"); return 1;

This is not a blocking comment, meaning that this is not a request
to fix before your patch gets accepted, but I'm starting to think
that the way you use your unbounded_string is to build the output
before printing it.  We typically would use a "ui_file" stream,
for that. In your case, you want a "memory" ui-file.  Have a look
at ui-file.h, and in particular at mem_fileopen, ui_file_write,
and ui_file_xstrdup.  That should provide you all the infrastructure
you need to get rid of this local "unbounded_string" type.

I'll give you the choice: Look at this as part of this patch, or
promise me that you'll look at it soon after this patch is in our tree.

> +/* D specific symbol demangler. SYMBOL_ is a mangled name.
       ^^^ missing hyphen.      ^^^ Missing second space after period.

> +   OPTIONS is demangler options. Return demangled name or NULL on failure.  */
                                  ^^^ Missing seconc space.

For the routine that implement a given function of a known "vector",
You don't need to repeat the description of that function.  The description
should already be provided where the function pointer is declared,
and repeating it here can potentially leead to inconsistencies.
So I'd rather you put a comment like the following:

/* Implements the la_demangle language_defn routine for language D.  */

> +char*
Missing space: char *

> +d_demangle (const char* symbol_, int options)
                           ^^^^^^

Could you use something other than a trailing underscore in your
parameter name. I've seen people use symbol1, for instance. A more
meaningful name would be ideal, but if it makes it too long, then
go for symbol1.

> +  unsigned char isFunc = 0;
                   ^^^^^^ is_func.

> +    return strdup("D main");
              ^^^^^^ use xstrdup.

> +  symbol = xstrdup(symbol_);

I don't really understand why you are duplicating the symbol string,
here...

> +  mangled.len = strlen(symbol);
> +  mangled.str = symbol;
> +  mangled.pos = symbol;

You're breaking a bit your abstraction by setting up your unbounded
string manually. This should encourage you to look at ui_files...

> +  output.len = 2;
> +  output.str = xmalloc(output.len);
> +  output.pos = output.str;

> +  if (symbol == strstr(symbol, "_D"))

Isn't just simpler to do:

     if (symbol[0] == '_' && symbol[1] == 'D')

Or:

     if (strncmp (symbol, "_D", 2) == 0

?

> +/* Table mapping opcodes into strings for printing operators
> +   and precedences of the operators.  */
> +const struct op_print d_op_print_tab[] =

Can you make this static?

> +const struct language_defn d_language_defn =
> +{

Same for this one? I'm not entire sure, since it looks like we're not
making static anywhere, but I don't see why not.

> +/* Detect dynamic array and print his contents. Returns the number of string
                                     ^^^ its contents.
Also, missing second space after the period.

> +   characters printed or -1 if TYPE not dynamic array.  */

> +  if (TYPE_NFIELDS (type) == 2
> +      && TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_INT
> +      && strcmp (TYPE_FIELD_NAME (type, 0), "length") == 0
> +      && strcmp (TYPE_FIELD_NAME (type, 1), "ptr") == 0)

Should you check the TYPE_CODE (type), here? I assume TYPE_CODE_STRUCT?
Hmmm, actually, coming back to here after having read the rest of
the patch, I see that this check has already been made.  You should
probably make a note of this in your function description. I propose
the new following description:

/* Assuming that TYPE is a TYPE_CODE_STRUCT, verify that TYPE is
   a dynamic array, and then print its value to STREAM.  Return
   the number of string characters printed, or -1 if TYPE is not
   a dynamic array.  */

You might also want to describe all the other parameters more in detail.

> +/* Print data of type TYPE located at VALADDR (within GDB), which came from
> +   the inferior at address ADDRESS, onto stdio stream STREAM according to
> +   OPTIONS.  The data at VALADDR is in target byte order.
> +
> +   If the data are a string pointer, returns the number of string characters
> +   printed.  */

Same comment as above. Since the semantics of this routine is well known
and defined elsewhere, just say that it implement the la_val_print
routine for language D.

> +	if (ret != -1)
> +	   break;
> +      default:
> +	ret = c_val_print (type, valaddr, embedded_offset, address, stream,
> +			   recurse, options);

This is surprising me a little. Don't you have plain struct types
that are not dynamic arrays? Right now, the code seems to indicate
that you don't expect any. Or maybe I missed something?

-- 
Joel

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-01-09 14:23       ` Joel Brobecker
@ 2010-01-13  4:42         ` Mihail Zenkov
  2010-01-15  5:10           ` Joel Brobecker
  2010-01-15 21:05           ` Tom Tromey
  0 siblings, 2 replies; 33+ messages in thread
From: Mihail Zenkov @ 2010-01-13  4:42 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 2335 bytes --]

> Please also make sure that you patch does not introduce any regression
> in our testsuite. Do you know how to test it? Basically, we run the
> testsuite before and after applying your patch, and verify that it
> does not introduce any new failures by comparing the gdb.sum files
> produced before and after.  Please also make sure to mention which
> architecture this was tested on (typically x86-linux or x86_64-linux).

Tested on x86-linux. I have one regression and fix it.

> This is not a blocking comment, meaning that this is not a request
> to fix before your patch gets accepted, but I'm starting to think
> that the way you use your unbounded_string is to build the output
> before printing it.  We typically would use a "ui_file" stream,
> for that. In your case, you want a "memory" ui-file.  Have a look
> at ui-file.h, and in particular at mem_fileopen, ui_file_write,
> and ui_file_xstrdup.  That should provide you all the infrastructure
> you need to get rid of this local "unbounded_string" type.
> 
> I'll give you the choice: Look at this as part of this patch, or
> promise me that you'll look at it soon after this patch is in our tree.

You right, but in unbounded_string we allocate what we needed + 20 byte.
It allows to call allocation of memory less often. This way chose John
Demme. It effective way, when we need allocate many unbounded buffers
with big size. But in ours case we need only on small buffer. 
I prefer another way - just allocate one buffer with size bigger than
worst case. It important in case with D language, as it can create only
static library at now. I do some test:

If we use ui_file we need call allocate 10275 times for "hello world"
and 86076 for real medium project on startup GDB.
If we use unbounded_string - 3130 and 25494.
If we use one buffer - 1214 and 8882.

Worst case size of buffer was 173 byte.

> > +	if (ret != -1)
> > +	   break;
> > +      default:
> > +	ret = c_val_print (type, valaddr, embedded_offset, address, stream,
> > +			   recurse, options);
> 
> This is surprising me a little. Don't you have plain struct types
> that are not dynamic arrays? Right now, the code seems to indicate
> that you don't expect any. Or maybe I missed something?

Look at this again. If we don't have dynamic array we ret -1. In this
case ret == -1 and we jump to default.

[-- Attachment #2: gdb-100113-d.patch --]
[-- Type: application/octet-stream, Size: 26830 bytes --]

gdb/ChangeLog:
	D language support.
	* Makefile.in (SFILES): Add d-lang.c d-valprint.c.
	(COMMON_OBS): Add d-lang.o d-valprint.o.
	(HFILES_NO_SRCDIR): Add d-lang.h.
	* c-lang.c: Make c_emit_char and exp_descriptor_c public.
	* c-lang.h: Add declaration c_emit_char and exp_descriptor_c.
	* d-lang.c: New file.
	* d-lang.h: New file.
	* d-valprint.c: New file.
	* defs.h (enum language): Add language_d.
	* doc/gdb.texinfo: Add mention about D language support.
	* dwarf2read.c (set_cu_language): Add DW_LANG_D.
	* language.c (binop_result_type, integral_type, character_type) 
	(string_type, boolean_type, structured_type): Add language_d.
	* symfile.c (init_filename_language_table): Add language_d.
	* symtab.c Include d-lang.h.
	(symbol_init_language_specific, symbol_find_demangled_name)
	(symbol_natural_name, lookup_symbol_in_language)
	(symbol_demangled_name, symbol_matches_domain): Add language_d.
	* testsuite/gdb.base/default.exp: fix "set language" test.

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 4d3e02a..7acd968 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -641,6 +641,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	charset.c cli-out.c coffread.c coff-pe-read.c \
 	complaints.c completer.c corefile.c \
 	cp-abi.c cp-support.c cp-namespace.c cp-valprint.c \
+	d-lang.c d-valprint.c \
 	cp-name-parser.y \
 	dbxread.c demangle.c dictionary.c disasm.c doublest.c dummy-frame.c \
 	dwarf2expr.c dwarf2loc.c dwarf2read.c dwarf2-frame.c \
@@ -707,7 +708,7 @@ cli-out.h gdb_expat.h breakpoint.h infcall.h obsd-tdep.h gnu-v2-abi.h \
 exec.h m32r-tdep.h osabi.h gdbcore.h solib-som.h \
 i386bsd-nat.h xml-support.h xml-tdesc.h alphabsd-tdep.h gdb_obstack.h \
 ia64-tdep.h ada-lang.h varobj.h frv-tdep.h nto-tdep.h serial.h \
-c-lang.h frame.h event-loop.h block.h cli/cli-setshow.h	\
+c-lang.h d-lang.h frame.h event-loop.h block.h cli/cli-setshow.h	\
 cli/cli-decode.h cli/cli-cmds.h cli/cli-dump.h \
 cli/cli-script.h macrotab.h symtab.h version.h gnulib/wchar.in.h \
 gnulib/string.in.h gnulib/str-two-way.h gnulib/extra/link-warning.h \
@@ -810,7 +811,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	dbxread.o coffread.o coff-pe-read.o \
 	dwarf2read.o mipsread.o stabsread.o corefile.o \
 	dwarf2expr.o dwarf2loc.o dwarf2-frame.o \
-	ada-lang.o c-lang.o f-lang.o objc-lang.o \
+	ada-lang.o c-lang.o d-lang.o f-lang.o objc-lang.o \
 	ada-tasks.o \
 	ui-out.o cli-out.o \
 	varobj.o vec.o wrapper.o \
@@ -820,7 +821,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	sentinel-frame.o \
 	complaints.o typeprint.o \
 	ada-typeprint.o c-typeprint.o f-typeprint.o m2-typeprint.o \
-	ada-valprint.o c-valprint.o cp-valprint.o f-valprint.o m2-valprint.o \
+	ada-valprint.o c-valprint.o cp-valprint.o d-valprint.o f-valprint.o \
+	m2-valprint.o \
 	serial.o mdebugread.o top.o utils.o \
 	ui-file.o \
 	user-regs.o \
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 66a9901..7b7e5da 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -253,7 +253,7 @@ print_wchar (gdb_wint_t w, const gdb_byte *orig, int orig_len,
    string whose delimiter is QUOTER.  Note that that format for printing
    characters and strings is language specific. */
 
-static void
+void
 c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
@@ -1133,7 +1133,7 @@ c_language_arch_info (struct gdbarch *gdbarch,
   lai->bool_type_default = builtin->builtin_int;
 }
 
-static const struct exp_descriptor exp_descriptor_c = 
+const struct exp_descriptor exp_descriptor_c = 
 {
   print_subexp_standard,
   operator_length_standard,
diff --git a/gdb/c-lang.h b/gdb/c-lang.h
index c2c5252..4d23364 100644
--- a/gdb/c-lang.h
+++ b/gdb/c-lang.h
@@ -87,6 +87,10 @@ extern void c_printstr (struct ui_file * stream, struct type *elttype,
 extern void c_language_arch_info (struct gdbarch *gdbarch,
 				  struct language_arch_info *lai);
 
+extern const struct exp_descriptor exp_descriptor_c;
+
+extern void c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter);
+
 /* These are in c-typeprint.c: */
 
 extern void c_type_print_base (struct type *, struct ui_file *, int, int);
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
new file mode 100644
index 0000000..62f40be
--- /dev/null
+++ b/gdb/d-lang.c
@@ -0,0 +1,302 @@
+/* D language support routines for GDB, the GNU debugger.
+
+   Copyright (C) 2005, 2006, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "symtab.h"
+#include "language.h"
+#include "d-lang.h"
+#include "c-lang.h"
+#include "gdb_string.h"
+#include "parser-defs.h"
+
+#include <ctype.h>
+
+static char* out_str;
+static char* out_pos;
+static char* mangled_str;
+
+/* Append string SRC to the end of string OUT_STR.
+   LEN is the length of SRC.  */
+static void
+append_len (char* src, size_t len)
+{
+  int size = out_pos - out_str;
+
+  if (size < 1024) {
+    memcpy (out_pos, src, len);
+    out_pos += len;
+  }
+}
+
+/* Append string SRC to the end of string OUT_STR.  */
+static void
+append (char* src)
+{
+  append_len (src, strlen (src));
+}
+
+/* Extract identifiers from MANGLED_STR and append it to OUT_STR.
+   Return 1 on success or 0 on failure.  */
+static int
+extract_identifiers ()
+{
+  long i = 0;
+
+  while (isdigit (*mangled_str))
+    {
+      i = strtol (mangled_str, &mangled_str, 10);
+      if (i <= 0  && strlen (mangled_str) < i)
+        return 0;
+      append_len (mangled_str, i);
+      mangled_str += i;
+      append (".");
+    }
+  if (*mangled_str == '\0' || i == 0)
+    return 0;
+  out_pos--;
+  return 1;
+}
+
+/* Extract and demangle type from MANGLED_STR and append it to OUT_STR.
+   Return 1 on success or 0 on failure.  */
+static int
+extract_type_info ()
+{
+  if (*mangled_str == '\0')
+    return 0;
+  switch (*mangled_str++)
+    {
+      case 'A': /* dynamic array */
+      case 'G': /* static array */
+      case 'H': /* associative array */
+	if (!extract_type_info ())
+	  return 0;
+	append ("[]");
+	return 1;
+      case 'P': /* pointer */
+	if (!extract_type_info ())
+	  return 0;
+	append ("*");
+	return 1;
+      case 'R': /* reference */
+	if (!extract_type_info ())
+	  return 0;
+	append ("&");
+	return 1;
+      case 'Z': /* return value */
+	return extract_type_info ();
+      case 'J': /* out */
+	append ("out ");
+	return extract_type_info ();
+      case 'K': /* inout */
+	append ("inout ");
+	return extract_type_info ();
+      case 'E': /* enum */
+      case 'T': /* typedef */
+      case 'D': /* delegate */
+      case 'C': /* class */
+      case 'S': /* struct */
+	return extract_identifiers ();
+
+      /* basic types: */
+      case 'n': append ("none"); return 1;
+      case 'v': append ("void"); return 1;
+      case 'g': append ("byte"); return 1;
+      case 'h': append ("ubyte"); return 1;
+      case 's': append ("short"); return 1;
+      case 't': append ("ushort"); return 1;
+      case 'i': append ("int"); return 1;
+      case 'k': append ("uint"); return 1;
+      case 'l': append ("long"); return 1;
+      case 'm': append ("ulong"); return 1;
+      case 'f': append ("float"); return 1;
+      case 'd': append ("double"); return 1;
+      case 'e': append ("real"); return 1;
+
+      /* imaginary and complex: */
+      case 'o': append ("ifloat"); return 1;
+      case 'p': append ("idouble"); return 1;
+      case 'j': append ("ireal"); return 1;
+      case 'q': append ("cfloat"); return 1;
+      case 'r': append ("cdouble"); return 1;
+      case 'c': append ("creal"); return 1;
+
+      /* other types: */
+      case 'b': append ("bit"); return 1;
+      case 'a': append ("char"); return 1;
+      case 'u': append ("wchar"); return 1;
+      case 'w': append ("dchar"); return 1;
+
+      default:
+	append ("unknown");
+	return 1;
+    }
+}
+
+/* Implements the la_demangle language_defn routine for language D.  */
+char *
+d_demangle (const char* symbol, int options)
+{
+  unsigned char is_func = 0;
+  int size;
+
+  mangled_str = (char *) symbol;
+
+  if (mangled_str == NULL)
+    return NULL;
+  else if (strcmp (mangled_str, "_Dmain") == 0)
+    return xstrdup ("D main");
+
+  out_str = xmalloc(1024);
+  out_pos = out_str;
+
+  if (mangled_str[0] == '_' && mangled_str[1] == 'D')
+    {
+      mangled_str += 2;
+      is_func = 1;
+    } else if (mangled_str == strstr (mangled_str, "__Class_"))
+      mangled_str += 8;
+    else if (mangled_str == strstr (mangled_str, "__init_"))
+      mangled_str += 7;
+    else if (mangled_str == strstr (mangled_str, "__vtbl_"))
+      mangled_str += 7;
+    else if (mangled_str == strstr (mangled_str, "__modctor_"))
+      mangled_str += 10;
+    else if (mangled_str == strstr (mangled_str, "__moddtor_"))
+      mangled_str += 10;
+    else if (mangled_str == strstr (mangled_str, "__ModuleInfo_"))
+      mangled_str += 13;
+    else
+      {
+	xfree (out_str);
+	return NULL;
+      }
+  
+  if (!extract_identifiers ())
+    {
+      xfree (out_str);
+      return NULL;
+    }
+
+  append ("(");
+  if (is_func == 1 && *mangled_str == 'F')
+    {
+      mangled_str++;
+      while (*mangled_str != '\0' && *mangled_str != 'Z')
+	{
+	  if (is_func == 1)
+	    is_func++;
+	  else
+	    append (", ");
+	  if (!extract_type_info ())
+	    {
+	      xfree (out_str);
+	      return NULL;
+	   }
+	}
+     }
+  append (")");
+
+  /* Doesn't display the return type, but wouldn't be too hard to do.  */
+
+  size = out_pos - out_str;
+  out_str[size] = 0;
+  out_str = xrealloc (out_str, size + 1);
+  return out_str;
+}
+
+/* Table mapping opcodes into strings for printing operators
+   and precedences of the operators.  */
+static const struct op_print d_op_print_tab[] =
+{
+  {",", BINOP_COMMA, PREC_COMMA, 0},
+  {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
+  {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
+  {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
+  {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
+  {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
+  {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
+  {"==", BINOP_EQUAL, PREC_EQUAL, 0},
+  {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
+  {"<=", BINOP_LEQ, PREC_ORDER, 0},
+  {">=", BINOP_GEQ, PREC_ORDER, 0},
+  {">", BINOP_GTR, PREC_ORDER, 0},
+  {"<", BINOP_LESS, PREC_ORDER, 0},
+  {">>", BINOP_RSH, PREC_SHIFT, 0},
+  {"<<", BINOP_LSH, PREC_SHIFT, 0},
+  {"+", BINOP_ADD, PREC_ADD, 0},
+  {"-", BINOP_SUB, PREC_ADD, 0},
+  {"*", BINOP_MUL, PREC_MUL, 0},
+  {"/", BINOP_DIV, PREC_MUL, 0},
+  {"%", BINOP_REM, PREC_MUL, 0},
+  {"@", BINOP_REPEAT, PREC_REPEAT, 0},
+  {"-", UNOP_NEG, PREC_PREFIX, 0},
+  {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
+  {"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
+  {"*", UNOP_IND, PREC_PREFIX, 0},
+  {"&", UNOP_ADDR, PREC_PREFIX, 0},
+  {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
+  {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
+  {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
+  {NULL, 0, 0, 0}
+};
+
+static const struct language_defn d_language_defn =
+{
+  "d",			/* Language name */
+  language_d,
+  range_check_off,
+  type_check_off,
+  case_sensitive_on,
+  array_row_major,
+  macro_expansion_c,
+  &exp_descriptor_c,
+  c_parse,
+  c_error,
+  null_post_parser,
+  c_printchar,		/* Print a character constant */
+  c_printstr,		/* Function to print string constant */
+  c_emit_char,		/* Print a single char */
+  c_print_type,		/* Print a type using appropriate syntax */
+  c_print_typedef,	/* Print a typedef using appropriate syntax */
+  d_val_print,		/* Print a value using appropriate syntax */
+  c_value_print,	/* Print a top-level value */
+  NULL,			/* Language specific skip_trampoline */
+  "this",		/* name_of_this */
+  basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
+  basic_lookup_transparent_type,/* lookup_transparent_type */
+  d_demangle,		/* Language specific symbol demangler */
+  NULL,			/* Language specific class_name_from_physname */
+  d_op_print_tab,	/* expression operators for printing */
+  1,			/* c-style arrays */
+  0,			/* String lower bound */
+  default_word_break_characters,
+  default_make_symbol_completion_list,
+  c_language_arch_info,
+  default_print_array_index,
+  default_pass_by_reference,
+  c_get_string,
+  LANG_MAGIC
+};
+
+void
+_initialize_d_language (void)
+{
+  add_language (&d_language_defn);
+}
diff --git a/gdb/d-lang.h b/gdb/d-lang.h
new file mode 100644
index 0000000..6af2c66
--- /dev/null
+++ b/gdb/d-lang.h
@@ -0,0 +1,31 @@
+/* D language support definitions for GDB, the GNU debugger.
+
+   Copyright (C) 2005, 2006, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#if !defined (D_LANG_H)
+#define D_LANG_H 1
+
+#include "symtab.h"
+
+extern char* d_demangle (const char* mangled, int options);
+
+extern int d_val_print (struct type *type, const gdb_byte *valaddr,
+			int embedded_offset, CORE_ADDR address,
+			struct ui_file *stream, int recurse,
+			const struct value_print_options *options);
+#endif /* !defined (D_LANG_H) */
diff --git a/gdb/d-valprint.c b/gdb/d-valprint.c
new file mode 100644
index 0000000..67b32b7
--- /dev/null
+++ b/gdb/d-valprint.c
@@ -0,0 +1,91 @@
+/* Support for printing D values for GDB, the GNU debugger.
+
+   Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "gdbcore.h"
+#include "d-lang.h"
+#include "c-lang.h"
+
+/* Assuming that TYPE is a TYPE_CODE_STRUCT, verify that TYPE is
+   a dynamic array, and then print its value to STREAM.  Return
+   the number of string characters printed, or -1 if TYPE is not
+   a dynamic array.  */
+static int
+dynamic_array_type (struct type *type, const gdb_byte *valaddr,
+		    int embedded_offset, CORE_ADDR address,
+		    struct ui_file *stream, int recurse,
+		    const struct value_print_options *options)
+{
+  if (TYPE_NFIELDS (type) == 2
+      && TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_INT
+      && strcmp (TYPE_FIELD_NAME (type, 0), "length") == 0
+      && strcmp (TYPE_FIELD_NAME (type, 1), "ptr") == 0)
+    {
+      CORE_ADDR addr;
+      struct type *elttype;
+      struct type *true_type;
+      struct type *ptr_type;
+      struct type *range_type;
+      const gdb_byte *ptraddr;
+      struct value *val;
+      int length;
+
+      length = unpack_field_as_long (type, valaddr + embedded_offset, 0);
+
+      ptr_type = TYPE_FIELD_TYPE (type, 1);
+      elttype = check_typedef (TYPE_TARGET_TYPE (ptr_type));
+      addr = unpack_pointer (ptr_type,
+			     valaddr + TYPE_FIELD_BITPOS (type, 1) / 8
+			     + embedded_offset);
+      true_type = check_typedef (elttype);
+
+      true_type = lookup_array_range_type (true_type, 0, length - 1);
+      val = value_at (true_type, addr);
+      ptraddr = value_contents (val);
+
+      return d_val_print (true_type, ptraddr, 0, addr, stream, recurse + 1,
+			  options);
+    }
+  return -1;
+}
+
+/* Implements the la_val_print routine for language D.  */
+int
+d_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
+             CORE_ADDR address, struct ui_file *stream, int recurse,
+             const struct value_print_options *options)
+{
+  int ret;
+
+  CHECK_TYPEDEF (type);
+  switch (TYPE_CODE (type))
+    {
+      case TYPE_CODE_STRUCT:
+        ret = dynamic_array_type (type, valaddr, embedded_offset, address,
+				  stream, recurse, options);
+	if (ret != -1)
+	   break;
+      default:
+	ret = c_val_print (type, valaddr, embedded_offset, address, stream,
+			   recurse, options);
+    }
+
+  return ret;
+}
diff --git a/gdb/defs.h b/gdb/defs.h
index 5d251b5..2c14c80 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -188,6 +188,7 @@ enum language
     language_auto,		/* Placeholder for automatic setting */
     language_c,			/* C */
     language_cplus,		/* C++ */
+    language_d,			/* D */
     language_objc,		/* Objective-C */
     language_java,		/* Java */
     language_fortran,		/* Fortran */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 5b78f50..d203649 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -213,6 +213,10 @@ You can use @value{GDBN} to debug programs written in C and C@t{++}.
 For more information, see @ref{Supported Languages,,Supported Languages}.
 For more information, see @ref{C,,C and C++}.
 
+@cindex D
+Support for D is partial.  For information on D, see
+@ref{D,,D}.
+
 @cindex Modula-2
 Support for Modula-2 is partial.  For information on Modula-2, see
 @ref{Modula-2,,Modula-2}.
@@ -10554,6 +10558,9 @@ C source file
 @itemx .c++
 C@t{++} source file
 
+@item .d
+D source file
+
 @item .m
 Objective-C source file
 
@@ -10831,7 +10838,7 @@ being set automatically by @value{GDBN}.
 @node Supported Languages
 @section Supported Languages
 
-@value{GDBN} supports C, C@t{++}, Objective-C, Fortran, Java, Pascal,
+@value{GDBN} supports C, C@t{++}, D, Objective-C, Fortran, Java, Pascal,
 assembly, Modula-2, and Ada.
 @c This is false ...
 Some @value{GDBN} features may be used in expressions regardless of the
@@ -10850,6 +10857,7 @@ language reference or tutorial.
 
 @menu
 * C::                           C and C@t{++}
+* D::                           D
 * Objective-C::                 Objective-C
 * Fortran::                     Fortran
 * Pascal::                      Pascal
@@ -11387,6 +11395,14 @@ In the PowerPC architecture, @value{GDBN} provides a set of pseudo-registers
 to inspect @code{_Decimal128} values stored in floating point registers.
 See @ref{PowerPC,,PowerPC} for more details.
 
+@node D
+@subsection D
+
+@cindex D
+@value{GDBN} can be used to debug programs written in D and compiled with
+GDC, LDC or DMD. Currently @value{GDBN} supports only one D specific
+features - dynamic arrays.
+
 @node Objective-C
 @subsection Objective-C
 
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 7623035..4eafdc5 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -7515,6 +7515,9 @@ set_cu_language (unsigned int lang, struct dwarf2_cu *cu)
     case DW_LANG_C_plus_plus:
       cu->language = language_cplus;
       break;
+    case DW_LANG_D:
+      cu->language = language_d;
+      break;
     case DW_LANG_Fortran77:
     case DW_LANG_Fortran90:
     case DW_LANG_Fortran95:
diff --git a/gdb/language.c b/gdb/language.c
index 3500a97..6aa8f0e 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -486,6 +486,7 @@ binop_result_type (struct value *v1, struct value *v2)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       if (TYPE_CODE (t1) == TYPE_CODE_FLT)
 	return TYPE_CODE (t2) == TYPE_CODE_FLT && l2 > l1 ?
@@ -597,6 +598,7 @@ integral_type (struct type *type)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) != TYPE_CODE_INT) &&
 	(TYPE_CODE (type) != TYPE_CODE_ENUM) ? 0 : 1;
@@ -637,6 +639,7 @@ character_type (struct type *type)
 
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) == TYPE_CODE_INT) &&
 	TYPE_LENGTH (type) == sizeof (char)
@@ -659,6 +662,7 @@ string_type (struct type *type)
 
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       /* C does not have distinct string type. */
       return (0);
@@ -678,6 +682,7 @@ boolean_type (struct type *type)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       /* Might be more cleanly handled by having a
          TYPE_CODE_INT_NOT_BOOL for (the deleted) CHILL and such
@@ -717,6 +722,7 @@ structured_type (struct type *type)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) == TYPE_CODE_STRUCT) ||
 	(TYPE_CODE (type) == TYPE_CODE_UNION) ||
diff --git a/gdb/symfile.c b/gdb/symfile.c
index cee84db..48d23da 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -2534,6 +2534,7 @@ init_filename_language_table (void)
       filename_language_table =
 	xmalloc (fl_table_size * sizeof (*filename_language_table));
       add_filename_language (".c", language_c);
+      add_filename_language (".d", language_d);
       add_filename_language (".C", language_cplus);
       add_filename_language (".cc", language_cplus);
       add_filename_language (".cp", language_cplus);
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 7f5dabd..be6f23a 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -39,6 +39,7 @@
 #include "source.h"
 #include "filenames.h"		/* for FILENAME_CMP */
 #include "objc-lang.h"
+#include "d-lang.h"
 #include "ada-lang.h"
 #include "p-lang.h"
 #include "addrmap.h"
@@ -413,6 +414,7 @@ symbol_init_language_specific (struct general_symbol_info *gsymbol,
 {
   gsymbol->language = language;
   if (gsymbol->language == language_cplus
+      || gsymbol->language == language_d
       || gsymbol->language == language_java
       || gsymbol->language == language_objc)
     {
@@ -516,6 +518,16 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
 	  return demangled;
 	}
     }
+  if (gsymbol->language == language_d
+      || gsymbol->language == language_auto)
+    {
+      demangled = d_demangle(mangled, 0);
+      if (demangled != NULL)
+        {
+          gsymbol->language = language_d;
+          return demangled;
+        }
+    }
   return NULL;
 }
 
@@ -693,6 +705,7 @@ symbol_natural_name (const struct general_symbol_info *gsymbol)
   switch (gsymbol->language)
     {
     case language_cplus:
+    case language_d:
     case language_java:
     case language_objc:
       if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
@@ -718,6 +731,7 @@ symbol_demangled_name (const struct general_symbol_info *gsymbol)
   switch (gsymbol->language)
     {
     case language_cplus:
+    case language_d:
     case language_java:
     case language_objc:
       if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
@@ -1263,7 +1277,7 @@ lookup_symbol_in_language (const char *name, const struct block *block,
 
   modified_name = name;
 
-  /* If we are using C++ or Java, demangle the name before doing a lookup, so
+  /* If we are using C++, D, or Java, demangle the name before doing a lookup, so
      we can always binary search. */
   if (lang == language_cplus)
     {
@@ -1286,6 +1300,16 @@ lookup_symbol_in_language (const char *name, const struct block *block,
 	    }
 	}
     }
+  else if (current_language->la_language == language_d)
+    {
+      demangled_name = d_demangle (name, 0);
+      if (demangled_name)
+	{
+	  mangled_name = name;
+	  modified_name = demangled_name;
+	  make_cleanup (xfree, demangled_name);
+	}
+    }
   else if (lang == language_java)
     {
       demangled_name = cplus_demangle (name,
@@ -1734,6 +1758,7 @@ symbol_matches_domain (enum language symbol_language,
      A Java class declaration also defines a typedef for the class.
      Similarly, any Ada type declaration implicitly defines a typedef.  */
   if (symbol_language == language_cplus
+      || symbol_language == language_d
       || symbol_language == language_java
       || symbol_language == language_ada)
     {
diff --git a/gdb/testsuite/gdb.base/default.exp b/gdb/testsuite/gdb.base/default.exp
index ab7a846..8cb4a5c 100644
--- a/gdb/testsuite/gdb.base/default.exp
+++ b/gdb/testsuite/gdb.base/default.exp
@@ -530,7 +530,7 @@ gdb_test "set history size" "Argument required .integer to set it to.*" "set his
 #test set history
 gdb_test "set history" "\"set history\" must be followed by the name of a history subcommand.(\[^\r\n\]*\[\r\n\])+List of set history subcommands:(\[^\r\n\]*\[\r\n\])+set history expansion -- Set history expansion on command input(\[^\r\n\]*\[\r\n\])+set history filename -- Set the filename in which to record the command history(\[^\r\n\]*\[\r\n\])+set history save -- Set saving of the history record on exit(\[^\r\n\]*\[\r\n\])+set history size -- Set the size of the command history(\[^\r\n\]*\[\r\n\])+Type \"help set history\" followed by set history subcommand name for full documentation.(\[^\r\n\]*\[\r\n\])+Command name abbreviations are allowed if unambiguous." "set history"
 #test set language
-gdb_test "set language" "Requires an argument. Valid arguments are auto, local, unknown, ada, c, c.., asm, minimal, fortran, objective-c, java, modula-2, pascal, scheme." "set language"
+gdb_test "set language" "Requires an argument. Valid arguments are auto, local, unknown, ada, c, c.., asm, minimal, d, fortran, objective-c, java, modula-2, pascal, scheme." "set language"
 #test set listsize
 gdb_test "set listsize" "Argument required .integer to set it to.*" "set listsize"
 #test set print "p" abbreviation

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-01-13  4:42         ` Mihail Zenkov
@ 2010-01-15  5:10           ` Joel Brobecker
  2010-01-15 21:02             ` Tom Tromey
  2010-01-15 21:05           ` Tom Tromey
  1 sibling, 1 reply; 33+ messages in thread
From: Joel Brobecker @ 2010-01-15  5:10 UTC (permalink / raw)
  To: Mihail Zenkov; +Cc: gdb-patches

> It allows to call allocation of memory less often. This way chose John
> Demme. It effective way, when we need allocate many unbounded buffers
> with big size.

Are you sure this is a problem in practice? Have you made some measurement
that string allocation/deallocation for D identifiers are having
a noticeable  performance impact on GDB operations?

> But in ours case we need only on small buffer. 
> I prefer another way - just allocate one buffer with size bigger than
> worst case.

If you can prove that you can never ever exceed that worse case
scenario, then that would be fine, as long as you provide a comment
justifying this hard-coded limitation and how it was computed.
Otherwise, if some code, or some user command can lead to overflow,
however whimsical it might be, then you need to switch to a dynamic
approach.  The GNU Coding Standards explicitly warn against using
abitrary limits.

Which approach you chose is no longer important to me. The suggestions
were meant to be helpful, but it's not a huge amount of code and it's
going to be "your" maintenance problem - if any.

> 	* c-lang.c: Make c_emit_char and exp_descriptor_c public.
> 	* c-lang.h: Add declaration c_emit_char and exp_descriptor_c.

Please change the above to:

        * c-lang.c (c_emit_char, exp_descriptor_c): Make public.
        * c-lang.h (c_emit_char, exp_descriptor_c): Add declaration.

> 	* symtab.c Include d-lang.h.
                ^^^^ missing colon.

> 	* testsuite/gdb.base/default.exp: fix "set language" test.
                                         ^^^ Fix

> +static char* out_str;
> +static char* out_pos;
> +static char* mangled_str;

I prefered it when you had a type, encapsulating the whole bounded
string concept. You can always make it static if you think it helps.

If you are going to use a hard-coded limit, please use a constant
or a macro:

  #define MAX_BLA_BLA_BLA
  struct bounded_string
  {
    char buf[MAX_BLA_BLA_BLA];
    char *buf_pos;
  };

This is important, because I'm seeing "magic" constants in your code,
such as:

> +  if (size < 1024) {
> +    memcpy (out_pos, src, len);
> +    out_pos += len;

A few comments on the code above:

  . Formatting: The '{' should be on the next line.
  . No litteral constant, use MAX_BLA_BLA_BLA.
  . You do nothing when there is an overflow; This is bad, because
    this will at best lead to a mysterious error message, and at worst
    a silent malfunction.  You need to error() out.  If there is no
    valid situation where the overflow should ever happen, then
    it is internal_error() that should be called.

> +static int
> +extract_identifiers ()
                      ^^^^ (void)

> +static int
> +extract_type_info ()
                    ^^^^^ same here

> +  mangled_str = (char *) symbol;

Outch! You are bypassing the "const", preventing potentially useful
compiler warnings. Isn't there a way to avoid this?

> +  out_str = xmalloc(1024);
> +  out_pos = out_str;

If you have a static unbounded_string, you could just allocate it
once, instead of everytime to start demangling (in other words,
declare an array of char instead of a char pointer).

> +    } else if (mangled_str == strstr (mangled_str, "__Class_"))
> +      mangled_str += 8;
> +    else if (mangled_str == strstr (mangled_str, "__init_"))
> +      mangled_str += 7;
> +    else if (mangled_str == strstr (mangled_str, "__vtbl_"))
> +      mangled_str += 7;
> +    else if (mangled_str == strstr (mangled_str, "__modctor_"))
> +      mangled_str += 10;
> +    else if (mangled_str == strstr (mangled_str, "__moddtor_"))
> +      mangled_str += 10;
> +    else if (mangled_str == strstr (mangled_str, "__ModuleInfo_"))
> +      mangled_str += 13;

Use strncmp, it will be more efficient.

> +  c_printchar,		/* Print a character constant */
> +  c_printstr,		/* Function to print string constant */
> +  c_emit_char,		/* Print a single char */
> +  c_print_type,		/* Print a type using appropriate syntax */
> +  c_print_typedef,	/* Print a typedef using appropriate syntax */
> +  d_val_print,		/* Print a value using appropriate syntax */
> +  c_value_print,	/* Print a top-level value */
> +  NULL,			/* Language specific skip_trampoline */
> +  "this",		/* name_of_this */
> +  basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
> +  basic_lookup_transparent_type,/* lookup_transparent_type */
> +  d_demangle,		/* Language specific symbol demangler */
> +  NULL,			/* Language specific class_name_from_physname */
> +  d_op_print_tab,	/* expression operators for printing */
> +  1,			/* c-style arrays */
> +  0,			/* String lower bound */

If you use English-style comments, then you need to start sentences
with a capital letter, and end them with a period.  For instance:

  /* Print a character constant.  */

I haven't double-checked, but I think some of us just put the name
of the struct component in the comment.  That way, someone modifying
the profile of one of these routines could simply grep of that
component name to find implementations of that routine.

> +  else if (current_language->la_language == language_d)
> +    {
> +      demangled_name = d_demangle (name, 0);
> +      if (demangled_name)
> +	{
> +	  mangled_name = name;
> +	  modified_name = demangled_name;
> +	  make_cleanup (xfree, demangled_name);
> +	}
> +    }

Can you move this back to after 'else if (lang == language_java)'?

-- 
Joel

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-01-15  5:10           ` Joel Brobecker
@ 2010-01-15 21:02             ` Tom Tromey
  0 siblings, 0 replies; 33+ messages in thread
From: Tom Tromey @ 2010-01-15 21:02 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: Mihail Zenkov, gdb-patches

>>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:

>> +static char* out_str;
>> +static char* out_pos;
>> +static char* mangled_str;

Joel> I prefered it when you had a type, encapsulating the whole bounded
Joel> string concept. You can always make it static if you think it helps.

Just use an obstack.

We already have plenty of expanding data types -- VEC, obstack,
dyn_string from libiberty.  Unless there is strong proof for a need,
don't introduce a new one or a hand-written one.

>> +  mangled_str = (char *) symbol;

Joel> Outch! You are bypassing the "const", preventing potentially useful
Joel> compiler warnings. Isn't there a way to avoid this?

I looked at this and I don't think there's any need for it.

Tom

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-01-13  4:42         ` Mihail Zenkov
  2010-01-15  5:10           ` Joel Brobecker
@ 2010-01-15 21:05           ` Tom Tromey
  2010-04-14 22:22             ` Mihail Zenkov
  1 sibling, 1 reply; 33+ messages in thread
From: Tom Tromey @ 2010-01-15 21:05 UTC (permalink / raw)
  To: Mihail Zenkov; +Cc: Joel Brobecker, gdb-patches

>>>>> "Mihail" == Mihail Zenkov <mihail.zenkov@gmail.com> writes:

Mihail> +@node D
Mihail> +@subsection D
Mihail> +
Mihail> +@cindex D
Mihail> +@value{GDBN} can be used to debug programs written in D and compiled with
Mihail> +GDC, LDC or DMD. Currently @value{GDBN} supports only one D specific
Mihail> +features - dynamic arrays.

s/features/feature

Mihail> diff --git a/gdb/testsuite/gdb.base/default.exp b/gdb/testsuite/gdb.base/default.exp

It would be nice to have any kind of smoke test for the D support.

Tom

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-01-15 21:05           ` Tom Tromey
@ 2010-04-14 22:22             ` Mihail Zenkov
  2010-04-20 21:39               ` Tom Tromey
  2010-04-23 21:35               ` Robert Clipsham
  0 siblings, 2 replies; 33+ messages in thread
From: Mihail Zenkov @ 2010-04-14 22:22 UTC (permalink / raw)
  To: tromey; +Cc: Mihail Zenkov, Joel Brobecker, gdb-patches

[-- Attachment #1: Type: text/plain, Size: 938 bytes --]

On Fri, 15 Jan 2010 14:04:39 -0700
Tom Tromey <tromey@redhat.com> wrote:

> >>>>> "Mihail" == Mihail Zenkov <mihail.zenkov@gmail.com> writes:
> 
> Mihail> +@node D
> Mihail> +@subsection D
> Mihail> +
> Mihail> +@cindex D
> Mihail> +@value{GDBN} can be used to debug programs written in D and compiled with
> Mihail> +GDC, LDC or DMD. Currently @value{GDBN} supports only one D specific
> Mihail> +features - dynamic arrays.
> 
> s/features/feature
> 
> Mihail> diff --git a/gdb/testsuite/gdb.base/default.exp b/gdb/testsuite/gdb.base/default.exp
> 
> It would be nice to have any kind of smoke test for the D support.
> 
> Tom

Sorry for too very long delay. I fix patch as you and Joel suggested, i hope it ready for inclusion. Also i write second patch for testsuite, it work good with GDC, but fail with DMD and LDC - probably it have some problem/particularity in DWARF implementation. I try do more test and write to their authors.

[-- Attachment #2: gdb-100414-d.patch --]
[-- Type: application/octet-stream, Size: 27045 bytes --]

gdb/ChangeLog:
	D language support.
	* Makefile.in (SFILES): Add d-lang.c d-valprint.c.
	(COMMON_OBS): Add d-lang.o d-valprint.o.
	(HFILES_NO_SRCDIR): Add d-lang.h.
	* c-lang.c (c_emit_char, exp_descriptor_c): Make public.
	* c-lang.h (c_emit_char, exp_descriptor_c): Add declaration.
	* d-lang.c: New file.
	* d-lang.h: New file.
	* d-valprint.c: New file.
	* defs.h (enum language): Add language_d.
	* doc/gdb.texinfo: Add mention about D language support.
	* dwarf2read.c (set_cu_language): Add DW_LANG_D.
	* language.c (binop_result_type, integral_type, character_type) 
	(string_type, boolean_type, structured_type): Add language_d.
	* symfile.c (init_filename_language_table): Add language_d.
	* symtab.c: Include d-lang.h.
	(symbol_init_language_specific, symbol_find_demangled_name)
	(symbol_natural_name, lookup_symbol_in_language)
	(symbol_demangled_name, symbol_matches_domain): Add language_d.
	* testsuite/gdb.base/default.exp: Fix "set language" test.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index b507d3e..f34dcfa 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -654,6 +654,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	charset.c cli-out.c coffread.c coff-pe-read.c \
 	complaints.c completer.c corefile.c \
 	cp-abi.c cp-support.c cp-namespace.c cp-valprint.c \
+	d-lang.c d-valprint.c \
 	cp-name-parser.y \
 	dbxread.c demangle.c dictionary.c disasm.c doublest.c dummy-frame.c \
 	dwarf2expr.c dwarf2loc.c dwarf2read.c dwarf2-frame.c \
@@ -721,7 +722,7 @@ cli-out.h gdb_expat.h breakpoint.h infcall.h obsd-tdep.h \
 exec.h m32r-tdep.h osabi.h gdbcore.h solib-som.h \
 i386bsd-nat.h xml-support.h xml-tdesc.h alphabsd-tdep.h gdb_obstack.h \
 ia64-tdep.h ada-lang.h varobj.h frv-tdep.h nto-tdep.h serial.h \
-c-lang.h frame.h event-loop.h block.h cli/cli-setshow.h	\
+c-lang.h d-lang.h frame.h event-loop.h block.h cli/cli-setshow.h	\
 cli/cli-decode.h cli/cli-cmds.h cli/cli-dump.h \
 cli/cli-script.h macrotab.h symtab.h version.h gnulib/wchar.in.h \
 gnulib/string.in.h gnulib/str-two-way.h gnulib/extra/link-warning.h \
@@ -826,7 +827,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	dbxread.o coffread.o coff-pe-read.o \
 	dwarf2read.o mipsread.o stabsread.o corefile.o \
 	dwarf2expr.o dwarf2loc.o dwarf2-frame.o \
-	ada-lang.o c-lang.o f-lang.o objc-lang.o \
+	ada-lang.o c-lang.o d-lang.o f-lang.o objc-lang.o \
 	ada-tasks.o \
 	ui-out.o cli-out.o \
 	varobj.o vec.o wrapper.o \
@@ -836,7 +837,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	sentinel-frame.o \
 	complaints.o typeprint.o \
 	ada-typeprint.o c-typeprint.o f-typeprint.o m2-typeprint.o \
-	ada-valprint.o c-valprint.o cp-valprint.o f-valprint.o m2-valprint.o \
+	ada-valprint.o c-valprint.o cp-valprint.o d-valprint.o f-valprint.o \
+	m2-valprint.o \
 	serial.o mdebugread.o top.o utils.o \
 	ui-file.o \
 	user-regs.o \
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index fefd675..d28594d 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -253,7 +253,7 @@ print_wchar (gdb_wint_t w, const gdb_byte *orig, int orig_len,
    string whose delimiter is QUOTER.  Note that that format for printing
    characters and strings is language specific. */
 
-static void
+void
 c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
@@ -1135,7 +1135,7 @@ c_language_arch_info (struct gdbarch *gdbarch,
   lai->bool_type_default = builtin->builtin_int;
 }
 
-static const struct exp_descriptor exp_descriptor_c = 
+const struct exp_descriptor exp_descriptor_c = 
 {
   print_subexp_standard,
   operator_length_standard,
diff --git a/gdb/c-lang.h b/gdb/c-lang.h
index 423cee0..404c212 100644
--- a/gdb/c-lang.h
+++ b/gdb/c-lang.h
@@ -87,6 +87,10 @@ extern void c_printstr (struct ui_file * stream, struct type *elttype,
 extern void c_language_arch_info (struct gdbarch *gdbarch,
 				  struct language_arch_info *lai);
 
+extern const struct exp_descriptor exp_descriptor_c;
+
+extern void c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter);
+
 /* These are in c-typeprint.c: */
 
 extern void c_type_print_base (struct type *, struct ui_file *, int, int);
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
new file mode 100644
index 0000000..317e6f9
--- /dev/null
+++ b/gdb/d-lang.c
@@ -0,0 +1,283 @@
+/* D language support routines for GDB, the GNU debugger.
+
+   Copyright (C) 2005, 2006, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "symtab.h"
+#include "language.h"
+#include "d-lang.h"
+#include "c-lang.h"
+#include "gdb_string.h"
+#include "parser-defs.h"
+#include "gdb_obstack.h"
+
+#include <ctype.h>
+
+
+static const char* mangled_str;
+/* Temporary obstack used for holding strings.  */
+static struct obstack tempbuf;
+
+/* Extract identifiers from MANGLED_STR and append it to TEMPBUF.
+   Return 1 on success or 0 on failure.  */
+static int
+extract_identifiers (void)
+{
+  long i = 0;
+
+  while (isdigit (*mangled_str))
+    {
+      i = strtol (mangled_str, NULL, 10);
+      mangled_str++;
+      if (i <= 0  && strlen (mangled_str) < i)
+        return 0;
+      obstack_grow (&tempbuf, mangled_str, i);
+      mangled_str += i;
+      obstack_grow_str (&tempbuf, ".");
+    }
+  if (*mangled_str == '\0' || i == 0)
+    return 0;
+  obstack_blank(&tempbuf, -1);
+  return 1;
+}
+
+/* Extract and demangle type from MANGLED_STR and append it to TEMPBUF.
+   Return 1 on success or 0 on failure.  */
+static int
+extract_type_info (void)
+{
+  if (*mangled_str == '\0')
+    return 0;
+  switch (*mangled_str++)
+    {
+      case 'A': /* dynamic array */
+      case 'G': /* static array */
+      case 'H': /* associative array */
+	if (!extract_type_info ())
+	  return 0;
+	obstack_grow_str (&tempbuf, "[]");
+	return 1;
+      case 'P': /* pointer */
+	if (!extract_type_info ())
+	  return 0;
+	obstack_grow_str (&tempbuf, "*");
+	return 1;
+      case 'R': /* reference */
+	if (!extract_type_info ())
+	  return 0;
+	obstack_grow_str (&tempbuf, "&");
+	return 1;
+      case 'Z': /* return value */
+	return extract_type_info ();
+      case 'J': /* out */
+	obstack_grow_str (&tempbuf, "out ");
+	return extract_type_info ();
+      case 'K': /* inout */
+	obstack_grow_str (&tempbuf, "inout ");
+	return extract_type_info ();
+      case 'E': /* enum */
+      case 'T': /* typedef */
+      case 'D': /* delegate */
+      case 'C': /* class */
+      case 'S': /* struct */
+	return extract_identifiers ();
+
+      /* basic types: */
+      case 'n': obstack_grow_str (&tempbuf, "none"); return 1;
+      case 'v': obstack_grow_str (&tempbuf, "void"); return 1;
+      case 'g': obstack_grow_str (&tempbuf, "byte"); return 1;
+      case 'h': obstack_grow_str (&tempbuf, "ubyte"); return 1;
+      case 's': obstack_grow_str (&tempbuf, "short"); return 1;
+      case 't': obstack_grow_str (&tempbuf, "ushort"); return 1;
+      case 'i': obstack_grow_str (&tempbuf, "int"); return 1;
+      case 'k': obstack_grow_str (&tempbuf, "uint"); return 1;
+      case 'l': obstack_grow_str (&tempbuf, "long"); return 1;
+      case 'm': obstack_grow_str (&tempbuf, "ulong"); return 1;
+      case 'f': obstack_grow_str (&tempbuf, "float"); return 1;
+      case 'd': obstack_grow_str (&tempbuf, "double"); return 1;
+      case 'e': obstack_grow_str (&tempbuf, "real"); return 1;
+
+      /* imaginary and complex: */
+      case 'o': obstack_grow_str (&tempbuf, "ifloat"); return 1;
+      case 'p': obstack_grow_str (&tempbuf, "idouble"); return 1;
+      case 'j': obstack_grow_str (&tempbuf, "ireal"); return 1;
+      case 'q': obstack_grow_str (&tempbuf, "cfloat"); return 1;
+      case 'r': obstack_grow_str (&tempbuf, "cdouble"); return 1;
+      case 'c': obstack_grow_str (&tempbuf, "creal"); return 1;
+
+      /* other types: */
+      case 'b': obstack_grow_str (&tempbuf, "bit"); return 1;
+      case 'a': obstack_grow_str (&tempbuf, "char"); return 1;
+      case 'u': obstack_grow_str (&tempbuf, "wchar"); return 1;
+      case 'w': obstack_grow_str (&tempbuf, "dchar"); return 1;
+
+      default:
+	obstack_grow_str (&tempbuf, "unknown");
+	return 1;
+    }
+}
+
+/* Implements the la_demangle language_defn routine for language D.  */
+char *
+d_demangle (const char* symbol, int options)
+{
+  char* out_str;
+  unsigned char is_func = 0;
+
+  mangled_str = symbol;
+
+  if (mangled_str == NULL)
+    return NULL;
+  else if (strcmp (mangled_str, "_Dmain") == 0)
+    return xstrdup ("D main");
+
+  obstack_init (&tempbuf);
+  
+  if (mangled_str[0] == '_' && mangled_str[1] == 'D')
+    {
+      mangled_str += 2;
+      is_func = 1;
+    } else if (strncmp (mangled_str, "__Class_", 8) == 0)
+      mangled_str += 8;
+    else if (strncmp (mangled_str, "__init_", 7) == 0)
+      mangled_str += 7;
+    else if (strncmp (mangled_str, "__vtbl_", 7) == 0)
+      mangled_str += 7;
+    else if (strncmp (mangled_str, "__modctor_", 10) == 0)
+      mangled_str += 10;
+    else if (strncmp (mangled_str, "__moddtor_", 10) == 0)
+      mangled_str += 10;
+    else if (strncmp (mangled_str, "__ModuleInfo_", 13) == 0)
+      mangled_str += 13;
+    else
+      {
+	obstack_free (&tempbuf, NULL);
+	return NULL;
+      }
+  
+  if (!extract_identifiers ())
+    {
+      obstack_free (&tempbuf, NULL);
+      return NULL;
+    }
+
+  obstack_grow_str (&tempbuf, "(");
+  if (is_func == 1 && *mangled_str == 'F')
+    {
+      mangled_str++;
+      while (*mangled_str != '\0' && *mangled_str != 'Z')
+	{
+	  if (is_func == 1)
+	    is_func++;
+	  else
+	    obstack_grow_str (&tempbuf, ", ");
+	  if (!extract_type_info ())
+	    {
+	      obstack_free (&tempbuf, NULL);
+	      return NULL;
+	   }
+	}
+     }
+  obstack_grow_str0 (&tempbuf, ")");
+
+  /* Doesn't display the return type, but wouldn't be too hard to do.  */
+
+  out_str = xstrdup (obstack_finish (&tempbuf));
+  obstack_free (&tempbuf, NULL);
+  return out_str;
+}
+
+/* Table mapping opcodes into strings for printing operators
+   and precedences of the operators.  */
+static const struct op_print d_op_print_tab[] =
+{
+  {",", BINOP_COMMA, PREC_COMMA, 0},
+  {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
+  {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
+  {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
+  {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
+  {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
+  {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
+  {"==", BINOP_EQUAL, PREC_EQUAL, 0},
+  {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
+  {"<=", BINOP_LEQ, PREC_ORDER, 0},
+  {">=", BINOP_GEQ, PREC_ORDER, 0},
+  {">", BINOP_GTR, PREC_ORDER, 0},
+  {"<", BINOP_LESS, PREC_ORDER, 0},
+  {">>", BINOP_RSH, PREC_SHIFT, 0},
+  {"<<", BINOP_LSH, PREC_SHIFT, 0},
+  {"+", BINOP_ADD, PREC_ADD, 0},
+  {"-", BINOP_SUB, PREC_ADD, 0},
+  {"*", BINOP_MUL, PREC_MUL, 0},
+  {"/", BINOP_DIV, PREC_MUL, 0},
+  {"%", BINOP_REM, PREC_MUL, 0},
+  {"@", BINOP_REPEAT, PREC_REPEAT, 0},
+  {"-", UNOP_NEG, PREC_PREFIX, 0},
+  {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
+  {"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
+  {"*", UNOP_IND, PREC_PREFIX, 0},
+  {"&", UNOP_ADDR, PREC_PREFIX, 0},
+  {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
+  {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
+  {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
+  {NULL, 0, 0, 0}
+};
+
+static const struct language_defn d_language_defn =
+{
+  "d",
+  language_d,
+  range_check_off,
+  type_check_off,
+  case_sensitive_on,
+  array_row_major,
+  macro_expansion_c,
+  &exp_descriptor_c,
+  c_parse,
+  c_error,
+  null_post_parser,
+  c_printchar,			/* Print a character constant.  */
+  c_printstr,			/* Function to print string constant.  */
+  c_emit_char,			/* Print a single char.  */
+  c_print_type,			/* Print a type using appropriate syntax.  */
+  c_print_typedef,		/* Print a typedef using appropriate syntax.  */
+  d_val_print,			/* Print a value using appropriate syntax.  */
+  c_value_print,		/* Print a top-level value.  */
+  NULL,				/* Language specific skip_trampoline.  */
+  "this",
+  basic_lookup_symbol_nonlocal, 
+  basic_lookup_transparent_type,
+  d_demangle,			/* Language specific symbol demangler.  */
+  NULL,				/* Language specific class_name_from_physname.  */
+  d_op_print_tab,		/* Expression operators for printing.  */
+  1,				/* C-style arrays.  */
+  0,				/* String lower bound.  */
+  default_word_break_characters,
+  default_make_symbol_completion_list,
+  c_language_arch_info,
+  default_print_array_index,
+  default_pass_by_reference,
+  c_get_string,
+  LANG_MAGIC
+};
+
+void
+_initialize_d_language (void)
+{
+  add_language (&d_language_defn);
+}
diff --git a/gdb/d-lang.h b/gdb/d-lang.h
new file mode 100644
index 0000000..6af2c66
--- /dev/null
+++ b/gdb/d-lang.h
@@ -0,0 +1,31 @@
+/* D language support definitions for GDB, the GNU debugger.
+
+   Copyright (C) 2005, 2006, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#if !defined (D_LANG_H)
+#define D_LANG_H 1
+
+#include "symtab.h"
+
+extern char* d_demangle (const char* mangled, int options);
+
+extern int d_val_print (struct type *type, const gdb_byte *valaddr,
+			int embedded_offset, CORE_ADDR address,
+			struct ui_file *stream, int recurse,
+			const struct value_print_options *options);
+#endif /* !defined (D_LANG_H) */
diff --git a/gdb/d-valprint.c b/gdb/d-valprint.c
new file mode 100644
index 0000000..67b32b7
--- /dev/null
+++ b/gdb/d-valprint.c
@@ -0,0 +1,91 @@
+/* Support for printing D values for GDB, the GNU debugger.
+
+   Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "gdbcore.h"
+#include "d-lang.h"
+#include "c-lang.h"
+
+/* Assuming that TYPE is a TYPE_CODE_STRUCT, verify that TYPE is
+   a dynamic array, and then print its value to STREAM.  Return
+   the number of string characters printed, or -1 if TYPE is not
+   a dynamic array.  */
+static int
+dynamic_array_type (struct type *type, const gdb_byte *valaddr,
+		    int embedded_offset, CORE_ADDR address,
+		    struct ui_file *stream, int recurse,
+		    const struct value_print_options *options)
+{
+  if (TYPE_NFIELDS (type) == 2
+      && TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_INT
+      && strcmp (TYPE_FIELD_NAME (type, 0), "length") == 0
+      && strcmp (TYPE_FIELD_NAME (type, 1), "ptr") == 0)
+    {
+      CORE_ADDR addr;
+      struct type *elttype;
+      struct type *true_type;
+      struct type *ptr_type;
+      struct type *range_type;
+      const gdb_byte *ptraddr;
+      struct value *val;
+      int length;
+
+      length = unpack_field_as_long (type, valaddr + embedded_offset, 0);
+
+      ptr_type = TYPE_FIELD_TYPE (type, 1);
+      elttype = check_typedef (TYPE_TARGET_TYPE (ptr_type));
+      addr = unpack_pointer (ptr_type,
+			     valaddr + TYPE_FIELD_BITPOS (type, 1) / 8
+			     + embedded_offset);
+      true_type = check_typedef (elttype);
+
+      true_type = lookup_array_range_type (true_type, 0, length - 1);
+      val = value_at (true_type, addr);
+      ptraddr = value_contents (val);
+
+      return d_val_print (true_type, ptraddr, 0, addr, stream, recurse + 1,
+			  options);
+    }
+  return -1;
+}
+
+/* Implements the la_val_print routine for language D.  */
+int
+d_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
+             CORE_ADDR address, struct ui_file *stream, int recurse,
+             const struct value_print_options *options)
+{
+  int ret;
+
+  CHECK_TYPEDEF (type);
+  switch (TYPE_CODE (type))
+    {
+      case TYPE_CODE_STRUCT:
+        ret = dynamic_array_type (type, valaddr, embedded_offset, address,
+				  stream, recurse, options);
+	if (ret != -1)
+	   break;
+      default:
+	ret = c_val_print (type, valaddr, embedded_offset, address, stream,
+			   recurse, options);
+    }
+
+  return ret;
+}
diff --git a/gdb/defs.h b/gdb/defs.h
index e8a1dd4..d4a9b19 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -188,6 +188,7 @@ enum language
     language_auto,		/* Placeholder for automatic setting */
     language_c,			/* C */
     language_cplus,		/* C++ */
+    language_d,			/* D */
     language_objc,		/* Objective-C */
     language_java,		/* Java */
     language_fortran,		/* Fortran */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 887547b..68ba6f3 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -214,6 +214,10 @@ You can use @value{GDBN} to debug programs written in C and C@t{++}.
 For more information, see @ref{Supported Languages,,Supported Languages}.
 For more information, see @ref{C,,C and C++}.
 
+@cindex D
+Support for D is partial.  For information on D, see
+@ref{D,,D}.
+
 @cindex Modula-2
 Support for Modula-2 is partial.  For information on Modula-2, see
 @ref{Modula-2,,Modula-2}.
@@ -10731,6 +10735,9 @@ C source file
 @itemx .c++
 C@t{++} source file
 
+@item .d
+D source file
+
 @item .m
 Objective-C source file
 
@@ -11008,7 +11015,7 @@ being set automatically by @value{GDBN}.
 @node Supported Languages
 @section Supported Languages
 
-@value{GDBN} supports C, C@t{++}, Objective-C, Fortran, Java, Pascal,
+@value{GDBN} supports C, C@t{++}, D, Objective-C, Fortran, Java, Pascal,
 assembly, Modula-2, and Ada.
 @c This is false ...
 Some @value{GDBN} features may be used in expressions regardless of the
@@ -11027,6 +11034,7 @@ language reference or tutorial.
 
 @menu
 * C::                           C and C@t{++}
+* D::                           D
 * Objective-C::                 Objective-C
 * Fortran::                     Fortran
 * Pascal::                      Pascal
@@ -11564,6 +11572,14 @@ In the PowerPC architecture, @value{GDBN} provides a set of pseudo-registers
 to inspect @code{_Decimal128} values stored in floating point registers.
 See @ref{PowerPC,,PowerPC} for more details.
 
+@node D
+@subsection D
+
+@cindex D
+@value{GDBN} can be used to debug programs written in D and compiled with
+GDC, LDC or DMD. Currently @value{GDBN} supports only one D specific
+feature - dynamic arrays.
+
 @node Objective-C
 @subsection Objective-C
 
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 724016f..fba3d58 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -7600,6 +7600,9 @@ set_cu_language (unsigned int lang, struct dwarf2_cu *cu)
     case DW_LANG_C_plus_plus:
       cu->language = language_cplus;
       break;
+    case DW_LANG_D:
+      cu->language = language_d;
+      break;
     case DW_LANG_Fortran77:
     case DW_LANG_Fortran90:
     case DW_LANG_Fortran95:
diff --git a/gdb/language.c b/gdb/language.c
index dcd70b0..aba8a9e 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -486,6 +486,7 @@ binop_result_type (struct value *v1, struct value *v2)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       if (TYPE_CODE (t1) == TYPE_CODE_FLT)
 	return TYPE_CODE (t2) == TYPE_CODE_FLT && l2 > l1 ?
@@ -597,6 +598,7 @@ integral_type (struct type *type)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) != TYPE_CODE_INT) &&
 	(TYPE_CODE (type) != TYPE_CODE_ENUM) ? 0 : 1;
@@ -637,6 +639,7 @@ character_type (struct type *type)
 
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) == TYPE_CODE_INT) &&
 	TYPE_LENGTH (type) == sizeof (char)
@@ -659,6 +662,7 @@ string_type (struct type *type)
 
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       /* C does not have distinct string type. */
       return (0);
@@ -678,6 +682,7 @@ boolean_type (struct type *type)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       /* Might be more cleanly handled by having a
          TYPE_CODE_INT_NOT_BOOL for (the deleted) CHILL and such
@@ -717,6 +722,7 @@ structured_type (struct type *type)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) == TYPE_CODE_STRUCT) ||
 	(TYPE_CODE (type) == TYPE_CODE_UNION) ||
diff --git a/gdb/symfile.c b/gdb/symfile.c
index eda26cc..cf7b41a 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -2618,6 +2618,7 @@ init_filename_language_table (void)
       filename_language_table =
 	xmalloc (fl_table_size * sizeof (*filename_language_table));
       add_filename_language (".c", language_c);
+      add_filename_language (".d", language_d);
       add_filename_language (".C", language_cplus);
       add_filename_language (".cc", language_cplus);
       add_filename_language (".cp", language_cplus);
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 29142da..c2cab96 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -39,6 +39,7 @@
 #include "source.h"
 #include "filenames.h"		/* for FILENAME_CMP */
 #include "objc-lang.h"
+#include "d-lang.h"
 #include "ada-lang.h"
 #include "p-lang.h"
 #include "addrmap.h"
@@ -346,6 +347,7 @@ symbol_init_language_specific (struct general_symbol_info *gsymbol,
 {
   gsymbol->language = language;
   if (gsymbol->language == language_cplus
+      || gsymbol->language == language_d
       || gsymbol->language == language_java
       || gsymbol->language == language_objc)
     {
@@ -449,6 +451,17 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
 	  return demangled;
 	}
     }
+  if (gsymbol->language == language_d
+      || gsymbol->language == language_auto)
+    {
+      demangled =
+	d_demangle(mangled, 0);
+      if (demangled != NULL)
+	{
+	  gsymbol->language = language_d;
+	  return demangled;
+	}
+    }
   return NULL;
 }
 
@@ -626,6 +639,7 @@ symbol_natural_name (const struct general_symbol_info *gsymbol)
   switch (gsymbol->language)
     {
     case language_cplus:
+    case language_d:
     case language_java:
     case language_objc:
       if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
@@ -651,6 +665,7 @@ symbol_demangled_name (const struct general_symbol_info *gsymbol)
   switch (gsymbol->language)
     {
     case language_cplus:
+    case language_d:
     case language_java:
     case language_objc:
       if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
@@ -940,7 +955,7 @@ lookup_symbol_in_language (const char *name, const struct block *block,
 
   modified_name = name;
 
-  /* If we are using C++ or Java, demangle the name before doing a lookup, so
+  /* If we are using C++, D, or Java, demangle the name before doing a lookup, so
      we can always binary search. */
   if (lang == language_cplus)
     {
@@ -972,6 +987,15 @@ lookup_symbol_in_language (const char *name, const struct block *block,
 	  make_cleanup (xfree, demangled_name);
 	}
     }
+  else if (lang == language_d)
+    {
+      demangled_name = d_demangle (name, 0);
+      if (demangled_name)
+	{
+	  modified_name = demangled_name;
+	  make_cleanup (xfree, demangled_name);
+	}
+    }
 
   if (case_sensitivity == case_sensitive_off)
     {
@@ -1412,6 +1436,7 @@ symbol_matches_domain (enum language symbol_language,
      A Java class declaration also defines a typedef for the class.
      Similarly, any Ada type declaration implicitly defines a typedef.  */
   if (symbol_language == language_cplus
+      || symbol_language == language_d
       || symbol_language == language_java
       || symbol_language == language_ada)
     {
diff --git a/gdb/testsuite/gdb.base/default.exp b/gdb/testsuite/gdb.base/default.exp
index 97d5407..2a13007 100644
--- a/gdb/testsuite/gdb.base/default.exp
+++ b/gdb/testsuite/gdb.base/default.exp
@@ -531,7 +531,7 @@ gdb_test "set history size" "Argument required .integer to set it to.*" "set his
 #test set history
 gdb_test "set history" "\"set history\" must be followed by the name of a history subcommand.(\[^\r\n\]*\[\r\n\])+List of set history subcommands:(\[^\r\n\]*\[\r\n\])+set history expansion -- Set history expansion on command input(\[^\r\n\]*\[\r\n\])+set history filename -- Set the filename in which to record the command history(\[^\r\n\]*\[\r\n\])+set history save -- Set saving of the history record on exit(\[^\r\n\]*\[\r\n\])+set history size -- Set the size of the command history(\[^\r\n\]*\[\r\n\])+Type \"help set history\" followed by set history subcommand name for full documentation.(\[^\r\n\]*\[\r\n\])+Command name abbreviations are allowed if unambiguous." "set history"
 #test set language
-gdb_test "set language" "Requires an argument. Valid arguments are auto, local, unknown, ada, c, c.., asm, minimal, fortran, objective-c, java, modula-2, pascal, scheme." "set language"
+gdb_test "set language" "Requires an argument. Valid arguments are auto, local, unknown, ada, c, c.., asm, minimal, d, fortran, objective-c, java, modula-2, pascal, scheme." "set language"
 #test set listsize
 gdb_test "set listsize" "Argument required .integer to set it to.*" "set listsize"
 #test set print "p" abbreviation

[-- Attachment #3: gdb-100414-d_testsuite.patch --]
[-- Type: application/octet-stream, Size: 12246 bytes --]

gdb/testsuite/ChangeLog:
	D language support.
	* configure.ac (AC_OUTPUT): Add gdb.d/Makefile.
	* Makefile.in (ALL_SUBDIRS): Add gdb.d.
	* lib/d.exp: New file.
	* gdb.d/darray.d: New file.
	* gdb.d/darray.exp: New file.
	* gdb.d/main.d: New file.
	* gdb.d/main.exp: New file.
	* gdb.d/Makefile.in: New file.
diff --git a/gdb/testsuite/Makefile.in b/gdb/testsuite/Makefile.in
index 8d8d704..d64f7c0 100644
--- a/gdb/testsuite/Makefile.in
+++ b/gdb/testsuite/Makefile.in
@@ -33,8 +33,8 @@ SHELL = @SHELL@
 EXEEXT = @EXEEXT@
 SUBDIRS = @subdirs@
 RPATH_ENVVAR = @RPATH_ENVVAR@
-ALL_SUBDIRS = gdb.ada gdb.arch gdb.asm gdb.base gdb.cp gdb.disasm \
-	gdb.dwarf2 \
+ALL_SUBDIRS = gdb.ada gdb.arch gdb.asm gdb.base gdb.cp gdb.d \
+	gdb.disasm gdb.dwarf2 \
 	gdb.fortran gdb.server gdb.java gdb.mi gdb.multi \
 	gdb.objc gdb.opt gdb.pascal gdb.python gdb.threads gdb.trace \
 	gdb.xml \
diff --git a/gdb/testsuite/configure.ac b/gdb/testsuite/configure.ac
index c8668e5..22e50e4 100644
--- a/gdb/testsuite/configure.ac
+++ b/gdb/testsuite/configure.ac
@@ -139,9 +139,9 @@ AC_CHECK_HEADERS(pthread.h)
 AC_EXEEXT
 
 AC_OUTPUT([Makefile \
-  gdb.ada/Makefile \
-  gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile \
-  gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile \
+  gdb.ada/Makefile gdb.arch/Makefile gdb.asm/Makefile \
+  gdb.base/Makefile gdb.cp/Makefile gdb.d/Makefile \
+  gdb.disasm/Makefile gdb.dwarf2/Makefile \
   gdb.fortran/Makefile gdb.server/Makefile gdb.java/Makefile \
   gdb.mi/Makefile gdb.modula2/Makefile gdb.multi/Makefile \
   gdb.objc/Makefile gdb.opt/Makefile gdb.pascal/Makefile \
diff --git a/gdb/testsuite/gdb.d/Makefile.in b/gdb/testsuite/gdb.d/Makefile.in
new file mode 100644
index 0000000..16ed52b
--- /dev/null
+++ b/gdb/testsuite/gdb.d/Makefile.in
@@ -0,0 +1,14 @@
+VPATH = @srcdir@
+srcdir = @srcdir@
+
+EXECUTABLES = darray main 
+
+all info install-info dvi install uninstall installcheck check:
+	@echo "Nothing to be done for $@..."
+
+clean mostlyclean:
+	-rm -f *~ *.o *.ci
+	-rm -f core ${EXECUTABLES}
+
+distclean maintainer-clean realclean: clean
+	-rm -f Makefile config.status config.log
diff --git a/gdb/testsuite/gdb.d/darray.d b/gdb/testsuite/gdb.d/darray.d
new file mode 100644
index 0000000..4ecde29
--- /dev/null
+++ b/gdb/testsuite/gdb.d/darray.d
@@ -0,0 +1,38 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2010 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+   */
+
+void
+marker() {}
+
+int 
+main() 
+{
+  int[] a = [0, 1, 2];
+
+  char[] s;
+  s.length = 11;
+  s[] = "Test String";
+
+  char[][] s1 = ["Test 1", "Test 22", "Test 333"];
+
+  marker();
+  return 0;
+} 
+
+
+
diff --git a/gdb/testsuite/gdb.d/darray.exp b/gdb/testsuite/gdb.d/darray.exp
new file mode 100644
index 0000000..7194675
--- /dev/null
+++ b/gdb/testsuite/gdb.d/darray.exp
@@ -0,0 +1,46 @@
+# Copyright 2010 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+load_lib "d.exp"
+
+set testfile "darray"
+set srcfile ${testfile}.d
+set binfile ${objdir}/${subdir}/${testfile}
+
+if {[gdb_compile_d "${srcdir}/${subdir}/${srcfile}" "${binfile}"] != "" } {
+  return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+gdb_test "break marker" \
+         "Breakpoint 1 at .*darray.d.*" \
+
+gdb_test "run" \
+         ".*marker.*" \
+         "going to marker"
+
+gdb_test "next" ".*return 0;"
+
+gdb_test "print a" ".*0, 1, 2.*"
+gdb_test "print s" ".*= \"Test String\""
+gdb_test "print s1" ".*= {\"Test 1\", \"Test 22\", \"Test 333\"}"
diff --git a/gdb/testsuite/gdb.d/main.d b/gdb/testsuite/gdb.d/main.d
new file mode 100644
index 0000000..346fd96
--- /dev/null
+++ b/gdb/testsuite/gdb.d/main.d
@@ -0,0 +1,63 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2010 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+   */
+
+int z;
+
+void
+foo()
+{
+  z = 22;
+}
+
+class CTest
+{
+  int x;
+  static int y;
+  this()
+  {
+    x = 11;
+    y = 3;
+  }
+}
+
+struct STest
+{
+  int x;
+  static int y;
+}
+
+int 
+main() 
+{
+  int i = 1;
+  int[3] a = [0, 1, 2];
+  char[11] s = "Test String";
+
+  foo();
+
+  CTest ct = new CTest;
+
+  STest st;
+  st.x = 2;
+  st.y = 4;
+
+  int *p = null; 
+  *p = 5;
+
+  return 0;
+} 
diff --git a/gdb/testsuite/gdb.d/main.exp b/gdb/testsuite/gdb.d/main.exp
new file mode 100644
index 0000000..1f38bd6
--- /dev/null
+++ b/gdb/testsuite/gdb.d/main.exp
@@ -0,0 +1,62 @@
+# Copyright 2010 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+load_lib "d.exp"
+
+set testfile "main"
+set srcfile ${testfile}.d
+set binfile ${objdir}/${subdir}/${testfile}
+
+if {[gdb_compile_d "${srcdir}/${subdir}/${srcfile}" "${binfile}"] != "" } {
+  return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+gdb_test "break 'D main'" \
+         "Breakpoint 1 at .*main.d.*" \
+
+gdb_test "break foo" \
+         "Breakpoint 2 at .*main.d.*" \
+
+gdb_test "run" \
+         ".*int i = 1;" \
+         "going to 'D main'"
+
+gdb_test "continue" \
+         ".*z = 22;" \
+         "going to foo"
+
+gdb_test "backtrace" \
+	 "#0  foo .*main.d.*#1.*main.*main.d.*"
+
+gdb_test "continue" \
+         ".*p = 5;" \
+         "segmentation fault"
+
+gdb_test "print i" ".* = 1"
+gdb_test "print a" ".*0, 1, 2.*"
+gdb_test "print 'main.z'" ".* = 22"
+gdb_test "print ct" ".*x = 11.*"
+gdb_test "print 'main.CTest.y'" ".* = 3"
+gdb_test "print st" ".*x = 2.*"
+gdb_test "print 'main.STest.y'" ".* = 4"
diff --git a/gdb/testsuite/lib/d.exp b/gdb/testsuite/lib/d.exp
new file mode 100644
index 0000000..f067a93
--- /dev/null
+++ b/gdb/testsuite/lib/d.exp
@@ -0,0 +1,128 @@
+# Copyright 2010 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+load_lib libgloss.exp
+
+set d_init_done 0
+
+# This procedure looks for a suitable D compiler
+# First, environment variable GDC is checked
+# if present, GDC compiler is assumed to be the value of
+# that environment variable.
+# Second, environment variable DMD is checked
+# if present, DMD is assumed to be the value of
+# that environment variable.
+# Third, environment variable LDC is checked
+# if present, LDC is assumed to be the value of
+# that environment variable.
+# Fourth, gdc executable is searched using `which gdc`
+# Fifth, dmd executable is searched using `which dmd`
+# Lastly, ldc executable is searched using `which ldc`
+# Using environment variable allows to force
+# which compiler is used in testsuite.
+ 
+proc d_init {} {
+    global d_init_done
+    global d_compiler_is_gdc
+    global d_compiler_is_dmd
+    global d_compiler_is_ldc
+    global gdc_compiler
+    global dmd_compiler
+    global ldc_compiler
+    global env
+ 
+    if { $d_init_done == 1 } {
+	return
+    }
+
+    set d_compiler_is_gdc 0
+    set d_compiler_is_dmd 0
+    set d_compiler_is_ldc 0
+    set gdc_compiler [transform gdc]
+    set dmd_compiler [transform dmd]
+    set ldc_compiler [transform ldc]
+
+    if ![is_remote host] {
+	if { [info exists env(GDC)] } {
+	    set d_compiler_is_gdc 1
+	    set gdc_compiler $env(GDC)
+	    verbose -log "Assuming GDC ($gdc_compiler)"
+	} elseif { [info exists env(DMD)] } {
+	    set d_compiler_is_dmd 1
+	    set dmd_compiler $env(DMD)
+	    verbose -log "Assuming DMD ($dmd_compiler)"
+	} elseif { [info exists env(LDC)] } {
+	    set d_compiler_is_ldc 1
+	    set ldc_compiler $env(LDC)
+	    verbose -log "Assuming LDC ($ldc_compiler)"
+	} elseif { [which $gdc_compiler] != 0 } {
+	    set d_compiler_is_gdc 1
+	    verbose -log "GDC found"
+        } elseif { [which $dmd_compiler] != 0 } {
+	    set d_compiler_is_dmd 1
+	    verbose -log "DMD found"
+        } elseif { [which $ldc_compiler] != 0 } {
+	    set d_compiler_is_ldc 1
+	    verbose -log "LDC found"
+	}
+    }
+    set d_init_done 1
+}   
+
+proc gdc_compile {source dest} {
+    global gdc_compiler
+    set result [remote_exec host $gdc_compiler "-g3 -O0 $source -o $dest"]
+    return $result
+}
+
+proc dmd_compile {source dest} {
+    global dmd_compiler
+    set result [remote_exec host $dmd_compiler "-gc $source -of$dest"]
+    return $result
+}
+
+proc ldc_compile {source dest} {
+    global ldc_compiler
+    set result [remote_exec host $ldc_compiler "-O0 -g $source -of$dest"]
+    return $result
+}
+
+proc gdb_compile_d {source dest} {
+    global d_init_done
+    global d_compiler_is_gdc
+    global d_compiler_is_dmd
+    global d_compiler_is_ldc
+
+    if { $d_init_done == 0 } { 
+	d_init
+    }
+
+    if { $d_compiler_is_gdc == 1 } {
+        set result [gdc_compile $source $dest]
+    } elseif { $d_compiler_is_dmd == 1 } {
+        set result [dmd_compile $source $dest]
+    } elseif { $d_compiler_is_ldc == 1 } {
+        set result [ldc_compile $source $dest]
+    } else {
+	unsupported "No D compiler found"
+	return "No D compiler. Compilation failed."
+    }
+
+    if ![file exists $dest] {
+        unsupported "D compilation failed: $result"
+        return "D compilation failed."
+    }
+}
+

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-04-14 22:22             ` Mihail Zenkov
@ 2010-04-20 21:39               ` Tom Tromey
  2010-04-21  0:01                 ` Mihail Zenkov
  2010-04-23 21:35               ` Robert Clipsham
  1 sibling, 1 reply; 33+ messages in thread
From: Tom Tromey @ 2010-04-20 21:39 UTC (permalink / raw)
  To: Mihail Zenkov; +Cc: Joel Brobecker, gdb-patches

>>>>> "Mihail" == Mihail Zenkov <mihail.zenkov@gmail.com> writes:

Mihail> Sorry for too very long delay. I fix patch as you and Joel
Mihail> suggested, i hope it ready for inclusion.

It is very close.  In fact, I think I only saw formatting nits.
Thanks for working on this.

I think this needs a NEWS entry.

Mihail> gdb/ChangeLog:
[...]
Mihail> 	* doc/gdb.texinfo: Add mention about D language support.
[...]
Mihail> 	* testsuite/gdb.base/default.exp: Fix "set language" test.

These directories have their own ChangeLog files, so you have to split
up the entry.

Mihail> +extern void c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter);

This wraps past 80 columns, so it should be split after the second comma.

Mihail> +static const char* mangled_str;

GDB style is "const char *mangled_str" -- the "*" is in the wrong place.

Mihail> +  obstack_blank(&tempbuf, -1);

Space before open paren.

Mihail> +    } else if (strncmp (mangled_str, "__Class_", 8) == 0)

Newline before "else".

Mihail> +extern int d_val_print (struct type *type, const gdb_byte *valaddr,
Mihail> +			int embedded_offset, CORE_ADDR address,
Mihail> +			struct ui_file *stream, int recurse,
Mihail> +			const struct value_print_options *options);
Mihail> +#endif /* !defined (D_LANG_H) */

Blank line before the #endif.

thanks,
Tom

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-04-20 21:39               ` Tom Tromey
@ 2010-04-21  0:01                 ` Mihail Zenkov
  2010-04-21 15:57                   ` Joel Brobecker
  0 siblings, 1 reply; 33+ messages in thread
From: Mihail Zenkov @ 2010-04-21  0:01 UTC (permalink / raw)
  To: tromey; +Cc: Mihail Zenkov, Joel Brobecker, gdb-patches

[-- Attachment #1: Type: text/plain, Size: 382 bytes --]

On Tue, 20 Apr 2010 15:39:17 -0600
Tom Tromey <tromey@redhat.com> wrote:

> >>>>> "Mihail" == Mihail Zenkov <mihail.zenkov@gmail.com> writes:
> 
> Mihail> Sorry for too very long delay. I fix patch as you and Joel
> Mihail> suggested, i hope it ready for inclusion.
> 
> It is very close.  In fact, I think I only saw formatting nits.
> Thanks for working on this.
> 
Great, fixed.

[-- Attachment #2: gdb-100421-d.patch --]
[-- Type: application/octet-stream, Size: 27316 bytes --]

gdb/NEWS:
* D language support.
 Support for debugging the D programming language has been
 integrated into GDB.
gdb/ChangeLog:
	D language support.
	* Makefile.in (SFILES): Add d-lang.c d-valprint.c.
	(COMMON_OBS): Add d-lang.o d-valprint.o.
	(HFILES_NO_SRCDIR): Add d-lang.h.
	* c-lang.c (c_emit_char, exp_descriptor_c): Make public.
	* c-lang.h (c_emit_char, exp_descriptor_c): Add declaration.
	* d-lang.c: New file.
	* d-lang.h: New file.
	* d-valprint.c: New file.
	* defs.h (enum language): Add language_d.
	* dwarf2read.c (set_cu_language): Add DW_LANG_D.
	* language.c (binop_result_type, integral_type, character_type) 
	(string_type, boolean_type, structured_type): Add language_d.
	* symfile.c (init_filename_language_table): Add language_d.
	* symtab.c: Include d-lang.h.
	(symbol_init_language_specific, symbol_find_demangled_name)
	(symbol_natural_name, lookup_symbol_in_language)
	(symbol_demangled_name, symbol_matches_domain): Add language_d.
gdb/doc/ChangeLog:
	* gdb.texinfo: Add mention about D language support.
gdb/testsuite/ChangeLog:
	* gdb.base/default.exp: Fix "set language" test.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index fc16fbf..1c5ead2 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -656,6 +656,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	charset.c cli-out.c coffread.c coff-pe-read.c \
 	complaints.c completer.c corefile.c \
 	cp-abi.c cp-support.c cp-namespace.c cp-valprint.c \
+	d-lang.c d-valprint.c \
 	cp-name-parser.y \
 	dbxread.c demangle.c dictionary.c disasm.c doublest.c dummy-frame.c \
 	dwarf2expr.c dwarf2loc.c dwarf2read.c dwarf2-frame.c \
@@ -723,7 +724,7 @@ cli-out.h gdb_expat.h breakpoint.h infcall.h obsd-tdep.h \
 exec.h m32r-tdep.h osabi.h gdbcore.h solib-som.h \
 i386bsd-nat.h xml-support.h xml-tdesc.h alphabsd-tdep.h gdb_obstack.h \
 ia64-tdep.h ada-lang.h varobj.h frv-tdep.h nto-tdep.h serial.h \
-c-lang.h frame.h event-loop.h block.h cli/cli-setshow.h	\
+c-lang.h d-lang.h frame.h event-loop.h block.h cli/cli-setshow.h	\
 cli/cli-decode.h cli/cli-cmds.h cli/cli-dump.h \
 cli/cli-script.h macrotab.h symtab.h version.h gnulib/wchar.in.h \
 gnulib/string.in.h gnulib/str-two-way.h gnulib/extra/link-warning.h \
@@ -828,7 +829,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	dbxread.o coffread.o coff-pe-read.o \
 	dwarf2read.o mipsread.o stabsread.o corefile.o \
 	dwarf2expr.o dwarf2loc.o dwarf2-frame.o \
-	ada-lang.o c-lang.o f-lang.o objc-lang.o \
+	ada-lang.o c-lang.o d-lang.o f-lang.o objc-lang.o \
 	ada-tasks.o \
 	ui-out.o cli-out.o \
 	varobj.o vec.o wrapper.o \
@@ -838,7 +839,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	sentinel-frame.o \
 	complaints.o typeprint.o \
 	ada-typeprint.o c-typeprint.o f-typeprint.o m2-typeprint.o \
-	ada-valprint.o c-valprint.o cp-valprint.o f-valprint.o m2-valprint.o \
+	ada-valprint.o c-valprint.o cp-valprint.o d-valprint.o f-valprint.o \
+	m2-valprint.o \
 	serial.o mdebugread.o top.o utils.o \
 	ui-file.o \
 	user-regs.o \
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index fefd675..825eb4d 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -253,8 +253,9 @@ print_wchar (gdb_wint_t w, const gdb_byte *orig, int orig_len,
    string whose delimiter is QUOTER.  Note that that format for printing
    characters and strings is language specific. */
 
-static void
-c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter)
+void
+c_emit_char (int c, struct type *type,
+	     struct ui_file *stream, int quoter)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
   struct obstack wchar_buf, output;
@@ -1135,7 +1136,7 @@ c_language_arch_info (struct gdbarch *gdbarch,
   lai->bool_type_default = builtin->builtin_int;
 }
 
-static const struct exp_descriptor exp_descriptor_c = 
+const struct exp_descriptor exp_descriptor_c = 
 {
   print_subexp_standard,
   operator_length_standard,
diff --git a/gdb/c-lang.h b/gdb/c-lang.h
index 423cee0..404c212 100644
--- a/gdb/c-lang.h
+++ b/gdb/c-lang.h
@@ -87,6 +87,10 @@ extern void c_printstr (struct ui_file * stream, struct type *elttype,
 extern void c_language_arch_info (struct gdbarch *gdbarch,
 				  struct language_arch_info *lai);
 
+extern const struct exp_descriptor exp_descriptor_c;
+
+extern void c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter);
+
 /* These are in c-typeprint.c: */
 
 extern void c_type_print_base (struct type *, struct ui_file *, int, int);
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
new file mode 100644
index 0000000..1ae27a6
--- /dev/null
+++ b/gdb/d-lang.c
@@ -0,0 +1,284 @@
+/* D language support routines for GDB, the GNU debugger.
+
+   Copyright (C) 2005, 2006, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "symtab.h"
+#include "language.h"
+#include "d-lang.h"
+#include "c-lang.h"
+#include "gdb_string.h"
+#include "parser-defs.h"
+#include "gdb_obstack.h"
+
+#include <ctype.h>
+
+
+static const char *mangled_str;
+/* Temporary obstack used for holding strings.  */
+static struct obstack tempbuf;
+
+/* Extract identifiers from MANGLED_STR and append it to TEMPBUF.
+   Return 1 on success or 0 on failure.  */
+static int
+extract_identifiers (void)
+{
+  long i = 0;
+
+  while (isdigit (*mangled_str))
+    {
+      i = strtol (mangled_str, NULL, 10);
+      mangled_str++;
+      if (i <= 0  && strlen (mangled_str) < i)
+        return 0;
+      obstack_grow (&tempbuf, mangled_str, i);
+      mangled_str += i;
+      obstack_grow_str (&tempbuf, ".");
+    }
+  if (*mangled_str == '\0' || i == 0)
+    return 0;
+  obstack_blank (&tempbuf, -1);
+  return 1;
+}
+
+/* Extract and demangle type from MANGLED_STR and append it to TEMPBUF.
+   Return 1 on success or 0 on failure.  */
+static int
+extract_type_info (void)
+{
+  if (*mangled_str == '\0')
+    return 0;
+  switch (*mangled_str++)
+    {
+      case 'A': /* dynamic array */
+      case 'G': /* static array */
+      case 'H': /* associative array */
+	if (!extract_type_info ())
+	  return 0;
+	obstack_grow_str (&tempbuf, "[]");
+	return 1;
+      case 'P': /* pointer */
+	if (!extract_type_info ())
+	  return 0;
+	obstack_grow_str (&tempbuf, "*");
+	return 1;
+      case 'R': /* reference */
+	if (!extract_type_info ())
+	  return 0;
+	obstack_grow_str (&tempbuf, "&");
+	return 1;
+      case 'Z': /* return value */
+	return extract_type_info ();
+      case 'J': /* out */
+	obstack_grow_str (&tempbuf, "out ");
+	return extract_type_info ();
+      case 'K': /* inout */
+	obstack_grow_str (&tempbuf, "inout ");
+	return extract_type_info ();
+      case 'E': /* enum */
+      case 'T': /* typedef */
+      case 'D': /* delegate */
+      case 'C': /* class */
+      case 'S': /* struct */
+	return extract_identifiers ();
+
+      /* basic types: */
+      case 'n': obstack_grow_str (&tempbuf, "none"); return 1;
+      case 'v': obstack_grow_str (&tempbuf, "void"); return 1;
+      case 'g': obstack_grow_str (&tempbuf, "byte"); return 1;
+      case 'h': obstack_grow_str (&tempbuf, "ubyte"); return 1;
+      case 's': obstack_grow_str (&tempbuf, "short"); return 1;
+      case 't': obstack_grow_str (&tempbuf, "ushort"); return 1;
+      case 'i': obstack_grow_str (&tempbuf, "int"); return 1;
+      case 'k': obstack_grow_str (&tempbuf, "uint"); return 1;
+      case 'l': obstack_grow_str (&tempbuf, "long"); return 1;
+      case 'm': obstack_grow_str (&tempbuf, "ulong"); return 1;
+      case 'f': obstack_grow_str (&tempbuf, "float"); return 1;
+      case 'd': obstack_grow_str (&tempbuf, "double"); return 1;
+      case 'e': obstack_grow_str (&tempbuf, "real"); return 1;
+
+      /* imaginary and complex: */
+      case 'o': obstack_grow_str (&tempbuf, "ifloat"); return 1;
+      case 'p': obstack_grow_str (&tempbuf, "idouble"); return 1;
+      case 'j': obstack_grow_str (&tempbuf, "ireal"); return 1;
+      case 'q': obstack_grow_str (&tempbuf, "cfloat"); return 1;
+      case 'r': obstack_grow_str (&tempbuf, "cdouble"); return 1;
+      case 'c': obstack_grow_str (&tempbuf, "creal"); return 1;
+
+      /* other types: */
+      case 'b': obstack_grow_str (&tempbuf, "bit"); return 1;
+      case 'a': obstack_grow_str (&tempbuf, "char"); return 1;
+      case 'u': obstack_grow_str (&tempbuf, "wchar"); return 1;
+      case 'w': obstack_grow_str (&tempbuf, "dchar"); return 1;
+
+      default:
+	obstack_grow_str (&tempbuf, "unknown");
+	return 1;
+    }
+}
+
+/* Implements the la_demangle language_defn routine for language D.  */
+char *
+d_demangle (const char* symbol, int options)
+{
+  char* out_str;
+  unsigned char is_func = 0;
+
+  mangled_str = symbol;
+
+  if (mangled_str == NULL)
+    return NULL;
+  else if (strcmp (mangled_str, "_Dmain") == 0)
+    return xstrdup ("D main");
+
+  obstack_init (&tempbuf);
+  
+  if (mangled_str[0] == '_' && mangled_str[1] == 'D')
+    {
+      mangled_str += 2;
+      is_func = 1;
+    }
+    else if (strncmp (mangled_str, "__Class_", 8) == 0)
+      mangled_str += 8;
+    else if (strncmp (mangled_str, "__init_", 7) == 0)
+      mangled_str += 7;
+    else if (strncmp (mangled_str, "__vtbl_", 7) == 0)
+      mangled_str += 7;
+    else if (strncmp (mangled_str, "__modctor_", 10) == 0)
+      mangled_str += 10;
+    else if (strncmp (mangled_str, "__moddtor_", 10) == 0)
+      mangled_str += 10;
+    else if (strncmp (mangled_str, "__ModuleInfo_", 13) == 0)
+      mangled_str += 13;
+    else
+      {
+	obstack_free (&tempbuf, NULL);
+	return NULL;
+      }
+  
+  if (!extract_identifiers ())
+    {
+      obstack_free (&tempbuf, NULL);
+      return NULL;
+    }
+
+  obstack_grow_str (&tempbuf, "(");
+  if (is_func == 1 && *mangled_str == 'F')
+    {
+      mangled_str++;
+      while (*mangled_str != '\0' && *mangled_str != 'Z')
+	{
+	  if (is_func == 1)
+	    is_func++;
+	  else
+	    obstack_grow_str (&tempbuf, ", ");
+	  if (!extract_type_info ())
+	    {
+	      obstack_free (&tempbuf, NULL);
+	      return NULL;
+	   }
+	}
+     }
+  obstack_grow_str0 (&tempbuf, ")");
+
+  /* Doesn't display the return type, but wouldn't be too hard to do.  */
+
+  out_str = xstrdup (obstack_finish (&tempbuf));
+  obstack_free (&tempbuf, NULL);
+  return out_str;
+}
+
+/* Table mapping opcodes into strings for printing operators
+   and precedences of the operators.  */
+static const struct op_print d_op_print_tab[] =
+{
+  {",", BINOP_COMMA, PREC_COMMA, 0},
+  {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
+  {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
+  {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
+  {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
+  {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
+  {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
+  {"==", BINOP_EQUAL, PREC_EQUAL, 0},
+  {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
+  {"<=", BINOP_LEQ, PREC_ORDER, 0},
+  {">=", BINOP_GEQ, PREC_ORDER, 0},
+  {">", BINOP_GTR, PREC_ORDER, 0},
+  {"<", BINOP_LESS, PREC_ORDER, 0},
+  {">>", BINOP_RSH, PREC_SHIFT, 0},
+  {"<<", BINOP_LSH, PREC_SHIFT, 0},
+  {"+", BINOP_ADD, PREC_ADD, 0},
+  {"-", BINOP_SUB, PREC_ADD, 0},
+  {"*", BINOP_MUL, PREC_MUL, 0},
+  {"/", BINOP_DIV, PREC_MUL, 0},
+  {"%", BINOP_REM, PREC_MUL, 0},
+  {"@", BINOP_REPEAT, PREC_REPEAT, 0},
+  {"-", UNOP_NEG, PREC_PREFIX, 0},
+  {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
+  {"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
+  {"*", UNOP_IND, PREC_PREFIX, 0},
+  {"&", UNOP_ADDR, PREC_PREFIX, 0},
+  {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
+  {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
+  {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
+  {NULL, 0, 0, 0}
+};
+
+static const struct language_defn d_language_defn =
+{
+  "d",
+  language_d,
+  range_check_off,
+  type_check_off,
+  case_sensitive_on,
+  array_row_major,
+  macro_expansion_c,
+  &exp_descriptor_c,
+  c_parse,
+  c_error,
+  null_post_parser,
+  c_printchar,			/* Print a character constant.  */
+  c_printstr,			/* Function to print string constant.  */
+  c_emit_char,			/* Print a single char.  */
+  c_print_type,			/* Print a type using appropriate syntax.  */
+  c_print_typedef,		/* Print a typedef using appropriate syntax.  */
+  d_val_print,			/* Print a value using appropriate syntax.  */
+  c_value_print,		/* Print a top-level value.  */
+  NULL,				/* Language specific skip_trampoline.  */
+  "this",
+  basic_lookup_symbol_nonlocal, 
+  basic_lookup_transparent_type,
+  d_demangle,			/* Language specific symbol demangler.  */
+  NULL,				/* Language specific class_name_from_physname.  */
+  d_op_print_tab,		/* Expression operators for printing.  */
+  1,				/* C-style arrays.  */
+  0,				/* String lower bound.  */
+  default_word_break_characters,
+  default_make_symbol_completion_list,
+  c_language_arch_info,
+  default_print_array_index,
+  default_pass_by_reference,
+  c_get_string,
+  LANG_MAGIC
+};
+
+void
+_initialize_d_language (void)
+{
+  add_language (&d_language_defn);
+}
diff --git a/gdb/d-lang.h b/gdb/d-lang.h
new file mode 100644
index 0000000..0dee81d
--- /dev/null
+++ b/gdb/d-lang.h
@@ -0,0 +1,32 @@
+/* D language support definitions for GDB, the GNU debugger.
+
+   Copyright (C) 2005, 2006, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#if !defined (D_LANG_H)
+#define D_LANG_H 1
+
+#include "symtab.h"
+
+extern char* d_demangle (const char* mangled, int options);
+
+extern int d_val_print (struct type *type, const gdb_byte *valaddr,
+			int embedded_offset, CORE_ADDR address,
+			struct ui_file *stream, int recurse,
+			const struct value_print_options *options);
+
+#endif /* !defined (D_LANG_H) */
diff --git a/gdb/d-valprint.c b/gdb/d-valprint.c
new file mode 100644
index 0000000..67b32b7
--- /dev/null
+++ b/gdb/d-valprint.c
@@ -0,0 +1,91 @@
+/* Support for printing D values for GDB, the GNU debugger.
+
+   Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "gdbcore.h"
+#include "d-lang.h"
+#include "c-lang.h"
+
+/* Assuming that TYPE is a TYPE_CODE_STRUCT, verify that TYPE is
+   a dynamic array, and then print its value to STREAM.  Return
+   the number of string characters printed, or -1 if TYPE is not
+   a dynamic array.  */
+static int
+dynamic_array_type (struct type *type, const gdb_byte *valaddr,
+		    int embedded_offset, CORE_ADDR address,
+		    struct ui_file *stream, int recurse,
+		    const struct value_print_options *options)
+{
+  if (TYPE_NFIELDS (type) == 2
+      && TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_INT
+      && strcmp (TYPE_FIELD_NAME (type, 0), "length") == 0
+      && strcmp (TYPE_FIELD_NAME (type, 1), "ptr") == 0)
+    {
+      CORE_ADDR addr;
+      struct type *elttype;
+      struct type *true_type;
+      struct type *ptr_type;
+      struct type *range_type;
+      const gdb_byte *ptraddr;
+      struct value *val;
+      int length;
+
+      length = unpack_field_as_long (type, valaddr + embedded_offset, 0);
+
+      ptr_type = TYPE_FIELD_TYPE (type, 1);
+      elttype = check_typedef (TYPE_TARGET_TYPE (ptr_type));
+      addr = unpack_pointer (ptr_type,
+			     valaddr + TYPE_FIELD_BITPOS (type, 1) / 8
+			     + embedded_offset);
+      true_type = check_typedef (elttype);
+
+      true_type = lookup_array_range_type (true_type, 0, length - 1);
+      val = value_at (true_type, addr);
+      ptraddr = value_contents (val);
+
+      return d_val_print (true_type, ptraddr, 0, addr, stream, recurse + 1,
+			  options);
+    }
+  return -1;
+}
+
+/* Implements the la_val_print routine for language D.  */
+int
+d_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
+             CORE_ADDR address, struct ui_file *stream, int recurse,
+             const struct value_print_options *options)
+{
+  int ret;
+
+  CHECK_TYPEDEF (type);
+  switch (TYPE_CODE (type))
+    {
+      case TYPE_CODE_STRUCT:
+        ret = dynamic_array_type (type, valaddr, embedded_offset, address,
+				  stream, recurse, options);
+	if (ret != -1)
+	   break;
+      default:
+	ret = c_val_print (type, valaddr, embedded_offset, address, stream,
+			   recurse, options);
+    }
+
+  return ret;
+}
diff --git a/gdb/defs.h b/gdb/defs.h
index e8a1dd4..d4a9b19 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -188,6 +188,7 @@ enum language
     language_auto,		/* Placeholder for automatic setting */
     language_c,			/* C */
     language_cplus,		/* C++ */
+    language_d,			/* D */
     language_objc,		/* Objective-C */
     language_java,		/* Java */
     language_fortran,		/* Fortran */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 0924430..0fc2d45 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -214,6 +214,10 @@ You can use @value{GDBN} to debug programs written in C and C@t{++}.
 For more information, see @ref{Supported Languages,,Supported Languages}.
 For more information, see @ref{C,,C and C++}.
 
+@cindex D
+Support for D is partial.  For information on D, see
+@ref{D,,D}.
+
 @cindex Modula-2
 Support for Modula-2 is partial.  For information on Modula-2, see
 @ref{Modula-2,,Modula-2}.
@@ -10768,6 +10772,9 @@ C source file
 @itemx .c++
 C@t{++} source file
 
+@item .d
+D source file
+
 @item .m
 Objective-C source file
 
@@ -11045,7 +11052,7 @@ being set automatically by @value{GDBN}.
 @node Supported Languages
 @section Supported Languages
 
-@value{GDBN} supports C, C@t{++}, Objective-C, Fortran, Java, Pascal,
+@value{GDBN} supports C, C@t{++}, D, Objective-C, Fortran, Java, Pascal,
 assembly, Modula-2, and Ada.
 @c This is false ...
 Some @value{GDBN} features may be used in expressions regardless of the
@@ -11064,6 +11071,7 @@ language reference or tutorial.
 
 @menu
 * C::                           C and C@t{++}
+* D::                           D
 * Objective-C::                 Objective-C
 * Fortran::                     Fortran
 * Pascal::                      Pascal
@@ -11601,6 +11609,14 @@ In the PowerPC architecture, @value{GDBN} provides a set of pseudo-registers
 to inspect @code{_Decimal128} values stored in floating point registers.
 See @ref{PowerPC,,PowerPC} for more details.
 
+@node D
+@subsection D
+
+@cindex D
+@value{GDBN} can be used to debug programs written in D and compiled with
+GDC, LDC or DMD. Currently @value{GDBN} supports only one D specific
+feature - dynamic arrays.
+
 @node Objective-C
 @subsection Objective-C
 
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 3096ab7..f4cbc59 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -7619,6 +7619,9 @@ set_cu_language (unsigned int lang, struct dwarf2_cu *cu)
     case DW_LANG_C_plus_plus:
       cu->language = language_cplus;
       break;
+    case DW_LANG_D:
+      cu->language = language_d;
+      break;
     case DW_LANG_Fortran77:
     case DW_LANG_Fortran90:
     case DW_LANG_Fortran95:
diff --git a/gdb/language.c b/gdb/language.c
index dcd70b0..aba8a9e 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -486,6 +486,7 @@ binop_result_type (struct value *v1, struct value *v2)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       if (TYPE_CODE (t1) == TYPE_CODE_FLT)
 	return TYPE_CODE (t2) == TYPE_CODE_FLT && l2 > l1 ?
@@ -597,6 +598,7 @@ integral_type (struct type *type)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) != TYPE_CODE_INT) &&
 	(TYPE_CODE (type) != TYPE_CODE_ENUM) ? 0 : 1;
@@ -637,6 +639,7 @@ character_type (struct type *type)
 
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) == TYPE_CODE_INT) &&
 	TYPE_LENGTH (type) == sizeof (char)
@@ -659,6 +662,7 @@ string_type (struct type *type)
 
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       /* C does not have distinct string type. */
       return (0);
@@ -678,6 +682,7 @@ boolean_type (struct type *type)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       /* Might be more cleanly handled by having a
          TYPE_CODE_INT_NOT_BOOL for (the deleted) CHILL and such
@@ -717,6 +722,7 @@ structured_type (struct type *type)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) == TYPE_CODE_STRUCT) ||
 	(TYPE_CODE (type) == TYPE_CODE_UNION) ||
diff --git a/gdb/symfile.c b/gdb/symfile.c
index eda26cc..cf7b41a 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -2618,6 +2618,7 @@ init_filename_language_table (void)
       filename_language_table =
 	xmalloc (fl_table_size * sizeof (*filename_language_table));
       add_filename_language (".c", language_c);
+      add_filename_language (".d", language_d);
       add_filename_language (".C", language_cplus);
       add_filename_language (".cc", language_cplus);
       add_filename_language (".cp", language_cplus);
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 29142da..c2cab96 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -39,6 +39,7 @@
 #include "source.h"
 #include "filenames.h"		/* for FILENAME_CMP */
 #include "objc-lang.h"
+#include "d-lang.h"
 #include "ada-lang.h"
 #include "p-lang.h"
 #include "addrmap.h"
@@ -346,6 +347,7 @@ symbol_init_language_specific (struct general_symbol_info *gsymbol,
 {
   gsymbol->language = language;
   if (gsymbol->language == language_cplus
+      || gsymbol->language == language_d
       || gsymbol->language == language_java
       || gsymbol->language == language_objc)
     {
@@ -449,6 +451,17 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
 	  return demangled;
 	}
     }
+  if (gsymbol->language == language_d
+      || gsymbol->language == language_auto)
+    {
+      demangled =
+	d_demangle(mangled, 0);
+      if (demangled != NULL)
+	{
+	  gsymbol->language = language_d;
+	  return demangled;
+	}
+    }
   return NULL;
 }
 
@@ -626,6 +639,7 @@ symbol_natural_name (const struct general_symbol_info *gsymbol)
   switch (gsymbol->language)
     {
     case language_cplus:
+    case language_d:
     case language_java:
     case language_objc:
       if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
@@ -651,6 +665,7 @@ symbol_demangled_name (const struct general_symbol_info *gsymbol)
   switch (gsymbol->language)
     {
     case language_cplus:
+    case language_d:
     case language_java:
     case language_objc:
       if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
@@ -940,7 +955,7 @@ lookup_symbol_in_language (const char *name, const struct block *block,
 
   modified_name = name;
 
-  /* If we are using C++ or Java, demangle the name before doing a lookup, so
+  /* If we are using C++, D, or Java, demangle the name before doing a lookup, so
      we can always binary search. */
   if (lang == language_cplus)
     {
@@ -972,6 +987,15 @@ lookup_symbol_in_language (const char *name, const struct block *block,
 	  make_cleanup (xfree, demangled_name);
 	}
     }
+  else if (lang == language_d)
+    {
+      demangled_name = d_demangle (name, 0);
+      if (demangled_name)
+	{
+	  modified_name = demangled_name;
+	  make_cleanup (xfree, demangled_name);
+	}
+    }
 
   if (case_sensitivity == case_sensitive_off)
     {
@@ -1412,6 +1436,7 @@ symbol_matches_domain (enum language symbol_language,
      A Java class declaration also defines a typedef for the class.
      Similarly, any Ada type declaration implicitly defines a typedef.  */
   if (symbol_language == language_cplus
+      || symbol_language == language_d
       || symbol_language == language_java
       || symbol_language == language_ada)
     {
diff --git a/gdb/testsuite/gdb.base/default.exp b/gdb/testsuite/gdb.base/default.exp
index 97d5407..2a13007 100644
--- a/gdb/testsuite/gdb.base/default.exp
+++ b/gdb/testsuite/gdb.base/default.exp
@@ -531,7 +531,7 @@ gdb_test "set history size" "Argument required .integer to set it to.*" "set his
 #test set history
 gdb_test "set history" "\"set history\" must be followed by the name of a history subcommand.(\[^\r\n\]*\[\r\n\])+List of set history subcommands:(\[^\r\n\]*\[\r\n\])+set history expansion -- Set history expansion on command input(\[^\r\n\]*\[\r\n\])+set history filename -- Set the filename in which to record the command history(\[^\r\n\]*\[\r\n\])+set history save -- Set saving of the history record on exit(\[^\r\n\]*\[\r\n\])+set history size -- Set the size of the command history(\[^\r\n\]*\[\r\n\])+Type \"help set history\" followed by set history subcommand name for full documentation.(\[^\r\n\]*\[\r\n\])+Command name abbreviations are allowed if unambiguous." "set history"
 #test set language
-gdb_test "set language" "Requires an argument. Valid arguments are auto, local, unknown, ada, c, c.., asm, minimal, fortran, objective-c, java, modula-2, pascal, scheme." "set language"
+gdb_test "set language" "Requires an argument. Valid arguments are auto, local, unknown, ada, c, c.., asm, minimal, d, fortran, objective-c, java, modula-2, pascal, scheme." "set language"
 #test set listsize
 gdb_test "set listsize" "Argument required .integer to set it to.*" "set listsize"
 #test set print "p" abbreviation

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-04-21  0:01                 ` Mihail Zenkov
@ 2010-04-21 15:57                   ` Joel Brobecker
  2010-04-22  0:11                     ` Mihail Zenkov
  0 siblings, 1 reply; 33+ messages in thread
From: Joel Brobecker @ 2010-04-21 15:57 UTC (permalink / raw)
  To: Mihail Zenkov; +Cc: tromey, gdb-patches

> gdb/ChangeLog:
> 	D language support.
> 	* Makefile.in (SFILES): Add d-lang.c d-valprint.c.
> 	(COMMON_OBS): Add d-lang.o d-valprint.o.
> 	(HFILES_NO_SRCDIR): Add d-lang.h.
> 	* c-lang.c (c_emit_char, exp_descriptor_c): Make public.
> 	* c-lang.h (c_emit_char, exp_descriptor_c): Add declaration.
> 	* d-lang.c: New file.
> 	* d-lang.h: New file.
> 	* d-valprint.c: New file.
> 	* defs.h (enum language): Add language_d.
> 	* dwarf2read.c (set_cu_language): Add DW_LANG_D.
> 	* language.c (binop_result_type, integral_type, character_type) 
> 	(string_type, boolean_type, structured_type): Add language_d.
> 	* symfile.c (init_filename_language_table): Add language_d.
> 	* symtab.c: Include d-lang.h.
> 	(symbol_init_language_specific, symbol_find_demangled_name)
> 	(symbol_natural_name, lookup_symbol_in_language)
> 	(symbol_demangled_name, symbol_matches_domain): Add language_d.
> gdb/doc/ChangeLog:
> 	* gdb.texinfo: Add mention about D language support.
> gdb/testsuite/ChangeLog:
> 	* gdb.base/default.exp: Fix "set language" test.

Overall, looks good to me, but I have a question on a couple of globals
and a few last formatting nits.  We will also need to add an entry in
the NEWS file, but that can be done separately.

> +extern void c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter);

This line exceeds the 78 characters limit - can you split it in two?

> +static const char *mangled_str;

I think this part needs to be rethinked, or at least I don't understand
why this needs to be a global. Can you elaborate?

Similarly, I do not understand why ...
> +/* Temporary obstack used for holding strings.  */
> +static struct obstack tempbuf;
... needs to be a global?

I will not necessarily object to the code being checked in as is;
this is, after all, an implementation detail local to this language,
but if we can look at this, and fix it if applicable, let's do it now.

> +  if (gsymbol->language == language_d
> +      || gsymbol->language == language_auto)
> +    {
> +      demangled =
> +	d_demangle(mangled, 0);

Can you join the last two lines?

-- 
Joel

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-04-21 15:57                   ` Joel Brobecker
@ 2010-04-22  0:11                     ` Mihail Zenkov
  2010-04-22  0:44                       ` Joel Brobecker
  0 siblings, 1 reply; 33+ messages in thread
From: Mihail Zenkov @ 2010-04-22  0:11 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: Mihail Zenkov, tromey, gdb-patches

> > +static const char *mangled_str;
> 
> I think this part needs to be rethinked, or at least I don't understand
> why this needs to be a global. Can you elaborate?
> 
> Similarly, I do not understand why ...
> > +/* Temporary obstack used for holding strings.  */
> > +static struct obstack tempbuf;
> ... needs to be a global?

It not real global. As it static it visibility limited to current file. In this case we can 
think about this file as if it was C++ class. IMHO it more easy readable code - we
promptly see all function use same variables.

I see same code in many other places (c-exp.c:3823, c-exp.c:4192, c-exp.c:4609,
ada-lang.c:307, ada-exp.c:2769 and others).

> > +  if (gsymbol->language == language_d
> > +      || gsymbol->language == language_auto)
> > +    {
> > +      demangled =
> > +	d_demangle(mangled, 0);
> 
> Can you join the last two lines?

Current code:

  if (gsymbol->language == language_objc
      || gsymbol->language == language_auto)
    {
      demangled =
        objc_demangle (mangled, 0);
      if (demangled != NULL)
        {
          gsymbol->language = language_objc;
          return demangled;
        }
    }
  if (gsymbol->language == language_cplus
      || gsymbol->language == language_auto)
    {
      demangled =
        cplus_demangle (mangled, DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE);
      if (demangled != NULL)
        {
          gsymbol->language = language_cplus;
          return demangled;
        }
    }
  if (gsymbol->language == language_java)
    {
      demangled =
        cplus_demangle (mangled,
                        DMGL_PARAMS | DMGL_ANSI | DMGL_JAVA);

Still i should join it?

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-04-22  0:11                     ` Mihail Zenkov
@ 2010-04-22  0:44                       ` Joel Brobecker
  2010-04-22  1:53                         ` Mihail Zenkov
  2010-04-23 18:09                         ` Tom Tromey
  0 siblings, 2 replies; 33+ messages in thread
From: Joel Brobecker @ 2010-04-22  0:44 UTC (permalink / raw)
  To: Mihail Zenkov; +Cc: tromey, gdb-patches

> It not real global. As it static it visibility limited to current
> file. In this case we can think about this file as if it was C++
> class. IMHO it more easy readable code - we promptly see all function
> use same variables.

Although making the variable static limits the damage, I pretty strongly
disagree that having this inter-routine global makes the code more
readable. But, as I said, I don't see this as a blocking problem because
it's localized to an area that I hope will require little attention from
anyone but you; so I am happy to let it go provided that another Global
Maintainer says it's OK - I'll try to remember to ask Tom for his take
on it, if no one else provides an opinion...

> > > +  if (gsymbol->language == language_d
> > > +      || gsymbol->language == language_auto)
> > > +    {
> > > +      demangled =
> > > +	d_demangle(mangled, 0);
[...]
> Still i should join it?

Yes, please. It's not a matter of style for this line. In your case,
the whole statement fits in one line, and thus should be written as
such. For the cases you quoted, it did not, and thus the statement was
split across 2 or more lines...

-- 
Joel

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-04-22  0:44                       ` Joel Brobecker
@ 2010-04-22  1:53                         ` Mihail Zenkov
  2010-04-23 18:11                           ` Tom Tromey
  2010-04-23 18:09                         ` Tom Tromey
  1 sibling, 1 reply; 33+ messages in thread
From: Mihail Zenkov @ 2010-04-22  1:53 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: Mihail Zenkov, tromey, gdb-patches

[-- Attachment #1: Type: text/plain, Size: 476 bytes --]

> > > > +  if (gsymbol->language == language_d
> > > > +      || gsymbol->language == language_auto)
> > > > +    {
> > > > +      demangled =
> > > > +	d_demangle(mangled, 0);
> [...]
> > Still i should join it?
> 
> Yes, please. It's not a matter of style for this line. In your case,
> the whole statement fits in one line, and thus should be written as
> such. For the cases you quoted, it did not, and thus the statement was
> split across 2 or more lines...

OK, fixed.

[-- Attachment #2: gdb-100422-d.patch --]
[-- Type: application/octet-stream, Size: 27314 bytes --]

gdb/NEWS:
* D language support.
 Support for debugging the D programming language has been
 integrated into GDB.
gdb/ChangeLog:
	D language support.
	* Makefile.in (SFILES): Add d-lang.c d-valprint.c.
	(COMMON_OBS): Add d-lang.o d-valprint.o.
	(HFILES_NO_SRCDIR): Add d-lang.h.
	* c-lang.c (c_emit_char, exp_descriptor_c): Make public.
	* c-lang.h (c_emit_char, exp_descriptor_c): Add declaration.
	* d-lang.c: New file.
	* d-lang.h: New file.
	* d-valprint.c: New file.
	* defs.h (enum language): Add language_d.
	* dwarf2read.c (set_cu_language): Add DW_LANG_D.
	* language.c (binop_result_type, integral_type, character_type) 
	(string_type, boolean_type, structured_type): Add language_d.
	* symfile.c (init_filename_language_table): Add language_d.
	* symtab.c: Include d-lang.h.
	(symbol_init_language_specific, symbol_find_demangled_name)
	(symbol_natural_name, lookup_symbol_in_language)
	(symbol_demangled_name, symbol_matches_domain): Add language_d.
gdb/doc/ChangeLog:
	* gdb.texinfo: Add mention about D language support.
gdb/testsuite/ChangeLog:
	* gdb.base/default.exp: Fix "set language" test.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index fc16fbf..1c5ead2 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -656,6 +656,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	charset.c cli-out.c coffread.c coff-pe-read.c \
 	complaints.c completer.c corefile.c \
 	cp-abi.c cp-support.c cp-namespace.c cp-valprint.c \
+	d-lang.c d-valprint.c \
 	cp-name-parser.y \
 	dbxread.c demangle.c dictionary.c disasm.c doublest.c dummy-frame.c \
 	dwarf2expr.c dwarf2loc.c dwarf2read.c dwarf2-frame.c \
@@ -723,7 +724,7 @@ cli-out.h gdb_expat.h breakpoint.h infcall.h obsd-tdep.h \
 exec.h m32r-tdep.h osabi.h gdbcore.h solib-som.h \
 i386bsd-nat.h xml-support.h xml-tdesc.h alphabsd-tdep.h gdb_obstack.h \
 ia64-tdep.h ada-lang.h varobj.h frv-tdep.h nto-tdep.h serial.h \
-c-lang.h frame.h event-loop.h block.h cli/cli-setshow.h	\
+c-lang.h d-lang.h frame.h event-loop.h block.h cli/cli-setshow.h	\
 cli/cli-decode.h cli/cli-cmds.h cli/cli-dump.h \
 cli/cli-script.h macrotab.h symtab.h version.h gnulib/wchar.in.h \
 gnulib/string.in.h gnulib/str-two-way.h gnulib/extra/link-warning.h \
@@ -828,7 +829,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	dbxread.o coffread.o coff-pe-read.o \
 	dwarf2read.o mipsread.o stabsread.o corefile.o \
 	dwarf2expr.o dwarf2loc.o dwarf2-frame.o \
-	ada-lang.o c-lang.o f-lang.o objc-lang.o \
+	ada-lang.o c-lang.o d-lang.o f-lang.o objc-lang.o \
 	ada-tasks.o \
 	ui-out.o cli-out.o \
 	varobj.o vec.o wrapper.o \
@@ -838,7 +839,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	sentinel-frame.o \
 	complaints.o typeprint.o \
 	ada-typeprint.o c-typeprint.o f-typeprint.o m2-typeprint.o \
-	ada-valprint.o c-valprint.o cp-valprint.o f-valprint.o m2-valprint.o \
+	ada-valprint.o c-valprint.o cp-valprint.o d-valprint.o f-valprint.o \
+	m2-valprint.o \
 	serial.o mdebugread.o top.o utils.o \
 	ui-file.o \
 	user-regs.o \
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index fefd675..825eb4d 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -253,8 +253,9 @@ print_wchar (gdb_wint_t w, const gdb_byte *orig, int orig_len,
    string whose delimiter is QUOTER.  Note that that format for printing
    characters and strings is language specific. */
 
-static void
-c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter)
+void
+c_emit_char (int c, struct type *type,
+	     struct ui_file *stream, int quoter)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
   struct obstack wchar_buf, output;
@@ -1135,7 +1136,7 @@ c_language_arch_info (struct gdbarch *gdbarch,
   lai->bool_type_default = builtin->builtin_int;
 }
 
-static const struct exp_descriptor exp_descriptor_c = 
+const struct exp_descriptor exp_descriptor_c = 
 {
   print_subexp_standard,
   operator_length_standard,
diff --git a/gdb/c-lang.h b/gdb/c-lang.h
index 423cee0..404c212 100644
--- a/gdb/c-lang.h
+++ b/gdb/c-lang.h
@@ -87,6 +87,10 @@ extern void c_printstr (struct ui_file * stream, struct type *elttype,
 extern void c_language_arch_info (struct gdbarch *gdbarch,
 				  struct language_arch_info *lai);
 
+extern const struct exp_descriptor exp_descriptor_c;
+
+extern void c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter);
+
 /* These are in c-typeprint.c: */
 
 extern void c_type_print_base (struct type *, struct ui_file *, int, int);
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
new file mode 100644
index 0000000..1ae27a6
--- /dev/null
+++ b/gdb/d-lang.c
@@ -0,0 +1,284 @@
+/* D language support routines for GDB, the GNU debugger.
+
+   Copyright (C) 2005, 2006, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "symtab.h"
+#include "language.h"
+#include "d-lang.h"
+#include "c-lang.h"
+#include "gdb_string.h"
+#include "parser-defs.h"
+#include "gdb_obstack.h"
+
+#include <ctype.h>
+
+
+static const char *mangled_str;
+/* Temporary obstack used for holding strings.  */
+static struct obstack tempbuf;
+
+/* Extract identifiers from MANGLED_STR and append it to TEMPBUF.
+   Return 1 on success or 0 on failure.  */
+static int
+extract_identifiers (void)
+{
+  long i = 0;
+
+  while (isdigit (*mangled_str))
+    {
+      i = strtol (mangled_str, NULL, 10);
+      mangled_str++;
+      if (i <= 0  && strlen (mangled_str) < i)
+        return 0;
+      obstack_grow (&tempbuf, mangled_str, i);
+      mangled_str += i;
+      obstack_grow_str (&tempbuf, ".");
+    }
+  if (*mangled_str == '\0' || i == 0)
+    return 0;
+  obstack_blank (&tempbuf, -1);
+  return 1;
+}
+
+/* Extract and demangle type from MANGLED_STR and append it to TEMPBUF.
+   Return 1 on success or 0 on failure.  */
+static int
+extract_type_info (void)
+{
+  if (*mangled_str == '\0')
+    return 0;
+  switch (*mangled_str++)
+    {
+      case 'A': /* dynamic array */
+      case 'G': /* static array */
+      case 'H': /* associative array */
+	if (!extract_type_info ())
+	  return 0;
+	obstack_grow_str (&tempbuf, "[]");
+	return 1;
+      case 'P': /* pointer */
+	if (!extract_type_info ())
+	  return 0;
+	obstack_grow_str (&tempbuf, "*");
+	return 1;
+      case 'R': /* reference */
+	if (!extract_type_info ())
+	  return 0;
+	obstack_grow_str (&tempbuf, "&");
+	return 1;
+      case 'Z': /* return value */
+	return extract_type_info ();
+      case 'J': /* out */
+	obstack_grow_str (&tempbuf, "out ");
+	return extract_type_info ();
+      case 'K': /* inout */
+	obstack_grow_str (&tempbuf, "inout ");
+	return extract_type_info ();
+      case 'E': /* enum */
+      case 'T': /* typedef */
+      case 'D': /* delegate */
+      case 'C': /* class */
+      case 'S': /* struct */
+	return extract_identifiers ();
+
+      /* basic types: */
+      case 'n': obstack_grow_str (&tempbuf, "none"); return 1;
+      case 'v': obstack_grow_str (&tempbuf, "void"); return 1;
+      case 'g': obstack_grow_str (&tempbuf, "byte"); return 1;
+      case 'h': obstack_grow_str (&tempbuf, "ubyte"); return 1;
+      case 's': obstack_grow_str (&tempbuf, "short"); return 1;
+      case 't': obstack_grow_str (&tempbuf, "ushort"); return 1;
+      case 'i': obstack_grow_str (&tempbuf, "int"); return 1;
+      case 'k': obstack_grow_str (&tempbuf, "uint"); return 1;
+      case 'l': obstack_grow_str (&tempbuf, "long"); return 1;
+      case 'm': obstack_grow_str (&tempbuf, "ulong"); return 1;
+      case 'f': obstack_grow_str (&tempbuf, "float"); return 1;
+      case 'd': obstack_grow_str (&tempbuf, "double"); return 1;
+      case 'e': obstack_grow_str (&tempbuf, "real"); return 1;
+
+      /* imaginary and complex: */
+      case 'o': obstack_grow_str (&tempbuf, "ifloat"); return 1;
+      case 'p': obstack_grow_str (&tempbuf, "idouble"); return 1;
+      case 'j': obstack_grow_str (&tempbuf, "ireal"); return 1;
+      case 'q': obstack_grow_str (&tempbuf, "cfloat"); return 1;
+      case 'r': obstack_grow_str (&tempbuf, "cdouble"); return 1;
+      case 'c': obstack_grow_str (&tempbuf, "creal"); return 1;
+
+      /* other types: */
+      case 'b': obstack_grow_str (&tempbuf, "bit"); return 1;
+      case 'a': obstack_grow_str (&tempbuf, "char"); return 1;
+      case 'u': obstack_grow_str (&tempbuf, "wchar"); return 1;
+      case 'w': obstack_grow_str (&tempbuf, "dchar"); return 1;
+
+      default:
+	obstack_grow_str (&tempbuf, "unknown");
+	return 1;
+    }
+}
+
+/* Implements the la_demangle language_defn routine for language D.  */
+char *
+d_demangle (const char* symbol, int options)
+{
+  char* out_str;
+  unsigned char is_func = 0;
+
+  mangled_str = symbol;
+
+  if (mangled_str == NULL)
+    return NULL;
+  else if (strcmp (mangled_str, "_Dmain") == 0)
+    return xstrdup ("D main");
+
+  obstack_init (&tempbuf);
+  
+  if (mangled_str[0] == '_' && mangled_str[1] == 'D')
+    {
+      mangled_str += 2;
+      is_func = 1;
+    }
+    else if (strncmp (mangled_str, "__Class_", 8) == 0)
+      mangled_str += 8;
+    else if (strncmp (mangled_str, "__init_", 7) == 0)
+      mangled_str += 7;
+    else if (strncmp (mangled_str, "__vtbl_", 7) == 0)
+      mangled_str += 7;
+    else if (strncmp (mangled_str, "__modctor_", 10) == 0)
+      mangled_str += 10;
+    else if (strncmp (mangled_str, "__moddtor_", 10) == 0)
+      mangled_str += 10;
+    else if (strncmp (mangled_str, "__ModuleInfo_", 13) == 0)
+      mangled_str += 13;
+    else
+      {
+	obstack_free (&tempbuf, NULL);
+	return NULL;
+      }
+  
+  if (!extract_identifiers ())
+    {
+      obstack_free (&tempbuf, NULL);
+      return NULL;
+    }
+
+  obstack_grow_str (&tempbuf, "(");
+  if (is_func == 1 && *mangled_str == 'F')
+    {
+      mangled_str++;
+      while (*mangled_str != '\0' && *mangled_str != 'Z')
+	{
+	  if (is_func == 1)
+	    is_func++;
+	  else
+	    obstack_grow_str (&tempbuf, ", ");
+	  if (!extract_type_info ())
+	    {
+	      obstack_free (&tempbuf, NULL);
+	      return NULL;
+	   }
+	}
+     }
+  obstack_grow_str0 (&tempbuf, ")");
+
+  /* Doesn't display the return type, but wouldn't be too hard to do.  */
+
+  out_str = xstrdup (obstack_finish (&tempbuf));
+  obstack_free (&tempbuf, NULL);
+  return out_str;
+}
+
+/* Table mapping opcodes into strings for printing operators
+   and precedences of the operators.  */
+static const struct op_print d_op_print_tab[] =
+{
+  {",", BINOP_COMMA, PREC_COMMA, 0},
+  {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
+  {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
+  {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
+  {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
+  {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
+  {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
+  {"==", BINOP_EQUAL, PREC_EQUAL, 0},
+  {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
+  {"<=", BINOP_LEQ, PREC_ORDER, 0},
+  {">=", BINOP_GEQ, PREC_ORDER, 0},
+  {">", BINOP_GTR, PREC_ORDER, 0},
+  {"<", BINOP_LESS, PREC_ORDER, 0},
+  {">>", BINOP_RSH, PREC_SHIFT, 0},
+  {"<<", BINOP_LSH, PREC_SHIFT, 0},
+  {"+", BINOP_ADD, PREC_ADD, 0},
+  {"-", BINOP_SUB, PREC_ADD, 0},
+  {"*", BINOP_MUL, PREC_MUL, 0},
+  {"/", BINOP_DIV, PREC_MUL, 0},
+  {"%", BINOP_REM, PREC_MUL, 0},
+  {"@", BINOP_REPEAT, PREC_REPEAT, 0},
+  {"-", UNOP_NEG, PREC_PREFIX, 0},
+  {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
+  {"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
+  {"*", UNOP_IND, PREC_PREFIX, 0},
+  {"&", UNOP_ADDR, PREC_PREFIX, 0},
+  {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
+  {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
+  {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
+  {NULL, 0, 0, 0}
+};
+
+static const struct language_defn d_language_defn =
+{
+  "d",
+  language_d,
+  range_check_off,
+  type_check_off,
+  case_sensitive_on,
+  array_row_major,
+  macro_expansion_c,
+  &exp_descriptor_c,
+  c_parse,
+  c_error,
+  null_post_parser,
+  c_printchar,			/* Print a character constant.  */
+  c_printstr,			/* Function to print string constant.  */
+  c_emit_char,			/* Print a single char.  */
+  c_print_type,			/* Print a type using appropriate syntax.  */
+  c_print_typedef,		/* Print a typedef using appropriate syntax.  */
+  d_val_print,			/* Print a value using appropriate syntax.  */
+  c_value_print,		/* Print a top-level value.  */
+  NULL,				/* Language specific skip_trampoline.  */
+  "this",
+  basic_lookup_symbol_nonlocal, 
+  basic_lookup_transparent_type,
+  d_demangle,			/* Language specific symbol demangler.  */
+  NULL,				/* Language specific class_name_from_physname.  */
+  d_op_print_tab,		/* Expression operators for printing.  */
+  1,				/* C-style arrays.  */
+  0,				/* String lower bound.  */
+  default_word_break_characters,
+  default_make_symbol_completion_list,
+  c_language_arch_info,
+  default_print_array_index,
+  default_pass_by_reference,
+  c_get_string,
+  LANG_MAGIC
+};
+
+void
+_initialize_d_language (void)
+{
+  add_language (&d_language_defn);
+}
diff --git a/gdb/d-lang.h b/gdb/d-lang.h
new file mode 100644
index 0000000..0dee81d
--- /dev/null
+++ b/gdb/d-lang.h
@@ -0,0 +1,32 @@
+/* D language support definitions for GDB, the GNU debugger.
+
+   Copyright (C) 2005, 2006, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#if !defined (D_LANG_H)
+#define D_LANG_H 1
+
+#include "symtab.h"
+
+extern char* d_demangle (const char* mangled, int options);
+
+extern int d_val_print (struct type *type, const gdb_byte *valaddr,
+			int embedded_offset, CORE_ADDR address,
+			struct ui_file *stream, int recurse,
+			const struct value_print_options *options);
+
+#endif /* !defined (D_LANG_H) */
diff --git a/gdb/d-valprint.c b/gdb/d-valprint.c
new file mode 100644
index 0000000..67b32b7
--- /dev/null
+++ b/gdb/d-valprint.c
@@ -0,0 +1,91 @@
+/* Support for printing D values for GDB, the GNU debugger.
+
+   Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "gdbcore.h"
+#include "d-lang.h"
+#include "c-lang.h"
+
+/* Assuming that TYPE is a TYPE_CODE_STRUCT, verify that TYPE is
+   a dynamic array, and then print its value to STREAM.  Return
+   the number of string characters printed, or -1 if TYPE is not
+   a dynamic array.  */
+static int
+dynamic_array_type (struct type *type, const gdb_byte *valaddr,
+		    int embedded_offset, CORE_ADDR address,
+		    struct ui_file *stream, int recurse,
+		    const struct value_print_options *options)
+{
+  if (TYPE_NFIELDS (type) == 2
+      && TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_INT
+      && strcmp (TYPE_FIELD_NAME (type, 0), "length") == 0
+      && strcmp (TYPE_FIELD_NAME (type, 1), "ptr") == 0)
+    {
+      CORE_ADDR addr;
+      struct type *elttype;
+      struct type *true_type;
+      struct type *ptr_type;
+      struct type *range_type;
+      const gdb_byte *ptraddr;
+      struct value *val;
+      int length;
+
+      length = unpack_field_as_long (type, valaddr + embedded_offset, 0);
+
+      ptr_type = TYPE_FIELD_TYPE (type, 1);
+      elttype = check_typedef (TYPE_TARGET_TYPE (ptr_type));
+      addr = unpack_pointer (ptr_type,
+			     valaddr + TYPE_FIELD_BITPOS (type, 1) / 8
+			     + embedded_offset);
+      true_type = check_typedef (elttype);
+
+      true_type = lookup_array_range_type (true_type, 0, length - 1);
+      val = value_at (true_type, addr);
+      ptraddr = value_contents (val);
+
+      return d_val_print (true_type, ptraddr, 0, addr, stream, recurse + 1,
+			  options);
+    }
+  return -1;
+}
+
+/* Implements the la_val_print routine for language D.  */
+int
+d_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
+             CORE_ADDR address, struct ui_file *stream, int recurse,
+             const struct value_print_options *options)
+{
+  int ret;
+
+  CHECK_TYPEDEF (type);
+  switch (TYPE_CODE (type))
+    {
+      case TYPE_CODE_STRUCT:
+        ret = dynamic_array_type (type, valaddr, embedded_offset, address,
+				  stream, recurse, options);
+	if (ret != -1)
+	   break;
+      default:
+	ret = c_val_print (type, valaddr, embedded_offset, address, stream,
+			   recurse, options);
+    }
+
+  return ret;
+}
diff --git a/gdb/defs.h b/gdb/defs.h
index e8a1dd4..d4a9b19 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -188,6 +188,7 @@ enum language
     language_auto,		/* Placeholder for automatic setting */
     language_c,			/* C */
     language_cplus,		/* C++ */
+    language_d,			/* D */
     language_objc,		/* Objective-C */
     language_java,		/* Java */
     language_fortran,		/* Fortran */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 97a5531..66a265a 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -214,6 +214,10 @@ You can use @value{GDBN} to debug programs written in C and C@t{++}.
 For more information, see @ref{Supported Languages,,Supported Languages}.
 For more information, see @ref{C,,C and C++}.
 
+@cindex D
+Support for D is partial.  For information on D, see
+@ref{D,,D}.
+
 @cindex Modula-2
 Support for Modula-2 is partial.  For information on Modula-2, see
 @ref{Modula-2,,Modula-2}.
@@ -10776,6 +10780,9 @@ C source file
 @itemx .c++
 C@t{++} source file
 
+@item .d
+D source file
+
 @item .m
 Objective-C source file
 
@@ -11053,7 +11060,7 @@ being set automatically by @value{GDBN}.
 @node Supported Languages
 @section Supported Languages
 
-@value{GDBN} supports C, C@t{++}, Objective-C, Fortran, Java, Pascal,
+@value{GDBN} supports C, C@t{++}, D, Objective-C, Fortran, Java, Pascal,
 assembly, Modula-2, and Ada.
 @c This is false ...
 Some @value{GDBN} features may be used in expressions regardless of the
@@ -11072,6 +11079,7 @@ language reference or tutorial.
 
 @menu
 * C::                           C and C@t{++}
+* D::                           D
 * Objective-C::                 Objective-C
 * Fortran::                     Fortran
 * Pascal::                      Pascal
@@ -11609,6 +11617,14 @@ In the PowerPC architecture, @value{GDBN} provides a set of pseudo-registers
 to inspect @code{_Decimal128} values stored in floating point registers.
 See @ref{PowerPC,,PowerPC} for more details.
 
+@node D
+@subsection D
+
+@cindex D
+@value{GDBN} can be used to debug programs written in D and compiled with
+GDC, LDC or DMD. Currently @value{GDBN} supports only one D specific
+feature - dynamic arrays.
+
 @node Objective-C
 @subsection Objective-C
 
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 3096ab7..f4cbc59 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -7619,6 +7619,9 @@ set_cu_language (unsigned int lang, struct dwarf2_cu *cu)
     case DW_LANG_C_plus_plus:
       cu->language = language_cplus;
       break;
+    case DW_LANG_D:
+      cu->language = language_d;
+      break;
     case DW_LANG_Fortran77:
     case DW_LANG_Fortran90:
     case DW_LANG_Fortran95:
diff --git a/gdb/language.c b/gdb/language.c
index dcd70b0..aba8a9e 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -486,6 +486,7 @@ binop_result_type (struct value *v1, struct value *v2)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       if (TYPE_CODE (t1) == TYPE_CODE_FLT)
 	return TYPE_CODE (t2) == TYPE_CODE_FLT && l2 > l1 ?
@@ -597,6 +598,7 @@ integral_type (struct type *type)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) != TYPE_CODE_INT) &&
 	(TYPE_CODE (type) != TYPE_CODE_ENUM) ? 0 : 1;
@@ -637,6 +639,7 @@ character_type (struct type *type)
 
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) == TYPE_CODE_INT) &&
 	TYPE_LENGTH (type) == sizeof (char)
@@ -659,6 +662,7 @@ string_type (struct type *type)
 
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       /* C does not have distinct string type. */
       return (0);
@@ -678,6 +682,7 @@ boolean_type (struct type *type)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       /* Might be more cleanly handled by having a
          TYPE_CODE_INT_NOT_BOOL for (the deleted) CHILL and such
@@ -717,6 +722,7 @@ structured_type (struct type *type)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) == TYPE_CODE_STRUCT) ||
 	(TYPE_CODE (type) == TYPE_CODE_UNION) ||
diff --git a/gdb/symfile.c b/gdb/symfile.c
index eda26cc..cf7b41a 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -2618,6 +2618,7 @@ init_filename_language_table (void)
       filename_language_table =
 	xmalloc (fl_table_size * sizeof (*filename_language_table));
       add_filename_language (".c", language_c);
+      add_filename_language (".d", language_d);
       add_filename_language (".C", language_cplus);
       add_filename_language (".cc", language_cplus);
       add_filename_language (".cp", language_cplus);
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 29142da..6026c29 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -39,6 +39,7 @@
 #include "source.h"
 #include "filenames.h"		/* for FILENAME_CMP */
 #include "objc-lang.h"
+#include "d-lang.h"
 #include "ada-lang.h"
 #include "p-lang.h"
 #include "addrmap.h"
@@ -346,6 +347,7 @@ symbol_init_language_specific (struct general_symbol_info *gsymbol,
 {
   gsymbol->language = language;
   if (gsymbol->language == language_cplus
+      || gsymbol->language == language_d
       || gsymbol->language == language_java
       || gsymbol->language == language_objc)
     {
@@ -449,6 +451,16 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
 	  return demangled;
 	}
     }
+  if (gsymbol->language == language_d
+      || gsymbol->language == language_auto)
+    {
+      demangled = d_demangle(mangled, 0);
+      if (demangled != NULL)
+	{
+	  gsymbol->language = language_d;
+	  return demangled;
+	}
+    }
   return NULL;
 }
 
@@ -626,6 +638,7 @@ symbol_natural_name (const struct general_symbol_info *gsymbol)
   switch (gsymbol->language)
     {
     case language_cplus:
+    case language_d:
     case language_java:
     case language_objc:
       if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
@@ -651,6 +664,7 @@ symbol_demangled_name (const struct general_symbol_info *gsymbol)
   switch (gsymbol->language)
     {
     case language_cplus:
+    case language_d:
     case language_java:
     case language_objc:
       if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
@@ -940,7 +954,7 @@ lookup_symbol_in_language (const char *name, const struct block *block,
 
   modified_name = name;
 
-  /* If we are using C++ or Java, demangle the name before doing a lookup, so
+  /* If we are using C++, D, or Java, demangle the name before doing a lookup, so
      we can always binary search. */
   if (lang == language_cplus)
     {
@@ -972,6 +986,15 @@ lookup_symbol_in_language (const char *name, const struct block *block,
 	  make_cleanup (xfree, demangled_name);
 	}
     }
+  else if (lang == language_d)
+    {
+      demangled_name = d_demangle (name, 0);
+      if (demangled_name)
+	{
+	  modified_name = demangled_name;
+	  make_cleanup (xfree, demangled_name);
+	}
+    }
 
   if (case_sensitivity == case_sensitive_off)
     {
@@ -1412,6 +1435,7 @@ symbol_matches_domain (enum language symbol_language,
      A Java class declaration also defines a typedef for the class.
      Similarly, any Ada type declaration implicitly defines a typedef.  */
   if (symbol_language == language_cplus
+      || symbol_language == language_d
       || symbol_language == language_java
       || symbol_language == language_ada)
     {
diff --git a/gdb/testsuite/gdb.base/default.exp b/gdb/testsuite/gdb.base/default.exp
index 97d5407..2a13007 100644
--- a/gdb/testsuite/gdb.base/default.exp
+++ b/gdb/testsuite/gdb.base/default.exp
@@ -531,7 +531,7 @@ gdb_test "set history size" "Argument required .integer to set it to.*" "set his
 #test set history
 gdb_test "set history" "\"set history\" must be followed by the name of a history subcommand.(\[^\r\n\]*\[\r\n\])+List of set history subcommands:(\[^\r\n\]*\[\r\n\])+set history expansion -- Set history expansion on command input(\[^\r\n\]*\[\r\n\])+set history filename -- Set the filename in which to record the command history(\[^\r\n\]*\[\r\n\])+set history save -- Set saving of the history record on exit(\[^\r\n\]*\[\r\n\])+set history size -- Set the size of the command history(\[^\r\n\]*\[\r\n\])+Type \"help set history\" followed by set history subcommand name for full documentation.(\[^\r\n\]*\[\r\n\])+Command name abbreviations are allowed if unambiguous." "set history"
 #test set language
-gdb_test "set language" "Requires an argument. Valid arguments are auto, local, unknown, ada, c, c.., asm, minimal, fortran, objective-c, java, modula-2, pascal, scheme." "set language"
+gdb_test "set language" "Requires an argument. Valid arguments are auto, local, unknown, ada, c, c.., asm, minimal, d, fortran, objective-c, java, modula-2, pascal, scheme." "set language"
 #test set listsize
 gdb_test "set listsize" "Argument required .integer to set it to.*" "set listsize"
 #test set print "p" abbreviation

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-04-22  0:44                       ` Joel Brobecker
  2010-04-22  1:53                         ` Mihail Zenkov
@ 2010-04-23 18:09                         ` Tom Tromey
  2010-04-23 20:15                           ` Leandro Lucarella
  1 sibling, 1 reply; 33+ messages in thread
From: Tom Tromey @ 2010-04-23 18:09 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: Mihail Zenkov, gdb-patches

>>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:

Joel> Although making the variable static limits the damage, I pretty strongly
Joel> disagree that having this inter-routine global makes the code more
Joel> readable. But, as I said, I don't see this as a blocking problem because
Joel> it's localized to an area that I hope will require little attention from
Joel> anyone but you; so I am happy to let it go provided that another Global
Joel> Maintainer says it's OK - I'll try to remember to ask Tom for his take
Joel> on it, if no one else provides an opinion...

I took another look at it.

I agree with Joel.  In this case, the variables in question could easily
be replaced with function arguments.

I realize this means adding a bunch of "*"s all over the place, which is
kind of ugly.  But the flip side is that globals make functions more
difficult to understand in isolation.

I also realize that this sort of thing appears elsewhere.  I'd rather we
not emulate bad decisions in new code, though.

I saw a couple more style nits too, more in the next note.

Tom

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-04-22  1:53                         ` Mihail Zenkov
@ 2010-04-23 18:11                           ` Tom Tromey
  2010-04-24  0:06                             ` Mihail Zenkov
  0 siblings, 1 reply; 33+ messages in thread
From: Tom Tromey @ 2010-04-23 18:11 UTC (permalink / raw)
  To: Mihail Zenkov; +Cc: Joel Brobecker, gdb-patches

>>>>> "Mihail" == Mihail Zenkov <mihail.zenkov@gmail.com> writes:

Style nits...

Mihail> +extern void c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter);

Must split this line.

Mihail> +d_demangle (const char* symbol, int options)

"char *", not "char* ".

Mihail> +  if (mangled_str[0] == '_' && mangled_str[1] == 'D')
Mihail> +    {
Mihail> +      mangled_str += 2;
Mihail> +      is_func = 1;
Mihail> +    }
Mihail> +    else if (strncmp (mangled_str, "__Class_", 8) == 0)
Mihail> +      mangled_str += 8;
Mihail> +    else if (strncmp (mangled_str, "__init_", 7) == 0)
Mihail> +      mangled_str += 7;

All the "else if"s are indented too far.

Tom

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-04-23 18:09                         ` Tom Tromey
@ 2010-04-23 20:15                           ` Leandro Lucarella
  2010-04-23 20:37                             ` Tom Tromey
  0 siblings, 1 reply; 33+ messages in thread
From: Leandro Lucarella @ 2010-04-23 20:15 UTC (permalink / raw)
  To: gdb-patches

Tom Tromey, el 23 de abril a las 12:09 me escribiste:
> >>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:
> 
> Joel> Although making the variable static limits the damage, I pretty strongly
> Joel> disagree that having this inter-routine global makes the code more
> Joel> readable. But, as I said, I don't see this as a blocking problem because
> Joel> it's localized to an area that I hope will require little attention from
> Joel> anyone but you; so I am happy to let it go provided that another Global
> Joel> Maintainer says it's OK - I'll try to remember to ask Tom for his take
> Joel> on it, if no one else provides an opinion...
> 
> I took another look at it.
> 
> I agree with Joel.  In this case, the variables in question could easily
> be replaced with function arguments.
> 
> I realize this means adding a bunch of "*"s all over the place, which is
> kind of ugly.  But the flip side is that globals make functions more
> difficult to understand in isolation.
> 
> I also realize that this sort of thing appears elsewhere.  I'd rather we
> not emulate bad decisions in new code, though.
> 
> I saw a couple more style nits too, more in the next note.

Is the indent program invoked with -gnu option enough to fix the style
nits or GDB has its own rules? It might save some time to everybody =)

Thanks to all the people involved in the patch review process BTW.

-- 
Leandro Lucarella (AKA luca)                     http://llucax.com.ar/
----------------------------------------------------------------------
GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)
----------------------------------------------------------------------
El amor es como una reina ortopédica.
	-- Poroto

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-04-23 20:15                           ` Leandro Lucarella
@ 2010-04-23 20:37                             ` Tom Tromey
  2010-04-26 23:51                               ` Stan Shebs
  0 siblings, 1 reply; 33+ messages in thread
From: Tom Tromey @ 2010-04-23 20:37 UTC (permalink / raw)
  To: Leandro Lucarella; +Cc: gdb-patches

>>>>> "Leandro" == Leandro Lucarella <llucax@gmail.com> writes:

Leandro> Is the indent program invoked with -gnu option enough to fix the style
Leandro> nits or GDB has its own rules? It might save some time to everybody =)

Weirdly, indent -gnu doesn't really use the GNU style.
It is a sort of approximation.

We have a gdb_indent.sh in the tree, and I think it was used at one
point, but in the end I think it was abandoned.  I think sometimes it
did the wrong thing.

We do spend an inordinate amount of time on something that, ideally,
should be done by a machine.

Tom

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-04-14 22:22             ` Mihail Zenkov
  2010-04-20 21:39               ` Tom Tromey
@ 2010-04-23 21:35               ` Robert Clipsham
  2010-04-24  0:26                 ` Mihail Zenkov
  1 sibling, 1 reply; 33+ messages in thread
From: Robert Clipsham @ 2010-04-23 21:35 UTC (permalink / raw)
  To: gdb-patches

On 14/04/10 23:21, Mihail Zenkov wrote:
> Sorry for too very long delay. I fix patch as you and Joel suggested,
> i hope it ready for inclusion. Also i write second patch for
> testsuite, it work good with GDC, but fail with DMD and LDC -
> probably it have some problem/particularity in DWARF implementation.
> I try do more test and write to their authors.

Can you give an instance of where dmd is failing to produce the 
expected/correct debug info? I wrote several patches to improve dmd's 
debug info which are sitting in bugzilla waiting to be included... If 
you can find somewhere where dmd isn't playing nicely I can help get it 
working :)

Robert

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-04-23 18:11                           ` Tom Tromey
@ 2010-04-24  0:06                             ` Mihail Zenkov
  2010-04-27 16:05                               ` Joel Brobecker
  0 siblings, 1 reply; 33+ messages in thread
From: Mihail Zenkov @ 2010-04-24  0:06 UTC (permalink / raw)
  To: tromey; +Cc: Mihail Zenkov, Joel Brobecker, gdb-patches

[-- Attachment #1: Type: text/plain, Size: 169 bytes --]

On Fri, 23 Apr 2010 12:10:33 -0600
Tom Tromey <tromey@redhat.com> wrote:

> >>>>> "Mihail" == Mihail Zenkov <mihail.zenkov@gmail.com> writes:
> 
> Style nits...

Fixed.

[-- Attachment #2: gdb-100424-d.patch --]
[-- Type: application/octet-stream, Size: 27422 bytes --]

gdb/NEWS:
* D language support.
 Support for debugging the D programming language has been
 integrated into GDB.
gdb/ChangeLog:
	D language support.
	* Makefile.in (SFILES): Add d-lang.c d-valprint.c.
	(COMMON_OBS): Add d-lang.o d-valprint.o.
	(HFILES_NO_SRCDIR): Add d-lang.h.
	* c-lang.c (c_emit_char, exp_descriptor_c): Make public.
	* c-lang.h (c_emit_char, exp_descriptor_c): Add declaration.
	* d-lang.c: New file.
	* d-lang.h: New file.
	* d-valprint.c: New file.
	* defs.h (enum language): Add language_d.
	* dwarf2read.c (set_cu_language): Add DW_LANG_D.
	* language.c (binop_result_type, integral_type, character_type) 
	(string_type, boolean_type, structured_type): Add language_d.
	* symfile.c (init_filename_language_table): Add language_d.
	* symtab.c: Include d-lang.h.
	(symbol_init_language_specific, symbol_find_demangled_name)
	(symbol_natural_name, lookup_symbol_in_language)
	(symbol_demangled_name, symbol_matches_domain): Add language_d.
gdb/doc/ChangeLog:
	* gdb.texinfo: Add mention about D language support.
gdb/testsuite/ChangeLog:
	* gdb.base/default.exp: Fix "set language" test.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index d62dc63..d19c74d 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -658,6 +658,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	charset.c cli-out.c coffread.c coff-pe-read.c \
 	complaints.c completer.c corefile.c \
 	cp-abi.c cp-support.c cp-namespace.c cp-valprint.c \
+	d-lang.c d-valprint.c \
 	cp-name-parser.y \
 	dbxread.c demangle.c dictionary.c disasm.c doublest.c dummy-frame.c \
 	dwarf2expr.c dwarf2loc.c dwarf2read.c dwarf2-frame.c \
@@ -725,7 +726,7 @@ cli-out.h gdb_expat.h breakpoint.h infcall.h obsd-tdep.h \
 exec.h m32r-tdep.h osabi.h gdbcore.h solib-som.h \
 i386bsd-nat.h xml-support.h xml-tdesc.h alphabsd-tdep.h gdb_obstack.h \
 ia64-tdep.h ada-lang.h varobj.h frv-tdep.h nto-tdep.h serial.h \
-c-lang.h frame.h event-loop.h block.h cli/cli-setshow.h	\
+c-lang.h d-lang.h frame.h event-loop.h block.h cli/cli-setshow.h	\
 cli/cli-decode.h cli/cli-cmds.h cli/cli-dump.h \
 cli/cli-script.h macrotab.h symtab.h version.h gnulib/wchar.in.h \
 gnulib/string.in.h gnulib/str-two-way.h gnulib/extra/link-warning.h \
@@ -830,7 +831,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	dbxread.o coffread.o coff-pe-read.o \
 	dwarf2read.o mipsread.o stabsread.o corefile.o \
 	dwarf2expr.o dwarf2loc.o dwarf2-frame.o \
-	ada-lang.o c-lang.o f-lang.o objc-lang.o \
+	ada-lang.o c-lang.o d-lang.o f-lang.o objc-lang.o \
 	ada-tasks.o \
 	ui-out.o cli-out.o \
 	varobj.o vec.o wrapper.o \
@@ -840,7 +841,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	sentinel-frame.o \
 	complaints.o typeprint.o \
 	ada-typeprint.o c-typeprint.o f-typeprint.o m2-typeprint.o \
-	ada-valprint.o c-valprint.o cp-valprint.o f-valprint.o m2-valprint.o \
+	ada-valprint.o c-valprint.o cp-valprint.o d-valprint.o f-valprint.o \
+	m2-valprint.o \
 	serial.o mdebugread.o top.o utils.o \
 	ui-file.o \
 	user-regs.o \
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 805c572..aa69f94 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -253,8 +253,9 @@ print_wchar (gdb_wint_t w, const gdb_byte *orig, int orig_len,
    string whose delimiter is QUOTER.  Note that that format for printing
    characters and strings is language specific. */
 
-static void
-c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter)
+void
+c_emit_char (int c, struct type *type,
+	     struct ui_file *stream, int quoter)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
   struct obstack wchar_buf, output;
@@ -1135,7 +1136,7 @@ c_language_arch_info (struct gdbarch *gdbarch,
   lai->bool_type_default = builtin->builtin_int;
 }
 
-static const struct exp_descriptor exp_descriptor_c = 
+const struct exp_descriptor exp_descriptor_c = 
 {
   print_subexp_standard,
   operator_length_standard,
diff --git a/gdb/c-lang.h b/gdb/c-lang.h
index 423cee0..c2cdd56 100644
--- a/gdb/c-lang.h
+++ b/gdb/c-lang.h
@@ -87,6 +87,11 @@ extern void c_printstr (struct ui_file * stream, struct type *elttype,
 extern void c_language_arch_info (struct gdbarch *gdbarch,
 				  struct language_arch_info *lai);
 
+extern const struct exp_descriptor exp_descriptor_c;
+
+extern void c_emit_char (int c, struct type *type,
+			 struct ui_file *stream, int quoter);
+
 /* These are in c-typeprint.c: */
 
 extern void c_type_print_base (struct type *, struct ui_file *, int, int);
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
new file mode 100644
index 0000000..cf58335
--- /dev/null
+++ b/gdb/d-lang.c
@@ -0,0 +1,283 @@
+/* D language support routines for GDB, the GNU debugger.
+
+   Copyright (C) 2005, 2006, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "symtab.h"
+#include "language.h"
+#include "d-lang.h"
+#include "c-lang.h"
+#include "gdb_string.h"
+#include "parser-defs.h"
+#include "gdb_obstack.h"
+
+#include <ctype.h>
+
+
+static const char *mangled_str;
+/* Temporary obstack used for holding strings.  */
+static struct obstack tempbuf;
+
+/* Extract identifiers from MANGLED_STR and append it to TEMPBUF.
+   Return 1 on success or 0 on failure.  */
+static int
+extract_identifiers (const char *mangled_str, struct obstack *tempbuf)
+{
+  long i = 0;
+
+  while (isdigit (*mangled_str))
+    {
+      i = strtol (mangled_str, NULL, 10);
+      mangled_str++;
+      if (i <= 0  && strlen (mangled_str) < i)
+        return 0;
+      obstack_grow (tempbuf, mangled_str, i);
+      mangled_str += i;
+      obstack_grow_str (tempbuf, ".");
+    }
+  if (*mangled_str == '\0' || i == 0)
+    return 0;
+  obstack_blank (tempbuf, -1);
+  return 1;
+}
+
+/* Extract and demangle type from MANGLED_STR and append it to TEMPBUF.
+   Return 1 on success or 0 on failure.  */
+static int
+extract_type_info (const char *mangled_str, struct obstack *tempbuf)
+{
+  if (*mangled_str == '\0')
+    return 0;
+  switch (*mangled_str++)
+    {
+      case 'A': /* dynamic array */
+      case 'G': /* static array */
+      case 'H': /* associative array */
+	if (!extract_type_info (mangled_str, tempbuf))
+	  return 0;
+	obstack_grow_str (tempbuf, "[]");
+	return 1;
+      case 'P': /* pointer */
+	if (!extract_type_info (mangled_str, tempbuf))
+	  return 0;
+	obstack_grow_str (tempbuf, "*");
+	return 1;
+      case 'R': /* reference */
+	if (!extract_type_info (mangled_str, tempbuf))
+	  return 0;
+	obstack_grow_str (tempbuf, "&");
+	return 1;
+      case 'Z': /* return value */
+	return extract_type_info (mangled_str, tempbuf);
+      case 'J': /* out */
+	obstack_grow_str (tempbuf, "out ");
+	return extract_type_info (mangled_str, tempbuf);
+      case 'K': /* inout */
+	obstack_grow_str (tempbuf, "inout ");
+	return extract_type_info (mangled_str, tempbuf);
+      case 'E': /* enum */
+      case 'T': /* typedef */
+      case 'D': /* delegate */
+      case 'C': /* class */
+      case 'S': /* struct */
+	return extract_identifiers (mangled_str, tempbuf);
+
+      /* basic types: */
+      case 'n': obstack_grow_str (tempbuf, "none"); return 1;
+      case 'v': obstack_grow_str (tempbuf, "void"); return 1;
+      case 'g': obstack_grow_str (tempbuf, "byte"); return 1;
+      case 'h': obstack_grow_str (tempbuf, "ubyte"); return 1;
+      case 's': obstack_grow_str (tempbuf, "short"); return 1;
+      case 't': obstack_grow_str (tempbuf, "ushort"); return 1;
+      case 'i': obstack_grow_str (tempbuf, "int"); return 1;
+      case 'k': obstack_grow_str (tempbuf, "uint"); return 1;
+      case 'l': obstack_grow_str (tempbuf, "long"); return 1;
+      case 'm': obstack_grow_str (tempbuf, "ulong"); return 1;
+      case 'f': obstack_grow_str (tempbuf, "float"); return 1;
+      case 'd': obstack_grow_str (tempbuf, "double"); return 1;
+      case 'e': obstack_grow_str (tempbuf, "real"); return 1;
+
+      /* imaginary and complex: */
+      case 'o': obstack_grow_str (tempbuf, "ifloat"); return 1;
+      case 'p': obstack_grow_str (tempbuf, "idouble"); return 1;
+      case 'j': obstack_grow_str (tempbuf, "ireal"); return 1;
+      case 'q': obstack_grow_str (tempbuf, "cfloat"); return 1;
+      case 'r': obstack_grow_str (tempbuf, "cdouble"); return 1;
+      case 'c': obstack_grow_str (tempbuf, "creal"); return 1;
+
+      /* other types: */
+      case 'b': obstack_grow_str (tempbuf, "bit"); return 1;
+      case 'a': obstack_grow_str (tempbuf, "char"); return 1;
+      case 'u': obstack_grow_str (tempbuf, "wchar"); return 1;
+      case 'w': obstack_grow_str (tempbuf, "dchar"); return 1;
+
+      default:
+	obstack_grow_str (tempbuf, "unknown");
+	return 1;
+    }
+}
+
+/* Implements the la_demangle language_defn routine for language D.  */
+char *
+d_demangle (const char *symbol, int options)
+{
+  struct obstack tempbuf;
+  char *out_str;
+  unsigned char is_func = 0;
+
+  if (symbol == NULL)
+    return NULL;
+  else if (strcmp (symbol, "_Dmain") == 0)
+    return xstrdup ("D main");
+
+  obstack_init (&tempbuf);
+  
+  if (symbol[0] == '_' && symbol[1] == 'D')
+    {
+      symbol += 2;
+      is_func = 1;
+    }
+  else if (strncmp (symbol, "__Class_", 8) == 0)
+    symbol += 8;
+  else if (strncmp (symbol, "__init_", 7) == 0)
+    symbol += 7;
+  else if (strncmp (symbol, "__vtbl_", 7) == 0)
+    symbol += 7;
+  else if (strncmp (symbol, "__modctor_", 10) == 0)
+    symbol += 10;
+  else if (strncmp (symbol, "__moddtor_", 10) == 0)
+    symbol += 10;
+  else if (strncmp (symbol, "__ModuleInfo_", 13) == 0)
+    symbol += 13;
+  else
+    {
+      obstack_free (&tempbuf, NULL);
+      return NULL;
+    }
+  
+  if (!extract_identifiers (symbol, &tempbuf))
+    {
+      obstack_free (&tempbuf, NULL);
+      return NULL;
+    }
+
+  obstack_grow_str (&tempbuf, "(");
+  if (is_func == 1 && *symbol == 'F')
+    {
+      symbol++;
+      while (*symbol != '\0' && *symbol != 'Z')
+	{
+	  if (is_func == 1)
+	    is_func++;
+	  else
+	    obstack_grow_str (&tempbuf, ", ");
+	  if (!extract_type_info (symbol, &tempbuf))
+	    {
+	      obstack_free (&tempbuf, NULL);
+	      return NULL;
+	   }
+	}
+     }
+  obstack_grow_str0 (&tempbuf, ")");
+
+  /* Doesn't display the return type, but wouldn't be too hard to do.  */
+
+  out_str = xstrdup (obstack_finish (&tempbuf));
+  obstack_free (&tempbuf, NULL);
+  return out_str;
+}
+
+/* Table mapping opcodes into strings for printing operators
+   and precedences of the operators.  */
+static const struct op_print d_op_print_tab[] =
+{
+  {",", BINOP_COMMA, PREC_COMMA, 0},
+  {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
+  {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
+  {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
+  {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
+  {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
+  {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
+  {"==", BINOP_EQUAL, PREC_EQUAL, 0},
+  {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
+  {"<=", BINOP_LEQ, PREC_ORDER, 0},
+  {">=", BINOP_GEQ, PREC_ORDER, 0},
+  {">", BINOP_GTR, PREC_ORDER, 0},
+  {"<", BINOP_LESS, PREC_ORDER, 0},
+  {">>", BINOP_RSH, PREC_SHIFT, 0},
+  {"<<", BINOP_LSH, PREC_SHIFT, 0},
+  {"+", BINOP_ADD, PREC_ADD, 0},
+  {"-", BINOP_SUB, PREC_ADD, 0},
+  {"*", BINOP_MUL, PREC_MUL, 0},
+  {"/", BINOP_DIV, PREC_MUL, 0},
+  {"%", BINOP_REM, PREC_MUL, 0},
+  {"@", BINOP_REPEAT, PREC_REPEAT, 0},
+  {"-", UNOP_NEG, PREC_PREFIX, 0},
+  {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
+  {"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
+  {"*", UNOP_IND, PREC_PREFIX, 0},
+  {"&", UNOP_ADDR, PREC_PREFIX, 0},
+  {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
+  {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
+  {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
+  {NULL, 0, 0, 0}
+};
+
+static const struct language_defn d_language_defn =
+{
+  "d",
+  language_d,
+  range_check_off,
+  type_check_off,
+  case_sensitive_on,
+  array_row_major,
+  macro_expansion_c,
+  &exp_descriptor_c,
+  c_parse,
+  c_error,
+  null_post_parser,
+  c_printchar,			/* Print a character constant.  */
+  c_printstr,			/* Function to print string constant.  */
+  c_emit_char,			/* Print a single char.  */
+  c_print_type,			/* Print a type using appropriate syntax.  */
+  c_print_typedef,		/* Print a typedef using appropriate syntax.  */
+  d_val_print,			/* Print a value using appropriate syntax.  */
+  c_value_print,		/* Print a top-level value.  */
+  NULL,				/* Language specific skip_trampoline.  */
+  "this",
+  basic_lookup_symbol_nonlocal, 
+  basic_lookup_transparent_type,
+  d_demangle,			/* Language specific symbol demangler.  */
+  NULL,				/* Language specific class_name_from_physname.  */
+  d_op_print_tab,		/* Expression operators for printing.  */
+  1,				/* C-style arrays.  */
+  0,				/* String lower bound.  */
+  default_word_break_characters,
+  default_make_symbol_completion_list,
+  c_language_arch_info,
+  default_print_array_index,
+  default_pass_by_reference,
+  c_get_string,
+  LANG_MAGIC
+};
+
+void
+_initialize_d_language (void)
+{
+  add_language (&d_language_defn);
+}
diff --git a/gdb/d-lang.h b/gdb/d-lang.h
new file mode 100644
index 0000000..be27827
--- /dev/null
+++ b/gdb/d-lang.h
@@ -0,0 +1,32 @@
+/* D language support definitions for GDB, the GNU debugger.
+
+   Copyright (C) 2005, 2006, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#if !defined (D_LANG_H)
+#define D_LANG_H 1
+
+#include "symtab.h"
+
+extern char *d_demangle (const char *mangled, int options);
+
+extern int d_val_print (struct type *type, const gdb_byte *valaddr,
+			int embedded_offset, CORE_ADDR address,
+			struct ui_file *stream, int recurse,
+			const struct value_print_options *options);
+
+#endif /* !defined (D_LANG_H) */
diff --git a/gdb/d-valprint.c b/gdb/d-valprint.c
new file mode 100644
index 0000000..67b32b7
--- /dev/null
+++ b/gdb/d-valprint.c
@@ -0,0 +1,91 @@
+/* Support for printing D values for GDB, the GNU debugger.
+
+   Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "gdbcore.h"
+#include "d-lang.h"
+#include "c-lang.h"
+
+/* Assuming that TYPE is a TYPE_CODE_STRUCT, verify that TYPE is
+   a dynamic array, and then print its value to STREAM.  Return
+   the number of string characters printed, or -1 if TYPE is not
+   a dynamic array.  */
+static int
+dynamic_array_type (struct type *type, const gdb_byte *valaddr,
+		    int embedded_offset, CORE_ADDR address,
+		    struct ui_file *stream, int recurse,
+		    const struct value_print_options *options)
+{
+  if (TYPE_NFIELDS (type) == 2
+      && TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_INT
+      && strcmp (TYPE_FIELD_NAME (type, 0), "length") == 0
+      && strcmp (TYPE_FIELD_NAME (type, 1), "ptr") == 0)
+    {
+      CORE_ADDR addr;
+      struct type *elttype;
+      struct type *true_type;
+      struct type *ptr_type;
+      struct type *range_type;
+      const gdb_byte *ptraddr;
+      struct value *val;
+      int length;
+
+      length = unpack_field_as_long (type, valaddr + embedded_offset, 0);
+
+      ptr_type = TYPE_FIELD_TYPE (type, 1);
+      elttype = check_typedef (TYPE_TARGET_TYPE (ptr_type));
+      addr = unpack_pointer (ptr_type,
+			     valaddr + TYPE_FIELD_BITPOS (type, 1) / 8
+			     + embedded_offset);
+      true_type = check_typedef (elttype);
+
+      true_type = lookup_array_range_type (true_type, 0, length - 1);
+      val = value_at (true_type, addr);
+      ptraddr = value_contents (val);
+
+      return d_val_print (true_type, ptraddr, 0, addr, stream, recurse + 1,
+			  options);
+    }
+  return -1;
+}
+
+/* Implements the la_val_print routine for language D.  */
+int
+d_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
+             CORE_ADDR address, struct ui_file *stream, int recurse,
+             const struct value_print_options *options)
+{
+  int ret;
+
+  CHECK_TYPEDEF (type);
+  switch (TYPE_CODE (type))
+    {
+      case TYPE_CODE_STRUCT:
+        ret = dynamic_array_type (type, valaddr, embedded_offset, address,
+				  stream, recurse, options);
+	if (ret != -1)
+	   break;
+      default:
+	ret = c_val_print (type, valaddr, embedded_offset, address, stream,
+			   recurse, options);
+    }
+
+  return ret;
+}
diff --git a/gdb/defs.h b/gdb/defs.h
index e8a1dd4..d4a9b19 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -188,6 +188,7 @@ enum language
     language_auto,		/* Placeholder for automatic setting */
     language_c,			/* C */
     language_cplus,		/* C++ */
+    language_d,			/* D */
     language_objc,		/* Objective-C */
     language_java,		/* Java */
     language_fortran,		/* Fortran */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 93a98f3..0f7ea38 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -214,6 +214,10 @@ You can use @value{GDBN} to debug programs written in C and C@t{++}.
 For more information, see @ref{Supported Languages,,Supported Languages}.
 For more information, see @ref{C,,C and C++}.
 
+@cindex D
+Support for D is partial.  For information on D, see
+@ref{D,,D}.
+
 @cindex Modula-2
 Support for Modula-2 is partial.  For information on Modula-2, see
 @ref{Modula-2,,Modula-2}.
@@ -10824,6 +10828,9 @@ C source file
 @itemx .c++
 C@t{++} source file
 
+@item .d
+D source file
+
 @item .m
 Objective-C source file
 
@@ -11101,7 +11108,7 @@ being set automatically by @value{GDBN}.
 @node Supported Languages
 @section Supported Languages
 
-@value{GDBN} supports C, C@t{++}, Objective-C, Fortran, Java, Pascal,
+@value{GDBN} supports C, C@t{++}, D, Objective-C, Fortran, Java, Pascal,
 assembly, Modula-2, and Ada.
 @c This is false ...
 Some @value{GDBN} features may be used in expressions regardless of the
@@ -11120,6 +11127,7 @@ language reference or tutorial.
 
 @menu
 * C::                           C and C@t{++}
+* D::                           D
 * Objective-C::                 Objective-C
 * Fortran::                     Fortran
 * Pascal::                      Pascal
@@ -11657,6 +11665,14 @@ In the PowerPC architecture, @value{GDBN} provides a set of pseudo-registers
 to inspect @code{_Decimal128} values stored in floating point registers.
 See @ref{PowerPC,,PowerPC} for more details.
 
+@node D
+@subsection D
+
+@cindex D
+@value{GDBN} can be used to debug programs written in D and compiled with
+GDC, LDC or DMD. Currently @value{GDBN} supports only one D specific
+feature - dynamic arrays.
+
 @node Objective-C
 @subsection Objective-C
 
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 3096ab7..f4cbc59 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -7619,6 +7619,9 @@ set_cu_language (unsigned int lang, struct dwarf2_cu *cu)
     case DW_LANG_C_plus_plus:
       cu->language = language_cplus;
       break;
+    case DW_LANG_D:
+      cu->language = language_d;
+      break;
     case DW_LANG_Fortran77:
     case DW_LANG_Fortran90:
     case DW_LANG_Fortran95:
diff --git a/gdb/language.c b/gdb/language.c
index dcd70b0..aba8a9e 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -486,6 +486,7 @@ binop_result_type (struct value *v1, struct value *v2)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       if (TYPE_CODE (t1) == TYPE_CODE_FLT)
 	return TYPE_CODE (t2) == TYPE_CODE_FLT && l2 > l1 ?
@@ -597,6 +598,7 @@ integral_type (struct type *type)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) != TYPE_CODE_INT) &&
 	(TYPE_CODE (type) != TYPE_CODE_ENUM) ? 0 : 1;
@@ -637,6 +639,7 @@ character_type (struct type *type)
 
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) == TYPE_CODE_INT) &&
 	TYPE_LENGTH (type) == sizeof (char)
@@ -659,6 +662,7 @@ string_type (struct type *type)
 
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       /* C does not have distinct string type. */
       return (0);
@@ -678,6 +682,7 @@ boolean_type (struct type *type)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       /* Might be more cleanly handled by having a
          TYPE_CODE_INT_NOT_BOOL for (the deleted) CHILL and such
@@ -717,6 +722,7 @@ structured_type (struct type *type)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) == TYPE_CODE_STRUCT) ||
 	(TYPE_CODE (type) == TYPE_CODE_UNION) ||
diff --git a/gdb/symfile.c b/gdb/symfile.c
index eda26cc..cf7b41a 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -2618,6 +2618,7 @@ init_filename_language_table (void)
       filename_language_table =
 	xmalloc (fl_table_size * sizeof (*filename_language_table));
       add_filename_language (".c", language_c);
+      add_filename_language (".d", language_d);
       add_filename_language (".C", language_cplus);
       add_filename_language (".cc", language_cplus);
       add_filename_language (".cp", language_cplus);
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 1d6b648..67a784b 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -39,6 +39,7 @@
 #include "source.h"
 #include "filenames.h"		/* for FILENAME_CMP */
 #include "objc-lang.h"
+#include "d-lang.h"
 #include "ada-lang.h"
 #include "p-lang.h"
 #include "addrmap.h"
@@ -346,6 +347,7 @@ symbol_init_language_specific (struct general_symbol_info *gsymbol,
 {
   gsymbol->language = language;
   if (gsymbol->language == language_cplus
+      || gsymbol->language == language_d
       || gsymbol->language == language_java
       || gsymbol->language == language_objc)
     {
@@ -449,6 +451,16 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
 	  return demangled;
 	}
     }
+  if (gsymbol->language == language_d
+      || gsymbol->language == language_auto)
+    {
+      demangled = d_demangle(mangled, 0);
+      if (demangled != NULL)
+	{
+	  gsymbol->language = language_d;
+	  return demangled;
+	}
+    }
   return NULL;
 }
 
@@ -626,6 +638,7 @@ symbol_natural_name (const struct general_symbol_info *gsymbol)
   switch (gsymbol->language)
     {
     case language_cplus:
+    case language_d:
     case language_java:
     case language_objc:
       if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
@@ -651,6 +664,7 @@ symbol_demangled_name (const struct general_symbol_info *gsymbol)
   switch (gsymbol->language)
     {
     case language_cplus:
+    case language_d:
     case language_java:
     case language_objc:
       if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
@@ -940,7 +954,7 @@ lookup_symbol_in_language (const char *name, const struct block *block,
 
   modified_name = name;
 
-  /* If we are using C++ or Java, demangle the name before doing a lookup, so
+  /* If we are using C++, D, or Java, demangle the name before doing a lookup, so
      we can always binary search. */
   if (lang == language_cplus)
     {
@@ -972,6 +986,15 @@ lookup_symbol_in_language (const char *name, const struct block *block,
 	  make_cleanup (xfree, demangled_name);
 	}
     }
+  else if (lang == language_d)
+    {
+      demangled_name = d_demangle (name, 0);
+      if (demangled_name)
+	{
+	  modified_name = demangled_name;
+	  make_cleanup (xfree, demangled_name);
+	}
+    }
 
   if (case_sensitivity == case_sensitive_off)
     {
@@ -1412,6 +1435,7 @@ symbol_matches_domain (enum language symbol_language,
      A Java class declaration also defines a typedef for the class.
      Similarly, any Ada type declaration implicitly defines a typedef.  */
   if (symbol_language == language_cplus
+      || symbol_language == language_d
       || symbol_language == language_java
       || symbol_language == language_ada)
     {
diff --git a/gdb/testsuite/gdb.base/default.exp b/gdb/testsuite/gdb.base/default.exp
index 97d5407..2a13007 100644
--- a/gdb/testsuite/gdb.base/default.exp
+++ b/gdb/testsuite/gdb.base/default.exp
@@ -531,7 +531,7 @@ gdb_test "set history size" "Argument required .integer to set it to.*" "set his
 #test set history
 gdb_test "set history" "\"set history\" must be followed by the name of a history subcommand.(\[^\r\n\]*\[\r\n\])+List of set history subcommands:(\[^\r\n\]*\[\r\n\])+set history expansion -- Set history expansion on command input(\[^\r\n\]*\[\r\n\])+set history filename -- Set the filename in which to record the command history(\[^\r\n\]*\[\r\n\])+set history save -- Set saving of the history record on exit(\[^\r\n\]*\[\r\n\])+set history size -- Set the size of the command history(\[^\r\n\]*\[\r\n\])+Type \"help set history\" followed by set history subcommand name for full documentation.(\[^\r\n\]*\[\r\n\])+Command name abbreviations are allowed if unambiguous." "set history"
 #test set language
-gdb_test "set language" "Requires an argument. Valid arguments are auto, local, unknown, ada, c, c.., asm, minimal, fortran, objective-c, java, modula-2, pascal, scheme." "set language"
+gdb_test "set language" "Requires an argument. Valid arguments are auto, local, unknown, ada, c, c.., asm, minimal, d, fortran, objective-c, java, modula-2, pascal, scheme." "set language"
 #test set listsize
 gdb_test "set listsize" "Argument required .integer to set it to.*" "set listsize"
 #test set print "p" abbreviation

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-04-23 21:35               ` Robert Clipsham
@ 2010-04-24  0:26                 ` Mihail Zenkov
  2010-04-27 20:27                   ` Robert Clipsham
  0 siblings, 1 reply; 33+ messages in thread
From: Mihail Zenkov @ 2010-04-24  0:26 UTC (permalink / raw)
  To: Robert Clipsham; +Cc: gdb-patches

On Fri, 23 Apr 2010 22:34:05 +0100
Robert Clipsham <robert@octarineparrot.com> wrote:

> On 14/04/10 23:21, Mihail Zenkov wrote:
> > Sorry for too very long delay. I fix patch as you and Joel suggested,
> > i hope it ready for inclusion. Also i write second patch for
> > testsuite, it work good with GDC, but fail with DMD and LDC -
> > probably it have some problem/particularity in DWARF implementation.
> > I try do more test and write to their authors.
> 
> Can you give an instance of where dmd is failing to produce the 
> expected/correct debug info? I wrote several patches to improve dmd's 
> debug info which are sitting in bugzilla waiting to be included... If 
> you can find somewhere where dmd isn't playing nicely I can help get it 
> working :)

Thanks! I'll try patchs from bugzilla and add comments.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-04-23 20:37                             ` Tom Tromey
@ 2010-04-26 23:51                               ` Stan Shebs
  2010-04-27  0:29                                 ` Joel Brobecker
  0 siblings, 1 reply; 33+ messages in thread
From: Stan Shebs @ 2010-04-26 23:51 UTC (permalink / raw)
  To: tromey; +Cc: Leandro Lucarella, gdb-patches

Tom Tromey wrote:
>>>>>> "Leandro" == Leandro Lucarella <llucax@gmail.com> writes:
>>>>>>             
>
> Leandro> Is the indent program invoked with -gnu option enough to fix the style
> Leandro> nits or GDB has its own rules? It might save some time to everybody =)
>
> Weirdly, indent -gnu doesn't really use the GNU style.
> It is a sort of approximation.
>
> We have a gdb_indent.sh in the tree, and I think it was used at one
> point, but in the end I think it was abandoned.  I think sometimes it
> did the wrong thing.
>   
To some extent, one just has to decide that the output of the script is 
"correct", even if it looks wrong here and there.  But I think part of 
the pain comes from having *two* programs - emacs and indent - that can 
have differing conclusions, and being unsure as to which should take 
precedence.

Somebody should give gdb_indent.sh a try, see how it does on today's 
sources.  We have more people participating in maintenance these days, 
seems like we could run it once a week or so, and it has the bonus of 
cleaning up after those rouge global maintainers who check in massive 
hacks willy-nilly. :-)

Stan

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-04-26 23:51                               ` Stan Shebs
@ 2010-04-27  0:29                                 ` Joel Brobecker
  0 siblings, 0 replies; 33+ messages in thread
From: Joel Brobecker @ 2010-04-27  0:29 UTC (permalink / raw)
  To: Stan Shebs; +Cc: tromey, Leandro Lucarella, gdb-patches

> Somebody should give gdb_indent.sh a try, see how it does on today's
> sources.

<conversation mode on>The last time I applied gdb_indent.sh to ada-lang.c
and committed the patch (I had barely started at AdaCore then), it showed
me how extraordinarily powerful Paul Hilfinger is. He showed incredible
restraint and politeness in the way he complained about some of the
horrible results that we got from it. And despite his restraint, I was
sure glad he was 9 time zones and 14 flying hours away at the time ;-).
<conversation mode off>

It would be interesting to see if GNU indent does better nowadays.
The GNU indent page seems a bit terse, but looking at the FTP site,
it looks like a minor release we made in Feb 2009 - the first since
Dec 2002. Hum!

-- 
Joel

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-04-24  0:06                             ` Mihail Zenkov
@ 2010-04-27 16:05                               ` Joel Brobecker
  2010-04-27 23:55                                 ` Mihail Zenkov
  0 siblings, 1 reply; 33+ messages in thread
From: Joel Brobecker @ 2010-04-27 16:05 UTC (permalink / raw)
  To: Mihail Zenkov; +Cc: tromey, gdb-patches

> +static const char *mangled_str;
> +/* Temporary obstack used for holding strings.  */
> +static struct obstack tempbuf;

Can you remove the declaration of these globals? They shouldn't be
necessary anymore...

Otherwise, the rest looks OK to me.

-- 
Joel

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-04-24  0:26                 ` Mihail Zenkov
@ 2010-04-27 20:27                   ` Robert Clipsham
  0 siblings, 0 replies; 33+ messages in thread
From: Robert Clipsham @ 2010-04-27 20:27 UTC (permalink / raw)
  To: gdb-patches

On 24/04/10 01:25, Mihail Zenkov wrote:
> Thanks! I'll try patchs from bugzilla and add comments.

The patches have been applied in svn now, I've tested dmd r452, and the 
debug information is loads better now. Again, if you spot any issues let 
me know and I'll see about getting them fixed :)

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-04-27 16:05                               ` Joel Brobecker
@ 2010-04-27 23:55                                 ` Mihail Zenkov
  2010-04-28 15:17                                   ` Joel Brobecker
  2010-04-28 17:10                                   ` Eli Zaretskii
  0 siblings, 2 replies; 33+ messages in thread
From: Mihail Zenkov @ 2010-04-27 23:55 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: Mihail Zenkov, tromey, gdb-patches

[-- Attachment #1: Type: text/plain, Size: 327 bytes --]

On Tue, 27 Apr 2010 09:05:23 -0700
Joel Brobecker <brobecker@adacore.com> wrote:

> > +static const char *mangled_str;
> > +/* Temporary obstack used for holding strings.  */
> > +static struct obstack tempbuf;
> 
> Can you remove the declaration of these globals? They shouldn't be
> necessary anymore...

Oops! Sorry, fixed.

[-- Attachment #2: gdb-100428-d.patch --]
[-- Type: application/octet-stream, Size: 27301 bytes --]

gdb/NEWS:
* D language support.
 Support for debugging the D programming language has been
 integrated into GDB.
gdb/ChangeLog:
	D language support.
	* Makefile.in (SFILES): Add d-lang.c d-valprint.c.
	(COMMON_OBS): Add d-lang.o d-valprint.o.
	(HFILES_NO_SRCDIR): Add d-lang.h.
	* c-lang.c (c_emit_char, exp_descriptor_c): Make public.
	* c-lang.h (c_emit_char, exp_descriptor_c): Add declaration.
	* d-lang.c: New file.
	* d-lang.h: New file.
	* d-valprint.c: New file.
	* defs.h (enum language): Add language_d.
	* dwarf2read.c (set_cu_language): Add DW_LANG_D.
	* language.c (binop_result_type, integral_type, character_type) 
	(string_type, boolean_type, structured_type): Add language_d.
	* symfile.c (init_filename_language_table): Add language_d.
	* symtab.c: Include d-lang.h.
	(symbol_init_language_specific, symbol_find_demangled_name)
	(symbol_natural_name, lookup_symbol_in_language)
	(symbol_demangled_name, symbol_matches_domain): Add language_d.
gdb/doc/ChangeLog:
	* gdb.texinfo: Add mention about D language support.
gdb/testsuite/ChangeLog:
	* gdb.base/default.exp: Fix "set language" test.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 750fdfd..cbbd813 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -658,6 +658,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	charset.c cli-out.c coffread.c coff-pe-read.c \
 	complaints.c completer.c corefile.c \
 	cp-abi.c cp-support.c cp-namespace.c cp-valprint.c \
+	d-lang.c d-valprint.c \
 	cp-name-parser.y \
 	dbxread.c demangle.c dictionary.c disasm.c doublest.c dummy-frame.c \
 	dwarf2expr.c dwarf2loc.c dwarf2read.c dwarf2-frame.c \
@@ -725,7 +726,7 @@ cli-out.h gdb_expat.h breakpoint.h infcall.h obsd-tdep.h \
 exec.h m32r-tdep.h osabi.h gdbcore.h solib-som.h \
 i386bsd-nat.h xml-support.h xml-tdesc.h alphabsd-tdep.h gdb_obstack.h \
 ia64-tdep.h ada-lang.h varobj.h frv-tdep.h nto-tdep.h serial.h \
-c-lang.h frame.h event-loop.h block.h cli/cli-setshow.h	\
+c-lang.h d-lang.h frame.h event-loop.h block.h cli/cli-setshow.h	\
 cli/cli-decode.h cli/cli-cmds.h cli/cli-dump.h \
 cli/cli-script.h macrotab.h symtab.h version.h gnulib/wchar.in.h \
 gnulib/string.in.h gnulib/str-two-way.h gnulib/extra/link-warning.h \
@@ -831,7 +832,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	dbxread.o coffread.o coff-pe-read.o \
 	dwarf2read.o mipsread.o stabsread.o corefile.o \
 	dwarf2expr.o dwarf2loc.o dwarf2-frame.o \
-	ada-lang.o c-lang.o f-lang.o objc-lang.o \
+	ada-lang.o c-lang.o d-lang.o f-lang.o objc-lang.o \
 	ada-tasks.o \
 	ui-out.o cli-out.o \
 	varobj.o vec.o wrapper.o \
@@ -841,7 +842,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	sentinel-frame.o \
 	complaints.o typeprint.o \
 	ada-typeprint.o c-typeprint.o f-typeprint.o m2-typeprint.o \
-	ada-valprint.o c-valprint.o cp-valprint.o f-valprint.o m2-valprint.o \
+	ada-valprint.o c-valprint.o cp-valprint.o d-valprint.o f-valprint.o \
+	m2-valprint.o \
 	serial.o mdebugread.o top.o utils.o \
 	ui-file.o \
 	user-regs.o \
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 805c572..aa69f94 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -253,8 +253,9 @@ print_wchar (gdb_wint_t w, const gdb_byte *orig, int orig_len,
    string whose delimiter is QUOTER.  Note that that format for printing
    characters and strings is language specific. */
 
-static void
-c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter)
+void
+c_emit_char (int c, struct type *type,
+	     struct ui_file *stream, int quoter)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
   struct obstack wchar_buf, output;
@@ -1135,7 +1136,7 @@ c_language_arch_info (struct gdbarch *gdbarch,
   lai->bool_type_default = builtin->builtin_int;
 }
 
-static const struct exp_descriptor exp_descriptor_c = 
+const struct exp_descriptor exp_descriptor_c = 
 {
   print_subexp_standard,
   operator_length_standard,
diff --git a/gdb/c-lang.h b/gdb/c-lang.h
index 423cee0..c2cdd56 100644
--- a/gdb/c-lang.h
+++ b/gdb/c-lang.h
@@ -87,6 +87,11 @@ extern void c_printstr (struct ui_file * stream, struct type *elttype,
 extern void c_language_arch_info (struct gdbarch *gdbarch,
 				  struct language_arch_info *lai);
 
+extern const struct exp_descriptor exp_descriptor_c;
+
+extern void c_emit_char (int c, struct type *type,
+			 struct ui_file *stream, int quoter);
+
 /* These are in c-typeprint.c: */
 
 extern void c_type_print_base (struct type *, struct ui_file *, int, int);
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
new file mode 100644
index 0000000..6db521b
--- /dev/null
+++ b/gdb/d-lang.c
@@ -0,0 +1,278 @@
+/* D language support routines for GDB, the GNU debugger.
+
+   Copyright (C) 2005, 2006, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "symtab.h"
+#include "language.h"
+#include "d-lang.h"
+#include "c-lang.h"
+#include "gdb_string.h"
+#include "parser-defs.h"
+#include "gdb_obstack.h"
+
+#include <ctype.h>
+
+/* Extract identifiers from MANGLED_STR and append it to TEMPBUF.
+   Return 1 on success or 0 on failure.  */
+static int
+extract_identifiers (const char *mangled_str, struct obstack *tempbuf)
+{
+  long i = 0;
+
+  while (isdigit (*mangled_str))
+    {
+      i = strtol (mangled_str, NULL, 10);
+      mangled_str++;
+      if (i <= 0  && strlen (mangled_str) < i)
+        return 0;
+      obstack_grow (tempbuf, mangled_str, i);
+      mangled_str += i;
+      obstack_grow_str (tempbuf, ".");
+    }
+  if (*mangled_str == '\0' || i == 0)
+    return 0;
+  obstack_blank (tempbuf, -1);
+  return 1;
+}
+
+/* Extract and demangle type from MANGLED_STR and append it to TEMPBUF.
+   Return 1 on success or 0 on failure.  */
+static int
+extract_type_info (const char *mangled_str, struct obstack *tempbuf)
+{
+  if (*mangled_str == '\0')
+    return 0;
+  switch (*mangled_str++)
+    {
+      case 'A': /* dynamic array */
+      case 'G': /* static array */
+      case 'H': /* associative array */
+	if (!extract_type_info (mangled_str, tempbuf))
+	  return 0;
+	obstack_grow_str (tempbuf, "[]");
+	return 1;
+      case 'P': /* pointer */
+	if (!extract_type_info (mangled_str, tempbuf))
+	  return 0;
+	obstack_grow_str (tempbuf, "*");
+	return 1;
+      case 'R': /* reference */
+	if (!extract_type_info (mangled_str, tempbuf))
+	  return 0;
+	obstack_grow_str (tempbuf, "&");
+	return 1;
+      case 'Z': /* return value */
+	return extract_type_info (mangled_str, tempbuf);
+      case 'J': /* out */
+	obstack_grow_str (tempbuf, "out ");
+	return extract_type_info (mangled_str, tempbuf);
+      case 'K': /* inout */
+	obstack_grow_str (tempbuf, "inout ");
+	return extract_type_info (mangled_str, tempbuf);
+      case 'E': /* enum */
+      case 'T': /* typedef */
+      case 'D': /* delegate */
+      case 'C': /* class */
+      case 'S': /* struct */
+	return extract_identifiers (mangled_str, tempbuf);
+
+      /* basic types: */
+      case 'n': obstack_grow_str (tempbuf, "none"); return 1;
+      case 'v': obstack_grow_str (tempbuf, "void"); return 1;
+      case 'g': obstack_grow_str (tempbuf, "byte"); return 1;
+      case 'h': obstack_grow_str (tempbuf, "ubyte"); return 1;
+      case 's': obstack_grow_str (tempbuf, "short"); return 1;
+      case 't': obstack_grow_str (tempbuf, "ushort"); return 1;
+      case 'i': obstack_grow_str (tempbuf, "int"); return 1;
+      case 'k': obstack_grow_str (tempbuf, "uint"); return 1;
+      case 'l': obstack_grow_str (tempbuf, "long"); return 1;
+      case 'm': obstack_grow_str (tempbuf, "ulong"); return 1;
+      case 'f': obstack_grow_str (tempbuf, "float"); return 1;
+      case 'd': obstack_grow_str (tempbuf, "double"); return 1;
+      case 'e': obstack_grow_str (tempbuf, "real"); return 1;
+
+      /* imaginary and complex: */
+      case 'o': obstack_grow_str (tempbuf, "ifloat"); return 1;
+      case 'p': obstack_grow_str (tempbuf, "idouble"); return 1;
+      case 'j': obstack_grow_str (tempbuf, "ireal"); return 1;
+      case 'q': obstack_grow_str (tempbuf, "cfloat"); return 1;
+      case 'r': obstack_grow_str (tempbuf, "cdouble"); return 1;
+      case 'c': obstack_grow_str (tempbuf, "creal"); return 1;
+
+      /* other types: */
+      case 'b': obstack_grow_str (tempbuf, "bit"); return 1;
+      case 'a': obstack_grow_str (tempbuf, "char"); return 1;
+      case 'u': obstack_grow_str (tempbuf, "wchar"); return 1;
+      case 'w': obstack_grow_str (tempbuf, "dchar"); return 1;
+
+      default:
+	obstack_grow_str (tempbuf, "unknown");
+	return 1;
+    }
+}
+
+/* Implements the la_demangle language_defn routine for language D.  */
+char *
+d_demangle (const char *symbol, int options)
+{
+  struct obstack tempbuf;
+  char *out_str;
+  unsigned char is_func = 0;
+
+  if (symbol == NULL)
+    return NULL;
+  else if (strcmp (symbol, "_Dmain") == 0)
+    return xstrdup ("D main");
+
+  obstack_init (&tempbuf);
+  
+  if (symbol[0] == '_' && symbol[1] == 'D')
+    {
+      symbol += 2;
+      is_func = 1;
+    }
+  else if (strncmp (symbol, "__Class_", 8) == 0)
+    symbol += 8;
+  else if (strncmp (symbol, "__init_", 7) == 0)
+    symbol += 7;
+  else if (strncmp (symbol, "__vtbl_", 7) == 0)
+    symbol += 7;
+  else if (strncmp (symbol, "__modctor_", 10) == 0)
+    symbol += 10;
+  else if (strncmp (symbol, "__moddtor_", 10) == 0)
+    symbol += 10;
+  else if (strncmp (symbol, "__ModuleInfo_", 13) == 0)
+    symbol += 13;
+  else
+    {
+      obstack_free (&tempbuf, NULL);
+      return NULL;
+    }
+  
+  if (!extract_identifiers (symbol, &tempbuf))
+    {
+      obstack_free (&tempbuf, NULL);
+      return NULL;
+    }
+
+  obstack_grow_str (&tempbuf, "(");
+  if (is_func == 1 && *symbol == 'F')
+    {
+      symbol++;
+      while (*symbol != '\0' && *symbol != 'Z')
+	{
+	  if (is_func == 1)
+	    is_func++;
+	  else
+	    obstack_grow_str (&tempbuf, ", ");
+	  if (!extract_type_info (symbol, &tempbuf))
+	    {
+	      obstack_free (&tempbuf, NULL);
+	      return NULL;
+	   }
+	}
+     }
+  obstack_grow_str0 (&tempbuf, ")");
+
+  /* Doesn't display the return type, but wouldn't be too hard to do.  */
+
+  out_str = xstrdup (obstack_finish (&tempbuf));
+  obstack_free (&tempbuf, NULL);
+  return out_str;
+}
+
+/* Table mapping opcodes into strings for printing operators
+   and precedences of the operators.  */
+static const struct op_print d_op_print_tab[] =
+{
+  {",", BINOP_COMMA, PREC_COMMA, 0},
+  {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
+  {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
+  {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
+  {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
+  {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
+  {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
+  {"==", BINOP_EQUAL, PREC_EQUAL, 0},
+  {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
+  {"<=", BINOP_LEQ, PREC_ORDER, 0},
+  {">=", BINOP_GEQ, PREC_ORDER, 0},
+  {">", BINOP_GTR, PREC_ORDER, 0},
+  {"<", BINOP_LESS, PREC_ORDER, 0},
+  {">>", BINOP_RSH, PREC_SHIFT, 0},
+  {"<<", BINOP_LSH, PREC_SHIFT, 0},
+  {"+", BINOP_ADD, PREC_ADD, 0},
+  {"-", BINOP_SUB, PREC_ADD, 0},
+  {"*", BINOP_MUL, PREC_MUL, 0},
+  {"/", BINOP_DIV, PREC_MUL, 0},
+  {"%", BINOP_REM, PREC_MUL, 0},
+  {"@", BINOP_REPEAT, PREC_REPEAT, 0},
+  {"-", UNOP_NEG, PREC_PREFIX, 0},
+  {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
+  {"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
+  {"*", UNOP_IND, PREC_PREFIX, 0},
+  {"&", UNOP_ADDR, PREC_PREFIX, 0},
+  {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
+  {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
+  {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
+  {NULL, 0, 0, 0}
+};
+
+static const struct language_defn d_language_defn =
+{
+  "d",
+  language_d,
+  range_check_off,
+  type_check_off,
+  case_sensitive_on,
+  array_row_major,
+  macro_expansion_c,
+  &exp_descriptor_c,
+  c_parse,
+  c_error,
+  null_post_parser,
+  c_printchar,			/* Print a character constant.  */
+  c_printstr,			/* Function to print string constant.  */
+  c_emit_char,			/* Print a single char.  */
+  c_print_type,			/* Print a type using appropriate syntax.  */
+  c_print_typedef,		/* Print a typedef using appropriate syntax.  */
+  d_val_print,			/* Print a value using appropriate syntax.  */
+  c_value_print,		/* Print a top-level value.  */
+  NULL,				/* Language specific skip_trampoline.  */
+  "this",
+  basic_lookup_symbol_nonlocal, 
+  basic_lookup_transparent_type,
+  d_demangle,			/* Language specific symbol demangler.  */
+  NULL,				/* Language specific class_name_from_physname.  */
+  d_op_print_tab,		/* Expression operators for printing.  */
+  1,				/* C-style arrays.  */
+  0,				/* String lower bound.  */
+  default_word_break_characters,
+  default_make_symbol_completion_list,
+  c_language_arch_info,
+  default_print_array_index,
+  default_pass_by_reference,
+  c_get_string,
+  LANG_MAGIC
+};
+
+void
+_initialize_d_language (void)
+{
+  add_language (&d_language_defn);
+}
diff --git a/gdb/d-lang.h b/gdb/d-lang.h
new file mode 100644
index 0000000..be27827
--- /dev/null
+++ b/gdb/d-lang.h
@@ -0,0 +1,32 @@
+/* D language support definitions for GDB, the GNU debugger.
+
+   Copyright (C) 2005, 2006, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#if !defined (D_LANG_H)
+#define D_LANG_H 1
+
+#include "symtab.h"
+
+extern char *d_demangle (const char *mangled, int options);
+
+extern int d_val_print (struct type *type, const gdb_byte *valaddr,
+			int embedded_offset, CORE_ADDR address,
+			struct ui_file *stream, int recurse,
+			const struct value_print_options *options);
+
+#endif /* !defined (D_LANG_H) */
diff --git a/gdb/d-valprint.c b/gdb/d-valprint.c
new file mode 100644
index 0000000..67b32b7
--- /dev/null
+++ b/gdb/d-valprint.c
@@ -0,0 +1,91 @@
+/* Support for printing D values for GDB, the GNU debugger.
+
+   Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "gdbcore.h"
+#include "d-lang.h"
+#include "c-lang.h"
+
+/* Assuming that TYPE is a TYPE_CODE_STRUCT, verify that TYPE is
+   a dynamic array, and then print its value to STREAM.  Return
+   the number of string characters printed, or -1 if TYPE is not
+   a dynamic array.  */
+static int
+dynamic_array_type (struct type *type, const gdb_byte *valaddr,
+		    int embedded_offset, CORE_ADDR address,
+		    struct ui_file *stream, int recurse,
+		    const struct value_print_options *options)
+{
+  if (TYPE_NFIELDS (type) == 2
+      && TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_INT
+      && strcmp (TYPE_FIELD_NAME (type, 0), "length") == 0
+      && strcmp (TYPE_FIELD_NAME (type, 1), "ptr") == 0)
+    {
+      CORE_ADDR addr;
+      struct type *elttype;
+      struct type *true_type;
+      struct type *ptr_type;
+      struct type *range_type;
+      const gdb_byte *ptraddr;
+      struct value *val;
+      int length;
+
+      length = unpack_field_as_long (type, valaddr + embedded_offset, 0);
+
+      ptr_type = TYPE_FIELD_TYPE (type, 1);
+      elttype = check_typedef (TYPE_TARGET_TYPE (ptr_type));
+      addr = unpack_pointer (ptr_type,
+			     valaddr + TYPE_FIELD_BITPOS (type, 1) / 8
+			     + embedded_offset);
+      true_type = check_typedef (elttype);
+
+      true_type = lookup_array_range_type (true_type, 0, length - 1);
+      val = value_at (true_type, addr);
+      ptraddr = value_contents (val);
+
+      return d_val_print (true_type, ptraddr, 0, addr, stream, recurse + 1,
+			  options);
+    }
+  return -1;
+}
+
+/* Implements the la_val_print routine for language D.  */
+int
+d_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
+             CORE_ADDR address, struct ui_file *stream, int recurse,
+             const struct value_print_options *options)
+{
+  int ret;
+
+  CHECK_TYPEDEF (type);
+  switch (TYPE_CODE (type))
+    {
+      case TYPE_CODE_STRUCT:
+        ret = dynamic_array_type (type, valaddr, embedded_offset, address,
+				  stream, recurse, options);
+	if (ret != -1)
+	   break;
+      default:
+	ret = c_val_print (type, valaddr, embedded_offset, address, stream,
+			   recurse, options);
+    }
+
+  return ret;
+}
diff --git a/gdb/defs.h b/gdb/defs.h
index 2c4e5c4..71e8b3a 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -188,6 +188,7 @@ enum language
     language_auto,		/* Placeholder for automatic setting */
     language_c,			/* C */
     language_cplus,		/* C++ */
+    language_d,			/* D */
     language_objc,		/* Objective-C */
     language_java,		/* Java */
     language_fortran,		/* Fortran */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 3bb8ef9..5c199ff 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -214,6 +214,10 @@ You can use @value{GDBN} to debug programs written in C and C@t{++}.
 For more information, see @ref{Supported Languages,,Supported Languages}.
 For more information, see @ref{C,,C and C++}.
 
+@cindex D
+Support for D is partial.  For information on D, see
+@ref{D,,D}.
+
 @cindex Modula-2
 Support for Modula-2 is partial.  For information on Modula-2, see
 @ref{Modula-2,,Modula-2}.
@@ -10824,6 +10828,9 @@ C source file
 @itemx .c++
 C@t{++} source file
 
+@item .d
+D source file
+
 @item .m
 Objective-C source file
 
@@ -11101,7 +11108,7 @@ being set automatically by @value{GDBN}.
 @node Supported Languages
 @section Supported Languages
 
-@value{GDBN} supports C, C@t{++}, Objective-C, Fortran, Java, Pascal,
+@value{GDBN} supports C, C@t{++}, D, Objective-C, Fortran, Java, Pascal,
 assembly, Modula-2, and Ada.
 @c This is false ...
 Some @value{GDBN} features may be used in expressions regardless of the
@@ -11120,6 +11127,7 @@ language reference or tutorial.
 
 @menu
 * C::                           C and C@t{++}
+* D::                           D
 * Objective-C::                 Objective-C
 * Fortran::                     Fortran
 * Pascal::                      Pascal
@@ -11657,6 +11665,14 @@ In the PowerPC architecture, @value{GDBN} provides a set of pseudo-registers
 to inspect @code{_Decimal128} values stored in floating point registers.
 See @ref{PowerPC,,PowerPC} for more details.
 
+@node D
+@subsection D
+
+@cindex D
+@value{GDBN} can be used to debug programs written in D and compiled with
+GDC, LDC or DMD. Currently @value{GDBN} supports only one D specific
+feature - dynamic arrays.
+
 @node Objective-C
 @subsection Objective-C
 
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 3096ab7..f4cbc59 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -7619,6 +7619,9 @@ set_cu_language (unsigned int lang, struct dwarf2_cu *cu)
     case DW_LANG_C_plus_plus:
       cu->language = language_cplus;
       break;
+    case DW_LANG_D:
+      cu->language = language_d;
+      break;
     case DW_LANG_Fortran77:
     case DW_LANG_Fortran90:
     case DW_LANG_Fortran95:
diff --git a/gdb/language.c b/gdb/language.c
index dcd70b0..aba8a9e 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -486,6 +486,7 @@ binop_result_type (struct value *v1, struct value *v2)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       if (TYPE_CODE (t1) == TYPE_CODE_FLT)
 	return TYPE_CODE (t2) == TYPE_CODE_FLT && l2 > l1 ?
@@ -597,6 +598,7 @@ integral_type (struct type *type)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) != TYPE_CODE_INT) &&
 	(TYPE_CODE (type) != TYPE_CODE_ENUM) ? 0 : 1;
@@ -637,6 +639,7 @@ character_type (struct type *type)
 
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) == TYPE_CODE_INT) &&
 	TYPE_LENGTH (type) == sizeof (char)
@@ -659,6 +662,7 @@ string_type (struct type *type)
 
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       /* C does not have distinct string type. */
       return (0);
@@ -678,6 +682,7 @@ boolean_type (struct type *type)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       /* Might be more cleanly handled by having a
          TYPE_CODE_INT_NOT_BOOL for (the deleted) CHILL and such
@@ -717,6 +722,7 @@ structured_type (struct type *type)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) == TYPE_CODE_STRUCT) ||
 	(TYPE_CODE (type) == TYPE_CODE_UNION) ||
diff --git a/gdb/symfile.c b/gdb/symfile.c
index a02b2d2..e39a1f0 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -2616,6 +2616,7 @@ init_filename_language_table (void)
       filename_language_table =
 	xmalloc (fl_table_size * sizeof (*filename_language_table));
       add_filename_language (".c", language_c);
+      add_filename_language (".d", language_d);
       add_filename_language (".C", language_cplus);
       add_filename_language (".cc", language_cplus);
       add_filename_language (".cp", language_cplus);
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 1d6b648..67a784b 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -39,6 +39,7 @@
 #include "source.h"
 #include "filenames.h"		/* for FILENAME_CMP */
 #include "objc-lang.h"
+#include "d-lang.h"
 #include "ada-lang.h"
 #include "p-lang.h"
 #include "addrmap.h"
@@ -346,6 +347,7 @@ symbol_init_language_specific (struct general_symbol_info *gsymbol,
 {
   gsymbol->language = language;
   if (gsymbol->language == language_cplus
+      || gsymbol->language == language_d
       || gsymbol->language == language_java
       || gsymbol->language == language_objc)
     {
@@ -449,6 +451,16 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
 	  return demangled;
 	}
     }
+  if (gsymbol->language == language_d
+      || gsymbol->language == language_auto)
+    {
+      demangled = d_demangle(mangled, 0);
+      if (demangled != NULL)
+	{
+	  gsymbol->language = language_d;
+	  return demangled;
+	}
+    }
   return NULL;
 }
 
@@ -626,6 +638,7 @@ symbol_natural_name (const struct general_symbol_info *gsymbol)
   switch (gsymbol->language)
     {
     case language_cplus:
+    case language_d:
     case language_java:
     case language_objc:
       if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
@@ -651,6 +664,7 @@ symbol_demangled_name (const struct general_symbol_info *gsymbol)
   switch (gsymbol->language)
     {
     case language_cplus:
+    case language_d:
     case language_java:
     case language_objc:
       if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
@@ -940,7 +954,7 @@ lookup_symbol_in_language (const char *name, const struct block *block,
 
   modified_name = name;
 
-  /* If we are using C++ or Java, demangle the name before doing a lookup, so
+  /* If we are using C++, D, or Java, demangle the name before doing a lookup, so
      we can always binary search. */
   if (lang == language_cplus)
     {
@@ -972,6 +986,15 @@ lookup_symbol_in_language (const char *name, const struct block *block,
 	  make_cleanup (xfree, demangled_name);
 	}
     }
+  else if (lang == language_d)
+    {
+      demangled_name = d_demangle (name, 0);
+      if (demangled_name)
+	{
+	  modified_name = demangled_name;
+	  make_cleanup (xfree, demangled_name);
+	}
+    }
 
   if (case_sensitivity == case_sensitive_off)
     {
@@ -1412,6 +1435,7 @@ symbol_matches_domain (enum language symbol_language,
      A Java class declaration also defines a typedef for the class.
      Similarly, any Ada type declaration implicitly defines a typedef.  */
   if (symbol_language == language_cplus
+      || symbol_language == language_d
       || symbol_language == language_java
       || symbol_language == language_ada)
     {
diff --git a/gdb/testsuite/gdb.base/default.exp b/gdb/testsuite/gdb.base/default.exp
index 97d5407..2a13007 100644
--- a/gdb/testsuite/gdb.base/default.exp
+++ b/gdb/testsuite/gdb.base/default.exp
@@ -531,7 +531,7 @@ gdb_test "set history size" "Argument required .integer to set it to.*" "set his
 #test set history
 gdb_test "set history" "\"set history\" must be followed by the name of a history subcommand.(\[^\r\n\]*\[\r\n\])+List of set history subcommands:(\[^\r\n\]*\[\r\n\])+set history expansion -- Set history expansion on command input(\[^\r\n\]*\[\r\n\])+set history filename -- Set the filename in which to record the command history(\[^\r\n\]*\[\r\n\])+set history save -- Set saving of the history record on exit(\[^\r\n\]*\[\r\n\])+set history size -- Set the size of the command history(\[^\r\n\]*\[\r\n\])+Type \"help set history\" followed by set history subcommand name for full documentation.(\[^\r\n\]*\[\r\n\])+Command name abbreviations are allowed if unambiguous." "set history"
 #test set language
-gdb_test "set language" "Requires an argument. Valid arguments are auto, local, unknown, ada, c, c.., asm, minimal, fortran, objective-c, java, modula-2, pascal, scheme." "set language"
+gdb_test "set language" "Requires an argument. Valid arguments are auto, local, unknown, ada, c, c.., asm, minimal, d, fortran, objective-c, java, modula-2, pascal, scheme." "set language"
 #test set listsize
 gdb_test "set listsize" "Argument required .integer to set it to.*" "set listsize"
 #test set print "p" abbreviation

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-04-27 23:55                                 ` Mihail Zenkov
@ 2010-04-28 15:17                                   ` Joel Brobecker
  2010-04-28 17:11                                     ` Eli Zaretskii
  2010-04-29  2:16                                     ` Mihail Zenkov
  2010-04-28 17:10                                   ` Eli Zaretskii
  1 sibling, 2 replies; 33+ messages in thread
From: Joel Brobecker @ 2010-04-28 15:17 UTC (permalink / raw)
  To: Mihail Zenkov; +Cc: tromey, gdb-patches

Mihail,

> gdb/NEWS:
> * D language support.
>  Support for debugging the D programming language has been
>  integrated into GDB.
> gdb/ChangeLog:
> 	D language support.
> 	* Makefile.in (SFILES): Add d-lang.c d-valprint.c.
> 	(COMMON_OBS): Add d-lang.o d-valprint.o.
> 	(HFILES_NO_SRCDIR): Add d-lang.h.
> 	* c-lang.c (c_emit_char, exp_descriptor_c): Make public.
> 	* c-lang.h (c_emit_char, exp_descriptor_c): Add declaration.
> 	* d-lang.c: New file.
> 	* d-lang.h: New file.
> 	* d-valprint.c: New file.
> 	* defs.h (enum language): Add language_d.
> 	* dwarf2read.c (set_cu_language): Add DW_LANG_D.
> 	* language.c (binop_result_type, integral_type, character_type) 
> 	(string_type, boolean_type, structured_type): Add language_d.
> 	* symfile.c (init_filename_language_table): Add language_d.
> 	* symtab.c: Include d-lang.h.
> 	(symbol_init_language_specific, symbol_find_demangled_name)
> 	(symbol_natural_name, lookup_symbol_in_language)
> 	(symbol_demangled_name, symbol_matches_domain): Add language_d.
> gdb/doc/ChangeLog:
> 	* gdb.texinfo: Add mention about D language support.
> gdb/testsuite/ChangeLog:
> 	* gdb.base/default.exp: Fix "set language" test.

The patch is approved (good job!).

A couple of technical items:

  - Has the modification to gdb/NEWS been approved by Eli? If not,
    it has to be reviewed and approved by him.  Also, when you do
    commit the change, the NEWS file is similar to all other files,
    so it means that you have to send a diff, and provide a ChangeLog
    entry. Hence, the following...

         > gdb/NEWS:
         > * D language support.
         >  Support for debugging the D programming language has been
         >  integrated into GDB.

    ... does not follow the procedures (we don't know where you plan
    to insert this entry, for instance).

  - Now that you have submitted one good patch, you qualify for having
    write access to the GDB repository.  Should you be interested, let
    us know, and I'll send you some pointers.

-- 
Joel

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-04-27 23:55                                 ` Mihail Zenkov
  2010-04-28 15:17                                   ` Joel Brobecker
@ 2010-04-28 17:10                                   ` Eli Zaretskii
  2010-04-29  1:59                                     ` Mihail Zenkov
  1 sibling, 1 reply; 33+ messages in thread
From: Eli Zaretskii @ 2010-04-28 17:10 UTC (permalink / raw)
  To: Mihail Zenkov; +Cc: brobecker, mihail.zenkov, tromey, gdb-patches

> Date: Wed, 28 Apr 2010 02:53:34 +0300
> From: Mihail Zenkov <mihail.zenkov@gmail.com>
> Cc: Mihail Zenkov <mihail.zenkov@gmail.com>, tromey@redhat.com,  gdb-patches@sourceware.org
> 
> gdb/NEWS:
> * D language support.
>  Support for debugging the D programming language has been
>  integrated into GDB.

Suggest to say this instead:

   GDB now supports debugging programs written in the D programming
   language.

> gdb/doc/ChangeLog:
> 	* gdb.texinfo: Add mention about D language support.

The ChangeLog entry should include the name(s) of node(s) added to the
manual.

> +@cindex D
> +Support for D is partial.  For information on D, see
> +@ref{D,,D}.

Please remove the @cindex entry from here.  You already have one in
the section where the D support is described; having another identical
index entry pointing here, where D is not described at all, is not
useful.  The index entries are for readers who are looking for a
description of some specific subject, so they should point to the place
where that subject is described in full.

> +@value{GDBN} can be used to debug programs written in D and compiled with
> +GDC, LDC or DMD.

Suggest to add "compilers" to the end of this sentence.  Also, please
leave two spaces between sentences.

> Currently @value{GDBN} supports only one D specific
> +feature - dynamic arrays.
           ^
Please use "---" (3 dashes in a row) to produce an em-dash.

Okay with those changes.

Thanks.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-04-28 15:17                                   ` Joel Brobecker
@ 2010-04-28 17:11                                     ` Eli Zaretskii
  2010-04-29  2:16                                     ` Mihail Zenkov
  1 sibling, 0 replies; 33+ messages in thread
From: Eli Zaretskii @ 2010-04-28 17:11 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: mihail.zenkov, tromey, gdb-patches

> Date: Wed, 28 Apr 2010 08:17:17 -0700
> From: Joel Brobecker <brobecker@adacore.com>
> Cc: tromey@redhat.com, gdb-patches@sourceware.org
> 
>   - Has the modification to gdb/NEWS been approved by Eli?

It has been now.

Posting patches encoded in base64 always runs a risk to evade my
eyes.  Sorry.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-04-28 17:10                                   ` Eli Zaretskii
@ 2010-04-29  1:59                                     ` Mihail Zenkov
  2010-04-29  3:10                                       ` Eli Zaretskii
  2010-04-29 14:47                                       ` Joel Brobecker
  0 siblings, 2 replies; 33+ messages in thread
From: Mihail Zenkov @ 2010-04-29  1:59 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Mihail Zenkov, brobecker, tromey, gdb-patches

[-- Attachment #1: Type: text/plain, Size: 1613 bytes --]

On Wed, 28 Apr 2010 20:09:49 +0300
Eli Zaretskii <eliz@gnu.org> wrote:

> > Date: Wed, 28 Apr 2010 02:53:34 +0300
> > From: Mihail Zenkov <mihail.zenkov@gmail.com>
> > Cc: Mihail Zenkov <mihail.zenkov@gmail.com>, tromey@redhat.com,  gdb-patches@sourceware.org
> > 
> > gdb/NEWS:
> > * D language support.
> >  Support for debugging the D programming language has been
> >  integrated into GDB.
> 
> Suggest to say this instead:
> 
>    GDB now supports debugging programs written in the D programming
>    language.
> 
> > gdb/doc/ChangeLog:
> > 	* gdb.texinfo: Add mention about D language support.
> 
> The ChangeLog entry should include the name(s) of node(s) added to the
> manual.
> 
> > +@cindex D
> > +Support for D is partial.  For information on D, see
> > +@ref{D,,D}.
> 
> Please remove the @cindex entry from here.  You already have one in
> the section where the D support is described; having another identical
> index entry pointing here, where D is not described at all, is not
> useful.  The index entries are for readers who are looking for a
> description of some specific subject, so they should point to the place
> where that subject is described in full.
> 
> > +@value{GDBN} can be used to debug programs written in D and compiled with
> > +GDC, LDC or DMD.
> 
> Suggest to add "compilers" to the end of this sentence.  Also, please
> leave two spaces between sentences.
> 
> > Currently @value{GDBN} supports only one D specific
> > +feature - dynamic arrays.
>            ^
> Please use "---" (3 dashes in a row) to produce an em-dash.
> 
> Okay with those changes.
> 
> Thanks.

Fixed.

[-- Attachment #2: gdb-100429-d.patch --]
[-- Type: application/octet-stream, Size: 27606 bytes --]

gdb/ChangeLog:
	D language support.
	* Makefile.in (SFILES): Add d-lang.c d-valprint.c.
	(COMMON_OBS): Add d-lang.o d-valprint.o.
	(HFILES_NO_SRCDIR): Add d-lang.h.
	* NEWS: Mention D language support.
	* c-lang.c (c_emit_char, exp_descriptor_c): Make public.
	* c-lang.h (c_emit_char, exp_descriptor_c): Add declaration.
	* d-lang.c: New file.
	* d-lang.h: New file.
	* d-valprint.c: New file.
	* defs.h (enum language): Add language_d.
	* dwarf2read.c (set_cu_language): Add DW_LANG_D.
	* language.c (binop_result_type, integral_type, character_type) 
	(string_type, boolean_type, structured_type): Add language_d.
	* symfile.c (init_filename_language_table): Add language_d.
	* symtab.c: Include d-lang.h.
	(symbol_init_language_specific, symbol_find_demangled_name)
	(symbol_natural_name, lookup_symbol_in_language)
	(symbol_demangled_name, symbol_matches_domain): Add language_d.
gdb/doc/ChangeLog:
	* gdb.texinfo: (Summary) Add mention about D language support.
	(Filenames): Add D suffixes.
	(D): New node.
gdb/testsuite/ChangeLog:
	* gdb.base/default.exp: Fix "set language" test.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 750fdfd..cbbd813 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -658,6 +658,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	charset.c cli-out.c coffread.c coff-pe-read.c \
 	complaints.c completer.c corefile.c \
 	cp-abi.c cp-support.c cp-namespace.c cp-valprint.c \
+	d-lang.c d-valprint.c \
 	cp-name-parser.y \
 	dbxread.c demangle.c dictionary.c disasm.c doublest.c dummy-frame.c \
 	dwarf2expr.c dwarf2loc.c dwarf2read.c dwarf2-frame.c \
@@ -725,7 +726,7 @@ cli-out.h gdb_expat.h breakpoint.h infcall.h obsd-tdep.h \
 exec.h m32r-tdep.h osabi.h gdbcore.h solib-som.h \
 i386bsd-nat.h xml-support.h xml-tdesc.h alphabsd-tdep.h gdb_obstack.h \
 ia64-tdep.h ada-lang.h varobj.h frv-tdep.h nto-tdep.h serial.h \
-c-lang.h frame.h event-loop.h block.h cli/cli-setshow.h	\
+c-lang.h d-lang.h frame.h event-loop.h block.h cli/cli-setshow.h	\
 cli/cli-decode.h cli/cli-cmds.h cli/cli-dump.h \
 cli/cli-script.h macrotab.h symtab.h version.h gnulib/wchar.in.h \
 gnulib/string.in.h gnulib/str-two-way.h gnulib/extra/link-warning.h \
@@ -831,7 +832,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	dbxread.o coffread.o coff-pe-read.o \
 	dwarf2read.o mipsread.o stabsread.o corefile.o \
 	dwarf2expr.o dwarf2loc.o dwarf2-frame.o \
-	ada-lang.o c-lang.o f-lang.o objc-lang.o \
+	ada-lang.o c-lang.o d-lang.o f-lang.o objc-lang.o \
 	ada-tasks.o \
 	ui-out.o cli-out.o \
 	varobj.o vec.o wrapper.o \
@@ -841,7 +842,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	sentinel-frame.o \
 	complaints.o typeprint.o \
 	ada-typeprint.o c-typeprint.o f-typeprint.o m2-typeprint.o \
-	ada-valprint.o c-valprint.o cp-valprint.o f-valprint.o m2-valprint.o \
+	ada-valprint.o c-valprint.o cp-valprint.o d-valprint.o f-valprint.o \
+	m2-valprint.o \
 	serial.o mdebugread.o top.o utils.o \
 	ui-file.o \
 	user-regs.o \
diff --git a/gdb/NEWS b/gdb/NEWS
index 696da2e..99254c9 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -100,6 +100,10 @@ regular breakpoints.
 
 ARM Symbian			arm*-*-symbianelf*
 
+* D language support.
+  GDB now supports debugging programs written in the D programming
+  language.
+
 *** Changes in GDB 7.1
 
 * C++ Improvements
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 805c572..aa69f94 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -253,8 +253,9 @@ print_wchar (gdb_wint_t w, const gdb_byte *orig, int orig_len,
    string whose delimiter is QUOTER.  Note that that format for printing
    characters and strings is language specific. */
 
-static void
-c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter)
+void
+c_emit_char (int c, struct type *type,
+	     struct ui_file *stream, int quoter)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
   struct obstack wchar_buf, output;
@@ -1135,7 +1136,7 @@ c_language_arch_info (struct gdbarch *gdbarch,
   lai->bool_type_default = builtin->builtin_int;
 }
 
-static const struct exp_descriptor exp_descriptor_c = 
+const struct exp_descriptor exp_descriptor_c = 
 {
   print_subexp_standard,
   operator_length_standard,
diff --git a/gdb/c-lang.h b/gdb/c-lang.h
index 423cee0..c2cdd56 100644
--- a/gdb/c-lang.h
+++ b/gdb/c-lang.h
@@ -87,6 +87,11 @@ extern void c_printstr (struct ui_file * stream, struct type *elttype,
 extern void c_language_arch_info (struct gdbarch *gdbarch,
 				  struct language_arch_info *lai);
 
+extern const struct exp_descriptor exp_descriptor_c;
+
+extern void c_emit_char (int c, struct type *type,
+			 struct ui_file *stream, int quoter);
+
 /* These are in c-typeprint.c: */
 
 extern void c_type_print_base (struct type *, struct ui_file *, int, int);
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
new file mode 100644
index 0000000..6db521b
--- /dev/null
+++ b/gdb/d-lang.c
@@ -0,0 +1,278 @@
+/* D language support routines for GDB, the GNU debugger.
+
+   Copyright (C) 2005, 2006, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "symtab.h"
+#include "language.h"
+#include "d-lang.h"
+#include "c-lang.h"
+#include "gdb_string.h"
+#include "parser-defs.h"
+#include "gdb_obstack.h"
+
+#include <ctype.h>
+
+/* Extract identifiers from MANGLED_STR and append it to TEMPBUF.
+   Return 1 on success or 0 on failure.  */
+static int
+extract_identifiers (const char *mangled_str, struct obstack *tempbuf)
+{
+  long i = 0;
+
+  while (isdigit (*mangled_str))
+    {
+      i = strtol (mangled_str, NULL, 10);
+      mangled_str++;
+      if (i <= 0  && strlen (mangled_str) < i)
+        return 0;
+      obstack_grow (tempbuf, mangled_str, i);
+      mangled_str += i;
+      obstack_grow_str (tempbuf, ".");
+    }
+  if (*mangled_str == '\0' || i == 0)
+    return 0;
+  obstack_blank (tempbuf, -1);
+  return 1;
+}
+
+/* Extract and demangle type from MANGLED_STR and append it to TEMPBUF.
+   Return 1 on success or 0 on failure.  */
+static int
+extract_type_info (const char *mangled_str, struct obstack *tempbuf)
+{
+  if (*mangled_str == '\0')
+    return 0;
+  switch (*mangled_str++)
+    {
+      case 'A': /* dynamic array */
+      case 'G': /* static array */
+      case 'H': /* associative array */
+	if (!extract_type_info (mangled_str, tempbuf))
+	  return 0;
+	obstack_grow_str (tempbuf, "[]");
+	return 1;
+      case 'P': /* pointer */
+	if (!extract_type_info (mangled_str, tempbuf))
+	  return 0;
+	obstack_grow_str (tempbuf, "*");
+	return 1;
+      case 'R': /* reference */
+	if (!extract_type_info (mangled_str, tempbuf))
+	  return 0;
+	obstack_grow_str (tempbuf, "&");
+	return 1;
+      case 'Z': /* return value */
+	return extract_type_info (mangled_str, tempbuf);
+      case 'J': /* out */
+	obstack_grow_str (tempbuf, "out ");
+	return extract_type_info (mangled_str, tempbuf);
+      case 'K': /* inout */
+	obstack_grow_str (tempbuf, "inout ");
+	return extract_type_info (mangled_str, tempbuf);
+      case 'E': /* enum */
+      case 'T': /* typedef */
+      case 'D': /* delegate */
+      case 'C': /* class */
+      case 'S': /* struct */
+	return extract_identifiers (mangled_str, tempbuf);
+
+      /* basic types: */
+      case 'n': obstack_grow_str (tempbuf, "none"); return 1;
+      case 'v': obstack_grow_str (tempbuf, "void"); return 1;
+      case 'g': obstack_grow_str (tempbuf, "byte"); return 1;
+      case 'h': obstack_grow_str (tempbuf, "ubyte"); return 1;
+      case 's': obstack_grow_str (tempbuf, "short"); return 1;
+      case 't': obstack_grow_str (tempbuf, "ushort"); return 1;
+      case 'i': obstack_grow_str (tempbuf, "int"); return 1;
+      case 'k': obstack_grow_str (tempbuf, "uint"); return 1;
+      case 'l': obstack_grow_str (tempbuf, "long"); return 1;
+      case 'm': obstack_grow_str (tempbuf, "ulong"); return 1;
+      case 'f': obstack_grow_str (tempbuf, "float"); return 1;
+      case 'd': obstack_grow_str (tempbuf, "double"); return 1;
+      case 'e': obstack_grow_str (tempbuf, "real"); return 1;
+
+      /* imaginary and complex: */
+      case 'o': obstack_grow_str (tempbuf, "ifloat"); return 1;
+      case 'p': obstack_grow_str (tempbuf, "idouble"); return 1;
+      case 'j': obstack_grow_str (tempbuf, "ireal"); return 1;
+      case 'q': obstack_grow_str (tempbuf, "cfloat"); return 1;
+      case 'r': obstack_grow_str (tempbuf, "cdouble"); return 1;
+      case 'c': obstack_grow_str (tempbuf, "creal"); return 1;
+
+      /* other types: */
+      case 'b': obstack_grow_str (tempbuf, "bit"); return 1;
+      case 'a': obstack_grow_str (tempbuf, "char"); return 1;
+      case 'u': obstack_grow_str (tempbuf, "wchar"); return 1;
+      case 'w': obstack_grow_str (tempbuf, "dchar"); return 1;
+
+      default:
+	obstack_grow_str (tempbuf, "unknown");
+	return 1;
+    }
+}
+
+/* Implements the la_demangle language_defn routine for language D.  */
+char *
+d_demangle (const char *symbol, int options)
+{
+  struct obstack tempbuf;
+  char *out_str;
+  unsigned char is_func = 0;
+
+  if (symbol == NULL)
+    return NULL;
+  else if (strcmp (symbol, "_Dmain") == 0)
+    return xstrdup ("D main");
+
+  obstack_init (&tempbuf);
+  
+  if (symbol[0] == '_' && symbol[1] == 'D')
+    {
+      symbol += 2;
+      is_func = 1;
+    }
+  else if (strncmp (symbol, "__Class_", 8) == 0)
+    symbol += 8;
+  else if (strncmp (symbol, "__init_", 7) == 0)
+    symbol += 7;
+  else if (strncmp (symbol, "__vtbl_", 7) == 0)
+    symbol += 7;
+  else if (strncmp (symbol, "__modctor_", 10) == 0)
+    symbol += 10;
+  else if (strncmp (symbol, "__moddtor_", 10) == 0)
+    symbol += 10;
+  else if (strncmp (symbol, "__ModuleInfo_", 13) == 0)
+    symbol += 13;
+  else
+    {
+      obstack_free (&tempbuf, NULL);
+      return NULL;
+    }
+  
+  if (!extract_identifiers (symbol, &tempbuf))
+    {
+      obstack_free (&tempbuf, NULL);
+      return NULL;
+    }
+
+  obstack_grow_str (&tempbuf, "(");
+  if (is_func == 1 && *symbol == 'F')
+    {
+      symbol++;
+      while (*symbol != '\0' && *symbol != 'Z')
+	{
+	  if (is_func == 1)
+	    is_func++;
+	  else
+	    obstack_grow_str (&tempbuf, ", ");
+	  if (!extract_type_info (symbol, &tempbuf))
+	    {
+	      obstack_free (&tempbuf, NULL);
+	      return NULL;
+	   }
+	}
+     }
+  obstack_grow_str0 (&tempbuf, ")");
+
+  /* Doesn't display the return type, but wouldn't be too hard to do.  */
+
+  out_str = xstrdup (obstack_finish (&tempbuf));
+  obstack_free (&tempbuf, NULL);
+  return out_str;
+}
+
+/* Table mapping opcodes into strings for printing operators
+   and precedences of the operators.  */
+static const struct op_print d_op_print_tab[] =
+{
+  {",", BINOP_COMMA, PREC_COMMA, 0},
+  {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
+  {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
+  {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
+  {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
+  {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
+  {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
+  {"==", BINOP_EQUAL, PREC_EQUAL, 0},
+  {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
+  {"<=", BINOP_LEQ, PREC_ORDER, 0},
+  {">=", BINOP_GEQ, PREC_ORDER, 0},
+  {">", BINOP_GTR, PREC_ORDER, 0},
+  {"<", BINOP_LESS, PREC_ORDER, 0},
+  {">>", BINOP_RSH, PREC_SHIFT, 0},
+  {"<<", BINOP_LSH, PREC_SHIFT, 0},
+  {"+", BINOP_ADD, PREC_ADD, 0},
+  {"-", BINOP_SUB, PREC_ADD, 0},
+  {"*", BINOP_MUL, PREC_MUL, 0},
+  {"/", BINOP_DIV, PREC_MUL, 0},
+  {"%", BINOP_REM, PREC_MUL, 0},
+  {"@", BINOP_REPEAT, PREC_REPEAT, 0},
+  {"-", UNOP_NEG, PREC_PREFIX, 0},
+  {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
+  {"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
+  {"*", UNOP_IND, PREC_PREFIX, 0},
+  {"&", UNOP_ADDR, PREC_PREFIX, 0},
+  {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
+  {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
+  {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
+  {NULL, 0, 0, 0}
+};
+
+static const struct language_defn d_language_defn =
+{
+  "d",
+  language_d,
+  range_check_off,
+  type_check_off,
+  case_sensitive_on,
+  array_row_major,
+  macro_expansion_c,
+  &exp_descriptor_c,
+  c_parse,
+  c_error,
+  null_post_parser,
+  c_printchar,			/* Print a character constant.  */
+  c_printstr,			/* Function to print string constant.  */
+  c_emit_char,			/* Print a single char.  */
+  c_print_type,			/* Print a type using appropriate syntax.  */
+  c_print_typedef,		/* Print a typedef using appropriate syntax.  */
+  d_val_print,			/* Print a value using appropriate syntax.  */
+  c_value_print,		/* Print a top-level value.  */
+  NULL,				/* Language specific skip_trampoline.  */
+  "this",
+  basic_lookup_symbol_nonlocal, 
+  basic_lookup_transparent_type,
+  d_demangle,			/* Language specific symbol demangler.  */
+  NULL,				/* Language specific class_name_from_physname.  */
+  d_op_print_tab,		/* Expression operators for printing.  */
+  1,				/* C-style arrays.  */
+  0,				/* String lower bound.  */
+  default_word_break_characters,
+  default_make_symbol_completion_list,
+  c_language_arch_info,
+  default_print_array_index,
+  default_pass_by_reference,
+  c_get_string,
+  LANG_MAGIC
+};
+
+void
+_initialize_d_language (void)
+{
+  add_language (&d_language_defn);
+}
diff --git a/gdb/d-lang.h b/gdb/d-lang.h
new file mode 100644
index 0000000..be27827
--- /dev/null
+++ b/gdb/d-lang.h
@@ -0,0 +1,32 @@
+/* D language support definitions for GDB, the GNU debugger.
+
+   Copyright (C) 2005, 2006, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#if !defined (D_LANG_H)
+#define D_LANG_H 1
+
+#include "symtab.h"
+
+extern char *d_demangle (const char *mangled, int options);
+
+extern int d_val_print (struct type *type, const gdb_byte *valaddr,
+			int embedded_offset, CORE_ADDR address,
+			struct ui_file *stream, int recurse,
+			const struct value_print_options *options);
+
+#endif /* !defined (D_LANG_H) */
diff --git a/gdb/d-valprint.c b/gdb/d-valprint.c
new file mode 100644
index 0000000..67b32b7
--- /dev/null
+++ b/gdb/d-valprint.c
@@ -0,0 +1,91 @@
+/* Support for printing D values for GDB, the GNU debugger.
+
+   Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "gdbcore.h"
+#include "d-lang.h"
+#include "c-lang.h"
+
+/* Assuming that TYPE is a TYPE_CODE_STRUCT, verify that TYPE is
+   a dynamic array, and then print its value to STREAM.  Return
+   the number of string characters printed, or -1 if TYPE is not
+   a dynamic array.  */
+static int
+dynamic_array_type (struct type *type, const gdb_byte *valaddr,
+		    int embedded_offset, CORE_ADDR address,
+		    struct ui_file *stream, int recurse,
+		    const struct value_print_options *options)
+{
+  if (TYPE_NFIELDS (type) == 2
+      && TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_INT
+      && strcmp (TYPE_FIELD_NAME (type, 0), "length") == 0
+      && strcmp (TYPE_FIELD_NAME (type, 1), "ptr") == 0)
+    {
+      CORE_ADDR addr;
+      struct type *elttype;
+      struct type *true_type;
+      struct type *ptr_type;
+      struct type *range_type;
+      const gdb_byte *ptraddr;
+      struct value *val;
+      int length;
+
+      length = unpack_field_as_long (type, valaddr + embedded_offset, 0);
+
+      ptr_type = TYPE_FIELD_TYPE (type, 1);
+      elttype = check_typedef (TYPE_TARGET_TYPE (ptr_type));
+      addr = unpack_pointer (ptr_type,
+			     valaddr + TYPE_FIELD_BITPOS (type, 1) / 8
+			     + embedded_offset);
+      true_type = check_typedef (elttype);
+
+      true_type = lookup_array_range_type (true_type, 0, length - 1);
+      val = value_at (true_type, addr);
+      ptraddr = value_contents (val);
+
+      return d_val_print (true_type, ptraddr, 0, addr, stream, recurse + 1,
+			  options);
+    }
+  return -1;
+}
+
+/* Implements the la_val_print routine for language D.  */
+int
+d_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
+             CORE_ADDR address, struct ui_file *stream, int recurse,
+             const struct value_print_options *options)
+{
+  int ret;
+
+  CHECK_TYPEDEF (type);
+  switch (TYPE_CODE (type))
+    {
+      case TYPE_CODE_STRUCT:
+        ret = dynamic_array_type (type, valaddr, embedded_offset, address,
+				  stream, recurse, options);
+	if (ret != -1)
+	   break;
+      default:
+	ret = c_val_print (type, valaddr, embedded_offset, address, stream,
+			   recurse, options);
+    }
+
+  return ret;
+}
diff --git a/gdb/defs.h b/gdb/defs.h
index 2c4e5c4..71e8b3a 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -188,6 +188,7 @@ enum language
     language_auto,		/* Placeholder for automatic setting */
     language_c,			/* C */
     language_cplus,		/* C++ */
+    language_d,			/* D */
     language_objc,		/* Objective-C */
     language_java,		/* Java */
     language_fortran,		/* Fortran */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 3bb8ef9..02bd212 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -214,6 +214,9 @@ You can use @value{GDBN} to debug programs written in C and C@t{++}.
 For more information, see @ref{Supported Languages,,Supported Languages}.
 For more information, see @ref{C,,C and C++}.
 
+Support for D is partial.  For information on D, see
+@ref{D,,D}.
+
 @cindex Modula-2
 Support for Modula-2 is partial.  For information on Modula-2, see
 @ref{Modula-2,,Modula-2}.
@@ -10824,6 +10827,9 @@ C source file
 @itemx .c++
 C@t{++} source file
 
+@item .d
+D source file
+
 @item .m
 Objective-C source file
 
@@ -11101,7 +11107,7 @@ being set automatically by @value{GDBN}.
 @node Supported Languages
 @section Supported Languages
 
-@value{GDBN} supports C, C@t{++}, Objective-C, Fortran, Java, Pascal,
+@value{GDBN} supports C, C@t{++}, D, Objective-C, Fortran, Java, Pascal,
 assembly, Modula-2, and Ada.
 @c This is false ...
 Some @value{GDBN} features may be used in expressions regardless of the
@@ -11120,6 +11126,7 @@ language reference or tutorial.
 
 @menu
 * C::                           C and C@t{++}
+* D::                           D
 * Objective-C::                 Objective-C
 * Fortran::                     Fortran
 * Pascal::                      Pascal
@@ -11657,6 +11664,14 @@ In the PowerPC architecture, @value{GDBN} provides a set of pseudo-registers
 to inspect @code{_Decimal128} values stored in floating point registers.
 See @ref{PowerPC,,PowerPC} for more details.
 
+@node D
+@subsection D
+
+@cindex D
+@value{GDBN} can be used to debug programs written in D and compiled with
+GDC, LDC or DMD compilers. Currently @value{GDBN} supports only one D
+specific feature --- dynamic arrays.
+
 @node Objective-C
 @subsection Objective-C
 
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 3096ab7..f4cbc59 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -7619,6 +7619,9 @@ set_cu_language (unsigned int lang, struct dwarf2_cu *cu)
     case DW_LANG_C_plus_plus:
       cu->language = language_cplus;
       break;
+    case DW_LANG_D:
+      cu->language = language_d;
+      break;
     case DW_LANG_Fortran77:
     case DW_LANG_Fortran90:
     case DW_LANG_Fortran95:
diff --git a/gdb/language.c b/gdb/language.c
index dcd70b0..aba8a9e 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -486,6 +486,7 @@ binop_result_type (struct value *v1, struct value *v2)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       if (TYPE_CODE (t1) == TYPE_CODE_FLT)
 	return TYPE_CODE (t2) == TYPE_CODE_FLT && l2 > l1 ?
@@ -597,6 +598,7 @@ integral_type (struct type *type)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) != TYPE_CODE_INT) &&
 	(TYPE_CODE (type) != TYPE_CODE_ENUM) ? 0 : 1;
@@ -637,6 +639,7 @@ character_type (struct type *type)
 
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) == TYPE_CODE_INT) &&
 	TYPE_LENGTH (type) == sizeof (char)
@@ -659,6 +662,7 @@ string_type (struct type *type)
 
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       /* C does not have distinct string type. */
       return (0);
@@ -678,6 +682,7 @@ boolean_type (struct type *type)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       /* Might be more cleanly handled by having a
          TYPE_CODE_INT_NOT_BOOL for (the deleted) CHILL and such
@@ -717,6 +722,7 @@ structured_type (struct type *type)
     {
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) == TYPE_CODE_STRUCT) ||
 	(TYPE_CODE (type) == TYPE_CODE_UNION) ||
diff --git a/gdb/symfile.c b/gdb/symfile.c
index a02b2d2..e39a1f0 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -2616,6 +2616,7 @@ init_filename_language_table (void)
       filename_language_table =
 	xmalloc (fl_table_size * sizeof (*filename_language_table));
       add_filename_language (".c", language_c);
+      add_filename_language (".d", language_d);
       add_filename_language (".C", language_cplus);
       add_filename_language (".cc", language_cplus);
       add_filename_language (".cp", language_cplus);
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 1d6b648..67a784b 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -39,6 +39,7 @@
 #include "source.h"
 #include "filenames.h"		/* for FILENAME_CMP */
 #include "objc-lang.h"
+#include "d-lang.h"
 #include "ada-lang.h"
 #include "p-lang.h"
 #include "addrmap.h"
@@ -346,6 +347,7 @@ symbol_init_language_specific (struct general_symbol_info *gsymbol,
 {
   gsymbol->language = language;
   if (gsymbol->language == language_cplus
+      || gsymbol->language == language_d
       || gsymbol->language == language_java
       || gsymbol->language == language_objc)
     {
@@ -449,6 +451,16 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
 	  return demangled;
 	}
     }
+  if (gsymbol->language == language_d
+      || gsymbol->language == language_auto)
+    {
+      demangled = d_demangle(mangled, 0);
+      if (demangled != NULL)
+	{
+	  gsymbol->language = language_d;
+	  return demangled;
+	}
+    }
   return NULL;
 }
 
@@ -626,6 +638,7 @@ symbol_natural_name (const struct general_symbol_info *gsymbol)
   switch (gsymbol->language)
     {
     case language_cplus:
+    case language_d:
     case language_java:
     case language_objc:
       if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
@@ -651,6 +664,7 @@ symbol_demangled_name (const struct general_symbol_info *gsymbol)
   switch (gsymbol->language)
     {
     case language_cplus:
+    case language_d:
     case language_java:
     case language_objc:
       if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
@@ -940,7 +954,7 @@ lookup_symbol_in_language (const char *name, const struct block *block,
 
   modified_name = name;
 
-  /* If we are using C++ or Java, demangle the name before doing a lookup, so
+  /* If we are using C++, D, or Java, demangle the name before doing a lookup, so
      we can always binary search. */
   if (lang == language_cplus)
     {
@@ -972,6 +986,15 @@ lookup_symbol_in_language (const char *name, const struct block *block,
 	  make_cleanup (xfree, demangled_name);
 	}
     }
+  else if (lang == language_d)
+    {
+      demangled_name = d_demangle (name, 0);
+      if (demangled_name)
+	{
+	  modified_name = demangled_name;
+	  make_cleanup (xfree, demangled_name);
+	}
+    }
 
   if (case_sensitivity == case_sensitive_off)
     {
@@ -1412,6 +1435,7 @@ symbol_matches_domain (enum language symbol_language,
      A Java class declaration also defines a typedef for the class.
      Similarly, any Ada type declaration implicitly defines a typedef.  */
   if (symbol_language == language_cplus
+      || symbol_language == language_d
       || symbol_language == language_java
       || symbol_language == language_ada)
     {
diff --git a/gdb/testsuite/gdb.base/default.exp b/gdb/testsuite/gdb.base/default.exp
index 97d5407..2a13007 100644
--- a/gdb/testsuite/gdb.base/default.exp
+++ b/gdb/testsuite/gdb.base/default.exp
@@ -531,7 +531,7 @@ gdb_test "set history size" "Argument required .integer to set it to.*" "set his
 #test set history
 gdb_test "set history" "\"set history\" must be followed by the name of a history subcommand.(\[^\r\n\]*\[\r\n\])+List of set history subcommands:(\[^\r\n\]*\[\r\n\])+set history expansion -- Set history expansion on command input(\[^\r\n\]*\[\r\n\])+set history filename -- Set the filename in which to record the command history(\[^\r\n\]*\[\r\n\])+set history save -- Set saving of the history record on exit(\[^\r\n\]*\[\r\n\])+set history size -- Set the size of the command history(\[^\r\n\]*\[\r\n\])+Type \"help set history\" followed by set history subcommand name for full documentation.(\[^\r\n\]*\[\r\n\])+Command name abbreviations are allowed if unambiguous." "set history"
 #test set language
-gdb_test "set language" "Requires an argument. Valid arguments are auto, local, unknown, ada, c, c.., asm, minimal, fortran, objective-c, java, modula-2, pascal, scheme." "set language"
+gdb_test "set language" "Requires an argument. Valid arguments are auto, local, unknown, ada, c, c.., asm, minimal, d, fortran, objective-c, java, modula-2, pascal, scheme." "set language"
 #test set listsize
 gdb_test "set listsize" "Argument required .integer to set it to.*" "set listsize"
 #test set print "p" abbreviation

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-04-28 15:17                                   ` Joel Brobecker
  2010-04-28 17:11                                     ` Eli Zaretskii
@ 2010-04-29  2:16                                     ` Mihail Zenkov
  1 sibling, 0 replies; 33+ messages in thread
From: Mihail Zenkov @ 2010-04-29  2:16 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: Mihail Zenkov, tromey, gdb-patches

>   - Now that you have submitted one good patch, you qualify for having
>     write access to the GDB repository.  Should you be interested, let
>     us know, and I'll send you some pointers.

Thanks. But IMHO I need some more of practice with GNU standards before
I have write access :) Probably after few patches I take advantage of your offer.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-04-29  1:59                                     ` Mihail Zenkov
@ 2010-04-29  3:10                                       ` Eli Zaretskii
  2010-04-29 14:47                                       ` Joel Brobecker
  1 sibling, 0 replies; 33+ messages in thread
From: Eli Zaretskii @ 2010-04-29  3:10 UTC (permalink / raw)
  To: Mihail Zenkov; +Cc: mihail.zenkov, brobecker, tromey, gdb-patches

> Date: Thu, 29 Apr 2010 04:56:46 +0300
> From: Mihail Zenkov <mihail.zenkov@gmail.com>
> Cc: Mihail Zenkov <mihail.zenkov@gmail.com>, brobecker@adacore.com,
>  tromey@redhat.com, gdb-patches@sourceware.org
> 
> > Okay with those changes.
> > 
> > Thanks.
> 
> Fixed.

This version is fine with me.  Thanks.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: D language support
  2010-04-29  1:59                                     ` Mihail Zenkov
  2010-04-29  3:10                                       ` Eli Zaretskii
@ 2010-04-29 14:47                                       ` Joel Brobecker
  1 sibling, 0 replies; 33+ messages in thread
From: Joel Brobecker @ 2010-04-29 14:47 UTC (permalink / raw)
  To: Mihail Zenkov; +Cc: Eli Zaretskii, tromey, gdb-patches

> gdb/ChangeLog:
> 	D language support.
> 	* Makefile.in (SFILES): Add d-lang.c d-valprint.c.
> 	(COMMON_OBS): Add d-lang.o d-valprint.o.
> 	(HFILES_NO_SRCDIR): Add d-lang.h.
> 	* NEWS: Mention D language support.
> 	* c-lang.c (c_emit_char, exp_descriptor_c): Make public.
> 	* c-lang.h (c_emit_char, exp_descriptor_c): Add declaration.
> 	* d-lang.c: New file.
> 	* d-lang.h: New file.
> 	* d-valprint.c: New file.
> 	* defs.h (enum language): Add language_d.
> 	* dwarf2read.c (set_cu_language): Add DW_LANG_D.
> 	* language.c (binop_result_type, integral_type, character_type) 
> 	(string_type, boolean_type, structured_type): Add language_d.
> 	* symfile.c (init_filename_language_table): Add language_d.
> 	* symtab.c: Include d-lang.h.
> 	(symbol_init_language_specific, symbol_find_demangled_name)
> 	(symbol_natural_name, lookup_symbol_in_language)
> 	(symbol_demangled_name, symbol_matches_domain): Add language_d.
> gdb/doc/ChangeLog:
> 	* gdb.texinfo: (Summary) Add mention about D language support.
> 	(Filenames): Add D suffixes.
> 	(D): New node.
> gdb/testsuite/ChangeLog:
> 	* gdb.base/default.exp: Fix "set language" test.

I applied the version where the documentation was approved by Eli.

-- 
Joel

^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2010-04-29 14:47 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20091224015617.7092112b.mihai.zenkov@gmail.com>
     [not found] ` <20091230125539.GF2788@adacore.com>
2010-01-09  6:25   ` D language support Mihail Zenkov
2010-01-09  6:29     ` Mihail Zenkov
2010-01-09 14:23       ` Joel Brobecker
2010-01-13  4:42         ` Mihail Zenkov
2010-01-15  5:10           ` Joel Brobecker
2010-01-15 21:02             ` Tom Tromey
2010-01-15 21:05           ` Tom Tromey
2010-04-14 22:22             ` Mihail Zenkov
2010-04-20 21:39               ` Tom Tromey
2010-04-21  0:01                 ` Mihail Zenkov
2010-04-21 15:57                   ` Joel Brobecker
2010-04-22  0:11                     ` Mihail Zenkov
2010-04-22  0:44                       ` Joel Brobecker
2010-04-22  1:53                         ` Mihail Zenkov
2010-04-23 18:11                           ` Tom Tromey
2010-04-24  0:06                             ` Mihail Zenkov
2010-04-27 16:05                               ` Joel Brobecker
2010-04-27 23:55                                 ` Mihail Zenkov
2010-04-28 15:17                                   ` Joel Brobecker
2010-04-28 17:11                                     ` Eli Zaretskii
2010-04-29  2:16                                     ` Mihail Zenkov
2010-04-28 17:10                                   ` Eli Zaretskii
2010-04-29  1:59                                     ` Mihail Zenkov
2010-04-29  3:10                                       ` Eli Zaretskii
2010-04-29 14:47                                       ` Joel Brobecker
2010-04-23 18:09                         ` Tom Tromey
2010-04-23 20:15                           ` Leandro Lucarella
2010-04-23 20:37                             ` Tom Tromey
2010-04-26 23:51                               ` Stan Shebs
2010-04-27  0:29                                 ` Joel Brobecker
2010-04-23 21:35               ` Robert Clipsham
2010-04-24  0:26                 ` Mihail Zenkov
2010-04-27 20:27                   ` Robert Clipsham

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).