Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* D Symbol Demangling
@ 2006-04-19 11:18 Thomas Kuehne
  2006-04-20 13:20 ` Daniel Jacobowitz
  0 siblings, 1 reply; 26+ messages in thread
From: Thomas Kuehne @ 2006-04-19 11:18 UTC (permalink / raw)
  To: gdb-patches

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

Attached is a patch against GDB-6.4 that enables demangling of symbols
generated by DMD[1] and GDC[2].

The infrastructure part (c-lang.c, defs.h, d-lang.h, dwarf2read.c,
language.c, Makefile.in, symfile, syntab.c, dwarf2.h) is based on John
Demme's work[3][4].

The pluggable demangler (gdb/demangle_d/*) was written completely form
scratch and isn't based on John's work and supports templates and - to a
certain extend - nested functions and types.

Thomas

[1] http://digitalmars.com/d/dcompiler.html
[2] http://home.earthlink.net/~dvdfrdmn/d/
[3] http://www.dsource.org/forums/viewforum.php?f=58
[4] http://sourceware.org/ml/gdb-patches/2005-04/msg00039.html

[-- Attachment #2: gdb-6.4-demangle_d.diff --]
[-- Type: text/plain, Size: 40717 bytes --]

diff -urN gdb-6.4/gdb/c-lang.c gdb-6.4-demangle_d/gdb/c-lang.c
--- gdb-6.4/gdb/c-lang.c	2005-10-03 23:21:20.000000000 +0200
+++ gdb-6.4-demangle_d/gdb/c-lang.c	2006-04-17 21:29:25.000000000 +0200
@@ -27,6 +27,7 @@
 #include "parser-defs.h"
 #include "language.h"
 #include "c-lang.h"
+#include "d-lang.h"
 #include "valprint.h"
 #include "macroscope.h"
 #include "gdb_assert.h"
@@ -735,10 +736,48 @@
   LANG_MAGIC
 };
 
+const struct language_defn d_language_defn =
+{
+  "d",                         /* Language name */
+  language_d,
+  NULL,
+  range_check_off,
+  type_check_off,
+  case_sensitive_on,
+  array_row_major,
+  &exp_descriptor_standard,
+  c_preprocess_and_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_create_fundamental_type,	/* Create fundamental type in this language */
+  c_print_type,			/* Print a type using appropriate syntax */
+  c_val_print,			/* Print a value using appropriate syntax */
+  c_value_print,		/* Print a top-level value */
+  NULL,				/* Language specific skip_trampoline */
+  NULL,				/* value_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 */
+  c_op_print_tab,		/* expression operators for printing */
+  1,				/* c-style arrays */
+  0,				/* String lower bound */
+  NULL,
+  default_word_break_characters,
+  c_language_arch_info,
+  default_print_array_index,
+  LANG_MAGIC
+};
+
+
 void
 _initialize_c_language (void)
 {
   add_language (&c_language_defn);
+  add_language (&d_language_defn);
   add_language (&cplus_language_defn);
   add_language (&asm_language_defn);
   add_language (&minimal_language_defn);
diff -urN gdb-6.4/gdb/defs.h gdb-6.4-demangle_d/gdb/defs.h
--- gdb-6.4/gdb/defs.h	2005-08-05 23:08:54.000000000 +0200
+++ gdb-6.4-demangle_d/gdb/defs.h	2006-04-17 21:27:21.000000000 +0200
@@ -190,6 +190,7 @@
     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 -urN gdb-6.4/gdb/demangle_d/demangle_d.c gdb-6.4-demangle_d/gdb/demangle_d/demangle_d.c
--- gdb-6.4/gdb/demangle_d/demangle_d.c	1970-01-01 01:00:00.000000000 +0100
+++ gdb-6.4-demangle_d/gdb/demangle_d/demangle_d.c	2006-04-19 14:08:46.000000000 +0200
@@ -0,0 +1,844 @@
+/*
+ * demangle_d.c - pluggable D de-mangler
+ *
+ * Copyright 2006 Thomas Kuehne <thomas@kuehne.cn>
+ *
+ *
+ * Eiffel Forum License, version 1
+ *
+ * Permission is hereby granted to use, copy, modify and/or distribute this
+ * package, provided that:
+ *
+ *  - copyright notices are retained unchanged
+ *
+ *  - any distribution of this package, whether modified or not, includes
+ *    this file
+ *
+ * Permission is hereby also granted to distribute binary programs which
+ * depend on this package, provided that:
+ *
+ *  - if the binary program depends on a modified version of this package,
+ *    you must publicly release the modified version of this package
+ *
+ * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT WARRANTY. ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHORS BE LIABLE TO ANY PARTY FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS PACKAGE.
+ *
+ * 2006-04-19
+ *	added GDB support
+ * 
+ * 2006-04-17
+ * 	added Valgrind support
+ *
+ * 2006-04-16
+ * 	inital public release
+ *
+ */
+
+#include "demangle_d_conf.h"
+#include "demangle_d_internal.h"
+
+/* copy len first bytes into a newly allocated buffer */
+char*
+DD_(strndup)(const char* source, size_t len)
+{
+	char* dest;
+	dest = xmalloc(len+1);
+	xmemcpy(dest, source, len);
+	dest[len] = '\x00';
+	return dest;
+}
+
+#if (DEMANGLE_D_REQUIRE_strtol_10)
+/* convert a string to a long integer using base 10 */
+long int
+xstrtol_10(char* src, char** endptr)
+{
+	long int value;
+	int sign;
+
+	if(src[0] == '-'){
+		sign = -1;
+		src++;
+	}else if(src[0] == '+'){
+		sign = 1;
+		src++;
+	}else{
+		sign = 1;
+	}
+
+	value = 0;
+
+	while(xisdigit(src[0])){
+		value = (value * 10) + (src[0] - '0');
+		src++;
+	}
+
+	if(endptr){
+		*endptr = src;
+	}
+
+	return sign * value;
+}
+#endif
+
+#if (DEMANGLE_D_REQUIRE_malloc)
+void*
+DD_(malloc)(size_t len)
+{
+	void* ptr;
+	ptr = malloc(len);
+	if(!ptr){
+		perror("DD_(malloc)");
+		xabort();
+	}
+	return ptr;
+}
+#endif
+
+#if (DEMANGLE_D_REQUIRE_realloc)
+void*
+DD_(realloc)(void* ptr, size_t len)
+{
+	ptr = realloc(ptr, len);
+	if(!ptr){
+		perror("DD_(realloc)");
+		xabort();
+	}
+	return ptr;
+}
+#endif
+
+DD_(string_t)*
+DD_(new_string)(void)
+{
+	DD_(string_t)* str = xmalloc(sizeof(DD_(string_t)));
+	str->used = 0;
+	str->len = 128;
+	str->str = xmalloc(str->len);
+	str->str[0] = '\x00';
+	return str;
+}
+
+void
+DD_(append_n)(DD_(string_t)* dest, const char* source, size_t len)
+{
+	size_t new_len = dest->used + len + 1;
+	if(new_len > dest->len){
+		dest->len = (size_t)(new_len * 1.5);
+		dest->str = xrealloc(dest->str, dest->len);
+	}
+	xmemcpy(dest->str + dest->used, source, len);
+	dest->used += len;
+	dest->str[dest->used] = '\x00';
+}
+
+void
+DD_(append_c)(DD_(string_t)* dest, char source)
+{
+	size_t new_len = dest->used + 2;
+	if(new_len > dest->len){
+		dest->len = (size_t)(new_len * 1.5);
+		dest->str = xrealloc(dest->str, dest->len);
+	}
+	dest->str[dest->used++] = source;
+	dest->str[dest->used] = '\x00';
+}
+
+void
+DD_(append)(DD_(string_t)* dest, const char* source)
+{
+	DD_(append_n)(dest, source, xstrlen(source));
+}
+
+void
+DD_(prepend_n)(DD_(string_t)* dest, const char* source, size_t len)
+{
+	size_t new_len = dest->used + len + 1;
+	if(new_len > dest->len){
+		dest->len = (size_t)(new_len * 1.5);
+		dest->str = xrealloc(dest->str, dest->len);
+	}
+	if(dest->used){
+		xmemmove(dest->str + len, dest->str, dest->used);
+	}
+	xmemcpy(dest->str, source, len);
+	dest->used += len;
+	dest->str[dest->used] = '\x00';
+}
+
+void
+DD_(prepend)(DD_(string_t)* dest, const char* source)
+{
+	DD_(prepend_n)(dest, source, xstrlen(source));
+}
+
+void
+DD_(nestpend_n)(DD_(string_t)* dest, const char* source, size_t len,
+		int is_nested)
+{
+	if(is_nested){
+		DD_(append_n)(dest, source, len);
+	}else{
+		DD_(prepend)(dest, " ");
+		DD_(prepend_n)(dest, source, len);
+	}
+}
+
+void
+DD_(nestpend)(DD_(string_t)* dest, const char* source, int is_nested)
+{
+	DD_(nestpend_n)(dest, source, xstrlen(source), is_nested);
+}
+
+/* parse until the end of the next type */
+char*
+DD_(nextType)(DD_(string_t)* dest, char* source, int is_nested)
+{
+	if(!source || !source[0]){
+		return NULL;
+	}
+
+	if((source[0] == '_') && (source[1] == 'D')
+			&& xisdigit(source[2])
+			&& (source[2] != '0'))
+	{
+		DD_(string_t)* tmp;
+		tmp = DD_(new_string)();
+		source = DD_(nextType)(tmp, source + 2, 0);
+		if(dest->used && (dest->str[dest->used] != '.')){
+			DD_(append_c)(dest, '.');
+		}
+		DD_(append_n)(dest, tmp->str, tmp->used);
+		xfree(tmp->str);
+		xfree(tmp);
+		return source;
+	}
+
+	switch(source[0]){
+		case 'v':
+			DD_(nestpend)(dest, "void", is_nested);
+			source += 1;
+			break;
+		case 'b': /* deprecated since DMD-0.148 (2006-02-25) */
+			DD_(nestpend)(dest, "bit", is_nested);
+			source += 1;
+			break;
+		case 'x':
+			DD_(nestpend)(dest, "bool", is_nested);
+			source += 1;
+			break;
+		case 'g':
+			DD_(nestpend)(dest, "byte", is_nested);
+			source += 1;
+			break;
+		case 'h':
+			DD_(nestpend)(dest, "ubyte", is_nested);
+			source += 1;
+			break;
+		case 's':
+			DD_(nestpend)(dest, "short", is_nested);
+			source += 1;
+			break;
+		case 't':
+			DD_(nestpend)(dest, "ushort", is_nested);
+			source += 1;
+			break;
+		case 'i':
+			DD_(nestpend)(dest, "int", is_nested);
+			source += 1;
+			break;
+		case 'k':
+			DD_(nestpend)(dest, "uint", is_nested);
+			source += 1;
+			break;
+		case 'l':
+			DD_(nestpend)(dest, "long", is_nested);
+			source += 1;
+			break;
+		case 'm':
+			DD_(nestpend)(dest, "ulong", is_nested);
+			source += 1;
+			break;
+		case 'f':
+			DD_(nestpend)(dest, "float", is_nested);
+			source += 1;
+			break;
+		case 'd':
+			DD_(nestpend)(dest, "double", is_nested);
+			source += 1;
+			break;
+		case 'e':
+			DD_(nestpend)(dest, "real", is_nested);
+			source += 1;
+			break;
+		case 'o':
+			DD_(nestpend)(dest, "ifloat", is_nested);
+			source += 1;
+			break;
+		case 'p':
+			DD_(nestpend)(dest, "idouble", is_nested);
+			source += 1;
+			break;
+		case 'j':
+			DD_(nestpend)(dest, "ireal", is_nested);
+			source += 1;
+			break;
+		case 'q':
+			DD_(nestpend)(dest, "cfloat", is_nested);
+			source += 1;
+			break;
+		case 'r':
+			DD_(nestpend)(dest, "cdouble", is_nested);
+			source += 1;
+			break;
+		case 'c':
+			DD_(nestpend)(dest, "creal", is_nested);
+			source += 1;
+			break;
+		case 'a':
+			DD_(nestpend)(dest, "char", is_nested);
+			source += 1;
+			break;
+		case 'u':
+			DD_(nestpend)(dest, "wchar", is_nested);
+			source += 1;
+			break;
+		case 'w':
+			DD_(nestpend)(dest, "dchar", is_nested);
+			source += 1;
+			break;
+
+		case 'A': /* dynamic array */
+			if(!is_nested){
+				DD_(prepend)(dest, "[] ");
+			}
+			source = DD_(nextType)(dest, source+1, is_nested);
+			if(is_nested){
+				DD_(append)(dest, "[]");
+			}
+			break;
+
+		case 'G': { /* static array */
+			char* start = ++source;
+			char* end = start;
+			while(xisdigit(*end)){
+				end++;
+			}
+			if(!is_nested){
+				DD_(prepend)(dest, "] ");
+				DD_(prepend_n)(dest, start, end-start);
+				DD_(prepend)(dest, "[");
+			}
+			source = DD_(nextType)(dest, end, is_nested);
+			if(is_nested){
+				DD_(append)(dest, "[");
+				DD_(append_n)(dest, start, end-start);
+				DD_(append)(dest, "]");
+			}
+			break;
+		}
+
+		case 'H': { /* associative array */
+			DD_(string_t)* aa;
+			aa = DD_(new_string)();
+			source = DD_(nextType)(aa, source+1, 1);
+			DD_(prepend)(aa, "[");
+			DD_(append)(aa, "]");
+			source = DD_(nextType)(aa, source, 0);
+
+			DD_(nestpend)(dest, aa->str, is_nested);
+			xfree(aa->str);
+			xfree(aa);
+			break;
+		}
+
+		case 'D': { /* delegate */
+			DD_(string_t)* sig;
+			sig = DD_(new_string)();
+			source = DD_(parseFunction)(sig, source+1, NULL, 0);
+			DD_(nestpend_n)(dest, sig->str, sig->used, is_nested);
+			xfree(sig->str);
+			xfree(sig);
+			break;
+		}
+
+		case 'P': /* pointer */
+			if((source[1] == 'F') || (source[1]=='U')
+					|| (source[1]=='W') || (source[1]=='V')
+					|| (source[1]=='R'))
+			{
+				/* function */
+				DD_(string_t)* sig;
+				sig = DD_(new_string)();
+				source = DD_(parseFunction)(sig, source+1,
+						"", 0);
+				DD_(nestpend_n)(dest, sig->str, sig->used,
+						is_nested);
+				xfree(sig->str);
+				xfree(sig);
+			}else{
+				/* 'normal' type */
+				if(!is_nested){
+					DD_(prepend)(dest, "* ");
+				}
+				source = DD_(nextType)(dest, source+1,
+						is_nested);
+				if(is_nested){
+					DD_(append)(dest, " *");
+				}
+			}
+			break;
+
+		case 'J': /* out */
+			DD_(append)(dest, "out ");
+			source = DD_(nextType)(dest, source+1, 1);
+			break;
+
+		case 'K': /* inout */
+			DD_(append)(dest, "inout ");
+			source = DD_(nextType)(dest, source+1, 1);
+			break;
+
+		case 'C': /* class */
+		case 'S': /* struct */
+		case 'E': /* enum */
+		case 'T': /* typedef */
+		{
+#if (DEMANGLE_D_VERBOSE)
+			char tmp = source[0];
+#endif /* DEMANGLE_D_VERBOSE */
+			if(!is_nested){
+				DD_(string_t)* sig;
+				sig = DD_(new_string)();
+				source = DD_(nextType)(sig, source+1, 0);
+				DD_(append)(sig, " ");
+#if (DEMANGLE_D_VERBOSE)
+				switch(tmp){
+					case 'C':
+						DD_(prepend)(sig, "class ");
+						break;
+					case 'S':
+						DD_(prepend)(sig, "struct ");
+						break;
+					case 'E':
+						DD_(prepend)(sig, "enum ");
+						break;
+					case 'T':
+						DD_(prepend)(sig, "typedef ");
+						break;
+				}
+#endif /* DEMANGLE_D_VERBOSE */
+				DD_(prepend_n)(dest, sig->str, sig->used);
+				xfree(sig->str);
+				xfree(sig);
+			}else{
+#if (DEMANGLE_D_VERBOSE)
+				switch(tmp){
+					case 'C':
+						DD_(append)(dest, "class ");
+						break;
+					case 'S':
+						DD_(append)(dest, "struct ");
+						break;
+					case 'E':
+						DD_(append)(dest, "enum ");
+						break;
+					case 'T':
+						DD_(append)(dest, "typedef ");
+						break;
+				}
+#endif /* DEMANGLE_D_VERBOSE */
+				source = DD_(nextType)(dest, source+1, 1);
+			}
+			break;
+		}
+
+		case '1': /* qualified name */
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+		case '8':
+		case '9':
+		{
+			long int len;
+			len = xstrtol_10(source, &source);
+			if(len >= 5 && (source[0] == '_') && (source[1] == '_')
+					&& (source[2] == 'T')
+					&& xisdigit(source[3])
+					&& (source[3] != '0'))
+			{
+				/* template */
+				char* template = DD_(strndup)(source + 3, len-3);
+				DD_(interpreteTemplate)(dest, template);
+				xfree(template);
+			}else{
+				DD_(append_n)(dest, source, len);
+			}
+			source += len;
+			while(source && xisdigit(source[0])
+					&& (source[0] != '0'))
+			{
+				len = xstrtol_10(source, &source);
+				DD_(append_c)(dest, '.');
+				if(len >= 5 && (source[0] == '_')
+						&& (source[1] == '_')
+						&& (source[2] == 'T')
+						&& xisdigit(source[3])
+						&& (source[3] != '0'))
+				{
+					/* template */
+					char* template = DD_(strndup)(source + 3, len-3);
+					DD_(interpreteTemplate)(dest, template);
+					xfree(template);
+				}else if((len == 5) && (xstrncmp(source, "_ctor", len) == 0)){
+					DD_(append)(dest, "this");
+				}else if((len == 5) && (xstrncmp(source, "_dtor", len) == 0)){
+					DD_(append)(dest, "~this");
+				}else if((len == 11) && (xstrncmp(source, "_staticCtorFZv", len + 3) == 0)){
+					DD_(prepend)(dest, "static void ");
+					DD_(append)(dest, "this()");
+					source = source + 11 + 3;
+					break;
+				}else if((len == 11) && (xstrncmp(source, "_staticDtorFZv", len + 3) == 0)){
+					DD_(prepend)(dest, "static void ");
+					DD_(append)(dest, "~this()");
+					source = source + 11 + 3;
+					break;
+				}else{
+					DD_(append_n)(dest, source, len);
+				}
+				source += len;
+			}
+			if(!is_nested){
+				source = DD_(nextType)(dest, source, 0);
+			}
+			break;
+		}
+
+		case 'F': /* D function */
+		case 'U': /* C function */
+		case 'W': /* Windows function */
+		case 'V': /* Pascal function */
+		case 'R': /* C++ function */
+			if(!is_nested){
+				DD_(string_t)* id;
+				id = DD_(new_string)();
+				DD_(append_n)(id, dest->str, dest->used);
+				dest->used = 0;
+				dest->str[0] = '\x00';
+				source = DD_(parseFunction)(dest, source, id->str, 0);
+				xfree(id->str);
+				xfree(id);
+			}else{
+				source = DD_(parseFunction)(dest, source, "", 1);
+			}
+			break;
+
+		default:
+			DD_(append)(dest, " @bug@[2]{");
+			DD_(append)(dest, source);
+			DD_(append)(dest, "}");
+			source = NULL;
+			break;
+	}
+
+	return source;
+}
+
+/* parse a "real" template parameter */
+char*
+DD_(parseReal)(DD_(string_t)* dest, char* source)
+{
+	/* @BUG@ architecture dependent */
+	long double f;
+	size_t i;
+	int tmp;
+	unsigned char* c = (unsigned char*) &f;
+	char* buffer;
+
+	for(i = 0; i < 10; i++){
+		if(!xisxdigit(source[i * 2]) || !xisxdigit(source[i * 2 + 1])){
+format_error:
+			DD_(append)(dest, "0x");
+			DD_(append_n)(dest, source, 20);
+			return source + 20;
+		}
+		c[i] = (xasci2hex(source[i * 2]) << 4);
+		c[i] |= xasci2hex(source[i * 2 + 1]);
+	}
+
+	buffer = xmalloc(64);
+	tmp = xsnprintf(buffer, 64, "%Lf", f);
+	if(tmp < 1){
+		xfree(buffer);
+		goto format_error;
+	}
+	DD_(append_n)(dest, buffer, tmp);
+	xfree(buffer);
+	return source + 20;
+}
+
+/* parse a function (including arguments and return type) */
+char*
+DD_(parseFunction)(DD_(string_t)* dest, char* source, char* name,
+		int is_nested)
+{
+	DD_(string_t)* fn_return;
+	DD_(string_t)* fn_param;
+
+	fn_return = DD_(new_string)();
+	fn_param = DD_(new_string)();
+
+	source++;
+
+	/* params */
+	if(source[0] != 'Z'){
+		if(source[0] == 'Y'){
+			DD_(append)(fn_param, "...");
+			goto var_arg_param;
+		}
+		source = DD_(nextType)(fn_param, source, 1);
+		while(source && source[0] && source[0]!='Z'){
+			if(source[0] == 'Y'){
+				DD_(append)(fn_param, ", ...");
+				goto var_arg_param;
+			}else if(source[0] == 'X'){
+				DD_(append)(fn_param, " ...");
+				goto var_arg_param;
+			}
+			DD_(append)(fn_param, ", ");
+			source = DD_(nextType)(fn_param, source, 1);
+		}
+	}
+
+	/* return type */
+	if(source && source[0] == 'Z'){
+var_arg_param:
+		source = DD_(nextType)(fn_return, source + 1, 1);
+	}
+
+	/* output */
+	if(name && name[0]){
+		if(! is_nested){
+			DD_(prepend)(dest, " ");
+			DD_(prepend_n)(dest, fn_return->str, fn_return->used);
+			DD_(append)(dest, name);
+		}else{
+			DD_(append_n)(dest, fn_return->str, fn_return->used);
+			DD_(append)(dest, " ");
+			DD_(append)(dest, name);
+		}
+	}else if(name){
+		DD_(append_n)(dest, fn_return->str, fn_return->used);
+		DD_(append)(dest, " function");
+	}else{
+		DD_(append_n)(dest, fn_return->str, fn_return->used);
+		DD_(append)(dest, " delegate");
+	}
+
+	if(fn_param->used){
+		DD_(append)(dest, "(");
+		DD_(append_n)(dest, fn_param->str, fn_param->used);
+		DD_(append)(dest, ")");
+	}else{
+		DD_(append)(dest, "()");
+	}
+
+	xfree(fn_return->str);
+	xfree(fn_return);
+	xfree(fn_param->str);
+	xfree(fn_param);
+
+	return source;
+}
+
+/* interprete a NULL terminated template symbol */
+void
+DD_(interpreteTemplate)(DD_(string_t)* dest, char* raw)
+{
+	char* tmp;
+	int first_arg = 1;
+	long int dataLen;
+
+	/* id */
+	while(xisdigit(raw[0]) && (raw[0] != '0')){
+		long int len;
+		len = xstrtol_10(raw, &raw);
+		DD_(append_n)(dest, raw, len);
+		raw += len;
+	}
+	DD_(append)(dest, "!(");
+
+	/* arguments */
+	while(raw && raw[0]){
+		if(raw[0] == 'T'){
+			/* type parameter */
+			raw++;
+			if(!first_arg){
+				DD_(append)(dest, ", ");
+			}else{
+				first_arg = 0;
+			}
+			raw = DD_(nextType)(dest, raw, 1);
+		}else if(raw[0] == 'V'){
+			/* value parameter */
+			if(!first_arg){
+				DD_(append)(dest, ", ");
+			}else{
+				first_arg = 0;
+			}
+			raw = DD_(nextType)(dest, raw + 1, 1);
+			DD_(append)(dest, " ");
+			if(xisdigit(raw[0])){
+				/* integer */
+integer_arg:
+				tmp = raw;
+				while(xisdigit(raw[0])){
+					raw++;
+				}
+				DD_(append_n)(dest, tmp, raw-tmp);
+			}else if(raw[0] == 'N'){
+				/* negative integer */
+				raw++;
+				DD_(append)(dest, "-");
+				goto integer_arg;
+			}else if(raw[0] == 'e'){
+				/* float */
+				raw = DD_(parseReal)(dest, raw+1);
+			}else if(raw[0] == 'c'){
+				/* complex float */
+				raw = DD_(parseReal)(dest, raw+1);
+				DD_(append)(dest, " + ");
+				raw = DD_(parseReal)(dest, raw);
+				DD_(append)(dest, "i");
+			}else if(raw[0] == 'n'){
+				DD_(append)(dest, "null");
+				raw++;
+			}else if((raw[0] == 'a') || (raw[0] == 'w') || (raw[0] == 'd')){
+				/* character literal */
+				raw++;
+				if(!xisdigit(raw[0])){
+					goto bug;
+				}
+				dataLen = xstrtol_10(raw, &raw);
+				if(raw[0] != '_'){
+					goto bug;
+				}
+				raw++;
+				DD_(append)(dest, "\"");
+				while(dataLen--){
+					if(xisxdigit(raw[0]) && xisxdigit(raw[1])){
+						DD_(append_c)(dest, (xasci2hex(raw[0]) << 4)
+								+ xasci2hex(raw[1]));
+					}else{
+						DD_(append_c)(dest, '?');
+					}
+					raw += 2;
+				}
+				DD_(append)(dest, "\"");
+			}else{
+				goto bug;
+			}
+		}else if(raw[0] == 'Z'){
+			/* end of parameter list */
+			break;
+		}else{
+bug:
+			DD_(append)(dest, " @bug@[1]{");
+			DD_(append)(dest, raw);
+			DD_(append)(dest, "}");
+			break;
+		}
+	}
+	DD_(append)(dest, ")");
+}
+
+/* demangle a D symbol
+ *
+ * input:
+ * 	a NULL terminated mangled symbol
+ *
+ * output:
+ * 	UTF-8 encoded demangled symbol
+ * 	or NULL if unable to demangle
+ *
+ * memory:
+ * 	the caller is responsible to
+ * 	free input and output
+ */
+static char*
+DD_(demangle_d)(char* source)
+{
+	DD_(string_t)* dest;
+	DD_(string_t)* nested;
+	char* back;
+
+	if((source[0] != '_') || (source[1] != 'D') || (!xisdigit(source[2]))
+			|| (source[2] == '0'))
+	{
+		/* %% @BUG@ might be mangled with 'D' but hasn't 'D' linkage
+		 * samples:
+		 * _aaApply10treewalkerFPS3aaA3aaAZi
+		 * _aaKeys9_aaKeys_xFPS3aaA3aaAZv
+		 */
+		return NULL;
+	}else{
+		source += 2;
+	}
+
+	dest = DD_(new_string)();
+
+	source = DD_(nextType)(dest, source, 0);
+
+	while(source && source[0]){
+		/* nested symbols */
+		nested = DD_(new_string)();
+		DD_(append)(dest, ".");
+		source = DD_(nextType)(nested, source, 0);
+		DD_(append_n)(dest, nested->str, nested->used);
+		xfree(nested->str);
+		xfree(nested);
+	}
+
+	back = DD_(strndup)(dest->str, dest->used+1);
+	xfree(dest->str);
+	xfree(dest);
+
+	return back;
+}
+
+#if (DEMANGLE_D_STANDALONE)
+int
+main(int argc, char** argv)
+{
+	int i;
+	if(argc < 2){
+		xfprintf(stderr,
+			"pluggable D d-demangler by Thomas Kuehne <thomas@kuehne.cn> "
+			"($Date: 2006-04-19T11:09:00.287803Z $)\n");
+		if(argc > 0){
+			xfprintf(stderr, "%s <mangledSymbol_1> [<mangledSymbol_2> ...]\n", argv[0]);
+		}else{
+			xfprintf(stderr, "dmangle_d <mangledSymbol_1> [<mangledSymbol_2> ...]\n");
+		}
+		return (EXIT_FAILURE);
+	}
+	for(i = 1; i < argc; i++){
+		char* demangled = DD_(demangle_d)(argv[i]);
+		if(4 > xprintf("%s\t%s\n", argv[i], demangled)){
+			xperror("main");
+		}
+		if(demangled){
+			xfree(demangled);
+		}
+	}
+	return (EXIT_SUCCESS);
+}
+#endif
diff -urN gdb-6.4/gdb/demangle_d/demangle_d_conf.h gdb-6.4-demangle_d/gdb/demangle_d/demangle_d_conf.h
--- gdb-6.4/gdb/demangle_d/demangle_d_conf.h	1970-01-01 01:00:00.000000000 +0100
+++ gdb-6.4-demangle_d/gdb/demangle_d/demangle_d_conf.h	2006-04-19 13:47:54.000000000 +0200
@@ -0,0 +1,115 @@
+#if !(DEMANGLE_D_CONF_H)
+#define DEMANGLE_D_CONF_H 1
+
+#include "demangle_d.h"
+
+#if (DEMANGLE_D_IN_VALGRIND)
+
+/* valgrind - http://www.valgrind.org */
+
+#include <stddef.h> /* size_t */
+
+#define	xmemcpy		VG_(memcpy)
+#define xmemmove	MEMMOVE
+#define	xstrlen		VG_(strlen)
+#define	xstrncmp	VG_(strncmp)
+#define xmalloc		VG_(malloc)
+#define DEMANGLE_D_REQUIRE_malloc 0
+#define xrealloc	VG_(realloc)
+#define DEMANGLE_D_REQUIRE_realloc 0
+#define xfree		VG_(free)
+#define xsnprintf	VG_(snprintf)
+#define	xisdigit	ISDIGIT
+#define xisxdigit	ISXDIGIT
+#define xasci2hex	ASCI2HEX
+
+#define DEMANGLE_D_REQUIRE_strtol_10 1
+#define xstrtol_10	DD_(strtol_10)
+
+#else
+
+/* "normal" libc */
+#define DEMANGLE_D_IN_VALGRIND 0
+
+#include <string.h>
+#define	xmemcpy		memcpy
+#define xmemmove	memmove
+#define	xstrlen		strlen
+#define	xstrncmp	strncmp
+
+#include <stdlib.h>
+#define xmalloc		DD_(malloc)
+#define DEMANGLE_D_REQUIRE_malloc 1
+#define xrealloc	DD_(realloc)
+#define DEMANGLE_D_REQUIRE_realloc 1
+#define xfree		free
+#define xabort		abort
+#define xstrtol_10(n,p)	strtol((n), (p), 10)
+#define DEMANGLE_D_REQUIRE_strtol_10 0
+
+#include <stdio.h>
+#define xsnprintf	snprintf
+
+#include <ctype.h>
+#define	xisdigit	isdigit
+#define xisxdigit	isxdigit
+
+#define xasci2hex	ASCI2HEX
+
+#if (DEMANGLE_D_STANDALONE)
+#define xprintf		printf
+#define xperror		perror
+#define xfprintf	fprintf
+#else
+#define DEMANGLE_D_STANDALONE 0
+#endif
+
+#endif
+
+/* helper macros */
+
+#define MEMMOVE(dest, src, len) \
+{ \
+	if(((dest < src) && (dest + len < src)) \
+		|| (((src < dest) && (src + len < dest)))) \
+	{ \
+		xmemcpy(dest, src, len); \
+	}else{ \
+		void* tmp; \
+		tmp = xmalloc(len); \
+		xmemcpy(tmp, src, len); \
+		xmemcpy(dest, tmp, len); \
+		xfree(tmp); \
+	} \
+}
+
+#define ISDIGIT(c) (('0' <= (c)) && ((c) <= '9'))
+
+#define ISXDIGIT(c) ( \
+		(('0' <= (c)) && ((c) <= '9')) \
+		|| (('a' <= (c)) && ((c) <= 'f')) \
+		|| (('A' <= (c)) && ((c) <= 'F')) \
+		)
+
+#define ASCI2HEX(c) \
+	( \
+	 	('a' <= (c) && (c) <= 'f') \
+		? \
+		((c) - 'a' + 10) \
+		: \
+		( \
+		 	('A' <= (c) && (c) <= 'F') \
+			? \
+			((c) - 'A' + 10) \
+			: \
+			( \
+			 	('0' <= (c) && (c) <= '9') \
+				? \
+				((c) - '0') \
+				: \
+				0 \
+			) \
+		) \
+	)
+
+#endif /* DEMANGLE_D_CONF_H */
diff -urN gdb-6.4/gdb/demangle_d/demangle_d.h gdb-6.4-demangle_d/gdb/demangle_d/demangle_d.h
--- gdb-6.4/gdb/demangle_d/demangle_d.h	1970-01-01 01:00:00.000000000 +0100
+++ gdb-6.4-demangle_d/gdb/demangle_d/demangle_d.h	2006-04-19 13:22:13.000000000 +0200
@@ -0,0 +1,21 @@
+#if !(DEMANGLE_D_H)
+#define DEMANGEL_D_H 1
+
+#define DD_(str) demangle_d_##str
+
+/* demangle a D symbol
+ *
+ * input:
+ * 	a NULL terminated mangled symbol
+ *
+ * output:
+ * 	UTF-8 encoded demangled symbol
+ * 	or NULL if unable to demangle
+ *
+ * memory:
+ * 	the caller is responsible to
+ * 	free input and output
+ */
+static char* DD_(demangle_d)(char* source);
+
+#endif /* DEMANGEL_D_H */
diff -urN gdb-6.4/gdb/demangle_d/demangle_d_internal.h gdb-6.4-demangle_d/gdb/demangle_d/demangle_d_internal.h
--- gdb-6.4/gdb/demangle_d/demangle_d_internal.h	1970-01-01 01:00:00.000000000 +0100
+++ gdb-6.4-demangle_d/gdb/demangle_d/demangle_d_internal.h	2006-04-19 13:47:14.000000000 +0200
@@ -0,0 +1,45 @@
+#if !(DEMANGLE_D_INTERNAL_H)
+#define DEMANGLE_D_INTERNAL_H 1
+
+#include "demangle_d.h"
+
+typedef struct{
+	size_t	used;
+	char*	str;
+	size_t	len;
+} DD_(string_t);
+
+DD_(string_t)* DD_(new_string)(void);
+
+void DD_(append_n)(DD_(string_t)* dest, const char* source, size_t len);
+void DD_(append_c)(DD_(string_t)* dest, char source);
+void DD_(append)(DD_(string_t)* dest, const char* source);
+
+void DD_(prepend_n)(DD_(string_t)* dest, const char* source, size_t len);
+void DD_(prepend)(DD_(string_t)* dest, const char* source);
+
+void DD_(nestpend_n)(DD_(string_t)* dest, const char* source, size_t len, int is_nested);
+void DD_(nestpend)(DD_(string_t)* dest, const char* source, int is_nested);
+
+char* DD_(nextType)(DD_(string_t)* dest, char* raw, int is_nested);
+
+void DD_(interpreteTemplate)(DD_(string_t)* dest, char* raw);
+
+char* DD_(parseReal)(DD_(string_t)* dest, char* raw);
+char* DD_(parseFunction)(DD_(string_t)* dest, char* raw, char* name, int is_nested);
+
+char* DD_(strndup)(const char* source, size_t len);
+
+#if (DEMANGLE_D_REQUIRE_strtol_10)
+long int DD_(strtol_10)(char* src, char** endptr);
+#endif
+
+#if (DEMANGLE_D_REQUIRE_malloc)
+void* DD_(malloc)(size_t len);
+#endif
+
+#if (DEMANGLE_D_REQUIRE_realloc)
+void* DD_(realloc)(void* ptr, size_t len);
+#endif
+
+#endif /* DEMANGLE_D_INTERNAL_H */
diff -urN gdb-6.4/gdb/demangle_d/license.txt gdb-6.4-demangle_d/gdb/demangle_d/license.txt
--- gdb-6.4/gdb/demangle_d/license.txt	1970-01-01 01:00:00.000000000 +0100
+++ gdb-6.4-demangle_d/gdb/demangle_d/license.txt	2006-04-18 10:07:40.000000000 +0200
@@ -0,0 +1,22 @@
+Eiffel Forum License, version 1
+
+Permission is hereby granted to use, copy, modify and/or distribute this
+package, provided that:
+
+ - copyright notices are retained unchanged
+
+ - any distribution of this package, whether modified or not, includes this
+   file
+
+Permission is hereby also granted to distribute binary programs which depend
+on this package, provided that:
+
+ - if the binary program depends on a modified version of this package, you
+   must publicly release the modified version of this package
+
+THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT WARRANTY. ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE AUTHORS BE LIABLE TO ANY PARTY FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT
+OF THE USE OF THIS PACKAGE.
diff -urN gdb-6.4/gdb/demangle_d/readme.txt gdb-6.4-demangle_d/gdb/demangle_d/readme.txt
--- gdb-6.4/gdb/demangle_d/readme.txt	1970-01-01 01:00:00.000000000 +0100
+++ gdb-6.4-demangle_d/gdb/demangle_d/readme.txt	2006-04-19 12:02:13.000000000 +0200
@@ -0,0 +1,62 @@
+ pluggable D de-mangler
+=======================
+
+Author:
+	Thomas Kuehne <thomas@kuehne.cn>
+
+License:
+	Eiffel Forum License, version 1 (see license.txt)
+
+
+Usage: stand alone
+---------------------
+
+1) compile:
+	cc -DDEMANGLE_D_STANDALONE -o demangle_d demangle_d.c
+	
+2) run:
+	./demangle_d _D3std3utf6toUTF8FG4awZAa _D3std6string7sformatFAaYAa
+	> _D3std3utf6toUTF8FG4awZAa       char[] std.utf.toUTF8(char[4], dchar)
+	> _D3std6string7sformatFAaYAa     char[] std.string.sformat(char[], ...)
+
+
+Usage: plugin
+---------------------
+
+1) adapt demangle_d_conf.h to your system
+
+2) include demangle_d.c in your build system
+
+3) demangle:
+	#include "demangle_d.h"
+
+	char* mangled;
+	char* demangled;
+	
+	mangled = "_D1b5outerFeZf";
+	demangled = DD_(demangle_d)(mangled);
+
+	// ... process demangled ...
+
+	if(demangled){
+		free(demangled);
+	}
+
+optional:
+	adapt the DD_(str) macro in "demangle_d.h" to resolve potential
+	name clashes in your object code
+
+	
+TODO
+---------------------
+
+	* better output for symbols in nested types:
+		_staticCtorFZv3Ali5_ctorFiZC_D1b11_staticCtorFZv3Ali5innerFiZi
+	
+	* handle "special" names:
+		_init__D1b11_staticCtorFZv3Al
+		_Class__D1b11_staticCtorFZv3Ali
+		_vtbl__D1b11_staticCtorFZv3Ali
+		_modctor_1b
+		_assert_1b
+
diff -urN gdb-6.4/gdb/d-lang.c gdb-6.4-demangle_d/gdb/d-lang.c
--- gdb-6.4/gdb/d-lang.c	1970-01-01 01:00:00.000000000 +0100
+++ gdb-6.4-demangle_d/gdb/d-lang.c	2006-04-17 22:06:33.000000000 +0200
@@ -0,0 +1,32 @@
+/* C language support routines for GDB, the GNU debugger.
+   Copyright 2006
+   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 2 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "symtab.h"
+#include "demangle_d/demangle_d.c"
+
+char* d_demangle(char* symbol, int options) {
+  return DD_(demangle_d)(symbol);
+}
+
+char* d_sym_demangle(const struct general_symbol_info *gsymbol) {
+  return DD_(demangle_d)(gsymbol->name);
+}
diff -urN gdb-6.4/gdb/d-lang.h gdb-6.4-demangle_d/gdb/d-lang.h
--- gdb-6.4/gdb/d-lang.h	1970-01-01 01:00:00.000000000 +0100
+++ gdb-6.4-demangle_d/gdb/d-lang.h	2006-04-17 21:34:12.000000000 +0200
@@ -0,0 +1,37 @@
+/* C language support definitions for GDB, the GNU debugger.
+   Copyright 1992, 1994, 1995, 1996, 1997, 1998, 2000, 2002
+   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 2 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+
+#if !defined (D_LANG_H)
+#define D_LANG_H 1
+
+#include "symtab.h"
+
+/*****************************
+ D Language stuff
+******************************/
+
+char* d_demangle(const char* mangled, int options);
+
+char* d_sym_demangle(const struct general_symbol_info *gsymbol);
+
+
+#endif /* !defined (D_LANG_H) */
diff -urN gdb-6.4/gdb/dwarf2read.c gdb-6.4-demangle_d/gdb/dwarf2read.c
--- gdb-6.4/gdb/dwarf2read.c	2005-11-04 03:58:31.000000000 +0100
+++ gdb-6.4-demangle_d/gdb/dwarf2read.c	2006-04-17 21:30:07.000000000 +0200
@@ -6098,6 +6098,9 @@
     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:
@@ -6577,7 +6580,7 @@
                 file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
                 line_ptr += bytes_read;
                 fe = &lh->file_names[file - 1];
-                if (fe->dir_index)
+                if (fe->dir_index && lh->include_dirs != NULL)
                   dir = lh->include_dirs[fe->dir_index - 1];
                 else
                   dir = comp_dir;
diff -urN gdb-6.4/gdb/language.c gdb-6.4-demangle_d/gdb/language.c
--- gdb-6.4/gdb/language.c	2005-10-03 23:21:20.000000000 +0200
+++ gdb-6.4-demangle_d/gdb/language.c	2006-04-17 21:30:46.000000000 +0200
@@ -539,6 +539,7 @@
     {
     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 ?
@@ -650,6 +651,7 @@
     {
     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;
@@ -690,6 +692,7 @@
 
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) == TYPE_CODE_INT) &&
 	TYPE_LENGTH (type) == sizeof (char)
@@ -712,6 +715,7 @@
 
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       /* C does not have distinct string type. */
       return (0);
@@ -731,6 +735,7 @@
     {
     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
@@ -804,6 +809,7 @@
 	}
       return builtin_type_f_logical_s2;
     case language_cplus:
+    case language_d:
     case language_pascal:
       if (current_language->la_language==language_cplus)
         {sym = lookup_symbol ("bool", NULL, VAR_DOMAIN, NULL, NULL);}
diff -urN gdb-6.4/gdb/Makefile.in gdb-6.4-demangle_d/gdb/Makefile.in
--- gdb-6.4/gdb/Makefile.in	2005-11-16 13:44:10.000000000 +0100
+++ gdb-6.4-demangle_d/gdb/Makefile.in	2006-04-17 21:32:59.000000000 +0200
@@ -515,7 +515,7 @@
 	c-exp.y c-lang.c c-typeprint.c c-valprint.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 \
+	cp-abi.c cp-support.c cp-namespace.c cp-valprint.c d-lang.c \
 	cp-name-parser.y \
 	dbxread.c demangle.c dictionary.c disasm.c doublest.c dummy-frame.c \
 	dwarfread.c dwarf2expr.c dwarf2loc.c dwarf2read.c dwarf2-frame.c \
@@ -655,6 +655,7 @@
 completer_h = completer.h
 cp_abi_h = cp-abi.h
 cp_support_h = cp-support.h $(symtab_h)
+d_lang_h = d-lang.h $(symtab_h)
 dcache_h = dcache.h
 defs_h = defs.h $(config_h) $(ansidecl_h) $(gdb_locale_h) $(gdb_signals_h) \
 	$(libiberty_h) $(bfd_h) $(ui_file_h) $(xm_h) $(nm_h) $(tm_h) \
@@ -918,7 +919,7 @@
 	dbxread.o coffread.o coff-pe-read.o elfread.o \
 	dwarfread.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 \
 	ui-out.o cli-out.o \
 	varobj.o wrapper.o \
 	jv-lang.o jv-valprint.o jv-typeprint.o \
@@ -1859,6 +1860,9 @@
 c-valprint.o: c-valprint.c $(defs_h) $(gdb_string_h) $(symtab_h) \
 	$(gdbtypes_h) $(expression_h) $(value_h) $(valprint_h) $(language_h) \
 	$(c_lang_h) $(cp_abi_h) $(target_h)
+d-lang.o: d-lang.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \
+	$(parser_defs_h) $(language_h) $(c_lang_h) $(valprint_h) \
+	$(macroscope_h) $(gdb_assert_h) $(charset_h) $(gdb_string_h)
 # OBSOLETE d10v-tdep.o: d10v-tdep.c
 dbug-rom.o: dbug-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \
 	$(serial_h) $(regcache_h) $(m68k_tdep_h)
@@ -2668,7 +2672,7 @@
 	$(gdb_obstack_h) $(exceptions_h) $(language_h) $(bcache_h) \
 	$(block_h) $(gdb_regex_h) $(dictionary_h) $(gdb_string_h) \
 	$(readline_h)
-symtab.o: symtab.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(gdbcore_h) \
+symtab.o: symtab.c $(defs_h) $(d_lang_h) $(symtab_h) $(gdbtypes_h) $(gdbcore_h) \
 	$(frame_h) $(target_h) $(value_h) $(symfile_h) $(objfiles_h) \
 	$(gdbcmd_h) $(call_cmds_h) $(gdb_regex_h) $(expression_h) \
 	$(language_h) $(demangle_h) $(inferior_h) $(linespec_h) $(source_h) \
diff -urN gdb-6.4/gdb/symfile.c gdb-6.4-demangle_d/gdb/symfile.c
--- gdb-6.4/gdb/symfile.c	2005-08-31 23:07:33.000000000 +0200
+++ gdb-6.4-demangle_d/gdb/symfile.c	2006-04-17 21:31:23.000000000 +0200
@@ -2317,6 +2317,7 @@
       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 -urN gdb-6.4/gdb/symtab.c gdb-6.4-demangle_d/gdb/symtab.c
--- gdb-6.4/gdb/symtab.c	2005-03-08 05:34:44.000000000 +0100
+++ gdb-6.4-demangle_d/gdb/symtab.c	2006-04-17 21:32:33.000000000 +0200
@@ -42,6 +42,7 @@
 #include "filenames.h"		/* for FILENAME_CMP */
 #include "objc-lang.h"
 #include "ada-lang.h"
+#include "d-lang.h"
 
 #include "hashtab.h"
 
@@ -405,6 +406,7 @@
 {
   gsymbol->language = language;
   if (gsymbol->language == language_cplus
+      || gsymbol->language == language_d
       || gsymbol->language == language_java
       || gsymbol->language == language_objc)
     {
@@ -451,6 +453,15 @@
   if (gsymbol->language == language_unknown)
     gsymbol->language = language_auto;
 
+  if (gsymbol->language == language_d
+      || gsymbol->language == language_auto) {
+    demangled = d_demangle(mangled, 0);
+    if (demangled != NULL) {
+      gsymbol->language = language_d;
+      return demangled;
+    }
+  }
+
   if (gsymbol->language == language_objc
       || gsymbol->language == language_auto)
     {
@@ -610,6 +621,7 @@
 
   demangled = symbol_find_demangled_name (gsymbol, mangled);
   if (gsymbol->language == language_cplus
+      || gsymbol->language == language_d
       || gsymbol->language == language_java
       || gsymbol->language == language_objc)
     {
@@ -639,6 +651,7 @@
   switch (gsymbol->language) 
     {
     case language_cplus:
+    case language_d:
     case language_java:
     case language_objc:
       if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
@@ -664,6 +677,7 @@
   switch (gsymbol->language) 
     {
     case language_cplus:
+    case language_d:
     case language_java:
     case language_objc:
       if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
@@ -1023,7 +1037,7 @@
 
   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 (current_language->la_language == language_cplus)
     {
@@ -1035,6 +1049,16 @@
 	  needtofreename = 1;
 	}
     }
+  else if (current_language->la_language == language_d)
+    {
+      demangled_name = d_demangle (name, 0);
+      if (demangled_name)
+	{
+	  mangled_name = name;
+	  modified_name = demangled_name;
+	  needtofreename = 1;
+	}
+    }
   else if (current_language->la_language == language_java)
     {
       demangled_name = cplus_demangle (name, 
diff -urN gdb-6.4/include/elf/dwarf2.h gdb-6.4-demangle_d/include/elf/dwarf2.h
--- gdb-6.4/include/elf/dwarf2.h	2005-07-18 06:13:05.000000000 +0200
+++ gdb-6.4-demangle_d/include/elf/dwarf2.h	2006-04-17 21:47:19.000000000 +0200
@@ -732,6 +732,7 @@
     DW_LANG_C99 = 0x000c,
     DW_LANG_Ada95 = 0x000d,
     DW_LANG_Fortran95 = 0x000e,
+    DW_LANG_D = 0x0013,
     /* MIPS.  */
     DW_LANG_Mips_Assembler = 0x8001,
     /* UPC.  */

^ permalink raw reply	[flat|nested] 26+ messages in thread
* D Symbol Demangling
@ 2005-04-04  2:37 John Demme
  2005-04-04 18:21 ` Michael Snyder
  0 siblings, 1 reply; 26+ messages in thread
From: John Demme @ 2005-04-04  2:37 UTC (permalink / raw)
  To: gdb-patches

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

Greetings GDB hackers!

I'm new to GDB programming, so please excuse any stupid questions.

There is a language called D which, like C++, uses symbol mangling since
it supports things such as method overloading.  I've been attempting to
add support to GDB to demangle the names.

Thus far, I've had partial success.  In fairly simple D programs, my
demangling works, but in more complex programs with mixed C and D code
(D is link-compatible with C) it only calls the D demangler for some of
the functions.

Unfortunately, I'm not very familiar with GDB's architecture, so I've
been basically wandering around in the dark on this one. Any help you
could provide would be appreciated.

Attached is my patch against GDB 6.3.  It is not the cleanest code right
now, and certainly not anywhere near ready for a release... I'm just
trying to get it to work, and feeling out the GDB code.  Once it's
working, I'll refactor it into something decent.

Thanks
John Demme

BTW- more information about D can be found at
http://www.digitalmars.com/d and there is a forum for D GDB patches at
http://www.dsource.org/forums/viewforum.php?f=58


[-- Attachment #2: d.patch --]
[-- Type: text/x-patch, Size: 12642 bytes --]

Index: gdb/symtab.c
===================================================================
--- gdb/symtab.c	(revision 7)
+++ gdb/symtab.c	(working copy)
@@ -42,6 +42,7 @@
 #include "filenames.h"		/* for FILENAME_CMP */
 #include "objc-lang.h"
 #include "ada-lang.h"
+#include "c-lang.h"
 
 #include "hashtab.h"
 
@@ -395,7 +396,7 @@
   return (mangled_name);
 }
 
-\f
+
 /* Initialize the language dependent portion of a symbol
    depending upon the language for the symbol. */
 void
@@ -404,6 +405,7 @@
 {
   gsymbol->language = language;
   if (gsymbol->language == language_cplus
+      || gsymbol->language == language_d
       || gsymbol->language == language_java
       || gsymbol->language == language_objc)
     {
@@ -450,6 +452,15 @@
   if (gsymbol->language == language_unknown)
     gsymbol->language = language_auto;
 
+  if (gsymbol->language == language_d
+      || gsymbol->language == language_auto) {
+    demangled = d_demangle(mangled, 0);
+    if (demangled != NULL) {
+      gsymbol->language = language_d;
+      return demangled;
+    }
+  }
+
   if (gsymbol->language == language_objc
       || gsymbol->language == language_auto)
     {
@@ -609,6 +620,7 @@
 
   demangled = symbol_find_demangled_name (gsymbol, mangled);
   if (gsymbol->language == language_cplus
+      || gsymbol->language == language_d
       || gsymbol->language == language_java
       || gsymbol->language == language_objc)
     {
@@ -638,6 +650,7 @@
   switch (gsymbol->language) 
     {
     case language_cplus:
+    case language_d:
     case language_java:
     case language_objc:
       if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
@@ -663,6 +676,7 @@
   switch (gsymbol->language) 
     {
     case language_cplus:
+    case language_d:
     case language_java:
     case language_objc:
       if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
@@ -1020,7 +1034,7 @@
 
   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 (current_language->la_language == language_cplus)
     {
@@ -1032,6 +1046,16 @@
 	  needtofreename = 1;
 	}
     }
+  else if (current_language->la_language == language_d)
+    {
+      demangled_name = d_demangle (name, 0);
+      if (demangled_name)
+	{
+	  mangled_name = name;
+	  modified_name = demangled_name;
+	  needtofreename = 1;
+	}
+    }
   else if (current_language->la_language == language_java)
     {
       demangled_name = cplus_demangle (name, 
Index: gdb/c-lang.c
===================================================================
--- gdb/c-lang.c	(revision 7)
+++ gdb/c-lang.c	(working copy)
@@ -696,9 +696,214 @@
    a language currently not supported by GDB.  */
 
 const struct language_defn minimal_language_defn =
+ {
+   "minimal",			/* Language name */
+   language_minimal,
+   NULL,
+   range_check_off,
+   type_check_off,
+   case_sensitive_on,
+   array_row_major,
+   &exp_descriptor_standard,
+   c_preprocess_and_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_create_fundamental_type,	/* Create fundamental type in this language */
+   c_print_type,			/* Print a type using appropriate syntax */
+   c_val_print,			/* Print a value using appropriate syntax */
+   c_value_print,		/* Print a top-level value */
+   NULL,				/* Language specific skip_trampoline */
+   NULL,				/* value_of_this */
+  basic_lookup_symbol_nonlocal,	/* lookup_symbol_nonlocal */
+  basic_lookup_transparent_type,/* lookup_transparent_type */
+  NULL,				/* Language specific symbol demangler */
+  NULL,				/* Language specific class_name_from_physname */
+  c_op_print_tab,		/* expression operators for printing */
+  1,				/* c-style arrays */
+  0,				/* String lower bound */
+  NULL,
+  default_word_break_characters,
+  c_language_arch_info,
+  LANG_MAGIC
+};
+
+
+/*****************************
+ D Language stuff
+******************************/
+#include <string.h>
+#include <ctype.h>
+
+static int extractidentifiers(char** output, char** mangled) {
+  int i = -1;
+  while (isdigit(**mangled)) {
+    i = strtol(*mangled, mangled, 10);
+    if (strlen(*mangled) < i)
+      return -1;
+    memcpy(*output, *mangled, i);
+    *mangled += i;
+    *output += i + 1;
+    (*output)[-1] = '.';
+  }
+  if (**mangled == '\0' || i == -1)
+    return -1;
+  (*output)--;
+  return 1;
+}
+
+static void append(char** dest, char* src) {
+  int i = strlen(src);
+  for(;i>0; i--) {
+    *(*dest)++ = *src++;
+  }
+}
+
+static int extracttypeinfo(char** dest, char** id) {
+  if (**id == '\0')
+    return -1;
+  // Extract the type info:
+  switch (*(*id)++) {
+    // array, static array, dynamic array:
+  case 'A': case 'G': case 'H':
+    if (extracttypeinfo(dest, id) == -1)
+      return -1;
+    append(dest, "[]");
+    return 1;
+    // pointer:
+  case 'P':
+    if (extracttypeinfo(dest, id) == -1)
+      return -1;
+    append(dest, "*");
+    return 1;
+    // reference:
+  case 'R':
+    if (extracttypeinfo(dest, id) == -1)
+      return -1;
+    append(dest, "&");
+    return 1;
+    // return value:
+  case 'Z':
+    return extracttypeinfo(dest, id);
+    // out:
+  case 'J':
+    append(dest, "out ");
+    return extracttypeinfo(dest, id);
+    // inout:
+  case 'K':
+    append(dest, "inout ");
+    return extracttypeinfo(dest, id);
+    
+    // enum:
+  case 'E': case 'T': case 'D': case 'C': case 'S': case 'I':
+    return extractidentifiers(dest, id);
+    
+    // basic types:
+  case 'n': append(dest, "none"); return 1;  // ever used?
+  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;
+
+  // typeinfo, error, instance:
+  case '@': return extractidentifiers(dest, id); // BUG: is this right?
+
+  default: append(dest, "unknown"); return 1;
+  }
+}
+
+char* d_demangle(const char* mangled, int options) {
+  char *symbol = mangled;
+  char *output = malloc(strlen(mangled)+20), *orig = output;
+  unsigned char isFunc = 0;
+  if (mangled == NULL) {
+    free(output);
+    return NULL;
+  } else if (strcmp(mangled, "_Dmain") == 0) {
+    free(output);
+    return strdup("D main");
+  }
+  if (symbol == strstr(symbol, "_D")) {
+    symbol += 2;
+    isFunc = 1;
+  } else if (symbol == strstr(symbol, "__Class_")) {
+    symbol += 8;
+  } else if (symbol == strstr(symbol, "__init_")) {
+    symbol += 7;
+  } else if (symbol == strstr(symbol, "__vtbl_")) {
+    symbol += 7;
+  } else if (symbol == strstr(symbol, "__modctor_")) {
+    symbol += 10;
+  } else if (symbol == strstr(symbol, "__moddtor_")) {
+    symbol += 10;
+  } else if (symbol == strstr(symbol, "__ModuleInfo_")) {
+    symbol += 13;
+  } else {
+    free(orig);
+    return NULL;
+  }
+
+  if (extractidentifiers(&output, &symbol) < 0) {
+    free(orig);
+    return NULL;
+  }
+  append(&output, "(");
+  if (isFunc == 1 && *symbol == 'F') {
+    symbol++;
+    while (*symbol != '\0' && *symbol != 'Z') {
+      if (isFunc == 1) {
+	isFunc++;
+      } else {
+	append(&output, ", ");
+      }
+      if (extracttypeinfo(&output, &symbol) < 0) {
+	free(orig);
+	return NULL;
+      }
+    }
+  }
+  append(&output, ")");
+
+  //Doesn't display the return type, but wouldn't be too hard to do.
+  
+  *output = '\0';
+  output = strdup(orig);
+  free(orig);
+  return output;
+}
+
+char* d_sym_demangle(const struct general_symbol_info *gsymbol) {
+  return d_demangle(gsymbol->name, 0);
+}
+
+const struct language_defn d_language_defn =
 {
-  "minimal",			/* Language name */
-  language_minimal,
+  "d",				/* Language name */
+  language_d,
   NULL,
   range_check_off,
   type_check_off,
@@ -719,7 +924,7 @@
   NULL,				/* value_of_this */
   basic_lookup_symbol_nonlocal,	/* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
-  NULL,				/* Language specific symbol demangler */
+  d_demangle,			/* Language specific symbol demangler */
   NULL,				/* Language specific class_name_from_physname */
   c_op_print_tab,		/* expression operators for printing */
   1,				/* c-style arrays */
@@ -733,7 +938,8 @@
 void
 _initialize_c_language (void)
 {
-  add_language (&c_language_defn);
+  add_language (&c_language_defn); 
+  add_language (&d_language_defn);
   add_language (&cplus_language_defn);
   add_language (&asm_language_defn);
   add_language (&minimal_language_defn);
Index: gdb/language.c
===================================================================
--- gdb/language.c	(revision 7)
+++ gdb/language.c	(working copy)
@@ -553,6 +553,7 @@
     {
     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 ?
@@ -664,6 +665,7 @@
     {
     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;
@@ -704,6 +706,7 @@
 
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       return (TYPE_CODE (type) == TYPE_CODE_INT) &&
 	TYPE_LENGTH (type) == sizeof (char)
@@ -726,6 +729,7 @@
 
     case language_c:
     case language_cplus:
+    case language_d:
     case language_objc:
       /* C does not have distinct string type. */
       return (0);
@@ -745,6 +749,7 @@
     {
     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
@@ -818,6 +823,7 @@
 	}
       return builtin_type_f_logical_s2;
     case language_cplus:
+    case language_d:
     case language_pascal:
       if (current_language->la_language==language_cplus)
         {sym = lookup_symbol ("bool", NULL, VAR_DOMAIN, NULL, NULL);}
Index: gdb/c-lang.h
===================================================================
--- gdb/c-lang.h	(revision 7)
+++ gdb/c-lang.h	(working copy)
@@ -28,6 +28,7 @@
 
 #include "value.h"
 #include "macroexp.h"
+#include "symtab.h"
 
 
 extern int c_parse (void);	/* Defined in c-exp.y */
@@ -90,4 +91,13 @@
 extern int cp_is_vtbl_member (struct type *);
 
 
+/*****************************
+ D Language stuff
+******************************/
+
+char* d_demangle(const char* mangled, int options);
+
+char* d_sym_demangle(const struct general_symbol_info *gsymbol);
+
+
 #endif /* !defined (C_LANG_H) */
Index: gdb/defs.h
===================================================================
--- gdb/defs.h	(revision 7)
+++ gdb/defs.h	(working copy)
@@ -190,6 +190,7 @@
     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 */
Index: gdb/symfile.c
===================================================================
--- gdb/symfile.c	(revision 7)
+++ gdb/symfile.c	(working copy)
@@ -2169,6 +2169,7 @@
       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);

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

end of thread, other threads:[~2006-04-29 15:18 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-04-19 11:18 D Symbol Demangling Thomas Kuehne
2006-04-20 13:20 ` Daniel Jacobowitz
2006-04-20 15:20   ` OT: copyright issues (was: Re: D Symbol Demangling) Baurzhan Ismagulov
2006-04-20 15:40     ` DJ Delorie
2006-04-20 15:46       ` Daniel Jacobowitz
2006-04-20 16:39         ` Baurzhan Ismagulov
2006-04-20 17:05           ` Daniel Jacobowitz
2006-04-20 17:11             ` Baurzhan Ismagulov
2006-04-21 21:25   ` D Symbol Demangling Thomas Kühne
2006-04-22 22:52     ` Thomas Kühne
2006-04-24 17:21       ` Jim Blandy
2006-04-24 20:53         ` Daniel Jacobowitz
2006-04-25  3:35           ` Eli Zaretskii
2006-04-25 14:13             ` DJ Delorie
2006-04-29  7:23               ` Thomas Kühne
2006-04-29 16:47                 ` DJ Delorie
  -- strict thread matches above, loose matches on Subject: below --
2005-04-04  2:37 John Demme
2005-04-04 18:21 ` Michael Snyder
2005-04-04 20:44   ` John Demme
2005-04-04 20:47     ` Daniel Jacobowitz
2005-04-04 21:49     ` Michael Snyder
2005-04-04 22:39       ` John Demme
     [not found]       ` <1112654359.14153.50.camel@localhost.localdomain>
     [not found]         ` <4251CF00.5080002@redhat.com>
2005-04-08 16:47           ` John Demme
2005-04-08 16:52             ` Daniel Jacobowitz
2005-04-08 20:50               ` John Demme
2005-04-08 21:11                 ` Daniel Jacobowitz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox