This is the mail archive of the binutils@sourceware.cygnus.com mailing list for the binutils project.


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

[PATCH]Add gnat demangler


The following code is taken from H.J. Lu's version of binutils. It
implements a demangler for the GNAT Ada compiler. The author of this
code is unknown. I've asked Doug Rupp of GNAT if he knew who wrote the
code and he said it looked familar, but did not know. Can this code be
added without knowing the author?

This patch assumes that the JAVA patch has already been applied.


2000-06-20  Kenneth Block  <krblock@computer.org>

	* include/demangle.h: Add GNAT demangler.
	* libiberty/cplus-dem.c: Add GNAT demangler.

*** include/demangle.h.java	Tue Jun 20 17:07:54 2000
--- include/demangle.h	Tue Jun 20 17:16:48 2000
***************
*** 38,46 ****
                                              template arguments, etc. */
  #define DMGL_EDG	 (1 << 13)
  #define DMGL_GNU_NEW_ABI (1 << 14)
  
  /* 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|DMGL_GNU_NEW_ABI|DMGL_JAVA)
  
  /* Enumeration of possible demangling styles.
  
--- 38,47 ----
                                              template arguments, etc. */
  #define DMGL_EDG	 (1 << 13)
  #define DMGL_GNU_NEW_ABI (1 << 14)
+ #define DMGL_GNAT        (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|DMGL_GNU_NEW_ABI|DMGL_JAVA|DMGL_GNAT)
  
  /* Enumeration of possible demangling styles.
  
***************
*** 60,66 ****
    hp_demangling = DMGL_HP,
    edg_demangling = DMGL_EDG,
    gnu_new_abi_demangling = DMGL_GNU_NEW_ABI,
!   java_demangling = DMGL_JAVA
  } current_demangling_style;
  
  /* Define string names for the various demangling styles. */
--- 61,68 ----
    hp_demangling = DMGL_HP,
    edg_demangling = DMGL_EDG,
    gnu_new_abi_demangling = DMGL_GNU_NEW_ABI,
!   java_demangling = DMGL_JAVA,
!   gnat_demangling = DMGL_GNAT
  } current_demangling_style;
  
  /* Define string names for the various demangling styles. */
***************
*** 73,78 ****
--- 75,81 ----
  #define EDG_DEMANGLING_STYLE_STRING	      "edg"
  #define GNU_NEW_ABI_DEMANGLING_STYLE_STRING   "gnu-new-abi"
  #define JAVA_DEMANGLING_STYLE_STRING          "java"
+ #define GNAT_DEMANGLING_STYLE_STRING          "gnat"
  
  /* Some macros to test what demangling style is active. */
  
***************
*** 85,90 ****
--- 88,94 ----
  #define EDG_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_EDG)
  #define GNU_NEW_ABI_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU_NEW_ABI)
  #define JAVA_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_JAVA)
+ #define GNAT_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNAT)
  
  /* Provide information about the available demangle styles. This code is
     pulled from gdb into libiberty because it is useful to binutils also.  */
*** libiberty/cplus-dem.c.java	Tue Jun 20 17:08:08 2000
--- libiberty/cplus-dem.c	Tue Jun 20 17:27:43 2000
***************
*** 51,56 ****
--- 51,58 ----
  
  #include "libiberty.h"
  
+ static char *ada_demangle  PARAMS ((const char*, int));
+ 
  #define min(X,Y) (((X) < (Y)) ? (X) : (Y))
  
  /* A value at least one greater than the maximum number of characters
***************
*** 303,308 ****
--- 305,316 ----
    }
    ,
    {
+     GNAT_DEMANGLING_STYLE_STRING,
+     gnat_demangling,
+     "GNAT style demangling"
+   }
+   ,
+   {
      NULL, unknown_demangling, NULL
    }
  };
***************
*** 892,902 ****
--- 900,1045 ----
    if (GNU_NEW_ABI_DEMANGLING)
      return cplus_demangle_new_abi (mangled);
  
+   if (GNAT_DEMANGLING)
+     return ada_demangle(mangled,options);
+ 
    ret = internal_cplus_demangle (work, mangled);
    squangle_mop_up (work);
    return (ret);
  }
  
+ 
+ /* 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
+ grow_vect (old_vect, size, min_size, element_size)
+      void** old_vect;
+      size_t* size;
+      size_t min_size;
+      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 *
+ ada_demangle (mangled, opt)
+      const char* mangled;
+      int opt;
+ {
+   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;
+ }
  
  /* 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

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