This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

libiberty: D demangler support


The attached patch adds symbol demangling support for D[1] to libiberty.

todo: replace the include cludge with a propper MAKE rule

Thomas

[1] http://digitalmars.com/d/ http://home.earthlink.net/~dvdfrdmn/d/
diff -urN ./gcc/libiberty/cp-demangle.c ./gcc-demangle-d/libiberty/cp-demangle.c
--- ./gcc/libiberty/cp-demangle.c	2005-02-13 08:21:41.000000000 +0100
+++ ./gcc-demangle-d/libiberty/cp-demangle.c	2006-04-30 05:25:19.000000000 +0200
@@ -99,6 +99,7 @@
 #include "libiberty.h"
 #include "demangle.h"
 #include "cp-demangle.h"
+#include "d-demangle.h"
 
 /* If IN_GLIBCPP_V3 is defined, some functions are made static.  We
    also rename them via #define to avoid compiler errors when the
@@ -3909,6 +3910,16 @@
     }
   else
     {
+      if ((mangled[0] == '_') && (mangled[1] == 'D') && IS_DIGIT(mangled[2])
+            && (mangled[2] != '0'))
+       {
+         ret = DD_(demangle_d)(mangled);
+         if (ret)
+          {
+            *palc = strlen(ret);
+            return ret;
+          }
+       }
       if ((options & DMGL_TYPES) == 0)
 	return NULL;
       type = 1;
@@ -4457,3 +4468,7 @@
 }
 
 #endif /* STANDALONE_DEMANGLER */
+
+/* FIXME include d-demangle.c in build system */
+#include "d-demangle.c"
+
diff -urN ./gcc/libiberty/d-demangle.c ./gcc-demangle-d/libiberty/d-demangle.c
--- ./gcc/libiberty/d-demangle.c	1970-01-01 01:00:00.000000000 +0100
+++ ./gcc-demangle-d/libiberty/d-demangle.c	2006-04-30 05:25:19.000000000 +0200
@@ -0,0 +1,946 @@
+/*
+ * demangle_d - pluggable D de-mangler
+ * Copyright (C) 2006 Thomas Kuehne <thomas@kuehne.cn>
+ *
+ * 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.
+ *
+ * As a special exception, the copyright holders of this library give you
+ * permission to link this library with independent modules to produce an
+ * executable, regardless of the license terms of these independent modules,
+ * and to copy and distribute the resulting executable under terms of your
+ * choice, provided that you also meet, for each linked independent module,
+ * the terms and conditions of the license of that module. An independent
+ * module is a module which is not derived from or based on this library.
+ *
+ * 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 "d-demangle-internal.h"
+
+
+#ifdef D_DEMANGLE_REQUIRE_strndup
+/* Copy n first bytes into a newly allocated buffer.  */
+char*
+xstrndup(source, n)
+   const char* source; size_t n;
+{
+   char* dest;
+   dest = xmalloc(n+1);
+   xmemcpy(dest, source, n);
+   dest[n] = 0;
+   return dest;
+}
+#endif
+
+#ifdef D_DEMANGLE_REQUIRE_memmove
+/* Copy n bytes from memory area src to memory area dest.  */
+void * xmemmove(dest, src, n)
+   void *dest; const void *src; size_t n;
+{
+   void* tmp;
+   char* a;
+   const char* b;
+
+   a = (char*) dest;
+   b = (const char*) src;
+
+   if (((a < b) && (a + n < b)) || (((b < a) && (b + n < a))))
+      return xmemcpy(dest, src, n);
+   else
+    {
+      tmp = xmalloc(n);
+      xmemcpy(tmp, src, n);
+      xmemcpy(dest, tmp, n);
+      xfree(tmp);
+      return dest;
+    }
+}
+#endif
+
+
+#ifdef D_DEMANGLE_REQUIRE_strtol_10
+/* Convert the beginning of string src to an integer using base 10. 
+   If endptr is not NULL, store the address of the first invalid character in
+   *endptr.  */
+long int
+xstrtol_10(src, endptr)
+   const char* src; char const ** 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
+
+#ifdef D_DEMANGLE_REQUIRE_malloc
+/* Allocate n bytes and returns a pointer to the allocated memory.  */
+void*
+xmalloc(n)
+   size_t n;
+{
+   void* ptr;
+   ptr = malloc(n);
+   if (!ptr)
+      xerror(NULL);
+   return ptr;
+}
+#endif
+
+#ifdef D_DEMANGLE_REQUIRE_realloc
+/* Changes the size of the memory block pointed to by ptr to len bytes.  */
+void*
+xrealloc(ptr, len)
+   void* ptr; size_t len;
+{
+   ptr = realloc(ptr, len);
+   if (!ptr)
+      xerror(NULL);
+   return ptr;
+}
+#endif
+
+#ifdef D_DEMANGLE_REQUIRE_error
+/* Print error message and abort.  If message is null, print the last
+   encountered system error and abort.  */
+void
+xerror(message)
+   const char* message;
+{
+   if (message)
+      xfprintf(stderr, message);
+   else
+      xperror("demangle_d");
+   xabort();
+}
+#endif
+
+/* Create and initialize a new string.  */
+string_t
+new_string()
+{
+    string_t str = xmalloc(sizeof(string_t));
+    str->used = 0;
+    str->len = 128;
+    str->str = xmalloc(str->len);
+    str->str[0] = 0;
+    return str;
+}
+
+/* Append len bytes from source string to dest string.  */
+void
+append_n(dest, source, len)
+    string_t dest; const char* source; size_t len;
+{
+    size_t new_len;
+    new_len = dest->used + len + 1;
+    if (new_len > dest->len)
+      {
+	dest->len = new_len + (new_len >> 1);
+	dest->str = xrealloc(dest->str, dest->len);
+      }
+    xmemcpy(dest->str + dest->used, source, len);
+    dest->used += len;
+    dest->str[dest->used] = 0;
+}
+
+/* Append source char to dest string.  */
+void
+append_c(dest, source)
+    string_t dest; int source;
+{
+    size_t new_len;
+    new_len = dest->used + 2;
+    if (new_len > dest->len)
+      {
+	dest->len = new_len + (new_len >> 1);
+	dest->str = xrealloc(dest->str, dest->len);
+      }
+    dest->str[dest->used++] = (char)source;
+    dest->str[dest->used] = 0;
+}
+
+/* Append NULL-terminated string source to dest.  */
+void
+append(dest, source)
+    string_t dest; const char* source;
+{
+    append_n(dest, source, xstrlen(source));
+}
+
+/* Prepend len bytes from source string to dest string.  */
+void
+prepend_n(dest, source, len)
+    string_t dest; const char* source; size_t len;
+{
+    size_t new_len;
+    new_len = dest->used + len + 1;
+    if (new_len > dest->len)
+      {
+	dest->len = new_len + (new_len >> 1);
+	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] = 0;
+}
+
+/* Prepend NULL-terminated string source to dest.  */
+void
+prepend(dest, source)
+    string_t dest; const char* source;
+{
+    prepend_n(dest, source, xstrlen(source));
+}
+
+/* If not nested, append len bytes from source string to dest else
+   prepend with space.  */
+void
+nestpend_n(dest, source, len, is_nested)
+    string_t dest; const char* source; size_t len; int is_nested;
+{
+    if (is_nested)
+	append_n(dest, source, len);
+    else
+      {
+	prepend(dest, " ");
+	prepend_n(dest, source, len);
+      }
+}
+
+/* If not nested, append NULL-terminated source string to dest else
+   prepend with space.  */
+void
+nestpend(dest, source, is_nested)
+    string_t dest; const char* source; int is_nested;
+{
+    nestpend_n(dest, source, xstrlen(source), is_nested);
+}
+
+/* Parse until the end of the next type and return the pointer to the first
+   uninterpreted charachter or NULL.  Set is_nested if a nested type
+   (e.g. index of AA or template/function parameter) is parsed.  */
+const char*
+next_type(dest, source, is_nested)
+	string_t dest; const char* source; int is_nested;
+{
+    if (!source || !source[0])
+	return NULL;
+
+    if ((source[0] == '_') && (source[1] == 'D') && xisdigit(source[2])
+	    && (source[2] != '0'))
+      {
+	string_t tmp;
+	tmp = new_string();
+	source = next_type(tmp, source + 2, 0);
+	if (dest->used && (dest->str[dest->used] != '.'))
+	    append_c(dest, '.');
+	append_n(dest, tmp->str, tmp->used);
+	xfree(tmp->str);
+	xfree(tmp);
+	return source;
+      }
+
+    switch(source[0])
+      {
+	case 'v':
+	    nestpend(dest, "void", is_nested);
+	    source += 1;
+	    break;
+	case 'b': /* deprecated since DMD-0.148 (2006-02-25) */
+	    nestpend(dest, "bit", is_nested);
+	    source += 1;
+	    break;
+	case 'x':
+	    nestpend(dest, "bool", is_nested);
+	    source += 1;
+	    break;
+	case 'g':
+	    nestpend(dest, "byte", is_nested);
+	    source += 1;
+	    break;
+	case 'h':
+	    nestpend(dest, "ubyte", is_nested);
+	    source += 1;
+	    break;
+	case 's':
+	    nestpend(dest, "short", is_nested);
+	    source += 1;
+	    break;
+	case 't':
+	    nestpend(dest, "ushort", is_nested);
+	    source += 1;
+	    break;
+	case 'i':
+	    nestpend(dest, "int", is_nested);
+	    source += 1;
+	    break;
+	case 'k':
+	    nestpend(dest, "uint", is_nested);
+	    source += 1;
+	    break;
+	case 'l':
+	    nestpend(dest, "long", is_nested);
+	    source += 1;
+	    break;
+	case 'm':
+	    nestpend(dest, "ulong", is_nested);
+	    source += 1;
+	    break;
+	case 'f':
+	    nestpend(dest, "float", is_nested);
+	    source += 1;
+	    break;
+	case 'd':
+	    nestpend(dest, "double", is_nested);
+	    source += 1;
+	    break;
+	case 'e':
+	    nestpend(dest, "real", is_nested);
+	    source += 1;
+	    break;
+	case 'o':
+	    nestpend(dest, "ifloat", is_nested);
+	    source += 1;
+	    break;
+	case 'p':
+	    nestpend(dest, "idouble", is_nested);
+	    source += 1;
+	    break;
+	case 'j':
+	    nestpend(dest, "ireal", is_nested);
+	    source += 1;
+	    break;
+	case 'q':
+	    nestpend(dest, "cfloat", is_nested);
+	    source += 1;
+	    break;
+	case 'r':
+	    nestpend(dest, "cdouble", is_nested);
+	    source += 1;
+	    break;
+	case 'c':
+	    nestpend(dest, "creal", is_nested);
+	    source += 1;
+	    break;
+	case 'a':
+	    nestpend(dest, "char", is_nested);
+	    source += 1;
+	    break;
+	case 'u':
+	    nestpend(dest, "wchar", is_nested);
+	    source += 1;
+	    break;
+	case 'w':
+	    nestpend(dest, "dchar", is_nested);
+	    source += 1;
+	    break;
+
+	case 'A': /* dynamic array */
+	    if (!is_nested)
+		prepend(dest, "[] ");
+	    source = next_type(dest, source+1, is_nested);
+	    if (is_nested)
+		append(dest, "[]");
+	    break;
+
+	case 'G':  /* static array */
+	  {
+	    const char* start;
+	    const char* end;
+	    start = ++source;
+	    end = start;
+
+	    while (xisdigit(*end))
+		end++;
+	
+	    if (!is_nested)
+	      {
+		prepend(dest, "] ");
+		prepend_n(dest, start, end-start);
+		prepend(dest, "[");
+	      }
+	    source = next_type(dest, end, is_nested);
+	    if (is_nested)
+	      {
+		append_c(dest, '[');
+		append_n(dest, start, end-start);
+		append_c(dest, ']');
+	      }
+	    break;
+	  }
+
+	case 'H': /* associative array */
+	  {
+	    string_t aa;
+	    aa = new_string();
+	    source = next_type(aa, source+1, 1);
+	    prepend(aa, "[");
+	    append_c(aa, ']');
+	    source = next_type(aa, source, 0);
+	    nestpend(dest, aa->str, is_nested);
+	    xfree(aa->str);
+	    xfree(aa);
+	    break;
+	  }
+
+	case 'D': /* delegate */
+	  {
+	    string_t sig;
+	    sig = new_string();
+	    source = parse_function(sig, source+1, NULL, 0);
+	    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 */
+		string_t sig;
+		sig = new_string();
+		source = parse_function(sig, source+1, "", 0);
+		nestpend_n(dest, sig->str, sig->used, is_nested);
+		xfree(sig->str);
+		xfree(sig);
+	      }
+	    else
+	      {
+		/* 'normal' type */
+		if (!is_nested)
+		    prepend(dest, "* ");
+		source = next_type(dest, source+1, is_nested);
+		if (is_nested)
+		    append(dest, " *");
+	      }
+	    break;
+
+	case 'J': /* out */
+	    append(dest, "out ");
+	    source = next_type(dest, source+1, 1);
+	    break;
+
+	case 'K': /* inout */
+	    append(dest, "inout ");
+	    source = next_type(dest, source+1, 1);
+	    break;
+
+	case 'C': /* class */
+	case 'S': /* struct */
+	case 'E': /* enum */
+	case 'T': /* typedef */
+	  {
+#ifdef D_DEMANGLE_VERBOSE
+	    char tmp;
+	    tmp = source[0];
+#endif /* D_DEMANGLE_VERBOSE */
+	    if (!is_nested)
+	      {
+		string_t sig;
+		sig = new_string();
+		source = next_type(sig, source+1, 0);
+		append_c(sig, ' ');
+#ifdef D_DEMANGLE_VERBOSE
+		switch (tmp)
+		  {
+		    case 'C':
+			prepend(sig, "class ");
+			break;
+		    case 'S':
+			prepend(sig, "struct ");
+			break;
+		    case 'E':
+			prepend(sig, "enum ");
+			break;
+		    case 'T':
+			prepend(sig, "typedef ");
+			break;
+		  }
+#endif /* D_DEMANGLE_VERBOSE */
+		prepend_n(dest, sig->str, sig->used);
+		xfree(sig->str);
+		xfree(sig);
+	      }
+	    else
+	      {
+#ifdef D_DEMANGLE_VERBOSE
+		switch (tmp)
+		  {
+		    case 'C':
+			append(dest, "class ");
+			break;
+		    case 'S':
+			append(dest, "struct ");
+			break;
+		    case 'E':
+			append(dest, "enum ");
+			break;
+		    case 'T':
+			append(dest, "typedef ");
+			break;
+		  }
+#endif /* D_DEMANGLE_VERBOSE */
+		source = next_type(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':
+	  {
+	    int first_round;
+	    first_round = 1;
+
+	    while (source && xisdigit(source[0]) && (source[0] != '0'))
+	      {
+		long int len;
+		len = xstrtol_10(source, &source);
+
+		if (!first_round)
+		    append_c(dest, '.');
+		else
+		    first_round = 0;
+		
+		if (len >= 5 && (source[0] == '_') && (source[1] == '_')
+			&& (source[2] == 'T') && xisdigit(source[3])
+			&& (source[3] != '0'))
+		  {
+		    /* template */
+		    char* template;
+		    template = xstrndup(source + 3, len-3);
+		    interprete_template(dest, template);
+		    xfree(template);
+		  }
+		else if((len == 5) && (xstrncmp(source, "_ctor", len) == 0))
+		    append(dest, "this");
+		else if((len == 5) && (xstrncmp(source, "_dtor", len) == 0))
+		    append(dest, "~this");
+		else if((len == 11)
+			&& (xstrncmp(source, "_staticCtorFZv", len + 3) == 0))
+		  {
+		    prepend(dest, "static void ");
+		    append(dest, "this()");
+		    source = source + 11 + 3;
+		    break;
+		  }
+		else if((len == 11)
+			&& (xstrncmp(source, "_staticDtorFZv", len + 3) == 0))
+		  {
+		    prepend(dest, "static void ");
+		    append(dest, "~this()");
+		    source = source + 11 + 3;
+		    break;
+		  }
+		else
+		    /* plain identifier part */
+		    append_n(dest, source, len);
+
+		source += len;
+	      }
+	    if (!is_nested)
+		source = next_type(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)
+	      {
+		string_t id;
+		id = new_string();
+		append_n(id, dest->str, dest->used);
+		dest->used = 0;
+		dest->str[0] = 0;
+		source = parse_function(dest, source, id->str, 0);
+		xfree(id->str);
+		xfree(id);
+	      }
+	    else
+		source = parse_function(dest, source, "", 1);
+	    break;
+
+	default:
+	    append(dest, " @bug@[2]{");
+	    append(dest, source);
+	    append_c(dest, '}');
+	    source = NULL;
+	    break;
+      }
+
+    return source;
+}
+
+/* Parse a "real" template parameter and return a pointer to the first not
+   interpreted character.  */
+const char*
+parse_real(dest, source)
+	string_t dest; const char* source;
+{
+    /* FIXME architecture dependent */
+    long double f;
+    size_t i;
+    int tmp;
+    char* buffer;
+    unsigned char* c;
+    
+    c = (unsigned char*) &f;
+
+    for (i = 0; i < 10; i++)
+      {
+	if (!xisxdigit(source[i * 2]) || !xisxdigit(source[i * 2 + 1]))
+	  {
+format_error:
+	    append(dest, "0x");
+	    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;
+      }
+    append_n(dest, buffer, tmp);
+    xfree(buffer);
+    return source + 20;
+}
+
+/* Parse a function - including arguments and return type - and
+   return a pointer to the first not interpreted character.  */
+const char*
+parse_function(dest, source, name, is_nested)
+	string_t dest; const char* source; const char* name;
+	const int is_nested;
+{
+    string_t fn_return;
+    string_t fn_param;
+
+    fn_return = new_string();
+    fn_param = new_string();
+
+    source++;
+
+    /* params */
+    if (source[0] != 'Z')
+      {
+	if (source[0] == 'Y')
+	  {
+	    append(fn_param, "...");
+	    goto var_arg_param;
+	  }
+	source = next_type(fn_param, source, 1);
+	while (source && source[0] && source[0]!='Z')
+	  {
+	    if (source[0] == 'Y')
+	      {
+		append(fn_param, ", ...");
+		goto var_arg_param;
+	      }
+	    else if(source[0] == 'X')
+	      {
+		append(fn_param, " ...");
+		goto var_arg_param;
+	      }
+	    append(fn_param, ", ");
+	    source = next_type(fn_param, source, 1);
+	  }
+      }
+
+    /* return type */
+    if (source && source[0] == 'Z')
+var_arg_param:
+	source = next_type(fn_return, source + 1, 1);
+
+    /* output */
+    if (name && name[0])
+	if (! is_nested)
+	  {
+	    prepend(dest, " ");
+	    prepend_n(dest, fn_return->str, fn_return->used);
+	    append(dest, name);
+	  }
+	else
+	  {
+	    append_n(dest, fn_return->str, fn_return->used);
+	    append_c(dest, ' ');
+	    append(dest, name);
+	  }
+    else if(name)
+      {
+	append_n(dest, fn_return->str, fn_return->used);
+	append(dest, " function");
+      }
+    else
+      {
+	append_n(dest, fn_return->str, fn_return->used);
+	append(dest, " delegate");
+      }
+
+    if (fn_param->used)
+      {
+	append_c(dest, '(');
+	append_n(dest, fn_param->str, fn_param->used);
+	append_c(dest, ')');
+      }
+    else
+	append(dest, "()");
+
+    xfree(fn_return->str);
+    xfree(fn_return);
+    xfree(fn_param->str);
+    xfree(fn_param);
+
+    return source;
+}
+
+/* Interprete the NULL terminated template symbol.  */
+void
+interprete_template(dest, raw)
+	string_t dest; const char* raw;
+{
+    const char* tmp;
+    long int dataLen;
+    int first_arg;
+
+    first_arg = 1;
+
+    /* id */
+    while (xisdigit(raw[0]) && (raw[0] != '0'))
+      {
+	long int len;
+	len = xstrtol_10(raw, &raw);
+	append_n(dest, raw, len);
+	raw += len;
+      }
+    append(dest, "!(");
+
+    /* arguments */
+    while (raw && raw[0])
+      {
+	if (raw[0] == 'T')
+	  {
+	    /* type parameter */
+	    raw++;
+	    if (!first_arg)
+		append(dest, ", ");
+	    else
+		first_arg = 0;
+	    raw = next_type(dest, raw, 1);
+	  }
+	else if(raw[0] == 'V')
+	  {
+	    /* value parameter */
+	    if (!first_arg)
+		append(dest, ", ");
+	    else
+		first_arg = 0;
+	    raw = next_type(dest, raw + 1, 1);
+	    append_c(dest, ' ');
+	    if (xisdigit(raw[0]))
+	      {
+		/* positive integer */
+integer_arg:
+		tmp = raw;
+		while (xisdigit(raw[0]))
+		    raw++;
+		append_n(dest, tmp, raw-tmp);
+	      }
+	    else if(raw[0] == 'N')
+	      {
+		/* negative integer */
+		raw++;
+		append_c(dest, '-');
+		goto integer_arg;
+	      }
+	    else if(raw[0] == 'e')
+		/* float */
+		raw = parse_real(dest, raw+1);
+	    else if(raw[0] == 'c')
+	      {
+		/* complex float */
+		raw = parse_real(dest, raw+1);
+		append(dest, " + ");
+		raw = parse_real(dest, raw);
+		append_c(dest, 'i');
+	      }
+	    else if(raw[0] == 'n')
+	      {
+		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++;
+		append_c(dest, '"');
+		while (dataLen--)
+		  {
+		    if (xisxdigit(raw[0]) && xisxdigit(raw[1]))
+			append_c(dest, (xasci2hex(raw[0]) << 4)
+				+ xasci2hex(raw[1]));
+		    else
+			append_c(dest, '?');
+		    raw += 2;
+		  }
+		append_c(dest, '"');
+	      }
+	    else
+		goto bug;
+	  }
+	else if(raw[0] == 'Z')
+	    /* end of parameter list */
+	    break;
+	else
+	  {
+bug:
+	    append(dest, " @bug@[1]{");
+	    append(dest, raw);
+	    append_c(dest, '}');
+	    break;
+	  }
+      }
+    append_c(dest, ')');
+}
+
+/* Demangle the NULL-terminated D symbol and return the UTF-8 encoded
+   representation or NULL.  The caller is responsible to free input and
+   output.  */
+char*
+demangle_d(source)
+	const char* source;
+{
+    string_t dest;
+    string_t nested;
+    char* back;
+
+    if ((source[0] != '_') || (source[1] != 'D') || (!xisdigit(source[2]))
+	    || (source[2] == '0'))
+      {
+	/* FIXME might be mangled with 'D' but hasn't 'D' linkage
+	 * samples:
+	 * _aaApply10treewalkerFPS3aaA3aaAZi
+	 * _aaKeys9_aaKeys_xFPS3aaA3aaAZv
+	 */
+	/* FIXME handle special cases:
+	 * _init__D1b11_staticCtorFZv3Al
+	 * _Class__D1b11_staticCtorFZv3Ali
+	 * _vtbl__D1b11_staticCtorFZv3Ali
+	 * _modctor_1b
+	 * _assert_1b
+	 */
+	return NULL;
+      }
+    else
+	source += 2;
+
+    dest = new_string();
+
+    source = next_type(dest, source, 0);
+
+    while (source && source[0])
+      {
+	/* nested symbols */
+	nested = new_string();
+	append_c(dest, '.');
+	source = next_type(nested, source, 0);
+	append_n(dest, nested->str, nested->used);
+	xfree(nested->str);
+	xfree(nested);
+      }
+
+    back = xstrndup(dest->str, dest->used+1);
+    xfree(dest->str);
+    xfree(dest);
+
+    return back;
+}
+
+
+#ifdef D_DEMANGLE_STANDALONE
+int
+main(int argc, char** argv)
+{
+   int i;
+   if (argc < 2)
+     {
+      xfprintf(stderr,
+         _("pluggable D d-demangler by Thomas Kuehne <thomas@kuehne.cn> (%s)\n"),
+         "$Date: 2006-04-22T22:40:29.553250Z $");
+      xfprintf(stderr, _("%s <mangledSymbol_1> [<mangledSymbol_2> ...]\n"),
+	    argc ? argv[0] :"demangle_d");
+      return (EXIT_FAILURE);
+     }
+   for (i = 1; i < argc; i++)
+     {
+      char* demangled = demangle_d(argv[i]);
+      if (1 > xprintf(_("%s\t%s\n"), argv[i], demangled))
+         xperror(NULL);
+      if (demangled)
+         xfree(demangled);
+     }
+   return (EXIT_SUCCESS);
+}
+#endif /* D_DEMANGLE_STANDALONE */
diff -urN ./gcc/libiberty/d-demangle.h ./gcc-demangle-d/libiberty/d-demangle.h
--- ./gcc/libiberty/d-demangle.h	1970-01-01 01:00:00.000000000 +0100
+++ ./gcc-demangle-d/libiberty/d-demangle.h	2006-04-30 05:25:18.000000000 +0200
@@ -0,0 +1,21 @@
+#ifndef D_DEMANGLE_H
+#define D_DEMANGLE_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
+ */
+char* DD_(demangle_d)(const char*);
+
+#endif /* D_DEMANGLE_H */
diff -urN ./gcc/libiberty/d-demangle-internal.h ./gcc-demangle-d/libiberty/d-demangle-internal.h
--- ./gcc/libiberty/d-demangle-internal.h	1970-01-01 01:00:00.000000000 +0100
+++ ./gcc-demangle-d/libiberty/d-demangle-internal.h	2006-04-30 05:25:18.000000000 +0200
@@ -0,0 +1,251 @@
+/*
+ * demangle_d - pluggable D de-mangler
+ * Copyright (C) 2006 Thomas Kuehne <thomas@kuehne.cn>
+ *
+ * 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.
+ *
+ * As a special exception, the copyright holders of this library give you
+ * permission to link this library with independent modules to produce an
+ * executable, regardless of the license terms of these independent modules,
+ * and to copy and distribute the resulting executable under terms of your
+ * choice, provided that you also meet, for each linked independent module,
+ * the terms and conditions of the license of that module. An independent
+ * module is a module which is not derived from or based on this library.
+ *
+ * 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
+ *
+ */
+
+#ifndef D_DEMANGLE_INTERNAL_H
+#define D_DEMANGLE_INTERNAL_H 1
+
+#include "d-demangle.h"
+
+#undef D_DEMANGLE_REQUIRE_ISDIGIT
+#undef D_DEMANGLE_REQUIRE_ISXDIGIT
+#undef D_DEMANGLE_REQUIRE_ASCI2HEX
+
+#ifdef D_DEMANGLE_IN_VALGRIND
+
+/* valgrind - http://www.valgrind.org */
+
+#include <stddef.h> /* size_t */
+
+#define xstrlen		VG_(strlen)
+#define xstrncmp	VG_(strncmp)
+#define xsnprintf	VG_(snprintf)
+#define xisdigit	ISDIGIT
+#define D_DEMANGLE_REQUIRE_ISDIGIT 1
+#define xisxdigit	ISXDIGIT
+#define D_DEMANGLE_REQUIRE_ISXDIGIT 1
+#define xasci2hex	ASCI2HEX
+#define D_DEMANGLE_REQUIRE_ASCI2HEX 1
+
+#else /* not D_DEMANGLE_IN_VALGRIND */
+
+/* "normal" libc */
+
+#include <stddef.h> /* size_t */
+
+#include <string.h>
+#define xstrlen		strlen
+#define xstrncmp	strncmp
+
+#include <stdlib.h>
+#define xabort		abort
+
+#include <stdio.h>
+#define xsnprintf	snprintf
+
+#include <ctype.h>
+#define xisdigit	isdigit
+#define xisxdigit	isxdigit
+
+#define xasci2hex	ASCI2HEX
+#define D_DEMANGLE_REQUIRE_ASCI2HEX 1
+
+#endif /* not D_DEMANGLE_IN_VALGRIND */
+
+
+/* helper macros */
+
+#ifdef D_DEMANGLE_REQUIRE_ISDIGIT
+#define ISDIGIT(c) (('0' <= (c)) && ((c) <= '9'))
+#endif
+
+#ifdef D_DEMANGLE_REQUIRE_ISXDIGIT
+#define ISXDIGIT(c) ( \
+		(('0' <= (c)) && ((c) <= '9')) \
+		|| (('a' <= (c)) && ((c) <= 'f')) \
+		|| (('A' <= (c)) && ((c) <= 'F')) \
+		)
+#endif
+
+#ifdef D_DEMANGLE_REQUIRE_ASCI2HEX
+#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
+
+#undef D_DEMANGLE_REQUIRE_strndup
+#undef D_DEMANGLE_REQUIRE_strtol_10
+#undef D_DEMANGLE_REQUIRE_malloc
+#undef D_DEMANGLE_REQUIRE_realloc
+#undef D_DEMANGLE_REQUIRE_memmove
+#undef D_DEMANGLE_REQUIRE_error
+
+#ifdef D_DEMANGLE_IN_VALGRIND
+/* gdb - http://www.gnu.org/software/gdb/ */
+
+#define xstrndup        DD_(strndup)
+#define D_DEMANGLE_REQUIRE_strndup 1
+#define xstrtol_10      DD_(strtol_10)
+#define D_DEMANGLE_REQUIRE_strtol_10 1
+#define xmalloc         VG_(malloc)
+#define xrealloc        VG_(realloc)
+#define xmemmove        DD_(memmove)
+#define D_DEMANGLE_REQUIRE_memmove 1
+#define xfree           VG_(free)
+#define xmemcpy         VG_(memcpy)
+
+#else  /* not D_DEMANGLE_IN_VALGRIND && not D_DEMANGLE_IN_GDB */
+/* 'normal' libc */
+
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(__USE_GNU) || defined(_GNU_SOURCE)
+#define xstrndup	strndup
+#else
+#define xstrndup	DD_(strndup)
+#define D_DEMANGLE_REQUIRE_strndup 1
+#endif
+
+#define xstrtol_10      DD_(strtol_10)
+#define D_DEMANGLE_REQUIRE_strtol_10 1
+
+#define xmalloc		DD_(malloc)
+#define D_DEMANGLE_REQUIRE_malloc 1
+#define xrealloc	DD_(realloc)
+#define D_DEMANGLE_REQUIRE_realloc 1
+#define xmemmove	memmove
+#define xfree		free
+#define xmemcpy		memcpy
+
+#ifdef D_DEMANGLE_STANDALONE
+#define D_DEMANGLE_REQUIRE_error 1
+#define xerror		DD_(error)
+#define xprintf		printf
+#define xperror		perror
+#define xfprintf	fprintf
+#endif
+
+#endif  /* not D_DEMANGLE_IN_VALGRIND && not D_DEMANGLE_IN_GDB */
+
+#ifdef D_DEMANGLE_REQUIRE_strndup
+char* xstrndup(const char*, size_t);
+#endif
+
+#ifdef D_DEMANGLE_REQUIRE_strtol_10
+long int xstrtol_10(const char*, char const **);
+#endif
+
+#ifdef D_DEMANGLE_REQUIRE_malloc
+void* xmalloc(size_t);
+#define D_DEMANGLE_REQUIRE_error 1
+#endif
+
+#ifdef D_DEMANGLE_REQUIRE_realloc
+void* xrealloc(void*, size_t);
+#define D_DEMANGLE_REQUIRE_error 1
+#endif
+
+#ifdef D_DEMANGLE_REQUIRE_memmove
+void * xmemmove(void*, const void *, size_t );
+#endif
+
+#ifdef D_DEMANGLE_REQUIRE_error
+void xerror(const char*);
+#ifndef xperror
+#define xperror		perror
+#endif
+#ifndef xfprintf
+#define xfprintf	fprintf
+#endif
+#endif
+
+#define string_t	DD_(string_t)
+#define new_string	DD_(new_string)
+#define append_n	DD_(append_n)
+#define append_c	DD_(append_c)
+#define append		DD_(append)
+#define prepend_n	DD_(prepend_n)
+#define prepend		DD_(prepend)
+#define nestpend_n	DD_(nestpend_n)
+#define nestpend	DD_(nestpend)
+
+typedef struct{
+	size_t	used;
+	char*	str;
+	size_t	len;
+}* string_t;
+
+string_t new_string(void);
+
+void append(string_t, const char *);
+void append_n(string_t, const char *, size_t);
+void append_c(string_t, int);
+
+void prepend(string_t, const char *);
+void prepend_n(string_t, const char *, size_t);
+
+void nestpend_n(string_t, const char *, size_t, int);
+void nestpend(string_t, const char*, int);
+
+
+#define next_type		DD_(next_type)
+#define interprete_template	DD_(interprete_template)
+#define parse_real		DD_(parse_real)
+#define parse_function		DD_(parse_function)
+#define demangle_d		DD_(demangle_d)
+
+const char* next_type(string_t, const char*, int);
+
+void interprete_template(string_t, const char*);
+
+const char* parse_real(string_t, const char*);
+
+const char* parse_function(string_t, const char*, const char*, int);
+
+#ifndef _
+#define _(str)		str
+#endif
+
+#endif /* D_DEMANGLE_INTERNAL_H */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]