Back to index

cell-binutils  2.17cvs20070401
test-demangle.c
Go to the documentation of this file.
00001 /* Demangler test program,
00002    Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
00003    Written by Zack Weinberg <zack@codesourcery.com
00004 
00005    This file is part of GNU libiberty.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 
00020 */
00021 
00022 #ifdef HAVE_CONFIG_H
00023 #include "config.h"
00024 #endif
00025 #include "ansidecl.h"
00026 #include <stdio.h>
00027 #include "libiberty.h"
00028 #include "demangle.h"
00029 #ifdef HAVE_STRING_H
00030 #include <string.h>
00031 #endif
00032 #if HAVE_STDLIB_H
00033 # include <stdlib.h>
00034 #endif
00035 
00036 struct line
00037 {
00038   size_t alloced;
00039   char *data;
00040 };
00041 
00042 static unsigned int lineno;
00043 
00044 /* Safely read a single line of arbitrary length from standard input.  */
00045 
00046 #define LINELEN 80
00047 
00048 static void
00049 getline(buf)
00050      struct line *buf;
00051 {
00052   char *data = buf->data;
00053   size_t alloc = buf->alloced;
00054   size_t count = 0;
00055   int c;
00056 
00057   if (data == 0)
00058     {
00059       data = xmalloc (LINELEN);
00060       alloc = LINELEN;
00061     }
00062 
00063   /* Skip comment lines.  */
00064   while ((c = getchar()) == '#')
00065     {
00066       while ((c = getchar()) != EOF && c != '\n');
00067       lineno++;
00068     }
00069 
00070   /* c is the first character on the line, and it's not a comment
00071      line: copy this line into the buffer and return.  */
00072   while (c != EOF && c != '\n')
00073     {
00074       if (count + 1 >= alloc)
00075        {
00076          alloc *= 2;
00077          data = xrealloc (data, alloc);
00078        }
00079       data[count++] = c;
00080       c = getchar();
00081     }
00082   lineno++;
00083   data[count] = '\0';
00084 
00085   buf->data = data;
00086   buf->alloced = alloc;
00087 }
00088 
00089 /* If we have mmap() and mprotect(), copy the string S just before a
00090    protected page, so that if the demangler runs over the end of the
00091    string we'll get a fault, and return the address of the new string.
00092    If no mmap, or it fails, or it looks too hard, just return S.  */
00093 
00094 #ifdef HAVE_SYS_MMAN_H
00095 #include <sys/mman.h>
00096 #endif
00097 #if defined(MAP_ANON) && ! defined (MAP_ANONYMOUS)
00098 #define MAP_ANONYMOUS MAP_ANON
00099 #endif
00100 
00101 static const char *
00102 protect_end (const char * s)
00103 {
00104 #if defined(HAVE_MMAP) && defined (MAP_ANONYMOUS)
00105   size_t pagesize = getpagesize();
00106   static char * buf;
00107   size_t s_len = strlen (s);
00108   char * result;
00109   
00110   /* Don't try if S is too long.  */
00111   if (s_len >= pagesize)
00112     return s;
00113 
00114   /* Allocate one page of allocated space followed by an unmapped
00115      page.  */
00116   if (buf == NULL)
00117     {
00118       buf = mmap (NULL, pagesize * 2, PROT_READ | PROT_WRITE,
00119                 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
00120       if (! buf)
00121        return s;
00122       munmap (buf + pagesize, pagesize);
00123     }
00124   
00125   result = buf + (pagesize - s_len - 1);
00126   memcpy (result, s, s_len + 1);
00127   return result;
00128 #else
00129   return s;
00130 #endif
00131 }
00132 
00133 static void
00134 fail (lineno, opts, in, out, exp)
00135      int lineno;
00136      const char *opts;
00137      const char *in;
00138      const char *out;
00139      const char *exp;
00140 {
00141   printf ("\
00142 FAIL at line %d, options %s:\n\
00143 in:  %s\n\
00144 out: %s\n\
00145 exp: %s\n",
00146          lineno, opts, in, out != NULL ? out : "(null)", exp);
00147 }
00148 
00149 /* The tester operates on a data file consisting of groups of lines:
00150    options
00151    input to be demangled
00152    expected output
00153 
00154    Supported options:
00155      --format=<name>     Sets the demangling style.
00156      --no-params         There are two lines of expected output; the first
00157                          is with DMGL_PARAMS, the second is without it.
00158      --is-v3-ctor        Calls is_gnu_v3_mangled_ctor on input; expected
00159                          output is an integer representing ctor_kind.
00160      --is-v3-dtor        Likewise, but for dtors.
00161      --ret-postfix       Passes the DMGL_RET_POSTFIX option
00162 
00163    For compatibility, just in case it matters, the options line may be
00164    empty, to mean --format=auto.  If it doesn't start with --, then it
00165    may contain only a format name.
00166 */
00167 
00168 int
00169 main(argc, argv)
00170      int argc;
00171      char **argv;
00172 {
00173   enum demangling_styles style = auto_demangling;
00174   int no_params;
00175   int is_v3_ctor;
00176   int is_v3_dtor;
00177   int ret_postfix;
00178   struct line format;
00179   struct line input;
00180   struct line expect;
00181   char *result;
00182   int failures = 0;
00183   int tests = 0;
00184 
00185   if (argc > 1)
00186     {
00187       fprintf (stderr, "usage: %s < test-set\n", argv[0]);
00188       return 2;
00189     }
00190 
00191   format.data = 0;
00192   input.data = 0;
00193   expect.data = 0;
00194 
00195   for (;;)
00196     {
00197       const char *inp;
00198       
00199       getline (&format);
00200       if (feof (stdin))
00201        break;
00202 
00203       getline (&input);
00204       getline (&expect);
00205 
00206       inp = protect_end (input.data);
00207 
00208       tests++;
00209 
00210       no_params = 0;
00211       ret_postfix = 0;
00212       is_v3_ctor = 0;
00213       is_v3_dtor = 0;
00214       if (format.data[0] == '\0')
00215        style = auto_demangling;
00216       else if (format.data[0] != '-')
00217        {
00218          style = cplus_demangle_name_to_style (format.data);
00219          if (style == unknown_demangling)
00220            {
00221              printf ("FAIL at line %d: unknown demangling style %s\n",
00222                     lineno, format.data);
00223              failures++;
00224              continue;
00225            }
00226        }
00227       else
00228        {
00229          char *p;
00230          char *opt;
00231 
00232          p = format.data;
00233          while (*p != '\0')
00234            {
00235              char c;
00236 
00237              opt = p;
00238              p += strcspn (p, " \t=");
00239              c = *p;
00240              *p = '\0';
00241              if (strcmp (opt, "--format") == 0 && c == '=')
00242               {
00243                 char *fstyle;
00244 
00245                 *p = c;
00246                 ++p;
00247                 fstyle = p;
00248                 p += strcspn (p, " \t");
00249                 c = *p;
00250                 *p = '\0';
00251                 style = cplus_demangle_name_to_style (fstyle);
00252                 if (style == unknown_demangling)
00253                   {
00254                     printf ("FAIL at line %d: unknown demangling style %s\n",
00255                            lineno, fstyle);
00256                     failures++;
00257                     continue;
00258                   }
00259               }
00260              else if (strcmp (opt, "--no-params") == 0)
00261               no_params = 1;
00262              else if (strcmp (opt, "--is-v3-ctor") == 0)
00263               is_v3_ctor = 1;
00264              else if (strcmp (opt, "--is-v3-dtor") == 0)
00265               is_v3_dtor = 1;
00266              else if (strcmp (opt, "--ret-postfix") == 0)
00267               ret_postfix = 1;
00268              else
00269               {
00270                 printf ("FAIL at line %d: unrecognized option %s\n",
00271                        lineno, opt);
00272                 failures++;
00273                 continue;
00274               }
00275              *p = c;
00276              p += strspn (p, " \t");
00277            }
00278        }
00279 
00280       if (is_v3_ctor || is_v3_dtor)
00281        {
00282          char buf[20];
00283 
00284          if (is_v3_ctor)
00285            {
00286              enum gnu_v3_ctor_kinds kc;
00287 
00288              kc = is_gnu_v3_mangled_ctor (inp);
00289              sprintf (buf, "%d", (int) kc);
00290            }
00291          else
00292            {
00293              enum gnu_v3_dtor_kinds kd;
00294 
00295              kd = is_gnu_v3_mangled_dtor (inp);
00296              sprintf (buf, "%d", (int) kd);
00297            }
00298 
00299          if (strcmp (buf, expect.data) != 0)
00300            {
00301              fail (lineno, format.data, input.data, buf, expect.data);
00302              failures++;
00303            }
00304 
00305          continue;
00306        }
00307 
00308       cplus_demangle_set_style (style);
00309 
00310       result = cplus_demangle (inp,
00311                             DMGL_PARAMS|DMGL_ANSI|DMGL_TYPES
00312                             |(ret_postfix ? DMGL_RET_POSTFIX : 0));
00313 
00314       if (result
00315          ? strcmp (result, expect.data)
00316          : strcmp (input.data, expect.data))
00317        {
00318          fail (lineno, format.data, input.data, result, expect.data);
00319          failures++;
00320        }
00321       free (result);
00322 
00323       if (no_params)
00324        {
00325          getline (&expect);
00326          result = cplus_demangle (inp, DMGL_ANSI|DMGL_TYPES);
00327 
00328          if (result
00329              ? strcmp (result, expect.data)
00330              : strcmp (input.data, expect.data))
00331            {
00332              fail (lineno, format.data, input.data, result, expect.data);
00333              failures++;
00334            }
00335          free (result);
00336        }
00337     }
00338 
00339   free (format.data);
00340   free (input.data);
00341   free (expect.data);
00342 
00343   printf ("%s: %d tests, %d failures\n", argv[0], tests, failures);
00344   return failures ? 1 : 0;
00345 }