Patchwork Ping [Patch] Improve ada demangler

login
register
mail settings
Submitter Tristan Gingold
Date Sept. 22, 2010, 9:26 a.m.
Message ID <7173A6E0-1F50-4472-A6FF-7FEC05932A01@adacore.com>
Download mbox | patch
Permalink /patch/65413/
State New
Headers show

Comments

Tristan Gingold - Sept. 22, 2010, 9:26 a.m.
On Sep 21, 2010, at 4:30 PM, Ian Lance Taylor wrote:

> Tristan Gingold <gingold@adacore.com> writes:
> 
>>> libiberty:
>>> 2010-09-07  Tristan Gingold  <gingold@adacore.com>
>>> 
>>> 	* cplus-dem.c (ada_demangle): Add comments.
>>> 	Handle stream and controlled type operations.
>>> 	Decoding of some uppercase letters moved before separators.
>>> 	* testsuite/demangle-expected: Add tests.
> 
>>> +      if (p[0] == 'S' && p[1] && (p[2] == '_' || p[2] == 0))
> 
> Write p[1] != 0 or p[1] != '\0'.
> 
>>> +                      int l = strlen (special[k][0]);
> 
> l is kind of a poor choice of variable name in this code which is
> littered with 1's.  Consider len.  Also consider changing the type to
> size_t.
> 
>>> +                      if (!strncmp (p, special[k][0], l))
> 
> Write strncmp (p, special[k][0], l) != 0 rather than using ! (I know the
> existing code used !).
> 
>>> +                  if (special[k][0])
> 
> Write special[k][0] != 0 or special[k][0] != '\0'.
> 
> 
> This is OK with those changes.

Thank you for the review.  I have committed the following patch, after a make check in libiberty and a compiler build.

Tristan.

Patch

===================================================================
--- cplus-dem.c	(revision 164509)
+++ cplus-dem.c	(working copy)
@@ -895,18 +895,20 @@ 
 
   /* Most of the demangling will trivially remove chars.  Operator names
      may add one char but because they are always preceeded by '__' which is
-     replaced by '.', they eventually never expand the size.  '___elabs' and
-     '___elabb' add only 2 chars, but they occur only once.  */
-  len0 = strlen (mangled) + 2 + 1;
+     replaced by '.', they eventually never expand the size.
+     A few special names such as '___elabs' add a few chars (at most 7), but
+     they occur only once.  */
+  len0 = strlen (mangled) + 7 + 1;
   demangled = XNEWVEC (char, len0);
   
   d = demangled;
   p = mangled;
   while (1)
     {
-      /* Convert name, which is always lower-case.  */
+      /* An entity names is expected.  */
       if (ISLOWER (*p))
         {
+          /* An identifier, which is always lower case.  */
           do
             *d++ = *p++;
           while (ISLOWER(*p) || ISDIGIT (*p)
@@ -914,6 +916,7 @@ 
         }
       else if (p[0] == 'O')
         {
+          /* An operator name.  */
           static const char * const operators[][2] =
             {{"Oabs", "abs"},  {"Oand", "and"},    {"Omod", "mod"},
              {"Onot", "not"},  {"Oor", "or"},      {"Orem", "rem"},
@@ -924,22 +927,22 @@ 
              {"Oexpon", "**"}, {NULL, NULL}};
           int k;
 
-          for (k = 0; operators[k][0]; k++)
+          for (k = 0; operators[k][0] != NULL; k++)
             {
-              int l = strlen (operators[k][0]);
-              if (!strncmp (p, operators[k][0], l))
+              size_t slen = strlen (operators[k][0]);
+              if (strncmp (p, operators[k][0], slen) == 0)
                 {
-                  p += l;
-                  l = strlen (operators[k][1]);
+                  p += slen;
+                  slen = strlen (operators[k][1]);
                   *d++ = '"';
-                  memcpy (d, operators[k][1], l);
-                  d += l;
+                  memcpy (d, operators[k][1], slen);
+                  d += slen;
                   *d++ = '"';
                   break;
                 }
             }
           /* Operator not found.  */
-          if (!operators[k][0])
+          if (operators[k][0] == NULL)
             goto unknown;
         }
       else
@@ -948,6 +951,92 @@ 
           goto unknown;
         }
 
+      /* The name can be directly followed by some uppercase letters.  */
+      if (p[0] == 'T' && p[1] == 'K')
+        {
+          /* Task stuff.  */
+          if (p[2] == 'B' && p[3] == 0)
+            {
+              /* Subprogram for task body.  */
+              break;
+            }
+          else if (p[2] == '_' && p[3] == '_')
+            {
+              /* Inner declarations in a task.  */
+              p += 4;
+              *d++ = '.';
+              continue;
+            }
+          else
+            goto unknown;
+        }
+      if (p[0] == 'E' && p[1] == 0)
+        {
+          /* Exception name.  */
+          goto unknown;
+        }
+      if ((p[0] == 'P' || p[0] == 'N') && p[1] == 0)
+        {
+          /* Protected type subprogram.  */
+          break;
+        }
+      if ((*p == 'N' || *p == 'S') && p[1] == 0)
+        {
+          /* Enumerated type name table.  */
+          goto unknown;
+        }
+      if (p[0] == 'X')
+        {
+          /* Body nested.  */
+          p++;
+          while (p[0] == 'n' || p[0] == 'b')
+            p++;
+        }
+      if (p[0] == 'S' && p[1] != 0 && (p[2] == '_' || p[2] == 0))
+        {
+          /* Stream operations.  */
+          const char *name;
+          switch (p[1])
+            {
+            case 'R':
+              name = "'Read";
+              break;
+            case 'W':
+              name = "'Write";
+              break;
+            case 'I':
+              name = "'Input";
+              break;
+            case 'O':
+              name = "'Output";
+              break;
+            default:
+              goto unknown;
+            }
+          p += 2;
+          strcpy (d, name);
+          d += strlen (name);
+        }
+      else if (p[0] == 'D')
+        {
+          /* Controlled type operation.  */
+          const char *name;
+          switch (p[1])
+            {
+            case 'F':
+              name = ".Finalize";
+              break;
+            case 'A':
+              name = ".Adjust";
+              break;
+            default:
+              goto unknown;
+            }
+          strcpy (d, name);
+          d += strlen (name);
+          break;
+        }
+
       if (p[0] == '_')
         {
           /* Separator.  */
@@ -955,25 +1044,50 @@ 
             {
               /* Standard separator.  Handled first.  */
               p += 2;
+
               if (ISDIGIT (*p))
                 {
-                  /* Overloading.  */
+                  /* Overloading number.  */
                   do
                     p++;
                   while (ISDIGIT (*p) || (p[0] == '_' && ISDIGIT (p[1])));
+                  if (*p == 'X')
+                    {
+                      p++;
+                      while (p[0] == 'n' || p[0] == 'b')
+                        p++;
+                    }
                 }
-              else if (*p == '_' && !strcmp (p + 1, "elabb"))
+              else if (p[0] == '_' && p[1] != '_')
                 {
-                  memcpy (d, "'Elab_Body", 10);
-                  d += 10;
-                  break;
+                  /* Special names.  */
+                  static const char * const special[][2] = {
+                    { "_elabb", "'Elab_Body" },
+                    { "_elabs", "'Elab_Spec" },
+                    { "_size", "'Size" },
+                    { "_alignment", "'Alignment" },
+                    { "_assign", ".\":=\"" },
+                    { NULL, NULL }
+                  };
+                  int k;
+
+                  for (k = 0; special[k][0] != NULL; k++)
+                    {
+                      size_t slen = strlen (special[k][0]);
+                      if (strncmp (p, special[k][0], slen) == 0)
+                        {
+                          p += slen;
+                          slen = strlen (special[k][1]);
+                          memcpy (d, special[k][1], slen);
+                          d += slen;
+                          break;
+                        }
+                    }
+                  if (special[k][0] != NULL)
+                    break;
+                  else
+                    goto unknown;
                 }
-              else if (*p == '_' && !strcmp (p + 1, "elabs"))
-                {
-                  memcpy (d, "'Elab_Spec", 10);
-                  d += 10;
-                  break;
-                }
               else
                 {
                   *d++ = '.';
@@ -995,46 +1109,6 @@ 
             goto unknown;
         }
 
-      if (p[0] == 'T' && p[1] == 'K')
-        {
-          if (p[2] == 'B' && p[3] == 0)
-            {
-              /* Subprogram for task body.  */
-              break;
-            }
-          else if (p[2] == '_' && p[3] == '_')
-            {
-              /* Inner declarations in a task.  */
-              p += 4;
-              *d++ = '.';
-              continue;
-            }
-          else
-            goto unknown;
-        }
-      if ((p[0] == 'P' || p[0] == 'N') && p[1] == 0)
-        {
-          /* Protected type subprogram.  */
-          break;
-        }
-      if (p[0] == 'E' && p[1] == 0)
-        {
-          /* Exception name.  */
-          goto unknown;
-        }
-      if (*p == 'N' || *p == 'S')
-        {
-          /* Enumerated type name table.  */
-          goto unknown;
-        }
-      if (p[0] == 'X')
-        {
-          /* Body nested.  */
-          if (p[1] == 'n' || p[1] == 'b')
-            p += 2;
-          else if (p[1] == 0)
-            p++;
-        }
       if (p[0] == '.' && ISDIGIT (p[1]))
         {
           /* Nested subprogram.  */