A patch for cplus-dem.c

H.J. Lu hjl@valinux.com
Sun Oct 10 16:08:00 GMT 1999


Here is my first patch for cplus-dem.c:

1. Rename the entry point from cplus_demangle to demangle_symbol.
2. Add init_demangler.
3. Add Ada/GNAT support.
4. Provide cplus_demangle () for backward compatibility.

If you don't want to use the new interface, nothing needs to be done.
You can use

	s1 = demangle_symbol (name1);
	s2 = demangle_symbol (name1);

It is equivalent to

	s1 = cplus_demangle (name1, DMGL_ANSI | DMGL_PARAMS);
	s2 = cplus_demangle (name2, DMGL_ANSI | DMGL_PARAMS);

init_demangler () can be used to control how a symbol is demangled
by demangle_symbol ().

I didn't rename the file. It will be in my followup patches. BTW, my
patch has some dlopen code, but it is not enabled. When -static is
used, you can build static binaries using cplus-dem.c only under
Linux since there are no dlopen/dlsym in the static library on
other platforms. I will come up with something in my followup patches.

BTW, I was told that the GNAT patch was from GNAT. Kenner may know more
about its copyright status.

Thanks.

-- 
H.J. Lu (hjl@gnu.org)
--
Sun Oct 10 15:48:07 1999  H.J. Lu  (hjl@gnu.org)

	* cplus-dem.c (usage): Modified -s/--format. Added
	-d/--demangler.
	(long_options): Add demangler.
	(main): Handle 'd'. Use o_style () for setting
	current_demangling_style. Call init_demangler ().

Sun Oct 10 10:46:41 1999  H.J. Lu  (hjl@gnu.org)

	* cplus-dem.c (demangle_symbol, demangle_symbol_with_options,
	init_demangler): New prototypes.

Fri Oct  1 08:15:24 1999  H.J. Lu  (hjl@gnu.org)

	* cplus-dem.c (gnat_demangle): Renamed from ada_demangle.
	(internal_ada_demangle): New.
	(cplus_demangle): Call internal_ada_demangle instead of
	ada_demangle.

Sun Feb 14 12:22:14 1999  H.J. Lu  (hjl@gnu.org)

	Based on patch from Juergen.Pfeifer@t-online.de (Juergen
	Pfeifer) on Tue, 09 Feb 1999 22:54:07:

	* cplus-dem.c (ada_demangle): New.
	(cplus_demangle): Call ada_demangle () if options & DMGL_GNAT
	is not zero.

Sat Oct  9 09:52:54 1999  H.J. Lu  (hjl@gnu.org)

	* demangle.h (DMGL_COMPAQ): New.
	(demangling_styles): Add gnat_demangling and compaq_demangling.
	(GNAT_DEMANGLING_STYLE_STRING, COMPAQ_DEMANGLING_STYLE_STRING):
	New macros.
	(demangle_symbol, demangle_symbol_with_options,
	init_demangler): New prototypes.

Sun Feb 14 12:26:18 1999  H.J. Lu  (hjl@gnu.org)

	* demangle.h (DMGL_GNAT): New.

--- ../../import/egcs/libiberty/cplus-dem.c	Sun Oct 10 09:08:14 1999
+++ libiberty/cplus-dem.c	Sun Oct 10 09:21:29 1999
@@ -38,6 +38,10 @@ Boston, MA 02111-1307, USA.  */
 #include <string.h>
 #include <stdio.h>
 
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
 #else
@@ -51,6 +55,13 @@ char * realloc ();
 
 #include "libiberty.h"
 
+static char *internal_ada_demangle PARAMS ((const char*, int));
+static char *gnat_demangle PARAMS ((const char*));
+static int o_mnemonic PARAMS ((const char *mnemonic));
+static enum demangling_styles o_style PARAMS ((const char *style));
+static char *(*demangler_function) PARAMS ((const char *, int)) = NULL;
+static int demangler_options = DMGL_ANSI | DMGL_PARAMS;
+
 #define min(X,Y) (((X) < (Y)) ? (X) : (Y))
 
 extern void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN;
@@ -436,12 +447,6 @@ static void
 recursively_demangle PARAMS ((struct work_stuff *, const char **, string *,
 			      int));
 
-static const char *
-standard_symbol_characters PARAMS ((void));
-
-static const char *
-hp_symbol_characters PARAMS ((void));
-
 /* Translate count to integer, consuming tokens in the process.
    Conversion terminates on the first non-digit character.
 
@@ -785,6 +790,7 @@ cplus_demangle (mangled, options)
 {
   char *ret;
   struct work_stuff work[1];
+
   memset ((char *) work, 0, sizeof (work));
   work -> options = options;
   if ((work -> options & DMGL_STYLE_MASK) == 0)
@@ -795,6 +801,166 @@ cplus_demangle (mangled, options)
   return (ret);
 }
 
+static int
+o_mnemonic (mnemonic)
+     const char *mnemonic;
+{
+  if (strncasecmp (mnemonic, "PARAMS", sizeof ("PARAMS") - 1) == 0)
+    return DMGL_PARAMS;
+  else if (strncasecmp (mnemonic, "ANSI", sizeof ("ANSI") - 1) == 0)
+    return DMGL_ANSI;
+  else if (strncasecmp (mnemonic, "JAVA", sizeof ("JAVA") - 1) == 0)
+    return DMGL_JAVA;
+  else if (strncasecmp (mnemonic, "AUTO", sizeof ("AUTO") - 1) == 0)
+    return DMGL_AUTO;
+  else if (strncasecmp (mnemonic, "GNU", sizeof ("GNU") - 1) == 0)
+    return DMGL_GNU;
+  else if (strncasecmp (mnemonic, "LUCID", sizeof ("LUCID") - 1) == 0)
+    return DMGL_LUCID;
+  else if (strncasecmp (mnemonic, "ARM", sizeof ("ARM") - 1) == 0)
+    return DMGL_ARM;
+  else if (strncasecmp (mnemonic, "HP", sizeof ("HP") - 1) == 0)
+    return DMGL_HP;
+  else if (strncasecmp (mnemonic, "EDG", sizeof ("EDG") - 1) == 0)
+    return DMGL_EDG;
+  else if (strncasecmp (mnemonic, "GNAT", sizeof ("GNAT") - 1) == 0)
+    return DMGL_GNAT;
+  else if (strncasecmp (mnemonic, "COMPAQ", sizeof ("COMPAQ") - 1) == 0)
+    return DMGL_COMPAQ;
+  else 
+    return DMGL_NO_OPTS;
+}
+
+static enum demangling_styles
+o_style (style)
+     const char *style;
+{
+  if (strcasecmp (style, "gnu") == 0)
+    return gnu_demangling;
+  else if (strcasecmp (style, "lucid") == 0)
+    return lucid_demangling;
+  else if (strcasecmp (style, "arm") == 0)
+    return arm_demangling;
+  else if (strcasecmp (style, "hp") == 0)
+    return hp_demangling;
+  else if (strcasecmp (style, "edg") == 0)
+    return edg_demangling;
+  else if (strcasecmp (style, "gnat") == 0)
+    return gnat_demangling;
+  else if (strcasecmp (style, "compaq") == 0)
+    return compaq_demangling;
+  return unknown_demangling;
+}
+
+int
+init_demangler (style, options, demangler)
+     const char *style;
+     const char *options;
+     const char *demangler;
+{
+#ifdef HAVE_DLFCN_H
+  char *dso = NULL;
+  char *function = NULL;
+#endif
+
+  if (style != NULL)
+    {
+      current_demangling_style = o_style (style);
+      if (current_demangling_style == unknown_demangling)
+	{
+	  fprintf (stderr, "init_demangler: unknown demangling style `%s'\n",
+		   style);
+	  exit (1);
+	}
+    }
+
+  if (options == NULL)
+     demangler_options = DMGL_ANSI | DMGL_PARAMS;
+  else
+    {
+      const char *cp;
+
+      for (cp = options; *cp; )
+	{
+	  if (*cp == ';')
+	    cp++;
+	  demangler_options |= o_mnemonic (cp);
+	  while (*cp && *cp != ':')
+	    cp++;
+	}
+    }
+
+#ifdef HAVE_DLFCN_H
+  if (demangler)
+    {
+      dso = alloca (strlen (demangler) + 1);
+      strcpy (dso, demangler);
+      function = strchr (dso, ':');
+      if (!function)
+	{
+	  fprintf (stderr, "init_demangler: invalid `dso:function': `%s'\n",
+		   demangler);
+	  exit (1);
+	}
+      *function = '\0';
+      function++;
+    }
+
+  if (current_demangling_style == compaq_demangling)
+    {
+      if (dso == NULL || *dso == '\0')
+        dso = "compaq/libcompaq_demangle.so";
+      if (function == NULL)
+        function = "libiberty_demangle_string";
+    }
+
+  if (dso && function)
+    {
+      void *handle;
+
+      handle = dlopen (dso, RTLD_LAZY);
+      if (handle == NULL)
+	{
+	  fprintf(stderr, "init_demangler: %s\n", dlerror ());
+	  exit (1);
+	}
+
+      demangler_function = dlsym (handle, function);
+      if (demangler_function == NULL)
+	{
+	  fprintf(stderr, "init_demangler: %s\n", dlerror ());
+	  exit (1);
+	}
+    }
+  else
+#endif
+    if (current_demangling_style == gnat_demangling)
+      demangler_function = internal_ada_demangle;
+    else
+      demangler_function = cplus_demangle;
+
+  return 0;
+}
+
+char *
+demangle_symbol (mangled)
+     const char *mangled;
+{
+  return demangle_symbol_with_options (mangled, demangler_options);
+}
+
+char *
+demangle_symbol_with_options (mangled, options)
+     const char *mangled;
+     int options;
+{
+  if (demangler_function)
+    return (*demangler_function) (mangled, options);
+  if (options & DMGL_GNAT)
+    return internal_ada_demangle (mangled, options);
+  else
+    return cplus_demangle (mangled, options);
+}
 
 /* This function performs most of what cplus_demangle use to do, but
    to be able to demangle a name with a B, K or n code, we need to
@@ -4356,6 +4522,8 @@ static int flags = DMGL_PARAMS | DMGL_AN
 static void demangle_it PARAMS ((char *));
 static void usage PARAMS ((FILE *, int)) ATTRIBUTE_NORETURN;
 static void fatal PARAMS ((const char *)) ATTRIBUTE_NORETURN;
+static const char * standard_symbol_characters PARAMS ((void));
+static const char * hp_symbol_characters PARAMS ((void));
 
 static void
 demangle_it (mangled_name)
@@ -4381,9 +4549,10 @@ usage (stream, status)
      int status;
 {
   fprintf (stream, "\
-Usage: %s [-_] [-n] [-s {gnu,lucid,arm,hp,edg}] [--strip-underscores]\n\
-       [--no-strip-underscores] [--format={gnu,lucid,arm,hp,edg}]\n\
-      [--help] [--version] [arg...]\n",
+Usage: %s [-_] [-n] [-s {gnu,lucid,arm,hp,edg,gnat,compaq}] [--strip-underscores]\n\
+       [--no-strip-underscores] [--format={gnu,lucid,arm,hp,edg,gnat,compaq}]\n\
+       [-d dso:function] [--demangler=dso:function]\n\
+       [--help] [--version] [arg...]\n",
 	   program_name);
   exit (status);
 }
@@ -4399,6 +4568,7 @@ int strip_underscore = 0;
 static struct option long_options[] = {
   {"strip-underscores", no_argument, 0, '_'},
   {"format", required_argument, 0, 's'},
+  {"demangler", required_argument, 0, 'd'},
   {"help", no_argument, 0, 'h'},
   {"java", no_argument, 0, 'j'},
   {"no-strip-underscores", no_argument, 0, 'n'},
@@ -4474,12 +4644,13 @@ main (argc, argv)
   char *result;
   int c;
   const char *valid_symbols;
+  const char *demangler = NULL;
 
   program_name = argv[0];
 
   strip_underscore = prepends_underscore;
 
-  while ((c = getopt_long (argc, argv, "_ns:j", long_options, (int *) 0)) != EOF)
+  while ((c = getopt_long (argc, argv, "_ns:jd:", long_options, (int *) 0)) != EOF)
     {
       switch (c)
 	{
@@ -4500,28 +4671,12 @@ main (argc, argv)
 	case 'j':
 	  flags |= DMGL_JAVA;
 	  break;
+	case 'd':
+  	  demangler = optarg;
+	  break;
 	case 's':
-	  if (strcmp (optarg, "gnu") == 0)
-	    {
-	      current_demangling_style = gnu_demangling;
-	    }
-	  else if (strcmp (optarg, "lucid") == 0)
-	    {
-	      current_demangling_style = lucid_demangling;
-	    }
-	  else if (strcmp (optarg, "arm") == 0)
-	    {
-	      current_demangling_style = arm_demangling;
-	    }
-	  else if (strcmp (optarg, "hp") == 0)
-	    {
-	      current_demangling_style = hp_demangling;
-	    }
-          else if (strcmp (optarg, "edg") == 0)
-            {
-              current_demangling_style = edg_demangling;
-            }
-	  else
+	  current_demangling_style = o_style (optarg);
+	  if (current_demangling_style == unknown_demangling)
 	    {
 	      fprintf (stderr, "%s: unknown demangling style `%s'\n",
 		       program_name, optarg);
@@ -4546,6 +4701,8 @@ main (argc, argv)
 	case lucid_demangling:
 	case arm_demangling:
 	case edg_demangling:
+	case gnat_demangling:
+	case compaq_demangling:
 	  valid_symbols = standard_symbol_characters ();
 	  break;
 	case hp_demangling:
@@ -4558,6 +4715,8 @@ main (argc, argv)
 	  abort ();
 	}
 
+      init_demangler (NULL, NULL, demangler);
+
       for (;;)
 	{
 	  int i = 0;
@@ -4635,3 +4794,140 @@ xrealloc (ptr, size)
   return value;
 }
 #endif	/* main */
+
+/* Assuming *OLD_VECT points to an array of *SIZE objects of size
+   ELEMENT_SIZE, grow it to contain at least MIN_SIZE objects,
+   updating *OLD_VECT and *SIZE as necessary. */
+static void
+DEFUN (grow_vect, (old_vect, size, min_size, element_size),
+       void** old_vect
+       AND size_t* size
+       AND size_t min_size
+       AND int element_size)
+{
+  if (*size < min_size) {
+    *size *= 2;
+    if (*size < min_size)
+      *size = min_size;
+    *old_vect = xrealloc (*old_vect, *size * element_size);
+  }
+}
+
+/* Demangle ada names:
+   1. Discard final __{DIGIT}+ or ${DIGIT}+
+   2. Convert other instances of embedded "__" to `.'.
+   3. Discard leading _ada_.
+   4. Remove everything after first ___ if it is followed by
+   'X'.
+   5. Put symbols that should be suppressed in <...> brackets.
+   The resulting string is valid until the next call of ada_demangle.
+*/
+static char *
+DEFUN (gnat_demangle, (mangled), const char* mangled)
+{
+  int i, j;
+  int len0;
+  const char* p;
+  char* demangled = NULL;
+  int at_start_name;
+  int changed;
+  char* demangling_buffer = NULL;
+  size_t demangling_buffer_size = 0;
+  
+  changed = 0;
+
+  if (strncmp (mangled, "_ada_", 5) == 0)
+    {
+      mangled += 5;
+      changed = 1;
+    }
+  
+  if (mangled[0] == '_' || mangled[0] == '<')
+    goto Suppress;
+  
+  p = strstr (mangled, "___");
+  if (p == NULL)
+    len0 = strlen (mangled);
+  else
+    {
+      if (p[3] == 'X')
+	{
+	  len0 = p - mangled;
+	  changed = 1;
+	}
+      else
+	goto Suppress;
+    }
+  
+  /* Make demangled big enough for possible expansion by operator name. */
+  grow_vect ((void**) &(demangling_buffer),
+	     &demangling_buffer_size,  2 * len0 + 1,
+	     sizeof (char));
+  demangled = demangling_buffer;
+  
+  if (isdigit (mangled[len0 - 1])) {
+    for (i = len0-2; i >= 0 && isdigit (mangled[i]); i -= 1)
+      ;
+    if (i > 1 && mangled[i] == '_' && mangled[i-1] == '_')
+      {
+	len0 = i - 1;
+	changed = 1;
+      }
+    else if (mangled[i] == '$')
+      {
+	len0 = i;
+	changed = 1;
+      }
+  }
+  
+  for (i = 0, j = 0; i < len0 && ! isalpha (mangled[i]); i += 1, j += 1)
+    demangled[j] = mangled[i];
+  
+  at_start_name = 1;
+  while (i < len0)
+    {
+      at_start_name = 0;
+      
+      if (i < len0-2 && mangled[i] == '_' && mangled[i+1] == '_')
+	{
+	  demangled[j] = '.';
+	  changed = at_start_name = 1;
+	  i += 2; j += 1;
+	}
+      else
+	{
+	  demangled[j] = mangled[i];
+	  i += 1;  j += 1;
+	}
+    }
+  demangled[j] = '\000';
+  
+  for (i = 0; demangled[i] != '\0'; i += 1)
+    if (isupper (demangled[i]) || demangled[i] == ' ')
+      goto Suppress;
+
+  if (! changed)
+    return NULL;
+  else
+    return demangled;
+  
+ Suppress:
+  grow_vect ((void**) &(demangling_buffer),
+	     &demangling_buffer_size,  strlen (mangled) + 3,
+	     sizeof (char));
+  demangled = demangling_buffer;
+  if (mangled[0] == '<')
+     strcpy (demangled, mangled);
+  else
+    sprintf (demangled, "<%s>", mangled);
+
+  return demangled;
+}
+
+static char *
+DEFUN (internal_ada_demangle, (mangled, option),
+       const char* mangled
+       AND int option ATTRIBUTE_UNUSED)
+{
+  return gnat_demangle (mangled);
+}
--- ../../import/egcs/include/demangle.h	Sun Dec 13 22:55:06 1998
+++ include/demangle.h	Sat Oct  9 15:54:50 1999
@@ -36,6 +36,8 @@
 #define DMGL_HP 	(1 << 12)       /* For the HP aCC compiler; same as ARM
                                            except for template arguments, etc. */
 #define DMGL_EDG	(1 << 13)
+#define DMGL_GNAT	(1 << 14)
+#define DMGL_COMPAQ	(1 << 15)
 
 /* If none of these are set, use 'current_demangling_style' as the default. */
 #define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM|DMGL_HP|DMGL_EDG)
@@ -56,7 +58,9 @@ extern enum demangling_styles
   lucid_demangling = DMGL_LUCID,
   arm_demangling = DMGL_ARM,
   hp_demangling = DMGL_HP,
-  edg_demangling = DMGL_EDG
+  edg_demangling = DMGL_EDG,
+  gnat_demangling = DMGL_GNAT,
+  compaq_demangling = DMGL_COMPAQ
 } current_demangling_style;
 
 /* Define string names for the various demangling styles. */
@@ -67,6 +71,8 @@ extern enum demangling_styles
 #define ARM_DEMANGLING_STYLE_STRING	"arm"
 #define HP_DEMANGLING_STYLE_STRING	"hp"
 #define EDG_DEMANGLING_STYLE_STRING	"edg"
+#define GNAT_DEMANGLING_STYLE_STRING	"gnat"
+#define COMPAQ_DEMANGLING_STYLE_STRING	"compaq"
 
 /* Some macros to test what demangling style is active. */
 
@@ -91,5 +97,16 @@ cplus_mangle_opname PARAMS ((const char 
 
 extern void
 set_cplus_marker_for_demangling PARAMS ((int ch));
+
+extern char *
+demangle_symbol PARAMS ((const char *mangled));
+
+extern char *
+demangle_symbol_with_options PARAMS ((const char *mangled,
+				      int options));
+
+extern int
+init_demangler PARAMS ((const char *style, const char *options,
+			const char *demangler));
 
 #endif	/* DEMANGLE_H */


More information about the Gcc-patches mailing list