Add ELFv2 .localentry support.
[deliverable/binutils-gdb.git] / libiberty / testsuite / test-demangle.c
index 6e5d0b4b9731b160b0efe85d522b2ffa2b4ba230..11d9729999b80259cb82189012d08bd449e58f5f 100644 (file)
@@ -1,5 +1,5 @@
 /* Demangler test program,
-   Copyright (C) 2002 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
    Written by Zack Weinberg <zack@codesourcery.com
 
    This file is part of GNU libiberty.
@@ -16,7 +16,7 @@
 
    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. 
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 
 */
 
 #ifdef HAVE_CONFIG_H
 #include <stdio.h>
 #include "libiberty.h"
 #include "demangle.h"
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
 
 struct line
 {
@@ -40,7 +46,7 @@ static unsigned int lineno;
 #define LINELEN 80
 
 static void
-getline(buf)
+get_line(buf)
      struct line *buf;
 {
   char *data = buf->data;
@@ -80,27 +86,99 @@ getline(buf)
   buf->alloced = alloc;
 }
 
-/* The tester operates on a data file consisting of triples of lines:
-   format switch
+/* If we have mmap() and mprotect(), copy the string S just before a
+   protected page, so that if the demangler runs over the end of the
+   string we'll get a fault, and return the address of the new string.
+   If no mmap, or it fails, or it looks too hard, just return S.  */
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#if defined(MAP_ANON) && ! defined (MAP_ANONYMOUS)
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+static const char *
+protect_end (const char * s)
+{
+#if defined(HAVE_MMAP) && defined (MAP_ANONYMOUS)
+  size_t pagesize = getpagesize();
+  static char * buf;
+  size_t s_len = strlen (s);
+  char * result;
+  
+  /* Don't try if S is too long.  */
+  if (s_len >= pagesize)
+    return s;
+
+  /* Allocate one page of allocated space followed by an unmapped
+     page.  */
+  if (buf == NULL)
+    {
+      buf = mmap (NULL, pagesize * 2, PROT_READ | PROT_WRITE,
+                 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+      if (! buf)
+       return s;
+      munmap (buf + pagesize, pagesize);
+    }
+  
+  result = buf + (pagesize - s_len - 1);
+  memcpy (result, s, s_len + 1);
+  return result;
+#else
+  return s;
+#endif
+}
+
+static void
+fail (lineno, opts, in, out, exp)
+     int lineno;
+     const char *opts;
+     const char *in;
+     const char *out;
+     const char *exp;
+{
+  printf ("\
+FAIL at line %d, options %s:\n\
+in:  %s\n\
+out: %s\n\
+exp: %s\n",
+         lineno, opts, in, out != NULL ? out : "(null)", exp);
+}
+
+/* The tester operates on a data file consisting of groups of lines:
+   options
    input to be demangled
    expected output
 
-   The format switch is expected to be either the empty string, a
-   line of the form --format=<name>, or just <name> by itself.  */
+   Supported options:
+     --format=<name>     Sets the demangling style.
+     --no-params         There are two lines of expected output; the first
+                         is with DMGL_PARAMS, the second is without it.
+     --is-v3-ctor        Calls is_gnu_v3_mangled_ctor on input; expected
+                         output is an integer representing ctor_kind.
+     --is-v3-dtor        Likewise, but for dtors.
+     --ret-postfix       Passes the DMGL_RET_POSTFIX option
+     --ret-drop          Passes the DMGL_RET_DROP option
 
-#define FORMATS "--format="
-#define FORMATL (sizeof FORMATS - 1)
+   For compatibility, just in case it matters, the options line may be
+   empty, to mean --format=auto.  If it doesn't start with --, then it
+   may contain only a format name.
+*/
 
 int
 main(argc, argv)
      int argc;
      char **argv;
 {
-  enum demangling_styles style;
+  enum demangling_styles style = auto_demangling;
+  int no_params;
+  int is_v3_ctor;
+  int is_v3_dtor;
+  int ret_postfix, ret_drop;
   struct line format;
   struct line input;
   struct line expect;
-  char *fstyle;
   char *result;
   int failures = 0;
   int tests = 0;
@@ -117,53 +195,149 @@ main(argc, argv)
 
   for (;;)
     {
-      getline (&format);
+      const char *inp;
+      
+      get_line (&format);
       if (feof (stdin))
        break;
 
-      getline (&input);
-      getline (&expect);
+      get_line (&input);
+      get_line (&expect);
 
-      tests++;
+      inp = protect_end (input.data);
 
-      fstyle = format.data;
-      if (!strncmp (fstyle, FORMATS, FORMATL))
-       fstyle += FORMATL;
+      tests++;
 
-      if (fstyle[0] == '\0')
+      no_params = 0;
+      ret_postfix = 0;
+      ret_drop = 0;
+      is_v3_ctor = 0;
+      is_v3_dtor = 0;
+      if (format.data[0] == '\0')
        style = auto_demangling;
+      else if (format.data[0] != '-')
+       {
+         style = cplus_demangle_name_to_style (format.data);
+         if (style == unknown_demangling)
+           {
+             printf ("FAIL at line %d: unknown demangling style %s\n",
+                     lineno, format.data);
+             failures++;
+             continue;
+           }
+       }
       else
-       style = cplus_demangle_name_to_style (fstyle);
+       {
+         char *p;
+         char *opt;
+
+         p = format.data;
+         while (*p != '\0')
+           {
+             char c;
+
+             opt = p;
+             p += strcspn (p, " \t=");
+             c = *p;
+             *p = '\0';
+             if (strcmp (opt, "--format") == 0 && c == '=')
+               {
+                 char *fstyle;
 
-      if (style == unknown_demangling)
+                 *p = c;
+                 ++p;
+                 fstyle = p;
+                 p += strcspn (p, " \t");
+                 c = *p;
+                 *p = '\0';
+                 style = cplus_demangle_name_to_style (fstyle);
+                 if (style == unknown_demangling)
+                   {
+                     printf ("FAIL at line %d: unknown demangling style %s\n",
+                             lineno, fstyle);
+                     failures++;
+                     continue;
+                   }
+               }
+             else if (strcmp (opt, "--no-params") == 0)
+               no_params = 1;
+             else if (strcmp (opt, "--is-v3-ctor") == 0)
+               is_v3_ctor = 1;
+             else if (strcmp (opt, "--is-v3-dtor") == 0)
+               is_v3_dtor = 1;
+             else if (strcmp (opt, "--ret-postfix") == 0)
+               ret_postfix = 1;
+             else if (strcmp (opt, "--ret-drop") == 0)
+               ret_drop = 1;
+             else
+               {
+                 printf ("FAIL at line %d: unrecognized option %s\n",
+                         lineno, opt);
+                 failures++;
+                 continue;
+               }
+             *p = c;
+             p += strspn (p, " \t");
+           }
+       }
+
+      if (is_v3_ctor || is_v3_dtor)
        {
-         printf ("FAIL at line %d: unknown demangling style %s\n",
-                 lineno, fstyle);
-         failures++;
+         char buf[20];
+
+         if (is_v3_ctor)
+           {
+             enum gnu_v3_ctor_kinds kc;
+
+             kc = is_gnu_v3_mangled_ctor (inp);
+             sprintf (buf, "%d", (int) kc);
+           }
+         else
+           {
+             enum gnu_v3_dtor_kinds kd;
+
+             kd = is_gnu_v3_mangled_dtor (inp);
+             sprintf (buf, "%d", (int) kd);
+           }
+
+         if (strcmp (buf, expect.data) != 0)
+           {
+             fail (lineno, format.data, input.data, buf, expect.data);
+             failures++;
+           }
+
          continue;
        }
 
       cplus_demangle_set_style (style);
 
-      result = cplus_demangle (input.data,
-                              DMGL_PARAMS|DMGL_ANSI|DMGL_VERBOSE|DMGL_TYPES);
+      result = cplus_demangle (inp, (DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES
+                                    | (ret_postfix ? DMGL_RET_POSTFIX : 0)
+                                    | (ret_drop ? DMGL_RET_DROP : 0)));
 
       if (result
          ? strcmp (result, expect.data)
          : strcmp (input.data, expect.data))
        {
-         printf ("\
-FAIL at line %d, style %s:\n\
-in:  %s\n\
-out: %s\n\
-exp: %s\n",
-                  lineno, fstyle,
-                  input.data,
-                  result,
-                  expect.data);
+         fail (lineno, format.data, input.data, result, expect.data);
          failures++;
        }
       free (result);
+
+      if (no_params)
+       {
+         get_line (&expect);
+         result = cplus_demangle (inp, DMGL_ANSI|DMGL_TYPES);
+
+         if (result
+             ? strcmp (result, expect.data)
+             : strcmp (input.data, expect.data))
+           {
+             fail (lineno, format.data, input.data, result, expect.data);
+             failures++;
+           }
+         free (result);
+       }
     }
 
   free (format.data);
This page took 0.027211 seconds and 4 git commands to generate.