test-demangle.c revision 169695
1/* Demangler test program,
2   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
3   Written by Zack Weinberg <zack@codesourcery.com
4
5   This file is part of GNU libiberty.
6
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 2 of the License, or
10   (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program; if not, write to the Free Software
19   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20*/
21
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
25#include "ansidecl.h"
26#include <stdio.h>
27#include "libiberty.h"
28#include "demangle.h"
29#ifdef HAVE_STRING_H
30#include <string.h>
31#endif
32#if HAVE_STDLIB_H
33# include <stdlib.h>
34#endif
35
36struct line
37{
38  size_t alloced;
39  char *data;
40};
41
42static unsigned int lineno;
43
44/* Safely read a single line of arbitrary length from standard input.  */
45
46#define LINELEN 80
47
48static void
49getline(buf)
50     struct line *buf;
51{
52  char *data = buf->data;
53  size_t alloc = buf->alloced;
54  size_t count = 0;
55  int c;
56
57  if (data == 0)
58    {
59      data = xmalloc (LINELEN);
60      alloc = LINELEN;
61    }
62
63  /* Skip comment lines.  */
64  while ((c = getchar()) == '#')
65    {
66      while ((c = getchar()) != EOF && c != '\n');
67      lineno++;
68    }
69
70  /* c is the first character on the line, and it's not a comment
71     line: copy this line into the buffer and return.  */
72  while (c != EOF && c != '\n')
73    {
74      if (count + 1 >= alloc)
75	{
76	  alloc *= 2;
77	  data = xrealloc (data, alloc);
78	}
79      data[count++] = c;
80      c = getchar();
81    }
82  lineno++;
83  data[count] = '\0';
84
85  buf->data = data;
86  buf->alloced = alloc;
87}
88
89static void
90fail (lineno, opts, in, out, exp)
91     int lineno;
92     const char *opts;
93     const char *in;
94     const char *out;
95     const char *exp;
96{
97  printf ("\
98FAIL at line %d, options %s:\n\
99in:  %s\n\
100out: %s\n\
101exp: %s\n",
102	  lineno, opts, in, out != NULL ? out : "(null)", exp);
103}
104
105/* The tester operates on a data file consisting of groups of lines:
106   options
107   input to be demangled
108   expected output
109
110   Supported options:
111     --format=<name>     Sets the demangling style.
112     --no-params         There are two lines of expected output; the first
113                         is with DMGL_PARAMS, the second is without it.
114     --is-v3-ctor        Calls is_gnu_v3_mangled_ctor on input; expected
115                         output is an integer representing ctor_kind.
116     --is-v3-dtor        Likewise, but for dtors.
117     --ret-postfix       Passes the DMGL_RET_POSTFIX option
118
119   For compatibility, just in case it matters, the options line may be
120   empty, to mean --format=auto.  If it doesn't start with --, then it
121   may contain only a format name.
122*/
123
124int
125main(argc, argv)
126     int argc;
127     char **argv;
128{
129  enum demangling_styles style = auto_demangling;
130  int no_params;
131  int is_v3_ctor;
132  int is_v3_dtor;
133  int ret_postfix;
134  struct line format;
135  struct line input;
136  struct line expect;
137  char *result;
138  int failures = 0;
139  int tests = 0;
140
141  if (argc > 1)
142    {
143      fprintf (stderr, "usage: %s < test-set\n", argv[0]);
144      return 2;
145    }
146
147  format.data = 0;
148  input.data = 0;
149  expect.data = 0;
150
151  for (;;)
152    {
153      getline (&format);
154      if (feof (stdin))
155	break;
156
157      getline (&input);
158      getline (&expect);
159
160      tests++;
161
162      no_params = 0;
163      ret_postfix = 0;
164      is_v3_ctor = 0;
165      is_v3_dtor = 0;
166      if (format.data[0] == '\0')
167	style = auto_demangling;
168      else if (format.data[0] != '-')
169	{
170	  style = cplus_demangle_name_to_style (format.data);
171	  if (style == unknown_demangling)
172	    {
173	      printf ("FAIL at line %d: unknown demangling style %s\n",
174		      lineno, format.data);
175	      failures++;
176	      continue;
177	    }
178	}
179      else
180	{
181	  char *p;
182	  char *opt;
183
184	  p = format.data;
185	  while (*p != '\0')
186	    {
187	      char c;
188
189	      opt = p;
190	      p += strcspn (p, " \t=");
191	      c = *p;
192	      *p = '\0';
193	      if (strcmp (opt, "--format") == 0 && c == '=')
194		{
195		  char *fstyle;
196
197		  *p = c;
198		  ++p;
199		  fstyle = p;
200		  p += strcspn (p, " \t");
201		  c = *p;
202		  *p = '\0';
203		  style = cplus_demangle_name_to_style (fstyle);
204		  if (style == unknown_demangling)
205		    {
206		      printf ("FAIL at line %d: unknown demangling style %s\n",
207			      lineno, fstyle);
208		      failures++;
209		      continue;
210		    }
211		}
212	      else if (strcmp (opt, "--no-params") == 0)
213		no_params = 1;
214	      else if (strcmp (opt, "--is-v3-ctor") == 0)
215		is_v3_ctor = 1;
216	      else if (strcmp (opt, "--is-v3-dtor") == 0)
217		is_v3_dtor = 1;
218	      else if (strcmp (opt, "--ret-postfix") == 0)
219		ret_postfix = 1;
220	      else
221		{
222		  printf ("FAIL at line %d: unrecognized option %s\n",
223			  lineno, opt);
224		  failures++;
225		  continue;
226		}
227	      *p = c;
228	      p += strspn (p, " \t");
229	    }
230	}
231
232      if (is_v3_ctor || is_v3_dtor)
233	{
234	  char buf[20];
235
236	  if (is_v3_ctor)
237	    {
238	      enum gnu_v3_ctor_kinds kc;
239
240	      kc = is_gnu_v3_mangled_ctor (input.data);
241	      sprintf (buf, "%d", (int) kc);
242	    }
243	  else
244	    {
245	      enum gnu_v3_dtor_kinds kd;
246
247	      kd = is_gnu_v3_mangled_dtor (input.data);
248	      sprintf (buf, "%d", (int) kd);
249	    }
250
251	  if (strcmp (buf, expect.data) != 0)
252	    {
253	      fail (lineno, format.data, input.data, buf, expect.data);
254	      failures++;
255	    }
256
257	  continue;
258	}
259
260      cplus_demangle_set_style (style);
261
262      result = cplus_demangle (input.data,
263			       DMGL_PARAMS|DMGL_ANSI|DMGL_TYPES
264			       |(ret_postfix ? DMGL_RET_POSTFIX : 0));
265
266      if (result
267	  ? strcmp (result, expect.data)
268	  : strcmp (input.data, expect.data))
269	{
270	  fail (lineno, format.data, input.data, result, expect.data);
271	  failures++;
272	}
273      free (result);
274
275      if (no_params)
276	{
277	  getline (&expect);
278	  result = cplus_demangle (input.data, DMGL_ANSI|DMGL_TYPES);
279
280	  if (result
281	      ? strcmp (result, expect.data)
282	      : strcmp (input.data, expect.data))
283	    {
284	      fail (lineno, format.data, input.data, result, expect.data);
285	      failures++;
286	    }
287	  free (result);
288	}
289    }
290
291  free (format.data);
292  free (input.data);
293  free (expect.data);
294
295  printf ("%s: %d tests, %d failures\n", argv[0], tests, failures);
296  return failures ? 1 : 0;
297}
298