1130561Sobrien/* Demangler for g++ V3 ABI.
2218822Sdim   Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
3130561Sobrien   Written by Ian Lance Taylor <ian@wasabisystems.com>.
468765Sobrien
5130561Sobrien   This file is part of the libiberty library, which is part of GCC.
677298Sobrien
7130561Sobrien   This file is free software; you can redistribute it and/or modify
868765Sobrien   it under the terms of the GNU General Public License as published by
968765Sobrien   the Free Software Foundation; either version 2 of the License, or
1068765Sobrien   (at your option) any later version.
1168765Sobrien
12104834Sobrien   In addition to the permissions in the GNU General Public License, the
13104834Sobrien   Free Software Foundation gives you unlimited permission to link the
14104834Sobrien   compiled version of this file into combinations with other programs,
15104834Sobrien   and to distribute those combinations without any restriction coming
16104834Sobrien   from the use of this file.  (The General Public License restrictions
17104834Sobrien   do apply in other respects; for example, they cover modification of
18104834Sobrien   the file, and distribution when not linked into a combined
19104834Sobrien   executable.)
20104834Sobrien
2168765Sobrien   This program is distributed in the hope that it will be useful,
2268765Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
2368765Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2468765Sobrien   GNU General Public License for more details.
2568765Sobrien
2668765Sobrien   You should have received a copy of the GNU General Public License
2768765Sobrien   along with this program; if not, write to the Free Software
28218822Sdim   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
2968765Sobrien*/
3068765Sobrien
31130561Sobrien/* This code implements a demangler for the g++ V3 ABI.  The ABI is
32130561Sobrien   described on this web page:
33130561Sobrien       http://www.codesourcery.com/cxx-abi/abi.html#mangling
3468765Sobrien
35130561Sobrien   This code was written while looking at the demangler written by
36130561Sobrien   Alex Samuel <samuel@codesourcery.com>.
37130561Sobrien
38130561Sobrien   This code first pulls the mangled name apart into a list of
39130561Sobrien   components, and then walks the list generating the demangled
40130561Sobrien   name.
41130561Sobrien
42130561Sobrien   This file will normally define the following functions, q.v.:
43130561Sobrien      char *cplus_demangle_v3(const char *mangled, int options)
44130561Sobrien      char *java_demangle_v3(const char *mangled)
45218822Sdim      int cplus_demangle_v3_callback(const char *mangled, int options,
46218822Sdim                                     demangle_callbackref callback)
47218822Sdim      int java_demangle_v3_callback(const char *mangled,
48218822Sdim                                    demangle_callbackref callback)
49130561Sobrien      enum gnu_v3_ctor_kinds is_gnu_v3_mangled_ctor (const char *name)
50130561Sobrien      enum gnu_v3_dtor_kinds is_gnu_v3_mangled_dtor (const char *name)
51130561Sobrien
52130561Sobrien   Also, the interface to the component list is public, and defined in
53130561Sobrien   demangle.h.  The interface consists of these types, which are
54130561Sobrien   defined in demangle.h:
55130561Sobrien      enum demangle_component_type
56130561Sobrien      struct demangle_component
57218822Sdim      demangle_callbackref
58130561Sobrien   and these functions defined in this file:
59130561Sobrien      cplus_demangle_fill_name
60130561Sobrien      cplus_demangle_fill_extended_operator
61130561Sobrien      cplus_demangle_fill_ctor
62130561Sobrien      cplus_demangle_fill_dtor
63130561Sobrien      cplus_demangle_print
64218822Sdim      cplus_demangle_print_callback
65130561Sobrien   and other functions defined in the file cp-demint.c.
66130561Sobrien
67130561Sobrien   This file also defines some other functions and variables which are
68130561Sobrien   only to be used by the file cp-demint.c.
69130561Sobrien
70130561Sobrien   Preprocessor macros you can define while compiling this file:
71130561Sobrien
72130561Sobrien   IN_LIBGCC2
73218822Sdim      If defined, this file defines the following functions, q.v.:
74130561Sobrien         char *__cxa_demangle (const char *mangled, char *buf, size_t *len,
75130561Sobrien                               int *status)
76218822Sdim         int __gcclibcxx_demangle_callback (const char *,
77218822Sdim                                            void (*)
78218822Sdim                                              (const char *, size_t, void *),
79218822Sdim                                            void *)
80218822Sdim      instead of cplus_demangle_v3[_callback]() and
81218822Sdim      java_demangle_v3[_callback]().
82130561Sobrien
83130561Sobrien   IN_GLIBCPP_V3
84218822Sdim      If defined, this file defines only __cxa_demangle() and
85218822Sdim      __gcclibcxx_demangle_callback(), and no other publically visible
86218822Sdim      functions or variables.
87130561Sobrien
88130561Sobrien   STANDALONE_DEMANGLER
89130561Sobrien      If defined, this file defines a main() function which demangles
90130561Sobrien      any arguments, or, if none, demangles stdin.
91130561Sobrien
92130561Sobrien   CP_DEMANGLE_DEBUG
93130561Sobrien      If defined, turns on debugging mode, which prints information on
94130561Sobrien      stdout about the mangled string.  This is not generally useful.
95130561Sobrien*/
96130561Sobrien
97218822Sdim#if defined (_AIX) && !defined (__GNUC__)
98218822Sdim #pragma alloca
99218822Sdim#endif
100218822Sdim
10168765Sobrien#ifdef HAVE_CONFIG_H
10268765Sobrien#include "config.h"
10368765Sobrien#endif
10468765Sobrien
105130561Sobrien#include <stdio.h>
10668765Sobrien
10768765Sobrien#ifdef HAVE_STDLIB_H
10868765Sobrien#include <stdlib.h>
10968765Sobrien#endif
11068765Sobrien#ifdef HAVE_STRING_H
11168765Sobrien#include <string.h>
11268765Sobrien#endif
11368765Sobrien
114218822Sdim#ifdef HAVE_ALLOCA_H
115218822Sdim# include <alloca.h>
116218822Sdim#else
117218822Sdim# ifndef alloca
118218822Sdim#  ifdef __GNUC__
119218822Sdim#   define alloca __builtin_alloca
120218822Sdim#  else
121218822Sdimextern char *alloca ();
122218822Sdim#  endif /* __GNUC__ */
123218822Sdim# endif /* alloca */
124218822Sdim#endif /* HAVE_ALLOCA_H */
125218822Sdim
12668765Sobrien#include "ansidecl.h"
12768765Sobrien#include "libiberty.h"
12868765Sobrien#include "demangle.h"
129130561Sobrien#include "cp-demangle.h"
13068765Sobrien
131130561Sobrien/* If IN_GLIBCPP_V3 is defined, some functions are made static.  We
132130561Sobrien   also rename them via #define to avoid compiler errors when the
133130561Sobrien   static definition conflicts with the extern declaration in a header
134130561Sobrien   file.  */
135130561Sobrien#ifdef IN_GLIBCPP_V3
136130561Sobrien
137130561Sobrien#define CP_STATIC_IF_GLIBCPP_V3 static
138130561Sobrien
139130561Sobrien#define cplus_demangle_fill_name d_fill_name
140218822Sdimstatic int d_fill_name (struct demangle_component *, const char *, int);
141130561Sobrien
142130561Sobrien#define cplus_demangle_fill_extended_operator d_fill_extended_operator
143130561Sobrienstatic int
144218822Sdimd_fill_extended_operator (struct demangle_component *, int,
145218822Sdim                          struct demangle_component *);
146130561Sobrien
147130561Sobrien#define cplus_demangle_fill_ctor d_fill_ctor
148130561Sobrienstatic int
149218822Sdimd_fill_ctor (struct demangle_component *, enum gnu_v3_ctor_kinds,
150218822Sdim             struct demangle_component *);
151130561Sobrien
152130561Sobrien#define cplus_demangle_fill_dtor d_fill_dtor
153130561Sobrienstatic int
154218822Sdimd_fill_dtor (struct demangle_component *, enum gnu_v3_dtor_kinds,
155218822Sdim             struct demangle_component *);
156130561Sobrien
157130561Sobrien#define cplus_demangle_mangled_name d_mangled_name
158218822Sdimstatic struct demangle_component *d_mangled_name (struct d_info *, int);
159130561Sobrien
160130561Sobrien#define cplus_demangle_type d_type
161218822Sdimstatic struct demangle_component *d_type (struct d_info *);
162130561Sobrien
163130561Sobrien#define cplus_demangle_print d_print
164218822Sdimstatic char *d_print (int, const struct demangle_component *, int, size_t *);
165130561Sobrien
166218822Sdim#define cplus_demangle_print_callback d_print_callback
167218822Sdimstatic int d_print_callback (int, const struct demangle_component *,
168218822Sdim                             demangle_callbackref, void *);
169218822Sdim
170130561Sobrien#define cplus_demangle_init_info d_init_info
171218822Sdimstatic void d_init_info (const char *, int, size_t, struct d_info *);
172130561Sobrien
173130561Sobrien#else /* ! defined(IN_GLIBCPP_V3) */
174130561Sobrien#define CP_STATIC_IF_GLIBCPP_V3
175130561Sobrien#endif /* ! defined(IN_GLIBCPP_V3) */
176130561Sobrien
177130561Sobrien/* See if the compiler supports dynamic arrays.  */
178130561Sobrien
179130561Sobrien#ifdef __GNUC__
180130561Sobrien#define CP_DYNAMIC_ARRAYS
18168765Sobrien#else
182130561Sobrien#ifdef __STDC__
183130561Sobrien#ifdef __STDC_VERSION__
184130561Sobrien#if __STDC_VERSION__ >= 199901L
185130561Sobrien#define CP_DYNAMIC_ARRAYS
186130561Sobrien#endif /* __STDC__VERSION >= 199901L */
187130561Sobrien#endif /* defined (__STDC_VERSION__) */
188130561Sobrien#endif /* defined (__STDC__) */
189130561Sobrien#endif /* ! defined (__GNUC__) */
19068765Sobrien
191130561Sobrien/* We avoid pulling in the ctype tables, to prevent pulling in
192130561Sobrien   additional unresolved symbols when this code is used in a library.
193130561Sobrien   FIXME: Is this really a valid reason?  This comes from the original
194130561Sobrien   V3 demangler code.
19568765Sobrien
196130561Sobrien   As of this writing this file has the following undefined references
197218822Sdim   when compiled with -DIN_GLIBCPP_V3: realloc, free, memcpy, strcpy,
198218822Sdim   strcat, strlen.  */
199130561Sobrien
200130561Sobrien#define IS_DIGIT(c) ((c) >= '0' && (c) <= '9')
201130561Sobrien#define IS_UPPER(c) ((c) >= 'A' && (c) <= 'Z')
202130561Sobrien#define IS_LOWER(c) ((c) >= 'a' && (c) <= 'z')
203130561Sobrien
20477298Sobrien/* The prefix prepended by GCC to an identifier represnting the
20577298Sobrien   anonymous namespace.  */
20677298Sobrien#define ANONYMOUS_NAMESPACE_PREFIX "_GLOBAL_"
207130561Sobrien#define ANONYMOUS_NAMESPACE_PREFIX_LEN \
208130561Sobrien  (sizeof (ANONYMOUS_NAMESPACE_PREFIX) - 1)
20977298Sobrien
210130561Sobrien/* Information we keep for the standard substitutions.  */
21189857Sobrien
212130561Sobrienstruct d_standard_sub_info
213130561Sobrien{
214130561Sobrien  /* The code for this substitution.  */
215130561Sobrien  char code;
216130561Sobrien  /* The simple string it expands to.  */
217130561Sobrien  const char *simple_expansion;
218130561Sobrien  /* The length of the simple expansion.  */
219130561Sobrien  int simple_len;
220130561Sobrien  /* The results of a full, verbose, expansion.  This is used when
221130561Sobrien     qualifying a constructor/destructor, or when in verbose mode.  */
222130561Sobrien  const char *full_expansion;
223130561Sobrien  /* The length of the full expansion.  */
224130561Sobrien  int full_len;
225130561Sobrien  /* What to set the last_name field of d_info to; NULL if we should
226130561Sobrien     not set it.  This is only relevant when qualifying a
227130561Sobrien     constructor/destructor.  */
228130561Sobrien  const char *set_last_name;
229130561Sobrien  /* The length of set_last_name.  */
230130561Sobrien  int set_last_name_len;
231130561Sobrien};
23268765Sobrien
233130561Sobrien/* Accessors for subtrees of struct demangle_component.  */
23468765Sobrien
235130561Sobrien#define d_left(dc) ((dc)->u.s_binary.left)
236130561Sobrien#define d_right(dc) ((dc)->u.s_binary.right)
23768765Sobrien
238130561Sobrien/* A list of templates.  This is used while printing.  */
239130561Sobrien
240130561Sobrienstruct d_print_template
24168765Sobrien{
242130561Sobrien  /* Next template on the list.  */
243130561Sobrien  struct d_print_template *next;
244130561Sobrien  /* This template.  */
245218822Sdim  const struct demangle_component *template_decl;
246130561Sobrien};
24777298Sobrien
248130561Sobrien/* A list of type modifiers.  This is used while printing.  */
24977298Sobrien
250130561Sobrienstruct d_print_mod
251130561Sobrien{
252130561Sobrien  /* Next modifier on the list.  These are in the reverse of the order
253130561Sobrien     in which they appeared in the mangled string.  */
254130561Sobrien  struct d_print_mod *next;
255130561Sobrien  /* The modifier.  */
256130561Sobrien  const struct demangle_component *mod;
257130561Sobrien  /* Whether this modifier was printed.  */
258130561Sobrien  int printed;
259130561Sobrien  /* The list of templates which applies to this modifier.  */
260130561Sobrien  struct d_print_template *templates;
26168765Sobrien};
26268765Sobrien
263218822Sdim/* We use these structures to hold information during printing.  */
26468765Sobrien
265218822Sdimstruct d_growable_string
26668765Sobrien{
267130561Sobrien  /* Buffer holding the result.  */
268130561Sobrien  char *buf;
269130561Sobrien  /* Current length of data in buffer.  */
270130561Sobrien  size_t len;
271130561Sobrien  /* Allocated size of buffer.  */
272130561Sobrien  size_t alc;
273218822Sdim  /* Set to 1 if we had a memory allocation failure.  */
274218822Sdim  int allocation_failure;
275218822Sdim};
276218822Sdim
277218822Sdimenum { D_PRINT_BUFFER_LENGTH = 256 };
278218822Sdimstruct d_print_info
279218822Sdim{
280218822Sdim  /* The options passed to the demangler.  */
281218822Sdim  int options;
282218822Sdim  /* Fixed-length allocated buffer for demangled data, flushed to the
283218822Sdim     callback with a NUL termination once full.  */
284218822Sdim  char buf[D_PRINT_BUFFER_LENGTH];
285218822Sdim  /* Current length of data in buffer.  */
286218822Sdim  size_t len;
287218822Sdim  /* The last character printed, saved individually so that it survives
288218822Sdim     any buffer flush.  */
289218822Sdim  char last_char;
290218822Sdim  /* Callback function to handle demangled buffer flush.  */
291218822Sdim  demangle_callbackref callback;
292218822Sdim  /* Opaque callback argument.  */
293218822Sdim  void *opaque;
294130561Sobrien  /* The current list of templates, if any.  */
295130561Sobrien  struct d_print_template *templates;
296130561Sobrien  /* The current list of modifiers (e.g., pointer, reference, etc.),
297130561Sobrien     if any.  */
298130561Sobrien  struct d_print_mod *modifiers;
299218822Sdim  /* Set to 1 if we saw a demangling error.  */
300218822Sdim  int demangle_failure;
30168765Sobrien};
30268765Sobrien
303130561Sobrien#ifdef CP_DEMANGLE_DEBUG
304218822Sdimstatic void d_dump (struct demangle_component *, int);
305130561Sobrien#endif
30668765Sobrien
307130561Sobrienstatic struct demangle_component *
308218822Sdimd_make_empty (struct d_info *);
30968765Sobrien
310130561Sobrienstatic struct demangle_component *
311218822Sdimd_make_comp (struct d_info *, enum demangle_component_type,
312218822Sdim             struct demangle_component *,
313218822Sdim             struct demangle_component *);
31468765Sobrien
315130561Sobrienstatic struct demangle_component *
316218822Sdimd_make_name (struct d_info *, const char *, int);
31768765Sobrien
318130561Sobrienstatic struct demangle_component *
319218822Sdimd_make_builtin_type (struct d_info *,
320218822Sdim                     const struct demangle_builtin_type_info *);
32168765Sobrien
322130561Sobrienstatic struct demangle_component *
323218822Sdimd_make_operator (struct d_info *,
324218822Sdim                 const struct demangle_operator_info *);
32568765Sobrien
326130561Sobrienstatic struct demangle_component *
327218822Sdimd_make_extended_operator (struct d_info *, int,
328218822Sdim                          struct demangle_component *);
32968765Sobrien
330130561Sobrienstatic struct demangle_component *
331218822Sdimd_make_ctor (struct d_info *, enum gnu_v3_ctor_kinds,
332218822Sdim             struct demangle_component *);
33368765Sobrien
334130561Sobrienstatic struct demangle_component *
335218822Sdimd_make_dtor (struct d_info *, enum gnu_v3_dtor_kinds,
336218822Sdim             struct demangle_component *);
33768765Sobrien
338130561Sobrienstatic struct demangle_component *
339218822Sdimd_make_template_param (struct d_info *, long);
34068765Sobrien
341130561Sobrienstatic struct demangle_component *
342218822Sdimd_make_sub (struct d_info *, const char *, int);
34368765Sobrien
344130561Sobrienstatic int
345218822Sdimhas_return_type (struct demangle_component *);
34689857Sobrien
347130561Sobrienstatic int
348218822Sdimis_ctor_dtor_or_conversion (struct demangle_component *);
34989857Sobrien
350218822Sdimstatic struct demangle_component *d_encoding (struct d_info *, int);
35189857Sobrien
352218822Sdimstatic struct demangle_component *d_name (struct d_info *);
35368765Sobrien
354218822Sdimstatic struct demangle_component *d_nested_name (struct d_info *);
35568765Sobrien
356218822Sdimstatic struct demangle_component *d_prefix (struct d_info *);
35768765Sobrien
358218822Sdimstatic struct demangle_component *d_unqualified_name (struct d_info *);
35968765Sobrien
360218822Sdimstatic struct demangle_component *d_source_name (struct d_info *);
36168765Sobrien
362218822Sdimstatic long d_number (struct d_info *);
36368765Sobrien
364218822Sdimstatic struct demangle_component *d_identifier (struct d_info *, int);
36568765Sobrien
366218822Sdimstatic struct demangle_component *d_operator_name (struct d_info *);
36768765Sobrien
368218822Sdimstatic struct demangle_component *d_special_name (struct d_info *);
36968765Sobrien
370218822Sdimstatic int d_call_offset (struct d_info *, int);
37168765Sobrien
372218822Sdimstatic struct demangle_component *d_ctor_dtor_name (struct d_info *);
37368765Sobrien
374130561Sobrienstatic struct demangle_component **
375218822Sdimd_cv_qualifiers (struct d_info *, struct demangle_component **, int);
37668765Sobrien
377130561Sobrienstatic struct demangle_component *
378218822Sdimd_function_type (struct d_info *);
37968765Sobrien
380130561Sobrienstatic struct demangle_component *
381218822Sdimd_bare_function_type (struct d_info *, int);
38268765Sobrien
383130561Sobrienstatic struct demangle_component *
384218822Sdimd_class_enum_type (struct d_info *);
38568765Sobrien
386218822Sdimstatic struct demangle_component *d_array_type (struct d_info *);
38768765Sobrien
388130561Sobrienstatic struct demangle_component *
389218822Sdimd_pointer_to_member_type (struct d_info *);
39068765Sobrien
391130561Sobrienstatic struct demangle_component *
392218822Sdimd_template_param (struct d_info *);
39377298Sobrien
394218822Sdimstatic struct demangle_component *d_template_args (struct d_info *);
39568765Sobrien
396130561Sobrienstatic struct demangle_component *
397218822Sdimd_template_arg (struct d_info *);
39868765Sobrien
399218822Sdimstatic struct demangle_component *d_expression (struct d_info *);
40068765Sobrien
401218822Sdimstatic struct demangle_component *d_expr_primary (struct d_info *);
40277298Sobrien
403218822Sdimstatic struct demangle_component *d_local_name (struct d_info *);
40477298Sobrien
405218822Sdimstatic int d_discriminator (struct d_info *);
40677298Sobrien
407130561Sobrienstatic int
408218822Sdimd_add_substitution (struct d_info *, struct demangle_component *);
40968765Sobrien
410218822Sdimstatic struct demangle_component *d_substitution (struct d_info *, int);
41168765Sobrien
412218822Sdimstatic void d_growable_string_init (struct d_growable_string *, size_t);
41368765Sobrien
414218822Sdimstatic inline void
415218822Sdimd_growable_string_resize (struct d_growable_string *, size_t);
41668765Sobrien
417218822Sdimstatic inline void
418218822Sdimd_growable_string_append_buffer (struct d_growable_string *,
419218822Sdim                                 const char *, size_t);
420130561Sobrienstatic void
421218822Sdimd_growable_string_callback_adapter (const char *, size_t, void *);
42268765Sobrien
423130561Sobrienstatic void
424218822Sdimd_print_init (struct d_print_info *, int, demangle_callbackref, void *);
42568765Sobrien
426218822Sdimstatic inline void d_print_error (struct d_print_info *);
427218822Sdim
428218822Sdimstatic inline int d_print_saw_error (struct d_print_info *);
429218822Sdim
430218822Sdimstatic inline void d_print_flush (struct d_print_info *);
431218822Sdim
432218822Sdimstatic inline void d_append_char (struct d_print_info *, char);
433218822Sdim
434218822Sdimstatic inline void d_append_buffer (struct d_print_info *,
435218822Sdim                                    const char *, size_t);
436218822Sdim
437218822Sdimstatic inline void d_append_string (struct d_print_info *, const char *);
438218822Sdim
439218822Sdimstatic inline char d_last_char (struct d_print_info *);
440218822Sdim
441130561Sobrienstatic void
442218822Sdimd_print_comp (struct d_print_info *, const struct demangle_component *);
44368765Sobrien
444130561Sobrienstatic void
445218822Sdimd_print_java_identifier (struct d_print_info *, const char *, int);
44668765Sobrien
447130561Sobrienstatic void
448218822Sdimd_print_mod_list (struct d_print_info *, struct d_print_mod *, int);
44968765Sobrien
450130561Sobrienstatic void
451218822Sdimd_print_mod (struct d_print_info *, const struct demangle_component *);
45268765Sobrien
453130561Sobrienstatic void
454218822Sdimd_print_function_type (struct d_print_info *,
455218822Sdim                       const struct demangle_component *,
456218822Sdim                       struct d_print_mod *);
45768765Sobrien
458130561Sobrienstatic void
459218822Sdimd_print_array_type (struct d_print_info *,
460218822Sdim                    const struct demangle_component *,
461218822Sdim                    struct d_print_mod *);
46268765Sobrien
463130561Sobrienstatic void
464218822Sdimd_print_expr_op (struct d_print_info *, const struct demangle_component *);
46568765Sobrien
46668765Sobrienstatic void
467218822Sdimd_print_cast (struct d_print_info *, const struct demangle_component *);
46868765Sobrien
469218822Sdimstatic int d_demangle_callback (const char *, int,
470218822Sdim                                demangle_callbackref, void *);
471218822Sdimstatic char *d_demangle (const char *, int, size_t *);
47268765Sobrien
473130561Sobrien#ifdef CP_DEMANGLE_DEBUG
474130561Sobrien
475130561Sobrienstatic void
476218822Sdimd_dump (struct demangle_component *dc, int indent)
47768765Sobrien{
478130561Sobrien  int i;
47968765Sobrien
480130561Sobrien  if (dc == NULL)
481218822Sdim    {
482218822Sdim      if (indent == 0)
483218822Sdim        printf ("failed demangling\n");
484218822Sdim      return;
485218822Sdim    }
48668765Sobrien
487130561Sobrien  for (i = 0; i < indent; ++i)
488130561Sobrien    putchar (' ');
48968765Sobrien
490130561Sobrien  switch (dc->type)
491130561Sobrien    {
492130561Sobrien    case DEMANGLE_COMPONENT_NAME:
493130561Sobrien      printf ("name '%.*s'\n", dc->u.s_name.len, dc->u.s_name.s);
494130561Sobrien      return;
495130561Sobrien    case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
496130561Sobrien      printf ("template parameter %ld\n", dc->u.s_number.number);
497130561Sobrien      return;
498130561Sobrien    case DEMANGLE_COMPONENT_CTOR:
499130561Sobrien      printf ("constructor %d\n", (int) dc->u.s_ctor.kind);
500130561Sobrien      d_dump (dc->u.s_ctor.name, indent + 2);
501130561Sobrien      return;
502130561Sobrien    case DEMANGLE_COMPONENT_DTOR:
503130561Sobrien      printf ("destructor %d\n", (int) dc->u.s_dtor.kind);
504130561Sobrien      d_dump (dc->u.s_dtor.name, indent + 2);
505130561Sobrien      return;
506130561Sobrien    case DEMANGLE_COMPONENT_SUB_STD:
507130561Sobrien      printf ("standard substitution %s\n", dc->u.s_string.string);
508130561Sobrien      return;
509130561Sobrien    case DEMANGLE_COMPONENT_BUILTIN_TYPE:
510130561Sobrien      printf ("builtin type %s\n", dc->u.s_builtin.type->name);
511130561Sobrien      return;
512130561Sobrien    case DEMANGLE_COMPONENT_OPERATOR:
513130561Sobrien      printf ("operator %s\n", dc->u.s_operator.op->name);
514130561Sobrien      return;
515130561Sobrien    case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
516130561Sobrien      printf ("extended operator with %d args\n",
517130561Sobrien	      dc->u.s_extended_operator.args);
518130561Sobrien      d_dump (dc->u.s_extended_operator.name, indent + 2);
519130561Sobrien      return;
52068765Sobrien
521130561Sobrien    case DEMANGLE_COMPONENT_QUAL_NAME:
522130561Sobrien      printf ("qualified name\n");
523130561Sobrien      break;
524130561Sobrien    case DEMANGLE_COMPONENT_LOCAL_NAME:
525130561Sobrien      printf ("local name\n");
526130561Sobrien      break;
527130561Sobrien    case DEMANGLE_COMPONENT_TYPED_NAME:
528130561Sobrien      printf ("typed name\n");
529130561Sobrien      break;
530130561Sobrien    case DEMANGLE_COMPONENT_TEMPLATE:
531130561Sobrien      printf ("template\n");
532130561Sobrien      break;
533130561Sobrien    case DEMANGLE_COMPONENT_VTABLE:
534130561Sobrien      printf ("vtable\n");
535130561Sobrien      break;
536130561Sobrien    case DEMANGLE_COMPONENT_VTT:
537130561Sobrien      printf ("VTT\n");
538130561Sobrien      break;
539130561Sobrien    case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
540130561Sobrien      printf ("construction vtable\n");
541130561Sobrien      break;
542130561Sobrien    case DEMANGLE_COMPONENT_TYPEINFO:
543130561Sobrien      printf ("typeinfo\n");
544130561Sobrien      break;
545130561Sobrien    case DEMANGLE_COMPONENT_TYPEINFO_NAME:
546130561Sobrien      printf ("typeinfo name\n");
547130561Sobrien      break;
548130561Sobrien    case DEMANGLE_COMPONENT_TYPEINFO_FN:
549130561Sobrien      printf ("typeinfo function\n");
550130561Sobrien      break;
551130561Sobrien    case DEMANGLE_COMPONENT_THUNK:
552130561Sobrien      printf ("thunk\n");
553130561Sobrien      break;
554130561Sobrien    case DEMANGLE_COMPONENT_VIRTUAL_THUNK:
555130561Sobrien      printf ("virtual thunk\n");
556130561Sobrien      break;
557130561Sobrien    case DEMANGLE_COMPONENT_COVARIANT_THUNK:
558130561Sobrien      printf ("covariant thunk\n");
559130561Sobrien      break;
560130561Sobrien    case DEMANGLE_COMPONENT_JAVA_CLASS:
561130561Sobrien      printf ("java class\n");
562130561Sobrien      break;
563130561Sobrien    case DEMANGLE_COMPONENT_GUARD:
564130561Sobrien      printf ("guard\n");
565130561Sobrien      break;
566130561Sobrien    case DEMANGLE_COMPONENT_REFTEMP:
567130561Sobrien      printf ("reference temporary\n");
568130561Sobrien      break;
569218822Sdim    case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
570218822Sdim      printf ("hidden alias\n");
571218822Sdim      break;
572130561Sobrien    case DEMANGLE_COMPONENT_RESTRICT:
573130561Sobrien      printf ("restrict\n");
574130561Sobrien      break;
575130561Sobrien    case DEMANGLE_COMPONENT_VOLATILE:
576130561Sobrien      printf ("volatile\n");
577130561Sobrien      break;
578130561Sobrien    case DEMANGLE_COMPONENT_CONST:
579130561Sobrien      printf ("const\n");
580130561Sobrien      break;
581130561Sobrien    case DEMANGLE_COMPONENT_RESTRICT_THIS:
582130561Sobrien      printf ("restrict this\n");
583130561Sobrien      break;
584130561Sobrien    case DEMANGLE_COMPONENT_VOLATILE_THIS:
585130561Sobrien      printf ("volatile this\n");
586130561Sobrien      break;
587130561Sobrien    case DEMANGLE_COMPONENT_CONST_THIS:
588130561Sobrien      printf ("const this\n");
589130561Sobrien      break;
590130561Sobrien    case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
591130561Sobrien      printf ("vendor type qualifier\n");
592130561Sobrien      break;
593130561Sobrien    case DEMANGLE_COMPONENT_POINTER:
594130561Sobrien      printf ("pointer\n");
595130561Sobrien      break;
596130561Sobrien    case DEMANGLE_COMPONENT_REFERENCE:
597130561Sobrien      printf ("reference\n");
598130561Sobrien      break;
599130561Sobrien    case DEMANGLE_COMPONENT_COMPLEX:
600130561Sobrien      printf ("complex\n");
601130561Sobrien      break;
602130561Sobrien    case DEMANGLE_COMPONENT_IMAGINARY:
603130561Sobrien      printf ("imaginary\n");
604130561Sobrien      break;
605130561Sobrien    case DEMANGLE_COMPONENT_VENDOR_TYPE:
606130561Sobrien      printf ("vendor type\n");
607130561Sobrien      break;
608130561Sobrien    case DEMANGLE_COMPONENT_FUNCTION_TYPE:
609130561Sobrien      printf ("function type\n");
610130561Sobrien      break;
611130561Sobrien    case DEMANGLE_COMPONENT_ARRAY_TYPE:
612130561Sobrien      printf ("array type\n");
613130561Sobrien      break;
614130561Sobrien    case DEMANGLE_COMPONENT_PTRMEM_TYPE:
615130561Sobrien      printf ("pointer to member type\n");
616130561Sobrien      break;
617130561Sobrien    case DEMANGLE_COMPONENT_ARGLIST:
618130561Sobrien      printf ("argument list\n");
619130561Sobrien      break;
620130561Sobrien    case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
621130561Sobrien      printf ("template argument list\n");
622130561Sobrien      break;
623130561Sobrien    case DEMANGLE_COMPONENT_CAST:
624130561Sobrien      printf ("cast\n");
625130561Sobrien      break;
626130561Sobrien    case DEMANGLE_COMPONENT_UNARY:
627130561Sobrien      printf ("unary operator\n");
628130561Sobrien      break;
629130561Sobrien    case DEMANGLE_COMPONENT_BINARY:
630130561Sobrien      printf ("binary operator\n");
631130561Sobrien      break;
632130561Sobrien    case DEMANGLE_COMPONENT_BINARY_ARGS:
633130561Sobrien      printf ("binary operator arguments\n");
634130561Sobrien      break;
635130561Sobrien    case DEMANGLE_COMPONENT_TRINARY:
636130561Sobrien      printf ("trinary operator\n");
637130561Sobrien      break;
638130561Sobrien    case DEMANGLE_COMPONENT_TRINARY_ARG1:
639130561Sobrien      printf ("trinary operator arguments 1\n");
640130561Sobrien      break;
641130561Sobrien    case DEMANGLE_COMPONENT_TRINARY_ARG2:
642130561Sobrien      printf ("trinary operator arguments 1\n");
643130561Sobrien      break;
644130561Sobrien    case DEMANGLE_COMPONENT_LITERAL:
645130561Sobrien      printf ("literal\n");
646130561Sobrien      break;
647130561Sobrien    case DEMANGLE_COMPONENT_LITERAL_NEG:
648130561Sobrien      printf ("negative literal\n");
649130561Sobrien      break;
650130561Sobrien    }
65168765Sobrien
652130561Sobrien  d_dump (d_left (dc), indent + 2);
653130561Sobrien  d_dump (d_right (dc), indent + 2);
65468765Sobrien}
65568765Sobrien
656130561Sobrien#endif /* CP_DEMANGLE_DEBUG */
65768765Sobrien
658130561Sobrien/* Fill in a DEMANGLE_COMPONENT_NAME.  */
659130561Sobrien
660130561SobrienCP_STATIC_IF_GLIBCPP_V3
661130561Sobrienint
662218822Sdimcplus_demangle_fill_name (struct demangle_component *p, const char *s, int len)
66368765Sobrien{
664130561Sobrien  if (p == NULL || s == NULL || len == 0)
665130561Sobrien    return 0;
666130561Sobrien  p->type = DEMANGLE_COMPONENT_NAME;
667130561Sobrien  p->u.s_name.s = s;
668130561Sobrien  p->u.s_name.len = len;
669130561Sobrien  return 1;
67068765Sobrien}
67168765Sobrien
672130561Sobrien/* Fill in a DEMANGLE_COMPONENT_EXTENDED_OPERATOR.  */
67377298Sobrien
674130561SobrienCP_STATIC_IF_GLIBCPP_V3
675130561Sobrienint
676218822Sdimcplus_demangle_fill_extended_operator (struct demangle_component *p, int args,
677218822Sdim                                       struct demangle_component *name)
67877298Sobrien{
679130561Sobrien  if (p == NULL || args < 0 || name == NULL)
680130561Sobrien    return 0;
681130561Sobrien  p->type = DEMANGLE_COMPONENT_EXTENDED_OPERATOR;
682130561Sobrien  p->u.s_extended_operator.args = args;
683130561Sobrien  p->u.s_extended_operator.name = name;
684130561Sobrien  return 1;
68577298Sobrien}
68677298Sobrien
687130561Sobrien/* Fill in a DEMANGLE_COMPONENT_CTOR.  */
68877298Sobrien
689130561SobrienCP_STATIC_IF_GLIBCPP_V3
690130561Sobrienint
691218822Sdimcplus_demangle_fill_ctor (struct demangle_component *p,
692218822Sdim                          enum gnu_v3_ctor_kinds kind,
693218822Sdim                          struct demangle_component *name)
69477298Sobrien{
695130561Sobrien  if (p == NULL
696130561Sobrien      || name == NULL
697130561Sobrien      || (kind < gnu_v3_complete_object_ctor
698130561Sobrien	  && kind > gnu_v3_complete_object_allocating_ctor))
699130561Sobrien    return 0;
700130561Sobrien  p->type = DEMANGLE_COMPONENT_CTOR;
701130561Sobrien  p->u.s_ctor.kind = kind;
702130561Sobrien  p->u.s_ctor.name = name;
703130561Sobrien  return 1;
70477298Sobrien}
70577298Sobrien
706130561Sobrien/* Fill in a DEMANGLE_COMPONENT_DTOR.  */
70777298Sobrien
708130561SobrienCP_STATIC_IF_GLIBCPP_V3
709130561Sobrienint
710218822Sdimcplus_demangle_fill_dtor (struct demangle_component *p,
711218822Sdim                          enum gnu_v3_dtor_kinds kind,
712218822Sdim                          struct demangle_component *name)
71377298Sobrien{
714130561Sobrien  if (p == NULL
715130561Sobrien      || name == NULL
716130561Sobrien      || (kind < gnu_v3_deleting_dtor
717130561Sobrien	  && kind > gnu_v3_base_object_dtor))
718130561Sobrien    return 0;
719130561Sobrien  p->type = DEMANGLE_COMPONENT_DTOR;
720130561Sobrien  p->u.s_dtor.kind = kind;
721130561Sobrien  p->u.s_dtor.name = name;
722130561Sobrien  return 1;
72377298Sobrien}
72477298Sobrien
725130561Sobrien/* Add a new component.  */
72677298Sobrien
727130561Sobrienstatic struct demangle_component *
728218822Sdimd_make_empty (struct d_info *di)
72977298Sobrien{
730130561Sobrien  struct demangle_component *p;
731130561Sobrien
732130561Sobrien  if (di->next_comp >= di->num_comps)
733130561Sobrien    return NULL;
734130561Sobrien  p = &di->comps[di->next_comp];
735130561Sobrien  ++di->next_comp;
736130561Sobrien  return p;
73777298Sobrien}
73877298Sobrien
739130561Sobrien/* Add a new generic component.  */
74068765Sobrien
741130561Sobrienstatic struct demangle_component *
742218822Sdimd_make_comp (struct d_info *di, enum demangle_component_type type,
743218822Sdim             struct demangle_component *left,
744218822Sdim             struct demangle_component *right)
74568765Sobrien{
746130561Sobrien  struct demangle_component *p;
74768765Sobrien
748130561Sobrien  /* We check for errors here.  A typical error would be a NULL return
749130561Sobrien     from a subroutine.  We catch those here, and return NULL
750130561Sobrien     upward.  */
751130561Sobrien  switch (type)
752130561Sobrien    {
753130561Sobrien      /* These types require two parameters.  */
754130561Sobrien    case DEMANGLE_COMPONENT_QUAL_NAME:
755130561Sobrien    case DEMANGLE_COMPONENT_LOCAL_NAME:
756130561Sobrien    case DEMANGLE_COMPONENT_TYPED_NAME:
757130561Sobrien    case DEMANGLE_COMPONENT_TEMPLATE:
758130561Sobrien    case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
759130561Sobrien    case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
760130561Sobrien    case DEMANGLE_COMPONENT_PTRMEM_TYPE:
761130561Sobrien    case DEMANGLE_COMPONENT_UNARY:
762130561Sobrien    case DEMANGLE_COMPONENT_BINARY:
763130561Sobrien    case DEMANGLE_COMPONENT_BINARY_ARGS:
764130561Sobrien    case DEMANGLE_COMPONENT_TRINARY:
765130561Sobrien    case DEMANGLE_COMPONENT_TRINARY_ARG1:
766130561Sobrien    case DEMANGLE_COMPONENT_TRINARY_ARG2:
767130561Sobrien    case DEMANGLE_COMPONENT_LITERAL:
768130561Sobrien    case DEMANGLE_COMPONENT_LITERAL_NEG:
769130561Sobrien      if (left == NULL || right == NULL)
770130561Sobrien	return NULL;
771130561Sobrien      break;
77268765Sobrien
773130561Sobrien      /* These types only require one parameter.  */
774130561Sobrien    case DEMANGLE_COMPONENT_VTABLE:
775130561Sobrien    case DEMANGLE_COMPONENT_VTT:
776130561Sobrien    case DEMANGLE_COMPONENT_TYPEINFO:
777130561Sobrien    case DEMANGLE_COMPONENT_TYPEINFO_NAME:
778130561Sobrien    case DEMANGLE_COMPONENT_TYPEINFO_FN:
779130561Sobrien    case DEMANGLE_COMPONENT_THUNK:
780130561Sobrien    case DEMANGLE_COMPONENT_VIRTUAL_THUNK:
781130561Sobrien    case DEMANGLE_COMPONENT_COVARIANT_THUNK:
782130561Sobrien    case DEMANGLE_COMPONENT_JAVA_CLASS:
783130561Sobrien    case DEMANGLE_COMPONENT_GUARD:
784130561Sobrien    case DEMANGLE_COMPONENT_REFTEMP:
785218822Sdim    case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
786130561Sobrien    case DEMANGLE_COMPONENT_POINTER:
787130561Sobrien    case DEMANGLE_COMPONENT_REFERENCE:
788130561Sobrien    case DEMANGLE_COMPONENT_COMPLEX:
789130561Sobrien    case DEMANGLE_COMPONENT_IMAGINARY:
790130561Sobrien    case DEMANGLE_COMPONENT_VENDOR_TYPE:
791130561Sobrien    case DEMANGLE_COMPONENT_ARGLIST:
792130561Sobrien    case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
793130561Sobrien    case DEMANGLE_COMPONENT_CAST:
794130561Sobrien      if (left == NULL)
795130561Sobrien	return NULL;
796130561Sobrien      break;
79768765Sobrien
798130561Sobrien      /* This needs a right parameter, but the left parameter can be
799130561Sobrien	 empty.  */
800130561Sobrien    case DEMANGLE_COMPONENT_ARRAY_TYPE:
801130561Sobrien      if (right == NULL)
802130561Sobrien	return NULL;
803130561Sobrien      break;
80468765Sobrien
805130561Sobrien      /* These are allowed to have no parameters--in some cases they
806130561Sobrien	 will be filled in later.  */
807130561Sobrien    case DEMANGLE_COMPONENT_FUNCTION_TYPE:
808130561Sobrien    case DEMANGLE_COMPONENT_RESTRICT:
809130561Sobrien    case DEMANGLE_COMPONENT_VOLATILE:
810130561Sobrien    case DEMANGLE_COMPONENT_CONST:
811130561Sobrien    case DEMANGLE_COMPONENT_RESTRICT_THIS:
812130561Sobrien    case DEMANGLE_COMPONENT_VOLATILE_THIS:
813130561Sobrien    case DEMANGLE_COMPONENT_CONST_THIS:
814130561Sobrien      break;
815130561Sobrien
816130561Sobrien      /* Other types should not be seen here.  */
817130561Sobrien    default:
818130561Sobrien      return NULL;
81968765Sobrien    }
82068765Sobrien
821130561Sobrien  p = d_make_empty (di);
822130561Sobrien  if (p != NULL)
82368765Sobrien    {
824130561Sobrien      p->type = type;
825130561Sobrien      p->u.s_binary.left = left;
826130561Sobrien      p->u.s_binary.right = right;
82768765Sobrien    }
828130561Sobrien  return p;
829130561Sobrien}
83068765Sobrien
831130561Sobrien/* Add a new name component.  */
83268765Sobrien
833130561Sobrienstatic struct demangle_component *
834218822Sdimd_make_name (struct d_info *di, const char *s, int len)
835130561Sobrien{
836130561Sobrien  struct demangle_component *p;
83768765Sobrien
838130561Sobrien  p = d_make_empty (di);
839130561Sobrien  if (! cplus_demangle_fill_name (p, s, len))
840130561Sobrien    return NULL;
841130561Sobrien  return p;
84268765Sobrien}
84368765Sobrien
844130561Sobrien/* Add a new builtin type component.  */
84568765Sobrien
846130561Sobrienstatic struct demangle_component *
847218822Sdimd_make_builtin_type (struct d_info *di,
848218822Sdim                     const struct demangle_builtin_type_info *type)
84968765Sobrien{
850130561Sobrien  struct demangle_component *p;
85168765Sobrien
852130561Sobrien  if (type == NULL)
85368765Sobrien    return NULL;
854130561Sobrien  p = d_make_empty (di);
855130561Sobrien  if (p != NULL)
856130561Sobrien    {
857130561Sobrien      p->type = DEMANGLE_COMPONENT_BUILTIN_TYPE;
858130561Sobrien      p->u.s_builtin.type = type;
859130561Sobrien    }
860130561Sobrien  return p;
86168765Sobrien}
86268765Sobrien
863130561Sobrien/* Add a new operator component.  */
86468765Sobrien
865130561Sobrienstatic struct demangle_component *
866218822Sdimd_make_operator (struct d_info *di, const struct demangle_operator_info *op)
86768765Sobrien{
868130561Sobrien  struct demangle_component *p;
86968765Sobrien
870130561Sobrien  p = d_make_empty (di);
871130561Sobrien  if (p != NULL)
87268765Sobrien    {
873130561Sobrien      p->type = DEMANGLE_COMPONENT_OPERATOR;
874130561Sobrien      p->u.s_operator.op = op;
87568765Sobrien    }
876130561Sobrien  return p;
87768765Sobrien}
87868765Sobrien
879130561Sobrien/* Add a new extended operator component.  */
88068765Sobrien
881130561Sobrienstatic struct demangle_component *
882218822Sdimd_make_extended_operator (struct d_info *di, int args,
883218822Sdim                          struct demangle_component *name)
884130561Sobrien{
885130561Sobrien  struct demangle_component *p;
88668765Sobrien
887130561Sobrien  p = d_make_empty (di);
888130561Sobrien  if (! cplus_demangle_fill_extended_operator (p, args, name))
88968765Sobrien    return NULL;
890130561Sobrien  return p;
89168765Sobrien}
89268765Sobrien
893130561Sobrien/* Add a new constructor component.  */
89468765Sobrien
895130561Sobrienstatic struct demangle_component *
896218822Sdimd_make_ctor (struct d_info *di, enum gnu_v3_ctor_kinds kind,
897218822Sdim             struct demangle_component *name)
89868765Sobrien{
899130561Sobrien  struct demangle_component *p;
900130561Sobrien
901130561Sobrien  p = d_make_empty (di);
902130561Sobrien  if (! cplus_demangle_fill_ctor (p, kind, name))
903130561Sobrien    return NULL;
904130561Sobrien  return p;
90568765Sobrien}
90668765Sobrien
907130561Sobrien/* Add a new destructor component.  */
90868765Sobrien
909130561Sobrienstatic struct demangle_component *
910218822Sdimd_make_dtor (struct d_info *di, enum gnu_v3_dtor_kinds kind,
911218822Sdim             struct demangle_component *name)
91268765Sobrien{
913130561Sobrien  struct demangle_component *p;
91468765Sobrien
915130561Sobrien  p = d_make_empty (di);
916130561Sobrien  if (! cplus_demangle_fill_dtor (p, kind, name))
917130561Sobrien    return NULL;
918130561Sobrien  return p;
91968765Sobrien}
92068765Sobrien
921130561Sobrien/* Add a new template parameter.  */
92268765Sobrien
923130561Sobrienstatic struct demangle_component *
924218822Sdimd_make_template_param (struct d_info *di, long i)
92568765Sobrien{
926130561Sobrien  struct demangle_component *p;
92768765Sobrien
928130561Sobrien  p = d_make_empty (di);
929130561Sobrien  if (p != NULL)
93068765Sobrien    {
931130561Sobrien      p->type = DEMANGLE_COMPONENT_TEMPLATE_PARAM;
932130561Sobrien      p->u.s_number.number = i;
93368765Sobrien    }
934130561Sobrien  return p;
93568765Sobrien}
93668765Sobrien
937130561Sobrien/* Add a new standard substitution component.  */
93868765Sobrien
939130561Sobrienstatic struct demangle_component *
940218822Sdimd_make_sub (struct d_info *di, const char *name, int len)
94168765Sobrien{
942130561Sobrien  struct demangle_component *p;
94368765Sobrien
944130561Sobrien  p = d_make_empty (di);
945130561Sobrien  if (p != NULL)
94668765Sobrien    {
947130561Sobrien      p->type = DEMANGLE_COMPONENT_SUB_STD;
948130561Sobrien      p->u.s_string.string = name;
949130561Sobrien      p->u.s_string.len = len;
95068765Sobrien    }
951130561Sobrien  return p;
95268765Sobrien}
95368765Sobrien
954130561Sobrien/* <mangled-name> ::= _Z <encoding>
95568765Sobrien
956130561Sobrien   TOP_LEVEL is non-zero when called at the top level.  */
95768765Sobrien
958130561SobrienCP_STATIC_IF_GLIBCPP_V3
959130561Sobrienstruct demangle_component *
960218822Sdimcplus_demangle_mangled_name (struct d_info *di, int top_level)
96168765Sobrien{
962218822Sdim  if (! d_check_char (di, '_'))
963130561Sobrien    return NULL;
964218822Sdim  if (! d_check_char (di, 'Z'))
965130561Sobrien    return NULL;
966130561Sobrien  return d_encoding (di, top_level);
96768765Sobrien}
96868765Sobrien
969130561Sobrien/* Return whether a function should have a return type.  The argument
970130561Sobrien   is the function name, which may be qualified in various ways.  The
971130561Sobrien   rules are that template functions have return types with some
972130561Sobrien   exceptions, function types which are not part of a function name
973130561Sobrien   mangling have return types with some exceptions, and non-template
974130561Sobrien   function names do not have return types.  The exceptions are that
975130561Sobrien   constructors, destructors, and conversion operators do not have
976130561Sobrien   return types.  */
97768765Sobrien
978130561Sobrienstatic int
979218822Sdimhas_return_type (struct demangle_component *dc)
98068765Sobrien{
981130561Sobrien  if (dc == NULL)
982130561Sobrien    return 0;
983130561Sobrien  switch (dc->type)
98468765Sobrien    {
985130561Sobrien    default:
986130561Sobrien      return 0;
987130561Sobrien    case DEMANGLE_COMPONENT_TEMPLATE:
988130561Sobrien      return ! is_ctor_dtor_or_conversion (d_left (dc));
989130561Sobrien    case DEMANGLE_COMPONENT_RESTRICT_THIS:
990130561Sobrien    case DEMANGLE_COMPONENT_VOLATILE_THIS:
991130561Sobrien    case DEMANGLE_COMPONENT_CONST_THIS:
992130561Sobrien      return has_return_type (d_left (dc));
99368765Sobrien    }
99468765Sobrien}
99568765Sobrien
996130561Sobrien/* Return whether a name is a constructor, a destructor, or a
997130561Sobrien   conversion operator.  */
99868765Sobrien
999130561Sobrienstatic int
1000218822Sdimis_ctor_dtor_or_conversion (struct demangle_component *dc)
100168765Sobrien{
1002130561Sobrien  if (dc == NULL)
1003130561Sobrien    return 0;
1004130561Sobrien  switch (dc->type)
100568765Sobrien    {
1006130561Sobrien    default:
1007130561Sobrien      return 0;
1008130561Sobrien    case DEMANGLE_COMPONENT_QUAL_NAME:
1009130561Sobrien    case DEMANGLE_COMPONENT_LOCAL_NAME:
1010130561Sobrien      return is_ctor_dtor_or_conversion (d_right (dc));
1011130561Sobrien    case DEMANGLE_COMPONENT_CTOR:
1012130561Sobrien    case DEMANGLE_COMPONENT_DTOR:
1013130561Sobrien    case DEMANGLE_COMPONENT_CAST:
1014130561Sobrien      return 1;
101568765Sobrien    }
101668765Sobrien}
101768765Sobrien
1018130561Sobrien/* <encoding> ::= <(function) name> <bare-function-type>
1019130561Sobrien              ::= <(data) name>
1020130561Sobrien              ::= <special-name>
102168765Sobrien
1022130561Sobrien   TOP_LEVEL is non-zero when called at the top level, in which case
1023130561Sobrien   if DMGL_PARAMS is not set we do not demangle the function
1024130561Sobrien   parameters.  We only set this at the top level, because otherwise
1025130561Sobrien   we would not correctly demangle names in local scopes.  */
102668765Sobrien
1027130561Sobrienstatic struct demangle_component *
1028218822Sdimd_encoding (struct d_info *di, int top_level)
102968765Sobrien{
1030130561Sobrien  char peek = d_peek_char (di);
103168765Sobrien
1032130561Sobrien  if (peek == 'G' || peek == 'T')
1033130561Sobrien    return d_special_name (di);
103468765Sobrien  else
103568765Sobrien    {
1036130561Sobrien      struct demangle_component *dc;
103768765Sobrien
1038130561Sobrien      dc = d_name (di);
103968765Sobrien
1040130561Sobrien      if (dc != NULL && top_level && (di->options & DMGL_PARAMS) == 0)
1041130561Sobrien	{
1042130561Sobrien	  /* Strip off any initial CV-qualifiers, as they really apply
1043130561Sobrien	     to the `this' parameter, and they were not output by the
1044130561Sobrien	     v2 demangler without DMGL_PARAMS.  */
1045130561Sobrien	  while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS
1046130561Sobrien		 || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS
1047130561Sobrien		 || dc->type == DEMANGLE_COMPONENT_CONST_THIS)
1048130561Sobrien	    dc = d_left (dc);
104968765Sobrien
1050130561Sobrien	  /* If the top level is a DEMANGLE_COMPONENT_LOCAL_NAME, then
1051130561Sobrien	     there may be CV-qualifiers on its right argument which
1052130561Sobrien	     really apply here; this happens when parsing a class
1053130561Sobrien	     which is local to a function.  */
1054130561Sobrien	  if (dc->type == DEMANGLE_COMPONENT_LOCAL_NAME)
1055130561Sobrien	    {
1056130561Sobrien	      struct demangle_component *dcr;
105768765Sobrien
1058130561Sobrien	      dcr = d_right (dc);
1059130561Sobrien	      while (dcr->type == DEMANGLE_COMPONENT_RESTRICT_THIS
1060130561Sobrien		     || dcr->type == DEMANGLE_COMPONENT_VOLATILE_THIS
1061130561Sobrien		     || dcr->type == DEMANGLE_COMPONENT_CONST_THIS)
1062130561Sobrien		dcr = d_left (dcr);
1063130561Sobrien	      dc->u.s_binary.right = dcr;
1064130561Sobrien	    }
106568765Sobrien
1066130561Sobrien	  return dc;
1067130561Sobrien	}
106868765Sobrien
1069130561Sobrien      peek = d_peek_char (di);
1070218822Sdim      if (dc == NULL || peek == '\0' || peek == 'E')
1071130561Sobrien	return dc;
1072130561Sobrien      return d_make_comp (di, DEMANGLE_COMPONENT_TYPED_NAME, dc,
1073130561Sobrien			  d_bare_function_type (di, has_return_type (dc)));
107468765Sobrien    }
107568765Sobrien}
107668765Sobrien
1077130561Sobrien/* <name> ::= <nested-name>
1078130561Sobrien          ::= <unscoped-name>
1079130561Sobrien          ::= <unscoped-template-name> <template-args>
1080130561Sobrien          ::= <local-name>
108168765Sobrien
1082130561Sobrien   <unscoped-name> ::= <unqualified-name>
1083130561Sobrien                   ::= St <unqualified-name>
108468765Sobrien
1085130561Sobrien   <unscoped-template-name> ::= <unscoped-name>
1086130561Sobrien                            ::= <substitution>
1087130561Sobrien*/
108868765Sobrien
1089130561Sobrienstatic struct demangle_component *
1090218822Sdimd_name (struct d_info *di)
109168765Sobrien{
1092130561Sobrien  char peek = d_peek_char (di);
1093130561Sobrien  struct demangle_component *dc;
109468765Sobrien
109577298Sobrien  switch (peek)
109668765Sobrien    {
109768765Sobrien    case 'N':
1098130561Sobrien      return d_nested_name (di);
109968765Sobrien
110068765Sobrien    case 'Z':
1101130561Sobrien      return d_local_name (di);
110268765Sobrien
1103218822Sdim    case 'L':
1104218822Sdim      return d_unqualified_name (di);
1105218822Sdim
110668765Sobrien    case 'S':
1107130561Sobrien      {
1108130561Sobrien	int subst;
110977298Sobrien
1110130561Sobrien	if (d_peek_next_char (di) != 't')
1111130561Sobrien	  {
1112130561Sobrien	    dc = d_substitution (di, 0);
1113130561Sobrien	    subst = 1;
1114130561Sobrien	  }
1115130561Sobrien	else
1116130561Sobrien	  {
1117130561Sobrien	    d_advance (di, 2);
1118130561Sobrien	    dc = d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME,
1119130561Sobrien			      d_make_name (di, "std", 3),
1120130561Sobrien			      d_unqualified_name (di));
1121130561Sobrien	    di->expansion += 3;
1122130561Sobrien	    subst = 0;
1123130561Sobrien	  }
112468765Sobrien
1125130561Sobrien	if (d_peek_char (di) != 'I')
1126130561Sobrien	  {
1127130561Sobrien	    /* The grammar does not permit this case to occur if we
1128130561Sobrien	       called d_substitution() above (i.e., subst == 1).  We
1129130561Sobrien	       don't bother to check.  */
1130130561Sobrien	  }
1131130561Sobrien	else
1132130561Sobrien	  {
1133130561Sobrien	    /* This is <template-args>, which means that we just saw
1134130561Sobrien	       <unscoped-template-name>, which is a substitution
1135130561Sobrien	       candidate if we didn't just get it from a
1136130561Sobrien	       substitution.  */
1137130561Sobrien	    if (! subst)
1138130561Sobrien	      {
1139130561Sobrien		if (! d_add_substitution (di, dc))
1140130561Sobrien		  return NULL;
1141130561Sobrien	      }
1142130561Sobrien	    dc = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, dc,
1143130561Sobrien			      d_template_args (di));
1144130561Sobrien	  }
1145130561Sobrien
1146130561Sobrien	return dc;
1147130561Sobrien      }
1148130561Sobrien
114968765Sobrien    default:
1150130561Sobrien      dc = d_unqualified_name (di);
1151130561Sobrien      if (d_peek_char (di) == 'I')
115268765Sobrien	{
1153130561Sobrien	  /* This is <template-args>, which means that we just saw
1154130561Sobrien	     <unscoped-template-name>, which is a substitution
1155130561Sobrien	     candidate.  */
1156130561Sobrien	  if (! d_add_substitution (di, dc))
1157130561Sobrien	    return NULL;
1158130561Sobrien	  dc = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, dc,
1159130561Sobrien			    d_template_args (di));
116068765Sobrien	}
1161130561Sobrien      return dc;
116268765Sobrien    }
116368765Sobrien}
116468765Sobrien
1165130561Sobrien/* <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
1166130561Sobrien                 ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
1167130561Sobrien*/
116868765Sobrien
1169130561Sobrienstatic struct demangle_component *
1170218822Sdimd_nested_name (struct d_info *di)
117168765Sobrien{
1172130561Sobrien  struct demangle_component *ret;
1173130561Sobrien  struct demangle_component **pret;
117468765Sobrien
1175218822Sdim  if (! d_check_char (di, 'N'))
1176130561Sobrien    return NULL;
117768765Sobrien
1178130561Sobrien  pret = d_cv_qualifiers (di, &ret, 1);
1179130561Sobrien  if (pret == NULL)
1180130561Sobrien    return NULL;
118168765Sobrien
1182130561Sobrien  *pret = d_prefix (di);
1183130561Sobrien  if (*pret == NULL)
1184130561Sobrien    return NULL;
118568765Sobrien
1186218822Sdim  if (! d_check_char (di, 'E'))
1187130561Sobrien    return NULL;
118868765Sobrien
1189130561Sobrien  return ret;
119068765Sobrien}
119168765Sobrien
1192130561Sobrien/* <prefix> ::= <prefix> <unqualified-name>
1193130561Sobrien            ::= <template-prefix> <template-args>
1194130561Sobrien            ::= <template-param>
1195130561Sobrien            ::=
1196130561Sobrien            ::= <substitution>
119768765Sobrien
1198130561Sobrien   <template-prefix> ::= <prefix> <(template) unqualified-name>
1199130561Sobrien                     ::= <template-param>
1200130561Sobrien                     ::= <substitution>
1201130561Sobrien*/
120268765Sobrien
1203130561Sobrienstatic struct demangle_component *
1204218822Sdimd_prefix (struct d_info *di)
120568765Sobrien{
1206130561Sobrien  struct demangle_component *ret = NULL;
120768765Sobrien
120868765Sobrien  while (1)
120968765Sobrien    {
121068765Sobrien      char peek;
1211130561Sobrien      enum demangle_component_type comb_type;
1212130561Sobrien      struct demangle_component *dc;
121368765Sobrien
1214130561Sobrien      peek = d_peek_char (di);
1215130561Sobrien      if (peek == '\0')
1216130561Sobrien	return NULL;
121768765Sobrien
1218130561Sobrien      /* The older code accepts a <local-name> here, but I don't see
1219130561Sobrien	 that in the grammar.  The older code does not accept a
1220130561Sobrien	 <template-param> here.  */
122177298Sobrien
1222130561Sobrien      comb_type = DEMANGLE_COMPONENT_QUAL_NAME;
1223130561Sobrien      if (IS_DIGIT (peek)
1224130561Sobrien	  || IS_LOWER (peek)
1225130561Sobrien	  || peek == 'C'
1226218822Sdim	  || peek == 'D'
1227218822Sdim	  || peek == 'L')
1228130561Sobrien	dc = d_unqualified_name (di);
1229130561Sobrien      else if (peek == 'S')
1230130561Sobrien	dc = d_substitution (di, 1);
123168765Sobrien      else if (peek == 'I')
123268765Sobrien	{
1233130561Sobrien	  if (ret == NULL)
1234130561Sobrien	    return NULL;
1235130561Sobrien	  comb_type = DEMANGLE_COMPONENT_TEMPLATE;
1236130561Sobrien	  dc = d_template_args (di);
123768765Sobrien	}
1238130561Sobrien      else if (peek == 'T')
1239130561Sobrien	dc = d_template_param (di);
124068765Sobrien      else if (peek == 'E')
1241130561Sobrien	return ret;
124268765Sobrien      else
1243130561Sobrien	return NULL;
124468765Sobrien
1245130561Sobrien      if (ret == NULL)
1246130561Sobrien	ret = dc;
1247130561Sobrien      else
1248130561Sobrien	ret = d_make_comp (di, comb_type, ret, dc);
1249130561Sobrien
1250130561Sobrien      if (peek != 'S' && d_peek_char (di) != 'E')
1251130561Sobrien	{
1252130561Sobrien	  if (! d_add_substitution (di, ret))
1253130561Sobrien	    return NULL;
1254130561Sobrien	}
125568765Sobrien    }
125668765Sobrien}
125768765Sobrien
1258130561Sobrien/* <unqualified-name> ::= <operator-name>
1259130561Sobrien                      ::= <ctor-dtor-name>
1260130561Sobrien                      ::= <source-name>
1261218822Sdim		      ::= <local-source-name>
1262218822Sdim
1263218822Sdim    <local-source-name>	::= L <source-name> <discriminator>
1264130561Sobrien*/
126568765Sobrien
1266130561Sobrienstatic struct demangle_component *
1267218822Sdimd_unqualified_name (struct d_info *di)
126868765Sobrien{
1269130561Sobrien  char peek;
127068765Sobrien
1271130561Sobrien  peek = d_peek_char (di);
1272130561Sobrien  if (IS_DIGIT (peek))
1273130561Sobrien    return d_source_name (di);
1274130561Sobrien  else if (IS_LOWER (peek))
127568765Sobrien    {
1276130561Sobrien      struct demangle_component *ret;
127777298Sobrien
1278130561Sobrien      ret = d_operator_name (di);
1279130561Sobrien      if (ret != NULL && ret->type == DEMANGLE_COMPONENT_OPERATOR)
1280130561Sobrien	di->expansion += sizeof "operator" + ret->u.s_operator.op->len - 2;
1281130561Sobrien      return ret;
128268765Sobrien    }
128368765Sobrien  else if (peek == 'C' || peek == 'D')
1284130561Sobrien    return d_ctor_dtor_name (di);
1285218822Sdim  else if (peek == 'L')
1286218822Sdim    {
1287218822Sdim      struct demangle_component * ret;
1288218822Sdim
1289218822Sdim      d_advance (di, 1);
1290218822Sdim
1291218822Sdim      ret = d_source_name (di);
1292218822Sdim      if (ret == NULL)
1293218822Sdim	return NULL;
1294218822Sdim      if (! d_discriminator (di))
1295218822Sdim	return NULL;
1296218822Sdim      return ret;
1297218822Sdim    }
129868765Sobrien  else
1299130561Sobrien    return NULL;
130068765Sobrien}
130168765Sobrien
1302130561Sobrien/* <source-name> ::= <(positive length) number> <identifier>  */
130368765Sobrien
1304130561Sobrienstatic struct demangle_component *
1305218822Sdimd_source_name (struct d_info *di)
130668765Sobrien{
1307130561Sobrien  long len;
1308130561Sobrien  struct demangle_component *ret;
130968765Sobrien
1310130561Sobrien  len = d_number (di);
1311130561Sobrien  if (len <= 0)
1312130561Sobrien    return NULL;
1313130561Sobrien  ret = d_identifier (di, len);
1314130561Sobrien  di->last_name = ret;
1315130561Sobrien  return ret;
1316130561Sobrien}
131768765Sobrien
1318130561Sobrien/* number ::= [n] <(non-negative decimal integer)>  */
131968765Sobrien
1320130561Sobrienstatic long
1321218822Sdimd_number (struct d_info *di)
1322130561Sobrien{
1323130561Sobrien  int negative;
1324130561Sobrien  char peek;
1325130561Sobrien  long ret;
132668765Sobrien
1327130561Sobrien  negative = 0;
1328130561Sobrien  peek = d_peek_char (di);
1329130561Sobrien  if (peek == 'n')
1330130561Sobrien    {
1331130561Sobrien      negative = 1;
1332130561Sobrien      d_advance (di, 1);
1333130561Sobrien      peek = d_peek_char (di);
1334130561Sobrien    }
133568765Sobrien
1336130561Sobrien  ret = 0;
1337130561Sobrien  while (1)
1338130561Sobrien    {
1339130561Sobrien      if (! IS_DIGIT (peek))
1340130561Sobrien	{
1341130561Sobrien	  if (negative)
1342130561Sobrien	    ret = - ret;
1343130561Sobrien	  return ret;
1344130561Sobrien	}
1345130561Sobrien      ret = ret * 10 + peek - '0';
1346130561Sobrien      d_advance (di, 1);
1347130561Sobrien      peek = d_peek_char (di);
1348130561Sobrien    }
134968765Sobrien}
135068765Sobrien
1351130561Sobrien/* identifier ::= <(unqualified source code identifier)>  */
135268765Sobrien
1353130561Sobrienstatic struct demangle_component *
1354218822Sdimd_identifier (struct d_info *di, int len)
1355130561Sobrien{
1356130561Sobrien  const char *name;
135768765Sobrien
1358130561Sobrien  name = d_str (di);
135968765Sobrien
1360130561Sobrien  if (di->send - name < len)
1361130561Sobrien    return NULL;
136268765Sobrien
1363130561Sobrien  d_advance (di, len);
136468765Sobrien
1365130561Sobrien  /* A Java mangled name may have a trailing '$' if it is a C++
1366130561Sobrien     keyword.  This '$' is not included in the length count.  We just
1367130561Sobrien     ignore the '$'.  */
1368130561Sobrien  if ((di->options & DMGL_JAVA) != 0
1369130561Sobrien      && d_peek_char (di) == '$')
1370130561Sobrien    d_advance (di, 1);
137168765Sobrien
1372130561Sobrien  /* Look for something which looks like a gcc encoding of an
1373130561Sobrien     anonymous namespace, and replace it with a more user friendly
1374130561Sobrien     name.  */
1375130561Sobrien  if (len >= (int) ANONYMOUS_NAMESPACE_PREFIX_LEN + 2
1376130561Sobrien      && memcmp (name, ANONYMOUS_NAMESPACE_PREFIX,
1377130561Sobrien		 ANONYMOUS_NAMESPACE_PREFIX_LEN) == 0)
1378130561Sobrien    {
1379130561Sobrien      const char *s;
138068765Sobrien
1381130561Sobrien      s = name + ANONYMOUS_NAMESPACE_PREFIX_LEN;
1382130561Sobrien      if ((*s == '.' || *s == '_' || *s == '$')
1383130561Sobrien	  && s[1] == 'N')
1384130561Sobrien	{
1385130561Sobrien	  di->expansion -= len - sizeof "(anonymous namespace)";
1386130561Sobrien	  return d_make_name (di, "(anonymous namespace)",
1387130561Sobrien			      sizeof "(anonymous namespace)" - 1);
1388130561Sobrien	}
1389130561Sobrien    }
1390130561Sobrien
1391130561Sobrien  return d_make_name (di, name, len);
139268765Sobrien}
139368765Sobrien
1394130561Sobrien/* operator_name ::= many different two character encodings.
1395130561Sobrien                 ::= cv <type>
1396130561Sobrien                 ::= v <digit> <source-name>
1397130561Sobrien*/
139868765Sobrien
1399130561Sobrien#define NL(s) s, (sizeof s) - 1
1400130561Sobrien
1401130561SobrienCP_STATIC_IF_GLIBCPP_V3
1402130561Sobrienconst struct demangle_operator_info cplus_demangle_operators[] =
140368765Sobrien{
1404130561Sobrien  { "aN", NL ("&="),        2 },
1405130561Sobrien  { "aS", NL ("="),         2 },
1406130561Sobrien  { "aa", NL ("&&"),        2 },
1407130561Sobrien  { "ad", NL ("&"),         1 },
1408130561Sobrien  { "an", NL ("&"),         2 },
1409130561Sobrien  { "cl", NL ("()"),        0 },
1410130561Sobrien  { "cm", NL (","),         2 },
1411130561Sobrien  { "co", NL ("~"),         1 },
1412130561Sobrien  { "dV", NL ("/="),        2 },
1413130561Sobrien  { "da", NL ("delete[]"),  1 },
1414130561Sobrien  { "de", NL ("*"),         1 },
1415130561Sobrien  { "dl", NL ("delete"),    1 },
1416130561Sobrien  { "dv", NL ("/"),         2 },
1417130561Sobrien  { "eO", NL ("^="),        2 },
1418130561Sobrien  { "eo", NL ("^"),         2 },
1419130561Sobrien  { "eq", NL ("=="),        2 },
1420130561Sobrien  { "ge", NL (">="),        2 },
1421130561Sobrien  { "gt", NL (">"),         2 },
1422130561Sobrien  { "ix", NL ("[]"),        2 },
1423130561Sobrien  { "lS", NL ("<<="),       2 },
1424130561Sobrien  { "le", NL ("<="),        2 },
1425130561Sobrien  { "ls", NL ("<<"),        2 },
1426130561Sobrien  { "lt", NL ("<"),         2 },
1427130561Sobrien  { "mI", NL ("-="),        2 },
1428130561Sobrien  { "mL", NL ("*="),        2 },
1429130561Sobrien  { "mi", NL ("-"),         2 },
1430130561Sobrien  { "ml", NL ("*"),         2 },
1431130561Sobrien  { "mm", NL ("--"),        1 },
1432130561Sobrien  { "na", NL ("new[]"),     1 },
1433130561Sobrien  { "ne", NL ("!="),        2 },
1434130561Sobrien  { "ng", NL ("-"),         1 },
1435130561Sobrien  { "nt", NL ("!"),         1 },
1436130561Sobrien  { "nw", NL ("new"),       1 },
1437130561Sobrien  { "oR", NL ("|="),        2 },
1438130561Sobrien  { "oo", NL ("||"),        2 },
1439130561Sobrien  { "or", NL ("|"),         2 },
1440130561Sobrien  { "pL", NL ("+="),        2 },
1441130561Sobrien  { "pl", NL ("+"),         2 },
1442130561Sobrien  { "pm", NL ("->*"),       2 },
1443130561Sobrien  { "pp", NL ("++"),        1 },
1444130561Sobrien  { "ps", NL ("+"),         1 },
1445130561Sobrien  { "pt", NL ("->"),        2 },
1446130561Sobrien  { "qu", NL ("?"),         3 },
1447130561Sobrien  { "rM", NL ("%="),        2 },
1448130561Sobrien  { "rS", NL (">>="),       2 },
1449130561Sobrien  { "rm", NL ("%"),         2 },
1450130561Sobrien  { "rs", NL (">>"),        2 },
1451130561Sobrien  { "st", NL ("sizeof "),   1 },
1452130561Sobrien  { "sz", NL ("sizeof "),   1 },
1453130561Sobrien  { NULL, NULL, 0,          0 }
1454130561Sobrien};
145568765Sobrien
1456130561Sobrienstatic struct demangle_component *
1457218822Sdimd_operator_name (struct d_info *di)
1458130561Sobrien{
1459130561Sobrien  char c1;
1460130561Sobrien  char c2;
146168765Sobrien
1462130561Sobrien  c1 = d_next_char (di);
1463130561Sobrien  c2 = d_next_char (di);
1464130561Sobrien  if (c1 == 'v' && IS_DIGIT (c2))
1465130561Sobrien    return d_make_extended_operator (di, c2 - '0', d_source_name (di));
1466130561Sobrien  else if (c1 == 'c' && c2 == 'v')
1467130561Sobrien    return d_make_comp (di, DEMANGLE_COMPONENT_CAST,
1468130561Sobrien			cplus_demangle_type (di), NULL);
1469130561Sobrien  else
147068765Sobrien    {
1471130561Sobrien      /* LOW is the inclusive lower bound.  */
1472130561Sobrien      int low = 0;
1473130561Sobrien      /* HIGH is the exclusive upper bound.  We subtract one to ignore
1474130561Sobrien	 the sentinel at the end of the array.  */
1475130561Sobrien      int high = ((sizeof (cplus_demangle_operators)
1476130561Sobrien		   / sizeof (cplus_demangle_operators[0]))
1477130561Sobrien		  - 1);
147868765Sobrien
1479130561Sobrien      while (1)
148068765Sobrien	{
1481130561Sobrien	  int i;
1482130561Sobrien	  const struct demangle_operator_info *p;
1483130561Sobrien
1484130561Sobrien	  i = low + (high - low) / 2;
1485130561Sobrien	  p = cplus_demangle_operators + i;
1486130561Sobrien
1487130561Sobrien	  if (c1 == p->code[0] && c2 == p->code[1])
1488130561Sobrien	    return d_make_operator (di, p);
1489130561Sobrien
1490130561Sobrien	  if (c1 < p->code[0] || (c1 == p->code[0] && c2 < p->code[1]))
1491130561Sobrien	    high = i;
1492130561Sobrien	  else
1493130561Sobrien	    low = i + 1;
1494130561Sobrien	  if (low == high)
1495130561Sobrien	    return NULL;
149668765Sobrien	}
149768765Sobrien    }
149868765Sobrien}
149968765Sobrien
1500130561Sobrien/* <special-name> ::= TV <type>
1501130561Sobrien                  ::= TT <type>
1502130561Sobrien                  ::= TI <type>
1503130561Sobrien                  ::= TS <type>
1504130561Sobrien                  ::= GV <(object) name>
1505130561Sobrien                  ::= T <call-offset> <(base) encoding>
1506130561Sobrien                  ::= Tc <call-offset> <call-offset> <(base) encoding>
1507130561Sobrien   Also g++ extensions:
1508130561Sobrien                  ::= TC <type> <(offset) number> _ <(base) type>
1509130561Sobrien                  ::= TF <type>
1510130561Sobrien                  ::= TJ <type>
1511130561Sobrien                  ::= GR <name>
1512218822Sdim		  ::= GA <encoding>
1513130561Sobrien*/
151468765Sobrien
1515130561Sobrienstatic struct demangle_component *
1516218822Sdimd_special_name (struct d_info *di)
151768765Sobrien{
1518130561Sobrien  di->expansion += 20;
1519218822Sdim  if (d_check_char (di, 'T'))
152068765Sobrien    {
1521130561Sobrien      switch (d_next_char (di))
1522130561Sobrien	{
1523130561Sobrien	case 'V':
1524130561Sobrien	  di->expansion -= 5;
1525130561Sobrien	  return d_make_comp (di, DEMANGLE_COMPONENT_VTABLE,
1526130561Sobrien			      cplus_demangle_type (di), NULL);
1527130561Sobrien	case 'T':
1528130561Sobrien	  di->expansion -= 10;
1529130561Sobrien	  return d_make_comp (di, DEMANGLE_COMPONENT_VTT,
1530130561Sobrien			      cplus_demangle_type (di), NULL);
1531130561Sobrien	case 'I':
1532130561Sobrien	  return d_make_comp (di, DEMANGLE_COMPONENT_TYPEINFO,
1533130561Sobrien			      cplus_demangle_type (di), NULL);
1534130561Sobrien	case 'S':
1535130561Sobrien	  return d_make_comp (di, DEMANGLE_COMPONENT_TYPEINFO_NAME,
1536130561Sobrien			      cplus_demangle_type (di), NULL);
1537104834Sobrien
1538130561Sobrien	case 'h':
1539130561Sobrien	  if (! d_call_offset (di, 'h'))
1540130561Sobrien	    return NULL;
1541130561Sobrien	  return d_make_comp (di, DEMANGLE_COMPONENT_THUNK,
1542130561Sobrien			      d_encoding (di, 0), NULL);
1543130561Sobrien
1544130561Sobrien	case 'v':
1545130561Sobrien	  if (! d_call_offset (di, 'v'))
1546130561Sobrien	    return NULL;
1547130561Sobrien	  return d_make_comp (di, DEMANGLE_COMPONENT_VIRTUAL_THUNK,
1548130561Sobrien			      d_encoding (di, 0), NULL);
1549130561Sobrien
1550130561Sobrien	case 'c':
1551130561Sobrien	  if (! d_call_offset (di, '\0'))
1552130561Sobrien	    return NULL;
1553130561Sobrien	  if (! d_call_offset (di, '\0'))
1554130561Sobrien	    return NULL;
1555130561Sobrien	  return d_make_comp (di, DEMANGLE_COMPONENT_COVARIANT_THUNK,
1556130561Sobrien			      d_encoding (di, 0), NULL);
1557130561Sobrien
1558130561Sobrien	case 'C':
1559130561Sobrien	  {
1560130561Sobrien	    struct demangle_component *derived_type;
1561130561Sobrien	    long offset;
1562130561Sobrien	    struct demangle_component *base_type;
1563130561Sobrien
1564130561Sobrien	    derived_type = cplus_demangle_type (di);
1565130561Sobrien	    offset = d_number (di);
1566130561Sobrien	    if (offset < 0)
1567130561Sobrien	      return NULL;
1568218822Sdim	    if (! d_check_char (di, '_'))
1569130561Sobrien	      return NULL;
1570130561Sobrien	    base_type = cplus_demangle_type (di);
1571130561Sobrien	    /* We don't display the offset.  FIXME: We should display
1572130561Sobrien	       it in verbose mode.  */
1573130561Sobrien	    di->expansion += 5;
1574130561Sobrien	    return d_make_comp (di, DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE,
1575130561Sobrien				base_type, derived_type);
1576130561Sobrien	  }
1577130561Sobrien
1578130561Sobrien	case 'F':
1579130561Sobrien	  return d_make_comp (di, DEMANGLE_COMPONENT_TYPEINFO_FN,
1580130561Sobrien			      cplus_demangle_type (di), NULL);
1581130561Sobrien	case 'J':
1582130561Sobrien	  return d_make_comp (di, DEMANGLE_COMPONENT_JAVA_CLASS,
1583130561Sobrien			      cplus_demangle_type (di), NULL);
1584130561Sobrien
1585130561Sobrien	default:
1586130561Sobrien	  return NULL;
1587104834Sobrien	}
158868765Sobrien    }
1589218822Sdim  else if (d_check_char (di, 'G'))
159077298Sobrien    {
1591130561Sobrien      switch (d_next_char (di))
1592130561Sobrien	{
1593130561Sobrien	case 'V':
1594130561Sobrien	  return d_make_comp (di, DEMANGLE_COMPONENT_GUARD, d_name (di), NULL);
159577298Sobrien
1596130561Sobrien	case 'R':
1597130561Sobrien	  return d_make_comp (di, DEMANGLE_COMPONENT_REFTEMP, d_name (di),
1598130561Sobrien			      NULL);
1599130561Sobrien
1600218822Sdim	case 'A':
1601218822Sdim	  return d_make_comp (di, DEMANGLE_COMPONENT_HIDDEN_ALIAS,
1602218822Sdim			      d_encoding (di, 0), NULL);
1603218822Sdim
1604130561Sobrien	default:
1605130561Sobrien	  return NULL;
160677298Sobrien	}
160777298Sobrien    }
1608130561Sobrien  else
1609130561Sobrien    return NULL;
161068765Sobrien}
161168765Sobrien
1612130561Sobrien/* <call-offset> ::= h <nv-offset> _
1613130561Sobrien                 ::= v <v-offset> _
161468765Sobrien
1615130561Sobrien   <nv-offset> ::= <(offset) number>
161668765Sobrien
1617130561Sobrien   <v-offset> ::= <(offset) number> _ <(virtual offset) number>
161868765Sobrien
1619130561Sobrien   The C parameter, if not '\0', is a character we just read which is
1620130561Sobrien   the start of the <call-offset>.
162168765Sobrien
1622130561Sobrien   We don't display the offset information anywhere.  FIXME: We should
1623130561Sobrien   display it in verbose mode.  */
162468765Sobrien
1625130561Sobrienstatic int
1626218822Sdimd_call_offset (struct d_info *di, int c)
1627130561Sobrien{
1628130561Sobrien  if (c == '\0')
1629130561Sobrien    c = d_next_char (di);
163068765Sobrien
1631130561Sobrien  if (c == 'h')
1632218822Sdim    d_number (di);
1633130561Sobrien  else if (c == 'v')
163468765Sobrien    {
1635218822Sdim      d_number (di);
1636218822Sdim      if (! d_check_char (di, '_'))
1637130561Sobrien	return 0;
1638218822Sdim      d_number (di);
163968765Sobrien    }
1640130561Sobrien  else
1641130561Sobrien    return 0;
164268765Sobrien
1643218822Sdim  if (! d_check_char (di, '_'))
1644130561Sobrien    return 0;
164568765Sobrien
1646130561Sobrien  return 1;
1647130561Sobrien}
1648130561Sobrien
1649130561Sobrien/* <ctor-dtor-name> ::= C1
1650130561Sobrien                    ::= C2
1651130561Sobrien                    ::= C3
1652130561Sobrien                    ::= D0
1653130561Sobrien                    ::= D1
1654130561Sobrien                    ::= D2
1655130561Sobrien*/
1656130561Sobrien
1657130561Sobrienstatic struct demangle_component *
1658218822Sdimd_ctor_dtor_name (struct d_info *di)
1659130561Sobrien{
1660130561Sobrien  if (di->last_name != NULL)
1661104834Sobrien    {
1662130561Sobrien      if (di->last_name->type == DEMANGLE_COMPONENT_NAME)
1663130561Sobrien	di->expansion += di->last_name->u.s_name.len;
1664130561Sobrien      else if (di->last_name->type == DEMANGLE_COMPONENT_SUB_STD)
1665130561Sobrien	di->expansion += di->last_name->u.s_string.len;
1666104834Sobrien    }
1667218822Sdim  switch (d_peek_char (di))
166868765Sobrien    {
1669130561Sobrien    case 'C':
1670130561Sobrien      {
1671130561Sobrien	enum gnu_v3_ctor_kinds kind;
167268765Sobrien
1673218822Sdim	switch (d_peek_next_char (di))
1674130561Sobrien	  {
1675130561Sobrien	  case '1':
1676130561Sobrien	    kind = gnu_v3_complete_object_ctor;
1677130561Sobrien	    break;
1678130561Sobrien	  case '2':
1679130561Sobrien	    kind = gnu_v3_base_object_ctor;
1680130561Sobrien	    break;
1681130561Sobrien	  case '3':
1682130561Sobrien	    kind = gnu_v3_complete_object_allocating_ctor;
1683130561Sobrien	    break;
1684130561Sobrien	  default:
1685130561Sobrien	    return NULL;
1686130561Sobrien	  }
1687218822Sdim	d_advance (di, 2);
1688130561Sobrien	return d_make_ctor (di, kind, di->last_name);
1689130561Sobrien      }
169068765Sobrien
1691130561Sobrien    case 'D':
1692130561Sobrien      {
1693130561Sobrien	enum gnu_v3_dtor_kinds kind;
169468765Sobrien
1695218822Sdim	switch (d_peek_next_char (di))
1696130561Sobrien	  {
1697130561Sobrien	  case '0':
1698130561Sobrien	    kind = gnu_v3_deleting_dtor;
1699130561Sobrien	    break;
1700130561Sobrien	  case '1':
1701130561Sobrien	    kind = gnu_v3_complete_object_dtor;
1702130561Sobrien	    break;
1703130561Sobrien	  case '2':
1704130561Sobrien	    kind = gnu_v3_base_object_dtor;
1705130561Sobrien	    break;
1706130561Sobrien	  default:
1707130561Sobrien	    return NULL;
1708130561Sobrien	  }
1709218822Sdim	d_advance (di, 2);
1710130561Sobrien	return d_make_dtor (di, kind, di->last_name);
1711130561Sobrien      }
171268765Sobrien
1713130561Sobrien    default:
1714130561Sobrien      return NULL;
171568765Sobrien    }
171668765Sobrien}
171768765Sobrien
1718130561Sobrien/* <type> ::= <builtin-type>
1719130561Sobrien          ::= <function-type>
1720130561Sobrien          ::= <class-enum-type>
1721130561Sobrien          ::= <array-type>
1722130561Sobrien          ::= <pointer-to-member-type>
1723130561Sobrien          ::= <template-param>
1724130561Sobrien          ::= <template-template-param> <template-args>
1725130561Sobrien          ::= <substitution>
1726130561Sobrien          ::= <CV-qualifiers> <type>
1727130561Sobrien          ::= P <type>
1728130561Sobrien          ::= R <type>
1729130561Sobrien          ::= C <type>
1730130561Sobrien          ::= G <type>
1731130561Sobrien          ::= U <source-name> <type>
173277298Sobrien
1733130561Sobrien   <builtin-type> ::= various one letter codes
1734130561Sobrien                  ::= u <source-name>
1735130561Sobrien*/
173677298Sobrien
1737130561SobrienCP_STATIC_IF_GLIBCPP_V3
1738130561Sobrienconst struct demangle_builtin_type_info
1739130561Sobriencplus_demangle_builtin_types[D_BUILTIN_TYPE_COUNT] =
174077298Sobrien{
1741218822Sdim  /* a */ { NL ("signed char"),	NL ("signed char"),	D_PRINT_DEFAULT },
1742130561Sobrien  /* b */ { NL ("bool"),	NL ("boolean"),		D_PRINT_BOOL },
1743218822Sdim  /* c */ { NL ("char"),	NL ("byte"),		D_PRINT_DEFAULT },
1744218822Sdim  /* d */ { NL ("double"),	NL ("double"),		D_PRINT_FLOAT },
1745218822Sdim  /* e */ { NL ("long double"),	NL ("long double"),	D_PRINT_FLOAT },
1746218822Sdim  /* f */ { NL ("float"),	NL ("float"),		D_PRINT_FLOAT },
1747218822Sdim  /* g */ { NL ("__float128"),	NL ("__float128"),	D_PRINT_FLOAT },
1748218822Sdim  /* h */ { NL ("unsigned char"), NL ("unsigned char"),	D_PRINT_DEFAULT },
1749130561Sobrien  /* i */ { NL ("int"),		NL ("int"),		D_PRINT_INT },
1750218822Sdim  /* j */ { NL ("unsigned int"), NL ("unsigned"),	D_PRINT_UNSIGNED },
1751130561Sobrien  /* k */ { NULL, 0,		NULL, 0,		D_PRINT_DEFAULT },
1752130561Sobrien  /* l */ { NL ("long"),	NL ("long"),		D_PRINT_LONG },
1753218822Sdim  /* m */ { NL ("unsigned long"), NL ("unsigned long"),	D_PRINT_UNSIGNED_LONG },
1754130561Sobrien  /* n */ { NL ("__int128"),	NL ("__int128"),	D_PRINT_DEFAULT },
1755218822Sdim  /* o */ { NL ("unsigned __int128"), NL ("unsigned __int128"),
1756218822Sdim	    D_PRINT_DEFAULT },
1757130561Sobrien  /* p */ { NULL, 0,		NULL, 0,		D_PRINT_DEFAULT },
1758130561Sobrien  /* q */ { NULL, 0,		NULL, 0,		D_PRINT_DEFAULT },
1759130561Sobrien  /* r */ { NULL, 0,		NULL, 0,		D_PRINT_DEFAULT },
1760218822Sdim  /* s */ { NL ("short"),	NL ("short"),		D_PRINT_DEFAULT },
1761218822Sdim  /* t */ { NL ("unsigned short"), NL ("unsigned short"), D_PRINT_DEFAULT },
1762130561Sobrien  /* u */ { NULL, 0,		NULL, 0,		D_PRINT_DEFAULT },
1763130561Sobrien  /* v */ { NL ("void"),	NL ("void"),		D_PRINT_VOID },
1764218822Sdim  /* w */ { NL ("wchar_t"),	NL ("char"),		D_PRINT_DEFAULT },
1765218822Sdim  /* x */ { NL ("long long"),	NL ("long"),		D_PRINT_LONG_LONG },
1766218822Sdim  /* y */ { NL ("unsigned long long"), NL ("unsigned long long"),
1767218822Sdim	    D_PRINT_UNSIGNED_LONG_LONG },
1768130561Sobrien  /* z */ { NL ("..."),		NL ("..."),		D_PRINT_DEFAULT },
1769130561Sobrien};
177077298Sobrien
1771130561SobrienCP_STATIC_IF_GLIBCPP_V3
1772130561Sobrienstruct demangle_component *
1773218822Sdimcplus_demangle_type (struct d_info *di)
1774130561Sobrien{
1775130561Sobrien  char peek;
1776130561Sobrien  struct demangle_component *ret;
1777130561Sobrien  int can_subst;
177877298Sobrien
1779130561Sobrien  /* The ABI specifies that when CV-qualifiers are used, the base type
1780130561Sobrien     is substitutable, and the fully qualified type is substitutable,
1781130561Sobrien     but the base type with a strict subset of the CV-qualifiers is
1782130561Sobrien     not substitutable.  The natural recursive implementation of the
1783130561Sobrien     CV-qualifiers would cause subsets to be substitutable, so instead
1784130561Sobrien     we pull them all off now.
178577298Sobrien
1786130561Sobrien     FIXME: The ABI says that order-insensitive vendor qualifiers
1787130561Sobrien     should be handled in the same way, but we have no way to tell
1788130561Sobrien     which vendor qualifiers are order-insensitive and which are
1789130561Sobrien     order-sensitive.  So we just assume that they are all
1790130561Sobrien     order-sensitive.  g++ 3.4 supports only one vendor qualifier,
1791130561Sobrien     __vector, and it treats it as order-sensitive when mangling
1792130561Sobrien     names.  */
1793130561Sobrien
1794130561Sobrien  peek = d_peek_char (di);
1795130561Sobrien  if (peek == 'r' || peek == 'V' || peek == 'K')
179677298Sobrien    {
1797130561Sobrien      struct demangle_component **pret;
1798130561Sobrien
1799130561Sobrien      pret = d_cv_qualifiers (di, &ret, 0);
1800130561Sobrien      if (pret == NULL)
1801130561Sobrien	return NULL;
1802130561Sobrien      *pret = cplus_demangle_type (di);
1803218822Sdim      if (! *pret || ! d_add_substitution (di, ret))
1804130561Sobrien	return NULL;
1805130561Sobrien      return ret;
180677298Sobrien    }
180777298Sobrien
1808130561Sobrien  can_subst = 1;
180977298Sobrien
1810130561Sobrien  switch (peek)
1811130561Sobrien    {
1812130561Sobrien    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
1813130561Sobrien    case 'h': case 'i': case 'j':           case 'l': case 'm': case 'n':
1814130561Sobrien    case 'o':                               case 's': case 't':
1815130561Sobrien    case 'v': case 'w': case 'x': case 'y': case 'z':
1816130561Sobrien      ret = d_make_builtin_type (di,
1817130561Sobrien				 &cplus_demangle_builtin_types[peek - 'a']);
1818130561Sobrien      di->expansion += ret->u.s_builtin.type->len;
1819130561Sobrien      can_subst = 0;
1820130561Sobrien      d_advance (di, 1);
1821130561Sobrien      break;
182277298Sobrien
1823130561Sobrien    case 'u':
1824130561Sobrien      d_advance (di, 1);
1825130561Sobrien      ret = d_make_comp (di, DEMANGLE_COMPONENT_VENDOR_TYPE,
1826130561Sobrien			 d_source_name (di), NULL);
1827130561Sobrien      break;
182877298Sobrien
1829130561Sobrien    case 'F':
1830130561Sobrien      ret = d_function_type (di);
1831130561Sobrien      break;
183277298Sobrien
1833130561Sobrien    case '0': case '1': case '2': case '3': case '4':
1834130561Sobrien    case '5': case '6': case '7': case '8': case '9':
1835130561Sobrien    case 'N':
1836130561Sobrien    case 'Z':
1837130561Sobrien      ret = d_class_enum_type (di);
1838130561Sobrien      break;
183977298Sobrien
1840130561Sobrien    case 'A':
1841130561Sobrien      ret = d_array_type (di);
1842130561Sobrien      break;
184377298Sobrien
1844130561Sobrien    case 'M':
1845130561Sobrien      ret = d_pointer_to_member_type (di);
1846130561Sobrien      break;
184777298Sobrien
1848130561Sobrien    case 'T':
1849130561Sobrien      ret = d_template_param (di);
1850130561Sobrien      if (d_peek_char (di) == 'I')
1851130561Sobrien	{
1852130561Sobrien	  /* This is <template-template-param> <template-args>.  The
1853130561Sobrien	     <template-template-param> part is a substitution
1854130561Sobrien	     candidate.  */
1855130561Sobrien	  if (! d_add_substitution (di, ret))
1856130561Sobrien	    return NULL;
1857130561Sobrien	  ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret,
1858130561Sobrien			     d_template_args (di));
1859130561Sobrien	}
1860130561Sobrien      break;
186177298Sobrien
1862130561Sobrien    case 'S':
1863130561Sobrien      /* If this is a special substitution, then it is the start of
1864130561Sobrien	 <class-enum-type>.  */
1865130561Sobrien      {
1866130561Sobrien	char peek_next;
186777298Sobrien
1868130561Sobrien	peek_next = d_peek_next_char (di);
1869130561Sobrien	if (IS_DIGIT (peek_next)
1870130561Sobrien	    || peek_next == '_'
1871130561Sobrien	    || IS_UPPER (peek_next))
1872130561Sobrien	  {
1873130561Sobrien	    ret = d_substitution (di, 0);
1874130561Sobrien	    /* The substituted name may have been a template name and
1875130561Sobrien	       may be followed by tepmlate args.  */
1876130561Sobrien	    if (d_peek_char (di) == 'I')
1877130561Sobrien	      ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret,
1878130561Sobrien				 d_template_args (di));
1879130561Sobrien	    else
1880130561Sobrien	      can_subst = 0;
1881130561Sobrien	  }
1882130561Sobrien	else
1883130561Sobrien	  {
1884130561Sobrien	    ret = d_class_enum_type (di);
1885130561Sobrien	    /* If the substitution was a complete type, then it is not
1886130561Sobrien	       a new substitution candidate.  However, if the
1887130561Sobrien	       substitution was followed by template arguments, then
1888130561Sobrien	       the whole thing is a substitution candidate.  */
1889130561Sobrien	    if (ret != NULL && ret->type == DEMANGLE_COMPONENT_SUB_STD)
1890130561Sobrien	      can_subst = 0;
1891130561Sobrien	  }
1892130561Sobrien      }
1893130561Sobrien      break;
1894130561Sobrien
1895130561Sobrien    case 'P':
1896130561Sobrien      d_advance (di, 1);
1897130561Sobrien      ret = d_make_comp (di, DEMANGLE_COMPONENT_POINTER,
1898130561Sobrien			 cplus_demangle_type (di), NULL);
1899130561Sobrien      break;
1900130561Sobrien
1901130561Sobrien    case 'R':
1902130561Sobrien      d_advance (di, 1);
1903130561Sobrien      ret = d_make_comp (di, DEMANGLE_COMPONENT_REFERENCE,
1904130561Sobrien			 cplus_demangle_type (di), NULL);
1905130561Sobrien      break;
1906130561Sobrien
1907130561Sobrien    case 'C':
1908130561Sobrien      d_advance (di, 1);
1909130561Sobrien      ret = d_make_comp (di, DEMANGLE_COMPONENT_COMPLEX,
1910130561Sobrien			 cplus_demangle_type (di), NULL);
1911130561Sobrien      break;
1912130561Sobrien
1913130561Sobrien    case 'G':
1914130561Sobrien      d_advance (di, 1);
1915130561Sobrien      ret = d_make_comp (di, DEMANGLE_COMPONENT_IMAGINARY,
1916130561Sobrien			 cplus_demangle_type (di), NULL);
1917130561Sobrien      break;
1918130561Sobrien
1919130561Sobrien    case 'U':
1920130561Sobrien      d_advance (di, 1);
1921130561Sobrien      ret = d_source_name (di);
1922130561Sobrien      ret = d_make_comp (di, DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL,
1923130561Sobrien			 cplus_demangle_type (di), ret);
1924130561Sobrien      break;
1925130561Sobrien
1926130561Sobrien    default:
1927130561Sobrien      return NULL;
1928130561Sobrien    }
1929130561Sobrien
1930130561Sobrien  if (can_subst)
193177298Sobrien    {
1932130561Sobrien      if (! d_add_substitution (di, ret))
1933130561Sobrien	return NULL;
193477298Sobrien    }
193577298Sobrien
1936130561Sobrien  return ret;
193777298Sobrien}
193877298Sobrien
1939130561Sobrien/* <CV-qualifiers> ::= [r] [V] [K]  */
194077298Sobrien
1941130561Sobrienstatic struct demangle_component **
1942218822Sdimd_cv_qualifiers (struct d_info *di,
1943218822Sdim                 struct demangle_component **pret, int member_fn)
194477298Sobrien{
1945130561Sobrien  char peek;
194677298Sobrien
1947130561Sobrien  peek = d_peek_char (di);
1948130561Sobrien  while (peek == 'r' || peek == 'V' || peek == 'K')
194977298Sobrien    {
1950130561Sobrien      enum demangle_component_type t;
195177298Sobrien
1952130561Sobrien      d_advance (di, 1);
1953130561Sobrien      if (peek == 'r')
1954130561Sobrien	{
1955130561Sobrien	  t = (member_fn
1956130561Sobrien	       ? DEMANGLE_COMPONENT_RESTRICT_THIS
1957130561Sobrien	       : DEMANGLE_COMPONENT_RESTRICT);
1958130561Sobrien	  di->expansion += sizeof "restrict";
1959130561Sobrien	}
1960130561Sobrien      else if (peek == 'V')
1961130561Sobrien	{
1962130561Sobrien	  t = (member_fn
1963130561Sobrien	       ? DEMANGLE_COMPONENT_VOLATILE_THIS
1964130561Sobrien	       : DEMANGLE_COMPONENT_VOLATILE);
1965130561Sobrien	  di->expansion += sizeof "volatile";
1966130561Sobrien	}
1967130561Sobrien      else
1968130561Sobrien	{
1969130561Sobrien	  t = (member_fn
1970130561Sobrien	       ? DEMANGLE_COMPONENT_CONST_THIS
1971130561Sobrien	       : DEMANGLE_COMPONENT_CONST);
1972130561Sobrien	  di->expansion += sizeof "const";
1973130561Sobrien	}
197477298Sobrien
1975130561Sobrien      *pret = d_make_comp (di, t, NULL, NULL);
1976130561Sobrien      if (*pret == NULL)
1977130561Sobrien	return NULL;
1978130561Sobrien      pret = &d_left (*pret);
1979130561Sobrien
1980130561Sobrien      peek = d_peek_char (di);
198177298Sobrien    }
198277298Sobrien
1983130561Sobrien  return pret;
198477298Sobrien}
198577298Sobrien
1986130561Sobrien/* <function-type> ::= F [Y] <bare-function-type> E  */
198768765Sobrien
1988130561Sobrienstatic struct demangle_component *
1989218822Sdimd_function_type (struct d_info *di)
1990130561Sobrien{
1991130561Sobrien  struct demangle_component *ret;
199268765Sobrien
1993218822Sdim  if (! d_check_char (di, 'F'))
1994130561Sobrien    return NULL;
1995130561Sobrien  if (d_peek_char (di) == 'Y')
1996130561Sobrien    {
1997130561Sobrien      /* Function has C linkage.  We don't print this information.
1998130561Sobrien	 FIXME: We should print it in verbose mode.  */
1999130561Sobrien      d_advance (di, 1);
2000130561Sobrien    }
2001130561Sobrien  ret = d_bare_function_type (di, 1);
2002218822Sdim  if (! d_check_char (di, 'E'))
2003130561Sobrien    return NULL;
2004130561Sobrien  return ret;
2005130561Sobrien}
200677298Sobrien
2007218822Sdim/* <bare-function-type> ::= [J]<type>+  */
200877298Sobrien
2009130561Sobrienstatic struct demangle_component *
2010218822Sdimd_bare_function_type (struct d_info *di, int has_return_type)
2011130561Sobrien{
2012130561Sobrien  struct demangle_component *return_type;
2013130561Sobrien  struct demangle_component *tl;
2014130561Sobrien  struct demangle_component **ptl;
2015218822Sdim  char peek;
201677298Sobrien
2017218822Sdim  /* Detect special qualifier indicating that the first argument
2018218822Sdim     is the return type.  */
2019218822Sdim  peek = d_peek_char (di);
2020218822Sdim  if (peek == 'J')
2021218822Sdim    {
2022218822Sdim      d_advance (di, 1);
2023218822Sdim      has_return_type = 1;
2024218822Sdim    }
2025218822Sdim
2026130561Sobrien  return_type = NULL;
2027130561Sobrien  tl = NULL;
2028130561Sobrien  ptl = &tl;
2029130561Sobrien  while (1)
2030130561Sobrien    {
2031130561Sobrien      struct demangle_component *type;
203277298Sobrien
2033130561Sobrien      peek = d_peek_char (di);
2034130561Sobrien      if (peek == '\0' || peek == 'E')
2035130561Sobrien	break;
2036130561Sobrien      type = cplus_demangle_type (di);
2037130561Sobrien      if (type == NULL)
2038130561Sobrien	return NULL;
2039130561Sobrien      if (has_return_type)
2040130561Sobrien	{
2041130561Sobrien	  return_type = type;
2042130561Sobrien	  has_return_type = 0;
2043130561Sobrien	}
2044130561Sobrien      else
2045130561Sobrien	{
2046130561Sobrien	  *ptl = d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, type, NULL);
2047130561Sobrien	  if (*ptl == NULL)
2048130561Sobrien	    return NULL;
2049130561Sobrien	  ptl = &d_right (*ptl);
2050130561Sobrien	}
2051130561Sobrien    }
205277298Sobrien
2053130561Sobrien  /* There should be at least one parameter type besides the optional
2054130561Sobrien     return type.  A function which takes no arguments will have a
2055130561Sobrien     single parameter type void.  */
2056130561Sobrien  if (tl == NULL)
2057130561Sobrien    return NULL;
205868765Sobrien
2059130561Sobrien  /* If we have a single parameter type void, omit it.  */
2060130561Sobrien  if (d_right (tl) == NULL
2061130561Sobrien      && d_left (tl)->type == DEMANGLE_COMPONENT_BUILTIN_TYPE
2062130561Sobrien      && d_left (tl)->u.s_builtin.type->print == D_PRINT_VOID)
2063130561Sobrien    {
2064130561Sobrien      di->expansion -= d_left (tl)->u.s_builtin.type->len;
2065130561Sobrien      tl = NULL;
2066130561Sobrien    }
206768765Sobrien
2068130561Sobrien  return d_make_comp (di, DEMANGLE_COMPONENT_FUNCTION_TYPE, return_type, tl);
2069130561Sobrien}
2070130561Sobrien
2071130561Sobrien/* <class-enum-type> ::= <name>  */
2072130561Sobrien
2073130561Sobrienstatic struct demangle_component *
2074218822Sdimd_class_enum_type (struct d_info *di)
207568765Sobrien{
2076130561Sobrien  return d_name (di);
2077130561Sobrien}
207868765Sobrien
2079130561Sobrien/* <array-type> ::= A <(positive dimension) number> _ <(element) type>
2080130561Sobrien                ::= A [<(dimension) expression>] _ <(element) type>
2081130561Sobrien*/
208268765Sobrien
2083130561Sobrienstatic struct demangle_component *
2084218822Sdimd_array_type (struct d_info *di)
2085130561Sobrien{
2086130561Sobrien  char peek;
2087130561Sobrien  struct demangle_component *dim;
2088130561Sobrien
2089218822Sdim  if (! d_check_char (di, 'A'))
2090130561Sobrien    return NULL;
2091130561Sobrien
2092130561Sobrien  peek = d_peek_char (di);
2093130561Sobrien  if (peek == '_')
2094130561Sobrien    dim = NULL;
2095130561Sobrien  else if (IS_DIGIT (peek))
209668765Sobrien    {
2097130561Sobrien      const char *s;
2098130561Sobrien
2099130561Sobrien      s = d_str (di);
2100130561Sobrien      do
210189857Sobrien	{
2102130561Sobrien	  d_advance (di, 1);
2103130561Sobrien	  peek = d_peek_char (di);
210489857Sobrien	}
2105130561Sobrien      while (IS_DIGIT (peek));
2106130561Sobrien      dim = d_make_name (di, s, d_str (di) - s);
2107130561Sobrien      if (dim == NULL)
2108130561Sobrien	return NULL;
210968765Sobrien    }
2110130561Sobrien  else
211168765Sobrien    {
2112130561Sobrien      dim = d_expression (di);
2113130561Sobrien      if (dim == NULL)
2114130561Sobrien	return NULL;
2115130561Sobrien    }
211668765Sobrien
2117218822Sdim  if (! d_check_char (di, '_'))
2118130561Sobrien    return NULL;
211968765Sobrien
2120130561Sobrien  return d_make_comp (di, DEMANGLE_COMPONENT_ARRAY_TYPE, dim,
2121130561Sobrien		      cplus_demangle_type (di));
2122130561Sobrien}
212368765Sobrien
2124130561Sobrien/* <pointer-to-member-type> ::= M <(class) type> <(member) type>  */
212568765Sobrien
2126130561Sobrienstatic struct demangle_component *
2127218822Sdimd_pointer_to_member_type (struct d_info *di)
2128130561Sobrien{
2129130561Sobrien  struct demangle_component *cl;
2130130561Sobrien  struct demangle_component *mem;
2131130561Sobrien  struct demangle_component **pmem;
213268765Sobrien
2133218822Sdim  if (! d_check_char (di, 'M'))
2134130561Sobrien    return NULL;
213568765Sobrien
2136130561Sobrien  cl = cplus_demangle_type (di);
213768765Sobrien
2138130561Sobrien  /* The ABI specifies that any type can be a substitution source, and
2139130561Sobrien     that M is followed by two types, and that when a CV-qualified
2140130561Sobrien     type is seen both the base type and the CV-qualified types are
2141130561Sobrien     substitution sources.  The ABI also specifies that for a pointer
2142130561Sobrien     to a CV-qualified member function, the qualifiers are attached to
2143130561Sobrien     the second type.  Given the grammar, a plain reading of the ABI
2144130561Sobrien     suggests that both the CV-qualified member function and the
2145130561Sobrien     non-qualified member function are substitution sources.  However,
2146130561Sobrien     g++ does not work that way.  g++ treats only the CV-qualified
2147130561Sobrien     member function as a substitution source.  FIXME.  So to work
2148130561Sobrien     with g++, we need to pull off the CV-qualifiers here, in order to
2149218822Sdim     avoid calling add_substitution() in cplus_demangle_type().  But
2150218822Sdim     for a CV-qualified member which is not a function, g++ does
2151218822Sdim     follow the ABI, so we need to handle that case here by calling
2152218822Sdim     d_add_substitution ourselves.  */
215368765Sobrien
2154130561Sobrien  pmem = d_cv_qualifiers (di, &mem, 1);
2155130561Sobrien  if (pmem == NULL)
2156130561Sobrien    return NULL;
2157130561Sobrien  *pmem = cplus_demangle_type (di);
2158218822Sdim  if (*pmem == NULL)
2159218822Sdim    return NULL;
216068765Sobrien
2161218822Sdim  if (pmem != &mem && (*pmem)->type != DEMANGLE_COMPONENT_FUNCTION_TYPE)
2162218822Sdim    {
2163218822Sdim      if (! d_add_substitution (di, mem))
2164218822Sdim	return NULL;
2165218822Sdim    }
2166218822Sdim
2167130561Sobrien  return d_make_comp (di, DEMANGLE_COMPONENT_PTRMEM_TYPE, cl, mem);
2168130561Sobrien}
216968765Sobrien
2170130561Sobrien/* <template-param> ::= T_
2171130561Sobrien                    ::= T <(parameter-2 non-negative) number> _
2172130561Sobrien*/
217377298Sobrien
2174130561Sobrienstatic struct demangle_component *
2175218822Sdimd_template_param (struct d_info *di)
2176130561Sobrien{
2177130561Sobrien  long param;
217868765Sobrien
2179218822Sdim  if (! d_check_char (di, 'T'))
2180130561Sobrien    return NULL;
218168765Sobrien
2182130561Sobrien  if (d_peek_char (di) == '_')
2183130561Sobrien    param = 0;
2184130561Sobrien  else
2185130561Sobrien    {
2186130561Sobrien      param = d_number (di);
2187130561Sobrien      if (param < 0)
2188130561Sobrien	return NULL;
2189130561Sobrien      param += 1;
2190130561Sobrien    }
219168765Sobrien
2192218822Sdim  if (! d_check_char (di, '_'))
2193130561Sobrien    return NULL;
219468765Sobrien
2195130561Sobrien  ++di->did_subs;
219668765Sobrien
2197130561Sobrien  return d_make_template_param (di, param);
2198130561Sobrien}
219968765Sobrien
2200130561Sobrien/* <template-args> ::= I <template-arg>+ E  */
220168765Sobrien
2202130561Sobrienstatic struct demangle_component *
2203218822Sdimd_template_args (struct d_info *di)
2204130561Sobrien{
2205130561Sobrien  struct demangle_component *hold_last_name;
2206130561Sobrien  struct demangle_component *al;
2207130561Sobrien  struct demangle_component **pal;
2208130561Sobrien
2209130561Sobrien  /* Preserve the last name we saw--don't let the template arguments
2210130561Sobrien     clobber it, as that would give us the wrong name for a subsequent
2211130561Sobrien     constructor or destructor.  */
2212130561Sobrien  hold_last_name = di->last_name;
2213130561Sobrien
2214218822Sdim  if (! d_check_char (di, 'I'))
2215130561Sobrien    return NULL;
2216130561Sobrien
2217130561Sobrien  al = NULL;
2218130561Sobrien  pal = &al;
2219130561Sobrien  while (1)
2220130561Sobrien    {
2221130561Sobrien      struct demangle_component *a;
2222130561Sobrien
2223130561Sobrien      a = d_template_arg (di);
2224130561Sobrien      if (a == NULL)
2225130561Sobrien	return NULL;
2226130561Sobrien
2227130561Sobrien      *pal = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, a, NULL);
2228130561Sobrien      if (*pal == NULL)
2229130561Sobrien	return NULL;
2230130561Sobrien      pal = &d_right (*pal);
2231130561Sobrien
2232130561Sobrien      if (d_peek_char (di) == 'E')
2233130561Sobrien	{
2234130561Sobrien	  d_advance (di, 1);
2235130561Sobrien	  break;
223668765Sobrien	}
223768765Sobrien    }
223868765Sobrien
2239130561Sobrien  di->last_name = hold_last_name;
2240130561Sobrien
2241130561Sobrien  return al;
224268765Sobrien}
224368765Sobrien
2244130561Sobrien/* <template-arg> ::= <type>
2245130561Sobrien                  ::= X <expression> E
2246130561Sobrien                  ::= <expr-primary>
2247130561Sobrien*/
224868765Sobrien
2249130561Sobrienstatic struct demangle_component *
2250218822Sdimd_template_arg (struct d_info *di)
225168765Sobrien{
2252130561Sobrien  struct demangle_component *ret;
225368765Sobrien
2254130561Sobrien  switch (d_peek_char (di))
2255130561Sobrien    {
2256130561Sobrien    case 'X':
2257130561Sobrien      d_advance (di, 1);
2258130561Sobrien      ret = d_expression (di);
2259218822Sdim      if (! d_check_char (di, 'E'))
2260130561Sobrien	return NULL;
2261130561Sobrien      return ret;
226268765Sobrien
2263130561Sobrien    case 'L':
2264130561Sobrien      return d_expr_primary (di);
2265130561Sobrien
2266130561Sobrien    default:
2267130561Sobrien      return cplus_demangle_type (di);
2268130561Sobrien    }
2269130561Sobrien}
2270130561Sobrien
2271130561Sobrien/* <expression> ::= <(unary) operator-name> <expression>
2272130561Sobrien                ::= <(binary) operator-name> <expression> <expression>
2273130561Sobrien                ::= <(trinary) operator-name> <expression> <expression> <expression>
2274130561Sobrien                ::= st <type>
2275130561Sobrien                ::= <template-param>
2276130561Sobrien                ::= sr <type> <unqualified-name>
2277130561Sobrien                ::= sr <type> <unqualified-name> <template-args>
2278130561Sobrien                ::= <expr-primary>
2279130561Sobrien*/
2280130561Sobrien
2281130561Sobrienstatic struct demangle_component *
2282218822Sdimd_expression (struct d_info *di)
2283130561Sobrien{
2284130561Sobrien  char peek;
2285130561Sobrien
2286130561Sobrien  peek = d_peek_char (di);
2287130561Sobrien  if (peek == 'L')
2288130561Sobrien    return d_expr_primary (di);
2289130561Sobrien  else if (peek == 'T')
2290130561Sobrien    return d_template_param (di);
2291130561Sobrien  else if (peek == 's' && d_peek_next_char (di) == 'r')
229268765Sobrien    {
2293130561Sobrien      struct demangle_component *type;
2294130561Sobrien      struct demangle_component *name;
2295130561Sobrien
2296130561Sobrien      d_advance (di, 2);
2297130561Sobrien      type = cplus_demangle_type (di);
2298130561Sobrien      name = d_unqualified_name (di);
2299130561Sobrien      if (d_peek_char (di) != 'I')
2300130561Sobrien	return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type, name);
2301130561Sobrien      else
2302130561Sobrien	return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type,
2303130561Sobrien			    d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name,
2304130561Sobrien					 d_template_args (di)));
230568765Sobrien    }
2306130561Sobrien  else
230768765Sobrien    {
2308130561Sobrien      struct demangle_component *op;
2309130561Sobrien      int args;
2310130561Sobrien
2311130561Sobrien      op = d_operator_name (di);
2312130561Sobrien      if (op == NULL)
2313130561Sobrien	return NULL;
2314130561Sobrien
2315130561Sobrien      if (op->type == DEMANGLE_COMPONENT_OPERATOR)
2316130561Sobrien	di->expansion += op->u.s_operator.op->len - 2;
2317130561Sobrien
2318130561Sobrien      if (op->type == DEMANGLE_COMPONENT_OPERATOR
2319130561Sobrien	  && strcmp (op->u.s_operator.op->code, "st") == 0)
2320130561Sobrien	return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
2321130561Sobrien			    cplus_demangle_type (di));
2322130561Sobrien
2323130561Sobrien      switch (op->type)
232489857Sobrien	{
2325130561Sobrien	default:
2326130561Sobrien	  return NULL;
2327130561Sobrien	case DEMANGLE_COMPONENT_OPERATOR:
2328130561Sobrien	  args = op->u.s_operator.op->args;
232989857Sobrien	  break;
2330130561Sobrien	case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
2331130561Sobrien	  args = op->u.s_extended_operator.args;
233289857Sobrien	  break;
2333130561Sobrien	case DEMANGLE_COMPONENT_CAST:
2334130561Sobrien	  args = 1;
233589857Sobrien	  break;
233689857Sobrien	}
2337130561Sobrien
2338130561Sobrien      switch (args)
233968765Sobrien	{
2340130561Sobrien	case 1:
2341130561Sobrien	  return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
2342130561Sobrien			      d_expression (di));
2343130561Sobrien	case 2:
2344130561Sobrien	  {
2345130561Sobrien	    struct demangle_component *left;
2346130561Sobrien
2347130561Sobrien	    left = d_expression (di);
2348130561Sobrien	    return d_make_comp (di, DEMANGLE_COMPONENT_BINARY, op,
2349130561Sobrien				d_make_comp (di,
2350130561Sobrien					     DEMANGLE_COMPONENT_BINARY_ARGS,
2351130561Sobrien					     left,
2352130561Sobrien					     d_expression (di)));
2353130561Sobrien	  }
2354130561Sobrien	case 3:
2355130561Sobrien	  {
2356130561Sobrien	    struct demangle_component *first;
2357130561Sobrien	    struct demangle_component *second;
2358130561Sobrien
2359130561Sobrien	    first = d_expression (di);
2360130561Sobrien	    second = d_expression (di);
2361130561Sobrien	    return d_make_comp (di, DEMANGLE_COMPONENT_TRINARY, op,
2362130561Sobrien				d_make_comp (di,
2363130561Sobrien					     DEMANGLE_COMPONENT_TRINARY_ARG1,
2364130561Sobrien					     first,
2365130561Sobrien					     d_make_comp (di,
2366130561Sobrien							  DEMANGLE_COMPONENT_TRINARY_ARG2,
2367130561Sobrien							  second,
2368130561Sobrien							  d_expression (di))));
2369130561Sobrien	  }
2370130561Sobrien	default:
2371130561Sobrien	  return NULL;
237268765Sobrien	}
237368765Sobrien    }
2374130561Sobrien}
2375130561Sobrien
2376130561Sobrien/* <expr-primary> ::= L <type> <(value) number> E
2377130561Sobrien                  ::= L <type> <(value) float> E
2378130561Sobrien                  ::= L <mangled-name> E
2379130561Sobrien*/
2380130561Sobrien
2381130561Sobrienstatic struct demangle_component *
2382218822Sdimd_expr_primary (struct d_info *di)
2383130561Sobrien{
2384130561Sobrien  struct demangle_component *ret;
2385130561Sobrien
2386218822Sdim  if (! d_check_char (di, 'L'))
2387130561Sobrien    return NULL;
2388130561Sobrien  if (d_peek_char (di) == '_')
2389130561Sobrien    ret = cplus_demangle_mangled_name (di, 0);
239068765Sobrien  else
2391130561Sobrien    {
2392130561Sobrien      struct demangle_component *type;
2393130561Sobrien      enum demangle_component_type t;
2394130561Sobrien      const char *s;
239568765Sobrien
2396130561Sobrien      type = cplus_demangle_type (di);
2397175790Sobrien      if (type == NULL)
2398175790Sobrien	return NULL;
239968765Sobrien
2400130561Sobrien      /* If we have a type we know how to print, we aren't going to
2401130561Sobrien	 print the type name itself.  */
2402130561Sobrien      if (type->type == DEMANGLE_COMPONENT_BUILTIN_TYPE
2403130561Sobrien	  && type->u.s_builtin.type->print != D_PRINT_DEFAULT)
2404130561Sobrien	di->expansion -= type->u.s_builtin.type->len;
240568765Sobrien
2406130561Sobrien      /* Rather than try to interpret the literal value, we just
2407130561Sobrien	 collect it as a string.  Note that it's possible to have a
2408130561Sobrien	 floating point literal here.  The ABI specifies that the
2409130561Sobrien	 format of such literals is machine independent.  That's fine,
2410130561Sobrien	 but what's not fine is that versions of g++ up to 3.2 with
2411130561Sobrien	 -fabi-version=1 used upper case letters in the hex constant,
2412130561Sobrien	 and dumped out gcc's internal representation.  That makes it
2413130561Sobrien	 hard to tell where the constant ends, and hard to dump the
2414130561Sobrien	 constant in any readable form anyhow.  We don't attempt to
2415130561Sobrien	 handle these cases.  */
241677298Sobrien
2417130561Sobrien      t = DEMANGLE_COMPONENT_LITERAL;
2418130561Sobrien      if (d_peek_char (di) == 'n')
2419130561Sobrien	{
2420130561Sobrien	  t = DEMANGLE_COMPONENT_LITERAL_NEG;
2421130561Sobrien	  d_advance (di, 1);
2422130561Sobrien	}
2423130561Sobrien      s = d_str (di);
2424130561Sobrien      while (d_peek_char (di) != 'E')
2425218822Sdim	{
2426218822Sdim	  if (d_peek_char (di) == '\0')
2427218822Sdim	    return NULL;
2428218822Sdim	  d_advance (di, 1);
2429218822Sdim	}
2430130561Sobrien      ret = d_make_comp (di, t, type, d_make_name (di, s, d_str (di) - s));
2431130561Sobrien    }
2432218822Sdim  if (! d_check_char (di, 'E'))
2433130561Sobrien    return NULL;
2434130561Sobrien  return ret;
2435130561Sobrien}
243677298Sobrien
2437130561Sobrien/* <local-name> ::= Z <(function) encoding> E <(entity) name> [<discriminator>]
2438130561Sobrien                ::= Z <(function) encoding> E s [<discriminator>]
2439130561Sobrien*/
244068765Sobrien
2441130561Sobrienstatic struct demangle_component *
2442218822Sdimd_local_name (struct d_info *di)
244368765Sobrien{
2444130561Sobrien  struct demangle_component *function;
244568765Sobrien
2446218822Sdim  if (! d_check_char (di, 'Z'))
2447130561Sobrien    return NULL;
244868765Sobrien
2449130561Sobrien  function = d_encoding (di, 0);
245068765Sobrien
2451218822Sdim  if (! d_check_char (di, 'E'))
2452130561Sobrien    return NULL;
245368765Sobrien
2454130561Sobrien  if (d_peek_char (di) == 's')
245577298Sobrien    {
2456130561Sobrien      d_advance (di, 1);
2457130561Sobrien      if (! d_discriminator (di))
2458130561Sobrien	return NULL;
2459130561Sobrien      return d_make_comp (di, DEMANGLE_COMPONENT_LOCAL_NAME, function,
2460130561Sobrien			  d_make_name (di, "string literal",
2461130561Sobrien				       sizeof "string literal" - 1));
2462130561Sobrien    }
2463130561Sobrien  else
2464130561Sobrien    {
2465130561Sobrien      struct demangle_component *name;
246668765Sobrien
2467130561Sobrien      name = d_name (di);
2468130561Sobrien      if (! d_discriminator (di))
2469130561Sobrien	return NULL;
2470130561Sobrien      return d_make_comp (di, DEMANGLE_COMPONENT_LOCAL_NAME, function, name);
2471130561Sobrien    }
2472130561Sobrien}
247368765Sobrien
2474130561Sobrien/* <discriminator> ::= _ <(non-negative) number>
247568765Sobrien
2476130561Sobrien   We demangle the discriminator, but we don't print it out.  FIXME:
2477130561Sobrien   We should print it out in verbose mode.  */
247877298Sobrien
2479130561Sobrienstatic int
2480218822Sdimd_discriminator (struct d_info *di)
2481130561Sobrien{
2482130561Sobrien  long discrim;
248377298Sobrien
2484130561Sobrien  if (d_peek_char (di) != '_')
2485130561Sobrien    return 1;
2486130561Sobrien  d_advance (di, 1);
2487130561Sobrien  discrim = d_number (di);
2488130561Sobrien  if (discrim < 0)
2489130561Sobrien    return 0;
2490130561Sobrien  return 1;
2491130561Sobrien}
249277298Sobrien
2493130561Sobrien/* Add a new substitution.  */
2494130561Sobrien
2495130561Sobrienstatic int
2496218822Sdimd_add_substitution (struct d_info *di, struct demangle_component *dc)
2497130561Sobrien{
2498130561Sobrien  if (dc == NULL)
2499130561Sobrien    return 0;
2500130561Sobrien  if (di->next_sub >= di->num_subs)
2501130561Sobrien    return 0;
2502130561Sobrien  di->subs[di->next_sub] = dc;
2503130561Sobrien  ++di->next_sub;
2504130561Sobrien  return 1;
250568765Sobrien}
250668765Sobrien
2507130561Sobrien/* <substitution> ::= S <seq-id> _
2508130561Sobrien                  ::= S_
2509130561Sobrien                  ::= St
2510130561Sobrien                  ::= Sa
2511130561Sobrien                  ::= Sb
2512130561Sobrien                  ::= Ss
2513130561Sobrien                  ::= Si
2514130561Sobrien                  ::= So
2515130561Sobrien                  ::= Sd
251668765Sobrien
2517130561Sobrien   If PREFIX is non-zero, then this type is being used as a prefix in
2518130561Sobrien   a qualified name.  In this case, for the standard substitutions, we
2519130561Sobrien   need to check whether we are being used as a prefix for a
2520130561Sobrien   constructor or destructor, and return a full template name.
2521130561Sobrien   Otherwise we will get something like std::iostream::~iostream()
2522130561Sobrien   which does not correspond particularly well to any function which
2523130561Sobrien   actually appears in the source.
2524130561Sobrien*/
252568765Sobrien
2526130561Sobrienstatic const struct d_standard_sub_info standard_subs[] =
252768765Sobrien{
2528130561Sobrien  { 't', NL ("std"),
2529130561Sobrien    NL ("std"),
2530130561Sobrien    NULL, 0 },
2531130561Sobrien  { 'a', NL ("std::allocator"),
2532130561Sobrien    NL ("std::allocator"),
2533130561Sobrien    NL ("allocator") },
2534130561Sobrien  { 'b', NL ("std::basic_string"),
2535130561Sobrien    NL ("std::basic_string"),
2536130561Sobrien    NL ("basic_string") },
2537130561Sobrien  { 's', NL ("std::string"),
2538130561Sobrien    NL ("std::basic_string<char, std::char_traits<char>, std::allocator<char> >"),
2539130561Sobrien    NL ("basic_string") },
2540130561Sobrien  { 'i', NL ("std::istream"),
2541130561Sobrien    NL ("std::basic_istream<char, std::char_traits<char> >"),
2542130561Sobrien    NL ("basic_istream") },
2543130561Sobrien  { 'o', NL ("std::ostream"),
2544130561Sobrien    NL ("std::basic_ostream<char, std::char_traits<char> >"),
2545130561Sobrien    NL ("basic_ostream") },
2546130561Sobrien  { 'd', NL ("std::iostream"),
2547130561Sobrien    NL ("std::basic_iostream<char, std::char_traits<char> >"),
2548130561Sobrien    NL ("basic_iostream") }
2549130561Sobrien};
255068765Sobrien
2551130561Sobrienstatic struct demangle_component *
2552218822Sdimd_substitution (struct d_info *di, int prefix)
2553130561Sobrien{
2554130561Sobrien  char c;
255577298Sobrien
2556218822Sdim  if (! d_check_char (di, 'S'))
2557130561Sobrien    return NULL;
255868765Sobrien
2559130561Sobrien  c = d_next_char (di);
2560130561Sobrien  if (c == '_' || IS_DIGIT (c) || IS_UPPER (c))
256168765Sobrien    {
2562130561Sobrien      int id;
2563130561Sobrien
2564130561Sobrien      id = 0;
2565130561Sobrien      if (c != '_')
256668765Sobrien	{
2567130561Sobrien	  do
2568130561Sobrien	    {
2569130561Sobrien	      if (IS_DIGIT (c))
2570130561Sobrien		id = id * 36 + c - '0';
2571130561Sobrien	      else if (IS_UPPER (c))
2572130561Sobrien		id = id * 36 + c - 'A' + 10;
2573130561Sobrien	      else
2574130561Sobrien		return NULL;
2575218822Sdim	      if (id < 0)
2576218822Sdim		return NULL;
2577130561Sobrien	      c = d_next_char (di);
2578130561Sobrien	    }
2579130561Sobrien	  while (c != '_');
258068765Sobrien
2581130561Sobrien	  ++id;
2582130561Sobrien	}
258368765Sobrien
2584130561Sobrien      if (id >= di->next_sub)
2585130561Sobrien	return NULL;
258668765Sobrien
2587130561Sobrien      ++di->did_subs;
258868765Sobrien
2589130561Sobrien      return di->subs[id];
2590130561Sobrien    }
2591130561Sobrien  else
2592130561Sobrien    {
2593130561Sobrien      int verbose;
2594130561Sobrien      const struct d_standard_sub_info *p;
2595130561Sobrien      const struct d_standard_sub_info *pend;
259668765Sobrien
2597130561Sobrien      verbose = (di->options & DMGL_VERBOSE) != 0;
2598130561Sobrien      if (! verbose && prefix)
2599130561Sobrien	{
2600130561Sobrien	  char peek;
260168765Sobrien
2602130561Sobrien	  peek = d_peek_char (di);
2603130561Sobrien	  if (peek == 'C' || peek == 'D')
2604130561Sobrien	    verbose = 1;
2605130561Sobrien	}
260668765Sobrien
2607130561Sobrien      pend = (&standard_subs[0]
2608130561Sobrien	      + sizeof standard_subs / sizeof standard_subs[0]);
2609130561Sobrien      for (p = &standard_subs[0]; p < pend; ++p)
2610130561Sobrien	{
2611130561Sobrien	  if (c == p->code)
2612130561Sobrien	    {
2613130561Sobrien	      const char *s;
2614130561Sobrien	      int len;
261577298Sobrien
2616130561Sobrien	      if (p->set_last_name != NULL)
2617130561Sobrien		di->last_name = d_make_sub (di, p->set_last_name,
2618130561Sobrien					    p->set_last_name_len);
2619130561Sobrien	      if (verbose)
2620130561Sobrien		{
2621130561Sobrien		  s = p->full_expansion;
2622130561Sobrien		  len = p->full_len;
2623130561Sobrien		}
2624130561Sobrien	      else
2625130561Sobrien		{
2626130561Sobrien		  s = p->simple_expansion;
2627130561Sobrien		  len = p->simple_len;
2628130561Sobrien		}
2629130561Sobrien	      di->expansion += len;
2630130561Sobrien	      return d_make_sub (di, s, len);
2631130561Sobrien	    }
2632130561Sobrien	}
263377298Sobrien
2634130561Sobrien      return NULL;
2635130561Sobrien    }
2636130561Sobrien}
263777298Sobrien
2638218822Sdim/* Initialize a growable string.  */
263968765Sobrien
2640130561Sobrienstatic void
2641218822Sdimd_growable_string_init (struct d_growable_string *dgs, size_t estimate)
2642130561Sobrien{
2643218822Sdim  dgs->buf = NULL;
2644218822Sdim  dgs->len = 0;
2645218822Sdim  dgs->alc = 0;
2646218822Sdim  dgs->allocation_failure = 0;
264777298Sobrien
2648218822Sdim  if (estimate > 0)
2649218822Sdim    d_growable_string_resize (dgs, estimate);
2650218822Sdim}
2651218822Sdim
2652218822Sdim/* Grow a growable string to a given size.  */
2653218822Sdim
2654218822Sdimstatic inline void
2655218822Sdimd_growable_string_resize (struct d_growable_string *dgs, size_t need)
2656218822Sdim{
2657218822Sdim  size_t newalc;
2658218822Sdim  char *newbuf;
2659218822Sdim
2660218822Sdim  if (dgs->allocation_failure)
2661130561Sobrien    return;
2662218822Sdim
2663218822Sdim  /* Start allocation at two bytes to avoid any possibility of confusion
2664218822Sdim     with the special value of 1 used as a return in *palc to indicate
2665218822Sdim     allocation failures.  */
2666218822Sdim  newalc = dgs->alc > 0 ? dgs->alc : 2;
2667218822Sdim  while (newalc < need)
2668218822Sdim    newalc <<= 1;
2669218822Sdim
2670218822Sdim  newbuf = (char *) realloc (dgs->buf, newalc);
2671218822Sdim  if (newbuf == NULL)
2672130561Sobrien    {
2673218822Sdim      free (dgs->buf);
2674218822Sdim      dgs->buf = NULL;
2675218822Sdim      dgs->len = 0;
2676218822Sdim      dgs->alc = 0;
2677218822Sdim      dgs->allocation_failure = 1;
2678218822Sdim      return;
2679130561Sobrien    }
2680218822Sdim  dgs->buf = newbuf;
2681218822Sdim  dgs->alc = newalc;
2682130561Sobrien}
268368765Sobrien
2684218822Sdim/* Append a buffer to a growable string.  */
268568765Sobrien
2686218822Sdimstatic inline void
2687218822Sdimd_growable_string_append_buffer (struct d_growable_string *dgs,
2688218822Sdim                                 const char *s, size_t l)
2689130561Sobrien{
2690218822Sdim  size_t need;
269168765Sobrien
2692218822Sdim  need = dgs->len + l + 1;
2693218822Sdim  if (need > dgs->alc)
2694218822Sdim    d_growable_string_resize (dgs, need);
2695218822Sdim
2696218822Sdim  if (dgs->allocation_failure)
2697218822Sdim    return;
2698218822Sdim
2699218822Sdim  memcpy (dgs->buf + dgs->len, s, l);
2700218822Sdim  dgs->buf[dgs->len + l] = '\0';
2701218822Sdim  dgs->len += l;
2702130561Sobrien}
270368765Sobrien
2704218822Sdim/* Bridge growable strings to the callback mechanism.  */
270568765Sobrien
2706130561Sobrienstatic void
2707218822Sdimd_growable_string_callback_adapter (const char *s, size_t l, void *opaque)
2708130561Sobrien{
2709218822Sdim  struct d_growable_string *dgs = (struct d_growable_string*) opaque;
271068765Sobrien
2711218822Sdim  d_growable_string_append_buffer (dgs, s, l);
2712130561Sobrien}
271368765Sobrien
2714218822Sdim/* Initialize a print information structure.  */
271568765Sobrien
2716130561Sobrienstatic void
2717218822Sdimd_print_init (struct d_print_info *dpi, int options,
2718218822Sdim              demangle_callbackref callback, void *opaque)
2719130561Sobrien{
2720218822Sdim  dpi->options = options;
2721218822Sdim  dpi->len = 0;
2722218822Sdim  dpi->last_char = '\0';
2723218822Sdim  dpi->templates = NULL;
2724218822Sdim  dpi->modifiers = NULL;
2725218822Sdim
2726218822Sdim  dpi->callback = callback;
2727218822Sdim  dpi->opaque = opaque;
2728218822Sdim
2729218822Sdim  dpi->demangle_failure = 0;
273068765Sobrien}
273168765Sobrien
2732218822Sdim/* Indicate that an error occurred during printing, and test for error.  */
2733218822Sdim
2734218822Sdimstatic inline void
2735218822Sdimd_print_error (struct d_print_info *dpi)
2736218822Sdim{
2737218822Sdim  dpi->demangle_failure = 1;
2738218822Sdim}
2739218822Sdim
2740218822Sdimstatic inline int
2741218822Sdimd_print_saw_error (struct d_print_info *dpi)
2742218822Sdim{
2743218822Sdim  return dpi->demangle_failure != 0;
2744218822Sdim}
2745218822Sdim
2746218822Sdim/* Flush buffered characters to the callback.  */
2747218822Sdim
2748218822Sdimstatic inline void
2749218822Sdimd_print_flush (struct d_print_info *dpi)
2750218822Sdim{
2751218822Sdim  dpi->buf[dpi->len] = '\0';
2752218822Sdim  dpi->callback (dpi->buf, dpi->len, dpi->opaque);
2753218822Sdim  dpi->len = 0;
2754218822Sdim}
2755218822Sdim
2756218822Sdim/* Append characters and buffers for printing.  */
2757218822Sdim
2758218822Sdimstatic inline void
2759218822Sdimd_append_char (struct d_print_info *dpi, char c)
2760218822Sdim{
2761218822Sdim  if (dpi->len == sizeof (dpi->buf) - 1)
2762218822Sdim    d_print_flush (dpi);
2763218822Sdim
2764218822Sdim  dpi->buf[dpi->len++] = c;
2765218822Sdim  dpi->last_char = c;
2766218822Sdim}
2767218822Sdim
2768218822Sdimstatic inline void
2769218822Sdimd_append_buffer (struct d_print_info *dpi, const char *s, size_t l)
2770218822Sdim{
2771218822Sdim  size_t i;
2772218822Sdim
2773218822Sdim  for (i = 0; i < l; i++)
2774218822Sdim    d_append_char (dpi, s[i]);
2775218822Sdim}
2776218822Sdim
2777218822Sdimstatic inline void
2778218822Sdimd_append_string (struct d_print_info *dpi, const char *s)
2779218822Sdim{
2780218822Sdim  d_append_buffer (dpi, s, strlen (s));
2781218822Sdim}
2782218822Sdim
2783218822Sdimstatic inline char
2784218822Sdimd_last_char (struct d_print_info *dpi)
2785218822Sdim{
2786218822Sdim  return dpi->last_char;
2787218822Sdim}
2788218822Sdim
2789130561Sobrien/* Turn components into a human readable string.  OPTIONS is the
2790130561Sobrien   options bits passed to the demangler.  DC is the tree to print.
2791218822Sdim   CALLBACK is a function to call to flush demangled string segments
2792218822Sdim   as they fill the intermediate buffer, and OPAQUE is a generalized
2793218822Sdim   callback argument.  On success, this returns 1.  On failure,
2794218822Sdim   it returns 0, indicating a bad parse.  It does not use heap
2795218822Sdim   memory to build an output string, so cannot encounter memory
2796218822Sdim   allocation failure.  */
2797218822Sdim
2798218822SdimCP_STATIC_IF_GLIBCPP_V3
2799218822Sdimint
2800218822Sdimcplus_demangle_print_callback (int options,
2801218822Sdim                               const struct demangle_component *dc,
2802218822Sdim                               demangle_callbackref callback, void *opaque)
2803218822Sdim{
2804218822Sdim  struct d_print_info dpi;
2805218822Sdim
2806218822Sdim  d_print_init (&dpi, options, callback, opaque);
2807218822Sdim
2808218822Sdim  d_print_comp (&dpi, dc);
2809218822Sdim
2810218822Sdim  d_print_flush (&dpi);
2811218822Sdim
2812218822Sdim  return ! d_print_saw_error (&dpi);
2813218822Sdim}
2814218822Sdim
2815218822Sdim/* Turn components into a human readable string.  OPTIONS is the
2816218822Sdim   options bits passed to the demangler.  DC is the tree to print.
2817130561Sobrien   ESTIMATE is a guess at the length of the result.  This returns a
2818130561Sobrien   string allocated by malloc, or NULL on error.  On success, this
2819130561Sobrien   sets *PALC to the size of the allocated buffer.  On failure, this
2820130561Sobrien   sets *PALC to 0 for a bad parse, or to 1 for a memory allocation
2821130561Sobrien   failure.  */
282268765Sobrien
2823130561SobrienCP_STATIC_IF_GLIBCPP_V3
2824130561Sobrienchar *
2825218822Sdimcplus_demangle_print (int options, const struct demangle_component *dc,
2826218822Sdim                      int estimate, size_t *palc)
282789857Sobrien{
2828218822Sdim  struct d_growable_string dgs;
282989857Sobrien
2830218822Sdim  d_growable_string_init (&dgs, estimate);
283168765Sobrien
2832218822Sdim  if (! cplus_demangle_print_callback (options, dc,
2833218822Sdim                                       d_growable_string_callback_adapter,
2834218822Sdim                                       &dgs))
2835130561Sobrien    {
2836218822Sdim      free (dgs.buf);
2837218822Sdim      *palc = 0;
2838130561Sobrien      return NULL;
2839130561Sobrien    }
284068765Sobrien
2841218822Sdim  *palc = dgs.allocation_failure ? 1 : dgs.alc;
2842218822Sdim  return dgs.buf;
284368765Sobrien}
284468765Sobrien
2845130561Sobrien/* Subroutine to handle components.  */
284668765Sobrien
2847130561Sobrienstatic void
2848218822Sdimd_print_comp (struct d_print_info *dpi,
2849218822Sdim              const struct demangle_component *dc)
285068765Sobrien{
2851130561Sobrien  if (dc == NULL)
2852130561Sobrien    {
2853130561Sobrien      d_print_error (dpi);
2854130561Sobrien      return;
2855130561Sobrien    }
2856130561Sobrien  if (d_print_saw_error (dpi))
2857130561Sobrien    return;
285868765Sobrien
2859130561Sobrien  switch (dc->type)
286068765Sobrien    {
2861130561Sobrien    case DEMANGLE_COMPONENT_NAME:
2862130561Sobrien      if ((dpi->options & DMGL_JAVA) == 0)
2863130561Sobrien	d_append_buffer (dpi, dc->u.s_name.s, dc->u.s_name.len);
2864130561Sobrien      else
2865130561Sobrien	d_print_java_identifier (dpi, dc->u.s_name.s, dc->u.s_name.len);
2866130561Sobrien      return;
286768765Sobrien
2868130561Sobrien    case DEMANGLE_COMPONENT_QUAL_NAME:
2869130561Sobrien    case DEMANGLE_COMPONENT_LOCAL_NAME:
2870130561Sobrien      d_print_comp (dpi, d_left (dc));
2871130561Sobrien      if ((dpi->options & DMGL_JAVA) == 0)
2872218822Sdim	d_append_string (dpi, "::");
2873130561Sobrien      else
2874130561Sobrien	d_append_char (dpi, '.');
2875130561Sobrien      d_print_comp (dpi, d_right (dc));
2876130561Sobrien      return;
287768765Sobrien
2878130561Sobrien    case DEMANGLE_COMPONENT_TYPED_NAME:
2879130561Sobrien      {
2880130561Sobrien	struct d_print_mod *hold_modifiers;
2881130561Sobrien	struct demangle_component *typed_name;
2882130561Sobrien	struct d_print_mod adpm[4];
2883130561Sobrien	unsigned int i;
2884130561Sobrien	struct d_print_template dpt;
288568765Sobrien
2886130561Sobrien	/* Pass the name down to the type so that it can be printed in
2887130561Sobrien	   the right place for the type.  We also have to pass down
2888130561Sobrien	   any CV-qualifiers, which apply to the this parameter.  */
2889130561Sobrien	hold_modifiers = dpi->modifiers;
2890130561Sobrien	i = 0;
2891130561Sobrien	typed_name = d_left (dc);
2892130561Sobrien	while (typed_name != NULL)
2893130561Sobrien	  {
2894130561Sobrien	    if (i >= sizeof adpm / sizeof adpm[0])
2895130561Sobrien	      {
2896130561Sobrien		d_print_error (dpi);
2897130561Sobrien		return;
2898130561Sobrien	      }
289968765Sobrien
2900130561Sobrien	    adpm[i].next = dpi->modifiers;
2901130561Sobrien	    dpi->modifiers = &adpm[i];
2902130561Sobrien	    adpm[i].mod = typed_name;
2903130561Sobrien	    adpm[i].printed = 0;
2904130561Sobrien	    adpm[i].templates = dpi->templates;
2905130561Sobrien	    ++i;
290668765Sobrien
2907130561Sobrien	    if (typed_name->type != DEMANGLE_COMPONENT_RESTRICT_THIS
2908130561Sobrien		&& typed_name->type != DEMANGLE_COMPONENT_VOLATILE_THIS
2909130561Sobrien		&& typed_name->type != DEMANGLE_COMPONENT_CONST_THIS)
2910130561Sobrien	      break;
291168765Sobrien
2912130561Sobrien	    typed_name = d_left (typed_name);
2913130561Sobrien	  }
291468765Sobrien
2915130561Sobrien	/* If typed_name is a template, then it applies to the
2916130561Sobrien	   function type as well.  */
2917130561Sobrien	if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE)
2918130561Sobrien	  {
2919130561Sobrien	    dpt.next = dpi->templates;
2920130561Sobrien	    dpi->templates = &dpt;
2921218822Sdim	    dpt.template_decl = typed_name;
2922130561Sobrien	  }
292368765Sobrien
2924130561Sobrien	/* If typed_name is a DEMANGLE_COMPONENT_LOCAL_NAME, then
2925130561Sobrien	   there may be CV-qualifiers on its right argument which
2926130561Sobrien	   really apply here; this happens when parsing a class which
2927130561Sobrien	   is local to a function.  */
2928130561Sobrien	if (typed_name->type == DEMANGLE_COMPONENT_LOCAL_NAME)
2929130561Sobrien	  {
2930130561Sobrien	    struct demangle_component *local_name;
293168765Sobrien
2932130561Sobrien	    local_name = d_right (typed_name);
2933130561Sobrien	    while (local_name->type == DEMANGLE_COMPONENT_RESTRICT_THIS
2934130561Sobrien		   || local_name->type == DEMANGLE_COMPONENT_VOLATILE_THIS
2935130561Sobrien		   || local_name->type == DEMANGLE_COMPONENT_CONST_THIS)
2936130561Sobrien	      {
2937130561Sobrien		if (i >= sizeof adpm / sizeof adpm[0])
2938130561Sobrien		  {
2939130561Sobrien		    d_print_error (dpi);
2940130561Sobrien		    return;
2941130561Sobrien		  }
294268765Sobrien
2943130561Sobrien		adpm[i] = adpm[i - 1];
2944130561Sobrien		adpm[i].next = &adpm[i - 1];
2945130561Sobrien		dpi->modifiers = &adpm[i];
294668765Sobrien
2947130561Sobrien		adpm[i - 1].mod = local_name;
2948130561Sobrien		adpm[i - 1].printed = 0;
2949130561Sobrien		adpm[i - 1].templates = dpi->templates;
2950130561Sobrien		++i;
295168765Sobrien
2952130561Sobrien		local_name = d_left (local_name);
2953130561Sobrien	      }
2954130561Sobrien	  }
295568765Sobrien
2956130561Sobrien	d_print_comp (dpi, d_right (dc));
295768765Sobrien
2958130561Sobrien	if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE)
2959130561Sobrien	  dpi->templates = dpt.next;
296068765Sobrien
2961130561Sobrien	/* If the modifiers didn't get printed by the type, print them
2962130561Sobrien	   now.  */
2963130561Sobrien	while (i > 0)
2964130561Sobrien	  {
2965130561Sobrien	    --i;
2966130561Sobrien	    if (! adpm[i].printed)
2967130561Sobrien	      {
2968130561Sobrien		d_append_char (dpi, ' ');
2969130561Sobrien		d_print_mod (dpi, adpm[i].mod);
2970130561Sobrien	      }
2971130561Sobrien	  }
297268765Sobrien
2973130561Sobrien	dpi->modifiers = hold_modifiers;
297468765Sobrien
2975130561Sobrien	return;
2976130561Sobrien      }
297777298Sobrien
2978130561Sobrien    case DEMANGLE_COMPONENT_TEMPLATE:
2979130561Sobrien      {
2980130561Sobrien	struct d_print_mod *hold_dpm;
2981218822Sdim	struct demangle_component *dcl;
298268765Sobrien
2983130561Sobrien	/* Don't push modifiers into a template definition.  Doing so
2984130561Sobrien	   could give the wrong definition for a template argument.
2985130561Sobrien	   Instead, treat the template essentially as a name.  */
298668765Sobrien
2987130561Sobrien	hold_dpm = dpi->modifiers;
2988130561Sobrien	dpi->modifiers = NULL;
298968765Sobrien
2990218822Sdim        dcl = d_left (dc);
299168765Sobrien
2992218822Sdim        if ((dpi->options & DMGL_JAVA) != 0
2993218822Sdim            && dcl->type == DEMANGLE_COMPONENT_NAME
2994218822Sdim            && dcl->u.s_name.len == 6
2995218822Sdim            && strncmp (dcl->u.s_name.s, "JArray", 6) == 0)
2996218822Sdim          {
2997218822Sdim            /* Special-case Java arrays, so that JArray<TYPE> appears
2998218822Sdim               instead as TYPE[].  */
2999218822Sdim
3000218822Sdim            d_print_comp (dpi, d_right (dc));
3001218822Sdim            d_append_string (dpi, "[]");
3002218822Sdim          }
3003218822Sdim        else
3004218822Sdim          {
3005218822Sdim	    d_print_comp (dpi, dcl);
3006218822Sdim	    if (d_last_char (dpi) == '<')
3007218822Sdim	      d_append_char (dpi, ' ');
3008218822Sdim	    d_append_char (dpi, '<');
3009218822Sdim	    d_print_comp (dpi, d_right (dc));
3010218822Sdim	    /* Avoid generating two consecutive '>' characters, to avoid
3011218822Sdim	       the C++ syntactic ambiguity.  */
3012218822Sdim	    if (d_last_char (dpi) == '>')
3013218822Sdim	      d_append_char (dpi, ' ');
3014218822Sdim	    d_append_char (dpi, '>');
3015218822Sdim          }
3016218822Sdim
3017130561Sobrien	dpi->modifiers = hold_dpm;
301868765Sobrien
3019130561Sobrien	return;
3020130561Sobrien      }
302168765Sobrien
3022130561Sobrien    case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
3023130561Sobrien      {
3024130561Sobrien	long i;
3025130561Sobrien	struct demangle_component *a;
3026130561Sobrien	struct d_print_template *hold_dpt;
302768765Sobrien
3028130561Sobrien	if (dpi->templates == NULL)
3029130561Sobrien	  {
3030130561Sobrien	    d_print_error (dpi);
3031130561Sobrien	    return;
3032130561Sobrien	  }
3033130561Sobrien	i = dc->u.s_number.number;
3034218822Sdim	for (a = d_right (dpi->templates->template_decl);
3035130561Sobrien	     a != NULL;
3036130561Sobrien	     a = d_right (a))
3037130561Sobrien	  {
3038130561Sobrien	    if (a->type != DEMANGLE_COMPONENT_TEMPLATE_ARGLIST)
3039130561Sobrien	      {
3040130561Sobrien		d_print_error (dpi);
3041130561Sobrien		return;
3042130561Sobrien	      }
3043130561Sobrien	    if (i <= 0)
3044130561Sobrien	      break;
3045130561Sobrien	    --i;
3046130561Sobrien	  }
3047130561Sobrien	if (i != 0 || a == NULL)
3048130561Sobrien	  {
3049130561Sobrien	    d_print_error (dpi);
3050130561Sobrien	    return;
3051130561Sobrien	  }
305277298Sobrien
3053130561Sobrien	/* While processing this parameter, we need to pop the list of
3054130561Sobrien	   templates.  This is because the template parameter may
3055130561Sobrien	   itself be a reference to a parameter of an outer
3056130561Sobrien	   template.  */
305777298Sobrien
3058130561Sobrien	hold_dpt = dpi->templates;
3059130561Sobrien	dpi->templates = hold_dpt->next;
306068765Sobrien
3061130561Sobrien	d_print_comp (dpi, d_left (a));
306268765Sobrien
3063130561Sobrien	dpi->templates = hold_dpt;
306468765Sobrien
3065130561Sobrien	return;
3066130561Sobrien      }
306768765Sobrien
3068130561Sobrien    case DEMANGLE_COMPONENT_CTOR:
3069130561Sobrien      d_print_comp (dpi, dc->u.s_ctor.name);
3070130561Sobrien      return;
307168765Sobrien
3072130561Sobrien    case DEMANGLE_COMPONENT_DTOR:
3073130561Sobrien      d_append_char (dpi, '~');
3074130561Sobrien      d_print_comp (dpi, dc->u.s_dtor.name);
3075130561Sobrien      return;
307677298Sobrien
3077130561Sobrien    case DEMANGLE_COMPONENT_VTABLE:
3078218822Sdim      d_append_string (dpi, "vtable for ");
3079130561Sobrien      d_print_comp (dpi, d_left (dc));
3080130561Sobrien      return;
308168765Sobrien
3082130561Sobrien    case DEMANGLE_COMPONENT_VTT:
3083218822Sdim      d_append_string (dpi, "VTT for ");
3084130561Sobrien      d_print_comp (dpi, d_left (dc));
3085130561Sobrien      return;
308668765Sobrien
3087130561Sobrien    case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
3088218822Sdim      d_append_string (dpi, "construction vtable for ");
3089130561Sobrien      d_print_comp (dpi, d_left (dc));
3090218822Sdim      d_append_string (dpi, "-in-");
3091130561Sobrien      d_print_comp (dpi, d_right (dc));
3092130561Sobrien      return;
309368765Sobrien
3094130561Sobrien    case DEMANGLE_COMPONENT_TYPEINFO:
3095218822Sdim      d_append_string (dpi, "typeinfo for ");
3096130561Sobrien      d_print_comp (dpi, d_left (dc));
3097130561Sobrien      return;
309868765Sobrien
3099130561Sobrien    case DEMANGLE_COMPONENT_TYPEINFO_NAME:
3100218822Sdim      d_append_string (dpi, "typeinfo name for ");
3101130561Sobrien      d_print_comp (dpi, d_left (dc));
3102130561Sobrien      return;
310368765Sobrien
3104130561Sobrien    case DEMANGLE_COMPONENT_TYPEINFO_FN:
3105218822Sdim      d_append_string (dpi, "typeinfo fn for ");
3106130561Sobrien      d_print_comp (dpi, d_left (dc));
3107130561Sobrien      return;
310868765Sobrien
3109130561Sobrien    case DEMANGLE_COMPONENT_THUNK:
3110218822Sdim      d_append_string (dpi, "non-virtual thunk to ");
3111130561Sobrien      d_print_comp (dpi, d_left (dc));
3112130561Sobrien      return;
311368765Sobrien
3114130561Sobrien    case DEMANGLE_COMPONENT_VIRTUAL_THUNK:
3115218822Sdim      d_append_string (dpi, "virtual thunk to ");
3116130561Sobrien      d_print_comp (dpi, d_left (dc));
3117130561Sobrien      return;
311868765Sobrien
3119130561Sobrien    case DEMANGLE_COMPONENT_COVARIANT_THUNK:
3120218822Sdim      d_append_string (dpi, "covariant return thunk to ");
3121130561Sobrien      d_print_comp (dpi, d_left (dc));
3122130561Sobrien      return;
312368765Sobrien
3124130561Sobrien    case DEMANGLE_COMPONENT_JAVA_CLASS:
3125218822Sdim      d_append_string (dpi, "java Class for ");
3126130561Sobrien      d_print_comp (dpi, d_left (dc));
3127130561Sobrien      return;
312868765Sobrien
3129130561Sobrien    case DEMANGLE_COMPONENT_GUARD:
3130218822Sdim      d_append_string (dpi, "guard variable for ");
3131130561Sobrien      d_print_comp (dpi, d_left (dc));
3132130561Sobrien      return;
313368765Sobrien
3134130561Sobrien    case DEMANGLE_COMPONENT_REFTEMP:
3135218822Sdim      d_append_string (dpi, "reference temporary for ");
3136130561Sobrien      d_print_comp (dpi, d_left (dc));
3137130561Sobrien      return;
313868765Sobrien
3139218822Sdim    case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
3140218822Sdim      d_append_string (dpi, "hidden alias for ");
3141218822Sdim      d_print_comp (dpi, d_left (dc));
3142218822Sdim      return;
3143218822Sdim
3144130561Sobrien    case DEMANGLE_COMPONENT_SUB_STD:
3145130561Sobrien      d_append_buffer (dpi, dc->u.s_string.string, dc->u.s_string.len);
3146130561Sobrien      return;
314768765Sobrien
3148130561Sobrien    case DEMANGLE_COMPONENT_RESTRICT:
3149130561Sobrien    case DEMANGLE_COMPONENT_VOLATILE:
3150130561Sobrien    case DEMANGLE_COMPONENT_CONST:
3151218822Sdim      {
3152218822Sdim	struct d_print_mod *pdpm;
3153218822Sdim
3154218822Sdim	/* When printing arrays, it's possible to have cases where the
3155218822Sdim	   same CV-qualifier gets pushed on the stack multiple times.
3156218822Sdim	   We only need to print it once.  */
3157218822Sdim
3158218822Sdim	for (pdpm = dpi->modifiers; pdpm != NULL; pdpm = pdpm->next)
3159218822Sdim	  {
3160218822Sdim	    if (! pdpm->printed)
3161218822Sdim	      {
3162218822Sdim		if (pdpm->mod->type != DEMANGLE_COMPONENT_RESTRICT
3163218822Sdim		    && pdpm->mod->type != DEMANGLE_COMPONENT_VOLATILE
3164218822Sdim		    && pdpm->mod->type != DEMANGLE_COMPONENT_CONST)
3165218822Sdim		  break;
3166218822Sdim		if (pdpm->mod->type == dc->type)
3167218822Sdim		  {
3168218822Sdim		    d_print_comp (dpi, d_left (dc));
3169218822Sdim		    return;
3170218822Sdim		  }
3171218822Sdim	      }
3172218822Sdim	  }
3173218822Sdim      }
3174218822Sdim      /* Fall through.  */
3175130561Sobrien    case DEMANGLE_COMPONENT_RESTRICT_THIS:
3176130561Sobrien    case DEMANGLE_COMPONENT_VOLATILE_THIS:
3177130561Sobrien    case DEMANGLE_COMPONENT_CONST_THIS:
3178130561Sobrien    case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
3179130561Sobrien    case DEMANGLE_COMPONENT_POINTER:
3180130561Sobrien    case DEMANGLE_COMPONENT_REFERENCE:
3181130561Sobrien    case DEMANGLE_COMPONENT_COMPLEX:
3182130561Sobrien    case DEMANGLE_COMPONENT_IMAGINARY:
3183130561Sobrien      {
3184130561Sobrien	/* We keep a list of modifiers on the stack.  */
3185130561Sobrien	struct d_print_mod dpm;
318668765Sobrien
3187130561Sobrien	dpm.next = dpi->modifiers;
3188130561Sobrien	dpi->modifiers = &dpm;
3189130561Sobrien	dpm.mod = dc;
3190130561Sobrien	dpm.printed = 0;
3191130561Sobrien	dpm.templates = dpi->templates;
319268765Sobrien
3193130561Sobrien	d_print_comp (dpi, d_left (dc));
319468765Sobrien
3195130561Sobrien	/* If the modifier didn't get printed by the type, print it
3196130561Sobrien	   now.  */
3197130561Sobrien	if (! dpm.printed)
3198130561Sobrien	  d_print_mod (dpi, dc);
319968765Sobrien
3200130561Sobrien	dpi->modifiers = dpm.next;
320168765Sobrien
3202130561Sobrien	return;
3203130561Sobrien      }
3204130561Sobrien
3205130561Sobrien    case DEMANGLE_COMPONENT_BUILTIN_TYPE:
3206130561Sobrien      if ((dpi->options & DMGL_JAVA) == 0)
3207130561Sobrien	d_append_buffer (dpi, dc->u.s_builtin.type->name,
3208130561Sobrien			 dc->u.s_builtin.type->len);
320968765Sobrien      else
3210130561Sobrien	d_append_buffer (dpi, dc->u.s_builtin.type->java_name,
3211130561Sobrien			 dc->u.s_builtin.type->java_len);
3212130561Sobrien      return;
321368765Sobrien
3214130561Sobrien    case DEMANGLE_COMPONENT_VENDOR_TYPE:
3215130561Sobrien      d_print_comp (dpi, d_left (dc));
3216130561Sobrien      return;
321768765Sobrien
3218130561Sobrien    case DEMANGLE_COMPONENT_FUNCTION_TYPE:
3219130561Sobrien      {
3220218822Sdim	if ((dpi->options & DMGL_RET_POSTFIX) != 0)
3221218822Sdim	  d_print_function_type (dpi, dc, dpi->modifiers);
3222218822Sdim
3223218822Sdim	/* Print return type if present */
3224130561Sobrien	if (d_left (dc) != NULL)
3225130561Sobrien	  {
3226130561Sobrien	    struct d_print_mod dpm;
322768765Sobrien
3228130561Sobrien	    /* We must pass this type down as a modifier in order to
3229130561Sobrien	       print it in the right location.  */
3230130561Sobrien	    dpm.next = dpi->modifiers;
3231130561Sobrien	    dpi->modifiers = &dpm;
3232130561Sobrien	    dpm.mod = dc;
3233130561Sobrien	    dpm.printed = 0;
3234130561Sobrien	    dpm.templates = dpi->templates;
323568765Sobrien
3236130561Sobrien	    d_print_comp (dpi, d_left (dc));
323768765Sobrien
3238130561Sobrien	    dpi->modifiers = dpm.next;
323968765Sobrien
3240130561Sobrien	    if (dpm.printed)
3241130561Sobrien	      return;
324268765Sobrien
3243218822Sdim	    /* In standard prefix notation, there is a space between the
3244218822Sdim	       return type and the function signature.  */
3245218822Sdim	    if ((dpi->options & DMGL_RET_POSTFIX) == 0)
3246218822Sdim	      d_append_char (dpi, ' ');
3247130561Sobrien	  }
324868765Sobrien
3249218822Sdim	if ((dpi->options & DMGL_RET_POSTFIX) == 0)
3250218822Sdim	  d_print_function_type (dpi, dc, dpi->modifiers);
325168765Sobrien
3252130561Sobrien	return;
3253130561Sobrien      }
325468765Sobrien
3255130561Sobrien    case DEMANGLE_COMPONENT_ARRAY_TYPE:
3256130561Sobrien      {
3257218822Sdim	struct d_print_mod *hold_modifiers;
3258218822Sdim	struct d_print_mod adpm[4];
3259218822Sdim	unsigned int i;
3260218822Sdim	struct d_print_mod *pdpm;
326168765Sobrien
3262130561Sobrien	/* We must pass this type down as a modifier in order to print
3263218822Sdim	   multi-dimensional arrays correctly.  If the array itself is
3264218822Sdim	   CV-qualified, we act as though the element type were
3265218822Sdim	   CV-qualified.  We do this by copying the modifiers down
3266218822Sdim	   rather than fiddling pointers, so that we don't wind up
3267218822Sdim	   with a d_print_mod higher on the stack pointing into our
3268218822Sdim	   stack frame after we return.  */
326968765Sobrien
3270218822Sdim	hold_modifiers = dpi->modifiers;
327168765Sobrien
3272218822Sdim	adpm[0].next = hold_modifiers;
3273218822Sdim	dpi->modifiers = &adpm[0];
3274218822Sdim	adpm[0].mod = dc;
3275218822Sdim	adpm[0].printed = 0;
3276218822Sdim	adpm[0].templates = dpi->templates;
3277218822Sdim
3278218822Sdim	i = 1;
3279218822Sdim	pdpm = hold_modifiers;
3280218822Sdim	while (pdpm != NULL
3281218822Sdim	       && (pdpm->mod->type == DEMANGLE_COMPONENT_RESTRICT
3282218822Sdim		   || pdpm->mod->type == DEMANGLE_COMPONENT_VOLATILE
3283218822Sdim		   || pdpm->mod->type == DEMANGLE_COMPONENT_CONST))
3284218822Sdim	  {
3285218822Sdim	    if (! pdpm->printed)
3286218822Sdim	      {
3287218822Sdim		if (i >= sizeof adpm / sizeof adpm[0])
3288218822Sdim		  {
3289218822Sdim		    d_print_error (dpi);
3290218822Sdim		    return;
3291218822Sdim		  }
3292218822Sdim
3293218822Sdim		adpm[i] = *pdpm;
3294218822Sdim		adpm[i].next = dpi->modifiers;
3295218822Sdim		dpi->modifiers = &adpm[i];
3296218822Sdim		pdpm->printed = 1;
3297218822Sdim		++i;
3298218822Sdim	      }
3299218822Sdim
3300218822Sdim	    pdpm = pdpm->next;
3301218822Sdim	  }
3302218822Sdim
3303130561Sobrien	d_print_comp (dpi, d_right (dc));
330468765Sobrien
3305218822Sdim	dpi->modifiers = hold_modifiers;
3306130561Sobrien
3307218822Sdim	if (adpm[0].printed)
3308130561Sobrien	  return;
3309130561Sobrien
3310218822Sdim	while (i > 1)
3311218822Sdim	  {
3312218822Sdim	    --i;
3313218822Sdim	    d_print_mod (dpi, adpm[i].mod);
3314218822Sdim	  }
3315218822Sdim
3316130561Sobrien	d_print_array_type (dpi, dc, dpi->modifiers);
3317130561Sobrien
3318130561Sobrien	return;
3319130561Sobrien      }
3320130561Sobrien
3321130561Sobrien    case DEMANGLE_COMPONENT_PTRMEM_TYPE:
3322130561Sobrien      {
3323130561Sobrien	struct d_print_mod dpm;
3324130561Sobrien
3325130561Sobrien	dpm.next = dpi->modifiers;
3326130561Sobrien	dpi->modifiers = &dpm;
3327130561Sobrien	dpm.mod = dc;
3328130561Sobrien	dpm.printed = 0;
3329130561Sobrien	dpm.templates = dpi->templates;
3330130561Sobrien
3331130561Sobrien	d_print_comp (dpi, d_right (dc));
3332130561Sobrien
3333130561Sobrien	/* If the modifier didn't get printed by the type, print it
3334130561Sobrien	   now.  */
3335130561Sobrien	if (! dpm.printed)
3336130561Sobrien	  {
3337130561Sobrien	    d_append_char (dpi, ' ');
3338130561Sobrien	    d_print_comp (dpi, d_left (dc));
3339218822Sdim	    d_append_string (dpi, "::*");
3340130561Sobrien	  }
3341130561Sobrien
3342130561Sobrien	dpi->modifiers = dpm.next;
3343130561Sobrien
3344130561Sobrien	return;
3345130561Sobrien      }
3346130561Sobrien
3347130561Sobrien    case DEMANGLE_COMPONENT_ARGLIST:
3348130561Sobrien    case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
3349130561Sobrien      d_print_comp (dpi, d_left (dc));
3350130561Sobrien      if (d_right (dc) != NULL)
335168765Sobrien	{
3352218822Sdim	  d_append_string (dpi, ", ");
3353130561Sobrien	  d_print_comp (dpi, d_right (dc));
335468765Sobrien	}
3355130561Sobrien      return;
335668765Sobrien
3357130561Sobrien    case DEMANGLE_COMPONENT_OPERATOR:
3358130561Sobrien      {
3359130561Sobrien	char c;
336068765Sobrien
3361218822Sdim	d_append_string (dpi, "operator");
3362130561Sobrien	c = dc->u.s_operator.op->name[0];
3363130561Sobrien	if (IS_LOWER (c))
3364130561Sobrien	  d_append_char (dpi, ' ');
3365130561Sobrien	d_append_buffer (dpi, dc->u.s_operator.op->name,
3366130561Sobrien			 dc->u.s_operator.op->len);
3367130561Sobrien	return;
3368130561Sobrien      }
336968765Sobrien
3370130561Sobrien    case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
3371218822Sdim      d_append_string (dpi, "operator ");
3372130561Sobrien      d_print_comp (dpi, dc->u.s_extended_operator.name);
3373130561Sobrien      return;
3374130561Sobrien
3375130561Sobrien    case DEMANGLE_COMPONENT_CAST:
3376218822Sdim      d_append_string (dpi, "operator ");
3377130561Sobrien      d_print_cast (dpi, dc);
3378130561Sobrien      return;
3379130561Sobrien
3380130561Sobrien    case DEMANGLE_COMPONENT_UNARY:
3381130561Sobrien      if (d_left (dc)->type != DEMANGLE_COMPONENT_CAST)
3382130561Sobrien	d_print_expr_op (dpi, d_left (dc));
3383130561Sobrien      else
3384130561Sobrien	{
3385218822Sdim	  d_append_char (dpi, '(');
3386130561Sobrien	  d_print_cast (dpi, d_left (dc));
3387130561Sobrien	  d_append_char (dpi, ')');
338868765Sobrien	}
3389130561Sobrien      d_append_char (dpi, '(');
3390130561Sobrien      d_print_comp (dpi, d_right (dc));
3391130561Sobrien      d_append_char (dpi, ')');
3392130561Sobrien      return;
339368765Sobrien
3394130561Sobrien    case DEMANGLE_COMPONENT_BINARY:
3395130561Sobrien      if (d_right (dc)->type != DEMANGLE_COMPONENT_BINARY_ARGS)
3396130561Sobrien	{
3397130561Sobrien	  d_print_error (dpi);
3398130561Sobrien	  return;
3399130561Sobrien	}
340068765Sobrien
3401130561Sobrien      /* We wrap an expression which uses the greater-than operator in
3402130561Sobrien	 an extra layer of parens so that it does not get confused
3403130561Sobrien	 with the '>' which ends the template parameters.  */
3404130561Sobrien      if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR
3405130561Sobrien	  && d_left (dc)->u.s_operator.op->len == 1
3406130561Sobrien	  && d_left (dc)->u.s_operator.op->name[0] == '>')
3407130561Sobrien	d_append_char (dpi, '(');
340868765Sobrien
3409130561Sobrien      d_append_char (dpi, '(');
3410130561Sobrien      d_print_comp (dpi, d_left (d_right (dc)));
3411218822Sdim      d_append_string (dpi, ") ");
3412130561Sobrien      d_print_expr_op (dpi, d_left (dc));
3413218822Sdim      d_append_string (dpi, " (");
3414130561Sobrien      d_print_comp (dpi, d_right (d_right (dc)));
3415130561Sobrien      d_append_char (dpi, ')');
341668765Sobrien
3417130561Sobrien      if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR
3418130561Sobrien	  && d_left (dc)->u.s_operator.op->len == 1
3419130561Sobrien	  && d_left (dc)->u.s_operator.op->name[0] == '>')
3420130561Sobrien	d_append_char (dpi, ')');
342168765Sobrien
3422130561Sobrien      return;
342368765Sobrien
3424130561Sobrien    case DEMANGLE_COMPONENT_BINARY_ARGS:
3425130561Sobrien      /* We should only see this as part of DEMANGLE_COMPONENT_BINARY.  */
3426130561Sobrien      d_print_error (dpi);
3427130561Sobrien      return;
342868765Sobrien
3429130561Sobrien    case DEMANGLE_COMPONENT_TRINARY:
3430130561Sobrien      if (d_right (dc)->type != DEMANGLE_COMPONENT_TRINARY_ARG1
3431130561Sobrien	  || d_right (d_right (dc))->type != DEMANGLE_COMPONENT_TRINARY_ARG2)
3432130561Sobrien	{
3433130561Sobrien	  d_print_error (dpi);
3434130561Sobrien	  return;
3435130561Sobrien	}
3436130561Sobrien      d_append_char (dpi, '(');
3437130561Sobrien      d_print_comp (dpi, d_left (d_right (dc)));
3438218822Sdim      d_append_string (dpi, ") ");
3439130561Sobrien      d_print_expr_op (dpi, d_left (dc));
3440218822Sdim      d_append_string (dpi, " (");
3441130561Sobrien      d_print_comp (dpi, d_left (d_right (d_right (dc))));
3442218822Sdim      d_append_string (dpi, ") : (");
3443130561Sobrien      d_print_comp (dpi, d_right (d_right (d_right (dc))));
3444130561Sobrien      d_append_char (dpi, ')');
3445130561Sobrien      return;
344668765Sobrien
3447130561Sobrien    case DEMANGLE_COMPONENT_TRINARY_ARG1:
3448130561Sobrien    case DEMANGLE_COMPONENT_TRINARY_ARG2:
3449130561Sobrien      /* We should only see these are part of DEMANGLE_COMPONENT_TRINARY.  */
3450130561Sobrien      d_print_error (dpi);
3451130561Sobrien      return;
345268765Sobrien
3453130561Sobrien    case DEMANGLE_COMPONENT_LITERAL:
3454130561Sobrien    case DEMANGLE_COMPONENT_LITERAL_NEG:
3455218822Sdim      {
3456218822Sdim	enum d_builtin_type_print tp;
3457130561Sobrien
3458218822Sdim	/* For some builtin types, produce simpler output.  */
3459218822Sdim	tp = D_PRINT_DEFAULT;
3460218822Sdim	if (d_left (dc)->type == DEMANGLE_COMPONENT_BUILTIN_TYPE)
3461218822Sdim	  {
3462218822Sdim	    tp = d_left (dc)->u.s_builtin.type->print;
3463218822Sdim	    switch (tp)
3464218822Sdim	      {
3465218822Sdim	      case D_PRINT_INT:
3466218822Sdim	      case D_PRINT_UNSIGNED:
3467218822Sdim	      case D_PRINT_LONG:
3468218822Sdim	      case D_PRINT_UNSIGNED_LONG:
3469218822Sdim	      case D_PRINT_LONG_LONG:
3470218822Sdim	      case D_PRINT_UNSIGNED_LONG_LONG:
3471218822Sdim		if (d_right (dc)->type == DEMANGLE_COMPONENT_NAME)
3472218822Sdim		  {
3473218822Sdim		    if (dc->type == DEMANGLE_COMPONENT_LITERAL_NEG)
3474218822Sdim		      d_append_char (dpi, '-');
3475218822Sdim		    d_print_comp (dpi, d_right (dc));
3476218822Sdim		    switch (tp)
3477218822Sdim		      {
3478218822Sdim		      default:
3479218822Sdim			break;
3480218822Sdim		      case D_PRINT_UNSIGNED:
3481218822Sdim			d_append_char (dpi, 'u');
3482218822Sdim			break;
3483218822Sdim		      case D_PRINT_LONG:
3484218822Sdim			d_append_char (dpi, 'l');
3485218822Sdim			break;
3486218822Sdim		      case D_PRINT_UNSIGNED_LONG:
3487218822Sdim			d_append_string (dpi, "ul");
3488218822Sdim			break;
3489218822Sdim		      case D_PRINT_LONG_LONG:
3490218822Sdim			d_append_string (dpi, "ll");
3491218822Sdim			break;
3492218822Sdim		      case D_PRINT_UNSIGNED_LONG_LONG:
3493218822Sdim			d_append_string (dpi, "ull");
3494218822Sdim			break;
3495218822Sdim		      }
3496218822Sdim		    return;
3497218822Sdim		  }
3498218822Sdim		break;
3499130561Sobrien
3500218822Sdim	      case D_PRINT_BOOL:
3501218822Sdim		if (d_right (dc)->type == DEMANGLE_COMPONENT_NAME
3502218822Sdim		    && d_right (dc)->u.s_name.len == 1
3503218822Sdim		    && dc->type == DEMANGLE_COMPONENT_LITERAL)
3504218822Sdim		  {
3505218822Sdim		    switch (d_right (dc)->u.s_name.s[0])
3506218822Sdim		      {
3507218822Sdim		      case '0':
3508218822Sdim			d_append_string (dpi, "false");
3509218822Sdim			return;
3510218822Sdim		      case '1':
3511218822Sdim			d_append_string (dpi, "true");
3512218822Sdim			return;
3513218822Sdim		      default:
3514218822Sdim			break;
3515218822Sdim		      }
3516218822Sdim		  }
3517218822Sdim		break;
3518130561Sobrien
3519218822Sdim	      default:
3520218822Sdim		break;
3521218822Sdim	      }
3522218822Sdim	  }
352368765Sobrien
3524218822Sdim	d_append_char (dpi, '(');
3525218822Sdim	d_print_comp (dpi, d_left (dc));
3526218822Sdim	d_append_char (dpi, ')');
3527218822Sdim	if (dc->type == DEMANGLE_COMPONENT_LITERAL_NEG)
3528218822Sdim	  d_append_char (dpi, '-');
3529218822Sdim	if (tp == D_PRINT_FLOAT)
3530218822Sdim	  d_append_char (dpi, '[');
3531218822Sdim	d_print_comp (dpi, d_right (dc));
3532218822Sdim	if (tp == D_PRINT_FLOAT)
3533218822Sdim	  d_append_char (dpi, ']');
3534218822Sdim      }
3535130561Sobrien      return;
353668765Sobrien
353768765Sobrien    default:
3538130561Sobrien      d_print_error (dpi);
3539130561Sobrien      return;
354068765Sobrien    }
354168765Sobrien}
354268765Sobrien
3543130561Sobrien/* Print a Java dentifier.  For Java we try to handle encoded extended
3544130561Sobrien   Unicode characters.  The C++ ABI doesn't mention Unicode encoding,
3545130561Sobrien   so we don't it for C++.  Characters are encoded as
3546130561Sobrien   __U<hex-char>+_.  */
354768765Sobrien
3548130561Sobrienstatic void
3549218822Sdimd_print_java_identifier (struct d_print_info *dpi, const char *name, int len)
355068765Sobrien{
3551130561Sobrien  const char *p;
3552130561Sobrien  const char *end;
355368765Sobrien
3554130561Sobrien  end = name + len;
3555130561Sobrien  for (p = name; p < end; ++p)
355668765Sobrien    {
3557130561Sobrien      if (end - p > 3
3558130561Sobrien	  && p[0] == '_'
3559130561Sobrien	  && p[1] == '_'
3560130561Sobrien	  && p[2] == 'U')
3561130561Sobrien	{
3562130561Sobrien	  unsigned long c;
3563130561Sobrien	  const char *q;
356468765Sobrien
3565130561Sobrien	  c = 0;
3566130561Sobrien	  for (q = p + 3; q < end; ++q)
3567130561Sobrien	    {
3568130561Sobrien	      int dig;
356968765Sobrien
3570130561Sobrien	      if (IS_DIGIT (*q))
3571130561Sobrien		dig = *q - '0';
3572130561Sobrien	      else if (*q >= 'A' && *q <= 'F')
3573130561Sobrien		dig = *q - 'A' + 10;
3574130561Sobrien	      else if (*q >= 'a' && *q <= 'f')
3575130561Sobrien		dig = *q - 'a' + 10;
3576130561Sobrien	      else
3577130561Sobrien		break;
3578130561Sobrien
3579130561Sobrien	      c = c * 16 + dig;
3580130561Sobrien	    }
3581130561Sobrien	  /* If the Unicode character is larger than 256, we don't try
3582130561Sobrien	     to deal with it here.  FIXME.  */
3583130561Sobrien	  if (q < end && *q == '_' && c < 256)
3584130561Sobrien	    {
3585130561Sobrien	      d_append_char (dpi, c);
3586130561Sobrien	      p = q;
3587130561Sobrien	      continue;
3588130561Sobrien	    }
358968765Sobrien	}
359068765Sobrien
3591130561Sobrien      d_append_char (dpi, *p);
359268765Sobrien    }
359368765Sobrien}
359468765Sobrien
3595130561Sobrien/* Print a list of modifiers.  SUFFIX is 1 if we are printing
3596130561Sobrien   qualifiers on this after printing a function.  */
359768765Sobrien
3598130561Sobrienstatic void
3599218822Sdimd_print_mod_list (struct d_print_info *dpi,
3600218822Sdim                  struct d_print_mod *mods, int suffix)
360168765Sobrien{
3602130561Sobrien  struct d_print_template *hold_dpt;
360368765Sobrien
3604130561Sobrien  if (mods == NULL || d_print_saw_error (dpi))
3605130561Sobrien    return;
360668765Sobrien
3607130561Sobrien  if (mods->printed
3608130561Sobrien      || (! suffix
3609130561Sobrien	  && (mods->mod->type == DEMANGLE_COMPONENT_RESTRICT_THIS
3610130561Sobrien	      || mods->mod->type == DEMANGLE_COMPONENT_VOLATILE_THIS
3611130561Sobrien	      || mods->mod->type == DEMANGLE_COMPONENT_CONST_THIS)))
3612130561Sobrien    {
3613130561Sobrien      d_print_mod_list (dpi, mods->next, suffix);
3614130561Sobrien      return;
3615130561Sobrien    }
361668765Sobrien
3617130561Sobrien  mods->printed = 1;
361868765Sobrien
3619130561Sobrien  hold_dpt = dpi->templates;
3620130561Sobrien  dpi->templates = mods->templates;
362168765Sobrien
3622130561Sobrien  if (mods->mod->type == DEMANGLE_COMPONENT_FUNCTION_TYPE)
362368765Sobrien    {
3624130561Sobrien      d_print_function_type (dpi, mods->mod, mods->next);
3625130561Sobrien      dpi->templates = hold_dpt;
3626130561Sobrien      return;
3627130561Sobrien    }
3628130561Sobrien  else if (mods->mod->type == DEMANGLE_COMPONENT_ARRAY_TYPE)
3629130561Sobrien    {
3630130561Sobrien      d_print_array_type (dpi, mods->mod, mods->next);
3631130561Sobrien      dpi->templates = hold_dpt;
3632130561Sobrien      return;
3633130561Sobrien    }
3634130561Sobrien  else if (mods->mod->type == DEMANGLE_COMPONENT_LOCAL_NAME)
3635130561Sobrien    {
3636130561Sobrien      struct d_print_mod *hold_modifiers;
3637130561Sobrien      struct demangle_component *dc;
363868765Sobrien
3639130561Sobrien      /* When this is on the modifier stack, we have pulled any
3640130561Sobrien	 qualifiers off the right argument already.  Otherwise, we
3641130561Sobrien	 print it as usual, but don't let the left argument see any
3642130561Sobrien	 modifiers.  */
3643130561Sobrien
3644130561Sobrien      hold_modifiers = dpi->modifiers;
3645130561Sobrien      dpi->modifiers = NULL;
3646130561Sobrien      d_print_comp (dpi, d_left (mods->mod));
3647130561Sobrien      dpi->modifiers = hold_modifiers;
3648130561Sobrien
3649130561Sobrien      if ((dpi->options & DMGL_JAVA) == 0)
3650218822Sdim	d_append_string (dpi, "::");
365168765Sobrien      else
3652130561Sobrien	d_append_char (dpi, '.');
365368765Sobrien
3654130561Sobrien      dc = d_right (mods->mod);
3655130561Sobrien      while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS
3656130561Sobrien	     || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS
3657130561Sobrien	     || dc->type == DEMANGLE_COMPONENT_CONST_THIS)
3658130561Sobrien	dc = d_left (dc);
3659130561Sobrien
3660130561Sobrien      d_print_comp (dpi, dc);
3661130561Sobrien
3662130561Sobrien      dpi->templates = hold_dpt;
3663130561Sobrien      return;
366468765Sobrien    }
366568765Sobrien
3666130561Sobrien  d_print_mod (dpi, mods->mod);
366768765Sobrien
3668130561Sobrien  dpi->templates = hold_dpt;
366968765Sobrien
3670130561Sobrien  d_print_mod_list (dpi, mods->next, suffix);
3671130561Sobrien}
367268765Sobrien
3673130561Sobrien/* Print a modifier.  */
367468765Sobrien
3675130561Sobrienstatic void
3676218822Sdimd_print_mod (struct d_print_info *dpi,
3677218822Sdim             const struct demangle_component *mod)
367868765Sobrien{
3679130561Sobrien  switch (mod->type)
3680130561Sobrien    {
3681130561Sobrien    case DEMANGLE_COMPONENT_RESTRICT:
3682130561Sobrien    case DEMANGLE_COMPONENT_RESTRICT_THIS:
3683218822Sdim      d_append_string (dpi, " restrict");
3684130561Sobrien      return;
3685130561Sobrien    case DEMANGLE_COMPONENT_VOLATILE:
3686130561Sobrien    case DEMANGLE_COMPONENT_VOLATILE_THIS:
3687218822Sdim      d_append_string (dpi, " volatile");
3688130561Sobrien      return;
3689130561Sobrien    case DEMANGLE_COMPONENT_CONST:
3690130561Sobrien    case DEMANGLE_COMPONENT_CONST_THIS:
3691218822Sdim      d_append_string (dpi, " const");
3692130561Sobrien      return;
3693130561Sobrien    case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
3694130561Sobrien      d_append_char (dpi, ' ');
3695130561Sobrien      d_print_comp (dpi, d_right (mod));
3696130561Sobrien      return;
3697130561Sobrien    case DEMANGLE_COMPONENT_POINTER:
3698130561Sobrien      /* There is no pointer symbol in Java.  */
3699130561Sobrien      if ((dpi->options & DMGL_JAVA) == 0)
3700130561Sobrien	d_append_char (dpi, '*');
3701130561Sobrien      return;
3702130561Sobrien    case DEMANGLE_COMPONENT_REFERENCE:
3703130561Sobrien      d_append_char (dpi, '&');
3704130561Sobrien      return;
3705130561Sobrien    case DEMANGLE_COMPONENT_COMPLEX:
3706218822Sdim      d_append_string (dpi, "complex ");
3707130561Sobrien      return;
3708130561Sobrien    case DEMANGLE_COMPONENT_IMAGINARY:
3709218822Sdim      d_append_string (dpi, "imaginary ");
3710130561Sobrien      return;
3711130561Sobrien    case DEMANGLE_COMPONENT_PTRMEM_TYPE:
3712130561Sobrien      if (d_last_char (dpi) != '(')
3713130561Sobrien	d_append_char (dpi, ' ');
3714130561Sobrien      d_print_comp (dpi, d_left (mod));
3715218822Sdim      d_append_string (dpi, "::*");
3716130561Sobrien      return;
3717130561Sobrien    case DEMANGLE_COMPONENT_TYPED_NAME:
3718130561Sobrien      d_print_comp (dpi, d_left (mod));
3719130561Sobrien      return;
3720130561Sobrien    default:
3721130561Sobrien      /* Otherwise, we have something that won't go back on the
3722130561Sobrien	 modifier stack, so we can just print it.  */
3723130561Sobrien      d_print_comp (dpi, mod);
3724130561Sobrien      return;
3725130561Sobrien    }
3726130561Sobrien}
372768765Sobrien
3728130561Sobrien/* Print a function type, except for the return type.  */
372968765Sobrien
3730130561Sobrienstatic void
3731218822Sdimd_print_function_type (struct d_print_info *dpi,
3732218822Sdim                       const struct demangle_component *dc,
3733218822Sdim                       struct d_print_mod *mods)
3734130561Sobrien{
3735130561Sobrien  int need_paren;
3736130561Sobrien  int saw_mod;
3737218822Sdim  int need_space;
3738130561Sobrien  struct d_print_mod *p;
3739130561Sobrien  struct d_print_mod *hold_modifiers;
374068765Sobrien
3741130561Sobrien  need_paren = 0;
3742130561Sobrien  saw_mod = 0;
3743218822Sdim  need_space = 0;
3744130561Sobrien  for (p = mods; p != NULL; p = p->next)
374568765Sobrien    {
3746130561Sobrien      if (p->printed)
3747130561Sobrien	break;
374868765Sobrien
3749130561Sobrien      saw_mod = 1;
3750130561Sobrien      switch (p->mod->type)
375168765Sobrien	{
3752218822Sdim	case DEMANGLE_COMPONENT_POINTER:
3753218822Sdim	case DEMANGLE_COMPONENT_REFERENCE:
3754218822Sdim	  need_paren = 1;
3755218822Sdim	  break;
3756130561Sobrien	case DEMANGLE_COMPONENT_RESTRICT:
3757130561Sobrien	case DEMANGLE_COMPONENT_VOLATILE:
3758130561Sobrien	case DEMANGLE_COMPONENT_CONST:
3759130561Sobrien	case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
3760130561Sobrien	case DEMANGLE_COMPONENT_COMPLEX:
3761130561Sobrien	case DEMANGLE_COMPONENT_IMAGINARY:
3762130561Sobrien	case DEMANGLE_COMPONENT_PTRMEM_TYPE:
3763218822Sdim	  need_space = 1;
3764130561Sobrien	  need_paren = 1;
376568765Sobrien	  break;
3766130561Sobrien	case DEMANGLE_COMPONENT_RESTRICT_THIS:
3767130561Sobrien	case DEMANGLE_COMPONENT_VOLATILE_THIS:
3768130561Sobrien	case DEMANGLE_COMPONENT_CONST_THIS:
376968765Sobrien	  break;
3770130561Sobrien	default:
377168765Sobrien	  break;
3772130561Sobrien	}
3773130561Sobrien      if (need_paren)
3774130561Sobrien	break;
3775130561Sobrien    }
377668765Sobrien
3777130561Sobrien  if (d_left (dc) != NULL && ! saw_mod)
3778130561Sobrien    need_paren = 1;
3779130561Sobrien
3780130561Sobrien  if (need_paren)
3781130561Sobrien    {
3782218822Sdim      if (! need_space)
3783130561Sobrien	{
3784218822Sdim	  if (d_last_char (dpi) != '('
3785218822Sdim	      && d_last_char (dpi) != '*')
3786218822Sdim	    need_space = 1;
3787130561Sobrien	}
3788218822Sdim      if (need_space && d_last_char (dpi) != ' ')
3789218822Sdim	d_append_char (dpi, ' ');
3790130561Sobrien      d_append_char (dpi, '(');
3791130561Sobrien    }
3792130561Sobrien
3793130561Sobrien  hold_modifiers = dpi->modifiers;
3794130561Sobrien  dpi->modifiers = NULL;
3795130561Sobrien
3796130561Sobrien  d_print_mod_list (dpi, mods, 0);
3797130561Sobrien
3798130561Sobrien  if (need_paren)
3799130561Sobrien    d_append_char (dpi, ')');
3800130561Sobrien
3801130561Sobrien  d_append_char (dpi, '(');
3802130561Sobrien
3803130561Sobrien  if (d_right (dc) != NULL)
3804130561Sobrien    d_print_comp (dpi, d_right (dc));
3805130561Sobrien
3806130561Sobrien  d_append_char (dpi, ')');
3807130561Sobrien
3808130561Sobrien  d_print_mod_list (dpi, mods, 1);
3809130561Sobrien
3810130561Sobrien  dpi->modifiers = hold_modifiers;
3811130561Sobrien}
3812130561Sobrien
3813130561Sobrien/* Print an array type, except for the element type.  */
3814130561Sobrien
3815130561Sobrienstatic void
3816218822Sdimd_print_array_type (struct d_print_info *dpi,
3817218822Sdim                    const struct demangle_component *dc,
3818218822Sdim                    struct d_print_mod *mods)
3819130561Sobrien{
3820130561Sobrien  int need_space;
3821130561Sobrien
3822130561Sobrien  need_space = 1;
3823130561Sobrien  if (mods != NULL)
3824130561Sobrien    {
3825130561Sobrien      int need_paren;
3826130561Sobrien      struct d_print_mod *p;
3827130561Sobrien
3828130561Sobrien      need_paren = 0;
3829130561Sobrien      for (p = mods; p != NULL; p = p->next)
3830130561Sobrien	{
3831218822Sdim	  if (! p->printed)
383268765Sobrien	    {
3833218822Sdim	      if (p->mod->type == DEMANGLE_COMPONENT_ARRAY_TYPE)
3834218822Sdim		{
3835218822Sdim		  need_space = 0;
3836218822Sdim		  break;
3837218822Sdim		}
3838218822Sdim	      else
3839218822Sdim		{
3840218822Sdim		  need_paren = 1;
3841218822Sdim		  need_space = 1;
3842218822Sdim		  break;
3843218822Sdim		}
384468765Sobrien	    }
384568765Sobrien	}
384668765Sobrien
3847130561Sobrien      if (need_paren)
3848218822Sdim	d_append_string (dpi, " (");
384968765Sobrien
3850130561Sobrien      d_print_mod_list (dpi, mods, 0);
3851130561Sobrien
3852130561Sobrien      if (need_paren)
3853130561Sobrien	d_append_char (dpi, ')');
385468765Sobrien    }
385568765Sobrien
3856130561Sobrien  if (need_space)
3857130561Sobrien    d_append_char (dpi, ' ');
385868765Sobrien
3859130561Sobrien  d_append_char (dpi, '[');
386068765Sobrien
3861130561Sobrien  if (d_left (dc) != NULL)
3862130561Sobrien    d_print_comp (dpi, d_left (dc));
3863130561Sobrien
3864130561Sobrien  d_append_char (dpi, ']');
386568765Sobrien}
386668765Sobrien
3867130561Sobrien/* Print an operator in an expression.  */
386868765Sobrien
3869130561Sobrienstatic void
3870218822Sdimd_print_expr_op (struct d_print_info *dpi,
3871218822Sdim                 const struct demangle_component *dc)
387268765Sobrien{
3873130561Sobrien  if (dc->type == DEMANGLE_COMPONENT_OPERATOR)
3874130561Sobrien    d_append_buffer (dpi, dc->u.s_operator.op->name,
3875130561Sobrien		     dc->u.s_operator.op->len);
3876130561Sobrien  else
3877130561Sobrien    d_print_comp (dpi, dc);
3878130561Sobrien}
387968765Sobrien
3880130561Sobrien/* Print a cast.  */
388168765Sobrien
3882130561Sobrienstatic void
3883218822Sdimd_print_cast (struct d_print_info *dpi,
3884218822Sdim              const struct demangle_component *dc)
3885130561Sobrien{
3886130561Sobrien  if (d_left (dc)->type != DEMANGLE_COMPONENT_TEMPLATE)
3887130561Sobrien    d_print_comp (dpi, d_left (dc));
388868765Sobrien  else
388968765Sobrien    {
3890130561Sobrien      struct d_print_mod *hold_dpm;
3891130561Sobrien      struct d_print_template dpt;
389268765Sobrien
3893130561Sobrien      /* It appears that for a templated cast operator, we need to put
3894130561Sobrien	 the template parameters in scope for the operator name, but
3895130561Sobrien	 not for the parameters.  The effect is that we need to handle
3896130561Sobrien	 the template printing here.  */
389768765Sobrien
3898130561Sobrien      hold_dpm = dpi->modifiers;
3899130561Sobrien      dpi->modifiers = NULL;
390068765Sobrien
3901130561Sobrien      dpt.next = dpi->templates;
3902130561Sobrien      dpi->templates = &dpt;
3903218822Sdim      dpt.template_decl = d_left (dc);
390468765Sobrien
3905130561Sobrien      d_print_comp (dpi, d_left (d_left (dc)));
390668765Sobrien
3907130561Sobrien      dpi->templates = dpt.next;
3908130561Sobrien
3909130561Sobrien      if (d_last_char (dpi) == '<')
3910130561Sobrien	d_append_char (dpi, ' ');
3911130561Sobrien      d_append_char (dpi, '<');
3912130561Sobrien      d_print_comp (dpi, d_right (d_left (dc)));
3913130561Sobrien      /* Avoid generating two consecutive '>' characters, to avoid
3914130561Sobrien	 the C++ syntactic ambiguity.  */
3915130561Sobrien      if (d_last_char (dpi) == '>')
3916130561Sobrien	d_append_char (dpi, ' ');
3917130561Sobrien      d_append_char (dpi, '>');
3918130561Sobrien
3919130561Sobrien      dpi->modifiers = hold_dpm;
392068765Sobrien    }
3921130561Sobrien}
392268765Sobrien
3923130561Sobrien/* Initialize the information structure we use to pass around
3924130561Sobrien   information.  */
3925130561Sobrien
3926130561SobrienCP_STATIC_IF_GLIBCPP_V3
3927130561Sobrienvoid
3928218822Sdimcplus_demangle_init_info (const char *mangled, int options, size_t len,
3929218822Sdim                          struct d_info *di)
3930130561Sobrien{
3931130561Sobrien  di->s = mangled;
3932130561Sobrien  di->send = mangled + len;
3933130561Sobrien  di->options = options;
3934130561Sobrien
3935130561Sobrien  di->n = mangled;
3936130561Sobrien
3937130561Sobrien  /* We can not need more components than twice the number of chars in
3938130561Sobrien     the mangled string.  Most components correspond directly to
3939130561Sobrien     chars, but the ARGLIST types are exceptions.  */
3940130561Sobrien  di->num_comps = 2 * len;
3941130561Sobrien  di->next_comp = 0;
3942130561Sobrien
3943130561Sobrien  /* Similarly, we can not need more substitutions than there are
3944130561Sobrien     chars in the mangled string.  */
3945130561Sobrien  di->num_subs = len;
3946130561Sobrien  di->next_sub = 0;
3947130561Sobrien  di->did_subs = 0;
3948130561Sobrien
3949130561Sobrien  di->last_name = NULL;
3950130561Sobrien
3951130561Sobrien  di->expansion = 0;
395268765Sobrien}
395368765Sobrien
3954218822Sdim/* Internal implementation for the demangler.  If MANGLED is a g++ v3 ABI
3955218822Sdim   mangled name, return strings in repeated callback giving the demangled
3956218822Sdim   name.  OPTIONS is the usual libiberty demangler options.  On success,
3957218822Sdim   this returns 1.  On failure, returns 0.  */
395868765Sobrien
3959218822Sdimstatic int
3960218822Sdimd_demangle_callback (const char *mangled, int options,
3961218822Sdim                     demangle_callbackref callback, void *opaque)
396268765Sobrien{
3963130561Sobrien  int type;
3964130561Sobrien  struct d_info di;
3965130561Sobrien  struct demangle_component *dc;
3966218822Sdim  int status;
396768765Sobrien
3968130561Sobrien  if (mangled[0] == '_' && mangled[1] == 'Z')
3969130561Sobrien    type = 0;
3970130561Sobrien  else if (strncmp (mangled, "_GLOBAL_", 8) == 0
3971130561Sobrien	   && (mangled[8] == '.' || mangled[8] == '_' || mangled[8] == '$')
3972130561Sobrien	   && (mangled[9] == 'D' || mangled[9] == 'I')
3973130561Sobrien	   && mangled[10] == '_')
397468765Sobrien    {
3975218822Sdim      const char *intro;
397668765Sobrien
3977218822Sdim      intro = (mangled[9] == 'I')
3978218822Sdim              ? "global constructors keyed to "
3979218822Sdim              : "global destructors keyed to ";
3980218822Sdim
3981218822Sdim      callback (intro, strlen (intro), opaque);
3982218822Sdim      callback (mangled + 11, strlen (mangled + 11), opaque);
3983218822Sdim      return 1;
398468765Sobrien    }
398568765Sobrien  else
398668765Sobrien    {
3987130561Sobrien      if ((options & DMGL_TYPES) == 0)
3988218822Sdim	return 0;
3989130561Sobrien      type = 1;
399068765Sobrien    }
399168765Sobrien
3992218822Sdim  cplus_demangle_init_info (mangled, options, strlen (mangled), &di);
399368765Sobrien
3994130561Sobrien  {
3995130561Sobrien#ifdef CP_DYNAMIC_ARRAYS
3996130561Sobrien    __extension__ struct demangle_component comps[di.num_comps];
3997130561Sobrien    __extension__ struct demangle_component *subs[di.num_subs];
399868765Sobrien
3999218822Sdim    di.comps = comps;
4000218822Sdim    di.subs = subs;
4001130561Sobrien#else
4002218822Sdim    di.comps = alloca (di.num_comps * sizeof (*di.comps));
4003218822Sdim    di.subs = alloca (di.num_subs * sizeof (*di.subs));
4004130561Sobrien#endif
400568765Sobrien
4006218822Sdim    if (type)
4007218822Sdim      dc = cplus_demangle_type (&di);
4008218822Sdim    else
4009130561Sobrien      dc = cplus_demangle_mangled_name (&di, 1);
401068765Sobrien
4011130561Sobrien    /* If DMGL_PARAMS is set, then if we didn't consume the entire
4012130561Sobrien       mangled string, then we didn't successfully demangle it.  If
4013130561Sobrien       DMGL_PARAMS is not set, we didn't look at the trailing
4014130561Sobrien       parameters.  */
4015130561Sobrien    if (((options & DMGL_PARAMS) != 0) && d_peek_char (&di) != '\0')
4016130561Sobrien      dc = NULL;
401768765Sobrien
4018130561Sobrien#ifdef CP_DEMANGLE_DEBUG
4019218822Sdim    d_dump (dc, 0);
4020130561Sobrien#endif
402168765Sobrien
4022218822Sdim    status = (dc != NULL)
4023218822Sdim             ? cplus_demangle_print_callback (options, dc, callback, opaque)
4024218822Sdim             : 0;
4025218822Sdim  }
402668765Sobrien
4027218822Sdim  return status;
4028218822Sdim}
4029130561Sobrien
4030218822Sdim/* Entry point for the demangler.  If MANGLED is a g++ v3 ABI mangled
4031218822Sdim   name, return a buffer allocated with malloc holding the demangled
4032218822Sdim   name.  OPTIONS is the usual libiberty demangler options.  On
4033218822Sdim   success, this sets *PALC to the allocated size of the returned
4034218822Sdim   buffer.  On failure, this sets *PALC to 0 for a bad name, or 1 for
4035218822Sdim   a memory allocation failure, and returns NULL.  */
4036130561Sobrien
4037218822Sdimstatic char *
4038218822Sdimd_demangle (const char *mangled, int options, size_t *palc)
4039218822Sdim{
4040218822Sdim  struct d_growable_string dgs;
4041218822Sdim  int status;
4042130561Sobrien
4043218822Sdim  d_growable_string_init (&dgs, 0);
4044130561Sobrien
4045218822Sdim  status = d_demangle_callback (mangled, options,
4046218822Sdim                                d_growable_string_callback_adapter, &dgs);
4047218822Sdim  if (status == 0)
4048218822Sdim    {
4049218822Sdim      free (dgs.buf);
4050218822Sdim      *palc = 0;
4051218822Sdim      return NULL;
4052218822Sdim    }
4053218822Sdim
4054218822Sdim  *palc = dgs.allocation_failure ? 1 : 0;
4055218822Sdim  return dgs.buf;
405668765Sobrien}
405768765Sobrien
4058104834Sobrien#if defined(IN_LIBGCC2) || defined(IN_GLIBCPP_V3)
4059130561Sobrien
4060218822Sdimextern char *__cxa_demangle (const char *, char *, size_t *, int *);
406168765Sobrien
4062130561Sobrien/* ia64 ABI-mandated entry point in the C++ runtime library for
4063130561Sobrien   performing demangling.  MANGLED_NAME is a NUL-terminated character
4064130561Sobrien   string containing the name to be demangled.
406568765Sobrien
406668765Sobrien   OUTPUT_BUFFER is a region of memory, allocated with malloc, of
406768765Sobrien   *LENGTH bytes, into which the demangled name is stored.  If
406868765Sobrien   OUTPUT_BUFFER is not long enough, it is expanded using realloc.
406968765Sobrien   OUTPUT_BUFFER may instead be NULL; in that case, the demangled name
4070130561Sobrien   is placed in a region of memory allocated with malloc.
407168765Sobrien
4072218822Sdim   If LENGTH is non-NULL, the length of the buffer containing the
4073130561Sobrien   demangled name, is placed in *LENGTH.
407468765Sobrien
407568765Sobrien   The return value is a pointer to the start of the NUL-terminated
407668765Sobrien   demangled name, or NULL if the demangling fails.  The caller is
4077130561Sobrien   responsible for deallocating this memory using free.
407868765Sobrien
407968765Sobrien   *STATUS is set to one of the following values:
408068765Sobrien      0: The demangling operation succeeded.
4081130561Sobrien     -1: A memory allocation failure occurred.
408268765Sobrien     -2: MANGLED_NAME is not a valid name under the C++ ABI mangling rules.
408368765Sobrien     -3: One of the arguments is invalid.
408468765Sobrien
4085130561Sobrien   The demangling is performed using the C++ ABI mangling rules, with
408668765Sobrien   GNU extensions.  */
408768765Sobrien
408868765Sobrienchar *
4089218822Sdim__cxa_demangle (const char *mangled_name, char *output_buffer,
4090218822Sdim                size_t *length, int *status)
409168765Sobrien{
4092130561Sobrien  char *demangled;
4093130561Sobrien  size_t alc;
409468765Sobrien
4095130561Sobrien  if (mangled_name == NULL)
4096130561Sobrien    {
4097218822Sdim      if (status != NULL)
4098218822Sdim	*status = -3;
4099130561Sobrien      return NULL;
4100130561Sobrien    }
410168765Sobrien
4102130561Sobrien  if (output_buffer != NULL && length == NULL)
4103130561Sobrien    {
4104218822Sdim      if (status != NULL)
4105218822Sdim	*status = -3;
410668765Sobrien      return NULL;
410768765Sobrien    }
410868765Sobrien
4109218822Sdim  demangled = d_demangle (mangled_name, DMGL_PARAMS | DMGL_TYPES, &alc);
411068765Sobrien
4111130561Sobrien  if (demangled == NULL)
411268765Sobrien    {
4113218822Sdim      if (status != NULL)
4114218822Sdim	{
4115218822Sdim	  if (alc == 1)
4116218822Sdim	    *status = -1;
4117218822Sdim	  else
4118218822Sdim	    *status = -2;
4119218822Sdim	}
4120130561Sobrien      return NULL;
412168765Sobrien    }
4122130561Sobrien
4123130561Sobrien  if (output_buffer == NULL)
412468765Sobrien    {
4125130561Sobrien      if (length != NULL)
4126130561Sobrien	*length = alc;
412768765Sobrien    }
412868765Sobrien  else
412968765Sobrien    {
4130130561Sobrien      if (strlen (demangled) < *length)
4131130561Sobrien	{
4132130561Sobrien	  strcpy (output_buffer, demangled);
4133130561Sobrien	  free (demangled);
4134130561Sobrien	  demangled = output_buffer;
4135130561Sobrien	}
4136130561Sobrien      else
4137130561Sobrien	{
4138130561Sobrien	  free (output_buffer);
4139130561Sobrien	  *length = alc;
4140130561Sobrien	}
414168765Sobrien    }
4142130561Sobrien
4143218822Sdim  if (status != NULL)
4144218822Sdim    *status = 0;
4145130561Sobrien
4146130561Sobrien  return demangled;
414768765Sobrien}
414868765Sobrien
4149218822Sdimextern int __gcclibcxx_demangle_callback (const char *,
4150218822Sdim                                          void (*)
4151218822Sdim                                            (const char *, size_t, void *),
4152218822Sdim                                          void *);
4153218822Sdim
4154218822Sdim/* Alternative, allocationless entry point in the C++ runtime library
4155218822Sdim   for performing demangling.  MANGLED_NAME is a NUL-terminated character
4156218822Sdim   string containing the name to be demangled.
4157218822Sdim
4158218822Sdim   CALLBACK is a callback function, called with demangled string
4159218822Sdim   segments as demangling progresses; it is called at least once,
4160218822Sdim   but may be called more than once.  OPAQUE is a generalized pointer
4161218822Sdim   used as a callback argument.
4162218822Sdim
4163218822Sdim   The return code is one of the following values, equivalent to
4164218822Sdim   the STATUS values of __cxa_demangle() (excluding -1, since this
4165218822Sdim   function performs no memory allocations):
4166218822Sdim      0: The demangling operation succeeded.
4167218822Sdim     -2: MANGLED_NAME is not a valid name under the C++ ABI mangling rules.
4168218822Sdim     -3: One of the arguments is invalid.
4169218822Sdim
4170218822Sdim   The demangling is performed using the C++ ABI mangling rules, with
4171218822Sdim   GNU extensions.  */
4172218822Sdim
4173218822Sdimint
4174218822Sdim__gcclibcxx_demangle_callback (const char *mangled_name,
4175218822Sdim                               void (*callback) (const char *, size_t, void *),
4176218822Sdim                               void *opaque)
4177218822Sdim{
4178218822Sdim  int status;
4179218822Sdim
4180218822Sdim  if (mangled_name == NULL || callback == NULL)
4181218822Sdim    return -3;
4182218822Sdim
4183218822Sdim  status = d_demangle_callback (mangled_name, DMGL_PARAMS | DMGL_TYPES,
4184218822Sdim                                callback, opaque);
4185218822Sdim  if (status == 0)
4186218822Sdim    return -2;
4187218822Sdim
4188218822Sdim  return 0;
4189218822Sdim}
4190218822Sdim
4191104834Sobrien#else /* ! (IN_LIBGCC2 || IN_GLIBCPP_V3) */
419268765Sobrien
4193130561Sobrien/* Entry point for libiberty demangler.  If MANGLED is a g++ v3 ABI
4194130561Sobrien   mangled name, return a buffer allocated with malloc holding the
4195130561Sobrien   demangled name.  Otherwise, return NULL.  */
419668765Sobrien
419768765Sobrienchar *
4198218822Sdimcplus_demangle_v3 (const char *mangled, int options)
419968765Sobrien{
4200130561Sobrien  size_t alc;
420177298Sobrien
4202130561Sobrien  return d_demangle (mangled, options, &alc);
420368765Sobrien}
420468765Sobrien
4205218822Sdimint
4206218822Sdimcplus_demangle_v3_callback (const char *mangled, int options,
4207218822Sdim                            demangle_callbackref callback, void *opaque)
4208218822Sdim{
4209218822Sdim  return d_demangle_callback (mangled, options, callback, opaque);
4210218822Sdim}
4211218822Sdim
421289857Sobrien/* Demangle a Java symbol.  Java uses a subset of the V3 ABI C++ mangling
421389857Sobrien   conventions, but the output formatting is a little different.
4214218822Sdim   This instructs the C++ demangler not to emit pointer characters ("*"), to
4215218822Sdim   use Java's namespace separator symbol ("." instead of "::"), and to output
4216218822Sdim   JArray<TYPE> as TYPE[].  */
421789857Sobrien
421889857Sobrienchar *
4219218822Sdimjava_demangle_v3 (const char *mangled)
422089857Sobrien{
4221130561Sobrien  size_t alc;
422289857Sobrien
4223218822Sdim  return d_demangle (mangled, DMGL_JAVA | DMGL_PARAMS | DMGL_RET_POSTFIX, &alc);
4224218822Sdim}
422589857Sobrien
4226218822Sdimint
4227218822Sdimjava_demangle_v3_callback (const char *mangled,
4228218822Sdim                           demangle_callbackref callback, void *opaque)
4229218822Sdim{
4230218822Sdim  return d_demangle_callback (mangled,
4231218822Sdim                              DMGL_JAVA | DMGL_PARAMS | DMGL_RET_POSTFIX,
4232218822Sdim                              callback, opaque);
423389857Sobrien}
423489857Sobrien
4235104834Sobrien#endif /* IN_LIBGCC2 || IN_GLIBCPP_V3 */
423668765Sobrien
4237130561Sobrien#ifndef IN_GLIBCPP_V3
423889857Sobrien
4239130561Sobrien/* Demangle a string in order to find out whether it is a constructor
4240130561Sobrien   or destructor.  Return non-zero on success.  Set *CTOR_KIND and
4241130561Sobrien   *DTOR_KIND appropriately.  */
4242130561Sobrien
4243130561Sobrienstatic int
4244218822Sdimis_ctor_or_dtor (const char *mangled,
4245218822Sdim                 enum gnu_v3_ctor_kinds *ctor_kind,
4246218822Sdim                 enum gnu_v3_dtor_kinds *dtor_kind)
424789857Sobrien{
4248130561Sobrien  struct d_info di;
4249130561Sobrien  struct demangle_component *dc;
4250130561Sobrien  int ret;
425189857Sobrien
4252130561Sobrien  *ctor_kind = (enum gnu_v3_ctor_kinds) 0;
4253130561Sobrien  *dtor_kind = (enum gnu_v3_dtor_kinds) 0;
425489857Sobrien
4255130561Sobrien  cplus_demangle_init_info (mangled, DMGL_GNU_V3, strlen (mangled), &di);
425689857Sobrien
4257130561Sobrien  {
4258130561Sobrien#ifdef CP_DYNAMIC_ARRAYS
4259130561Sobrien    __extension__ struct demangle_component comps[di.num_comps];
4260130561Sobrien    __extension__ struct demangle_component *subs[di.num_subs];
426189857Sobrien
4262218822Sdim    di.comps = comps;
4263218822Sdim    di.subs = subs;
4264130561Sobrien#else
4265218822Sdim    di.comps = alloca (di.num_comps * sizeof (*di.comps));
4266218822Sdim    di.subs = alloca (di.num_subs * sizeof (*di.subs));
4267130561Sobrien#endif
426889857Sobrien
4269130561Sobrien    dc = cplus_demangle_mangled_name (&di, 1);
4270130561Sobrien
4271130561Sobrien    /* Note that because we did not pass DMGL_PARAMS, we don't expect
4272130561Sobrien       to demangle the entire string.  */
4273130561Sobrien
4274130561Sobrien    ret = 0;
4275130561Sobrien    while (dc != NULL)
4276130561Sobrien      {
4277130561Sobrien	switch (dc->type)
4278130561Sobrien	  {
4279130561Sobrien	  default:
4280130561Sobrien	    dc = NULL;
4281130561Sobrien	    break;
4282130561Sobrien	  case DEMANGLE_COMPONENT_TYPED_NAME:
4283130561Sobrien	  case DEMANGLE_COMPONENT_TEMPLATE:
4284130561Sobrien	  case DEMANGLE_COMPONENT_RESTRICT_THIS:
4285130561Sobrien	  case DEMANGLE_COMPONENT_VOLATILE_THIS:
4286130561Sobrien	  case DEMANGLE_COMPONENT_CONST_THIS:
4287130561Sobrien	    dc = d_left (dc);
4288130561Sobrien	    break;
4289130561Sobrien	  case DEMANGLE_COMPONENT_QUAL_NAME:
4290130561Sobrien	  case DEMANGLE_COMPONENT_LOCAL_NAME:
4291130561Sobrien	    dc = d_right (dc);
4292130561Sobrien	    break;
4293130561Sobrien	  case DEMANGLE_COMPONENT_CTOR:
4294130561Sobrien	    *ctor_kind = dc->u.s_ctor.kind;
4295130561Sobrien	    ret = 1;
4296130561Sobrien	    dc = NULL;
4297130561Sobrien	    break;
4298130561Sobrien	  case DEMANGLE_COMPONENT_DTOR:
4299130561Sobrien	    *dtor_kind = dc->u.s_dtor.kind;
4300130561Sobrien	    ret = 1;
4301130561Sobrien	    dc = NULL;
4302130561Sobrien	    break;
4303130561Sobrien	  }
4304130561Sobrien      }
4305130561Sobrien  }
4306130561Sobrien
4307130561Sobrien  return ret;
430889857Sobrien}
430989857Sobrien
4310130561Sobrien/* Return whether NAME is the mangled form of a g++ V3 ABI constructor
4311130561Sobrien   name.  A non-zero return indicates the type of constructor.  */
431289857Sobrien
431389857Sobrienenum gnu_v3_ctor_kinds
4314218822Sdimis_gnu_v3_mangled_ctor (const char *name)
431589857Sobrien{
4316130561Sobrien  enum gnu_v3_ctor_kinds ctor_kind;
4317130561Sobrien  enum gnu_v3_dtor_kinds dtor_kind;
431889857Sobrien
4319130561Sobrien  if (! is_ctor_or_dtor (name, &ctor_kind, &dtor_kind))
4320130561Sobrien    return (enum gnu_v3_ctor_kinds) 0;
4321130561Sobrien  return ctor_kind;
432289857Sobrien}
432389857Sobrien
432489857Sobrien
4325130561Sobrien/* Return whether NAME is the mangled form of a g++ V3 ABI destructor
4326130561Sobrien   name.  A non-zero return indicates the type of destructor.  */
4327130561Sobrien
432889857Sobrienenum gnu_v3_dtor_kinds
4329218822Sdimis_gnu_v3_mangled_dtor (const char *name)
433089857Sobrien{
4331130561Sobrien  enum gnu_v3_ctor_kinds ctor_kind;
4332130561Sobrien  enum gnu_v3_dtor_kinds dtor_kind;
433389857Sobrien
4334130561Sobrien  if (! is_ctor_or_dtor (name, &ctor_kind, &dtor_kind))
4335130561Sobrien    return (enum gnu_v3_dtor_kinds) 0;
4336130561Sobrien  return dtor_kind;
433789857Sobrien}
4338130561Sobrien
4339104834Sobrien#endif /* IN_GLIBCPP_V3 */
434089857Sobrien
434168765Sobrien#ifdef STANDALONE_DEMANGLER
434268765Sobrien
434368765Sobrien#include "getopt.h"
4344130561Sobrien#include "dyn-string.h"
434568765Sobrien
4346218822Sdimstatic void print_usage (FILE* fp, int exit_value);
434768765Sobrien
4348130561Sobrien#define IS_ALPHA(CHAR)                                                  \
4349130561Sobrien  (((CHAR) >= 'a' && (CHAR) <= 'z')                                     \
4350130561Sobrien   || ((CHAR) >= 'A' && (CHAR) <= 'Z'))
4351130561Sobrien
435268765Sobrien/* Non-zero if CHAR is a character than can occur in a mangled name.  */
435368765Sobrien#define is_mangled_char(CHAR)                                           \
435477298Sobrien  (IS_ALPHA (CHAR) || IS_DIGIT (CHAR)                                   \
435577298Sobrien   || (CHAR) == '_' || (CHAR) == '.' || (CHAR) == '$')
435668765Sobrien
435768765Sobrien/* The name of this program, as invoked.  */
435868765Sobrienconst char* program_name;
435968765Sobrien
436068765Sobrien/* Prints usage summary to FP and then exits with EXIT_VALUE.  */
436168765Sobrien
436268765Sobrienstatic void
4363218822Sdimprint_usage (FILE* fp, int exit_value)
436468765Sobrien{
436568765Sobrien  fprintf (fp, "Usage: %s [options] [names ...]\n", program_name);
436677298Sobrien  fprintf (fp, "Options:\n");
436768765Sobrien  fprintf (fp, "  -h,--help       Display this message.\n");
4368130561Sobrien  fprintf (fp, "  -p,--no-params  Don't display function parameters\n");
436968765Sobrien  fprintf (fp, "  -v,--verbose    Produce verbose demanglings.\n");
437068765Sobrien  fprintf (fp, "If names are provided, they are demangled.  Otherwise filters standard input.\n");
437168765Sobrien
437268765Sobrien  exit (exit_value);
437368765Sobrien}
437468765Sobrien
437568765Sobrien/* Option specification for getopt_long.  */
437689857Sobrienstatic const struct option long_options[] =
437768765Sobrien{
4378130561Sobrien  { "help",	 no_argument, NULL, 'h' },
4379130561Sobrien  { "no-params", no_argument, NULL, 'p' },
4380130561Sobrien  { "verbose",   no_argument, NULL, 'v' },
4381130561Sobrien  { NULL,        no_argument, NULL, 0   },
438268765Sobrien};
438368765Sobrien
438468765Sobrien/* Main entry for a demangling filter executable.  It will demangle
438568765Sobrien   its command line arguments, if any.  If none are provided, it will
438668765Sobrien   filter stdin to stdout, replacing any recognized mangled C++ names
438768765Sobrien   with their demangled equivalents.  */
438868765Sobrien
438968765Sobrienint
4390218822Sdimmain (int argc, char *argv[])
439168765Sobrien{
439268765Sobrien  int i;
439368765Sobrien  int opt_char;
4394130561Sobrien  int options = DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES;
439568765Sobrien
439668765Sobrien  /* Use the program name of this program, as invoked.  */
439768765Sobrien  program_name = argv[0];
439868765Sobrien
439968765Sobrien  /* Parse options.  */
440068765Sobrien  do
440168765Sobrien    {
4402130561Sobrien      opt_char = getopt_long (argc, argv, "hpv", long_options, NULL);
440368765Sobrien      switch (opt_char)
440468765Sobrien	{
440568765Sobrien	case '?':  /* Unrecognized option.  */
440668765Sobrien	  print_usage (stderr, 1);
440768765Sobrien	  break;
440868765Sobrien
440968765Sobrien	case 'h':
441068765Sobrien	  print_usage (stdout, 0);
441168765Sobrien	  break;
441268765Sobrien
4413130561Sobrien	case 'p':
4414130561Sobrien	  options &= ~ DMGL_PARAMS;
441568765Sobrien	  break;
441668765Sobrien
441768765Sobrien	case 'v':
4418130561Sobrien	  options |= DMGL_VERBOSE;
441968765Sobrien	  break;
442068765Sobrien	}
442168765Sobrien    }
442268765Sobrien  while (opt_char != -1);
442368765Sobrien
442468765Sobrien  if (optind == argc)
442568765Sobrien    /* No command line arguments were provided.  Filter stdin.  */
442668765Sobrien    {
442768765Sobrien      dyn_string_t mangled = dyn_string_new (3);
4428130561Sobrien      char *s;
442968765Sobrien
443068765Sobrien      /* Read all of input.  */
443168765Sobrien      while (!feof (stdin))
443268765Sobrien	{
4433130561Sobrien	  char c;
443468765Sobrien
443568765Sobrien	  /* Pile characters into mangled until we hit one that can't
443668765Sobrien	     occur in a mangled name.  */
443768765Sobrien	  c = getchar ();
443868765Sobrien	  while (!feof (stdin) && is_mangled_char (c))
443968765Sobrien	    {
444068765Sobrien	      dyn_string_append_char (mangled, c);
444168765Sobrien	      if (feof (stdin))
444268765Sobrien		break;
444368765Sobrien	      c = getchar ();
444468765Sobrien	    }
444568765Sobrien
4446130561Sobrien	  if (dyn_string_length (mangled) > 0)
4447130561Sobrien	    {
4448218822Sdim#ifdef IN_GLIBCPP_V3
4449218822Sdim	      s = __cxa_demangle (dyn_string_buf (mangled), NULL, NULL, NULL);
4450218822Sdim#else
4451130561Sobrien	      s = cplus_demangle_v3 (dyn_string_buf (mangled), options);
4452218822Sdim#endif
445368765Sobrien
4454130561Sobrien	      if (s != NULL)
4455130561Sobrien		{
4456130561Sobrien		  fputs (s, stdout);
4457130561Sobrien		  free (s);
4458130561Sobrien		}
4459130561Sobrien	      else
4460130561Sobrien		{
4461130561Sobrien		  /* It might not have been a mangled name.  Print the
4462130561Sobrien		     original text.  */
4463130561Sobrien		  fputs (dyn_string_buf (mangled), stdout);
4464130561Sobrien		}
4465130561Sobrien
4466130561Sobrien	      dyn_string_clear (mangled);
446768765Sobrien	    }
446868765Sobrien
446968765Sobrien	  /* If we haven't hit EOF yet, we've read one character that
447068765Sobrien	     can't occur in a mangled name, so print it out.  */
447168765Sobrien	  if (!feof (stdin))
447268765Sobrien	    putchar (c);
447368765Sobrien	}
447468765Sobrien
447568765Sobrien      dyn_string_delete (mangled);
447668765Sobrien    }
447768765Sobrien  else
447868765Sobrien    /* Demangle command line arguments.  */
447968765Sobrien    {
448068765Sobrien      /* Loop over command line arguments.  */
448168765Sobrien      for (i = optind; i < argc; ++i)
448268765Sobrien	{
4483130561Sobrien	  char *s;
4484218822Sdim#ifdef IN_GLIBCPP_V3
4485218822Sdim	  int status;
4486218822Sdim#endif
4487130561Sobrien
448868765Sobrien	  /* Attempt to demangle.  */
4489218822Sdim#ifdef IN_GLIBCPP_V3
4490218822Sdim	  s = __cxa_demangle (argv[i], NULL, NULL, &status);
4491218822Sdim#else
4492130561Sobrien	  s = cplus_demangle_v3 (argv[i], options);
4493218822Sdim#endif
449468765Sobrien
449568765Sobrien	  /* If it worked, print the demangled name.  */
4496130561Sobrien	  if (s != NULL)
449768765Sobrien	    {
4498130561Sobrien	      printf ("%s\n", s);
4499130561Sobrien	      free (s);
450068765Sobrien	    }
4501130561Sobrien	  else
4502218822Sdim	    {
4503218822Sdim#ifdef IN_GLIBCPP_V3
4504218822Sdim	      fprintf (stderr, "Failed: %s (status %d)\n", argv[i], status);
4505218822Sdim#else
4506218822Sdim	      fprintf (stderr, "Failed: %s\n", argv[i]);
4507218822Sdim#endif
4508218822Sdim	    }
450968765Sobrien	}
451068765Sobrien    }
451168765Sobrien
451268765Sobrien  return 0;
451368765Sobrien}
451468765Sobrien
451568765Sobrien#endif /* STANDALONE_DEMANGLER */
4516