1de4a1d01951937632098a6cda45859afa587a06fsewardj/* Demangler for GNU C++
2de4a1d01951937632098a6cda45859afa587a06fsewardj   Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999,
38dc79cec6aa15e11a8b35c4ff781ebaff5811221florian   2000, 2001, 2002, 2003, 2004, 2010 Free Software Foundation, Inc.
4de4a1d01951937632098a6cda45859afa587a06fsewardj   Written by James Clark (jjc@jclark.uucp)
5de4a1d01951937632098a6cda45859afa587a06fsewardj   Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
6de4a1d01951937632098a6cda45859afa587a06fsewardj   Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
7de4a1d01951937632098a6cda45859afa587a06fsewardj
8de4a1d01951937632098a6cda45859afa587a06fsewardjThis file is part of the libiberty library.
9de4a1d01951937632098a6cda45859afa587a06fsewardjLibiberty is free software; you can redistribute it and/or
10de4a1d01951937632098a6cda45859afa587a06fsewardjmodify it under the terms of the GNU Library General Public
11de4a1d01951937632098a6cda45859afa587a06fsewardjLicense as published by the Free Software Foundation; either
12de4a1d01951937632098a6cda45859afa587a06fsewardjversion 2 of the License, or (at your option) any later version.
13de4a1d01951937632098a6cda45859afa587a06fsewardj
144f2683ace412ca2c8266f2dd860dee4461df3cafsewardjIn addition to the permissions in the GNU Library General Public
154f2683ace412ca2c8266f2dd860dee4461df3cafsewardjLicense, the Free Software Foundation gives you unlimited permission
164f2683ace412ca2c8266f2dd860dee4461df3cafsewardjto link the compiled version of this file into combinations with other
174f2683ace412ca2c8266f2dd860dee4461df3cafsewardjprograms, and to distribute those combinations without any restriction
184f2683ace412ca2c8266f2dd860dee4461df3cafsewardjcoming from the use of this file.  (The Library Public License
194f2683ace412ca2c8266f2dd860dee4461df3cafsewardjrestrictions do apply in other respects; for example, they cover
204f2683ace412ca2c8266f2dd860dee4461df3cafsewardjmodification of the file, and distribution when not linked into a
214f2683ace412ca2c8266f2dd860dee4461df3cafsewardjcombined executable.)
224f2683ace412ca2c8266f2dd860dee4461df3cafsewardj
23de4a1d01951937632098a6cda45859afa587a06fsewardjLibiberty is distributed in the hope that it will be useful,
24de4a1d01951937632098a6cda45859afa587a06fsewardjbut WITHOUT ANY WARRANTY; without even the implied warranty of
25de4a1d01951937632098a6cda45859afa587a06fsewardjMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
26de4a1d01951937632098a6cda45859afa587a06fsewardjLibrary General Public License for more details.
27de4a1d01951937632098a6cda45859afa587a06fsewardj
28de4a1d01951937632098a6cda45859afa587a06fsewardjYou should have received a copy of the GNU Library General Public
29de4a1d01951937632098a6cda45859afa587a06fsewardjLicense along with libiberty; see the file COPYING.LIB.  If
304f2683ace412ca2c8266f2dd860dee4461df3cafsewardjnot, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
314f2683ace412ca2c8266f2dd860dee4461df3cafsewardjBoston, MA 02110-1301, USA.  */
32de4a1d01951937632098a6cda45859afa587a06fsewardj
33de4a1d01951937632098a6cda45859afa587a06fsewardj/* This file exports two functions; cplus_mangle_opname and cplus_demangle.
34de4a1d01951937632098a6cda45859afa587a06fsewardj
35de4a1d01951937632098a6cda45859afa587a06fsewardj   This file imports xmalloc and xrealloc, which are like malloc and
36de4a1d01951937632098a6cda45859afa587a06fsewardj   realloc except that they generate a fatal error if there is no
37de4a1d01951937632098a6cda45859afa587a06fsewardj   available memory.  */
38de4a1d01951937632098a6cda45859afa587a06fsewardj
39de4a1d01951937632098a6cda45859afa587a06fsewardj/* This file lives in both GCC and libiberty.  When making changes, please
40de4a1d01951937632098a6cda45859afa587a06fsewardj   try not to break either.  */
41de4a1d01951937632098a6cda45859afa587a06fsewardj
424f2683ace412ca2c8266f2dd860dee4461df3cafsewardj#if 0 /* in valgrind */
43de4a1d01951937632098a6cda45859afa587a06fsewardj#ifdef HAVE_CONFIG_H
44de4a1d01951937632098a6cda45859afa587a06fsewardj#include "config.h"
45de4a1d01951937632098a6cda45859afa587a06fsewardj#endif
464f2683ace412ca2c8266f2dd860dee4461df3cafsewardj#endif /* ! in valgrind */
47de4a1d01951937632098a6cda45859afa587a06fsewardj
484f2683ace412ca2c8266f2dd860dee4461df3cafsewardj#if 0 /* in valgrind */
49de4a1d01951937632098a6cda45859afa587a06fsewardj#include "safe-ctype.h"
504f2683ace412ca2c8266f2dd860dee4461df3cafsewardj#endif /* ! in valgrind */
51de4a1d01951937632098a6cda45859afa587a06fsewardj
524f2683ace412ca2c8266f2dd860dee4461df3cafsewardj#if 0 /* in valgrind */
534f2683ace412ca2c8266f2dd860dee4461df3cafsewardj#include <sys/types.h>
54de4a1d01951937632098a6cda45859afa587a06fsewardj#include <string.h>
554f2683ace412ca2c8266f2dd860dee4461df3cafsewardj#include <stdio.h>
564f2683ace412ca2c8266f2dd860dee4461df3cafsewardj#endif /* ! in valgrind */
57de4a1d01951937632098a6cda45859afa587a06fsewardj
584f2683ace412ca2c8266f2dd860dee4461df3cafsewardj#if 0 /* in valgrind */
594f2683ace412ca2c8266f2dd860dee4461df3cafsewardj#ifdef HAVE_STDLIB_H
60de4a1d01951937632098a6cda45859afa587a06fsewardj#include <stdlib.h>
61de4a1d01951937632098a6cda45859afa587a06fsewardj#else
624f2683ace412ca2c8266f2dd860dee4461df3cafsewardjvoid * malloc ();
634f2683ace412ca2c8266f2dd860dee4461df3cafsewardjvoid * realloc ();
644f2683ace412ca2c8266f2dd860dee4461df3cafsewardj#endif
654f2683ace412ca2c8266f2dd860dee4461df3cafsewardj#endif /* ! in valgrind */
66de4a1d01951937632098a6cda45859afa587a06fsewardj
674f2683ace412ca2c8266f2dd860dee4461df3cafsewardj#if 0 /* in valgrind */
684f2683ace412ca2c8266f2dd860dee4461df3cafsewardj#include <demangle.h>
69de4a1d01951937632098a6cda45859afa587a06fsewardj#undef CURRENT_DEMANGLING_STYLE
70de4a1d01951937632098a6cda45859afa587a06fsewardj#define CURRENT_DEMANGLING_STYLE work->options
714f2683ace412ca2c8266f2dd860dee4461df3cafsewardj#endif /* ! in valgrind */
72de4a1d01951937632098a6cda45859afa587a06fsewardj
734f2683ace412ca2c8266f2dd860dee4461df3cafsewardj#if 0 /* in valgrind */
744f2683ace412ca2c8266f2dd860dee4461df3cafsewardj#include "libiberty.h"
754f2683ace412ca2c8266f2dd860dee4461df3cafsewardj#endif /* ! in valgrind */
76de4a1d01951937632098a6cda45859afa587a06fsewardj
774f2683ace412ca2c8266f2dd860dee4461df3cafsewardj#include "vg_libciface.h"
784f2683ace412ca2c8266f2dd860dee4461df3cafsewardj
794f2683ace412ca2c8266f2dd860dee4461df3cafsewardj#include "ansidecl.h"
804f2683ace412ca2c8266f2dd860dee4461df3cafsewardj#include "demangle.h"
814f2683ace412ca2c8266f2dd860dee4461df3cafsewardj#include "safe-ctype.h"
824f2683ace412ca2c8266f2dd860dee4461df3cafsewardj
83de4a1d01951937632098a6cda45859afa587a06fsewardj#define min(X,Y) (((X) < (Y)) ? (X) : (Y))
84de4a1d01951937632098a6cda45859afa587a06fsewardj
85de4a1d01951937632098a6cda45859afa587a06fsewardj/* A value at least one greater than the maximum number of characters
86de4a1d01951937632098a6cda45859afa587a06fsewardj   that will be output when using the `%d' format with `printf'.  */
87de4a1d01951937632098a6cda45859afa587a06fsewardj#define INTBUF_SIZE 32
88de4a1d01951937632098a6cda45859afa587a06fsewardj
894f2683ace412ca2c8266f2dd860dee4461df3cafsewardjextern void fancy_abort (void) ATTRIBUTE_NORETURN;
90de4a1d01951937632098a6cda45859afa587a06fsewardj
91de4a1d01951937632098a6cda45859afa587a06fsewardj/* In order to allow a single demangler executable to demangle strings
92de4a1d01951937632098a6cda45859afa587a06fsewardj   using various common values of CPLUS_MARKER, as well as any specific
93de4a1d01951937632098a6cda45859afa587a06fsewardj   one set at compile time, we maintain a string containing all the
94de4a1d01951937632098a6cda45859afa587a06fsewardj   commonly used ones, and check to see if the marker we are looking for
95de4a1d01951937632098a6cda45859afa587a06fsewardj   is in that string.  CPLUS_MARKER is usually '$' on systems where the
96de4a1d01951937632098a6cda45859afa587a06fsewardj   assembler can deal with that.  Where the assembler can't, it's usually
97de4a1d01951937632098a6cda45859afa587a06fsewardj   '.' (but on many systems '.' is used for other things).  We put the
98de4a1d01951937632098a6cda45859afa587a06fsewardj   current defined CPLUS_MARKER first (which defaults to '$'), followed
99de4a1d01951937632098a6cda45859afa587a06fsewardj   by the next most common value, followed by an explicit '$' in case
100de4a1d01951937632098a6cda45859afa587a06fsewardj   the value of CPLUS_MARKER is not '$'.
101de4a1d01951937632098a6cda45859afa587a06fsewardj
102de4a1d01951937632098a6cda45859afa587a06fsewardj   We could avoid this if we could just get g++ to tell us what the actual
103de4a1d01951937632098a6cda45859afa587a06fsewardj   cplus marker character is as part of the debug information, perhaps by
104de4a1d01951937632098a6cda45859afa587a06fsewardj   ensuring that it is the character that terminates the gcc<n>_compiled
105de4a1d01951937632098a6cda45859afa587a06fsewardj   marker symbol (FIXME).  */
106de4a1d01951937632098a6cda45859afa587a06fsewardj
107de4a1d01951937632098a6cda45859afa587a06fsewardj#if !defined (CPLUS_MARKER)
108de4a1d01951937632098a6cda45859afa587a06fsewardj#define CPLUS_MARKER '$'
109de4a1d01951937632098a6cda45859afa587a06fsewardj#endif
110de4a1d01951937632098a6cda45859afa587a06fsewardj
111de4a1d01951937632098a6cda45859afa587a06fsewardjenum demangling_styles current_demangling_style = auto_demangling;
112de4a1d01951937632098a6cda45859afa587a06fsewardj
113de4a1d01951937632098a6cda45859afa587a06fsewardjstatic char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
114de4a1d01951937632098a6cda45859afa587a06fsewardj
115de4a1d01951937632098a6cda45859afa587a06fsewardjstatic char char_str[2] = { '\000', '\000' };
116de4a1d01951937632098a6cda45859afa587a06fsewardj
117de4a1d01951937632098a6cda45859afa587a06fsewardjvoid
1184f2683ace412ca2c8266f2dd860dee4461df3cafsewardjset_cplus_marker_for_demangling (int ch)
119de4a1d01951937632098a6cda45859afa587a06fsewardj{
120de4a1d01951937632098a6cda45859afa587a06fsewardj  cplus_markers[0] = ch;
121de4a1d01951937632098a6cda45859afa587a06fsewardj}
122de4a1d01951937632098a6cda45859afa587a06fsewardj
123de4a1d01951937632098a6cda45859afa587a06fsewardjtypedef struct string		/* Beware: these aren't required to be */
124de4a1d01951937632098a6cda45859afa587a06fsewardj{				/*  '\0' terminated.  */
125de4a1d01951937632098a6cda45859afa587a06fsewardj  char *b;			/* pointer to start of string */
126de4a1d01951937632098a6cda45859afa587a06fsewardj  char *p;			/* pointer after last character */
127de4a1d01951937632098a6cda45859afa587a06fsewardj  char *e;			/* pointer after end of allocated space */
128de4a1d01951937632098a6cda45859afa587a06fsewardj} string;
129de4a1d01951937632098a6cda45859afa587a06fsewardj
130de4a1d01951937632098a6cda45859afa587a06fsewardj/* Stuff that is shared between sub-routines.
131de4a1d01951937632098a6cda45859afa587a06fsewardj   Using a shared structure allows cplus_demangle to be reentrant.  */
132de4a1d01951937632098a6cda45859afa587a06fsewardj
133de4a1d01951937632098a6cda45859afa587a06fsewardjstruct work_stuff
134de4a1d01951937632098a6cda45859afa587a06fsewardj{
135de4a1d01951937632098a6cda45859afa587a06fsewardj  int options;
136de4a1d01951937632098a6cda45859afa587a06fsewardj  char **typevec;
137de4a1d01951937632098a6cda45859afa587a06fsewardj  char **ktypevec;
138de4a1d01951937632098a6cda45859afa587a06fsewardj  char **btypevec;
139de4a1d01951937632098a6cda45859afa587a06fsewardj  int numk;
140de4a1d01951937632098a6cda45859afa587a06fsewardj  int numb;
141de4a1d01951937632098a6cda45859afa587a06fsewardj  int ksize;
142de4a1d01951937632098a6cda45859afa587a06fsewardj  int bsize;
143de4a1d01951937632098a6cda45859afa587a06fsewardj  int ntypes;
144de4a1d01951937632098a6cda45859afa587a06fsewardj  int typevec_size;
145de4a1d01951937632098a6cda45859afa587a06fsewardj  int constructor;
146de4a1d01951937632098a6cda45859afa587a06fsewardj  int destructor;
147de4a1d01951937632098a6cda45859afa587a06fsewardj  int static_type;	/* A static member function */
148de4a1d01951937632098a6cda45859afa587a06fsewardj  int temp_start;       /* index in demangled to start of template args */
149de4a1d01951937632098a6cda45859afa587a06fsewardj  int type_quals;       /* The type qualifiers.  */
150de4a1d01951937632098a6cda45859afa587a06fsewardj  int dllimported;	/* Symbol imported from a PE DLL */
151de4a1d01951937632098a6cda45859afa587a06fsewardj  char **tmpl_argvec;   /* Template function arguments. */
152de4a1d01951937632098a6cda45859afa587a06fsewardj  int ntmpl_args;       /* The number of template function arguments. */
153de4a1d01951937632098a6cda45859afa587a06fsewardj  int forgetting_types; /* Nonzero if we are not remembering the types
154de4a1d01951937632098a6cda45859afa587a06fsewardj			   we see.  */
155de4a1d01951937632098a6cda45859afa587a06fsewardj  string* previous_argument; /* The last function argument demangled.  */
156de4a1d01951937632098a6cda45859afa587a06fsewardj  int nrepeats;         /* The number of times to repeat the previous
157de4a1d01951937632098a6cda45859afa587a06fsewardj			   argument.  */
158de4a1d01951937632098a6cda45859afa587a06fsewardj};
159de4a1d01951937632098a6cda45859afa587a06fsewardj
160de4a1d01951937632098a6cda45859afa587a06fsewardj#define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
161de4a1d01951937632098a6cda45859afa587a06fsewardj#define PRINT_ARG_TYPES       (work -> options & DMGL_PARAMS)
162de4a1d01951937632098a6cda45859afa587a06fsewardj
163de4a1d01951937632098a6cda45859afa587a06fsewardjstatic const struct optable
164de4a1d01951937632098a6cda45859afa587a06fsewardj{
165de4a1d01951937632098a6cda45859afa587a06fsewardj  const char *const in;
166de4a1d01951937632098a6cda45859afa587a06fsewardj  const char *const out;
167de4a1d01951937632098a6cda45859afa587a06fsewardj  const int flags;
168de4a1d01951937632098a6cda45859afa587a06fsewardj} optable[] = {
169de4a1d01951937632098a6cda45859afa587a06fsewardj  {"nw",	  " new",	DMGL_ANSI},	/* new (1.92,	 ansi) */
170de4a1d01951937632098a6cda45859afa587a06fsewardj  {"dl",	  " delete",	DMGL_ANSI},	/* new (1.92,	 ansi) */
171de4a1d01951937632098a6cda45859afa587a06fsewardj  {"new",	  " new",	0},		/* old (1.91,	 and 1.x) */
172de4a1d01951937632098a6cda45859afa587a06fsewardj  {"delete",	  " delete",	0},		/* old (1.91,	 and 1.x) */
173de4a1d01951937632098a6cda45859afa587a06fsewardj  {"vn",	  " new []",	DMGL_ANSI},	/* GNU, pending ansi */
174de4a1d01951937632098a6cda45859afa587a06fsewardj  {"vd",	  " delete []",	DMGL_ANSI},	/* GNU, pending ansi */
175de4a1d01951937632098a6cda45859afa587a06fsewardj  {"as",	  "=",		DMGL_ANSI},	/* ansi */
176de4a1d01951937632098a6cda45859afa587a06fsewardj  {"ne",	  "!=",		DMGL_ANSI},	/* old, ansi */
177de4a1d01951937632098a6cda45859afa587a06fsewardj  {"eq",	  "==",		DMGL_ANSI},	/* old,	ansi */
178de4a1d01951937632098a6cda45859afa587a06fsewardj  {"ge",	  ">=",		DMGL_ANSI},	/* old,	ansi */
179de4a1d01951937632098a6cda45859afa587a06fsewardj  {"gt",	  ">",		DMGL_ANSI},	/* old,	ansi */
180de4a1d01951937632098a6cda45859afa587a06fsewardj  {"le",	  "<=",		DMGL_ANSI},	/* old,	ansi */
181de4a1d01951937632098a6cda45859afa587a06fsewardj  {"lt",	  "<",		DMGL_ANSI},	/* old,	ansi */
182de4a1d01951937632098a6cda45859afa587a06fsewardj  {"plus",	  "+",		0},		/* old */
183de4a1d01951937632098a6cda45859afa587a06fsewardj  {"pl",	  "+",		DMGL_ANSI},	/* ansi */
184de4a1d01951937632098a6cda45859afa587a06fsewardj  {"apl",	  "+=",		DMGL_ANSI},	/* ansi */
185de4a1d01951937632098a6cda45859afa587a06fsewardj  {"minus",	  "-",		0},		/* old */
186de4a1d01951937632098a6cda45859afa587a06fsewardj  {"mi",	  "-",		DMGL_ANSI},	/* ansi */
187de4a1d01951937632098a6cda45859afa587a06fsewardj  {"ami",	  "-=",		DMGL_ANSI},	/* ansi */
188de4a1d01951937632098a6cda45859afa587a06fsewardj  {"mult",	  "*",		0},		/* old */
189de4a1d01951937632098a6cda45859afa587a06fsewardj  {"ml",	  "*",		DMGL_ANSI},	/* ansi */
190de4a1d01951937632098a6cda45859afa587a06fsewardj  {"amu",	  "*=",		DMGL_ANSI},	/* ansi (ARM/Lucid) */
191de4a1d01951937632098a6cda45859afa587a06fsewardj  {"aml",	  "*=",		DMGL_ANSI},	/* ansi (GNU/g++) */
192de4a1d01951937632098a6cda45859afa587a06fsewardj  {"convert",	  "+",		0},		/* old (unary +) */
193de4a1d01951937632098a6cda45859afa587a06fsewardj  {"negate",	  "-",		0},		/* old (unary -) */
194de4a1d01951937632098a6cda45859afa587a06fsewardj  {"trunc_mod",	  "%",		0},		/* old */
195de4a1d01951937632098a6cda45859afa587a06fsewardj  {"md",	  "%",		DMGL_ANSI},	/* ansi */
196de4a1d01951937632098a6cda45859afa587a06fsewardj  {"amd",	  "%=",		DMGL_ANSI},	/* ansi */
197de4a1d01951937632098a6cda45859afa587a06fsewardj  {"trunc_div",	  "/",		0},		/* old */
198de4a1d01951937632098a6cda45859afa587a06fsewardj  {"dv",	  "/",		DMGL_ANSI},	/* ansi */
199de4a1d01951937632098a6cda45859afa587a06fsewardj  {"adv",	  "/=",		DMGL_ANSI},	/* ansi */
200de4a1d01951937632098a6cda45859afa587a06fsewardj  {"truth_andif", "&&",		0},		/* old */
201de4a1d01951937632098a6cda45859afa587a06fsewardj  {"aa",	  "&&",		DMGL_ANSI},	/* ansi */
202de4a1d01951937632098a6cda45859afa587a06fsewardj  {"truth_orif",  "||",		0},		/* old */
203de4a1d01951937632098a6cda45859afa587a06fsewardj  {"oo",	  "||",		DMGL_ANSI},	/* ansi */
204de4a1d01951937632098a6cda45859afa587a06fsewardj  {"truth_not",	  "!",		0},		/* old */
205de4a1d01951937632098a6cda45859afa587a06fsewardj  {"nt",	  "!",		DMGL_ANSI},	/* ansi */
206de4a1d01951937632098a6cda45859afa587a06fsewardj  {"postincrement","++",	0},		/* old */
207de4a1d01951937632098a6cda45859afa587a06fsewardj  {"pp",	  "++",		DMGL_ANSI},	/* ansi */
208de4a1d01951937632098a6cda45859afa587a06fsewardj  {"postdecrement","--",	0},		/* old */
209de4a1d01951937632098a6cda45859afa587a06fsewardj  {"mm",	  "--",		DMGL_ANSI},	/* ansi */
210de4a1d01951937632098a6cda45859afa587a06fsewardj  {"bit_ior",	  "|",		0},		/* old */
211de4a1d01951937632098a6cda45859afa587a06fsewardj  {"or",	  "|",		DMGL_ANSI},	/* ansi */
212de4a1d01951937632098a6cda45859afa587a06fsewardj  {"aor",	  "|=",		DMGL_ANSI},	/* ansi */
213de4a1d01951937632098a6cda45859afa587a06fsewardj  {"bit_xor",	  "^",		0},		/* old */
214de4a1d01951937632098a6cda45859afa587a06fsewardj  {"er",	  "^",		DMGL_ANSI},	/* ansi */
215de4a1d01951937632098a6cda45859afa587a06fsewardj  {"aer",	  "^=",		DMGL_ANSI},	/* ansi */
216de4a1d01951937632098a6cda45859afa587a06fsewardj  {"bit_and",	  "&",		0},		/* old */
217de4a1d01951937632098a6cda45859afa587a06fsewardj  {"ad",	  "&",		DMGL_ANSI},	/* ansi */
218de4a1d01951937632098a6cda45859afa587a06fsewardj  {"aad",	  "&=",		DMGL_ANSI},	/* ansi */
219de4a1d01951937632098a6cda45859afa587a06fsewardj  {"bit_not",	  "~",		0},		/* old */
220de4a1d01951937632098a6cda45859afa587a06fsewardj  {"co",	  "~",		DMGL_ANSI},	/* ansi */
221de4a1d01951937632098a6cda45859afa587a06fsewardj  {"call",	  "()",		0},		/* old */
222de4a1d01951937632098a6cda45859afa587a06fsewardj  {"cl",	  "()",		DMGL_ANSI},	/* ansi */
223de4a1d01951937632098a6cda45859afa587a06fsewardj  {"alshift",	  "<<",		0},		/* old */
224de4a1d01951937632098a6cda45859afa587a06fsewardj  {"ls",	  "<<",		DMGL_ANSI},	/* ansi */
225de4a1d01951937632098a6cda45859afa587a06fsewardj  {"als",	  "<<=",	DMGL_ANSI},	/* ansi */
226de4a1d01951937632098a6cda45859afa587a06fsewardj  {"arshift",	  ">>",		0},		/* old */
227de4a1d01951937632098a6cda45859afa587a06fsewardj  {"rs",	  ">>",		DMGL_ANSI},	/* ansi */
228de4a1d01951937632098a6cda45859afa587a06fsewardj  {"ars",	  ">>=",	DMGL_ANSI},	/* ansi */
229de4a1d01951937632098a6cda45859afa587a06fsewardj  {"component",	  "->",		0},		/* old */
230de4a1d01951937632098a6cda45859afa587a06fsewardj  {"pt",	  "->",		DMGL_ANSI},	/* ansi; Lucid C++ form */
231de4a1d01951937632098a6cda45859afa587a06fsewardj  {"rf",	  "->",		DMGL_ANSI},	/* ansi; ARM/GNU form */
232de4a1d01951937632098a6cda45859afa587a06fsewardj  {"indirect",	  "*",		0},		/* old */
233de4a1d01951937632098a6cda45859afa587a06fsewardj  {"method_call",  "->()",	0},		/* old */
234de4a1d01951937632098a6cda45859afa587a06fsewardj  {"addr",	  "&",		0},		/* old (unary &) */
235de4a1d01951937632098a6cda45859afa587a06fsewardj  {"array",	  "[]",		0},		/* old */
236de4a1d01951937632098a6cda45859afa587a06fsewardj  {"vc",	  "[]",		DMGL_ANSI},	/* ansi */
237de4a1d01951937632098a6cda45859afa587a06fsewardj  {"compound",	  ", ",		0},		/* old */
238de4a1d01951937632098a6cda45859afa587a06fsewardj  {"cm",	  ", ",		DMGL_ANSI},	/* ansi */
239de4a1d01951937632098a6cda45859afa587a06fsewardj  {"cond",	  "?:",		0},		/* old */
240de4a1d01951937632098a6cda45859afa587a06fsewardj  {"cn",	  "?:",		DMGL_ANSI},	/* pseudo-ansi */
241de4a1d01951937632098a6cda45859afa587a06fsewardj  {"max",	  ">?",		0},		/* old */
242de4a1d01951937632098a6cda45859afa587a06fsewardj  {"mx",	  ">?",		DMGL_ANSI},	/* pseudo-ansi */
243de4a1d01951937632098a6cda45859afa587a06fsewardj  {"min",	  "<?",		0},		/* old */
244de4a1d01951937632098a6cda45859afa587a06fsewardj  {"mn",	  "<?",		DMGL_ANSI},	/* pseudo-ansi */
245de4a1d01951937632098a6cda45859afa587a06fsewardj  {"nop",	  "",		0},		/* old (for operator=) */
246de4a1d01951937632098a6cda45859afa587a06fsewardj  {"rm",	  "->*",	DMGL_ANSI},	/* ansi */
247de4a1d01951937632098a6cda45859afa587a06fsewardj  {"sz",          "sizeof ",    DMGL_ANSI}      /* pseudo-ansi */
248de4a1d01951937632098a6cda45859afa587a06fsewardj};
249de4a1d01951937632098a6cda45859afa587a06fsewardj
250de4a1d01951937632098a6cda45859afa587a06fsewardj/* These values are used to indicate the various type varieties.
251de4a1d01951937632098a6cda45859afa587a06fsewardj   They are all non-zero so that they can be used as `success'
252de4a1d01951937632098a6cda45859afa587a06fsewardj   values.  */
253de4a1d01951937632098a6cda45859afa587a06fsewardjtypedef enum type_kind_t
254de4a1d01951937632098a6cda45859afa587a06fsewardj{
255de4a1d01951937632098a6cda45859afa587a06fsewardj  tk_none,
256de4a1d01951937632098a6cda45859afa587a06fsewardj  tk_pointer,
257de4a1d01951937632098a6cda45859afa587a06fsewardj  tk_reference,
258de4a1d01951937632098a6cda45859afa587a06fsewardj  tk_integral,
259de4a1d01951937632098a6cda45859afa587a06fsewardj  tk_bool,
260de4a1d01951937632098a6cda45859afa587a06fsewardj  tk_char,
261de4a1d01951937632098a6cda45859afa587a06fsewardj  tk_real
262de4a1d01951937632098a6cda45859afa587a06fsewardj} type_kind_t;
263de4a1d01951937632098a6cda45859afa587a06fsewardj
264de4a1d01951937632098a6cda45859afa587a06fsewardjconst struct demangler_engine libiberty_demanglers[] =
265de4a1d01951937632098a6cda45859afa587a06fsewardj{
266de4a1d01951937632098a6cda45859afa587a06fsewardj  {
267de4a1d01951937632098a6cda45859afa587a06fsewardj    NO_DEMANGLING_STYLE_STRING,
268de4a1d01951937632098a6cda45859afa587a06fsewardj    no_demangling,
269de4a1d01951937632098a6cda45859afa587a06fsewardj    "Demangling disabled"
270de4a1d01951937632098a6cda45859afa587a06fsewardj  }
271de4a1d01951937632098a6cda45859afa587a06fsewardj  ,
272de4a1d01951937632098a6cda45859afa587a06fsewardj  {
273de4a1d01951937632098a6cda45859afa587a06fsewardj    AUTO_DEMANGLING_STYLE_STRING,
274de4a1d01951937632098a6cda45859afa587a06fsewardj      auto_demangling,
275de4a1d01951937632098a6cda45859afa587a06fsewardj      "Automatic selection based on executable"
276de4a1d01951937632098a6cda45859afa587a06fsewardj  }
277de4a1d01951937632098a6cda45859afa587a06fsewardj  ,
278de4a1d01951937632098a6cda45859afa587a06fsewardj  {
279de4a1d01951937632098a6cda45859afa587a06fsewardj    GNU_DEMANGLING_STYLE_STRING,
280de4a1d01951937632098a6cda45859afa587a06fsewardj      gnu_demangling,
281de4a1d01951937632098a6cda45859afa587a06fsewardj      "GNU (g++) style demangling"
282de4a1d01951937632098a6cda45859afa587a06fsewardj  }
283de4a1d01951937632098a6cda45859afa587a06fsewardj  ,
284de4a1d01951937632098a6cda45859afa587a06fsewardj  {
285de4a1d01951937632098a6cda45859afa587a06fsewardj    LUCID_DEMANGLING_STYLE_STRING,
286de4a1d01951937632098a6cda45859afa587a06fsewardj      lucid_demangling,
287de4a1d01951937632098a6cda45859afa587a06fsewardj      "Lucid (lcc) style demangling"
288de4a1d01951937632098a6cda45859afa587a06fsewardj  }
289de4a1d01951937632098a6cda45859afa587a06fsewardj  ,
290de4a1d01951937632098a6cda45859afa587a06fsewardj  {
291de4a1d01951937632098a6cda45859afa587a06fsewardj    ARM_DEMANGLING_STYLE_STRING,
292de4a1d01951937632098a6cda45859afa587a06fsewardj      arm_demangling,
293de4a1d01951937632098a6cda45859afa587a06fsewardj      "ARM style demangling"
294de4a1d01951937632098a6cda45859afa587a06fsewardj  }
295de4a1d01951937632098a6cda45859afa587a06fsewardj  ,
296de4a1d01951937632098a6cda45859afa587a06fsewardj  {
297de4a1d01951937632098a6cda45859afa587a06fsewardj    HP_DEMANGLING_STYLE_STRING,
298de4a1d01951937632098a6cda45859afa587a06fsewardj      hp_demangling,
299de4a1d01951937632098a6cda45859afa587a06fsewardj      "HP (aCC) style demangling"
300de4a1d01951937632098a6cda45859afa587a06fsewardj  }
301de4a1d01951937632098a6cda45859afa587a06fsewardj  ,
302de4a1d01951937632098a6cda45859afa587a06fsewardj  {
303de4a1d01951937632098a6cda45859afa587a06fsewardj    EDG_DEMANGLING_STYLE_STRING,
304de4a1d01951937632098a6cda45859afa587a06fsewardj      edg_demangling,
305de4a1d01951937632098a6cda45859afa587a06fsewardj      "EDG style demangling"
306de4a1d01951937632098a6cda45859afa587a06fsewardj  }
307de4a1d01951937632098a6cda45859afa587a06fsewardj  ,
308de4a1d01951937632098a6cda45859afa587a06fsewardj  {
309de4a1d01951937632098a6cda45859afa587a06fsewardj    GNU_V3_DEMANGLING_STYLE_STRING,
310de4a1d01951937632098a6cda45859afa587a06fsewardj    gnu_v3_demangling,
311de4a1d01951937632098a6cda45859afa587a06fsewardj    "GNU (g++) V3 ABI-style demangling"
312de4a1d01951937632098a6cda45859afa587a06fsewardj  }
313de4a1d01951937632098a6cda45859afa587a06fsewardj  ,
314de4a1d01951937632098a6cda45859afa587a06fsewardj  {
315de4a1d01951937632098a6cda45859afa587a06fsewardj    JAVA_DEMANGLING_STYLE_STRING,
316de4a1d01951937632098a6cda45859afa587a06fsewardj    java_demangling,
317de4a1d01951937632098a6cda45859afa587a06fsewardj    "Java style demangling"
318de4a1d01951937632098a6cda45859afa587a06fsewardj  }
319de4a1d01951937632098a6cda45859afa587a06fsewardj  ,
320de4a1d01951937632098a6cda45859afa587a06fsewardj  {
321de4a1d01951937632098a6cda45859afa587a06fsewardj    GNAT_DEMANGLING_STYLE_STRING,
322de4a1d01951937632098a6cda45859afa587a06fsewardj    gnat_demangling,
323de4a1d01951937632098a6cda45859afa587a06fsewardj    "GNAT style demangling"
324de4a1d01951937632098a6cda45859afa587a06fsewardj  }
325de4a1d01951937632098a6cda45859afa587a06fsewardj  ,
326de4a1d01951937632098a6cda45859afa587a06fsewardj  {
327de4a1d01951937632098a6cda45859afa587a06fsewardj    NULL, unknown_demangling, NULL
328de4a1d01951937632098a6cda45859afa587a06fsewardj  }
329de4a1d01951937632098a6cda45859afa587a06fsewardj};
330de4a1d01951937632098a6cda45859afa587a06fsewardj
331de4a1d01951937632098a6cda45859afa587a06fsewardj#define STRING_EMPTY(str)	((str) -> b == (str) -> p)
332de4a1d01951937632098a6cda45859afa587a06fsewardj#define APPEND_BLANK(str)	{if (!STRING_EMPTY(str)) \
333de4a1d01951937632098a6cda45859afa587a06fsewardj    string_append(str, " ");}
334de4a1d01951937632098a6cda45859afa587a06fsewardj#define LEN_STRING(str)         ( (STRING_EMPTY(str))?0:((str)->p - (str)->b))
335de4a1d01951937632098a6cda45859afa587a06fsewardj
336de4a1d01951937632098a6cda45859afa587a06fsewardj/* The scope separator appropriate for the language being demangled.  */
337de4a1d01951937632098a6cda45859afa587a06fsewardj
338de4a1d01951937632098a6cda45859afa587a06fsewardj#define SCOPE_STRING(work) ((work->options & DMGL_JAVA) ? "." : "::")
339de4a1d01951937632098a6cda45859afa587a06fsewardj
340de4a1d01951937632098a6cda45859afa587a06fsewardj#define ARM_VTABLE_STRING "__vtbl__"	/* Lucid/ARM virtual table prefix */
341de4a1d01951937632098a6cda45859afa587a06fsewardj#define ARM_VTABLE_STRLEN 8		/* strlen (ARM_VTABLE_STRING) */
342de4a1d01951937632098a6cda45859afa587a06fsewardj
343de4a1d01951937632098a6cda45859afa587a06fsewardj/* Prototypes for local functions */
344de4a1d01951937632098a6cda45859afa587a06fsewardj
3454f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic void delete_work_stuff (struct work_stuff *);
346de4a1d01951937632098a6cda45859afa587a06fsewardj
3474f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic void delete_non_B_K_work_stuff (struct work_stuff *);
348de4a1d01951937632098a6cda45859afa587a06fsewardj
3494f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic char *mop_up (struct work_stuff *, string *, int);
350de4a1d01951937632098a6cda45859afa587a06fsewardj
3514f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic void squangle_mop_up (struct work_stuff *);
352de4a1d01951937632098a6cda45859afa587a06fsewardj
3534f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic void work_stuff_copy_to_from (struct work_stuff *, struct work_stuff *);
354de4a1d01951937632098a6cda45859afa587a06fsewardj
355de4a1d01951937632098a6cda45859afa587a06fsewardj#if 0
356de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
3574f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_method_args (struct work_stuff *, const char **, string *);
358de4a1d01951937632098a6cda45859afa587a06fsewardj#endif
359de4a1d01951937632098a6cda45859afa587a06fsewardj
360de4a1d01951937632098a6cda45859afa587a06fsewardjstatic char *
3614f2683ace412ca2c8266f2dd860dee4461df3cafsewardjinternal_cplus_demangle (struct work_stuff *, const char *);
362de4a1d01951937632098a6cda45859afa587a06fsewardj
363de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
3644f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_template_template_parm (struct work_stuff *work,
3654f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                                 const char **, string *);
366de4a1d01951937632098a6cda45859afa587a06fsewardj
367de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
3684f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_template (struct work_stuff *work, const char **, string *,
3694f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                   string *, int, int);
370de4a1d01951937632098a6cda45859afa587a06fsewardj
371de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
3721dcee097db02f9ef3ba355162c4373d90d0e895cnjnarm_pt (const char *, int, const char **, const char **);
373de4a1d01951937632098a6cda45859afa587a06fsewardj
374de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
3754f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_class_name (struct work_stuff *, const char **, string *);
376de4a1d01951937632098a6cda45859afa587a06fsewardj
377de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
3784f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_qualified (struct work_stuff *, const char **, string *,
3794f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                    int, int);
380de4a1d01951937632098a6cda45859afa587a06fsewardj
3814f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic int demangle_class (struct work_stuff *, const char **, string *);
382de4a1d01951937632098a6cda45859afa587a06fsewardj
3834f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic int demangle_fund_type (struct work_stuff *, const char **, string *);
384de4a1d01951937632098a6cda45859afa587a06fsewardj
3854f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic int demangle_signature (struct work_stuff *, const char **, string *);
386de4a1d01951937632098a6cda45859afa587a06fsewardj
3874f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic int demangle_prefix (struct work_stuff *, const char **, string *);
388de4a1d01951937632098a6cda45859afa587a06fsewardj
3894f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic int gnu_special (struct work_stuff *, const char **, string *);
390de4a1d01951937632098a6cda45859afa587a06fsewardj
3914f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic int arm_special (const char **, string *);
392de4a1d01951937632098a6cda45859afa587a06fsewardj
3934f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic void string_need (string *, int);
394de4a1d01951937632098a6cda45859afa587a06fsewardj
3954f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic void string_delete (string *);
396de4a1d01951937632098a6cda45859afa587a06fsewardj
397de4a1d01951937632098a6cda45859afa587a06fsewardjstatic void
3984f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstring_init (string *);
399de4a1d01951937632098a6cda45859afa587a06fsewardj
4004f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic void string_clear (string *);
401de4a1d01951937632098a6cda45859afa587a06fsewardj
402de4a1d01951937632098a6cda45859afa587a06fsewardj#if 0
4034f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic int string_empty (string *);
404de4a1d01951937632098a6cda45859afa587a06fsewardj#endif
405de4a1d01951937632098a6cda45859afa587a06fsewardj
4064f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic void string_append (string *, const char *);
407de4a1d01951937632098a6cda45859afa587a06fsewardj
4084f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic void string_appends (string *, string *);
409de4a1d01951937632098a6cda45859afa587a06fsewardj
4104f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic void string_appendn (string *, const char *, int);
411de4a1d01951937632098a6cda45859afa587a06fsewardj
4124f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic void string_prepend (string *, const char *);
413de4a1d01951937632098a6cda45859afa587a06fsewardj
4144f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic void string_prependn (string *, const char *, int);
415de4a1d01951937632098a6cda45859afa587a06fsewardj
4164f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic void string_append_template_idx (string *, int);
417de4a1d01951937632098a6cda45859afa587a06fsewardj
4184f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic int get_count (const char **, int *);
419de4a1d01951937632098a6cda45859afa587a06fsewardj
4204f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic int consume_count (const char **);
421de4a1d01951937632098a6cda45859afa587a06fsewardj
4224f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic int consume_count_with_underscores (const char**);
423de4a1d01951937632098a6cda45859afa587a06fsewardj
4244f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic int demangle_args (struct work_stuff *, const char **, string *);
425de4a1d01951937632098a6cda45859afa587a06fsewardj
4264f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic int demangle_nested_args (struct work_stuff*, const char**, string*);
427de4a1d01951937632098a6cda45859afa587a06fsewardj
4284f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic int do_type (struct work_stuff *, const char **, string *);
429de4a1d01951937632098a6cda45859afa587a06fsewardj
4304f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic int do_arg (struct work_stuff *, const char **, string *);
431de4a1d01951937632098a6cda45859afa587a06fsewardj
4324f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic int
4334f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_function_name (struct work_stuff *, const char **, string *,
4344f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                        const char *);
435de4a1d01951937632098a6cda45859afa587a06fsewardj
436de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
4374f2683ace412ca2c8266f2dd860dee4461df3cafsewardjiterate_demangle_function (struct work_stuff *,
4384f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                           const char **, string *, const char *);
439de4a1d01951937632098a6cda45859afa587a06fsewardj
4404f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic void remember_type (struct work_stuff *, const char *, int);
441de4a1d01951937632098a6cda45859afa587a06fsewardj
4424f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic void remember_Btype (struct work_stuff *, const char *, int, int);
443de4a1d01951937632098a6cda45859afa587a06fsewardj
4444f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic int register_Btype (struct work_stuff *);
445de4a1d01951937632098a6cda45859afa587a06fsewardj
4464f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic void remember_Ktype (struct work_stuff *, const char *, int);
447de4a1d01951937632098a6cda45859afa587a06fsewardj
4484f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic void forget_types (struct work_stuff *);
449de4a1d01951937632098a6cda45859afa587a06fsewardj
4504f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic void forget_B_and_K_types (struct work_stuff *);
451de4a1d01951937632098a6cda45859afa587a06fsewardj
4524f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic void string_prepends (string *, string *);
453de4a1d01951937632098a6cda45859afa587a06fsewardj
454de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
4554f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_template_value_parm (struct work_stuff*, const char**,
4564f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                              string*, type_kind_t);
457de4a1d01951937632098a6cda45859afa587a06fsewardj
458de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
4594f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdo_hpacc_template_const_value (struct work_stuff *, const char **, string *);
460de4a1d01951937632098a6cda45859afa587a06fsewardj
461de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
4624f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdo_hpacc_template_literal (struct work_stuff *, const char **, string *);
463de4a1d01951937632098a6cda45859afa587a06fsewardj
4644f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic int snarf_numeric_literal (const char **, string *);
465de4a1d01951937632098a6cda45859afa587a06fsewardj
466de4a1d01951937632098a6cda45859afa587a06fsewardj/* There is a TYPE_QUAL value for each type qualifier.  They can be
467de4a1d01951937632098a6cda45859afa587a06fsewardj   combined by bitwise-or to form the complete set of qualifiers for a
468de4a1d01951937632098a6cda45859afa587a06fsewardj   type.  */
469de4a1d01951937632098a6cda45859afa587a06fsewardj
470de4a1d01951937632098a6cda45859afa587a06fsewardj#define TYPE_UNQUALIFIED   0x0
471de4a1d01951937632098a6cda45859afa587a06fsewardj#define TYPE_QUAL_CONST    0x1
472de4a1d01951937632098a6cda45859afa587a06fsewardj#define TYPE_QUAL_VOLATILE 0x2
473de4a1d01951937632098a6cda45859afa587a06fsewardj#define TYPE_QUAL_RESTRICT 0x4
474de4a1d01951937632098a6cda45859afa587a06fsewardj
4754f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic int code_for_qualifier (int);
476de4a1d01951937632098a6cda45859afa587a06fsewardj
4774f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic const char* qualifier_string (int);
478de4a1d01951937632098a6cda45859afa587a06fsewardj
4794f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic const char* demangle_qualifier (int);
480de4a1d01951937632098a6cda45859afa587a06fsewardj
4814f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic int demangle_expression (struct work_stuff *, const char **, string *,
4824f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                                type_kind_t);
483de4a1d01951937632098a6cda45859afa587a06fsewardj
484de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
4854f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_integral_value (struct work_stuff *, const char **, string *);
486de4a1d01951937632098a6cda45859afa587a06fsewardj
487de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
4884f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_real_value (struct work_stuff *, const char **, string *);
489de4a1d01951937632098a6cda45859afa587a06fsewardj
490de4a1d01951937632098a6cda45859afa587a06fsewardjstatic void
4914f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_arm_hp_template (struct work_stuff *, const char **, int, string *);
492de4a1d01951937632098a6cda45859afa587a06fsewardj
493de4a1d01951937632098a6cda45859afa587a06fsewardjstatic void
4944f2683ace412ca2c8266f2dd860dee4461df3cafsewardjrecursively_demangle (struct work_stuff *, const char **, string *, int);
495de4a1d01951937632098a6cda45859afa587a06fsewardj
496de4a1d01951937632098a6cda45859afa587a06fsewardj/* Translate count to integer, consuming tokens in the process.
497de4a1d01951937632098a6cda45859afa587a06fsewardj   Conversion terminates on the first non-digit character.
498de4a1d01951937632098a6cda45859afa587a06fsewardj
499de4a1d01951937632098a6cda45859afa587a06fsewardj   Trying to consume something that isn't a count results in no
500de4a1d01951937632098a6cda45859afa587a06fsewardj   consumption of input and a return of -1.
501de4a1d01951937632098a6cda45859afa587a06fsewardj
502de4a1d01951937632098a6cda45859afa587a06fsewardj   Overflow consumes the rest of the digits, and returns -1.  */
503de4a1d01951937632098a6cda45859afa587a06fsewardj
504de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
5054f2683ace412ca2c8266f2dd860dee4461df3cafsewardjconsume_count (const char **type)
506de4a1d01951937632098a6cda45859afa587a06fsewardj{
507de4a1d01951937632098a6cda45859afa587a06fsewardj  int count = 0;
508de4a1d01951937632098a6cda45859afa587a06fsewardj
509de4a1d01951937632098a6cda45859afa587a06fsewardj  if (! ISDIGIT ((unsigned char)**type))
510de4a1d01951937632098a6cda45859afa587a06fsewardj    return -1;
511de4a1d01951937632098a6cda45859afa587a06fsewardj
512de4a1d01951937632098a6cda45859afa587a06fsewardj  while (ISDIGIT ((unsigned char)**type))
513de4a1d01951937632098a6cda45859afa587a06fsewardj    {
514de4a1d01951937632098a6cda45859afa587a06fsewardj      count *= 10;
515de4a1d01951937632098a6cda45859afa587a06fsewardj
516de4a1d01951937632098a6cda45859afa587a06fsewardj      /* Check for overflow.
517de4a1d01951937632098a6cda45859afa587a06fsewardj	 We assume that count is represented using two's-complement;
518de4a1d01951937632098a6cda45859afa587a06fsewardj	 no power of two is divisible by ten, so if an overflow occurs
519de4a1d01951937632098a6cda45859afa587a06fsewardj	 when multiplying by ten, the result will not be a multiple of
520de4a1d01951937632098a6cda45859afa587a06fsewardj	 ten.  */
521de4a1d01951937632098a6cda45859afa587a06fsewardj      if ((count % 10) != 0)
522de4a1d01951937632098a6cda45859afa587a06fsewardj	{
523de4a1d01951937632098a6cda45859afa587a06fsewardj	  while (ISDIGIT ((unsigned char) **type))
524de4a1d01951937632098a6cda45859afa587a06fsewardj	    (*type)++;
525de4a1d01951937632098a6cda45859afa587a06fsewardj	  return -1;
526de4a1d01951937632098a6cda45859afa587a06fsewardj	}
527de4a1d01951937632098a6cda45859afa587a06fsewardj
528de4a1d01951937632098a6cda45859afa587a06fsewardj      count += **type - '0';
529de4a1d01951937632098a6cda45859afa587a06fsewardj      (*type)++;
530de4a1d01951937632098a6cda45859afa587a06fsewardj    }
531de4a1d01951937632098a6cda45859afa587a06fsewardj
532de4a1d01951937632098a6cda45859afa587a06fsewardj  if (count < 0)
533de4a1d01951937632098a6cda45859afa587a06fsewardj    count = -1;
534de4a1d01951937632098a6cda45859afa587a06fsewardj
535de4a1d01951937632098a6cda45859afa587a06fsewardj  return (count);
536de4a1d01951937632098a6cda45859afa587a06fsewardj}
537de4a1d01951937632098a6cda45859afa587a06fsewardj
538de4a1d01951937632098a6cda45859afa587a06fsewardj
539de4a1d01951937632098a6cda45859afa587a06fsewardj/* Like consume_count, but for counts that are preceded and followed
540de4a1d01951937632098a6cda45859afa587a06fsewardj   by '_' if they are greater than 10.  Also, -1 is returned for
541de4a1d01951937632098a6cda45859afa587a06fsewardj   failure, since 0 can be a valid value.  */
542de4a1d01951937632098a6cda45859afa587a06fsewardj
543de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
5444f2683ace412ca2c8266f2dd860dee4461df3cafsewardjconsume_count_with_underscores (const char **mangled)
545de4a1d01951937632098a6cda45859afa587a06fsewardj{
546de4a1d01951937632098a6cda45859afa587a06fsewardj  int idx;
547de4a1d01951937632098a6cda45859afa587a06fsewardj
548de4a1d01951937632098a6cda45859afa587a06fsewardj  if (**mangled == '_')
549de4a1d01951937632098a6cda45859afa587a06fsewardj    {
550de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
551de4a1d01951937632098a6cda45859afa587a06fsewardj      if (!ISDIGIT ((unsigned char)**mangled))
552de4a1d01951937632098a6cda45859afa587a06fsewardj	return -1;
553de4a1d01951937632098a6cda45859afa587a06fsewardj
554de4a1d01951937632098a6cda45859afa587a06fsewardj      idx = consume_count (mangled);
555de4a1d01951937632098a6cda45859afa587a06fsewardj      if (**mangled != '_')
556de4a1d01951937632098a6cda45859afa587a06fsewardj	/* The trailing underscore was missing. */
557de4a1d01951937632098a6cda45859afa587a06fsewardj	return -1;
558de4a1d01951937632098a6cda45859afa587a06fsewardj
559de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
560de4a1d01951937632098a6cda45859afa587a06fsewardj    }
561de4a1d01951937632098a6cda45859afa587a06fsewardj  else
562de4a1d01951937632098a6cda45859afa587a06fsewardj    {
563de4a1d01951937632098a6cda45859afa587a06fsewardj      if (**mangled < '0' || **mangled > '9')
564de4a1d01951937632098a6cda45859afa587a06fsewardj	return -1;
565de4a1d01951937632098a6cda45859afa587a06fsewardj
566de4a1d01951937632098a6cda45859afa587a06fsewardj      idx = **mangled - '0';
567de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
568de4a1d01951937632098a6cda45859afa587a06fsewardj    }
569de4a1d01951937632098a6cda45859afa587a06fsewardj
570de4a1d01951937632098a6cda45859afa587a06fsewardj  return idx;
571de4a1d01951937632098a6cda45859afa587a06fsewardj}
572de4a1d01951937632098a6cda45859afa587a06fsewardj
573de4a1d01951937632098a6cda45859afa587a06fsewardj/* C is the code for a type-qualifier.  Return the TYPE_QUAL
574de4a1d01951937632098a6cda45859afa587a06fsewardj   corresponding to this qualifier.  */
575de4a1d01951937632098a6cda45859afa587a06fsewardj
576de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
5774f2683ace412ca2c8266f2dd860dee4461df3cafsewardjcode_for_qualifier (int c)
578de4a1d01951937632098a6cda45859afa587a06fsewardj{
579de4a1d01951937632098a6cda45859afa587a06fsewardj  switch (c)
580de4a1d01951937632098a6cda45859afa587a06fsewardj    {
581de4a1d01951937632098a6cda45859afa587a06fsewardj    case 'C':
582de4a1d01951937632098a6cda45859afa587a06fsewardj      return TYPE_QUAL_CONST;
583de4a1d01951937632098a6cda45859afa587a06fsewardj
584de4a1d01951937632098a6cda45859afa587a06fsewardj    case 'V':
585de4a1d01951937632098a6cda45859afa587a06fsewardj      return TYPE_QUAL_VOLATILE;
586de4a1d01951937632098a6cda45859afa587a06fsewardj
587de4a1d01951937632098a6cda45859afa587a06fsewardj    case 'u':
588de4a1d01951937632098a6cda45859afa587a06fsewardj      return TYPE_QUAL_RESTRICT;
589de4a1d01951937632098a6cda45859afa587a06fsewardj
590de4a1d01951937632098a6cda45859afa587a06fsewardj    default:
591de4a1d01951937632098a6cda45859afa587a06fsewardj      break;
592de4a1d01951937632098a6cda45859afa587a06fsewardj    }
593de4a1d01951937632098a6cda45859afa587a06fsewardj
594de4a1d01951937632098a6cda45859afa587a06fsewardj  /* C was an invalid qualifier.  */
595de4a1d01951937632098a6cda45859afa587a06fsewardj  abort ();
596de4a1d01951937632098a6cda45859afa587a06fsewardj}
597de4a1d01951937632098a6cda45859afa587a06fsewardj
598de4a1d01951937632098a6cda45859afa587a06fsewardj/* Return the string corresponding to the qualifiers given by
599de4a1d01951937632098a6cda45859afa587a06fsewardj   TYPE_QUALS.  */
600de4a1d01951937632098a6cda45859afa587a06fsewardj
601de4a1d01951937632098a6cda45859afa587a06fsewardjstatic const char*
6024f2683ace412ca2c8266f2dd860dee4461df3cafsewardjqualifier_string (int type_quals)
603de4a1d01951937632098a6cda45859afa587a06fsewardj{
604de4a1d01951937632098a6cda45859afa587a06fsewardj  switch (type_quals)
605de4a1d01951937632098a6cda45859afa587a06fsewardj    {
606de4a1d01951937632098a6cda45859afa587a06fsewardj    case TYPE_UNQUALIFIED:
607de4a1d01951937632098a6cda45859afa587a06fsewardj      return "";
608de4a1d01951937632098a6cda45859afa587a06fsewardj
609de4a1d01951937632098a6cda45859afa587a06fsewardj    case TYPE_QUAL_CONST:
610de4a1d01951937632098a6cda45859afa587a06fsewardj      return "const";
611de4a1d01951937632098a6cda45859afa587a06fsewardj
612de4a1d01951937632098a6cda45859afa587a06fsewardj    case TYPE_QUAL_VOLATILE:
613de4a1d01951937632098a6cda45859afa587a06fsewardj      return "volatile";
614de4a1d01951937632098a6cda45859afa587a06fsewardj
615de4a1d01951937632098a6cda45859afa587a06fsewardj    case TYPE_QUAL_RESTRICT:
616de4a1d01951937632098a6cda45859afa587a06fsewardj      return "__restrict";
617de4a1d01951937632098a6cda45859afa587a06fsewardj
618de4a1d01951937632098a6cda45859afa587a06fsewardj    case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE:
619de4a1d01951937632098a6cda45859afa587a06fsewardj      return "const volatile";
620de4a1d01951937632098a6cda45859afa587a06fsewardj
621de4a1d01951937632098a6cda45859afa587a06fsewardj    case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT:
622de4a1d01951937632098a6cda45859afa587a06fsewardj      return "const __restrict";
623de4a1d01951937632098a6cda45859afa587a06fsewardj
624de4a1d01951937632098a6cda45859afa587a06fsewardj    case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
625de4a1d01951937632098a6cda45859afa587a06fsewardj      return "volatile __restrict";
626de4a1d01951937632098a6cda45859afa587a06fsewardj
627de4a1d01951937632098a6cda45859afa587a06fsewardj    case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
628de4a1d01951937632098a6cda45859afa587a06fsewardj      return "const volatile __restrict";
629de4a1d01951937632098a6cda45859afa587a06fsewardj
630de4a1d01951937632098a6cda45859afa587a06fsewardj    default:
631de4a1d01951937632098a6cda45859afa587a06fsewardj      break;
632de4a1d01951937632098a6cda45859afa587a06fsewardj    }
633de4a1d01951937632098a6cda45859afa587a06fsewardj
634de4a1d01951937632098a6cda45859afa587a06fsewardj  /* TYPE_QUALS was an invalid qualifier set.  */
635de4a1d01951937632098a6cda45859afa587a06fsewardj  abort ();
636de4a1d01951937632098a6cda45859afa587a06fsewardj}
637de4a1d01951937632098a6cda45859afa587a06fsewardj
638de4a1d01951937632098a6cda45859afa587a06fsewardj/* C is the code for a type-qualifier.  Return the string
639de4a1d01951937632098a6cda45859afa587a06fsewardj   corresponding to this qualifier.  This function should only be
640de4a1d01951937632098a6cda45859afa587a06fsewardj   called with a valid qualifier code.  */
641de4a1d01951937632098a6cda45859afa587a06fsewardj
642de4a1d01951937632098a6cda45859afa587a06fsewardjstatic const char*
6434f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_qualifier (int c)
644de4a1d01951937632098a6cda45859afa587a06fsewardj{
645de4a1d01951937632098a6cda45859afa587a06fsewardj  return qualifier_string (code_for_qualifier (c));
646de4a1d01951937632098a6cda45859afa587a06fsewardj}
647de4a1d01951937632098a6cda45859afa587a06fsewardj
648de4a1d01951937632098a6cda45859afa587a06fsewardjint
6494f2683ace412ca2c8266f2dd860dee4461df3cafsewardjcplus_demangle_opname (const char *opname, char *result, int options)
650de4a1d01951937632098a6cda45859afa587a06fsewardj{
651de4a1d01951937632098a6cda45859afa587a06fsewardj  int len, len1, ret;
652de4a1d01951937632098a6cda45859afa587a06fsewardj  string type;
653de4a1d01951937632098a6cda45859afa587a06fsewardj  struct work_stuff work[1];
654de4a1d01951937632098a6cda45859afa587a06fsewardj  const char *tem;
655de4a1d01951937632098a6cda45859afa587a06fsewardj
656de4a1d01951937632098a6cda45859afa587a06fsewardj  len = strlen(opname);
657de4a1d01951937632098a6cda45859afa587a06fsewardj  result[0] = '\0';
658de4a1d01951937632098a6cda45859afa587a06fsewardj  ret = 0;
659de4a1d01951937632098a6cda45859afa587a06fsewardj  memset ((char *) work, 0, sizeof (work));
660de4a1d01951937632098a6cda45859afa587a06fsewardj  work->options = options;
661de4a1d01951937632098a6cda45859afa587a06fsewardj
662de4a1d01951937632098a6cda45859afa587a06fsewardj  if (opname[0] == '_' && opname[1] == '_'
663de4a1d01951937632098a6cda45859afa587a06fsewardj      && opname[2] == 'o' && opname[3] == 'p')
664de4a1d01951937632098a6cda45859afa587a06fsewardj    {
665de4a1d01951937632098a6cda45859afa587a06fsewardj      /* ANSI.  */
666de4a1d01951937632098a6cda45859afa587a06fsewardj      /* type conversion operator.  */
667de4a1d01951937632098a6cda45859afa587a06fsewardj      tem = opname + 4;
668de4a1d01951937632098a6cda45859afa587a06fsewardj      if (do_type (work, &tem, &type))
669de4a1d01951937632098a6cda45859afa587a06fsewardj	{
670de4a1d01951937632098a6cda45859afa587a06fsewardj	  strcat (result, "operator ");
671de4a1d01951937632098a6cda45859afa587a06fsewardj	  strncat (result, type.b, type.p - type.b);
672de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_delete (&type);
673de4a1d01951937632098a6cda45859afa587a06fsewardj	  ret = 1;
674de4a1d01951937632098a6cda45859afa587a06fsewardj	}
675de4a1d01951937632098a6cda45859afa587a06fsewardj    }
676de4a1d01951937632098a6cda45859afa587a06fsewardj  else if (opname[0] == '_' && opname[1] == '_'
677de4a1d01951937632098a6cda45859afa587a06fsewardj	   && ISLOWER((unsigned char)opname[2])
678de4a1d01951937632098a6cda45859afa587a06fsewardj	   && ISLOWER((unsigned char)opname[3]))
679de4a1d01951937632098a6cda45859afa587a06fsewardj    {
680de4a1d01951937632098a6cda45859afa587a06fsewardj      if (opname[4] == '\0')
681de4a1d01951937632098a6cda45859afa587a06fsewardj	{
682de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* Operator.  */
683de4a1d01951937632098a6cda45859afa587a06fsewardj	  size_t i;
684de4a1d01951937632098a6cda45859afa587a06fsewardj	  for (i = 0; i < ARRAY_SIZE (optable); i++)
685de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
686de4a1d01951937632098a6cda45859afa587a06fsewardj	      if (strlen (optable[i].in) == 2
687de4a1d01951937632098a6cda45859afa587a06fsewardj		  && memcmp (optable[i].in, opname + 2, 2) == 0)
688de4a1d01951937632098a6cda45859afa587a06fsewardj		{
689de4a1d01951937632098a6cda45859afa587a06fsewardj		  strcat (result, "operator");
690de4a1d01951937632098a6cda45859afa587a06fsewardj		  strcat (result, optable[i].out);
691de4a1d01951937632098a6cda45859afa587a06fsewardj		  ret = 1;
692de4a1d01951937632098a6cda45859afa587a06fsewardj		  break;
693de4a1d01951937632098a6cda45859afa587a06fsewardj		}
694de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
695de4a1d01951937632098a6cda45859afa587a06fsewardj	}
696de4a1d01951937632098a6cda45859afa587a06fsewardj      else
697de4a1d01951937632098a6cda45859afa587a06fsewardj	{
698de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (opname[2] == 'a' && opname[5] == '\0')
699de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
700de4a1d01951937632098a6cda45859afa587a06fsewardj	      /* Assignment.  */
701de4a1d01951937632098a6cda45859afa587a06fsewardj	      size_t i;
702de4a1d01951937632098a6cda45859afa587a06fsewardj	      for (i = 0; i < ARRAY_SIZE (optable); i++)
703de4a1d01951937632098a6cda45859afa587a06fsewardj		{
704de4a1d01951937632098a6cda45859afa587a06fsewardj		  if (strlen (optable[i].in) == 3
705de4a1d01951937632098a6cda45859afa587a06fsewardj		      && memcmp (optable[i].in, opname + 2, 3) == 0)
706de4a1d01951937632098a6cda45859afa587a06fsewardj		    {
707de4a1d01951937632098a6cda45859afa587a06fsewardj		      strcat (result, "operator");
708de4a1d01951937632098a6cda45859afa587a06fsewardj		      strcat (result, optable[i].out);
709de4a1d01951937632098a6cda45859afa587a06fsewardj		      ret = 1;
710de4a1d01951937632098a6cda45859afa587a06fsewardj		      break;
711de4a1d01951937632098a6cda45859afa587a06fsewardj		    }
712de4a1d01951937632098a6cda45859afa587a06fsewardj		}
713de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
714de4a1d01951937632098a6cda45859afa587a06fsewardj	}
715de4a1d01951937632098a6cda45859afa587a06fsewardj    }
716de4a1d01951937632098a6cda45859afa587a06fsewardj  else if (len >= 3
717de4a1d01951937632098a6cda45859afa587a06fsewardj	   && opname[0] == 'o'
718de4a1d01951937632098a6cda45859afa587a06fsewardj	   && opname[1] == 'p'
719de4a1d01951937632098a6cda45859afa587a06fsewardj	   && strchr (cplus_markers, opname[2]) != NULL)
720de4a1d01951937632098a6cda45859afa587a06fsewardj    {
721de4a1d01951937632098a6cda45859afa587a06fsewardj      /* see if it's an assignment expression */
722de4a1d01951937632098a6cda45859afa587a06fsewardj      if (len >= 10 /* op$assign_ */
723de4a1d01951937632098a6cda45859afa587a06fsewardj	  && memcmp (opname + 3, "assign_", 7) == 0)
724de4a1d01951937632098a6cda45859afa587a06fsewardj	{
725de4a1d01951937632098a6cda45859afa587a06fsewardj	  size_t i;
726de4a1d01951937632098a6cda45859afa587a06fsewardj	  for (i = 0; i < ARRAY_SIZE (optable); i++)
727de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
728de4a1d01951937632098a6cda45859afa587a06fsewardj	      len1 = len - 10;
729de4a1d01951937632098a6cda45859afa587a06fsewardj	      if ((int) strlen (optable[i].in) == len1
730de4a1d01951937632098a6cda45859afa587a06fsewardj		  && memcmp (optable[i].in, opname + 10, len1) == 0)
731de4a1d01951937632098a6cda45859afa587a06fsewardj		{
732de4a1d01951937632098a6cda45859afa587a06fsewardj		  strcat (result, "operator");
733de4a1d01951937632098a6cda45859afa587a06fsewardj		  strcat (result, optable[i].out);
734de4a1d01951937632098a6cda45859afa587a06fsewardj		  strcat (result, "=");
735de4a1d01951937632098a6cda45859afa587a06fsewardj		  ret = 1;
736de4a1d01951937632098a6cda45859afa587a06fsewardj		  break;
737de4a1d01951937632098a6cda45859afa587a06fsewardj		}
738de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
739de4a1d01951937632098a6cda45859afa587a06fsewardj	}
740de4a1d01951937632098a6cda45859afa587a06fsewardj      else
741de4a1d01951937632098a6cda45859afa587a06fsewardj	{
742de4a1d01951937632098a6cda45859afa587a06fsewardj	  size_t i;
743de4a1d01951937632098a6cda45859afa587a06fsewardj	  for (i = 0; i < ARRAY_SIZE (optable); i++)
744de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
745de4a1d01951937632098a6cda45859afa587a06fsewardj	      len1 = len - 3;
746de4a1d01951937632098a6cda45859afa587a06fsewardj	      if ((int) strlen (optable[i].in) == len1
747de4a1d01951937632098a6cda45859afa587a06fsewardj		  && memcmp (optable[i].in, opname + 3, len1) == 0)
748de4a1d01951937632098a6cda45859afa587a06fsewardj		{
749de4a1d01951937632098a6cda45859afa587a06fsewardj		  strcat (result, "operator");
750de4a1d01951937632098a6cda45859afa587a06fsewardj		  strcat (result, optable[i].out);
751de4a1d01951937632098a6cda45859afa587a06fsewardj		  ret = 1;
752de4a1d01951937632098a6cda45859afa587a06fsewardj		  break;
753de4a1d01951937632098a6cda45859afa587a06fsewardj		}
754de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
755de4a1d01951937632098a6cda45859afa587a06fsewardj	}
756de4a1d01951937632098a6cda45859afa587a06fsewardj    }
757de4a1d01951937632098a6cda45859afa587a06fsewardj  else if (len >= 5 && memcmp (opname, "type", 4) == 0
758de4a1d01951937632098a6cda45859afa587a06fsewardj	   && strchr (cplus_markers, opname[4]) != NULL)
759de4a1d01951937632098a6cda45859afa587a06fsewardj    {
760de4a1d01951937632098a6cda45859afa587a06fsewardj      /* type conversion operator */
761de4a1d01951937632098a6cda45859afa587a06fsewardj      tem = opname + 5;
762de4a1d01951937632098a6cda45859afa587a06fsewardj      if (do_type (work, &tem, &type))
763de4a1d01951937632098a6cda45859afa587a06fsewardj	{
764de4a1d01951937632098a6cda45859afa587a06fsewardj	  strcat (result, "operator ");
765de4a1d01951937632098a6cda45859afa587a06fsewardj	  strncat (result, type.b, type.p - type.b);
766de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_delete (&type);
767de4a1d01951937632098a6cda45859afa587a06fsewardj	  ret = 1;
768de4a1d01951937632098a6cda45859afa587a06fsewardj	}
769de4a1d01951937632098a6cda45859afa587a06fsewardj    }
770de4a1d01951937632098a6cda45859afa587a06fsewardj  squangle_mop_up (work);
771de4a1d01951937632098a6cda45859afa587a06fsewardj  return ret;
772de4a1d01951937632098a6cda45859afa587a06fsewardj
773de4a1d01951937632098a6cda45859afa587a06fsewardj}
774de4a1d01951937632098a6cda45859afa587a06fsewardj
775de4a1d01951937632098a6cda45859afa587a06fsewardj/* Takes operator name as e.g. "++" and returns mangled
776de4a1d01951937632098a6cda45859afa587a06fsewardj   operator name (e.g. "postincrement_expr"), or NULL if not found.
777de4a1d01951937632098a6cda45859afa587a06fsewardj
778de4a1d01951937632098a6cda45859afa587a06fsewardj   If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
779de4a1d01951937632098a6cda45859afa587a06fsewardj   if OPTIONS & DMGL_ANSI == 0, return the old GNU name.  */
780de4a1d01951937632098a6cda45859afa587a06fsewardj
781de4a1d01951937632098a6cda45859afa587a06fsewardjconst char *
7824f2683ace412ca2c8266f2dd860dee4461df3cafsewardjcplus_mangle_opname (const char *opname, int options)
783de4a1d01951937632098a6cda45859afa587a06fsewardj{
784de4a1d01951937632098a6cda45859afa587a06fsewardj  size_t i;
785de4a1d01951937632098a6cda45859afa587a06fsewardj  int len;
786de4a1d01951937632098a6cda45859afa587a06fsewardj
787de4a1d01951937632098a6cda45859afa587a06fsewardj  len = strlen (opname);
788de4a1d01951937632098a6cda45859afa587a06fsewardj  for (i = 0; i < ARRAY_SIZE (optable); i++)
789de4a1d01951937632098a6cda45859afa587a06fsewardj    {
790de4a1d01951937632098a6cda45859afa587a06fsewardj      if ((int) strlen (optable[i].out) == len
791de4a1d01951937632098a6cda45859afa587a06fsewardj	  && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
792de4a1d01951937632098a6cda45859afa587a06fsewardj	  && memcmp (optable[i].out, opname, len) == 0)
793de4a1d01951937632098a6cda45859afa587a06fsewardj	return optable[i].in;
794de4a1d01951937632098a6cda45859afa587a06fsewardj    }
795de4a1d01951937632098a6cda45859afa587a06fsewardj  return (0);
796de4a1d01951937632098a6cda45859afa587a06fsewardj}
797de4a1d01951937632098a6cda45859afa587a06fsewardj
798de4a1d01951937632098a6cda45859afa587a06fsewardj/* Add a routine to set the demangling style to be sure it is valid and
799de4a1d01951937632098a6cda45859afa587a06fsewardj   allow for any demangler initialization that maybe necessary. */
800de4a1d01951937632098a6cda45859afa587a06fsewardj
801de4a1d01951937632098a6cda45859afa587a06fsewardjenum demangling_styles
8024f2683ace412ca2c8266f2dd860dee4461df3cafsewardjcplus_demangle_set_style (enum demangling_styles style)
803de4a1d01951937632098a6cda45859afa587a06fsewardj{
804de4a1d01951937632098a6cda45859afa587a06fsewardj  const struct demangler_engine *demangler = libiberty_demanglers;
805de4a1d01951937632098a6cda45859afa587a06fsewardj
806de4a1d01951937632098a6cda45859afa587a06fsewardj  for (; demangler->demangling_style != unknown_demangling; ++demangler)
807de4a1d01951937632098a6cda45859afa587a06fsewardj    if (style == demangler->demangling_style)
808de4a1d01951937632098a6cda45859afa587a06fsewardj      {
809de4a1d01951937632098a6cda45859afa587a06fsewardj	current_demangling_style = style;
810de4a1d01951937632098a6cda45859afa587a06fsewardj	return current_demangling_style;
811de4a1d01951937632098a6cda45859afa587a06fsewardj      }
812de4a1d01951937632098a6cda45859afa587a06fsewardj
813de4a1d01951937632098a6cda45859afa587a06fsewardj  return unknown_demangling;
814de4a1d01951937632098a6cda45859afa587a06fsewardj}
815de4a1d01951937632098a6cda45859afa587a06fsewardj
816de4a1d01951937632098a6cda45859afa587a06fsewardj/* Do string name to style translation */
817de4a1d01951937632098a6cda45859afa587a06fsewardj
818de4a1d01951937632098a6cda45859afa587a06fsewardjenum demangling_styles
8194f2683ace412ca2c8266f2dd860dee4461df3cafsewardjcplus_demangle_name_to_style (const char *name)
820de4a1d01951937632098a6cda45859afa587a06fsewardj{
821de4a1d01951937632098a6cda45859afa587a06fsewardj  const struct demangler_engine *demangler = libiberty_demanglers;
822de4a1d01951937632098a6cda45859afa587a06fsewardj
823de4a1d01951937632098a6cda45859afa587a06fsewardj  for (; demangler->demangling_style != unknown_demangling; ++demangler)
824de4a1d01951937632098a6cda45859afa587a06fsewardj    if (strcmp (name, demangler->demangling_style_name) == 0)
825de4a1d01951937632098a6cda45859afa587a06fsewardj      return demangler->demangling_style;
826de4a1d01951937632098a6cda45859afa587a06fsewardj
827de4a1d01951937632098a6cda45859afa587a06fsewardj  return unknown_demangling;
828de4a1d01951937632098a6cda45859afa587a06fsewardj}
829de4a1d01951937632098a6cda45859afa587a06fsewardj
830de4a1d01951937632098a6cda45859afa587a06fsewardj/* char *cplus_demangle (const char *mangled, int options)
831de4a1d01951937632098a6cda45859afa587a06fsewardj
832de4a1d01951937632098a6cda45859afa587a06fsewardj   If MANGLED is a mangled function name produced by GNU C++, then
833de4a1d01951937632098a6cda45859afa587a06fsewardj   a pointer to a @code{malloc}ed string giving a C++ representation
834de4a1d01951937632098a6cda45859afa587a06fsewardj   of the name will be returned; otherwise NULL will be returned.
835de4a1d01951937632098a6cda45859afa587a06fsewardj   It is the caller's responsibility to free the string which
836de4a1d01951937632098a6cda45859afa587a06fsewardj   is returned.
837de4a1d01951937632098a6cda45859afa587a06fsewardj
838de4a1d01951937632098a6cda45859afa587a06fsewardj   The OPTIONS arg may contain one or more of the following bits:
839de4a1d01951937632098a6cda45859afa587a06fsewardj
840de4a1d01951937632098a6cda45859afa587a06fsewardj   	DMGL_ANSI	ANSI qualifiers such as `const' and `void' are
841de4a1d01951937632098a6cda45859afa587a06fsewardj			included.
842de4a1d01951937632098a6cda45859afa587a06fsewardj	DMGL_PARAMS	Function parameters are included.
843de4a1d01951937632098a6cda45859afa587a06fsewardj
844de4a1d01951937632098a6cda45859afa587a06fsewardj   For example,
845de4a1d01951937632098a6cda45859afa587a06fsewardj
846de4a1d01951937632098a6cda45859afa587a06fsewardj   cplus_demangle ("foo__1Ai", DMGL_PARAMS)		=> "A::foo(int)"
847de4a1d01951937632098a6cda45859afa587a06fsewardj   cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI)	=> "A::foo(int)"
848de4a1d01951937632098a6cda45859afa587a06fsewardj   cplus_demangle ("foo__1Ai", 0)			=> "A::foo"
849de4a1d01951937632098a6cda45859afa587a06fsewardj
850de4a1d01951937632098a6cda45859afa587a06fsewardj   cplus_demangle ("foo__1Afe", DMGL_PARAMS)		=> "A::foo(float,...)"
851de4a1d01951937632098a6cda45859afa587a06fsewardj   cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
852de4a1d01951937632098a6cda45859afa587a06fsewardj   cplus_demangle ("foo__1Afe", 0)			=> "A::foo"
853de4a1d01951937632098a6cda45859afa587a06fsewardj
854de4a1d01951937632098a6cda45859afa587a06fsewardj   Note that any leading underscores, or other such characters prepended by
855de4a1d01951937632098a6cda45859afa587a06fsewardj   the compilation system, are presumed to have already been stripped from
856de4a1d01951937632098a6cda45859afa587a06fsewardj   MANGLED.  */
857de4a1d01951937632098a6cda45859afa587a06fsewardj
858de4a1d01951937632098a6cda45859afa587a06fsewardjchar *
8594f2683ace412ca2c8266f2dd860dee4461df3cafsewardjML_(cplus_demangle) (const char *mangled, int options)
860de4a1d01951937632098a6cda45859afa587a06fsewardj{
861de4a1d01951937632098a6cda45859afa587a06fsewardj  char *ret;
862de4a1d01951937632098a6cda45859afa587a06fsewardj  struct work_stuff work[1];
863de4a1d01951937632098a6cda45859afa587a06fsewardj
864de4a1d01951937632098a6cda45859afa587a06fsewardj  if (current_demangling_style == no_demangling)
8654f2683ace412ca2c8266f2dd860dee4461df3cafsewardj    return xstrdup (mangled);
866de4a1d01951937632098a6cda45859afa587a06fsewardj
867de4a1d01951937632098a6cda45859afa587a06fsewardj  memset ((char *) work, 0, sizeof (work));
868de4a1d01951937632098a6cda45859afa587a06fsewardj  work->options = options;
869de4a1d01951937632098a6cda45859afa587a06fsewardj  if ((work->options & DMGL_STYLE_MASK) == 0)
870de4a1d01951937632098a6cda45859afa587a06fsewardj    work->options |= (int) current_demangling_style & DMGL_STYLE_MASK;
871de4a1d01951937632098a6cda45859afa587a06fsewardj
872de4a1d01951937632098a6cda45859afa587a06fsewardj  /* The V3 ABI demangling is implemented elsewhere.  */
873de4a1d01951937632098a6cda45859afa587a06fsewardj  if (GNU_V3_DEMANGLING || AUTO_DEMANGLING)
874de4a1d01951937632098a6cda45859afa587a06fsewardj    {
8754f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      ret = cplus_demangle_v3 (mangled, work->options);
876de4a1d01951937632098a6cda45859afa587a06fsewardj      if (ret || GNU_V3_DEMANGLING)
877de4a1d01951937632098a6cda45859afa587a06fsewardj	return ret;
878de4a1d01951937632098a6cda45859afa587a06fsewardj    }
879de4a1d01951937632098a6cda45859afa587a06fsewardj
880de4a1d01951937632098a6cda45859afa587a06fsewardj  if (JAVA_DEMANGLING)
881de4a1d01951937632098a6cda45859afa587a06fsewardj    {
8824f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      ret = java_demangle_v3 (mangled);
883de4a1d01951937632098a6cda45859afa587a06fsewardj      if (ret)
884de4a1d01951937632098a6cda45859afa587a06fsewardj        return ret;
885de4a1d01951937632098a6cda45859afa587a06fsewardj    }
886de4a1d01951937632098a6cda45859afa587a06fsewardj
887de4a1d01951937632098a6cda45859afa587a06fsewardj  if (GNAT_DEMANGLING)
8888dc79cec6aa15e11a8b35c4ff781ebaff5811221florian    return ada_demangle (mangled, options);
889de4a1d01951937632098a6cda45859afa587a06fsewardj
890de4a1d01951937632098a6cda45859afa587a06fsewardj  ret = internal_cplus_demangle (work, mangled);
891de4a1d01951937632098a6cda45859afa587a06fsewardj  squangle_mop_up (work);
892de4a1d01951937632098a6cda45859afa587a06fsewardj  return (ret);
893de4a1d01951937632098a6cda45859afa587a06fsewardj}
894de4a1d01951937632098a6cda45859afa587a06fsewardj
8958dc79cec6aa15e11a8b35c4ff781ebaff5811221florian/* Demangle ada names.  The encoding is documented in gcc/ada/exp_dbug.ads.  */
896de4a1d01951937632098a6cda45859afa587a06fsewardj
8978dc79cec6aa15e11a8b35c4ff781ebaff5811221florianchar *
8984f2683ace412ca2c8266f2dd860dee4461df3cafsewardjada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
899de4a1d01951937632098a6cda45859afa587a06fsewardj{
900de4a1d01951937632098a6cda45859afa587a06fsewardj  int len0;
901de4a1d01951937632098a6cda45859afa587a06fsewardj  const char* p;
9028dc79cec6aa15e11a8b35c4ff781ebaff5811221florian  char *d;
9038dc79cec6aa15e11a8b35c4ff781ebaff5811221florian  char *demangled;
904de4a1d01951937632098a6cda45859afa587a06fsewardj
9058dc79cec6aa15e11a8b35c4ff781ebaff5811221florian  /* Discard leading _ada_, which is used for library level subprograms.  */
906de4a1d01951937632098a6cda45859afa587a06fsewardj  if (strncmp (mangled, "_ada_", 5) == 0)
9078dc79cec6aa15e11a8b35c4ff781ebaff5811221florian    mangled += 5;
9088dc79cec6aa15e11a8b35c4ff781ebaff5811221florian
9098dc79cec6aa15e11a8b35c4ff781ebaff5811221florian  /* All ada unit names are lower-case.  */
9108dc79cec6aa15e11a8b35c4ff781ebaff5811221florian  if (!ISLOWER (mangled[0]))
9118dc79cec6aa15e11a8b35c4ff781ebaff5811221florian    goto unknown;
9128dc79cec6aa15e11a8b35c4ff781ebaff5811221florian
9138dc79cec6aa15e11a8b35c4ff781ebaff5811221florian  /* Most of the demangling will trivially remove chars.  Operator names
9148dc79cec6aa15e11a8b35c4ff781ebaff5811221florian     may add one char but because they are always preceeded by '__' which is
9158dc79cec6aa15e11a8b35c4ff781ebaff5811221florian     replaced by '.', they eventually never expand the size.
9168dc79cec6aa15e11a8b35c4ff781ebaff5811221florian     A few special names such as '___elabs' add a few chars (at most 7), but
9178dc79cec6aa15e11a8b35c4ff781ebaff5811221florian     they occur only once.  */
9188dc79cec6aa15e11a8b35c4ff781ebaff5811221florian  len0 = strlen (mangled) + 7 + 1;
9198dc79cec6aa15e11a8b35c4ff781ebaff5811221florian  demangled = XNEWVEC (char, len0);
920de4a1d01951937632098a6cda45859afa587a06fsewardj
9218dc79cec6aa15e11a8b35c4ff781ebaff5811221florian  d = demangled;
9228dc79cec6aa15e11a8b35c4ff781ebaff5811221florian  p = mangled;
9238dc79cec6aa15e11a8b35c4ff781ebaff5811221florian  while (1)
924de4a1d01951937632098a6cda45859afa587a06fsewardj    {
9258dc79cec6aa15e11a8b35c4ff781ebaff5811221florian      /* An entity names is expected.  */
9268dc79cec6aa15e11a8b35c4ff781ebaff5811221florian      if (ISLOWER (*p))
9278dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        {
9288dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          /* An identifier, which is always lower case.  */
9298dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          do
9308dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            *d++ = *p++;
9318dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          while (ISLOWER(*p) || ISDIGIT (*p)
9328dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                 || (p[0] == '_' && (ISLOWER (p[1]) || ISDIGIT (p[1]))));
9338dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        }
9348dc79cec6aa15e11a8b35c4ff781ebaff5811221florian      else if (p[0] == 'O')
9358dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        {
9368dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          /* An operator name.  */
9378dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          static const char * const operators[][2] =
9388dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            {{"Oabs", "abs"},  {"Oand", "and"},    {"Omod", "mod"},
9398dc79cec6aa15e11a8b35c4ff781ebaff5811221florian             {"Onot", "not"},  {"Oor", "or"},      {"Orem", "rem"},
9408dc79cec6aa15e11a8b35c4ff781ebaff5811221florian             {"Oxor", "xor"},  {"Oeq", "="},       {"One", "/="},
9418dc79cec6aa15e11a8b35c4ff781ebaff5811221florian             {"Olt", "<"},     {"Ole", "<="},      {"Ogt", ">"},
9428dc79cec6aa15e11a8b35c4ff781ebaff5811221florian             {"Oge", ">="},    {"Oadd", "+"},      {"Osubtract", "-"},
9438dc79cec6aa15e11a8b35c4ff781ebaff5811221florian             {"Oconcat", "&"}, {"Omultiply", "*"}, {"Odivide", "/"},
9448dc79cec6aa15e11a8b35c4ff781ebaff5811221florian             {"Oexpon", "**"}, {NULL, NULL}};
9458dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          int k;
9468dc79cec6aa15e11a8b35c4ff781ebaff5811221florian
9478dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          for (k = 0; operators[k][0] != NULL; k++)
9488dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            {
9498dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              size_t slen = strlen (operators[k][0]);
9508dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              if (strncmp (p, operators[k][0], slen) == 0)
9518dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                {
9528dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                  p += slen;
9538dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                  slen = strlen (operators[k][1]);
9548dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                  *d++ = '"';
9558dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                  memcpy (d, operators[k][1], slen);
9568dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                  d += slen;
9578dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                  *d++ = '"';
9588dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                  break;
9598dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                }
9608dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            }
9618dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          /* Operator not found.  */
9628dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          if (operators[k][0] == NULL)
9638dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            goto unknown;
9648dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        }
965de4a1d01951937632098a6cda45859afa587a06fsewardj      else
9668dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        {
9678dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          /* Not a GNAT encoding.  */
9688dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          goto unknown;
9698dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        }
9708dc79cec6aa15e11a8b35c4ff781ebaff5811221florian
9718dc79cec6aa15e11a8b35c4ff781ebaff5811221florian      /* The name can be directly followed by some uppercase letters.  */
9728dc79cec6aa15e11a8b35c4ff781ebaff5811221florian      if (p[0] == 'T' && p[1] == 'K')
9738dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        {
9748dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          /* Task stuff.  */
9758dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          if (p[2] == 'B' && p[3] == 0)
9768dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            {
9778dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              /* Subprogram for task body.  */
9788dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              break;
9798dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            }
9808dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          else if (p[2] == '_' && p[3] == '_')
9818dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            {
9828dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              /* Inner declarations in a task.  */
9838dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              p += 4;
9848dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              *d++ = '.';
9858dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              continue;
9868dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            }
9878dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          else
9888dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            goto unknown;
9898dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        }
9908dc79cec6aa15e11a8b35c4ff781ebaff5811221florian      if (p[0] == 'E' && p[1] == 0)
9918dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        {
9928dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          /* Exception name.  */
9938dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          goto unknown;
9948dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        }
9958dc79cec6aa15e11a8b35c4ff781ebaff5811221florian      if ((p[0] == 'P' || p[0] == 'N') && p[1] == 0)
9968dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        {
9978dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          /* Protected type subprogram.  */
9988dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          break;
9998dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        }
10008dc79cec6aa15e11a8b35c4ff781ebaff5811221florian      if ((*p == 'N' || *p == 'S') && p[1] == 0)
10018dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        {
10028dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          /* Enumerated type name table.  */
10038dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          goto unknown;
10048dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        }
10058dc79cec6aa15e11a8b35c4ff781ebaff5811221florian      if (p[0] == 'X')
10068dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        {
10078dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          /* Body nested.  */
10088dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          p++;
10098dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          while (p[0] == 'n' || p[0] == 'b')
10108dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            p++;
10118dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        }
10128dc79cec6aa15e11a8b35c4ff781ebaff5811221florian      if (p[0] == 'S' && p[1] != 0 && (p[2] == '_' || p[2] == 0))
10138dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        {
10148dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          /* Stream operations.  */
10158dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          const char *name;
10168dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          switch (p[1])
10178dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            {
10188dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            case 'R':
10198dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              name = "'Read";
10208dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              break;
10218dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            case 'W':
10228dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              name = "'Write";
10238dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              break;
10248dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            case 'I':
10258dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              name = "'Input";
10268dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              break;
10278dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            case 'O':
10288dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              name = "'Output";
10298dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              break;
10308dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            default:
10318dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              goto unknown;
10328dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            }
10338dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          p += 2;
10348dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          strcpy (d, name);
10358dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          d += strlen (name);
10368dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        }
10378dc79cec6aa15e11a8b35c4ff781ebaff5811221florian      else if (p[0] == 'D')
10388dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        {
10398dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          /* Controlled type operation.  */
10408dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          const char *name;
10418dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          switch (p[1])
10428dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            {
10438dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            case 'F':
10448dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              name = ".Finalize";
10458dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              break;
10468dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            case 'A':
10478dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              name = ".Adjust";
10488dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              break;
10498dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            default:
10508dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              goto unknown;
10518dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            }
10528dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          strcpy (d, name);
10538dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          d += strlen (name);
10548dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          break;
10558dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        }
10568dc79cec6aa15e11a8b35c4ff781ebaff5811221florian
10578dc79cec6aa15e11a8b35c4ff781ebaff5811221florian      if (p[0] == '_')
10588dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        {
10598dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          /* Separator.  */
10608dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          if (p[1] == '_')
10618dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            {
10628dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              /* Standard separator.  Handled first.  */
10638dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              p += 2;
10648dc79cec6aa15e11a8b35c4ff781ebaff5811221florian
10658dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              if (ISDIGIT (*p))
10668dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                {
10678dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                  /* Overloading number.  */
10688dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                  do
10698dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                    p++;
10708dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                  while (ISDIGIT (*p) || (p[0] == '_' && ISDIGIT (p[1])));
10718dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                  if (*p == 'X')
10728dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                    {
10738dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                      p++;
10748dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                      while (p[0] == 'n' || p[0] == 'b')
10758dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                        p++;
10768dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                    }
10778dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                }
10788dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              else if (p[0] == '_' && p[1] != '_')
10798dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                {
10808dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                  /* Special names.  */
10818dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                  static const char * const special[][2] = {
10828dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                    { "_elabb", "'Elab_Body" },
10838dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                    { "_elabs", "'Elab_Spec" },
10848dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                    { "_size", "'Size" },
10858dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                    { "_alignment", "'Alignment" },
10868dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                    { "_assign", ".\":=\"" },
10878dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                    { NULL, NULL }
10888dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                  };
10898dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                  int k;
10908dc79cec6aa15e11a8b35c4ff781ebaff5811221florian
10918dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                  for (k = 0; special[k][0] != NULL; k++)
10928dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                    {
10938dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                      size_t slen = strlen (special[k][0]);
10948dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                      if (strncmp (p, special[k][0], slen) == 0)
10958dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                        {
10968dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                          p += slen;
10978dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                          slen = strlen (special[k][1]);
10988dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                          memcpy (d, special[k][1], slen);
10998dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                          d += slen;
11008dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                          break;
11018dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                        }
11028dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                    }
11038dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                  if (special[k][0] != NULL)
11048dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                    break;
11058dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                  else
11068dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                    goto unknown;
11078dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                }
11088dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              else
11098dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                {
11108dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                  *d++ = '.';
11118dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                  continue;
11128dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                }
11138dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            }
11148dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          else if (p[1] == 'B' || p[1] == 'E')
11158dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            {
11168dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              /* Entry Body or barrier Evaluation.  */
11178dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              p += 2;
11188dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              while (ISDIGIT (*p))
11198dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                p++;
11208dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              if (p[0] == 's' && p[1] == 0)
11218dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                break;
11228dc79cec6aa15e11a8b35c4ff781ebaff5811221florian              else
11238dc79cec6aa15e11a8b35c4ff781ebaff5811221florian                goto unknown;
11248dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            }
11258dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          else
11268dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            goto unknown;
11278dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        }
11288dc79cec6aa15e11a8b35c4ff781ebaff5811221florian
11298dc79cec6aa15e11a8b35c4ff781ebaff5811221florian      if (p[0] == '.' && ISDIGIT (p[1]))
11308dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        {
11318dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          /* Nested subprogram.  */
11328dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          p += 2;
11338dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          while (ISDIGIT (*p))
11348dc79cec6aa15e11a8b35c4ff781ebaff5811221florian            p++;
11358dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        }
11368dc79cec6aa15e11a8b35c4ff781ebaff5811221florian      if (*p == 0)
11378dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        {
11388dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          /* End of mangled name.  */
11398dc79cec6aa15e11a8b35c4ff781ebaff5811221florian          break;
11408dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        }
1141de4a1d01951937632098a6cda45859afa587a06fsewardj      else
11428dc79cec6aa15e11a8b35c4ff781ebaff5811221florian        goto unknown;
1143de4a1d01951937632098a6cda45859afa587a06fsewardj    }
11448dc79cec6aa15e11a8b35c4ff781ebaff5811221florian  *d = 0;
11458dc79cec6aa15e11a8b35c4ff781ebaff5811221florian  return demangled;
1146de4a1d01951937632098a6cda45859afa587a06fsewardj
11478dc79cec6aa15e11a8b35c4ff781ebaff5811221florian unknown:
11488dc79cec6aa15e11a8b35c4ff781ebaff5811221florian  len0 = strlen (mangled);
11498dc79cec6aa15e11a8b35c4ff781ebaff5811221florian  demangled = XNEWVEC (char, len0 + 3);
11504f2683ace412ca2c8266f2dd860dee4461df3cafsewardj
1151de4a1d01951937632098a6cda45859afa587a06fsewardj  if (mangled[0] == '<')
1152de4a1d01951937632098a6cda45859afa587a06fsewardj     strcpy (demangled, mangled);
1153de4a1d01951937632098a6cda45859afa587a06fsewardj  else
1154de4a1d01951937632098a6cda45859afa587a06fsewardj    sprintf (demangled, "<%s>", mangled);
1155de4a1d01951937632098a6cda45859afa587a06fsewardj
1156de4a1d01951937632098a6cda45859afa587a06fsewardj  return demangled;
1157de4a1d01951937632098a6cda45859afa587a06fsewardj}
1158de4a1d01951937632098a6cda45859afa587a06fsewardj
1159de4a1d01951937632098a6cda45859afa587a06fsewardj/* This function performs most of what cplus_demangle use to do, but
1160de4a1d01951937632098a6cda45859afa587a06fsewardj   to be able to demangle a name with a B, K or n code, we need to
1161de4a1d01951937632098a6cda45859afa587a06fsewardj   have a longer term memory of what types have been seen. The original
11627e73e5f52016ca487bf004608bc833ea1aab0953daywalker   now initializes and cleans up the squangle code info, while internal
1163de4a1d01951937632098a6cda45859afa587a06fsewardj   calls go directly to this routine to avoid resetting that info. */
1164de4a1d01951937632098a6cda45859afa587a06fsewardj
1165de4a1d01951937632098a6cda45859afa587a06fsewardjstatic char *
11664f2683ace412ca2c8266f2dd860dee4461df3cafsewardjinternal_cplus_demangle (struct work_stuff *work, const char *mangled)
1167de4a1d01951937632098a6cda45859afa587a06fsewardj{
1168de4a1d01951937632098a6cda45859afa587a06fsewardj
1169de4a1d01951937632098a6cda45859afa587a06fsewardj  string decl;
1170de4a1d01951937632098a6cda45859afa587a06fsewardj  int success = 0;
1171de4a1d01951937632098a6cda45859afa587a06fsewardj  char *demangled = NULL;
1172de4a1d01951937632098a6cda45859afa587a06fsewardj  int s1, s2, s3, s4;
1173de4a1d01951937632098a6cda45859afa587a06fsewardj  s1 = work->constructor;
1174de4a1d01951937632098a6cda45859afa587a06fsewardj  s2 = work->destructor;
1175de4a1d01951937632098a6cda45859afa587a06fsewardj  s3 = work->static_type;
1176de4a1d01951937632098a6cda45859afa587a06fsewardj  s4 = work->type_quals;
1177de4a1d01951937632098a6cda45859afa587a06fsewardj  work->constructor = work->destructor = 0;
1178de4a1d01951937632098a6cda45859afa587a06fsewardj  work->type_quals = TYPE_UNQUALIFIED;
1179de4a1d01951937632098a6cda45859afa587a06fsewardj  work->dllimported = 0;
1180de4a1d01951937632098a6cda45859afa587a06fsewardj
1181de4a1d01951937632098a6cda45859afa587a06fsewardj  if ((mangled != NULL) && (*mangled != '\0'))
1182de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1183de4a1d01951937632098a6cda45859afa587a06fsewardj      string_init (&decl);
1184de4a1d01951937632098a6cda45859afa587a06fsewardj
1185de4a1d01951937632098a6cda45859afa587a06fsewardj      /* First check to see if gnu style demangling is active and if the
1186de4a1d01951937632098a6cda45859afa587a06fsewardj	 string to be demangled contains a CPLUS_MARKER.  If so, attempt to
1187de4a1d01951937632098a6cda45859afa587a06fsewardj	 recognize one of the gnu special forms rather than looking for a
1188de4a1d01951937632098a6cda45859afa587a06fsewardj	 standard prefix.  In particular, don't worry about whether there
1189de4a1d01951937632098a6cda45859afa587a06fsewardj	 is a "__" string in the mangled string.  Consider "_$_5__foo" for
1190de4a1d01951937632098a6cda45859afa587a06fsewardj	 example.  */
1191de4a1d01951937632098a6cda45859afa587a06fsewardj
1192de4a1d01951937632098a6cda45859afa587a06fsewardj      if ((AUTO_DEMANGLING || GNU_DEMANGLING))
1193de4a1d01951937632098a6cda45859afa587a06fsewardj	{
1194de4a1d01951937632098a6cda45859afa587a06fsewardj	  success = gnu_special (work, &mangled, &decl);
1195c9d7582cbe368687ea03acd7a33ca9cb96b7678fflorian	  if (!success)
1196c9d7582cbe368687ea03acd7a33ca9cb96b7678fflorian	    {
1197c9d7582cbe368687ea03acd7a33ca9cb96b7678fflorian	      delete_work_stuff (work);
1198c9d7582cbe368687ea03acd7a33ca9cb96b7678fflorian	      string_delete (&decl);
1199c9d7582cbe368687ea03acd7a33ca9cb96b7678fflorian	    }
1200de4a1d01951937632098a6cda45859afa587a06fsewardj	}
1201de4a1d01951937632098a6cda45859afa587a06fsewardj      if (!success)
1202de4a1d01951937632098a6cda45859afa587a06fsewardj	{
1203de4a1d01951937632098a6cda45859afa587a06fsewardj	  success = demangle_prefix (work, &mangled, &decl);
1204de4a1d01951937632098a6cda45859afa587a06fsewardj	}
1205de4a1d01951937632098a6cda45859afa587a06fsewardj      if (success && (*mangled != '\0'))
1206de4a1d01951937632098a6cda45859afa587a06fsewardj	{
1207de4a1d01951937632098a6cda45859afa587a06fsewardj	  success = demangle_signature (work, &mangled, &decl);
1208de4a1d01951937632098a6cda45859afa587a06fsewardj	}
1209de4a1d01951937632098a6cda45859afa587a06fsewardj      if (work->constructor == 2)
1210de4a1d01951937632098a6cda45859afa587a06fsewardj        {
1211de4a1d01951937632098a6cda45859afa587a06fsewardj          string_prepend (&decl, "global constructors keyed to ");
1212de4a1d01951937632098a6cda45859afa587a06fsewardj          work->constructor = 0;
1213de4a1d01951937632098a6cda45859afa587a06fsewardj        }
1214de4a1d01951937632098a6cda45859afa587a06fsewardj      else if (work->destructor == 2)
1215de4a1d01951937632098a6cda45859afa587a06fsewardj        {
1216de4a1d01951937632098a6cda45859afa587a06fsewardj          string_prepend (&decl, "global destructors keyed to ");
1217de4a1d01951937632098a6cda45859afa587a06fsewardj          work->destructor = 0;
1218de4a1d01951937632098a6cda45859afa587a06fsewardj        }
1219de4a1d01951937632098a6cda45859afa587a06fsewardj      else if (work->dllimported == 1)
1220de4a1d01951937632098a6cda45859afa587a06fsewardj        {
1221de4a1d01951937632098a6cda45859afa587a06fsewardj          string_prepend (&decl, "import stub for ");
1222de4a1d01951937632098a6cda45859afa587a06fsewardj          work->dllimported = 0;
1223de4a1d01951937632098a6cda45859afa587a06fsewardj        }
1224de4a1d01951937632098a6cda45859afa587a06fsewardj      demangled = mop_up (work, &decl, success);
1225de4a1d01951937632098a6cda45859afa587a06fsewardj    }
1226de4a1d01951937632098a6cda45859afa587a06fsewardj  work->constructor = s1;
1227de4a1d01951937632098a6cda45859afa587a06fsewardj  work->destructor = s2;
1228de4a1d01951937632098a6cda45859afa587a06fsewardj  work->static_type = s3;
1229de4a1d01951937632098a6cda45859afa587a06fsewardj  work->type_quals = s4;
1230de4a1d01951937632098a6cda45859afa587a06fsewardj  return demangled;
1231de4a1d01951937632098a6cda45859afa587a06fsewardj}
1232de4a1d01951937632098a6cda45859afa587a06fsewardj
1233de4a1d01951937632098a6cda45859afa587a06fsewardj
1234de4a1d01951937632098a6cda45859afa587a06fsewardj/* Clear out and squangling related storage */
1235de4a1d01951937632098a6cda45859afa587a06fsewardjstatic void
12364f2683ace412ca2c8266f2dd860dee4461df3cafsewardjsquangle_mop_up (struct work_stuff *work)
1237de4a1d01951937632098a6cda45859afa587a06fsewardj{
1238de4a1d01951937632098a6cda45859afa587a06fsewardj  /* clean up the B and K type mangling types. */
1239de4a1d01951937632098a6cda45859afa587a06fsewardj  forget_B_and_K_types (work);
1240de4a1d01951937632098a6cda45859afa587a06fsewardj  if (work -> btypevec != NULL)
1241de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1242de4a1d01951937632098a6cda45859afa587a06fsewardj      free ((char *) work -> btypevec);
1243c9d7582cbe368687ea03acd7a33ca9cb96b7678fflorian      work->btypevec = NULL;
1244de4a1d01951937632098a6cda45859afa587a06fsewardj    }
1245de4a1d01951937632098a6cda45859afa587a06fsewardj  if (work -> ktypevec != NULL)
1246de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1247de4a1d01951937632098a6cda45859afa587a06fsewardj      free ((char *) work -> ktypevec);
1248c9d7582cbe368687ea03acd7a33ca9cb96b7678fflorian      work->ktypevec = NULL;
1249de4a1d01951937632098a6cda45859afa587a06fsewardj    }
1250de4a1d01951937632098a6cda45859afa587a06fsewardj}
1251de4a1d01951937632098a6cda45859afa587a06fsewardj
1252de4a1d01951937632098a6cda45859afa587a06fsewardj
1253de4a1d01951937632098a6cda45859afa587a06fsewardj/* Copy the work state and storage.  */
1254de4a1d01951937632098a6cda45859afa587a06fsewardj
1255de4a1d01951937632098a6cda45859afa587a06fsewardjstatic void
12564f2683ace412ca2c8266f2dd860dee4461df3cafsewardjwork_stuff_copy_to_from (struct work_stuff *to, struct work_stuff *from)
1257de4a1d01951937632098a6cda45859afa587a06fsewardj{
1258de4a1d01951937632098a6cda45859afa587a06fsewardj  int i;
1259de4a1d01951937632098a6cda45859afa587a06fsewardj
1260de4a1d01951937632098a6cda45859afa587a06fsewardj  delete_work_stuff (to);
1261de4a1d01951937632098a6cda45859afa587a06fsewardj
1262de4a1d01951937632098a6cda45859afa587a06fsewardj  /* Shallow-copy scalars.  */
1263de4a1d01951937632098a6cda45859afa587a06fsewardj  memcpy (to, from, sizeof (*to));
1264de4a1d01951937632098a6cda45859afa587a06fsewardj
1265de4a1d01951937632098a6cda45859afa587a06fsewardj  /* Deep-copy dynamic storage.  */
1266de4a1d01951937632098a6cda45859afa587a06fsewardj  if (from->typevec_size)
12674f2683ace412ca2c8266f2dd860dee4461df3cafsewardj    to->typevec = XNEWVEC (char *, from->typevec_size);
1268de4a1d01951937632098a6cda45859afa587a06fsewardj
1269de4a1d01951937632098a6cda45859afa587a06fsewardj  for (i = 0; i < from->ntypes; i++)
1270de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1271de4a1d01951937632098a6cda45859afa587a06fsewardj      int len = strlen (from->typevec[i]) + 1;
1272de4a1d01951937632098a6cda45859afa587a06fsewardj
12734f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      to->typevec[i] = XNEWVEC (char, len);
1274de4a1d01951937632098a6cda45859afa587a06fsewardj      memcpy (to->typevec[i], from->typevec[i], len);
1275de4a1d01951937632098a6cda45859afa587a06fsewardj    }
1276de4a1d01951937632098a6cda45859afa587a06fsewardj
1277de4a1d01951937632098a6cda45859afa587a06fsewardj  if (from->ksize)
12784f2683ace412ca2c8266f2dd860dee4461df3cafsewardj    to->ktypevec = XNEWVEC (char *, from->ksize);
1279de4a1d01951937632098a6cda45859afa587a06fsewardj
1280de4a1d01951937632098a6cda45859afa587a06fsewardj  for (i = 0; i < from->numk; i++)
1281de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1282de4a1d01951937632098a6cda45859afa587a06fsewardj      int len = strlen (from->ktypevec[i]) + 1;
1283de4a1d01951937632098a6cda45859afa587a06fsewardj
12844f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      to->ktypevec[i] = XNEWVEC (char, len);
1285de4a1d01951937632098a6cda45859afa587a06fsewardj      memcpy (to->ktypevec[i], from->ktypevec[i], len);
1286de4a1d01951937632098a6cda45859afa587a06fsewardj    }
1287de4a1d01951937632098a6cda45859afa587a06fsewardj
1288de4a1d01951937632098a6cda45859afa587a06fsewardj  if (from->bsize)
12894f2683ace412ca2c8266f2dd860dee4461df3cafsewardj    to->btypevec = XNEWVEC (char *, from->bsize);
1290de4a1d01951937632098a6cda45859afa587a06fsewardj
1291de4a1d01951937632098a6cda45859afa587a06fsewardj  for (i = 0; i < from->numb; i++)
1292de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1293de4a1d01951937632098a6cda45859afa587a06fsewardj      int len = strlen (from->btypevec[i]) + 1;
1294de4a1d01951937632098a6cda45859afa587a06fsewardj
12954f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      to->btypevec[i] = XNEWVEC (char , len);
1296de4a1d01951937632098a6cda45859afa587a06fsewardj      memcpy (to->btypevec[i], from->btypevec[i], len);
1297de4a1d01951937632098a6cda45859afa587a06fsewardj    }
1298de4a1d01951937632098a6cda45859afa587a06fsewardj
1299de4a1d01951937632098a6cda45859afa587a06fsewardj  if (from->ntmpl_args)
13004f2683ace412ca2c8266f2dd860dee4461df3cafsewardj    to->tmpl_argvec = XNEWVEC (char *, from->ntmpl_args);
1301de4a1d01951937632098a6cda45859afa587a06fsewardj
1302de4a1d01951937632098a6cda45859afa587a06fsewardj  for (i = 0; i < from->ntmpl_args; i++)
1303de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1304de4a1d01951937632098a6cda45859afa587a06fsewardj      int len = strlen (from->tmpl_argvec[i]) + 1;
1305de4a1d01951937632098a6cda45859afa587a06fsewardj
13064f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      to->tmpl_argvec[i] = XNEWVEC (char, len);
1307de4a1d01951937632098a6cda45859afa587a06fsewardj      memcpy (to->tmpl_argvec[i], from->tmpl_argvec[i], len);
1308de4a1d01951937632098a6cda45859afa587a06fsewardj    }
1309de4a1d01951937632098a6cda45859afa587a06fsewardj
1310de4a1d01951937632098a6cda45859afa587a06fsewardj  if (from->previous_argument)
1311de4a1d01951937632098a6cda45859afa587a06fsewardj    {
13124f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      to->previous_argument = XNEW (string);
1313de4a1d01951937632098a6cda45859afa587a06fsewardj      string_init (to->previous_argument);
1314de4a1d01951937632098a6cda45859afa587a06fsewardj      string_appends (to->previous_argument, from->previous_argument);
1315de4a1d01951937632098a6cda45859afa587a06fsewardj    }
1316de4a1d01951937632098a6cda45859afa587a06fsewardj}
1317de4a1d01951937632098a6cda45859afa587a06fsewardj
1318de4a1d01951937632098a6cda45859afa587a06fsewardj
1319de4a1d01951937632098a6cda45859afa587a06fsewardj/* Delete dynamic stuff in work_stuff that is not to be re-used.  */
1320de4a1d01951937632098a6cda45859afa587a06fsewardj
1321de4a1d01951937632098a6cda45859afa587a06fsewardjstatic void
13224f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdelete_non_B_K_work_stuff (struct work_stuff *work)
1323de4a1d01951937632098a6cda45859afa587a06fsewardj{
1324de4a1d01951937632098a6cda45859afa587a06fsewardj  /* Discard the remembered types, if any.  */
1325de4a1d01951937632098a6cda45859afa587a06fsewardj
1326de4a1d01951937632098a6cda45859afa587a06fsewardj  forget_types (work);
1327de4a1d01951937632098a6cda45859afa587a06fsewardj  if (work -> typevec != NULL)
1328de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1329de4a1d01951937632098a6cda45859afa587a06fsewardj      free ((char *) work -> typevec);
1330de4a1d01951937632098a6cda45859afa587a06fsewardj      work -> typevec = NULL;
1331de4a1d01951937632098a6cda45859afa587a06fsewardj      work -> typevec_size = 0;
1332de4a1d01951937632098a6cda45859afa587a06fsewardj    }
1333de4a1d01951937632098a6cda45859afa587a06fsewardj  if (work->tmpl_argvec)
1334de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1335de4a1d01951937632098a6cda45859afa587a06fsewardj      int i;
1336de4a1d01951937632098a6cda45859afa587a06fsewardj
1337de4a1d01951937632098a6cda45859afa587a06fsewardj      for (i = 0; i < work->ntmpl_args; i++)
13388dc79cec6aa15e11a8b35c4ff781ebaff5811221florian	free ((char*) work->tmpl_argvec[i]);
1339de4a1d01951937632098a6cda45859afa587a06fsewardj
1340de4a1d01951937632098a6cda45859afa587a06fsewardj      free ((char*) work->tmpl_argvec);
1341de4a1d01951937632098a6cda45859afa587a06fsewardj      work->tmpl_argvec = NULL;
1342de4a1d01951937632098a6cda45859afa587a06fsewardj    }
1343de4a1d01951937632098a6cda45859afa587a06fsewardj  if (work->previous_argument)
1344de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1345de4a1d01951937632098a6cda45859afa587a06fsewardj      string_delete (work->previous_argument);
1346de4a1d01951937632098a6cda45859afa587a06fsewardj      free ((char*) work->previous_argument);
1347de4a1d01951937632098a6cda45859afa587a06fsewardj      work->previous_argument = NULL;
1348de4a1d01951937632098a6cda45859afa587a06fsewardj    }
1349de4a1d01951937632098a6cda45859afa587a06fsewardj}
1350de4a1d01951937632098a6cda45859afa587a06fsewardj
1351de4a1d01951937632098a6cda45859afa587a06fsewardj
1352de4a1d01951937632098a6cda45859afa587a06fsewardj/* Delete all dynamic storage in work_stuff.  */
1353de4a1d01951937632098a6cda45859afa587a06fsewardjstatic void
13544f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdelete_work_stuff (struct work_stuff *work)
1355de4a1d01951937632098a6cda45859afa587a06fsewardj{
1356de4a1d01951937632098a6cda45859afa587a06fsewardj  delete_non_B_K_work_stuff (work);
1357de4a1d01951937632098a6cda45859afa587a06fsewardj  squangle_mop_up (work);
1358de4a1d01951937632098a6cda45859afa587a06fsewardj}
1359de4a1d01951937632098a6cda45859afa587a06fsewardj
1360de4a1d01951937632098a6cda45859afa587a06fsewardj
1361de4a1d01951937632098a6cda45859afa587a06fsewardj/* Clear out any mangled storage */
1362de4a1d01951937632098a6cda45859afa587a06fsewardj
1363de4a1d01951937632098a6cda45859afa587a06fsewardjstatic char *
13644f2683ace412ca2c8266f2dd860dee4461df3cafsewardjmop_up (struct work_stuff *work, string *declp, int success)
1365de4a1d01951937632098a6cda45859afa587a06fsewardj{
1366de4a1d01951937632098a6cda45859afa587a06fsewardj  char *demangled = NULL;
1367de4a1d01951937632098a6cda45859afa587a06fsewardj
1368de4a1d01951937632098a6cda45859afa587a06fsewardj  delete_non_B_K_work_stuff (work);
1369de4a1d01951937632098a6cda45859afa587a06fsewardj
1370de4a1d01951937632098a6cda45859afa587a06fsewardj  /* If demangling was successful, ensure that the demangled string is null
1371de4a1d01951937632098a6cda45859afa587a06fsewardj     terminated and return it.  Otherwise, free the demangling decl.  */
1372de4a1d01951937632098a6cda45859afa587a06fsewardj
1373de4a1d01951937632098a6cda45859afa587a06fsewardj  if (!success)
1374de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1375de4a1d01951937632098a6cda45859afa587a06fsewardj      string_delete (declp);
1376de4a1d01951937632098a6cda45859afa587a06fsewardj    }
1377de4a1d01951937632098a6cda45859afa587a06fsewardj  else
1378de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1379de4a1d01951937632098a6cda45859afa587a06fsewardj      string_appendn (declp, "", 1);
1380de4a1d01951937632098a6cda45859afa587a06fsewardj      demangled = declp->b;
1381de4a1d01951937632098a6cda45859afa587a06fsewardj    }
1382de4a1d01951937632098a6cda45859afa587a06fsewardj  return (demangled);
1383de4a1d01951937632098a6cda45859afa587a06fsewardj}
1384de4a1d01951937632098a6cda45859afa587a06fsewardj
1385de4a1d01951937632098a6cda45859afa587a06fsewardj/*
1386de4a1d01951937632098a6cda45859afa587a06fsewardj
1387de4a1d01951937632098a6cda45859afa587a06fsewardjLOCAL FUNCTION
1388de4a1d01951937632098a6cda45859afa587a06fsewardj
1389de4a1d01951937632098a6cda45859afa587a06fsewardj	demangle_signature -- demangle the signature part of a mangled name
1390de4a1d01951937632098a6cda45859afa587a06fsewardj
1391de4a1d01951937632098a6cda45859afa587a06fsewardjSYNOPSIS
1392de4a1d01951937632098a6cda45859afa587a06fsewardj
1393de4a1d01951937632098a6cda45859afa587a06fsewardj	static int
1394de4a1d01951937632098a6cda45859afa587a06fsewardj	demangle_signature (struct work_stuff *work, const char **mangled,
1395de4a1d01951937632098a6cda45859afa587a06fsewardj			    string *declp);
1396de4a1d01951937632098a6cda45859afa587a06fsewardj
1397de4a1d01951937632098a6cda45859afa587a06fsewardjDESCRIPTION
1398de4a1d01951937632098a6cda45859afa587a06fsewardj
1399de4a1d01951937632098a6cda45859afa587a06fsewardj	Consume and demangle the signature portion of the mangled name.
1400de4a1d01951937632098a6cda45859afa587a06fsewardj
1401de4a1d01951937632098a6cda45859afa587a06fsewardj	DECLP is the string where demangled output is being built.  At
1402de4a1d01951937632098a6cda45859afa587a06fsewardj	entry it contains the demangled root name from the mangled name
1403de4a1d01951937632098a6cda45859afa587a06fsewardj	prefix.  I.E. either a demangled operator name or the root function
1404de4a1d01951937632098a6cda45859afa587a06fsewardj	name.  In some special cases, it may contain nothing.
1405de4a1d01951937632098a6cda45859afa587a06fsewardj
1406de4a1d01951937632098a6cda45859afa587a06fsewardj	*MANGLED points to the current unconsumed location in the mangled
1407de4a1d01951937632098a6cda45859afa587a06fsewardj	name.  As tokens are consumed and demangling is performed, the
1408de4a1d01951937632098a6cda45859afa587a06fsewardj	pointer is updated to continuously point at the next token to
1409de4a1d01951937632098a6cda45859afa587a06fsewardj	be consumed.
1410de4a1d01951937632098a6cda45859afa587a06fsewardj
1411de4a1d01951937632098a6cda45859afa587a06fsewardj	Demangling GNU style mangled names is nasty because there is no
1412de4a1d01951937632098a6cda45859afa587a06fsewardj	explicit token that marks the start of the outermost function
1413de4a1d01951937632098a6cda45859afa587a06fsewardj	argument list.  */
1414de4a1d01951937632098a6cda45859afa587a06fsewardj
1415de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
14164f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_signature (struct work_stuff *work,
14174f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                    const char **mangled, string *declp)
1418de4a1d01951937632098a6cda45859afa587a06fsewardj{
1419de4a1d01951937632098a6cda45859afa587a06fsewardj  int success = 1;
1420de4a1d01951937632098a6cda45859afa587a06fsewardj  int func_done = 0;
1421de4a1d01951937632098a6cda45859afa587a06fsewardj  int expect_func = 0;
1422de4a1d01951937632098a6cda45859afa587a06fsewardj  int expect_return_type = 0;
1423de4a1d01951937632098a6cda45859afa587a06fsewardj  const char *oldmangled = NULL;
1424de4a1d01951937632098a6cda45859afa587a06fsewardj  string trawname;
1425de4a1d01951937632098a6cda45859afa587a06fsewardj  string tname;
1426de4a1d01951937632098a6cda45859afa587a06fsewardj
1427de4a1d01951937632098a6cda45859afa587a06fsewardj  while (success && (**mangled != '\0'))
1428de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1429de4a1d01951937632098a6cda45859afa587a06fsewardj      switch (**mangled)
1430de4a1d01951937632098a6cda45859afa587a06fsewardj	{
1431de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'Q':
1432de4a1d01951937632098a6cda45859afa587a06fsewardj	  oldmangled = *mangled;
1433de4a1d01951937632098a6cda45859afa587a06fsewardj	  success = demangle_qualified (work, mangled, declp, 1, 0);
1434de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (success)
1435de4a1d01951937632098a6cda45859afa587a06fsewardj	    remember_type (work, oldmangled, *mangled - oldmangled);
1436de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (AUTO_DEMANGLING || GNU_DEMANGLING)
1437de4a1d01951937632098a6cda45859afa587a06fsewardj	    expect_func = 1;
1438de4a1d01951937632098a6cda45859afa587a06fsewardj	  oldmangled = NULL;
1439de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
1440de4a1d01951937632098a6cda45859afa587a06fsewardj
1441de4a1d01951937632098a6cda45859afa587a06fsewardj        case 'K':
14424c245e595b9f6300d3120408ca873f7115d9cc7dnjn	  //oldmangled = *mangled;
1443de4a1d01951937632098a6cda45859afa587a06fsewardj	  success = demangle_qualified (work, mangled, declp, 1, 0);
1444de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (AUTO_DEMANGLING || GNU_DEMANGLING)
1445de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
1446de4a1d01951937632098a6cda45859afa587a06fsewardj	      expect_func = 1;
1447de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
1448de4a1d01951937632098a6cda45859afa587a06fsewardj	  oldmangled = NULL;
1449de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
1450de4a1d01951937632098a6cda45859afa587a06fsewardj
1451de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'S':
1452de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* Static member function */
1453de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (oldmangled == NULL)
1454de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
1455de4a1d01951937632098a6cda45859afa587a06fsewardj	      oldmangled = *mangled;
1456de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
1457de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled)++;
1458de4a1d01951937632098a6cda45859afa587a06fsewardj	  work -> static_type = 1;
1459de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
1460de4a1d01951937632098a6cda45859afa587a06fsewardj
1461de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'C':
1462de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'V':
1463de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'u':
1464de4a1d01951937632098a6cda45859afa587a06fsewardj	  work->type_quals |= code_for_qualifier (**mangled);
1465de4a1d01951937632098a6cda45859afa587a06fsewardj
1466de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* a qualified member function */
1467de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (oldmangled == NULL)
1468de4a1d01951937632098a6cda45859afa587a06fsewardj	    oldmangled = *mangled;
1469de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled)++;
1470de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
1471de4a1d01951937632098a6cda45859afa587a06fsewardj
1472de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'L':
1473de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* Local class name follows after "Lnnn_" */
1474de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (HP_DEMANGLING)
1475de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
1476de4a1d01951937632098a6cda45859afa587a06fsewardj	      while (**mangled && (**mangled != '_'))
1477de4a1d01951937632098a6cda45859afa587a06fsewardj		(*mangled)++;
1478de4a1d01951937632098a6cda45859afa587a06fsewardj	      if (!**mangled)
1479de4a1d01951937632098a6cda45859afa587a06fsewardj		success = 0;
1480de4a1d01951937632098a6cda45859afa587a06fsewardj	      else
1481de4a1d01951937632098a6cda45859afa587a06fsewardj		(*mangled)++;
1482de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
1483de4a1d01951937632098a6cda45859afa587a06fsewardj	  else
1484de4a1d01951937632098a6cda45859afa587a06fsewardj	    success = 0;
1485de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
1486de4a1d01951937632098a6cda45859afa587a06fsewardj
1487de4a1d01951937632098a6cda45859afa587a06fsewardj	case '0': case '1': case '2': case '3': case '4':
1488de4a1d01951937632098a6cda45859afa587a06fsewardj	case '5': case '6': case '7': case '8': case '9':
1489de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (oldmangled == NULL)
1490de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
1491de4a1d01951937632098a6cda45859afa587a06fsewardj	      oldmangled = *mangled;
1492de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
1493de4a1d01951937632098a6cda45859afa587a06fsewardj          work->temp_start = -1; /* uppermost call to demangle_class */
1494de4a1d01951937632098a6cda45859afa587a06fsewardj	  success = demangle_class (work, mangled, declp);
1495de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (success)
1496de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
1497de4a1d01951937632098a6cda45859afa587a06fsewardj	      remember_type (work, oldmangled, *mangled - oldmangled);
1498de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
1499de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (AUTO_DEMANGLING || GNU_DEMANGLING || EDG_DEMANGLING)
1500de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
1501de4a1d01951937632098a6cda45859afa587a06fsewardj              /* EDG and others will have the "F", so we let the loop cycle
1502de4a1d01951937632098a6cda45859afa587a06fsewardj                 if we are looking at one. */
1503de4a1d01951937632098a6cda45859afa587a06fsewardj              if (**mangled != 'F')
1504de4a1d01951937632098a6cda45859afa587a06fsewardj                 expect_func = 1;
1505de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
1506de4a1d01951937632098a6cda45859afa587a06fsewardj	  oldmangled = NULL;
1507de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
1508de4a1d01951937632098a6cda45859afa587a06fsewardj
1509de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'B':
1510de4a1d01951937632098a6cda45859afa587a06fsewardj	  {
1511de4a1d01951937632098a6cda45859afa587a06fsewardj	    string s;
1512de4a1d01951937632098a6cda45859afa587a06fsewardj	    success = do_type (work, mangled, &s);
1513de4a1d01951937632098a6cda45859afa587a06fsewardj	    if (success)
1514de4a1d01951937632098a6cda45859afa587a06fsewardj	      {
1515de4a1d01951937632098a6cda45859afa587a06fsewardj		string_append (&s, SCOPE_STRING (work));
1516de4a1d01951937632098a6cda45859afa587a06fsewardj		string_prepends (declp, &s);
15174f2683ace412ca2c8266f2dd860dee4461df3cafsewardj		string_delete (&s);
1518de4a1d01951937632098a6cda45859afa587a06fsewardj	      }
1519de4a1d01951937632098a6cda45859afa587a06fsewardj	    oldmangled = NULL;
1520de4a1d01951937632098a6cda45859afa587a06fsewardj	    expect_func = 1;
1521de4a1d01951937632098a6cda45859afa587a06fsewardj	  }
1522de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
1523de4a1d01951937632098a6cda45859afa587a06fsewardj
1524de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'F':
1525de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* Function */
1526de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* ARM/HP style demangling includes a specific 'F' character after
1527de4a1d01951937632098a6cda45859afa587a06fsewardj	     the class name.  For GNU style, it is just implied.  So we can
1528de4a1d01951937632098a6cda45859afa587a06fsewardj	     safely just consume any 'F' at this point and be compatible
1529de4a1d01951937632098a6cda45859afa587a06fsewardj	     with either style.  */
1530de4a1d01951937632098a6cda45859afa587a06fsewardj
1531de4a1d01951937632098a6cda45859afa587a06fsewardj	  oldmangled = NULL;
1532de4a1d01951937632098a6cda45859afa587a06fsewardj	  func_done = 1;
1533de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled)++;
1534de4a1d01951937632098a6cda45859afa587a06fsewardj
1535de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* For lucid/ARM/HP style we have to forget any types we might
1536de4a1d01951937632098a6cda45859afa587a06fsewardj	     have remembered up to this point, since they were not argument
1537de4a1d01951937632098a6cda45859afa587a06fsewardj	     types.  GNU style considers all types seen as available for
1538de4a1d01951937632098a6cda45859afa587a06fsewardj	     back references.  See comment in demangle_args() */
1539de4a1d01951937632098a6cda45859afa587a06fsewardj
1540de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
1541de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
1542de4a1d01951937632098a6cda45859afa587a06fsewardj	      forget_types (work);
1543de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
1544de4a1d01951937632098a6cda45859afa587a06fsewardj	  success = demangle_args (work, mangled, declp);
1545de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* After picking off the function args, we expect to either
1546de4a1d01951937632098a6cda45859afa587a06fsewardj	     find the function return type (preceded by an '_') or the
1547de4a1d01951937632098a6cda45859afa587a06fsewardj	     end of the string. */
1548de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (success && (AUTO_DEMANGLING || EDG_DEMANGLING) && **mangled == '_')
1549de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
1550de4a1d01951937632098a6cda45859afa587a06fsewardj	      ++(*mangled);
1551de4a1d01951937632098a6cda45859afa587a06fsewardj              /* At this level, we do not care about the return type. */
1552de4a1d01951937632098a6cda45859afa587a06fsewardj              success = do_type (work, mangled, &tname);
1553de4a1d01951937632098a6cda45859afa587a06fsewardj              string_delete (&tname);
1554de4a1d01951937632098a6cda45859afa587a06fsewardj            }
1555de4a1d01951937632098a6cda45859afa587a06fsewardj
1556de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
1557de4a1d01951937632098a6cda45859afa587a06fsewardj
1558de4a1d01951937632098a6cda45859afa587a06fsewardj	case 't':
1559de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* G++ Template */
1560de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_init(&trawname);
1561de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_init(&tname);
1562de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (oldmangled == NULL)
1563de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
1564de4a1d01951937632098a6cda45859afa587a06fsewardj	      oldmangled = *mangled;
1565de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
1566de4a1d01951937632098a6cda45859afa587a06fsewardj	  success = demangle_template (work, mangled, &tname,
1567de4a1d01951937632098a6cda45859afa587a06fsewardj				       &trawname, 1, 1);
1568de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (success)
1569de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
1570de4a1d01951937632098a6cda45859afa587a06fsewardj	      remember_type (work, oldmangled, *mangled - oldmangled);
1571de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
1572de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_append (&tname, SCOPE_STRING (work));
1573de4a1d01951937632098a6cda45859afa587a06fsewardj
1574de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_prepends(declp, &tname);
1575de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (work -> destructor & 1)
1576de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
1577de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_prepend (&trawname, "~");
1578de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_appends (declp, &trawname);
1579de4a1d01951937632098a6cda45859afa587a06fsewardj	      work->destructor -= 1;
1580de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
1581de4a1d01951937632098a6cda45859afa587a06fsewardj	  if ((work->constructor & 1) || (work->destructor & 1))
1582de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
1583de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_appends (declp, &trawname);
1584de4a1d01951937632098a6cda45859afa587a06fsewardj	      work->constructor -= 1;
1585de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
1586de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_delete(&trawname);
1587de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_delete(&tname);
1588de4a1d01951937632098a6cda45859afa587a06fsewardj	  oldmangled = NULL;
1589de4a1d01951937632098a6cda45859afa587a06fsewardj	  expect_func = 1;
1590de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
1591de4a1d01951937632098a6cda45859afa587a06fsewardj
1592de4a1d01951937632098a6cda45859afa587a06fsewardj	case '_':
1593de4a1d01951937632098a6cda45859afa587a06fsewardj	  if ((AUTO_DEMANGLING || GNU_DEMANGLING) && expect_return_type)
1594de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
1595de4a1d01951937632098a6cda45859afa587a06fsewardj	      /* Read the return type. */
1596de4a1d01951937632098a6cda45859afa587a06fsewardj	      string return_type;
1597de4a1d01951937632098a6cda45859afa587a06fsewardj
1598de4a1d01951937632098a6cda45859afa587a06fsewardj	      (*mangled)++;
1599de4a1d01951937632098a6cda45859afa587a06fsewardj	      success = do_type (work, mangled, &return_type);
1600de4a1d01951937632098a6cda45859afa587a06fsewardj	      APPEND_BLANK (&return_type);
1601de4a1d01951937632098a6cda45859afa587a06fsewardj
1602de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_prepends (declp, &return_type);
1603de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_delete (&return_type);
1604de4a1d01951937632098a6cda45859afa587a06fsewardj	      break;
1605de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
1606de4a1d01951937632098a6cda45859afa587a06fsewardj	  else
1607de4a1d01951937632098a6cda45859afa587a06fsewardj	    /* At the outermost level, we cannot have a return type specified,
1608de4a1d01951937632098a6cda45859afa587a06fsewardj	       so if we run into another '_' at this point we are dealing with
1609de4a1d01951937632098a6cda45859afa587a06fsewardj	       a mangled name that is either bogus, or has been mangled by
1610de4a1d01951937632098a6cda45859afa587a06fsewardj	       some algorithm we don't know how to deal with.  So just
1611de4a1d01951937632098a6cda45859afa587a06fsewardj	       reject the entire demangling.  */
1612de4a1d01951937632098a6cda45859afa587a06fsewardj            /* However, "_nnn" is an expected suffix for alternate entry point
1613de4a1d01951937632098a6cda45859afa587a06fsewardj               numbered nnn for a function, with HP aCC, so skip over that
1614de4a1d01951937632098a6cda45859afa587a06fsewardj               without reporting failure. pai/1997-09-04 */
1615de4a1d01951937632098a6cda45859afa587a06fsewardj            if (HP_DEMANGLING)
1616de4a1d01951937632098a6cda45859afa587a06fsewardj              {
1617de4a1d01951937632098a6cda45859afa587a06fsewardj                (*mangled)++;
1618de4a1d01951937632098a6cda45859afa587a06fsewardj                while (**mangled && ISDIGIT ((unsigned char)**mangled))
1619de4a1d01951937632098a6cda45859afa587a06fsewardj                  (*mangled)++;
1620de4a1d01951937632098a6cda45859afa587a06fsewardj              }
1621de4a1d01951937632098a6cda45859afa587a06fsewardj            else
1622de4a1d01951937632098a6cda45859afa587a06fsewardj	      success = 0;
1623de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
1624de4a1d01951937632098a6cda45859afa587a06fsewardj
1625de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'H':
1626de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (AUTO_DEMANGLING || GNU_DEMANGLING)
1627de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
1628de4a1d01951937632098a6cda45859afa587a06fsewardj	      /* A G++ template function.  Read the template arguments. */
1629de4a1d01951937632098a6cda45859afa587a06fsewardj	      success = demangle_template (work, mangled, declp, 0, 0,
1630de4a1d01951937632098a6cda45859afa587a06fsewardj					   0);
1631de4a1d01951937632098a6cda45859afa587a06fsewardj	      if (!(work->constructor & 1))
1632de4a1d01951937632098a6cda45859afa587a06fsewardj		expect_return_type = 1;
1633de4a1d01951937632098a6cda45859afa587a06fsewardj	      (*mangled)++;
1634de4a1d01951937632098a6cda45859afa587a06fsewardj	      break;
1635de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
1636de4a1d01951937632098a6cda45859afa587a06fsewardj	  else
1637de4a1d01951937632098a6cda45859afa587a06fsewardj	    /* fall through */
1638de4a1d01951937632098a6cda45859afa587a06fsewardj	    {;}
1639de4a1d01951937632098a6cda45859afa587a06fsewardj
1640de4a1d01951937632098a6cda45859afa587a06fsewardj	default:
1641de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (AUTO_DEMANGLING || GNU_DEMANGLING)
1642de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
1643de4a1d01951937632098a6cda45859afa587a06fsewardj	      /* Assume we have stumbled onto the first outermost function
1644de4a1d01951937632098a6cda45859afa587a06fsewardj		 argument token, and start processing args.  */
1645de4a1d01951937632098a6cda45859afa587a06fsewardj	      func_done = 1;
1646de4a1d01951937632098a6cda45859afa587a06fsewardj	      success = demangle_args (work, mangled, declp);
1647de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
1648de4a1d01951937632098a6cda45859afa587a06fsewardj	  else
1649de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
1650de4a1d01951937632098a6cda45859afa587a06fsewardj	      /* Non-GNU demanglers use a specific token to mark the start
1651de4a1d01951937632098a6cda45859afa587a06fsewardj		 of the outermost function argument tokens.  Typically 'F',
1652de4a1d01951937632098a6cda45859afa587a06fsewardj		 for ARM/HP-demangling, for example.  So if we find something
1653de4a1d01951937632098a6cda45859afa587a06fsewardj		 we are not prepared for, it must be an error.  */
1654de4a1d01951937632098a6cda45859afa587a06fsewardj	      success = 0;
1655de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
1656de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
1657de4a1d01951937632098a6cda45859afa587a06fsewardj	}
1658de4a1d01951937632098a6cda45859afa587a06fsewardj      /*
1659de4a1d01951937632098a6cda45859afa587a06fsewardj	if (AUTO_DEMANGLING || GNU_DEMANGLING)
1660de4a1d01951937632098a6cda45859afa587a06fsewardj	*/
1661de4a1d01951937632098a6cda45859afa587a06fsewardj      {
1662de4a1d01951937632098a6cda45859afa587a06fsewardj	if (success && expect_func)
1663de4a1d01951937632098a6cda45859afa587a06fsewardj	  {
1664de4a1d01951937632098a6cda45859afa587a06fsewardj	    func_done = 1;
1665de4a1d01951937632098a6cda45859afa587a06fsewardj              if (LUCID_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING)
1666de4a1d01951937632098a6cda45859afa587a06fsewardj                {
1667de4a1d01951937632098a6cda45859afa587a06fsewardj                  forget_types (work);
1668de4a1d01951937632098a6cda45859afa587a06fsewardj                }
1669de4a1d01951937632098a6cda45859afa587a06fsewardj	    success = demangle_args (work, mangled, declp);
1670de4a1d01951937632098a6cda45859afa587a06fsewardj	    /* Since template include the mangling of their return types,
1671de4a1d01951937632098a6cda45859afa587a06fsewardj	       we must set expect_func to 0 so that we don't try do
1672de4a1d01951937632098a6cda45859afa587a06fsewardj	       demangle more arguments the next time we get here.  */
1673de4a1d01951937632098a6cda45859afa587a06fsewardj	    expect_func = 0;
1674de4a1d01951937632098a6cda45859afa587a06fsewardj	  }
1675de4a1d01951937632098a6cda45859afa587a06fsewardj      }
1676de4a1d01951937632098a6cda45859afa587a06fsewardj    }
1677de4a1d01951937632098a6cda45859afa587a06fsewardj  if (success && !func_done)
1678de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1679de4a1d01951937632098a6cda45859afa587a06fsewardj      if (AUTO_DEMANGLING || GNU_DEMANGLING)
1680de4a1d01951937632098a6cda45859afa587a06fsewardj	{
1681de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
1682de4a1d01951937632098a6cda45859afa587a06fsewardj	     bar__3fooi is 'foo::bar(int)'.  We get here when we find the
1683de4a1d01951937632098a6cda45859afa587a06fsewardj	     first case, and need to ensure that the '(void)' gets added to
1684de4a1d01951937632098a6cda45859afa587a06fsewardj	     the current declp.  Note that with ARM/HP, the first case
1685de4a1d01951937632098a6cda45859afa587a06fsewardj	     represents the name of a static data member 'foo::bar',
1686de4a1d01951937632098a6cda45859afa587a06fsewardj	     which is in the current declp, so we leave it alone.  */
1687de4a1d01951937632098a6cda45859afa587a06fsewardj	  success = demangle_args (work, mangled, declp);
1688de4a1d01951937632098a6cda45859afa587a06fsewardj	}
1689de4a1d01951937632098a6cda45859afa587a06fsewardj    }
1690de4a1d01951937632098a6cda45859afa587a06fsewardj  if (success && PRINT_ARG_TYPES)
1691de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1692de4a1d01951937632098a6cda45859afa587a06fsewardj      if (work->static_type)
1693de4a1d01951937632098a6cda45859afa587a06fsewardj	string_append (declp, " static");
1694de4a1d01951937632098a6cda45859afa587a06fsewardj      if (work->type_quals != TYPE_UNQUALIFIED)
1695de4a1d01951937632098a6cda45859afa587a06fsewardj	{
1696de4a1d01951937632098a6cda45859afa587a06fsewardj	  APPEND_BLANK (declp);
1697de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_append (declp, qualifier_string (work->type_quals));
1698de4a1d01951937632098a6cda45859afa587a06fsewardj	}
1699de4a1d01951937632098a6cda45859afa587a06fsewardj    }
1700de4a1d01951937632098a6cda45859afa587a06fsewardj
1701de4a1d01951937632098a6cda45859afa587a06fsewardj  return (success);
1702de4a1d01951937632098a6cda45859afa587a06fsewardj}
1703de4a1d01951937632098a6cda45859afa587a06fsewardj
1704de4a1d01951937632098a6cda45859afa587a06fsewardj#if 0
1705de4a1d01951937632098a6cda45859afa587a06fsewardj
1706de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
17074f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_method_args (struct work_stuff *work, const char **mangled,
17084f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                      string *declp)
1709de4a1d01951937632098a6cda45859afa587a06fsewardj{
1710de4a1d01951937632098a6cda45859afa587a06fsewardj  int success = 0;
1711de4a1d01951937632098a6cda45859afa587a06fsewardj
1712de4a1d01951937632098a6cda45859afa587a06fsewardj  if (work -> static_type)
1713de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1714de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (declp, *mangled + 1);
1715de4a1d01951937632098a6cda45859afa587a06fsewardj      *mangled += strlen (*mangled);
1716de4a1d01951937632098a6cda45859afa587a06fsewardj      success = 1;
1717de4a1d01951937632098a6cda45859afa587a06fsewardj    }
1718de4a1d01951937632098a6cda45859afa587a06fsewardj  else
1719de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1720de4a1d01951937632098a6cda45859afa587a06fsewardj      success = demangle_args (work, mangled, declp);
1721de4a1d01951937632098a6cda45859afa587a06fsewardj    }
1722de4a1d01951937632098a6cda45859afa587a06fsewardj  return (success);
1723de4a1d01951937632098a6cda45859afa587a06fsewardj}
1724de4a1d01951937632098a6cda45859afa587a06fsewardj
1725de4a1d01951937632098a6cda45859afa587a06fsewardj#endif
1726de4a1d01951937632098a6cda45859afa587a06fsewardj
1727de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
17284f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_template_template_parm (struct work_stuff *work,
17294f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                                 const char **mangled, string *tname)
1730de4a1d01951937632098a6cda45859afa587a06fsewardj{
1731de4a1d01951937632098a6cda45859afa587a06fsewardj  int i;
1732de4a1d01951937632098a6cda45859afa587a06fsewardj  int r;
1733de4a1d01951937632098a6cda45859afa587a06fsewardj  int need_comma = 0;
1734de4a1d01951937632098a6cda45859afa587a06fsewardj  int success = 1;
1735de4a1d01951937632098a6cda45859afa587a06fsewardj  string temp;
1736de4a1d01951937632098a6cda45859afa587a06fsewardj
1737de4a1d01951937632098a6cda45859afa587a06fsewardj  string_append (tname, "template <");
1738de4a1d01951937632098a6cda45859afa587a06fsewardj  /* get size of template parameter list */
1739de4a1d01951937632098a6cda45859afa587a06fsewardj  if (get_count (mangled, &r))
1740de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1741de4a1d01951937632098a6cda45859afa587a06fsewardj      for (i = 0; i < r; i++)
1742de4a1d01951937632098a6cda45859afa587a06fsewardj	{
1743de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (need_comma)
1744de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
1745de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_append (tname, ", ");
1746de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
1747de4a1d01951937632098a6cda45859afa587a06fsewardj
1748de4a1d01951937632098a6cda45859afa587a06fsewardj	    /* Z for type parameters */
1749de4a1d01951937632098a6cda45859afa587a06fsewardj	    if (**mangled == 'Z')
1750de4a1d01951937632098a6cda45859afa587a06fsewardj	      {
1751de4a1d01951937632098a6cda45859afa587a06fsewardj		(*mangled)++;
1752de4a1d01951937632098a6cda45859afa587a06fsewardj		string_append (tname, "class");
1753de4a1d01951937632098a6cda45859afa587a06fsewardj	      }
1754de4a1d01951937632098a6cda45859afa587a06fsewardj	      /* z for template parameters */
1755de4a1d01951937632098a6cda45859afa587a06fsewardj	    else if (**mangled == 'z')
1756de4a1d01951937632098a6cda45859afa587a06fsewardj	      {
1757de4a1d01951937632098a6cda45859afa587a06fsewardj		(*mangled)++;
1758de4a1d01951937632098a6cda45859afa587a06fsewardj		success =
1759de4a1d01951937632098a6cda45859afa587a06fsewardj		  demangle_template_template_parm (work, mangled, tname);
1760de4a1d01951937632098a6cda45859afa587a06fsewardj		if (!success)
1761de4a1d01951937632098a6cda45859afa587a06fsewardj		  {
1762de4a1d01951937632098a6cda45859afa587a06fsewardj		    break;
1763de4a1d01951937632098a6cda45859afa587a06fsewardj		  }
1764de4a1d01951937632098a6cda45859afa587a06fsewardj	      }
1765de4a1d01951937632098a6cda45859afa587a06fsewardj	    else
1766de4a1d01951937632098a6cda45859afa587a06fsewardj	      {
1767de4a1d01951937632098a6cda45859afa587a06fsewardj		/* temp is initialized in do_type */
1768de4a1d01951937632098a6cda45859afa587a06fsewardj		success = do_type (work, mangled, &temp);
1769de4a1d01951937632098a6cda45859afa587a06fsewardj		if (success)
1770de4a1d01951937632098a6cda45859afa587a06fsewardj		  {
1771de4a1d01951937632098a6cda45859afa587a06fsewardj		    string_appends (tname, &temp);
1772de4a1d01951937632098a6cda45859afa587a06fsewardj		  }
1773de4a1d01951937632098a6cda45859afa587a06fsewardj		string_delete(&temp);
1774de4a1d01951937632098a6cda45859afa587a06fsewardj		if (!success)
1775de4a1d01951937632098a6cda45859afa587a06fsewardj		  {
1776de4a1d01951937632098a6cda45859afa587a06fsewardj		    break;
1777de4a1d01951937632098a6cda45859afa587a06fsewardj		  }
1778de4a1d01951937632098a6cda45859afa587a06fsewardj	      }
1779de4a1d01951937632098a6cda45859afa587a06fsewardj	  need_comma = 1;
1780de4a1d01951937632098a6cda45859afa587a06fsewardj	}
1781de4a1d01951937632098a6cda45859afa587a06fsewardj
1782de4a1d01951937632098a6cda45859afa587a06fsewardj    }
1783de4a1d01951937632098a6cda45859afa587a06fsewardj  if (tname->p[-1] == '>')
1784de4a1d01951937632098a6cda45859afa587a06fsewardj    string_append (tname, " ");
1785de4a1d01951937632098a6cda45859afa587a06fsewardj  string_append (tname, "> class");
1786de4a1d01951937632098a6cda45859afa587a06fsewardj  return (success);
1787de4a1d01951937632098a6cda45859afa587a06fsewardj}
1788de4a1d01951937632098a6cda45859afa587a06fsewardj
1789de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
17904f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_expression (struct work_stuff *work, const char **mangled,
17914f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                     string *s, type_kind_t tk)
1792de4a1d01951937632098a6cda45859afa587a06fsewardj{
1793de4a1d01951937632098a6cda45859afa587a06fsewardj  int need_operator = 0;
1794de4a1d01951937632098a6cda45859afa587a06fsewardj  int success;
1795de4a1d01951937632098a6cda45859afa587a06fsewardj
1796de4a1d01951937632098a6cda45859afa587a06fsewardj  success = 1;
1797de4a1d01951937632098a6cda45859afa587a06fsewardj  string_appendn (s, "(", 1);
1798de4a1d01951937632098a6cda45859afa587a06fsewardj  (*mangled)++;
1799de4a1d01951937632098a6cda45859afa587a06fsewardj  while (success && **mangled != 'W' && **mangled != '\0')
1800de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1801de4a1d01951937632098a6cda45859afa587a06fsewardj      if (need_operator)
1802de4a1d01951937632098a6cda45859afa587a06fsewardj	{
1803de4a1d01951937632098a6cda45859afa587a06fsewardj	  size_t i;
1804de4a1d01951937632098a6cda45859afa587a06fsewardj	  size_t len;
1805de4a1d01951937632098a6cda45859afa587a06fsewardj
1806de4a1d01951937632098a6cda45859afa587a06fsewardj	  success = 0;
1807de4a1d01951937632098a6cda45859afa587a06fsewardj
1808de4a1d01951937632098a6cda45859afa587a06fsewardj	  len = strlen (*mangled);
1809de4a1d01951937632098a6cda45859afa587a06fsewardj
18104f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	  for (i = 0; i < ARRAY_SIZE (optable); ++i)
1811de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
1812de4a1d01951937632098a6cda45859afa587a06fsewardj	      size_t l = strlen (optable[i].in);
1813de4a1d01951937632098a6cda45859afa587a06fsewardj
1814de4a1d01951937632098a6cda45859afa587a06fsewardj	      if (l <= len
1815de4a1d01951937632098a6cda45859afa587a06fsewardj		  && memcmp (optable[i].in, *mangled, l) == 0)
1816de4a1d01951937632098a6cda45859afa587a06fsewardj		{
1817de4a1d01951937632098a6cda45859afa587a06fsewardj		  string_appendn (s, " ", 1);
1818de4a1d01951937632098a6cda45859afa587a06fsewardj		  string_append (s, optable[i].out);
1819de4a1d01951937632098a6cda45859afa587a06fsewardj		  string_appendn (s, " ", 1);
1820de4a1d01951937632098a6cda45859afa587a06fsewardj		  success = 1;
1821de4a1d01951937632098a6cda45859afa587a06fsewardj		  (*mangled) += l;
1822de4a1d01951937632098a6cda45859afa587a06fsewardj		  break;
1823de4a1d01951937632098a6cda45859afa587a06fsewardj		}
1824de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
1825de4a1d01951937632098a6cda45859afa587a06fsewardj
1826de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (!success)
1827de4a1d01951937632098a6cda45859afa587a06fsewardj	    break;
1828de4a1d01951937632098a6cda45859afa587a06fsewardj	}
1829de4a1d01951937632098a6cda45859afa587a06fsewardj      else
1830de4a1d01951937632098a6cda45859afa587a06fsewardj	need_operator = 1;
1831de4a1d01951937632098a6cda45859afa587a06fsewardj
1832de4a1d01951937632098a6cda45859afa587a06fsewardj      success = demangle_template_value_parm (work, mangled, s, tk);
1833de4a1d01951937632098a6cda45859afa587a06fsewardj    }
1834de4a1d01951937632098a6cda45859afa587a06fsewardj
1835de4a1d01951937632098a6cda45859afa587a06fsewardj  if (**mangled != 'W')
1836de4a1d01951937632098a6cda45859afa587a06fsewardj    success = 0;
1837de4a1d01951937632098a6cda45859afa587a06fsewardj  else
1838de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1839de4a1d01951937632098a6cda45859afa587a06fsewardj      string_appendn (s, ")", 1);
1840de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
1841de4a1d01951937632098a6cda45859afa587a06fsewardj    }
1842de4a1d01951937632098a6cda45859afa587a06fsewardj
1843de4a1d01951937632098a6cda45859afa587a06fsewardj  return success;
1844de4a1d01951937632098a6cda45859afa587a06fsewardj}
1845de4a1d01951937632098a6cda45859afa587a06fsewardj
1846de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
18474f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_integral_value (struct work_stuff *work,
18484f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                         const char **mangled, string *s)
1849de4a1d01951937632098a6cda45859afa587a06fsewardj{
1850de4a1d01951937632098a6cda45859afa587a06fsewardj  int success;
1851de4a1d01951937632098a6cda45859afa587a06fsewardj
1852de4a1d01951937632098a6cda45859afa587a06fsewardj  if (**mangled == 'E')
1853de4a1d01951937632098a6cda45859afa587a06fsewardj    success = demangle_expression (work, mangled, s, tk_integral);
1854de4a1d01951937632098a6cda45859afa587a06fsewardj  else if (**mangled == 'Q' || **mangled == 'K')
1855de4a1d01951937632098a6cda45859afa587a06fsewardj    success = demangle_qualified (work, mangled, s, 0, 1);
1856de4a1d01951937632098a6cda45859afa587a06fsewardj  else
1857de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1858de4a1d01951937632098a6cda45859afa587a06fsewardj      int value;
1859de4a1d01951937632098a6cda45859afa587a06fsewardj
1860de4a1d01951937632098a6cda45859afa587a06fsewardj      /* By default, we let the number decide whether we shall consume an
1861de4a1d01951937632098a6cda45859afa587a06fsewardj	 underscore.  */
18624f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      int multidigit_without_leading_underscore = 0;
1863de4a1d01951937632098a6cda45859afa587a06fsewardj      int leave_following_underscore = 0;
1864de4a1d01951937632098a6cda45859afa587a06fsewardj
1865de4a1d01951937632098a6cda45859afa587a06fsewardj      success = 0;
1866de4a1d01951937632098a6cda45859afa587a06fsewardj
18674f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      if (**mangled == '_')
18684f2683ace412ca2c8266f2dd860dee4461df3cafsewardj        {
18694f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	  if (mangled[0][1] == 'm')
18704f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	    {
18714f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	      /* Since consume_count_with_underscores does not handle the
18724f2683ace412ca2c8266f2dd860dee4461df3cafsewardj		 `m'-prefix we must do it here, using consume_count and
18734f2683ace412ca2c8266f2dd860dee4461df3cafsewardj		 adjusting underscores: we have to consume the underscore
18744f2683ace412ca2c8266f2dd860dee4461df3cafsewardj		 matching the prepended one.  */
18754f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	      multidigit_without_leading_underscore = 1;
18764f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	      string_appendn (s, "-", 1);
18774f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	      (*mangled) += 2;
18784f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	    }
18794f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	  else
18804f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	    {
18814f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	      /* Do not consume a following underscore;
18824f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	         consume_count_with_underscores will consume what
18834f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	         should be consumed.  */
18844f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	      leave_following_underscore = 1;
18854f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	    }
1886de4a1d01951937632098a6cda45859afa587a06fsewardj	}
18874f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      else
1888de4a1d01951937632098a6cda45859afa587a06fsewardj	{
18894f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	  /* Negative numbers are indicated with a leading `m'.  */
18904f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	  if (**mangled == 'm')
18914f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	  {
18924f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	    string_appendn (s, "-", 1);
18934f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	    (*mangled)++;
18944f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	  }
18954f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	  /* Since consume_count_with_underscores does not handle
18964f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	     multi-digit numbers that do not start with an underscore,
18974f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	     and this number can be an integer template parameter,
18984f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	     we have to call consume_count. */
18994f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	  multidigit_without_leading_underscore = 1;
19004f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	  /* These multi-digit numbers never end on an underscore,
19014f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	     so if there is one then don't eat it. */
1902de4a1d01951937632098a6cda45859afa587a06fsewardj	  leave_following_underscore = 1;
1903de4a1d01951937632098a6cda45859afa587a06fsewardj	}
1904de4a1d01951937632098a6cda45859afa587a06fsewardj
1905de4a1d01951937632098a6cda45859afa587a06fsewardj      /* We must call consume_count if we expect to remove a trailing
1906de4a1d01951937632098a6cda45859afa587a06fsewardj	 underscore, since consume_count_with_underscores expects
1907de4a1d01951937632098a6cda45859afa587a06fsewardj	 the leading underscore (that we consumed) if it is to handle
1908de4a1d01951937632098a6cda45859afa587a06fsewardj	 multi-digit numbers.  */
19094f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      if (multidigit_without_leading_underscore)
1910de4a1d01951937632098a6cda45859afa587a06fsewardj	value = consume_count (mangled);
1911de4a1d01951937632098a6cda45859afa587a06fsewardj      else
1912de4a1d01951937632098a6cda45859afa587a06fsewardj	value = consume_count_with_underscores (mangled);
1913de4a1d01951937632098a6cda45859afa587a06fsewardj
1914de4a1d01951937632098a6cda45859afa587a06fsewardj      if (value != -1)
1915de4a1d01951937632098a6cda45859afa587a06fsewardj	{
1916de4a1d01951937632098a6cda45859afa587a06fsewardj	  char buf[INTBUF_SIZE];
1917de4a1d01951937632098a6cda45859afa587a06fsewardj	  sprintf (buf, "%d", value);
1918de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_append (s, buf);
1919de4a1d01951937632098a6cda45859afa587a06fsewardj
1920de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* Numbers not otherwise delimited, might have an underscore
1921de4a1d01951937632098a6cda45859afa587a06fsewardj	     appended as a delimeter, which we should skip.
1922de4a1d01951937632098a6cda45859afa587a06fsewardj
1923de4a1d01951937632098a6cda45859afa587a06fsewardj	     ??? This used to always remove a following underscore, which
1924de4a1d01951937632098a6cda45859afa587a06fsewardj	     is wrong.  If other (arbitrary) cases are followed by an
1925de4a1d01951937632098a6cda45859afa587a06fsewardj	     underscore, we need to do something more radical.  */
1926de4a1d01951937632098a6cda45859afa587a06fsewardj
19274f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	  if ((value > 9 || multidigit_without_leading_underscore)
1928de4a1d01951937632098a6cda45859afa587a06fsewardj	      && ! leave_following_underscore
1929de4a1d01951937632098a6cda45859afa587a06fsewardj	      && **mangled == '_')
1930de4a1d01951937632098a6cda45859afa587a06fsewardj	    (*mangled)++;
1931de4a1d01951937632098a6cda45859afa587a06fsewardj
1932de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* All is well.  */
1933de4a1d01951937632098a6cda45859afa587a06fsewardj	  success = 1;
1934de4a1d01951937632098a6cda45859afa587a06fsewardj	}
19354f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      }
1936de4a1d01951937632098a6cda45859afa587a06fsewardj
1937de4a1d01951937632098a6cda45859afa587a06fsewardj  return success;
1938de4a1d01951937632098a6cda45859afa587a06fsewardj}
1939de4a1d01951937632098a6cda45859afa587a06fsewardj
1940de4a1d01951937632098a6cda45859afa587a06fsewardj/* Demangle the real value in MANGLED.  */
1941de4a1d01951937632098a6cda45859afa587a06fsewardj
1942de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
19434f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_real_value (struct work_stuff *work,
19444f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                     const char **mangled, string *s)
1945de4a1d01951937632098a6cda45859afa587a06fsewardj{
1946de4a1d01951937632098a6cda45859afa587a06fsewardj  if (**mangled == 'E')
1947de4a1d01951937632098a6cda45859afa587a06fsewardj    return demangle_expression (work, mangled, s, tk_real);
1948de4a1d01951937632098a6cda45859afa587a06fsewardj
1949de4a1d01951937632098a6cda45859afa587a06fsewardj  if (**mangled == 'm')
1950de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1951de4a1d01951937632098a6cda45859afa587a06fsewardj      string_appendn (s, "-", 1);
1952de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
1953de4a1d01951937632098a6cda45859afa587a06fsewardj    }
1954de4a1d01951937632098a6cda45859afa587a06fsewardj  while (ISDIGIT ((unsigned char)**mangled))
1955de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1956de4a1d01951937632098a6cda45859afa587a06fsewardj      string_appendn (s, *mangled, 1);
1957de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
1958de4a1d01951937632098a6cda45859afa587a06fsewardj    }
1959de4a1d01951937632098a6cda45859afa587a06fsewardj  if (**mangled == '.') /* fraction */
1960de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1961de4a1d01951937632098a6cda45859afa587a06fsewardj      string_appendn (s, ".", 1);
1962de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
1963de4a1d01951937632098a6cda45859afa587a06fsewardj      while (ISDIGIT ((unsigned char)**mangled))
1964de4a1d01951937632098a6cda45859afa587a06fsewardj	{
1965de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_appendn (s, *mangled, 1);
1966de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled)++;
1967de4a1d01951937632098a6cda45859afa587a06fsewardj	}
1968de4a1d01951937632098a6cda45859afa587a06fsewardj    }
1969de4a1d01951937632098a6cda45859afa587a06fsewardj  if (**mangled == 'e') /* exponent */
1970de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1971de4a1d01951937632098a6cda45859afa587a06fsewardj      string_appendn (s, "e", 1);
1972de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
1973de4a1d01951937632098a6cda45859afa587a06fsewardj      while (ISDIGIT ((unsigned char)**mangled))
1974de4a1d01951937632098a6cda45859afa587a06fsewardj	{
1975de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_appendn (s, *mangled, 1);
1976de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled)++;
1977de4a1d01951937632098a6cda45859afa587a06fsewardj	}
1978de4a1d01951937632098a6cda45859afa587a06fsewardj    }
1979de4a1d01951937632098a6cda45859afa587a06fsewardj
1980de4a1d01951937632098a6cda45859afa587a06fsewardj  return 1;
1981de4a1d01951937632098a6cda45859afa587a06fsewardj}
1982de4a1d01951937632098a6cda45859afa587a06fsewardj
1983de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
19844f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_template_value_parm (struct work_stuff *work, const char **mangled,
19854f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                              string *s, type_kind_t tk)
1986de4a1d01951937632098a6cda45859afa587a06fsewardj{
1987de4a1d01951937632098a6cda45859afa587a06fsewardj  int success = 1;
1988de4a1d01951937632098a6cda45859afa587a06fsewardj
1989de4a1d01951937632098a6cda45859afa587a06fsewardj  if (**mangled == 'Y')
1990de4a1d01951937632098a6cda45859afa587a06fsewardj    {
1991de4a1d01951937632098a6cda45859afa587a06fsewardj      /* The next argument is a template parameter. */
1992de4a1d01951937632098a6cda45859afa587a06fsewardj      int idx;
1993de4a1d01951937632098a6cda45859afa587a06fsewardj
1994de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
1995de4a1d01951937632098a6cda45859afa587a06fsewardj      idx = consume_count_with_underscores (mangled);
1996de4a1d01951937632098a6cda45859afa587a06fsewardj      if (idx == -1
1997de4a1d01951937632098a6cda45859afa587a06fsewardj	  || (work->tmpl_argvec && idx >= work->ntmpl_args)
1998de4a1d01951937632098a6cda45859afa587a06fsewardj	  || consume_count_with_underscores (mangled) == -1)
1999de4a1d01951937632098a6cda45859afa587a06fsewardj	return -1;
2000de4a1d01951937632098a6cda45859afa587a06fsewardj      if (work->tmpl_argvec)
2001de4a1d01951937632098a6cda45859afa587a06fsewardj	string_append (s, work->tmpl_argvec[idx]);
2002de4a1d01951937632098a6cda45859afa587a06fsewardj      else
2003de4a1d01951937632098a6cda45859afa587a06fsewardj	string_append_template_idx (s, idx);
2004de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2005de4a1d01951937632098a6cda45859afa587a06fsewardj  else if (tk == tk_integral)
2006de4a1d01951937632098a6cda45859afa587a06fsewardj    success = demangle_integral_value (work, mangled, s);
2007de4a1d01951937632098a6cda45859afa587a06fsewardj  else if (tk == tk_char)
2008de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2009de4a1d01951937632098a6cda45859afa587a06fsewardj      char tmp[2];
2010de4a1d01951937632098a6cda45859afa587a06fsewardj      int val;
2011de4a1d01951937632098a6cda45859afa587a06fsewardj      if (**mangled == 'm')
2012de4a1d01951937632098a6cda45859afa587a06fsewardj	{
2013de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_appendn (s, "-", 1);
2014de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled)++;
2015de4a1d01951937632098a6cda45859afa587a06fsewardj	}
2016de4a1d01951937632098a6cda45859afa587a06fsewardj      string_appendn (s, "'", 1);
2017de4a1d01951937632098a6cda45859afa587a06fsewardj      val = consume_count(mangled);
2018de4a1d01951937632098a6cda45859afa587a06fsewardj      if (val <= 0)
2019de4a1d01951937632098a6cda45859afa587a06fsewardj	success = 0;
2020de4a1d01951937632098a6cda45859afa587a06fsewardj      else
2021de4a1d01951937632098a6cda45859afa587a06fsewardj	{
2022de4a1d01951937632098a6cda45859afa587a06fsewardj	  tmp[0] = (char)val;
2023de4a1d01951937632098a6cda45859afa587a06fsewardj	  tmp[1] = '\0';
2024de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_appendn (s, &tmp[0], 1);
2025de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_appendn (s, "'", 1);
2026de4a1d01951937632098a6cda45859afa587a06fsewardj	}
2027de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2028de4a1d01951937632098a6cda45859afa587a06fsewardj  else if (tk == tk_bool)
2029de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2030de4a1d01951937632098a6cda45859afa587a06fsewardj      int val = consume_count (mangled);
2031de4a1d01951937632098a6cda45859afa587a06fsewardj      if (val == 0)
2032de4a1d01951937632098a6cda45859afa587a06fsewardj	string_appendn (s, "false", 5);
2033de4a1d01951937632098a6cda45859afa587a06fsewardj      else if (val == 1)
2034de4a1d01951937632098a6cda45859afa587a06fsewardj	string_appendn (s, "true", 4);
2035de4a1d01951937632098a6cda45859afa587a06fsewardj      else
2036de4a1d01951937632098a6cda45859afa587a06fsewardj	success = 0;
2037de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2038de4a1d01951937632098a6cda45859afa587a06fsewardj  else if (tk == tk_real)
2039de4a1d01951937632098a6cda45859afa587a06fsewardj    success = demangle_real_value (work, mangled, s);
2040de4a1d01951937632098a6cda45859afa587a06fsewardj  else if (tk == tk_pointer || tk == tk_reference)
2041de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2042de4a1d01951937632098a6cda45859afa587a06fsewardj      if (**mangled == 'Q')
2043de4a1d01951937632098a6cda45859afa587a06fsewardj	success = demangle_qualified (work, mangled, s,
2044de4a1d01951937632098a6cda45859afa587a06fsewardj				      /*isfuncname=*/0,
2045de4a1d01951937632098a6cda45859afa587a06fsewardj				      /*append=*/1);
2046de4a1d01951937632098a6cda45859afa587a06fsewardj      else
2047de4a1d01951937632098a6cda45859afa587a06fsewardj	{
2048de4a1d01951937632098a6cda45859afa587a06fsewardj	  int symbol_len  = consume_count (mangled);
2049de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (symbol_len == -1)
2050de4a1d01951937632098a6cda45859afa587a06fsewardj	    return -1;
2051de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (symbol_len == 0)
2052de4a1d01951937632098a6cda45859afa587a06fsewardj	    string_appendn (s, "0", 1);
2053de4a1d01951937632098a6cda45859afa587a06fsewardj	  else
2054de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
20554f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	      char *p = XNEWVEC (char, symbol_len + 1), *q;
2056de4a1d01951937632098a6cda45859afa587a06fsewardj	      strncpy (p, *mangled, symbol_len);
2057de4a1d01951937632098a6cda45859afa587a06fsewardj	      p [symbol_len] = '\0';
2058de4a1d01951937632098a6cda45859afa587a06fsewardj	      /* We use cplus_demangle here, rather than
2059de4a1d01951937632098a6cda45859afa587a06fsewardj		 internal_cplus_demangle, because the name of the entity
2060de4a1d01951937632098a6cda45859afa587a06fsewardj		 mangled here does not make use of any of the squangling
2061de4a1d01951937632098a6cda45859afa587a06fsewardj		 or type-code information we have built up thus far; it is
2062de4a1d01951937632098a6cda45859afa587a06fsewardj		 mangled independently.  */
206344fae838401cd4993b8e4b1cac152ebbd37f28e7sewardj	      q = ML_(cplus_demangle) (p, work->options);
2064de4a1d01951937632098a6cda45859afa587a06fsewardj	      if (tk == tk_pointer)
2065de4a1d01951937632098a6cda45859afa587a06fsewardj		string_appendn (s, "&", 1);
2066de4a1d01951937632098a6cda45859afa587a06fsewardj	      /* FIXME: Pointer-to-member constants should get a
2067de4a1d01951937632098a6cda45859afa587a06fsewardj		 qualifying class name here.  */
2068de4a1d01951937632098a6cda45859afa587a06fsewardj	      if (q)
2069de4a1d01951937632098a6cda45859afa587a06fsewardj		{
2070de4a1d01951937632098a6cda45859afa587a06fsewardj		  string_append (s, q);
2071de4a1d01951937632098a6cda45859afa587a06fsewardj		  free (q);
2072de4a1d01951937632098a6cda45859afa587a06fsewardj		}
2073de4a1d01951937632098a6cda45859afa587a06fsewardj	      else
2074de4a1d01951937632098a6cda45859afa587a06fsewardj		string_append (s, p);
2075de4a1d01951937632098a6cda45859afa587a06fsewardj	      free (p);
2076de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
2077de4a1d01951937632098a6cda45859afa587a06fsewardj	  *mangled += symbol_len;
2078de4a1d01951937632098a6cda45859afa587a06fsewardj	}
2079de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2080de4a1d01951937632098a6cda45859afa587a06fsewardj
2081de4a1d01951937632098a6cda45859afa587a06fsewardj  return success;
2082de4a1d01951937632098a6cda45859afa587a06fsewardj}
2083de4a1d01951937632098a6cda45859afa587a06fsewardj
2084de4a1d01951937632098a6cda45859afa587a06fsewardj/* Demangle the template name in MANGLED.  The full name of the
2085de4a1d01951937632098a6cda45859afa587a06fsewardj   template (e.g., S<int>) is placed in TNAME.  The name without the
2086de4a1d01951937632098a6cda45859afa587a06fsewardj   template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is
2087de4a1d01951937632098a6cda45859afa587a06fsewardj   non-NULL.  If IS_TYPE is nonzero, this template is a type template,
2088de4a1d01951937632098a6cda45859afa587a06fsewardj   not a function template.  If both IS_TYPE and REMEMBER are nonzero,
2089de4a1d01951937632098a6cda45859afa587a06fsewardj   the template is remembered in the list of back-referenceable
2090de4a1d01951937632098a6cda45859afa587a06fsewardj   types.  */
2091de4a1d01951937632098a6cda45859afa587a06fsewardj
2092de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
20934f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_template (struct work_stuff *work, const char **mangled,
20944f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                   string *tname, string *trawname,
20954f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                   int is_type, int remember)
2096de4a1d01951937632098a6cda45859afa587a06fsewardj{
2097de4a1d01951937632098a6cda45859afa587a06fsewardj  int i;
2098de4a1d01951937632098a6cda45859afa587a06fsewardj  int r;
2099de4a1d01951937632098a6cda45859afa587a06fsewardj  int need_comma = 0;
2100de4a1d01951937632098a6cda45859afa587a06fsewardj  int success = 0;
2101de4a1d01951937632098a6cda45859afa587a06fsewardj  int is_java_array = 0;
2102de4a1d01951937632098a6cda45859afa587a06fsewardj  string temp;
2103de4a1d01951937632098a6cda45859afa587a06fsewardj
2104de4a1d01951937632098a6cda45859afa587a06fsewardj  (*mangled)++;
2105de4a1d01951937632098a6cda45859afa587a06fsewardj  if (is_type)
2106de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2107de4a1d01951937632098a6cda45859afa587a06fsewardj      /* get template name */
2108de4a1d01951937632098a6cda45859afa587a06fsewardj      if (**mangled == 'z')
2109de4a1d01951937632098a6cda45859afa587a06fsewardj	{
2110de4a1d01951937632098a6cda45859afa587a06fsewardj	  int idx;
2111de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled)++;
2112de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled)++;
2113de4a1d01951937632098a6cda45859afa587a06fsewardj
2114de4a1d01951937632098a6cda45859afa587a06fsewardj	  idx = consume_count_with_underscores (mangled);
2115de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (idx == -1
2116de4a1d01951937632098a6cda45859afa587a06fsewardj	      || (work->tmpl_argvec && idx >= work->ntmpl_args)
2117de4a1d01951937632098a6cda45859afa587a06fsewardj	      || consume_count_with_underscores (mangled) == -1)
2118de4a1d01951937632098a6cda45859afa587a06fsewardj	    return (0);
2119de4a1d01951937632098a6cda45859afa587a06fsewardj
2120de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (work->tmpl_argvec)
2121de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
2122de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_append (tname, work->tmpl_argvec[idx]);
2123de4a1d01951937632098a6cda45859afa587a06fsewardj	      if (trawname)
2124de4a1d01951937632098a6cda45859afa587a06fsewardj		string_append (trawname, work->tmpl_argvec[idx]);
2125de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
2126de4a1d01951937632098a6cda45859afa587a06fsewardj	  else
2127de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
2128de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_append_template_idx (tname, idx);
2129de4a1d01951937632098a6cda45859afa587a06fsewardj	      if (trawname)
2130de4a1d01951937632098a6cda45859afa587a06fsewardj		string_append_template_idx (trawname, idx);
2131de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
2132de4a1d01951937632098a6cda45859afa587a06fsewardj	}
2133de4a1d01951937632098a6cda45859afa587a06fsewardj      else
2134de4a1d01951937632098a6cda45859afa587a06fsewardj	{
2135de4a1d01951937632098a6cda45859afa587a06fsewardj	  if ((r = consume_count (mangled)) <= 0
2136de4a1d01951937632098a6cda45859afa587a06fsewardj	      || (int) strlen (*mangled) < r)
2137de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
2138de4a1d01951937632098a6cda45859afa587a06fsewardj	      return (0);
2139de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
2140de4a1d01951937632098a6cda45859afa587a06fsewardj	  is_java_array = (work -> options & DMGL_JAVA)
2141de4a1d01951937632098a6cda45859afa587a06fsewardj	    && strncmp (*mangled, "JArray1Z", 8) == 0;
2142de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (! is_java_array)
2143de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
2144de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_appendn (tname, *mangled, r);
2145de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
2146de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (trawname)
2147de4a1d01951937632098a6cda45859afa587a06fsewardj	    string_appendn (trawname, *mangled, r);
2148de4a1d01951937632098a6cda45859afa587a06fsewardj	  *mangled += r;
2149de4a1d01951937632098a6cda45859afa587a06fsewardj	}
2150de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2151de4a1d01951937632098a6cda45859afa587a06fsewardj  if (!is_java_array)
2152de4a1d01951937632098a6cda45859afa587a06fsewardj    string_append (tname, "<");
2153de4a1d01951937632098a6cda45859afa587a06fsewardj  /* get size of template parameter list */
2154de4a1d01951937632098a6cda45859afa587a06fsewardj  if (!get_count (mangled, &r))
2155de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2156de4a1d01951937632098a6cda45859afa587a06fsewardj      return (0);
2157de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2158de4a1d01951937632098a6cda45859afa587a06fsewardj  if (!is_type)
2159de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2160de4a1d01951937632098a6cda45859afa587a06fsewardj      /* Create an array for saving the template argument values. */
21614f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      work->tmpl_argvec = XNEWVEC (char *, r);
2162de4a1d01951937632098a6cda45859afa587a06fsewardj      work->ntmpl_args = r;
2163de4a1d01951937632098a6cda45859afa587a06fsewardj      for (i = 0; i < r; i++)
2164de4a1d01951937632098a6cda45859afa587a06fsewardj	work->tmpl_argvec[i] = 0;
2165de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2166de4a1d01951937632098a6cda45859afa587a06fsewardj  for (i = 0; i < r; i++)
2167de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2168de4a1d01951937632098a6cda45859afa587a06fsewardj      if (need_comma)
2169de4a1d01951937632098a6cda45859afa587a06fsewardj	{
2170de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_append (tname, ", ");
2171de4a1d01951937632098a6cda45859afa587a06fsewardj	}
2172de4a1d01951937632098a6cda45859afa587a06fsewardj      /* Z for type parameters */
2173de4a1d01951937632098a6cda45859afa587a06fsewardj      if (**mangled == 'Z')
2174de4a1d01951937632098a6cda45859afa587a06fsewardj	{
2175de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled)++;
2176de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* temp is initialized in do_type */
2177de4a1d01951937632098a6cda45859afa587a06fsewardj	  success = do_type (work, mangled, &temp);
2178de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (success)
2179de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
2180de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_appends (tname, &temp);
2181de4a1d01951937632098a6cda45859afa587a06fsewardj
2182de4a1d01951937632098a6cda45859afa587a06fsewardj	      if (!is_type)
2183de4a1d01951937632098a6cda45859afa587a06fsewardj		{
2184de4a1d01951937632098a6cda45859afa587a06fsewardj		  /* Save the template argument. */
2185de4a1d01951937632098a6cda45859afa587a06fsewardj		  int len = temp.p - temp.b;
21864f2683ace412ca2c8266f2dd860dee4461df3cafsewardj		  work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
2187de4a1d01951937632098a6cda45859afa587a06fsewardj		  memcpy (work->tmpl_argvec[i], temp.b, len);
2188de4a1d01951937632098a6cda45859afa587a06fsewardj		  work->tmpl_argvec[i][len] = '\0';
2189de4a1d01951937632098a6cda45859afa587a06fsewardj		}
2190de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
2191de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_delete(&temp);
2192de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (!success)
2193de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
2194de4a1d01951937632098a6cda45859afa587a06fsewardj	      break;
2195de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
2196de4a1d01951937632098a6cda45859afa587a06fsewardj	}
2197de4a1d01951937632098a6cda45859afa587a06fsewardj      /* z for template parameters */
2198de4a1d01951937632098a6cda45859afa587a06fsewardj      else if (**mangled == 'z')
2199de4a1d01951937632098a6cda45859afa587a06fsewardj	{
2200de4a1d01951937632098a6cda45859afa587a06fsewardj	  int r2;
2201de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled)++;
2202de4a1d01951937632098a6cda45859afa587a06fsewardj	  success = demangle_template_template_parm (work, mangled, tname);
2203de4a1d01951937632098a6cda45859afa587a06fsewardj
2204de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (success
2205de4a1d01951937632098a6cda45859afa587a06fsewardj	      && (r2 = consume_count (mangled)) > 0
2206de4a1d01951937632098a6cda45859afa587a06fsewardj	      && (int) strlen (*mangled) >= r2)
2207de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
2208de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_append (tname, " ");
2209de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_appendn (tname, *mangled, r2);
2210de4a1d01951937632098a6cda45859afa587a06fsewardj	      if (!is_type)
2211de4a1d01951937632098a6cda45859afa587a06fsewardj		{
2212de4a1d01951937632098a6cda45859afa587a06fsewardj		  /* Save the template argument. */
2213de4a1d01951937632098a6cda45859afa587a06fsewardj		  int len = r2;
22144f2683ace412ca2c8266f2dd860dee4461df3cafsewardj		  work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
2215de4a1d01951937632098a6cda45859afa587a06fsewardj		  memcpy (work->tmpl_argvec[i], *mangled, len);
2216de4a1d01951937632098a6cda45859afa587a06fsewardj		  work->tmpl_argvec[i][len] = '\0';
2217de4a1d01951937632098a6cda45859afa587a06fsewardj		}
2218de4a1d01951937632098a6cda45859afa587a06fsewardj	      *mangled += r2;
2219de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
2220de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (!success)
2221de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
2222de4a1d01951937632098a6cda45859afa587a06fsewardj	      break;
2223de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
2224de4a1d01951937632098a6cda45859afa587a06fsewardj	}
2225de4a1d01951937632098a6cda45859afa587a06fsewardj      else
2226de4a1d01951937632098a6cda45859afa587a06fsewardj	{
2227de4a1d01951937632098a6cda45859afa587a06fsewardj	  string  param;
2228de4a1d01951937632098a6cda45859afa587a06fsewardj	  string* s;
2229de4a1d01951937632098a6cda45859afa587a06fsewardj
2230de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* otherwise, value parameter */
2231de4a1d01951937632098a6cda45859afa587a06fsewardj
2232de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* temp is initialized in do_type */
2233de4a1d01951937632098a6cda45859afa587a06fsewardj	  success = do_type (work, mangled, &temp);
2234de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_delete(&temp);
2235de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (!success)
2236de4a1d01951937632098a6cda45859afa587a06fsewardj	    break;
2237de4a1d01951937632098a6cda45859afa587a06fsewardj
2238de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (!is_type)
2239de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
2240de4a1d01951937632098a6cda45859afa587a06fsewardj	      s = &param;
2241de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_init (s);
2242de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
2243de4a1d01951937632098a6cda45859afa587a06fsewardj	  else
2244de4a1d01951937632098a6cda45859afa587a06fsewardj	    s = tname;
2245de4a1d01951937632098a6cda45859afa587a06fsewardj
2246de4a1d01951937632098a6cda45859afa587a06fsewardj	  success = demangle_template_value_parm (work, mangled, s,
2247de4a1d01951937632098a6cda45859afa587a06fsewardj						  (type_kind_t) success);
2248de4a1d01951937632098a6cda45859afa587a06fsewardj
2249de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (!success)
2250de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
2251de4a1d01951937632098a6cda45859afa587a06fsewardj	      if (!is_type)
2252de4a1d01951937632098a6cda45859afa587a06fsewardj		string_delete (s);
2253de4a1d01951937632098a6cda45859afa587a06fsewardj	      success = 0;
2254de4a1d01951937632098a6cda45859afa587a06fsewardj	      break;
2255de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
2256de4a1d01951937632098a6cda45859afa587a06fsewardj
2257de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (!is_type)
2258de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
2259de4a1d01951937632098a6cda45859afa587a06fsewardj	      int len = s->p - s->b;
22604f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	      work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
2261de4a1d01951937632098a6cda45859afa587a06fsewardj	      memcpy (work->tmpl_argvec[i], s->b, len);
2262de4a1d01951937632098a6cda45859afa587a06fsewardj	      work->tmpl_argvec[i][len] = '\0';
2263de4a1d01951937632098a6cda45859afa587a06fsewardj
2264de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_appends (tname, s);
2265de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_delete (s);
2266de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
2267de4a1d01951937632098a6cda45859afa587a06fsewardj	}
2268de4a1d01951937632098a6cda45859afa587a06fsewardj      need_comma = 1;
2269de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2270de4a1d01951937632098a6cda45859afa587a06fsewardj  if (is_java_array)
2271de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2272de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (tname, "[]");
2273de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2274de4a1d01951937632098a6cda45859afa587a06fsewardj  else
2275de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2276de4a1d01951937632098a6cda45859afa587a06fsewardj      if (tname->p[-1] == '>')
2277de4a1d01951937632098a6cda45859afa587a06fsewardj	string_append (tname, " ");
2278de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (tname, ">");
2279de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2280de4a1d01951937632098a6cda45859afa587a06fsewardj
2281de4a1d01951937632098a6cda45859afa587a06fsewardj  if (is_type && remember)
22824f2683ace412ca2c8266f2dd860dee4461df3cafsewardj    {
22834f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      const int bindex = register_Btype (work);
22844f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      remember_Btype (work, tname->b, LEN_STRING (tname), bindex);
22854f2683ace412ca2c8266f2dd860dee4461df3cafsewardj    }
2286de4a1d01951937632098a6cda45859afa587a06fsewardj
2287de4a1d01951937632098a6cda45859afa587a06fsewardj  /*
2288de4a1d01951937632098a6cda45859afa587a06fsewardj    if (work -> static_type)
2289de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2290de4a1d01951937632098a6cda45859afa587a06fsewardj    string_append (declp, *mangled + 1);
2291de4a1d01951937632098a6cda45859afa587a06fsewardj    *mangled += strlen (*mangled);
2292de4a1d01951937632098a6cda45859afa587a06fsewardj    success = 1;
2293de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2294de4a1d01951937632098a6cda45859afa587a06fsewardj    else
2295de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2296de4a1d01951937632098a6cda45859afa587a06fsewardj    success = demangle_args (work, mangled, declp);
2297de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2298de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2299de4a1d01951937632098a6cda45859afa587a06fsewardj    */
2300de4a1d01951937632098a6cda45859afa587a06fsewardj  return (success);
2301de4a1d01951937632098a6cda45859afa587a06fsewardj}
2302de4a1d01951937632098a6cda45859afa587a06fsewardj
2303de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
23041dcee097db02f9ef3ba355162c4373d90d0e895cnjnarm_pt (const char *mangled,
23054f2683ace412ca2c8266f2dd860dee4461df3cafsewardj        int n, const char **anchor, const char **args)
2306de4a1d01951937632098a6cda45859afa587a06fsewardj{
2307de4a1d01951937632098a6cda45859afa587a06fsewardj  /* Check if ARM template with "__pt__" in it ("parameterized type") */
2308de4a1d01951937632098a6cda45859afa587a06fsewardj  /* Allow HP also here, because HP's cfront compiler follows ARM to some extent */
2309de4a1d01951937632098a6cda45859afa587a06fsewardj  if ((ARM_DEMANGLING || HP_DEMANGLING) && (*anchor = strstr (mangled, "__pt__")))
2310de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2311de4a1d01951937632098a6cda45859afa587a06fsewardj      int len;
2312de4a1d01951937632098a6cda45859afa587a06fsewardj      *args = *anchor + 6;
2313de4a1d01951937632098a6cda45859afa587a06fsewardj      len = consume_count (args);
2314de4a1d01951937632098a6cda45859afa587a06fsewardj      if (len == -1)
2315de4a1d01951937632098a6cda45859afa587a06fsewardj	return 0;
2316de4a1d01951937632098a6cda45859afa587a06fsewardj      if (*args + len == mangled + n && **args == '_')
2317de4a1d01951937632098a6cda45859afa587a06fsewardj	{
2318de4a1d01951937632098a6cda45859afa587a06fsewardj	  ++*args;
2319de4a1d01951937632098a6cda45859afa587a06fsewardj	  return 1;
2320de4a1d01951937632098a6cda45859afa587a06fsewardj	}
2321de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2322de4a1d01951937632098a6cda45859afa587a06fsewardj  if (AUTO_DEMANGLING || EDG_DEMANGLING)
2323de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2324de4a1d01951937632098a6cda45859afa587a06fsewardj      if ((*anchor = strstr (mangled, "__tm__"))
2325de4a1d01951937632098a6cda45859afa587a06fsewardj          || (*anchor = strstr (mangled, "__ps__"))
2326de4a1d01951937632098a6cda45859afa587a06fsewardj          || (*anchor = strstr (mangled, "__pt__")))
2327de4a1d01951937632098a6cda45859afa587a06fsewardj        {
2328de4a1d01951937632098a6cda45859afa587a06fsewardj          int len;
2329de4a1d01951937632098a6cda45859afa587a06fsewardj          *args = *anchor + 6;
2330de4a1d01951937632098a6cda45859afa587a06fsewardj          len = consume_count (args);
2331de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (len == -1)
2332de4a1d01951937632098a6cda45859afa587a06fsewardj	    return 0;
2333de4a1d01951937632098a6cda45859afa587a06fsewardj          if (*args + len == mangled + n && **args == '_')
2334de4a1d01951937632098a6cda45859afa587a06fsewardj            {
2335de4a1d01951937632098a6cda45859afa587a06fsewardj              ++*args;
2336de4a1d01951937632098a6cda45859afa587a06fsewardj              return 1;
2337de4a1d01951937632098a6cda45859afa587a06fsewardj            }
2338de4a1d01951937632098a6cda45859afa587a06fsewardj        }
2339de4a1d01951937632098a6cda45859afa587a06fsewardj      else if ((*anchor = strstr (mangled, "__S")))
2340de4a1d01951937632098a6cda45859afa587a06fsewardj        {
2341de4a1d01951937632098a6cda45859afa587a06fsewardj 	  int len;
2342de4a1d01951937632098a6cda45859afa587a06fsewardj 	  *args = *anchor + 3;
2343de4a1d01951937632098a6cda45859afa587a06fsewardj 	  len = consume_count (args);
2344de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (len == -1)
2345de4a1d01951937632098a6cda45859afa587a06fsewardj	    return 0;
2346de4a1d01951937632098a6cda45859afa587a06fsewardj 	  if (*args + len == mangled + n && **args == '_')
2347de4a1d01951937632098a6cda45859afa587a06fsewardj            {
2348de4a1d01951937632098a6cda45859afa587a06fsewardj              ++*args;
2349de4a1d01951937632098a6cda45859afa587a06fsewardj 	      return 1;
2350de4a1d01951937632098a6cda45859afa587a06fsewardj            }
2351de4a1d01951937632098a6cda45859afa587a06fsewardj        }
2352de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2353de4a1d01951937632098a6cda45859afa587a06fsewardj
2354de4a1d01951937632098a6cda45859afa587a06fsewardj  return 0;
2355de4a1d01951937632098a6cda45859afa587a06fsewardj}
2356de4a1d01951937632098a6cda45859afa587a06fsewardj
2357de4a1d01951937632098a6cda45859afa587a06fsewardjstatic void
23584f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_arm_hp_template (struct work_stuff *work, const char **mangled,
23594f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                          int n, string *declp)
2360de4a1d01951937632098a6cda45859afa587a06fsewardj{
2361de4a1d01951937632098a6cda45859afa587a06fsewardj  const char *p;
2362de4a1d01951937632098a6cda45859afa587a06fsewardj  const char *args;
2363de4a1d01951937632098a6cda45859afa587a06fsewardj  const char *e = *mangled + n;
2364de4a1d01951937632098a6cda45859afa587a06fsewardj  string arg;
2365de4a1d01951937632098a6cda45859afa587a06fsewardj
2366de4a1d01951937632098a6cda45859afa587a06fsewardj  /* Check for HP aCC template spec: classXt1t2 where t1, t2 are
2367de4a1d01951937632098a6cda45859afa587a06fsewardj     template args */
2368de4a1d01951937632098a6cda45859afa587a06fsewardj  if (HP_DEMANGLING && ((*mangled)[n] == 'X'))
2369de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2370de4a1d01951937632098a6cda45859afa587a06fsewardj      char *start_spec_args = NULL;
23714f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      int hold_options;
2372de4a1d01951937632098a6cda45859afa587a06fsewardj
2373de4a1d01951937632098a6cda45859afa587a06fsewardj      /* First check for and omit template specialization pseudo-arguments,
2374de4a1d01951937632098a6cda45859afa587a06fsewardj         such as in "Spec<#1,#1.*>" */
2375de4a1d01951937632098a6cda45859afa587a06fsewardj      start_spec_args = strchr (*mangled, '<');
2376de4a1d01951937632098a6cda45859afa587a06fsewardj      if (start_spec_args && (start_spec_args - *mangled < n))
2377de4a1d01951937632098a6cda45859afa587a06fsewardj        string_appendn (declp, *mangled, start_spec_args - *mangled);
2378de4a1d01951937632098a6cda45859afa587a06fsewardj      else
2379de4a1d01951937632098a6cda45859afa587a06fsewardj        string_appendn (declp, *mangled, n);
2380de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled) += n + 1;
2381de4a1d01951937632098a6cda45859afa587a06fsewardj      string_init (&arg);
2382de4a1d01951937632098a6cda45859afa587a06fsewardj      if (work->temp_start == -1) /* non-recursive call */
2383de4a1d01951937632098a6cda45859afa587a06fsewardj        work->temp_start = declp->p - declp->b;
23844f2683ace412ca2c8266f2dd860dee4461df3cafsewardj
23854f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      /* We want to unconditionally demangle parameter types in
23864f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	 template parameters.  */
23874f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      hold_options = work->options;
23884f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      work->options |= DMGL_PARAMS;
23894f2683ace412ca2c8266f2dd860dee4461df3cafsewardj
2390de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (declp, "<");
2391de4a1d01951937632098a6cda45859afa587a06fsewardj      while (1)
2392de4a1d01951937632098a6cda45859afa587a06fsewardj        {
23934f2683ace412ca2c8266f2dd860dee4461df3cafsewardj          string_delete (&arg);
2394de4a1d01951937632098a6cda45859afa587a06fsewardj          switch (**mangled)
2395de4a1d01951937632098a6cda45859afa587a06fsewardj            {
2396de4a1d01951937632098a6cda45859afa587a06fsewardj              case 'T':
2397de4a1d01951937632098a6cda45859afa587a06fsewardj                /* 'T' signals a type parameter */
2398de4a1d01951937632098a6cda45859afa587a06fsewardj                (*mangled)++;
2399de4a1d01951937632098a6cda45859afa587a06fsewardj                if (!do_type (work, mangled, &arg))
2400de4a1d01951937632098a6cda45859afa587a06fsewardj                  goto hpacc_template_args_done;
2401de4a1d01951937632098a6cda45859afa587a06fsewardj                break;
2402de4a1d01951937632098a6cda45859afa587a06fsewardj
2403de4a1d01951937632098a6cda45859afa587a06fsewardj              case 'U':
2404de4a1d01951937632098a6cda45859afa587a06fsewardj              case 'S':
2405de4a1d01951937632098a6cda45859afa587a06fsewardj                /* 'U' or 'S' signals an integral value */
2406de4a1d01951937632098a6cda45859afa587a06fsewardj                if (!do_hpacc_template_const_value (work, mangled, &arg))
2407de4a1d01951937632098a6cda45859afa587a06fsewardj                  goto hpacc_template_args_done;
2408de4a1d01951937632098a6cda45859afa587a06fsewardj                break;
2409de4a1d01951937632098a6cda45859afa587a06fsewardj
2410de4a1d01951937632098a6cda45859afa587a06fsewardj              case 'A':
2411de4a1d01951937632098a6cda45859afa587a06fsewardj                /* 'A' signals a named constant expression (literal) */
2412de4a1d01951937632098a6cda45859afa587a06fsewardj                if (!do_hpacc_template_literal (work, mangled, &arg))
2413de4a1d01951937632098a6cda45859afa587a06fsewardj                  goto hpacc_template_args_done;
2414de4a1d01951937632098a6cda45859afa587a06fsewardj                break;
2415de4a1d01951937632098a6cda45859afa587a06fsewardj
2416de4a1d01951937632098a6cda45859afa587a06fsewardj              default:
2417de4a1d01951937632098a6cda45859afa587a06fsewardj                /* Today, 1997-09-03, we have only the above types
2418de4a1d01951937632098a6cda45859afa587a06fsewardj                   of template parameters */
2419de4a1d01951937632098a6cda45859afa587a06fsewardj                /* FIXME: maybe this should fail and return null */
2420de4a1d01951937632098a6cda45859afa587a06fsewardj                goto hpacc_template_args_done;
2421de4a1d01951937632098a6cda45859afa587a06fsewardj            }
2422de4a1d01951937632098a6cda45859afa587a06fsewardj          string_appends (declp, &arg);
2423de4a1d01951937632098a6cda45859afa587a06fsewardj         /* Check if we're at the end of template args.
2424de4a1d01951937632098a6cda45859afa587a06fsewardj             0 if at end of static member of template class,
2425de4a1d01951937632098a6cda45859afa587a06fsewardj             _ if done with template args for a function */
2426de4a1d01951937632098a6cda45859afa587a06fsewardj          if ((**mangled == '\000') || (**mangled == '_'))
2427de4a1d01951937632098a6cda45859afa587a06fsewardj            break;
2428de4a1d01951937632098a6cda45859afa587a06fsewardj          else
2429de4a1d01951937632098a6cda45859afa587a06fsewardj            string_append (declp, ",");
2430de4a1d01951937632098a6cda45859afa587a06fsewardj        }
2431de4a1d01951937632098a6cda45859afa587a06fsewardj    hpacc_template_args_done:
2432de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (declp, ">");
2433de4a1d01951937632098a6cda45859afa587a06fsewardj      string_delete (&arg);
2434de4a1d01951937632098a6cda45859afa587a06fsewardj      if (**mangled == '_')
2435de4a1d01951937632098a6cda45859afa587a06fsewardj        (*mangled)++;
24364f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      work->options = hold_options;
2437de4a1d01951937632098a6cda45859afa587a06fsewardj      return;
2438de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2439de4a1d01951937632098a6cda45859afa587a06fsewardj  /* ARM template? (Also handles HP cfront extensions) */
24401dcee097db02f9ef3ba355162c4373d90d0e895cnjn  else if (arm_pt (*mangled, n, &p, &args))
2441de4a1d01951937632098a6cda45859afa587a06fsewardj    {
24424f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      int hold_options;
2443de4a1d01951937632098a6cda45859afa587a06fsewardj      string type_str;
2444de4a1d01951937632098a6cda45859afa587a06fsewardj
2445de4a1d01951937632098a6cda45859afa587a06fsewardj      string_init (&arg);
2446de4a1d01951937632098a6cda45859afa587a06fsewardj      string_appendn (declp, *mangled, p - *mangled);
2447de4a1d01951937632098a6cda45859afa587a06fsewardj      if (work->temp_start == -1)  /* non-recursive call */
2448de4a1d01951937632098a6cda45859afa587a06fsewardj	work->temp_start = declp->p - declp->b;
24494f2683ace412ca2c8266f2dd860dee4461df3cafsewardj
24504f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      /* We want to unconditionally demangle parameter types in
24514f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	 template parameters.  */
24524f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      hold_options = work->options;
24534f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      work->options |= DMGL_PARAMS;
24544f2683ace412ca2c8266f2dd860dee4461df3cafsewardj
2455de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (declp, "<");
2456de4a1d01951937632098a6cda45859afa587a06fsewardj      /* should do error checking here */
2457de4a1d01951937632098a6cda45859afa587a06fsewardj      while (args < e) {
24584f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	string_delete (&arg);
2459de4a1d01951937632098a6cda45859afa587a06fsewardj
2460de4a1d01951937632098a6cda45859afa587a06fsewardj	/* Check for type or literal here */
2461de4a1d01951937632098a6cda45859afa587a06fsewardj	switch (*args)
2462de4a1d01951937632098a6cda45859afa587a06fsewardj	  {
2463de4a1d01951937632098a6cda45859afa587a06fsewardj	    /* HP cfront extensions to ARM for template args */
2464de4a1d01951937632098a6cda45859afa587a06fsewardj	    /* spec: Xt1Lv1 where t1 is a type, v1 is a literal value */
2465de4a1d01951937632098a6cda45859afa587a06fsewardj	    /* FIXME: We handle only numeric literals for HP cfront */
2466de4a1d01951937632098a6cda45859afa587a06fsewardj          case 'X':
2467de4a1d01951937632098a6cda45859afa587a06fsewardj            /* A typed constant value follows */
2468de4a1d01951937632098a6cda45859afa587a06fsewardj            args++;
2469de4a1d01951937632098a6cda45859afa587a06fsewardj            if (!do_type (work, &args, &type_str))
2470de4a1d01951937632098a6cda45859afa587a06fsewardj	      goto cfront_template_args_done;
2471de4a1d01951937632098a6cda45859afa587a06fsewardj            string_append (&arg, "(");
2472de4a1d01951937632098a6cda45859afa587a06fsewardj            string_appends (&arg, &type_str);
24734f2683ace412ca2c8266f2dd860dee4461df3cafsewardj            string_delete (&type_str);
2474de4a1d01951937632098a6cda45859afa587a06fsewardj            string_append (&arg, ")");
2475de4a1d01951937632098a6cda45859afa587a06fsewardj            if (*args != 'L')
2476de4a1d01951937632098a6cda45859afa587a06fsewardj              goto cfront_template_args_done;
2477de4a1d01951937632098a6cda45859afa587a06fsewardj            args++;
2478de4a1d01951937632098a6cda45859afa587a06fsewardj            /* Now snarf a literal value following 'L' */
2479de4a1d01951937632098a6cda45859afa587a06fsewardj            if (!snarf_numeric_literal (&args, &arg))
2480de4a1d01951937632098a6cda45859afa587a06fsewardj	      goto cfront_template_args_done;
2481de4a1d01951937632098a6cda45859afa587a06fsewardj            break;
2482de4a1d01951937632098a6cda45859afa587a06fsewardj
2483de4a1d01951937632098a6cda45859afa587a06fsewardj          case 'L':
2484de4a1d01951937632098a6cda45859afa587a06fsewardj            /* Snarf a literal following 'L' */
2485de4a1d01951937632098a6cda45859afa587a06fsewardj            args++;
2486de4a1d01951937632098a6cda45859afa587a06fsewardj            if (!snarf_numeric_literal (&args, &arg))
2487de4a1d01951937632098a6cda45859afa587a06fsewardj	      goto cfront_template_args_done;
2488de4a1d01951937632098a6cda45859afa587a06fsewardj            break;
2489de4a1d01951937632098a6cda45859afa587a06fsewardj          default:
2490de4a1d01951937632098a6cda45859afa587a06fsewardj            /* Not handling other HP cfront stuff */
24914f2683ace412ca2c8266f2dd860dee4461df3cafsewardj            {
24924f2683ace412ca2c8266f2dd860dee4461df3cafsewardj              const char* old_args = args;
24934f2683ace412ca2c8266f2dd860dee4461df3cafsewardj              if (!do_type (work, &args, &arg))
24944f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                goto cfront_template_args_done;
24954f2683ace412ca2c8266f2dd860dee4461df3cafsewardj
24964f2683ace412ca2c8266f2dd860dee4461df3cafsewardj              /* Fail if we didn't make any progress: prevent infinite loop. */
24974f2683ace412ca2c8266f2dd860dee4461df3cafsewardj              if (args == old_args)
24984f2683ace412ca2c8266f2dd860dee4461df3cafsewardj		{
24994f2683ace412ca2c8266f2dd860dee4461df3cafsewardj		  work->options = hold_options;
25004f2683ace412ca2c8266f2dd860dee4461df3cafsewardj		  return;
25014f2683ace412ca2c8266f2dd860dee4461df3cafsewardj		}
25024f2683ace412ca2c8266f2dd860dee4461df3cafsewardj            }
2503de4a1d01951937632098a6cda45859afa587a06fsewardj	  }
2504de4a1d01951937632098a6cda45859afa587a06fsewardj	string_appends (declp, &arg);
2505de4a1d01951937632098a6cda45859afa587a06fsewardj	string_append (declp, ",");
2506de4a1d01951937632098a6cda45859afa587a06fsewardj      }
2507de4a1d01951937632098a6cda45859afa587a06fsewardj    cfront_template_args_done:
2508de4a1d01951937632098a6cda45859afa587a06fsewardj      string_delete (&arg);
2509de4a1d01951937632098a6cda45859afa587a06fsewardj      if (args >= e)
2510de4a1d01951937632098a6cda45859afa587a06fsewardj	--declp->p; /* remove extra comma */
2511de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (declp, ">");
25124f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      work->options = hold_options;
2513de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2514de4a1d01951937632098a6cda45859afa587a06fsewardj  else if (n>10 && strncmp (*mangled, "_GLOBAL_", 8) == 0
2515de4a1d01951937632098a6cda45859afa587a06fsewardj	   && (*mangled)[9] == 'N'
2516de4a1d01951937632098a6cda45859afa587a06fsewardj	   && (*mangled)[8] == (*mangled)[10]
2517de4a1d01951937632098a6cda45859afa587a06fsewardj	   && strchr (cplus_markers, (*mangled)[8]))
2518de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2519de4a1d01951937632098a6cda45859afa587a06fsewardj      /* A member of the anonymous namespace.  */
2520de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (declp, "{anonymous}");
2521de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2522de4a1d01951937632098a6cda45859afa587a06fsewardj  else
2523de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2524de4a1d01951937632098a6cda45859afa587a06fsewardj      if (work->temp_start == -1) /* non-recursive call only */
2525de4a1d01951937632098a6cda45859afa587a06fsewardj	work->temp_start = 0;     /* disable in recursive calls */
2526de4a1d01951937632098a6cda45859afa587a06fsewardj      string_appendn (declp, *mangled, n);
2527de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2528de4a1d01951937632098a6cda45859afa587a06fsewardj  *mangled += n;
2529de4a1d01951937632098a6cda45859afa587a06fsewardj}
2530de4a1d01951937632098a6cda45859afa587a06fsewardj
2531de4a1d01951937632098a6cda45859afa587a06fsewardj/* Extract a class name, possibly a template with arguments, from the
2532de4a1d01951937632098a6cda45859afa587a06fsewardj   mangled string; qualifiers, local class indicators, etc. have
2533de4a1d01951937632098a6cda45859afa587a06fsewardj   already been dealt with */
2534de4a1d01951937632098a6cda45859afa587a06fsewardj
2535de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
25364f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_class_name (struct work_stuff *work, const char **mangled,
25374f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                     string *declp)
2538de4a1d01951937632098a6cda45859afa587a06fsewardj{
2539de4a1d01951937632098a6cda45859afa587a06fsewardj  int n;
2540de4a1d01951937632098a6cda45859afa587a06fsewardj  int success = 0;
2541de4a1d01951937632098a6cda45859afa587a06fsewardj
2542de4a1d01951937632098a6cda45859afa587a06fsewardj  n = consume_count (mangled);
2543de4a1d01951937632098a6cda45859afa587a06fsewardj  if (n == -1)
2544de4a1d01951937632098a6cda45859afa587a06fsewardj    return 0;
2545de4a1d01951937632098a6cda45859afa587a06fsewardj  if ((int) strlen (*mangled) >= n)
2546de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2547de4a1d01951937632098a6cda45859afa587a06fsewardj      demangle_arm_hp_template (work, mangled, n, declp);
2548de4a1d01951937632098a6cda45859afa587a06fsewardj      success = 1;
2549de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2550de4a1d01951937632098a6cda45859afa587a06fsewardj
2551de4a1d01951937632098a6cda45859afa587a06fsewardj  return (success);
2552de4a1d01951937632098a6cda45859afa587a06fsewardj}
2553de4a1d01951937632098a6cda45859afa587a06fsewardj
2554de4a1d01951937632098a6cda45859afa587a06fsewardj/*
2555de4a1d01951937632098a6cda45859afa587a06fsewardj
2556de4a1d01951937632098a6cda45859afa587a06fsewardjLOCAL FUNCTION
2557de4a1d01951937632098a6cda45859afa587a06fsewardj
2558de4a1d01951937632098a6cda45859afa587a06fsewardj	demangle_class -- demangle a mangled class sequence
2559de4a1d01951937632098a6cda45859afa587a06fsewardj
2560de4a1d01951937632098a6cda45859afa587a06fsewardjSYNOPSIS
2561de4a1d01951937632098a6cda45859afa587a06fsewardj
2562de4a1d01951937632098a6cda45859afa587a06fsewardj	static int
2563de4a1d01951937632098a6cda45859afa587a06fsewardj	demangle_class (struct work_stuff *work, const char **mangled,
2564de4a1d01951937632098a6cda45859afa587a06fsewardj			strint *declp)
2565de4a1d01951937632098a6cda45859afa587a06fsewardj
2566de4a1d01951937632098a6cda45859afa587a06fsewardjDESCRIPTION
2567de4a1d01951937632098a6cda45859afa587a06fsewardj
2568de4a1d01951937632098a6cda45859afa587a06fsewardj	DECLP points to the buffer into which demangling is being done.
2569de4a1d01951937632098a6cda45859afa587a06fsewardj
2570de4a1d01951937632098a6cda45859afa587a06fsewardj	*MANGLED points to the current token to be demangled.  On input,
2571de4a1d01951937632098a6cda45859afa587a06fsewardj	it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
2572de4a1d01951937632098a6cda45859afa587a06fsewardj	On exit, it points to the next token after the mangled class on
2573de4a1d01951937632098a6cda45859afa587a06fsewardj	success, or the first unconsumed token on failure.
2574de4a1d01951937632098a6cda45859afa587a06fsewardj
2575de4a1d01951937632098a6cda45859afa587a06fsewardj	If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
2576de4a1d01951937632098a6cda45859afa587a06fsewardj	we are demangling a constructor or destructor.  In this case
2577de4a1d01951937632098a6cda45859afa587a06fsewardj	we prepend "class::class" or "class::~class" to DECLP.
2578de4a1d01951937632098a6cda45859afa587a06fsewardj
2579de4a1d01951937632098a6cda45859afa587a06fsewardj	Otherwise, we prepend "class::" to the current DECLP.
2580de4a1d01951937632098a6cda45859afa587a06fsewardj
2581de4a1d01951937632098a6cda45859afa587a06fsewardj	Reset the constructor/destructor flags once they have been
2582de4a1d01951937632098a6cda45859afa587a06fsewardj	"consumed".  This allows demangle_class to be called later during
2583de4a1d01951937632098a6cda45859afa587a06fsewardj	the same demangling, to do normal class demangling.
2584de4a1d01951937632098a6cda45859afa587a06fsewardj
2585de4a1d01951937632098a6cda45859afa587a06fsewardj	Returns 1 if demangling is successful, 0 otherwise.
2586de4a1d01951937632098a6cda45859afa587a06fsewardj
2587de4a1d01951937632098a6cda45859afa587a06fsewardj*/
2588de4a1d01951937632098a6cda45859afa587a06fsewardj
2589de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
25904f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_class (struct work_stuff *work, const char **mangled, string *declp)
2591de4a1d01951937632098a6cda45859afa587a06fsewardj{
2592de4a1d01951937632098a6cda45859afa587a06fsewardj  int success = 0;
2593de4a1d01951937632098a6cda45859afa587a06fsewardj  int btype;
2594de4a1d01951937632098a6cda45859afa587a06fsewardj  string class_name;
2595de4a1d01951937632098a6cda45859afa587a06fsewardj  char *save_class_name_end = 0;
2596de4a1d01951937632098a6cda45859afa587a06fsewardj
2597de4a1d01951937632098a6cda45859afa587a06fsewardj  string_init (&class_name);
2598de4a1d01951937632098a6cda45859afa587a06fsewardj  btype = register_Btype (work);
2599de4a1d01951937632098a6cda45859afa587a06fsewardj  if (demangle_class_name (work, mangled, &class_name))
2600de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2601de4a1d01951937632098a6cda45859afa587a06fsewardj      save_class_name_end = class_name.p;
2602de4a1d01951937632098a6cda45859afa587a06fsewardj      if ((work->constructor & 1) || (work->destructor & 1))
2603de4a1d01951937632098a6cda45859afa587a06fsewardj	{
2604de4a1d01951937632098a6cda45859afa587a06fsewardj          /* adjust so we don't include template args */
2605de4a1d01951937632098a6cda45859afa587a06fsewardj          if (work->temp_start && (work->temp_start != -1))
2606de4a1d01951937632098a6cda45859afa587a06fsewardj            {
2607de4a1d01951937632098a6cda45859afa587a06fsewardj              class_name.p = class_name.b + work->temp_start;
2608de4a1d01951937632098a6cda45859afa587a06fsewardj            }
2609de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_prepends (declp, &class_name);
2610de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (work -> destructor & 1)
2611de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
2612de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_prepend (declp, "~");
2613de4a1d01951937632098a6cda45859afa587a06fsewardj              work -> destructor -= 1;
2614de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
2615de4a1d01951937632098a6cda45859afa587a06fsewardj	  else
2616de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
2617de4a1d01951937632098a6cda45859afa587a06fsewardj	      work -> constructor -= 1;
2618de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
2619de4a1d01951937632098a6cda45859afa587a06fsewardj	}
2620de4a1d01951937632098a6cda45859afa587a06fsewardj      class_name.p = save_class_name_end;
2621de4a1d01951937632098a6cda45859afa587a06fsewardj      remember_Ktype (work, class_name.b, LEN_STRING(&class_name));
2622de4a1d01951937632098a6cda45859afa587a06fsewardj      remember_Btype (work, class_name.b, LEN_STRING(&class_name), btype);
2623de4a1d01951937632098a6cda45859afa587a06fsewardj      string_prepend (declp, SCOPE_STRING (work));
2624de4a1d01951937632098a6cda45859afa587a06fsewardj      string_prepends (declp, &class_name);
2625de4a1d01951937632098a6cda45859afa587a06fsewardj      success = 1;
2626de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2627de4a1d01951937632098a6cda45859afa587a06fsewardj  string_delete (&class_name);
2628de4a1d01951937632098a6cda45859afa587a06fsewardj  return (success);
2629de4a1d01951937632098a6cda45859afa587a06fsewardj}
2630de4a1d01951937632098a6cda45859afa587a06fsewardj
2631de4a1d01951937632098a6cda45859afa587a06fsewardj
2632de4a1d01951937632098a6cda45859afa587a06fsewardj/* Called when there's a "__" in the mangled name, with `scan' pointing to
2633de4a1d01951937632098a6cda45859afa587a06fsewardj   the rightmost guess.
2634de4a1d01951937632098a6cda45859afa587a06fsewardj
2635de4a1d01951937632098a6cda45859afa587a06fsewardj   Find the correct "__"-sequence where the function name ends and the
2636de4a1d01951937632098a6cda45859afa587a06fsewardj   signature starts, which is ambiguous with GNU mangling.
2637de4a1d01951937632098a6cda45859afa587a06fsewardj   Call demangle_signature here, so we can make sure we found the right
2638de4a1d01951937632098a6cda45859afa587a06fsewardj   one; *mangled will be consumed so caller will not make further calls to
2639de4a1d01951937632098a6cda45859afa587a06fsewardj   demangle_signature.  */
2640de4a1d01951937632098a6cda45859afa587a06fsewardj
2641de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
26424f2683ace412ca2c8266f2dd860dee4461df3cafsewardjiterate_demangle_function (struct work_stuff *work, const char **mangled,
26434f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                           string *declp, const char *scan)
2644de4a1d01951937632098a6cda45859afa587a06fsewardj{
2645de4a1d01951937632098a6cda45859afa587a06fsewardj  const char *mangle_init = *mangled;
2646de4a1d01951937632098a6cda45859afa587a06fsewardj  int success = 0;
2647de4a1d01951937632098a6cda45859afa587a06fsewardj  string decl_init;
2648de4a1d01951937632098a6cda45859afa587a06fsewardj  struct work_stuff work_init;
2649de4a1d01951937632098a6cda45859afa587a06fsewardj
2650de4a1d01951937632098a6cda45859afa587a06fsewardj  if (*(scan + 2) == '\0')
2651de4a1d01951937632098a6cda45859afa587a06fsewardj    return 0;
2652de4a1d01951937632098a6cda45859afa587a06fsewardj
2653de4a1d01951937632098a6cda45859afa587a06fsewardj  /* Do not iterate for some demangling modes, or if there's only one
2654de4a1d01951937632098a6cda45859afa587a06fsewardj     "__"-sequence.  This is the normal case.  */
2655de4a1d01951937632098a6cda45859afa587a06fsewardj  if (ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING
2656de4a1d01951937632098a6cda45859afa587a06fsewardj      || strstr (scan + 2, "__") == NULL)
26574f2683ace412ca2c8266f2dd860dee4461df3cafsewardj    return demangle_function_name (work, mangled, declp, scan);
2658de4a1d01951937632098a6cda45859afa587a06fsewardj
2659de4a1d01951937632098a6cda45859afa587a06fsewardj  /* Save state so we can restart if the guess at the correct "__" was
2660de4a1d01951937632098a6cda45859afa587a06fsewardj     wrong.  */
2661de4a1d01951937632098a6cda45859afa587a06fsewardj  string_init (&decl_init);
2662de4a1d01951937632098a6cda45859afa587a06fsewardj  string_appends (&decl_init, declp);
2663de4a1d01951937632098a6cda45859afa587a06fsewardj  memset (&work_init, 0, sizeof work_init);
2664de4a1d01951937632098a6cda45859afa587a06fsewardj  work_stuff_copy_to_from (&work_init, work);
2665de4a1d01951937632098a6cda45859afa587a06fsewardj
2666de4a1d01951937632098a6cda45859afa587a06fsewardj  /* Iterate over occurrences of __, allowing names and types to have a
2667de4a1d01951937632098a6cda45859afa587a06fsewardj     "__" sequence in them.  We must start with the first (not the last)
2668de4a1d01951937632098a6cda45859afa587a06fsewardj     occurrence, since "__" most often occur between independent mangled
2669ad4e979f408239dabbaae955d8ffcb84a51a5c85florian     parts, hence starting at the last occurrence inside a signature
2670de4a1d01951937632098a6cda45859afa587a06fsewardj     might get us a "successful" demangling of the signature.  */
2671de4a1d01951937632098a6cda45859afa587a06fsewardj
2672de4a1d01951937632098a6cda45859afa587a06fsewardj  while (scan[2])
2673de4a1d01951937632098a6cda45859afa587a06fsewardj    {
26744f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      if (demangle_function_name (work, mangled, declp, scan))
26754f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	{
26764f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	  success = demangle_signature (work, mangled, declp);
26774f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	  if (success)
26784f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	    break;
26794f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	}
2680de4a1d01951937632098a6cda45859afa587a06fsewardj
2681de4a1d01951937632098a6cda45859afa587a06fsewardj      /* Reset demangle state for the next round.  */
2682de4a1d01951937632098a6cda45859afa587a06fsewardj      *mangled = mangle_init;
2683de4a1d01951937632098a6cda45859afa587a06fsewardj      string_clear (declp);
2684de4a1d01951937632098a6cda45859afa587a06fsewardj      string_appends (declp, &decl_init);
2685de4a1d01951937632098a6cda45859afa587a06fsewardj      work_stuff_copy_to_from (work, &work_init);
2686de4a1d01951937632098a6cda45859afa587a06fsewardj
2687de4a1d01951937632098a6cda45859afa587a06fsewardj      /* Leave this underscore-sequence.  */
2688de4a1d01951937632098a6cda45859afa587a06fsewardj      scan += 2;
2689de4a1d01951937632098a6cda45859afa587a06fsewardj
2690de4a1d01951937632098a6cda45859afa587a06fsewardj      /* Scan for the next "__" sequence.  */
2691de4a1d01951937632098a6cda45859afa587a06fsewardj      while (*scan && (scan[0] != '_' || scan[1] != '_'))
2692de4a1d01951937632098a6cda45859afa587a06fsewardj	scan++;
2693de4a1d01951937632098a6cda45859afa587a06fsewardj
2694de4a1d01951937632098a6cda45859afa587a06fsewardj      /* Move to last "__" in this sequence.  */
2695de4a1d01951937632098a6cda45859afa587a06fsewardj      while (*scan && *scan == '_')
2696de4a1d01951937632098a6cda45859afa587a06fsewardj	scan++;
2697de4a1d01951937632098a6cda45859afa587a06fsewardj      scan -= 2;
2698de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2699de4a1d01951937632098a6cda45859afa587a06fsewardj
2700de4a1d01951937632098a6cda45859afa587a06fsewardj  /* Delete saved state.  */
2701de4a1d01951937632098a6cda45859afa587a06fsewardj  delete_work_stuff (&work_init);
2702de4a1d01951937632098a6cda45859afa587a06fsewardj  string_delete (&decl_init);
2703de4a1d01951937632098a6cda45859afa587a06fsewardj
2704de4a1d01951937632098a6cda45859afa587a06fsewardj  return success;
2705de4a1d01951937632098a6cda45859afa587a06fsewardj}
2706de4a1d01951937632098a6cda45859afa587a06fsewardj
2707de4a1d01951937632098a6cda45859afa587a06fsewardj/*
2708de4a1d01951937632098a6cda45859afa587a06fsewardj
2709de4a1d01951937632098a6cda45859afa587a06fsewardjLOCAL FUNCTION
2710de4a1d01951937632098a6cda45859afa587a06fsewardj
2711de4a1d01951937632098a6cda45859afa587a06fsewardj	demangle_prefix -- consume the mangled name prefix and find signature
2712de4a1d01951937632098a6cda45859afa587a06fsewardj
2713de4a1d01951937632098a6cda45859afa587a06fsewardjSYNOPSIS
2714de4a1d01951937632098a6cda45859afa587a06fsewardj
2715de4a1d01951937632098a6cda45859afa587a06fsewardj	static int
2716de4a1d01951937632098a6cda45859afa587a06fsewardj	demangle_prefix (struct work_stuff *work, const char **mangled,
2717de4a1d01951937632098a6cda45859afa587a06fsewardj			 string *declp);
2718de4a1d01951937632098a6cda45859afa587a06fsewardj
2719de4a1d01951937632098a6cda45859afa587a06fsewardjDESCRIPTION
2720de4a1d01951937632098a6cda45859afa587a06fsewardj
2721de4a1d01951937632098a6cda45859afa587a06fsewardj	Consume and demangle the prefix of the mangled name.
2722de4a1d01951937632098a6cda45859afa587a06fsewardj	While processing the function name root, arrange to call
2723de4a1d01951937632098a6cda45859afa587a06fsewardj	demangle_signature if the root is ambiguous.
2724de4a1d01951937632098a6cda45859afa587a06fsewardj
2725de4a1d01951937632098a6cda45859afa587a06fsewardj	DECLP points to the string buffer into which demangled output is
2726de4a1d01951937632098a6cda45859afa587a06fsewardj	placed.  On entry, the buffer is empty.  On exit it contains
2727de4a1d01951937632098a6cda45859afa587a06fsewardj	the root function name, the demangled operator name, or in some
2728de4a1d01951937632098a6cda45859afa587a06fsewardj	special cases either nothing or the completely demangled result.
2729de4a1d01951937632098a6cda45859afa587a06fsewardj
2730de4a1d01951937632098a6cda45859afa587a06fsewardj	MANGLED points to the current pointer into the mangled name.  As each
2731de4a1d01951937632098a6cda45859afa587a06fsewardj	token of the mangled name is consumed, it is updated.  Upon entry
2732de4a1d01951937632098a6cda45859afa587a06fsewardj	the current mangled name pointer points to the first character of
2733de4a1d01951937632098a6cda45859afa587a06fsewardj	the mangled name.  Upon exit, it should point to the first character
2734de4a1d01951937632098a6cda45859afa587a06fsewardj	of the signature if demangling was successful, or to the first
2735de4a1d01951937632098a6cda45859afa587a06fsewardj	unconsumed character if demangling of the prefix was unsuccessful.
2736de4a1d01951937632098a6cda45859afa587a06fsewardj
2737de4a1d01951937632098a6cda45859afa587a06fsewardj	Returns 1 on success, 0 otherwise.
2738de4a1d01951937632098a6cda45859afa587a06fsewardj */
2739de4a1d01951937632098a6cda45859afa587a06fsewardj
2740de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
27414f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_prefix (struct work_stuff *work, const char **mangled,
27424f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                 string *declp)
2743de4a1d01951937632098a6cda45859afa587a06fsewardj{
2744de4a1d01951937632098a6cda45859afa587a06fsewardj  int success = 1;
2745de4a1d01951937632098a6cda45859afa587a06fsewardj  const char *scan;
2746de4a1d01951937632098a6cda45859afa587a06fsewardj  int i;
2747de4a1d01951937632098a6cda45859afa587a06fsewardj
2748de4a1d01951937632098a6cda45859afa587a06fsewardj  if (strlen(*mangled) > 6
2749de4a1d01951937632098a6cda45859afa587a06fsewardj      && (strncmp(*mangled, "_imp__", 6) == 0
2750de4a1d01951937632098a6cda45859afa587a06fsewardj          || strncmp(*mangled, "__imp_", 6) == 0))
2751de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2752de4a1d01951937632098a6cda45859afa587a06fsewardj      /* it's a symbol imported from a PE dynamic library. Check for both
2753de4a1d01951937632098a6cda45859afa587a06fsewardj         new style prefix _imp__ and legacy __imp_ used by older versions
2754de4a1d01951937632098a6cda45859afa587a06fsewardj	 of dlltool. */
2755de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled) += 6;
2756de4a1d01951937632098a6cda45859afa587a06fsewardj      work->dllimported = 1;
2757de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2758de4a1d01951937632098a6cda45859afa587a06fsewardj  else if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0)
2759de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2760de4a1d01951937632098a6cda45859afa587a06fsewardj      char *marker = strchr (cplus_markers, (*mangled)[8]);
2761de4a1d01951937632098a6cda45859afa587a06fsewardj      if (marker != NULL && *marker == (*mangled)[10])
2762de4a1d01951937632098a6cda45859afa587a06fsewardj	{
2763de4a1d01951937632098a6cda45859afa587a06fsewardj	  if ((*mangled)[9] == 'D')
2764de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
2765de4a1d01951937632098a6cda45859afa587a06fsewardj	      /* it's a GNU global destructor to be executed at program exit */
2766de4a1d01951937632098a6cda45859afa587a06fsewardj	      (*mangled) += 11;
2767de4a1d01951937632098a6cda45859afa587a06fsewardj	      work->destructor = 2;
2768de4a1d01951937632098a6cda45859afa587a06fsewardj	      if (gnu_special (work, mangled, declp))
2769de4a1d01951937632098a6cda45859afa587a06fsewardj		return success;
2770de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
2771de4a1d01951937632098a6cda45859afa587a06fsewardj	  else if ((*mangled)[9] == 'I')
2772de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
2773de4a1d01951937632098a6cda45859afa587a06fsewardj	      /* it's a GNU global constructor to be executed at program init */
2774de4a1d01951937632098a6cda45859afa587a06fsewardj	      (*mangled) += 11;
2775de4a1d01951937632098a6cda45859afa587a06fsewardj	      work->constructor = 2;
2776de4a1d01951937632098a6cda45859afa587a06fsewardj	      if (gnu_special (work, mangled, declp))
2777de4a1d01951937632098a6cda45859afa587a06fsewardj		return success;
2778de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
2779de4a1d01951937632098a6cda45859afa587a06fsewardj	}
2780de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2781de4a1d01951937632098a6cda45859afa587a06fsewardj  else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__std__", 7) == 0)
2782de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2783de4a1d01951937632098a6cda45859afa587a06fsewardj      /* it's a ARM global destructor to be executed at program exit */
2784de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled) += 7;
2785de4a1d01951937632098a6cda45859afa587a06fsewardj      work->destructor = 2;
2786de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2787de4a1d01951937632098a6cda45859afa587a06fsewardj  else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__sti__", 7) == 0)
2788de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2789de4a1d01951937632098a6cda45859afa587a06fsewardj      /* it's a ARM global constructor to be executed at program initial */
2790de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled) += 7;
2791de4a1d01951937632098a6cda45859afa587a06fsewardj      work->constructor = 2;
2792de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2793de4a1d01951937632098a6cda45859afa587a06fsewardj
2794de4a1d01951937632098a6cda45859afa587a06fsewardj  /*  This block of code is a reduction in strength time optimization
2795de4a1d01951937632098a6cda45859afa587a06fsewardj      of:
2796de4a1d01951937632098a6cda45859afa587a06fsewardj      scan = strstr (*mangled, "__"); */
2797de4a1d01951937632098a6cda45859afa587a06fsewardj
2798de4a1d01951937632098a6cda45859afa587a06fsewardj  {
2799de4a1d01951937632098a6cda45859afa587a06fsewardj    scan = *mangled;
2800de4a1d01951937632098a6cda45859afa587a06fsewardj
2801de4a1d01951937632098a6cda45859afa587a06fsewardj    do {
2802de4a1d01951937632098a6cda45859afa587a06fsewardj      scan = strchr (scan, '_');
2803de4a1d01951937632098a6cda45859afa587a06fsewardj    } while (scan != NULL && *++scan != '_');
2804de4a1d01951937632098a6cda45859afa587a06fsewardj
2805de4a1d01951937632098a6cda45859afa587a06fsewardj    if (scan != NULL) --scan;
2806de4a1d01951937632098a6cda45859afa587a06fsewardj  }
2807de4a1d01951937632098a6cda45859afa587a06fsewardj
2808de4a1d01951937632098a6cda45859afa587a06fsewardj  if (scan != NULL)
2809de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2810de4a1d01951937632098a6cda45859afa587a06fsewardj      /* We found a sequence of two or more '_', ensure that we start at
2811de4a1d01951937632098a6cda45859afa587a06fsewardj	 the last pair in the sequence.  */
28124f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      i = strspn (scan, "_");
2813de4a1d01951937632098a6cda45859afa587a06fsewardj      if (i > 2)
2814de4a1d01951937632098a6cda45859afa587a06fsewardj	{
2815de4a1d01951937632098a6cda45859afa587a06fsewardj	  scan += (i - 2);
2816de4a1d01951937632098a6cda45859afa587a06fsewardj	}
2817de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2818de4a1d01951937632098a6cda45859afa587a06fsewardj
2819de4a1d01951937632098a6cda45859afa587a06fsewardj  if (scan == NULL)
2820de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2821de4a1d01951937632098a6cda45859afa587a06fsewardj      success = 0;
2822de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2823de4a1d01951937632098a6cda45859afa587a06fsewardj  else if (work -> static_type)
2824de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2825de4a1d01951937632098a6cda45859afa587a06fsewardj      if (!ISDIGIT ((unsigned char)scan[0]) && (scan[0] != 't'))
2826de4a1d01951937632098a6cda45859afa587a06fsewardj	{
2827de4a1d01951937632098a6cda45859afa587a06fsewardj	  success = 0;
2828de4a1d01951937632098a6cda45859afa587a06fsewardj	}
2829de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2830de4a1d01951937632098a6cda45859afa587a06fsewardj  else if ((scan == *mangled)
2831de4a1d01951937632098a6cda45859afa587a06fsewardj	   && (ISDIGIT ((unsigned char)scan[2]) || (scan[2] == 'Q')
2832de4a1d01951937632098a6cda45859afa587a06fsewardj	       || (scan[2] == 't') || (scan[2] == 'K') || (scan[2] == 'H')))
2833de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2834de4a1d01951937632098a6cda45859afa587a06fsewardj      /* The ARM says nothing about the mangling of local variables.
2835de4a1d01951937632098a6cda45859afa587a06fsewardj	 But cfront mangles local variables by prepending __<nesting_level>
2836de4a1d01951937632098a6cda45859afa587a06fsewardj	 to them. As an extension to ARM demangling we handle this case.  */
2837de4a1d01951937632098a6cda45859afa587a06fsewardj      if ((LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING)
2838de4a1d01951937632098a6cda45859afa587a06fsewardj	  && ISDIGIT ((unsigned char)scan[2]))
2839de4a1d01951937632098a6cda45859afa587a06fsewardj	{
2840de4a1d01951937632098a6cda45859afa587a06fsewardj	  *mangled = scan + 2;
2841de4a1d01951937632098a6cda45859afa587a06fsewardj	  consume_count (mangled);
2842de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_append (declp, *mangled);
2843de4a1d01951937632098a6cda45859afa587a06fsewardj	  *mangled += strlen (*mangled);
2844de4a1d01951937632098a6cda45859afa587a06fsewardj	  success = 1;
2845de4a1d01951937632098a6cda45859afa587a06fsewardj	}
2846de4a1d01951937632098a6cda45859afa587a06fsewardj      else
2847de4a1d01951937632098a6cda45859afa587a06fsewardj	{
2848de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* A GNU style constructor starts with __[0-9Qt].  But cfront uses
2849de4a1d01951937632098a6cda45859afa587a06fsewardj	     names like __Q2_3foo3bar for nested type names.  So don't accept
2850de4a1d01951937632098a6cda45859afa587a06fsewardj	     this style of constructor for cfront demangling.  A GNU
2851de4a1d01951937632098a6cda45859afa587a06fsewardj	     style member-template constructor starts with 'H'. */
2852de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (!(LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING))
2853de4a1d01951937632098a6cda45859afa587a06fsewardj	    work -> constructor += 1;
2854de4a1d01951937632098a6cda45859afa587a06fsewardj	  *mangled = scan + 2;
2855de4a1d01951937632098a6cda45859afa587a06fsewardj	}
2856de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2857de4a1d01951937632098a6cda45859afa587a06fsewardj  else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't')
2858de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2859de4a1d01951937632098a6cda45859afa587a06fsewardj      /* Cfront-style parameterized type.  Handled later as a signature. */
2860de4a1d01951937632098a6cda45859afa587a06fsewardj      success = 1;
2861de4a1d01951937632098a6cda45859afa587a06fsewardj
2862de4a1d01951937632098a6cda45859afa587a06fsewardj      /* ARM template? */
2863de4a1d01951937632098a6cda45859afa587a06fsewardj      demangle_arm_hp_template (work, mangled, strlen (*mangled), declp);
2864de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2865de4a1d01951937632098a6cda45859afa587a06fsewardj  else if (EDG_DEMANGLING && ((scan[2] == 't' && scan[3] == 'm')
2866de4a1d01951937632098a6cda45859afa587a06fsewardj                              || (scan[2] == 'p' && scan[3] == 's')
2867de4a1d01951937632098a6cda45859afa587a06fsewardj                              || (scan[2] == 'p' && scan[3] == 't')))
2868de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2869de4a1d01951937632098a6cda45859afa587a06fsewardj      /* EDG-style parameterized type.  Handled later as a signature. */
2870de4a1d01951937632098a6cda45859afa587a06fsewardj      success = 1;
2871de4a1d01951937632098a6cda45859afa587a06fsewardj
2872de4a1d01951937632098a6cda45859afa587a06fsewardj      /* EDG template? */
2873de4a1d01951937632098a6cda45859afa587a06fsewardj      demangle_arm_hp_template (work, mangled, strlen (*mangled), declp);
2874de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2875de4a1d01951937632098a6cda45859afa587a06fsewardj  else if ((scan == *mangled) && !ISDIGIT ((unsigned char)scan[2])
2876de4a1d01951937632098a6cda45859afa587a06fsewardj	   && (scan[2] != 't'))
2877de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2878de4a1d01951937632098a6cda45859afa587a06fsewardj      /* Mangled name starts with "__".  Skip over any leading '_' characters,
2879de4a1d01951937632098a6cda45859afa587a06fsewardj	 then find the next "__" that separates the prefix from the signature.
2880de4a1d01951937632098a6cda45859afa587a06fsewardj	 */
2881de4a1d01951937632098a6cda45859afa587a06fsewardj      if (!(ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
2882de4a1d01951937632098a6cda45859afa587a06fsewardj	  || (arm_special (mangled, declp) == 0))
2883de4a1d01951937632098a6cda45859afa587a06fsewardj	{
2884de4a1d01951937632098a6cda45859afa587a06fsewardj	  while (*scan == '_')
2885de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
2886de4a1d01951937632098a6cda45859afa587a06fsewardj	      scan++;
2887de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
2888de4a1d01951937632098a6cda45859afa587a06fsewardj	  if ((scan = strstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
2889de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
2890de4a1d01951937632098a6cda45859afa587a06fsewardj	      /* No separator (I.E. "__not_mangled"), or empty signature
2891de4a1d01951937632098a6cda45859afa587a06fsewardj		 (I.E. "__not_mangled_either__") */
2892de4a1d01951937632098a6cda45859afa587a06fsewardj	      success = 0;
2893de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
2894de4a1d01951937632098a6cda45859afa587a06fsewardj	  else
2895de4a1d01951937632098a6cda45859afa587a06fsewardj	    return iterate_demangle_function (work, mangled, declp, scan);
2896de4a1d01951937632098a6cda45859afa587a06fsewardj	}
2897de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2898de4a1d01951937632098a6cda45859afa587a06fsewardj  else if (*(scan + 2) != '\0')
2899de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2900de4a1d01951937632098a6cda45859afa587a06fsewardj      /* Mangled name does not start with "__" but does have one somewhere
2901de4a1d01951937632098a6cda45859afa587a06fsewardj	 in there with non empty stuff after it.  Looks like a global
2902de4a1d01951937632098a6cda45859afa587a06fsewardj	 function name.  Iterate over all "__":s until the right
2903de4a1d01951937632098a6cda45859afa587a06fsewardj	 one is found.  */
2904de4a1d01951937632098a6cda45859afa587a06fsewardj      return iterate_demangle_function (work, mangled, declp, scan);
2905de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2906de4a1d01951937632098a6cda45859afa587a06fsewardj  else
2907de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2908de4a1d01951937632098a6cda45859afa587a06fsewardj      /* Doesn't look like a mangled name */
2909de4a1d01951937632098a6cda45859afa587a06fsewardj      success = 0;
2910de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2911de4a1d01951937632098a6cda45859afa587a06fsewardj
2912de4a1d01951937632098a6cda45859afa587a06fsewardj  if (!success && (work->constructor == 2 || work->destructor == 2))
2913de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2914de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (declp, *mangled);
2915de4a1d01951937632098a6cda45859afa587a06fsewardj      *mangled += strlen (*mangled);
2916de4a1d01951937632098a6cda45859afa587a06fsewardj      success = 1;
2917de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2918de4a1d01951937632098a6cda45859afa587a06fsewardj  return (success);
2919de4a1d01951937632098a6cda45859afa587a06fsewardj}
2920de4a1d01951937632098a6cda45859afa587a06fsewardj
2921de4a1d01951937632098a6cda45859afa587a06fsewardj/*
2922de4a1d01951937632098a6cda45859afa587a06fsewardj
2923de4a1d01951937632098a6cda45859afa587a06fsewardjLOCAL FUNCTION
2924de4a1d01951937632098a6cda45859afa587a06fsewardj
2925de4a1d01951937632098a6cda45859afa587a06fsewardj	gnu_special -- special handling of gnu mangled strings
2926de4a1d01951937632098a6cda45859afa587a06fsewardj
2927de4a1d01951937632098a6cda45859afa587a06fsewardjSYNOPSIS
2928de4a1d01951937632098a6cda45859afa587a06fsewardj
2929de4a1d01951937632098a6cda45859afa587a06fsewardj	static int
2930de4a1d01951937632098a6cda45859afa587a06fsewardj	gnu_special (struct work_stuff *work, const char **mangled,
2931de4a1d01951937632098a6cda45859afa587a06fsewardj		     string *declp);
2932de4a1d01951937632098a6cda45859afa587a06fsewardj
2933de4a1d01951937632098a6cda45859afa587a06fsewardj
2934de4a1d01951937632098a6cda45859afa587a06fsewardjDESCRIPTION
2935de4a1d01951937632098a6cda45859afa587a06fsewardj
2936de4a1d01951937632098a6cda45859afa587a06fsewardj	Process some special GNU style mangling forms that don't fit
2937de4a1d01951937632098a6cda45859afa587a06fsewardj	the normal pattern.  For example:
2938de4a1d01951937632098a6cda45859afa587a06fsewardj
2939de4a1d01951937632098a6cda45859afa587a06fsewardj		_$_3foo		(destructor for class foo)
2940de4a1d01951937632098a6cda45859afa587a06fsewardj		_vt$foo		(foo virtual table)
2941de4a1d01951937632098a6cda45859afa587a06fsewardj		_vt$foo$bar	(foo::bar virtual table)
2942de4a1d01951937632098a6cda45859afa587a06fsewardj		__vt_foo	(foo virtual table, new style with thunks)
2943de4a1d01951937632098a6cda45859afa587a06fsewardj		_3foo$varname	(static data member)
2944de4a1d01951937632098a6cda45859afa587a06fsewardj		_Q22rs2tu$vw	(static data member)
2945de4a1d01951937632098a6cda45859afa587a06fsewardj		__t6vector1Zii	(constructor with template)
2946de4a1d01951937632098a6cda45859afa587a06fsewardj		__thunk_4__$_7ostream (virtual function thunk)
2947de4a1d01951937632098a6cda45859afa587a06fsewardj */
2948de4a1d01951937632098a6cda45859afa587a06fsewardj
2949de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
29504f2683ace412ca2c8266f2dd860dee4461df3cafsewardjgnu_special (struct work_stuff *work, const char **mangled, string *declp)
2951de4a1d01951937632098a6cda45859afa587a06fsewardj{
2952de4a1d01951937632098a6cda45859afa587a06fsewardj  int n;
2953de4a1d01951937632098a6cda45859afa587a06fsewardj  int success = 1;
2954de4a1d01951937632098a6cda45859afa587a06fsewardj  const char *p;
2955de4a1d01951937632098a6cda45859afa587a06fsewardj
2956de4a1d01951937632098a6cda45859afa587a06fsewardj  if ((*mangled)[0] == '_'
2957de4a1d01951937632098a6cda45859afa587a06fsewardj      && strchr (cplus_markers, (*mangled)[1]) != NULL
2958de4a1d01951937632098a6cda45859afa587a06fsewardj      && (*mangled)[2] == '_')
2959de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2960de4a1d01951937632098a6cda45859afa587a06fsewardj      /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
2961de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled) += 3;
2962de4a1d01951937632098a6cda45859afa587a06fsewardj      work -> destructor += 1;
2963de4a1d01951937632098a6cda45859afa587a06fsewardj    }
2964de4a1d01951937632098a6cda45859afa587a06fsewardj  else if ((*mangled)[0] == '_'
2965de4a1d01951937632098a6cda45859afa587a06fsewardj	   && (((*mangled)[1] == '_'
2966de4a1d01951937632098a6cda45859afa587a06fsewardj		&& (*mangled)[2] == 'v'
2967de4a1d01951937632098a6cda45859afa587a06fsewardj		&& (*mangled)[3] == 't'
2968de4a1d01951937632098a6cda45859afa587a06fsewardj		&& (*mangled)[4] == '_')
2969de4a1d01951937632098a6cda45859afa587a06fsewardj	       || ((*mangled)[1] == 'v'
2970de4a1d01951937632098a6cda45859afa587a06fsewardj		   && (*mangled)[2] == 't'
2971de4a1d01951937632098a6cda45859afa587a06fsewardj		   && strchr (cplus_markers, (*mangled)[3]) != NULL)))
2972de4a1d01951937632098a6cda45859afa587a06fsewardj    {
2973de4a1d01951937632098a6cda45859afa587a06fsewardj      /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
2974de4a1d01951937632098a6cda45859afa587a06fsewardj         and create the decl.  Note that we consume the entire mangled
2975de4a1d01951937632098a6cda45859afa587a06fsewardj	 input string, which means that demangle_signature has no work
2976de4a1d01951937632098a6cda45859afa587a06fsewardj	 to do.  */
2977de4a1d01951937632098a6cda45859afa587a06fsewardj      if ((*mangled)[2] == 'v')
2978de4a1d01951937632098a6cda45859afa587a06fsewardj	(*mangled) += 5; /* New style, with thunks: "__vt_" */
2979de4a1d01951937632098a6cda45859afa587a06fsewardj      else
2980de4a1d01951937632098a6cda45859afa587a06fsewardj	(*mangled) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
2981de4a1d01951937632098a6cda45859afa587a06fsewardj      while (**mangled != '\0')
2982de4a1d01951937632098a6cda45859afa587a06fsewardj	{
2983de4a1d01951937632098a6cda45859afa587a06fsewardj	  switch (**mangled)
2984de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
2985de4a1d01951937632098a6cda45859afa587a06fsewardj	    case 'Q':
2986de4a1d01951937632098a6cda45859afa587a06fsewardj	    case 'K':
2987de4a1d01951937632098a6cda45859afa587a06fsewardj	      success = demangle_qualified (work, mangled, declp, 0, 1);
2988de4a1d01951937632098a6cda45859afa587a06fsewardj	      break;
2989de4a1d01951937632098a6cda45859afa587a06fsewardj	    case 't':
2990de4a1d01951937632098a6cda45859afa587a06fsewardj	      success = demangle_template (work, mangled, declp, 0, 1,
2991de4a1d01951937632098a6cda45859afa587a06fsewardj					   1);
2992de4a1d01951937632098a6cda45859afa587a06fsewardj	      break;
2993de4a1d01951937632098a6cda45859afa587a06fsewardj	    default:
2994de4a1d01951937632098a6cda45859afa587a06fsewardj	      if (ISDIGIT((unsigned char)*mangled[0]))
2995de4a1d01951937632098a6cda45859afa587a06fsewardj		{
2996de4a1d01951937632098a6cda45859afa587a06fsewardj		  n = consume_count(mangled);
2997de4a1d01951937632098a6cda45859afa587a06fsewardj		  /* We may be seeing a too-large size, or else a
2998de4a1d01951937632098a6cda45859afa587a06fsewardj		     ".<digits>" indicating a static local symbol.  In
2999de4a1d01951937632098a6cda45859afa587a06fsewardj		     any case, declare victory and move on; *don't* try
3000de4a1d01951937632098a6cda45859afa587a06fsewardj		     to use n to allocate.  */
3001de4a1d01951937632098a6cda45859afa587a06fsewardj		  if (n > (int) strlen (*mangled))
3002de4a1d01951937632098a6cda45859afa587a06fsewardj		    {
3003de4a1d01951937632098a6cda45859afa587a06fsewardj		      success = 1;
3004de4a1d01951937632098a6cda45859afa587a06fsewardj		      break;
3005de4a1d01951937632098a6cda45859afa587a06fsewardj		    }
3006de4a1d01951937632098a6cda45859afa587a06fsewardj		}
3007de4a1d01951937632098a6cda45859afa587a06fsewardj	      else
3008de4a1d01951937632098a6cda45859afa587a06fsewardj		{
30094f2683ace412ca2c8266f2dd860dee4461df3cafsewardj		  n = strcspn (*mangled, cplus_markers);
3010de4a1d01951937632098a6cda45859afa587a06fsewardj		}
3011de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_appendn (declp, *mangled, n);
3012de4a1d01951937632098a6cda45859afa587a06fsewardj	      (*mangled) += n;
3013de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
3014de4a1d01951937632098a6cda45859afa587a06fsewardj
3015de4a1d01951937632098a6cda45859afa587a06fsewardj	  p = strpbrk (*mangled, cplus_markers);
3016de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (success && ((p == NULL) || (p == *mangled)))
3017de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
3018de4a1d01951937632098a6cda45859afa587a06fsewardj	      if (p != NULL)
3019de4a1d01951937632098a6cda45859afa587a06fsewardj		{
3020de4a1d01951937632098a6cda45859afa587a06fsewardj		  string_append (declp, SCOPE_STRING (work));
3021de4a1d01951937632098a6cda45859afa587a06fsewardj		  (*mangled)++;
3022de4a1d01951937632098a6cda45859afa587a06fsewardj		}
3023de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
3024de4a1d01951937632098a6cda45859afa587a06fsewardj	  else
3025de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
3026de4a1d01951937632098a6cda45859afa587a06fsewardj	      success = 0;
3027de4a1d01951937632098a6cda45859afa587a06fsewardj	      break;
3028de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
3029de4a1d01951937632098a6cda45859afa587a06fsewardj	}
3030de4a1d01951937632098a6cda45859afa587a06fsewardj      if (success)
3031de4a1d01951937632098a6cda45859afa587a06fsewardj	string_append (declp, " virtual table");
3032de4a1d01951937632098a6cda45859afa587a06fsewardj    }
3033de4a1d01951937632098a6cda45859afa587a06fsewardj  else if ((*mangled)[0] == '_'
3034de4a1d01951937632098a6cda45859afa587a06fsewardj	   && (strchr("0123456789Qt", (*mangled)[1]) != NULL)
3035de4a1d01951937632098a6cda45859afa587a06fsewardj	   && (p = strpbrk (*mangled, cplus_markers)) != NULL)
3036de4a1d01951937632098a6cda45859afa587a06fsewardj    {
3037de4a1d01951937632098a6cda45859afa587a06fsewardj      /* static data member, "_3foo$varname" for example */
3038de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
3039de4a1d01951937632098a6cda45859afa587a06fsewardj      switch (**mangled)
3040de4a1d01951937632098a6cda45859afa587a06fsewardj	{
3041de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'Q':
3042de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'K':
3043de4a1d01951937632098a6cda45859afa587a06fsewardj	  success = demangle_qualified (work, mangled, declp, 0, 1);
3044de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
3045de4a1d01951937632098a6cda45859afa587a06fsewardj	case 't':
3046de4a1d01951937632098a6cda45859afa587a06fsewardj	  success = demangle_template (work, mangled, declp, 0, 1, 1);
3047de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
3048de4a1d01951937632098a6cda45859afa587a06fsewardj	default:
3049de4a1d01951937632098a6cda45859afa587a06fsewardj	  n = consume_count (mangled);
3050de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (n < 0 || n > (long) strlen (*mangled))
3051de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
3052de4a1d01951937632098a6cda45859afa587a06fsewardj	      success = 0;
3053de4a1d01951937632098a6cda45859afa587a06fsewardj	      break;
3054de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
3055de4a1d01951937632098a6cda45859afa587a06fsewardj
3056de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (n > 10 && strncmp (*mangled, "_GLOBAL_", 8) == 0
3057de4a1d01951937632098a6cda45859afa587a06fsewardj	      && (*mangled)[9] == 'N'
3058de4a1d01951937632098a6cda45859afa587a06fsewardj	      && (*mangled)[8] == (*mangled)[10]
3059de4a1d01951937632098a6cda45859afa587a06fsewardj	      && strchr (cplus_markers, (*mangled)[8]))
3060de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
3061de4a1d01951937632098a6cda45859afa587a06fsewardj	      /* A member of the anonymous namespace.  There's information
3062de4a1d01951937632098a6cda45859afa587a06fsewardj		 about what identifier or filename it was keyed to, but
3063de4a1d01951937632098a6cda45859afa587a06fsewardj		 it's just there to make the mangled name unique; we just
3064de4a1d01951937632098a6cda45859afa587a06fsewardj		 step over it.  */
3065de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_append (declp, "{anonymous}");
3066de4a1d01951937632098a6cda45859afa587a06fsewardj	      (*mangled) += n;
3067de4a1d01951937632098a6cda45859afa587a06fsewardj
3068de4a1d01951937632098a6cda45859afa587a06fsewardj	      /* Now p points to the marker before the N, so we need to
3069de4a1d01951937632098a6cda45859afa587a06fsewardj		 update it to the first marker after what we consumed.  */
3070de4a1d01951937632098a6cda45859afa587a06fsewardj	      p = strpbrk (*mangled, cplus_markers);
3071de4a1d01951937632098a6cda45859afa587a06fsewardj	      break;
3072de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
3073de4a1d01951937632098a6cda45859afa587a06fsewardj
3074de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_appendn (declp, *mangled, n);
3075de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled) += n;
3076de4a1d01951937632098a6cda45859afa587a06fsewardj	}
3077de4a1d01951937632098a6cda45859afa587a06fsewardj      if (success && (p == *mangled))
3078de4a1d01951937632098a6cda45859afa587a06fsewardj	{
3079de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* Consumed everything up to the cplus_marker, append the
3080de4a1d01951937632098a6cda45859afa587a06fsewardj	     variable name.  */
3081de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled)++;
3082de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_append (declp, SCOPE_STRING (work));
3083de4a1d01951937632098a6cda45859afa587a06fsewardj	  n = strlen (*mangled);
3084de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_appendn (declp, *mangled, n);
3085de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled) += n;
3086de4a1d01951937632098a6cda45859afa587a06fsewardj	}
3087de4a1d01951937632098a6cda45859afa587a06fsewardj      else
3088de4a1d01951937632098a6cda45859afa587a06fsewardj	{
3089de4a1d01951937632098a6cda45859afa587a06fsewardj	  success = 0;
3090de4a1d01951937632098a6cda45859afa587a06fsewardj	}
3091de4a1d01951937632098a6cda45859afa587a06fsewardj    }
3092de4a1d01951937632098a6cda45859afa587a06fsewardj  else if (strncmp (*mangled, "__thunk_", 8) == 0)
3093de4a1d01951937632098a6cda45859afa587a06fsewardj    {
3094de4a1d01951937632098a6cda45859afa587a06fsewardj      int delta;
3095de4a1d01951937632098a6cda45859afa587a06fsewardj
3096de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled) += 8;
3097de4a1d01951937632098a6cda45859afa587a06fsewardj      delta = consume_count (mangled);
3098de4a1d01951937632098a6cda45859afa587a06fsewardj      if (delta == -1)
3099de4a1d01951937632098a6cda45859afa587a06fsewardj	success = 0;
3100de4a1d01951937632098a6cda45859afa587a06fsewardj      else
3101de4a1d01951937632098a6cda45859afa587a06fsewardj	{
3102de4a1d01951937632098a6cda45859afa587a06fsewardj	  char *method = internal_cplus_demangle (work, ++*mangled);
3103de4a1d01951937632098a6cda45859afa587a06fsewardj
3104de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (method)
3105de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
3106de4a1d01951937632098a6cda45859afa587a06fsewardj	      char buf[50];
3107de4a1d01951937632098a6cda45859afa587a06fsewardj	      sprintf (buf, "virtual function thunk (delta:%d) for ", -delta);
3108de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_append (declp, buf);
3109de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_append (declp, method);
3110de4a1d01951937632098a6cda45859afa587a06fsewardj	      free (method);
3111de4a1d01951937632098a6cda45859afa587a06fsewardj	      n = strlen (*mangled);
3112de4a1d01951937632098a6cda45859afa587a06fsewardj	      (*mangled) += n;
3113de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
3114de4a1d01951937632098a6cda45859afa587a06fsewardj	  else
3115de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
3116de4a1d01951937632098a6cda45859afa587a06fsewardj	      success = 0;
3117de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
3118de4a1d01951937632098a6cda45859afa587a06fsewardj	}
3119de4a1d01951937632098a6cda45859afa587a06fsewardj    }
3120de4a1d01951937632098a6cda45859afa587a06fsewardj  else if (strncmp (*mangled, "__t", 3) == 0
3121de4a1d01951937632098a6cda45859afa587a06fsewardj	   && ((*mangled)[3] == 'i' || (*mangled)[3] == 'f'))
3122de4a1d01951937632098a6cda45859afa587a06fsewardj    {
3123de4a1d01951937632098a6cda45859afa587a06fsewardj      p = (*mangled)[3] == 'i' ? " type_info node" : " type_info function";
3124de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled) += 4;
3125de4a1d01951937632098a6cda45859afa587a06fsewardj      switch (**mangled)
3126de4a1d01951937632098a6cda45859afa587a06fsewardj	{
3127de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'Q':
3128de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'K':
3129de4a1d01951937632098a6cda45859afa587a06fsewardj	  success = demangle_qualified (work, mangled, declp, 0, 1);
3130de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
3131de4a1d01951937632098a6cda45859afa587a06fsewardj	case 't':
3132de4a1d01951937632098a6cda45859afa587a06fsewardj	  success = demangle_template (work, mangled, declp, 0, 1, 1);
3133de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
3134de4a1d01951937632098a6cda45859afa587a06fsewardj	default:
3135de4a1d01951937632098a6cda45859afa587a06fsewardj	  success = do_type (work, mangled, declp);
3136de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
3137de4a1d01951937632098a6cda45859afa587a06fsewardj	}
3138de4a1d01951937632098a6cda45859afa587a06fsewardj      if (success && **mangled != '\0')
3139de4a1d01951937632098a6cda45859afa587a06fsewardj	success = 0;
3140de4a1d01951937632098a6cda45859afa587a06fsewardj      if (success)
3141de4a1d01951937632098a6cda45859afa587a06fsewardj	string_append (declp, p);
3142de4a1d01951937632098a6cda45859afa587a06fsewardj    }
3143de4a1d01951937632098a6cda45859afa587a06fsewardj  else
3144de4a1d01951937632098a6cda45859afa587a06fsewardj    {
3145de4a1d01951937632098a6cda45859afa587a06fsewardj      success = 0;
3146de4a1d01951937632098a6cda45859afa587a06fsewardj    }
3147de4a1d01951937632098a6cda45859afa587a06fsewardj  return (success);
3148de4a1d01951937632098a6cda45859afa587a06fsewardj}
3149de4a1d01951937632098a6cda45859afa587a06fsewardj
3150de4a1d01951937632098a6cda45859afa587a06fsewardjstatic void
31514f2683ace412ca2c8266f2dd860dee4461df3cafsewardjrecursively_demangle(struct work_stuff *work, const char **mangled,
31524f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                     string *result, int namelength)
3153de4a1d01951937632098a6cda45859afa587a06fsewardj{
3154de4a1d01951937632098a6cda45859afa587a06fsewardj  char * recurse = (char *)NULL;
3155de4a1d01951937632098a6cda45859afa587a06fsewardj  char * recurse_dem = (char *)NULL;
3156de4a1d01951937632098a6cda45859afa587a06fsewardj
31574f2683ace412ca2c8266f2dd860dee4461df3cafsewardj  recurse = XNEWVEC (char, namelength + 1);
3158de4a1d01951937632098a6cda45859afa587a06fsewardj  memcpy (recurse, *mangled, namelength);
3159de4a1d01951937632098a6cda45859afa587a06fsewardj  recurse[namelength] = '\000';
3160de4a1d01951937632098a6cda45859afa587a06fsewardj
316144fae838401cd4993b8e4b1cac152ebbd37f28e7sewardj  recurse_dem = ML_(cplus_demangle) (recurse, work->options);
3162de4a1d01951937632098a6cda45859afa587a06fsewardj
3163de4a1d01951937632098a6cda45859afa587a06fsewardj  if (recurse_dem)
3164de4a1d01951937632098a6cda45859afa587a06fsewardj    {
3165de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (result, recurse_dem);
3166de4a1d01951937632098a6cda45859afa587a06fsewardj      free (recurse_dem);
3167de4a1d01951937632098a6cda45859afa587a06fsewardj    }
3168de4a1d01951937632098a6cda45859afa587a06fsewardj  else
3169de4a1d01951937632098a6cda45859afa587a06fsewardj    {
3170de4a1d01951937632098a6cda45859afa587a06fsewardj      string_appendn (result, *mangled, namelength);
3171de4a1d01951937632098a6cda45859afa587a06fsewardj    }
3172de4a1d01951937632098a6cda45859afa587a06fsewardj  free (recurse);
3173de4a1d01951937632098a6cda45859afa587a06fsewardj  *mangled += namelength;
3174de4a1d01951937632098a6cda45859afa587a06fsewardj}
3175de4a1d01951937632098a6cda45859afa587a06fsewardj
3176de4a1d01951937632098a6cda45859afa587a06fsewardj/*
3177de4a1d01951937632098a6cda45859afa587a06fsewardj
3178de4a1d01951937632098a6cda45859afa587a06fsewardjLOCAL FUNCTION
3179de4a1d01951937632098a6cda45859afa587a06fsewardj
3180de4a1d01951937632098a6cda45859afa587a06fsewardj	arm_special -- special handling of ARM/lucid mangled strings
3181de4a1d01951937632098a6cda45859afa587a06fsewardj
3182de4a1d01951937632098a6cda45859afa587a06fsewardjSYNOPSIS
3183de4a1d01951937632098a6cda45859afa587a06fsewardj
3184de4a1d01951937632098a6cda45859afa587a06fsewardj	static int
3185de4a1d01951937632098a6cda45859afa587a06fsewardj	arm_special (const char **mangled,
3186de4a1d01951937632098a6cda45859afa587a06fsewardj		     string *declp);
3187de4a1d01951937632098a6cda45859afa587a06fsewardj
3188de4a1d01951937632098a6cda45859afa587a06fsewardj
3189de4a1d01951937632098a6cda45859afa587a06fsewardjDESCRIPTION
3190de4a1d01951937632098a6cda45859afa587a06fsewardj
3191de4a1d01951937632098a6cda45859afa587a06fsewardj	Process some special ARM style mangling forms that don't fit
3192de4a1d01951937632098a6cda45859afa587a06fsewardj	the normal pattern.  For example:
3193de4a1d01951937632098a6cda45859afa587a06fsewardj
3194de4a1d01951937632098a6cda45859afa587a06fsewardj		__vtbl__3foo		(foo virtual table)
3195de4a1d01951937632098a6cda45859afa587a06fsewardj		__vtbl__3foo__3bar	(bar::foo virtual table)
3196de4a1d01951937632098a6cda45859afa587a06fsewardj
3197de4a1d01951937632098a6cda45859afa587a06fsewardj */
3198de4a1d01951937632098a6cda45859afa587a06fsewardj
3199de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
32004f2683ace412ca2c8266f2dd860dee4461df3cafsewardjarm_special (const char **mangled, string *declp)
3201de4a1d01951937632098a6cda45859afa587a06fsewardj{
3202de4a1d01951937632098a6cda45859afa587a06fsewardj  int n;
3203de4a1d01951937632098a6cda45859afa587a06fsewardj  int success = 1;
3204de4a1d01951937632098a6cda45859afa587a06fsewardj  const char *scan;
3205de4a1d01951937632098a6cda45859afa587a06fsewardj
3206de4a1d01951937632098a6cda45859afa587a06fsewardj  if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
3207de4a1d01951937632098a6cda45859afa587a06fsewardj    {
3208de4a1d01951937632098a6cda45859afa587a06fsewardj      /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
3209de4a1d01951937632098a6cda45859afa587a06fsewardj         and create the decl.  Note that we consume the entire mangled
3210de4a1d01951937632098a6cda45859afa587a06fsewardj	 input string, which means that demangle_signature has no work
3211de4a1d01951937632098a6cda45859afa587a06fsewardj	 to do.  */
3212de4a1d01951937632098a6cda45859afa587a06fsewardj      scan = *mangled + ARM_VTABLE_STRLEN;
3213de4a1d01951937632098a6cda45859afa587a06fsewardj      while (*scan != '\0')        /* first check it can be demangled */
3214de4a1d01951937632098a6cda45859afa587a06fsewardj        {
3215de4a1d01951937632098a6cda45859afa587a06fsewardj          n = consume_count (&scan);
3216de4a1d01951937632098a6cda45859afa587a06fsewardj          if (n == -1)
3217de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
3218de4a1d01951937632098a6cda45859afa587a06fsewardj	      return (0);           /* no good */
3219de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
3220de4a1d01951937632098a6cda45859afa587a06fsewardj          scan += n;
3221de4a1d01951937632098a6cda45859afa587a06fsewardj          if (scan[0] == '_' && scan[1] == '_')
3222de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
3223de4a1d01951937632098a6cda45859afa587a06fsewardj	      scan += 2;
3224de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
3225de4a1d01951937632098a6cda45859afa587a06fsewardj        }
3226de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled) += ARM_VTABLE_STRLEN;
3227de4a1d01951937632098a6cda45859afa587a06fsewardj      while (**mangled != '\0')
3228de4a1d01951937632098a6cda45859afa587a06fsewardj	{
3229de4a1d01951937632098a6cda45859afa587a06fsewardj	  n = consume_count (mangled);
3230de4a1d01951937632098a6cda45859afa587a06fsewardj          if (n == -1
3231de4a1d01951937632098a6cda45859afa587a06fsewardj	      || n > (long) strlen (*mangled))
3232de4a1d01951937632098a6cda45859afa587a06fsewardj	    return 0;
3233de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_prependn (declp, *mangled, n);
3234de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled) += n;
3235de4a1d01951937632098a6cda45859afa587a06fsewardj	  if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
3236de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
3237de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_prepend (declp, "::");
3238de4a1d01951937632098a6cda45859afa587a06fsewardj	      (*mangled) += 2;
3239de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
3240de4a1d01951937632098a6cda45859afa587a06fsewardj	}
3241de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (declp, " virtual table");
3242de4a1d01951937632098a6cda45859afa587a06fsewardj    }
3243de4a1d01951937632098a6cda45859afa587a06fsewardj  else
3244de4a1d01951937632098a6cda45859afa587a06fsewardj    {
3245de4a1d01951937632098a6cda45859afa587a06fsewardj      success = 0;
3246de4a1d01951937632098a6cda45859afa587a06fsewardj    }
3247de4a1d01951937632098a6cda45859afa587a06fsewardj  return (success);
3248de4a1d01951937632098a6cda45859afa587a06fsewardj}
3249de4a1d01951937632098a6cda45859afa587a06fsewardj
3250de4a1d01951937632098a6cda45859afa587a06fsewardj/*
3251de4a1d01951937632098a6cda45859afa587a06fsewardj
3252de4a1d01951937632098a6cda45859afa587a06fsewardjLOCAL FUNCTION
3253de4a1d01951937632098a6cda45859afa587a06fsewardj
3254de4a1d01951937632098a6cda45859afa587a06fsewardj	demangle_qualified -- demangle 'Q' qualified name strings
3255de4a1d01951937632098a6cda45859afa587a06fsewardj
3256de4a1d01951937632098a6cda45859afa587a06fsewardjSYNOPSIS
3257de4a1d01951937632098a6cda45859afa587a06fsewardj
3258de4a1d01951937632098a6cda45859afa587a06fsewardj	static int
3259de4a1d01951937632098a6cda45859afa587a06fsewardj	demangle_qualified (struct work_stuff *, const char *mangled,
3260de4a1d01951937632098a6cda45859afa587a06fsewardj			    string *result, int isfuncname, int append);
3261de4a1d01951937632098a6cda45859afa587a06fsewardj
3262de4a1d01951937632098a6cda45859afa587a06fsewardjDESCRIPTION
3263de4a1d01951937632098a6cda45859afa587a06fsewardj
3264de4a1d01951937632098a6cda45859afa587a06fsewardj	Demangle a qualified name, such as "Q25Outer5Inner" which is
3265de4a1d01951937632098a6cda45859afa587a06fsewardj	the mangled form of "Outer::Inner".  The demangled output is
3266de4a1d01951937632098a6cda45859afa587a06fsewardj	prepended or appended to the result string according to the
3267de4a1d01951937632098a6cda45859afa587a06fsewardj	state of the append flag.
3268de4a1d01951937632098a6cda45859afa587a06fsewardj
3269de4a1d01951937632098a6cda45859afa587a06fsewardj	If isfuncname is nonzero, then the qualified name we are building
3270de4a1d01951937632098a6cda45859afa587a06fsewardj	is going to be used as a member function name, so if it is a
3271de4a1d01951937632098a6cda45859afa587a06fsewardj	constructor or destructor function, append an appropriate
3272de4a1d01951937632098a6cda45859afa587a06fsewardj	constructor or destructor name.  I.E. for the above example,
3273de4a1d01951937632098a6cda45859afa587a06fsewardj	the result for use as a constructor is "Outer::Inner::Inner"
3274de4a1d01951937632098a6cda45859afa587a06fsewardj	and the result for use as a destructor is "Outer::Inner::~Inner".
3275de4a1d01951937632098a6cda45859afa587a06fsewardj
3276de4a1d01951937632098a6cda45859afa587a06fsewardjBUGS
3277de4a1d01951937632098a6cda45859afa587a06fsewardj
3278de4a1d01951937632098a6cda45859afa587a06fsewardj	Numeric conversion is ASCII dependent (FIXME).
3279de4a1d01951937632098a6cda45859afa587a06fsewardj
3280de4a1d01951937632098a6cda45859afa587a06fsewardj */
3281de4a1d01951937632098a6cda45859afa587a06fsewardj
3282de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
32834f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_qualified (struct work_stuff *work, const char **mangled,
32844f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                    string *result, int isfuncname, int append)
3285de4a1d01951937632098a6cda45859afa587a06fsewardj{
3286de4a1d01951937632098a6cda45859afa587a06fsewardj  int qualifiers = 0;
3287de4a1d01951937632098a6cda45859afa587a06fsewardj  int success = 1;
32884f2683ace412ca2c8266f2dd860dee4461df3cafsewardj  char num[2];
3289de4a1d01951937632098a6cda45859afa587a06fsewardj  string temp;
3290de4a1d01951937632098a6cda45859afa587a06fsewardj  string last_name;
3291de4a1d01951937632098a6cda45859afa587a06fsewardj  int bindex = register_Btype (work);
3292de4a1d01951937632098a6cda45859afa587a06fsewardj
3293de4a1d01951937632098a6cda45859afa587a06fsewardj  /* We only make use of ISFUNCNAME if the entity is a constructor or
3294de4a1d01951937632098a6cda45859afa587a06fsewardj     destructor.  */
3295de4a1d01951937632098a6cda45859afa587a06fsewardj  isfuncname = (isfuncname
3296de4a1d01951937632098a6cda45859afa587a06fsewardj		&& ((work->constructor & 1) || (work->destructor & 1)));
3297de4a1d01951937632098a6cda45859afa587a06fsewardj
3298de4a1d01951937632098a6cda45859afa587a06fsewardj  string_init (&temp);
3299de4a1d01951937632098a6cda45859afa587a06fsewardj  string_init (&last_name);
3300de4a1d01951937632098a6cda45859afa587a06fsewardj
3301de4a1d01951937632098a6cda45859afa587a06fsewardj  if ((*mangled)[0] == 'K')
3302de4a1d01951937632098a6cda45859afa587a06fsewardj    {
3303de4a1d01951937632098a6cda45859afa587a06fsewardj    /* Squangling qualified name reuse */
3304de4a1d01951937632098a6cda45859afa587a06fsewardj      int idx;
3305de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
3306de4a1d01951937632098a6cda45859afa587a06fsewardj      idx = consume_count_with_underscores (mangled);
3307de4a1d01951937632098a6cda45859afa587a06fsewardj      if (idx == -1 || idx >= work -> numk)
3308de4a1d01951937632098a6cda45859afa587a06fsewardj        success = 0;
3309de4a1d01951937632098a6cda45859afa587a06fsewardj      else
3310de4a1d01951937632098a6cda45859afa587a06fsewardj        string_append (&temp, work -> ktypevec[idx]);
3311de4a1d01951937632098a6cda45859afa587a06fsewardj    }
3312de4a1d01951937632098a6cda45859afa587a06fsewardj  else
3313de4a1d01951937632098a6cda45859afa587a06fsewardj    switch ((*mangled)[1])
3314de4a1d01951937632098a6cda45859afa587a06fsewardj    {
3315de4a1d01951937632098a6cda45859afa587a06fsewardj    case '_':
3316de4a1d01951937632098a6cda45859afa587a06fsewardj      /* GNU mangled name with more than 9 classes.  The count is preceded
3317de4a1d01951937632098a6cda45859afa587a06fsewardj	 by an underscore (to distinguish it from the <= 9 case) and followed
3318de4a1d01951937632098a6cda45859afa587a06fsewardj	 by an underscore.  */
3319de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
3320de4a1d01951937632098a6cda45859afa587a06fsewardj      qualifiers = consume_count_with_underscores (mangled);
3321de4a1d01951937632098a6cda45859afa587a06fsewardj      if (qualifiers == -1)
3322de4a1d01951937632098a6cda45859afa587a06fsewardj	success = 0;
3323de4a1d01951937632098a6cda45859afa587a06fsewardj      break;
3324de4a1d01951937632098a6cda45859afa587a06fsewardj
3325de4a1d01951937632098a6cda45859afa587a06fsewardj    case '1':
3326de4a1d01951937632098a6cda45859afa587a06fsewardj    case '2':
3327de4a1d01951937632098a6cda45859afa587a06fsewardj    case '3':
3328de4a1d01951937632098a6cda45859afa587a06fsewardj    case '4':
3329de4a1d01951937632098a6cda45859afa587a06fsewardj    case '5':
3330de4a1d01951937632098a6cda45859afa587a06fsewardj    case '6':
3331de4a1d01951937632098a6cda45859afa587a06fsewardj    case '7':
3332de4a1d01951937632098a6cda45859afa587a06fsewardj    case '8':
3333de4a1d01951937632098a6cda45859afa587a06fsewardj    case '9':
3334de4a1d01951937632098a6cda45859afa587a06fsewardj      /* The count is in a single digit.  */
33354f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      num[0] = (*mangled)[1];
33364f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      num[1] = '\0';
33374f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      qualifiers = atoi (num);
3338de4a1d01951937632098a6cda45859afa587a06fsewardj
3339de4a1d01951937632098a6cda45859afa587a06fsewardj      /* If there is an underscore after the digit, skip it.  This is
3340de4a1d01951937632098a6cda45859afa587a06fsewardj	 said to be for ARM-qualified names, but the ARM makes no
3341de4a1d01951937632098a6cda45859afa587a06fsewardj	 mention of such an underscore.  Perhaps cfront uses one.  */
3342de4a1d01951937632098a6cda45859afa587a06fsewardj      if ((*mangled)[2] == '_')
3343de4a1d01951937632098a6cda45859afa587a06fsewardj	{
3344de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled)++;
3345de4a1d01951937632098a6cda45859afa587a06fsewardj	}
3346de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled) += 2;
3347de4a1d01951937632098a6cda45859afa587a06fsewardj      break;
3348de4a1d01951937632098a6cda45859afa587a06fsewardj
3349de4a1d01951937632098a6cda45859afa587a06fsewardj    case '0':
3350de4a1d01951937632098a6cda45859afa587a06fsewardj    default:
3351de4a1d01951937632098a6cda45859afa587a06fsewardj      success = 0;
3352de4a1d01951937632098a6cda45859afa587a06fsewardj    }
3353de4a1d01951937632098a6cda45859afa587a06fsewardj
3354de4a1d01951937632098a6cda45859afa587a06fsewardj  if (!success)
33554f2683ace412ca2c8266f2dd860dee4461df3cafsewardj    return success;
3356de4a1d01951937632098a6cda45859afa587a06fsewardj
3357de4a1d01951937632098a6cda45859afa587a06fsewardj  /* Pick off the names and collect them in the temp buffer in the order
3358de4a1d01951937632098a6cda45859afa587a06fsewardj     in which they are found, separated by '::'.  */
3359de4a1d01951937632098a6cda45859afa587a06fsewardj
3360de4a1d01951937632098a6cda45859afa587a06fsewardj  while (qualifiers-- > 0)
3361de4a1d01951937632098a6cda45859afa587a06fsewardj    {
3362de4a1d01951937632098a6cda45859afa587a06fsewardj      int remember_K = 1;
3363de4a1d01951937632098a6cda45859afa587a06fsewardj      string_clear (&last_name);
3364de4a1d01951937632098a6cda45859afa587a06fsewardj
3365de4a1d01951937632098a6cda45859afa587a06fsewardj      if (*mangled[0] == '_')
3366de4a1d01951937632098a6cda45859afa587a06fsewardj	(*mangled)++;
3367de4a1d01951937632098a6cda45859afa587a06fsewardj
3368de4a1d01951937632098a6cda45859afa587a06fsewardj      if (*mangled[0] == 't')
3369de4a1d01951937632098a6cda45859afa587a06fsewardj	{
3370de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* Here we always append to TEMP since we will want to use
3371de4a1d01951937632098a6cda45859afa587a06fsewardj	     the template name without the template parameters as a
3372de4a1d01951937632098a6cda45859afa587a06fsewardj	     constructor or destructor name.  The appropriate
3373de4a1d01951937632098a6cda45859afa587a06fsewardj	     (parameter-less) value is returned by demangle_template
3374de4a1d01951937632098a6cda45859afa587a06fsewardj	     in LAST_NAME.  We do not remember the template type here,
3375de4a1d01951937632098a6cda45859afa587a06fsewardj	     in order to match the G++ mangling algorithm.  */
3376de4a1d01951937632098a6cda45859afa587a06fsewardj	  success = demangle_template(work, mangled, &temp,
3377de4a1d01951937632098a6cda45859afa587a06fsewardj				      &last_name, 1, 0);
3378de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (!success)
3379de4a1d01951937632098a6cda45859afa587a06fsewardj	    break;
3380de4a1d01951937632098a6cda45859afa587a06fsewardj	}
3381de4a1d01951937632098a6cda45859afa587a06fsewardj      else if (*mangled[0] == 'K')
3382de4a1d01951937632098a6cda45859afa587a06fsewardj	{
3383de4a1d01951937632098a6cda45859afa587a06fsewardj          int idx;
3384de4a1d01951937632098a6cda45859afa587a06fsewardj          (*mangled)++;
3385de4a1d01951937632098a6cda45859afa587a06fsewardj          idx = consume_count_with_underscores (mangled);
3386de4a1d01951937632098a6cda45859afa587a06fsewardj          if (idx == -1 || idx >= work->numk)
3387de4a1d01951937632098a6cda45859afa587a06fsewardj            success = 0;
3388de4a1d01951937632098a6cda45859afa587a06fsewardj          else
3389de4a1d01951937632098a6cda45859afa587a06fsewardj            string_append (&temp, work->ktypevec[idx]);
3390de4a1d01951937632098a6cda45859afa587a06fsewardj          remember_K = 0;
3391de4a1d01951937632098a6cda45859afa587a06fsewardj
3392de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (!success) break;
3393de4a1d01951937632098a6cda45859afa587a06fsewardj	}
3394de4a1d01951937632098a6cda45859afa587a06fsewardj      else
3395de4a1d01951937632098a6cda45859afa587a06fsewardj	{
3396de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (EDG_DEMANGLING)
3397de4a1d01951937632098a6cda45859afa587a06fsewardj            {
3398de4a1d01951937632098a6cda45859afa587a06fsewardj	      int namelength;
3399de4a1d01951937632098a6cda45859afa587a06fsewardj 	      /* Now recursively demangle the qualifier
3400de4a1d01951937632098a6cda45859afa587a06fsewardj 	       * This is necessary to deal with templates in
3401de4a1d01951937632098a6cda45859afa587a06fsewardj 	       * mangling styles like EDG */
3402de4a1d01951937632098a6cda45859afa587a06fsewardj	      namelength = consume_count (mangled);
3403de4a1d01951937632098a6cda45859afa587a06fsewardj	      if (namelength == -1)
3404de4a1d01951937632098a6cda45859afa587a06fsewardj		{
3405de4a1d01951937632098a6cda45859afa587a06fsewardj		  success = 0;
3406de4a1d01951937632098a6cda45859afa587a06fsewardj		  break;
3407de4a1d01951937632098a6cda45859afa587a06fsewardj		}
3408de4a1d01951937632098a6cda45859afa587a06fsewardj 	      recursively_demangle(work, mangled, &temp, namelength);
3409de4a1d01951937632098a6cda45859afa587a06fsewardj            }
3410de4a1d01951937632098a6cda45859afa587a06fsewardj          else
3411de4a1d01951937632098a6cda45859afa587a06fsewardj            {
34124f2683ace412ca2c8266f2dd860dee4461df3cafsewardj              string_delete (&last_name);
34134f2683ace412ca2c8266f2dd860dee4461df3cafsewardj              success = do_type (work, mangled, &last_name);
3414de4a1d01951937632098a6cda45859afa587a06fsewardj              if (!success)
34154f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                break;
34164f2683ace412ca2c8266f2dd860dee4461df3cafsewardj              string_appends (&temp, &last_name);
3417de4a1d01951937632098a6cda45859afa587a06fsewardj            }
3418de4a1d01951937632098a6cda45859afa587a06fsewardj	}
3419de4a1d01951937632098a6cda45859afa587a06fsewardj
3420de4a1d01951937632098a6cda45859afa587a06fsewardj      if (remember_K)
3421de4a1d01951937632098a6cda45859afa587a06fsewardj	remember_Ktype (work, temp.b, LEN_STRING (&temp));
3422de4a1d01951937632098a6cda45859afa587a06fsewardj
3423de4a1d01951937632098a6cda45859afa587a06fsewardj      if (qualifiers > 0)
3424de4a1d01951937632098a6cda45859afa587a06fsewardj	string_append (&temp, SCOPE_STRING (work));
3425de4a1d01951937632098a6cda45859afa587a06fsewardj    }
3426de4a1d01951937632098a6cda45859afa587a06fsewardj
3427de4a1d01951937632098a6cda45859afa587a06fsewardj  remember_Btype (work, temp.b, LEN_STRING (&temp), bindex);
3428de4a1d01951937632098a6cda45859afa587a06fsewardj
3429de4a1d01951937632098a6cda45859afa587a06fsewardj  /* If we are using the result as a function name, we need to append
3430de4a1d01951937632098a6cda45859afa587a06fsewardj     the appropriate '::' separated constructor or destructor name.
3431de4a1d01951937632098a6cda45859afa587a06fsewardj     We do this here because this is the most convenient place, where
3432de4a1d01951937632098a6cda45859afa587a06fsewardj     we already have a pointer to the name and the length of the name.  */
3433de4a1d01951937632098a6cda45859afa587a06fsewardj
3434de4a1d01951937632098a6cda45859afa587a06fsewardj  if (isfuncname)
3435de4a1d01951937632098a6cda45859afa587a06fsewardj    {
3436de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (&temp, SCOPE_STRING (work));
3437de4a1d01951937632098a6cda45859afa587a06fsewardj      if (work -> destructor & 1)
3438de4a1d01951937632098a6cda45859afa587a06fsewardj	string_append (&temp, "~");
3439de4a1d01951937632098a6cda45859afa587a06fsewardj      string_appends (&temp, &last_name);
3440de4a1d01951937632098a6cda45859afa587a06fsewardj    }
3441de4a1d01951937632098a6cda45859afa587a06fsewardj
3442de4a1d01951937632098a6cda45859afa587a06fsewardj  /* Now either prepend the temp buffer to the result, or append it,
3443de4a1d01951937632098a6cda45859afa587a06fsewardj     depending upon the state of the append flag.  */
3444de4a1d01951937632098a6cda45859afa587a06fsewardj
3445de4a1d01951937632098a6cda45859afa587a06fsewardj  if (append)
3446de4a1d01951937632098a6cda45859afa587a06fsewardj    string_appends (result, &temp);
3447de4a1d01951937632098a6cda45859afa587a06fsewardj  else
3448de4a1d01951937632098a6cda45859afa587a06fsewardj    {
3449de4a1d01951937632098a6cda45859afa587a06fsewardj      if (!STRING_EMPTY (result))
3450de4a1d01951937632098a6cda45859afa587a06fsewardj	string_append (&temp, SCOPE_STRING (work));
3451de4a1d01951937632098a6cda45859afa587a06fsewardj      string_prepends (result, &temp);
3452de4a1d01951937632098a6cda45859afa587a06fsewardj    }
3453de4a1d01951937632098a6cda45859afa587a06fsewardj
3454de4a1d01951937632098a6cda45859afa587a06fsewardj  string_delete (&last_name);
3455de4a1d01951937632098a6cda45859afa587a06fsewardj  string_delete (&temp);
3456de4a1d01951937632098a6cda45859afa587a06fsewardj  return (success);
3457de4a1d01951937632098a6cda45859afa587a06fsewardj}
3458de4a1d01951937632098a6cda45859afa587a06fsewardj
3459de4a1d01951937632098a6cda45859afa587a06fsewardj/*
3460de4a1d01951937632098a6cda45859afa587a06fsewardj
3461de4a1d01951937632098a6cda45859afa587a06fsewardjLOCAL FUNCTION
3462de4a1d01951937632098a6cda45859afa587a06fsewardj
3463de4a1d01951937632098a6cda45859afa587a06fsewardj	get_count -- convert an ascii count to integer, consuming tokens
3464de4a1d01951937632098a6cda45859afa587a06fsewardj
3465de4a1d01951937632098a6cda45859afa587a06fsewardjSYNOPSIS
3466de4a1d01951937632098a6cda45859afa587a06fsewardj
3467de4a1d01951937632098a6cda45859afa587a06fsewardj	static int
3468de4a1d01951937632098a6cda45859afa587a06fsewardj	get_count (const char **type, int *count)
3469de4a1d01951937632098a6cda45859afa587a06fsewardj
3470de4a1d01951937632098a6cda45859afa587a06fsewardjDESCRIPTION
3471de4a1d01951937632098a6cda45859afa587a06fsewardj
3472de4a1d01951937632098a6cda45859afa587a06fsewardj	Assume that *type points at a count in a mangled name; set
3473de4a1d01951937632098a6cda45859afa587a06fsewardj	*count to its value, and set *type to the next character after
3474de4a1d01951937632098a6cda45859afa587a06fsewardj	the count.  There are some weird rules in effect here.
3475de4a1d01951937632098a6cda45859afa587a06fsewardj
3476de4a1d01951937632098a6cda45859afa587a06fsewardj	If *type does not point at a string of digits, return zero.
3477de4a1d01951937632098a6cda45859afa587a06fsewardj
3478de4a1d01951937632098a6cda45859afa587a06fsewardj	If *type points at a string of digits followed by an
3479de4a1d01951937632098a6cda45859afa587a06fsewardj	underscore, set *count to their value as an integer, advance
3480de4a1d01951937632098a6cda45859afa587a06fsewardj	*type to point *after the underscore, and return 1.
3481de4a1d01951937632098a6cda45859afa587a06fsewardj
3482de4a1d01951937632098a6cda45859afa587a06fsewardj	If *type points at a string of digits not followed by an
3483de4a1d01951937632098a6cda45859afa587a06fsewardj	underscore, consume only the first digit.  Set *count to its
3484de4a1d01951937632098a6cda45859afa587a06fsewardj	value as an integer, leave *type pointing after that digit,
3485de4a1d01951937632098a6cda45859afa587a06fsewardj	and return 1.
3486de4a1d01951937632098a6cda45859afa587a06fsewardj
3487de4a1d01951937632098a6cda45859afa587a06fsewardj        The excuse for this odd behavior: in the ARM and HP demangling
3488de4a1d01951937632098a6cda45859afa587a06fsewardj        styles, a type can be followed by a repeat count of the form
3489de4a1d01951937632098a6cda45859afa587a06fsewardj        `Nxy', where:
3490de4a1d01951937632098a6cda45859afa587a06fsewardj
3491de4a1d01951937632098a6cda45859afa587a06fsewardj        `x' is a single digit specifying how many additional copies
3492de4a1d01951937632098a6cda45859afa587a06fsewardj            of the type to append to the argument list, and
3493de4a1d01951937632098a6cda45859afa587a06fsewardj
3494de4a1d01951937632098a6cda45859afa587a06fsewardj        `y' is one or more digits, specifying the zero-based index of
3495de4a1d01951937632098a6cda45859afa587a06fsewardj            the first repeated argument in the list.  Yes, as you're
3496de4a1d01951937632098a6cda45859afa587a06fsewardj            unmangling the name you can figure this out yourself, but
3497de4a1d01951937632098a6cda45859afa587a06fsewardj            it's there anyway.
3498de4a1d01951937632098a6cda45859afa587a06fsewardj
3499de4a1d01951937632098a6cda45859afa587a06fsewardj        So, for example, in `bar__3fooFPiN51', the first argument is a
3500de4a1d01951937632098a6cda45859afa587a06fsewardj        pointer to an integer (`Pi'), and then the next five arguments
3501de4a1d01951937632098a6cda45859afa587a06fsewardj        are the same (`N5'), and the first repeat is the function's
3502de4a1d01951937632098a6cda45859afa587a06fsewardj        second argument (`1').
3503de4a1d01951937632098a6cda45859afa587a06fsewardj*/
3504de4a1d01951937632098a6cda45859afa587a06fsewardj
3505de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
35064f2683ace412ca2c8266f2dd860dee4461df3cafsewardjget_count (const char **type, int *count)
3507de4a1d01951937632098a6cda45859afa587a06fsewardj{
3508de4a1d01951937632098a6cda45859afa587a06fsewardj  const char *p;
3509de4a1d01951937632098a6cda45859afa587a06fsewardj  int n;
3510de4a1d01951937632098a6cda45859afa587a06fsewardj
3511de4a1d01951937632098a6cda45859afa587a06fsewardj  if (!ISDIGIT ((unsigned char)**type))
3512de4a1d01951937632098a6cda45859afa587a06fsewardj    return (0);
3513de4a1d01951937632098a6cda45859afa587a06fsewardj  else
3514de4a1d01951937632098a6cda45859afa587a06fsewardj    {
3515de4a1d01951937632098a6cda45859afa587a06fsewardj      *count = **type - '0';
3516de4a1d01951937632098a6cda45859afa587a06fsewardj      (*type)++;
3517de4a1d01951937632098a6cda45859afa587a06fsewardj      if (ISDIGIT ((unsigned char)**type))
3518de4a1d01951937632098a6cda45859afa587a06fsewardj	{
3519de4a1d01951937632098a6cda45859afa587a06fsewardj	  p = *type;
3520de4a1d01951937632098a6cda45859afa587a06fsewardj	  n = *count;
3521de4a1d01951937632098a6cda45859afa587a06fsewardj	  do
3522de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
3523de4a1d01951937632098a6cda45859afa587a06fsewardj	      n *= 10;
3524de4a1d01951937632098a6cda45859afa587a06fsewardj	      n += *p - '0';
3525de4a1d01951937632098a6cda45859afa587a06fsewardj	      p++;
3526de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
3527de4a1d01951937632098a6cda45859afa587a06fsewardj	  while (ISDIGIT ((unsigned char)*p));
3528de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (*p == '_')
3529de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
3530de4a1d01951937632098a6cda45859afa587a06fsewardj	      *type = p + 1;
3531de4a1d01951937632098a6cda45859afa587a06fsewardj	      *count = n;
3532de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
3533de4a1d01951937632098a6cda45859afa587a06fsewardj	}
3534de4a1d01951937632098a6cda45859afa587a06fsewardj    }
3535de4a1d01951937632098a6cda45859afa587a06fsewardj  return (1);
3536de4a1d01951937632098a6cda45859afa587a06fsewardj}
3537de4a1d01951937632098a6cda45859afa587a06fsewardj
3538de4a1d01951937632098a6cda45859afa587a06fsewardj/* RESULT will be initialised here; it will be freed on failure.  The
3539de4a1d01951937632098a6cda45859afa587a06fsewardj   value returned is really a type_kind_t.  */
3540de4a1d01951937632098a6cda45859afa587a06fsewardj
3541de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
35424f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdo_type (struct work_stuff *work, const char **mangled, string *result)
3543de4a1d01951937632098a6cda45859afa587a06fsewardj{
3544de4a1d01951937632098a6cda45859afa587a06fsewardj  int n;
3545de4a1d01951937632098a6cda45859afa587a06fsewardj  int done;
3546de4a1d01951937632098a6cda45859afa587a06fsewardj  int success;
3547de4a1d01951937632098a6cda45859afa587a06fsewardj  string decl;
3548de4a1d01951937632098a6cda45859afa587a06fsewardj  const char *remembered_type;
3549de4a1d01951937632098a6cda45859afa587a06fsewardj  int type_quals;
3550de4a1d01951937632098a6cda45859afa587a06fsewardj  type_kind_t tk = tk_none;
3551de4a1d01951937632098a6cda45859afa587a06fsewardj
3552de4a1d01951937632098a6cda45859afa587a06fsewardj  string_init (&decl);
3553de4a1d01951937632098a6cda45859afa587a06fsewardj  string_init (result);
3554de4a1d01951937632098a6cda45859afa587a06fsewardj
3555de4a1d01951937632098a6cda45859afa587a06fsewardj  done = 0;
3556de4a1d01951937632098a6cda45859afa587a06fsewardj  success = 1;
3557de4a1d01951937632098a6cda45859afa587a06fsewardj  while (success && !done)
3558de4a1d01951937632098a6cda45859afa587a06fsewardj    {
3559de4a1d01951937632098a6cda45859afa587a06fsewardj      int member;
3560de4a1d01951937632098a6cda45859afa587a06fsewardj      switch (**mangled)
3561de4a1d01951937632098a6cda45859afa587a06fsewardj	{
3562de4a1d01951937632098a6cda45859afa587a06fsewardj
3563de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* A pointer type */
3564de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'P':
3565de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'p':
3566de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled)++;
3567de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (! (work -> options & DMGL_JAVA))
3568de4a1d01951937632098a6cda45859afa587a06fsewardj	    string_prepend (&decl, "*");
3569de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (tk == tk_none)
3570de4a1d01951937632098a6cda45859afa587a06fsewardj	    tk = tk_pointer;
3571de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
3572de4a1d01951937632098a6cda45859afa587a06fsewardj
3573de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* A reference type */
3574de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'R':
3575de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled)++;
3576de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_prepend (&decl, "&");
3577de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (tk == tk_none)
3578de4a1d01951937632098a6cda45859afa587a06fsewardj	    tk = tk_reference;
3579de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
3580de4a1d01951937632098a6cda45859afa587a06fsewardj
3581de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* An array */
3582de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'A':
3583de4a1d01951937632098a6cda45859afa587a06fsewardj	  {
3584de4a1d01951937632098a6cda45859afa587a06fsewardj	    ++(*mangled);
3585de4a1d01951937632098a6cda45859afa587a06fsewardj	    if (!STRING_EMPTY (&decl)
3586de4a1d01951937632098a6cda45859afa587a06fsewardj		&& (decl.b[0] == '*' || decl.b[0] == '&'))
3587de4a1d01951937632098a6cda45859afa587a06fsewardj	      {
3588de4a1d01951937632098a6cda45859afa587a06fsewardj		string_prepend (&decl, "(");
3589de4a1d01951937632098a6cda45859afa587a06fsewardj		string_append (&decl, ")");
3590de4a1d01951937632098a6cda45859afa587a06fsewardj	      }
3591de4a1d01951937632098a6cda45859afa587a06fsewardj	    string_append (&decl, "[");
3592de4a1d01951937632098a6cda45859afa587a06fsewardj	    if (**mangled != '_')
3593de4a1d01951937632098a6cda45859afa587a06fsewardj	      success = demangle_template_value_parm (work, mangled, &decl,
3594de4a1d01951937632098a6cda45859afa587a06fsewardj						      tk_integral);
3595de4a1d01951937632098a6cda45859afa587a06fsewardj	    if (**mangled == '_')
3596de4a1d01951937632098a6cda45859afa587a06fsewardj	      ++(*mangled);
3597de4a1d01951937632098a6cda45859afa587a06fsewardj	    string_append (&decl, "]");
3598de4a1d01951937632098a6cda45859afa587a06fsewardj	    break;
3599de4a1d01951937632098a6cda45859afa587a06fsewardj	  }
3600de4a1d01951937632098a6cda45859afa587a06fsewardj
3601de4a1d01951937632098a6cda45859afa587a06fsewardj	/* A back reference to a previously seen type */
3602de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'T':
3603de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled)++;
3604de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (!get_count (mangled, &n) || n >= work -> ntypes)
3605de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
3606de4a1d01951937632098a6cda45859afa587a06fsewardj	      success = 0;
3607de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
3608de4a1d01951937632098a6cda45859afa587a06fsewardj	  else
3609de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
3610de4a1d01951937632098a6cda45859afa587a06fsewardj	      remembered_type = work -> typevec[n];
3611de4a1d01951937632098a6cda45859afa587a06fsewardj	      mangled = &remembered_type;
3612de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
3613de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
3614de4a1d01951937632098a6cda45859afa587a06fsewardj
3615de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* A function */
3616de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'F':
3617de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled)++;
3618de4a1d01951937632098a6cda45859afa587a06fsewardj	    if (!STRING_EMPTY (&decl)
3619de4a1d01951937632098a6cda45859afa587a06fsewardj		&& (decl.b[0] == '*' || decl.b[0] == '&'))
3620de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
3621de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_prepend (&decl, "(");
3622de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_append (&decl, ")");
3623de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
3624de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* After picking off the function args, we expect to either find the
3625de4a1d01951937632098a6cda45859afa587a06fsewardj	     function return type (preceded by an '_') or the end of the
3626de4a1d01951937632098a6cda45859afa587a06fsewardj	     string.  */
3627de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (!demangle_nested_args (work, mangled, &decl)
3628de4a1d01951937632098a6cda45859afa587a06fsewardj	      || (**mangled != '_' && **mangled != '\0'))
3629de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
3630de4a1d01951937632098a6cda45859afa587a06fsewardj	      success = 0;
3631de4a1d01951937632098a6cda45859afa587a06fsewardj	      break;
3632de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
3633de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (success && (**mangled == '_'))
3634de4a1d01951937632098a6cda45859afa587a06fsewardj	    (*mangled)++;
3635de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
3636de4a1d01951937632098a6cda45859afa587a06fsewardj
3637de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'M':
3638de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'O':
3639de4a1d01951937632098a6cda45859afa587a06fsewardj	  {
3640de4a1d01951937632098a6cda45859afa587a06fsewardj	    type_quals = TYPE_UNQUALIFIED;
3641de4a1d01951937632098a6cda45859afa587a06fsewardj
3642de4a1d01951937632098a6cda45859afa587a06fsewardj	    member = **mangled == 'M';
3643de4a1d01951937632098a6cda45859afa587a06fsewardj	    (*mangled)++;
3644de4a1d01951937632098a6cda45859afa587a06fsewardj
3645de4a1d01951937632098a6cda45859afa587a06fsewardj	    string_append (&decl, ")");
3646de4a1d01951937632098a6cda45859afa587a06fsewardj
3647de4a1d01951937632098a6cda45859afa587a06fsewardj	    /* We don't need to prepend `::' for a qualified name;
3648de4a1d01951937632098a6cda45859afa587a06fsewardj	       demangle_qualified will do that for us.  */
3649de4a1d01951937632098a6cda45859afa587a06fsewardj	    if (**mangled != 'Q')
3650de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_prepend (&decl, SCOPE_STRING (work));
3651de4a1d01951937632098a6cda45859afa587a06fsewardj
3652de4a1d01951937632098a6cda45859afa587a06fsewardj	    if (ISDIGIT ((unsigned char)**mangled))
3653de4a1d01951937632098a6cda45859afa587a06fsewardj	      {
3654de4a1d01951937632098a6cda45859afa587a06fsewardj		n = consume_count (mangled);
3655de4a1d01951937632098a6cda45859afa587a06fsewardj		if (n == -1
3656de4a1d01951937632098a6cda45859afa587a06fsewardj		    || (int) strlen (*mangled) < n)
3657de4a1d01951937632098a6cda45859afa587a06fsewardj		  {
3658de4a1d01951937632098a6cda45859afa587a06fsewardj		    success = 0;
3659de4a1d01951937632098a6cda45859afa587a06fsewardj		    break;
3660de4a1d01951937632098a6cda45859afa587a06fsewardj		  }
3661de4a1d01951937632098a6cda45859afa587a06fsewardj		string_prependn (&decl, *mangled, n);
3662de4a1d01951937632098a6cda45859afa587a06fsewardj		*mangled += n;
3663de4a1d01951937632098a6cda45859afa587a06fsewardj	      }
3664de4a1d01951937632098a6cda45859afa587a06fsewardj	    else if (**mangled == 'X' || **mangled == 'Y')
3665de4a1d01951937632098a6cda45859afa587a06fsewardj	      {
3666de4a1d01951937632098a6cda45859afa587a06fsewardj		string temp;
3667de4a1d01951937632098a6cda45859afa587a06fsewardj		do_type (work, mangled, &temp);
3668de4a1d01951937632098a6cda45859afa587a06fsewardj		string_prepends (&decl, &temp);
36694f2683ace412ca2c8266f2dd860dee4461df3cafsewardj		string_delete (&temp);
3670de4a1d01951937632098a6cda45859afa587a06fsewardj	      }
3671de4a1d01951937632098a6cda45859afa587a06fsewardj	    else if (**mangled == 't')
3672de4a1d01951937632098a6cda45859afa587a06fsewardj	      {
3673de4a1d01951937632098a6cda45859afa587a06fsewardj		string temp;
3674de4a1d01951937632098a6cda45859afa587a06fsewardj		string_init (&temp);
3675de4a1d01951937632098a6cda45859afa587a06fsewardj		success = demangle_template (work, mangled, &temp,
3676de4a1d01951937632098a6cda45859afa587a06fsewardj					     NULL, 1, 1);
3677de4a1d01951937632098a6cda45859afa587a06fsewardj		if (success)
3678de4a1d01951937632098a6cda45859afa587a06fsewardj		  {
3679de4a1d01951937632098a6cda45859afa587a06fsewardj		    string_prependn (&decl, temp.b, temp.p - temp.b);
36804f2683ace412ca2c8266f2dd860dee4461df3cafsewardj		    string_delete (&temp);
3681de4a1d01951937632098a6cda45859afa587a06fsewardj		  }
3682de4a1d01951937632098a6cda45859afa587a06fsewardj		else
3683c9d7582cbe368687ea03acd7a33ca9cb96b7678fflorian		  {
3684c9d7582cbe368687ea03acd7a33ca9cb96b7678fflorian		    string_delete (&temp);
3685c9d7582cbe368687ea03acd7a33ca9cb96b7678fflorian		    break;
3686c9d7582cbe368687ea03acd7a33ca9cb96b7678fflorian		  }
3687de4a1d01951937632098a6cda45859afa587a06fsewardj	      }
3688de4a1d01951937632098a6cda45859afa587a06fsewardj	    else if (**mangled == 'Q')
3689de4a1d01951937632098a6cda45859afa587a06fsewardj	      {
3690de4a1d01951937632098a6cda45859afa587a06fsewardj		success = demangle_qualified (work, mangled, &decl,
3691de4a1d01951937632098a6cda45859afa587a06fsewardj					      /*isfuncnam=*/0,
3692de4a1d01951937632098a6cda45859afa587a06fsewardj					      /*append=*/0);
3693de4a1d01951937632098a6cda45859afa587a06fsewardj		if (!success)
3694de4a1d01951937632098a6cda45859afa587a06fsewardj		  break;
3695de4a1d01951937632098a6cda45859afa587a06fsewardj	      }
3696de4a1d01951937632098a6cda45859afa587a06fsewardj	    else
3697de4a1d01951937632098a6cda45859afa587a06fsewardj	      {
3698de4a1d01951937632098a6cda45859afa587a06fsewardj		success = 0;
3699de4a1d01951937632098a6cda45859afa587a06fsewardj		break;
3700de4a1d01951937632098a6cda45859afa587a06fsewardj	      }
3701de4a1d01951937632098a6cda45859afa587a06fsewardj
3702de4a1d01951937632098a6cda45859afa587a06fsewardj	    string_prepend (&decl, "(");
3703de4a1d01951937632098a6cda45859afa587a06fsewardj	    if (member)
3704de4a1d01951937632098a6cda45859afa587a06fsewardj	      {
3705de4a1d01951937632098a6cda45859afa587a06fsewardj		switch (**mangled)
3706de4a1d01951937632098a6cda45859afa587a06fsewardj		  {
3707de4a1d01951937632098a6cda45859afa587a06fsewardj		  case 'C':
3708de4a1d01951937632098a6cda45859afa587a06fsewardj		  case 'V':
3709de4a1d01951937632098a6cda45859afa587a06fsewardj		  case 'u':
3710de4a1d01951937632098a6cda45859afa587a06fsewardj		    type_quals |= code_for_qualifier (**mangled);
3711de4a1d01951937632098a6cda45859afa587a06fsewardj		    (*mangled)++;
3712de4a1d01951937632098a6cda45859afa587a06fsewardj		    break;
3713de4a1d01951937632098a6cda45859afa587a06fsewardj
3714de4a1d01951937632098a6cda45859afa587a06fsewardj		  default:
3715de4a1d01951937632098a6cda45859afa587a06fsewardj		    break;
3716de4a1d01951937632098a6cda45859afa587a06fsewardj		  }
3717de4a1d01951937632098a6cda45859afa587a06fsewardj
3718de4a1d01951937632098a6cda45859afa587a06fsewardj		if (*(*mangled)++ != 'F')
3719de4a1d01951937632098a6cda45859afa587a06fsewardj		  {
3720de4a1d01951937632098a6cda45859afa587a06fsewardj		    success = 0;
3721de4a1d01951937632098a6cda45859afa587a06fsewardj		    break;
3722de4a1d01951937632098a6cda45859afa587a06fsewardj		  }
3723de4a1d01951937632098a6cda45859afa587a06fsewardj	      }
3724de4a1d01951937632098a6cda45859afa587a06fsewardj	    if ((member && !demangle_nested_args (work, mangled, &decl))
3725de4a1d01951937632098a6cda45859afa587a06fsewardj		|| **mangled != '_')
3726de4a1d01951937632098a6cda45859afa587a06fsewardj	      {
3727de4a1d01951937632098a6cda45859afa587a06fsewardj		success = 0;
3728de4a1d01951937632098a6cda45859afa587a06fsewardj		break;
3729de4a1d01951937632098a6cda45859afa587a06fsewardj	      }
3730de4a1d01951937632098a6cda45859afa587a06fsewardj	    (*mangled)++;
3731de4a1d01951937632098a6cda45859afa587a06fsewardj	    if (! PRINT_ANSI_QUALIFIERS)
3732de4a1d01951937632098a6cda45859afa587a06fsewardj	      {
3733de4a1d01951937632098a6cda45859afa587a06fsewardj		break;
3734de4a1d01951937632098a6cda45859afa587a06fsewardj	      }
3735de4a1d01951937632098a6cda45859afa587a06fsewardj	    if (type_quals != TYPE_UNQUALIFIED)
3736de4a1d01951937632098a6cda45859afa587a06fsewardj	      {
3737de4a1d01951937632098a6cda45859afa587a06fsewardj		APPEND_BLANK (&decl);
3738de4a1d01951937632098a6cda45859afa587a06fsewardj		string_append (&decl, qualifier_string (type_quals));
3739de4a1d01951937632098a6cda45859afa587a06fsewardj	      }
3740de4a1d01951937632098a6cda45859afa587a06fsewardj	    break;
3741de4a1d01951937632098a6cda45859afa587a06fsewardj	  }
3742de4a1d01951937632098a6cda45859afa587a06fsewardj        case 'G':
3743de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled)++;
3744de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
3745de4a1d01951937632098a6cda45859afa587a06fsewardj
3746de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'C':
3747de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'V':
3748de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'u':
3749de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (PRINT_ANSI_QUALIFIERS)
3750de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
3751de4a1d01951937632098a6cda45859afa587a06fsewardj	      if (!STRING_EMPTY (&decl))
3752de4a1d01951937632098a6cda45859afa587a06fsewardj		string_prepend (&decl, " ");
3753de4a1d01951937632098a6cda45859afa587a06fsewardj
3754de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_prepend (&decl, demangle_qualifier (**mangled));
3755de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
3756de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled)++;
3757de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
3758de4a1d01951937632098a6cda45859afa587a06fsewardj	  /*
3759de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
3760de4a1d01951937632098a6cda45859afa587a06fsewardj	    */
3761de4a1d01951937632098a6cda45859afa587a06fsewardj
3762de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* fall through */
3763de4a1d01951937632098a6cda45859afa587a06fsewardj	default:
3764de4a1d01951937632098a6cda45859afa587a06fsewardj	  done = 1;
3765de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
3766de4a1d01951937632098a6cda45859afa587a06fsewardj	}
3767de4a1d01951937632098a6cda45859afa587a06fsewardj    }
3768de4a1d01951937632098a6cda45859afa587a06fsewardj
3769de4a1d01951937632098a6cda45859afa587a06fsewardj  if (success) switch (**mangled)
3770de4a1d01951937632098a6cda45859afa587a06fsewardj    {
3771de4a1d01951937632098a6cda45859afa587a06fsewardj      /* A qualified name, such as "Outer::Inner".  */
3772de4a1d01951937632098a6cda45859afa587a06fsewardj    case 'Q':
3773de4a1d01951937632098a6cda45859afa587a06fsewardj    case 'K':
3774de4a1d01951937632098a6cda45859afa587a06fsewardj      {
3775de4a1d01951937632098a6cda45859afa587a06fsewardj        success = demangle_qualified (work, mangled, result, 0, 1);
3776de4a1d01951937632098a6cda45859afa587a06fsewardj        break;
3777de4a1d01951937632098a6cda45859afa587a06fsewardj      }
3778de4a1d01951937632098a6cda45859afa587a06fsewardj
3779de4a1d01951937632098a6cda45859afa587a06fsewardj    /* A back reference to a previously seen squangled type */
3780de4a1d01951937632098a6cda45859afa587a06fsewardj    case 'B':
3781de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
3782de4a1d01951937632098a6cda45859afa587a06fsewardj      if (!get_count (mangled, &n) || n >= work -> numb)
3783de4a1d01951937632098a6cda45859afa587a06fsewardj	success = 0;
3784de4a1d01951937632098a6cda45859afa587a06fsewardj      else
3785de4a1d01951937632098a6cda45859afa587a06fsewardj	string_append (result, work->btypevec[n]);
3786de4a1d01951937632098a6cda45859afa587a06fsewardj      break;
3787de4a1d01951937632098a6cda45859afa587a06fsewardj
3788de4a1d01951937632098a6cda45859afa587a06fsewardj    case 'X':
3789de4a1d01951937632098a6cda45859afa587a06fsewardj    case 'Y':
3790de4a1d01951937632098a6cda45859afa587a06fsewardj      /* A template parm.  We substitute the corresponding argument. */
3791de4a1d01951937632098a6cda45859afa587a06fsewardj      {
3792de4a1d01951937632098a6cda45859afa587a06fsewardj	int idx;
3793de4a1d01951937632098a6cda45859afa587a06fsewardj
3794de4a1d01951937632098a6cda45859afa587a06fsewardj	(*mangled)++;
3795de4a1d01951937632098a6cda45859afa587a06fsewardj	idx = consume_count_with_underscores (mangled);
3796de4a1d01951937632098a6cda45859afa587a06fsewardj
3797de4a1d01951937632098a6cda45859afa587a06fsewardj	if (idx == -1
3798de4a1d01951937632098a6cda45859afa587a06fsewardj	    || (work->tmpl_argvec && idx >= work->ntmpl_args)
3799de4a1d01951937632098a6cda45859afa587a06fsewardj	    || consume_count_with_underscores (mangled) == -1)
3800de4a1d01951937632098a6cda45859afa587a06fsewardj	  {
3801de4a1d01951937632098a6cda45859afa587a06fsewardj	    success = 0;
3802de4a1d01951937632098a6cda45859afa587a06fsewardj	    break;
3803de4a1d01951937632098a6cda45859afa587a06fsewardj	  }
3804de4a1d01951937632098a6cda45859afa587a06fsewardj
3805de4a1d01951937632098a6cda45859afa587a06fsewardj	if (work->tmpl_argvec)
3806de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_append (result, work->tmpl_argvec[idx]);
3807de4a1d01951937632098a6cda45859afa587a06fsewardj	else
3808de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_append_template_idx (result, idx);
3809de4a1d01951937632098a6cda45859afa587a06fsewardj
3810de4a1d01951937632098a6cda45859afa587a06fsewardj	success = 1;
3811de4a1d01951937632098a6cda45859afa587a06fsewardj      }
3812de4a1d01951937632098a6cda45859afa587a06fsewardj    break;
3813de4a1d01951937632098a6cda45859afa587a06fsewardj
3814de4a1d01951937632098a6cda45859afa587a06fsewardj    default:
3815de4a1d01951937632098a6cda45859afa587a06fsewardj      success = demangle_fund_type (work, mangled, result);
3816de4a1d01951937632098a6cda45859afa587a06fsewardj      if (tk == tk_none)
3817de4a1d01951937632098a6cda45859afa587a06fsewardj	tk = (type_kind_t) success;
3818de4a1d01951937632098a6cda45859afa587a06fsewardj      break;
3819de4a1d01951937632098a6cda45859afa587a06fsewardj    }
3820de4a1d01951937632098a6cda45859afa587a06fsewardj
3821de4a1d01951937632098a6cda45859afa587a06fsewardj  if (success)
3822de4a1d01951937632098a6cda45859afa587a06fsewardj    {
3823de4a1d01951937632098a6cda45859afa587a06fsewardj      if (!STRING_EMPTY (&decl))
3824de4a1d01951937632098a6cda45859afa587a06fsewardj	{
3825de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_append (result, " ");
3826de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_appends (result, &decl);
3827de4a1d01951937632098a6cda45859afa587a06fsewardj	}
3828de4a1d01951937632098a6cda45859afa587a06fsewardj    }
3829de4a1d01951937632098a6cda45859afa587a06fsewardj  else
3830de4a1d01951937632098a6cda45859afa587a06fsewardj    string_delete (result);
3831de4a1d01951937632098a6cda45859afa587a06fsewardj  string_delete (&decl);
3832de4a1d01951937632098a6cda45859afa587a06fsewardj
3833de4a1d01951937632098a6cda45859afa587a06fsewardj  if (success)
3834de4a1d01951937632098a6cda45859afa587a06fsewardj    /* Assume an integral type, if we're not sure.  */
3835de4a1d01951937632098a6cda45859afa587a06fsewardj    return (int) ((tk == tk_none) ? tk_integral : tk);
3836de4a1d01951937632098a6cda45859afa587a06fsewardj  else
3837de4a1d01951937632098a6cda45859afa587a06fsewardj    return 0;
3838de4a1d01951937632098a6cda45859afa587a06fsewardj}
3839de4a1d01951937632098a6cda45859afa587a06fsewardj
3840de4a1d01951937632098a6cda45859afa587a06fsewardj/* Given a pointer to a type string that represents a fundamental type
3841de4a1d01951937632098a6cda45859afa587a06fsewardj   argument (int, long, unsigned int, etc) in TYPE, a pointer to the
3842de4a1d01951937632098a6cda45859afa587a06fsewardj   string in which the demangled output is being built in RESULT, and
3843de4a1d01951937632098a6cda45859afa587a06fsewardj   the WORK structure, decode the types and add them to the result.
3844de4a1d01951937632098a6cda45859afa587a06fsewardj
3845de4a1d01951937632098a6cda45859afa587a06fsewardj   For example:
3846de4a1d01951937632098a6cda45859afa587a06fsewardj
3847de4a1d01951937632098a6cda45859afa587a06fsewardj   	"Ci"	=>	"const int"
3848de4a1d01951937632098a6cda45859afa587a06fsewardj	"Sl"	=>	"signed long"
3849de4a1d01951937632098a6cda45859afa587a06fsewardj	"CUs"	=>	"const unsigned short"
3850de4a1d01951937632098a6cda45859afa587a06fsewardj
3851de4a1d01951937632098a6cda45859afa587a06fsewardj   The value returned is really a type_kind_t.  */
3852de4a1d01951937632098a6cda45859afa587a06fsewardj
3853de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
38544f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_fund_type (struct work_stuff *work,
38554f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                    const char **mangled, string *result)
3856de4a1d01951937632098a6cda45859afa587a06fsewardj{
3857de4a1d01951937632098a6cda45859afa587a06fsewardj  int done = 0;
3858de4a1d01951937632098a6cda45859afa587a06fsewardj  int success = 1;
38594f2683ace412ca2c8266f2dd860dee4461df3cafsewardj  char buf[INTBUF_SIZE + 5 /* 'int%u_t' */];
38604f2683ace412ca2c8266f2dd860dee4461df3cafsewardj  /* unsigned int dec = 0; */ /* JRS 2008-Oct-26: unused (see below) */
3861de4a1d01951937632098a6cda45859afa587a06fsewardj  type_kind_t tk = tk_integral;
3862de4a1d01951937632098a6cda45859afa587a06fsewardj
3863de4a1d01951937632098a6cda45859afa587a06fsewardj  /* First pick off any type qualifiers.  There can be more than one.  */
3864de4a1d01951937632098a6cda45859afa587a06fsewardj
3865de4a1d01951937632098a6cda45859afa587a06fsewardj  while (!done)
3866de4a1d01951937632098a6cda45859afa587a06fsewardj    {
3867de4a1d01951937632098a6cda45859afa587a06fsewardj      switch (**mangled)
3868de4a1d01951937632098a6cda45859afa587a06fsewardj	{
3869de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'C':
3870de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'V':
3871de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'u':
3872de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (PRINT_ANSI_QUALIFIERS)
3873de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
3874de4a1d01951937632098a6cda45859afa587a06fsewardj              if (!STRING_EMPTY (result))
3875de4a1d01951937632098a6cda45859afa587a06fsewardj                string_prepend (result, " ");
3876de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_prepend (result, demangle_qualifier (**mangled));
3877de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
3878de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled)++;
3879de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
3880de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'U':
3881de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled)++;
3882de4a1d01951937632098a6cda45859afa587a06fsewardj	  APPEND_BLANK (result);
3883de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_append (result, "unsigned");
3884de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
3885de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'S': /* signed char only */
3886de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled)++;
3887de4a1d01951937632098a6cda45859afa587a06fsewardj	  APPEND_BLANK (result);
3888de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_append (result, "signed");
3889de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
3890de4a1d01951937632098a6cda45859afa587a06fsewardj	case 'J':
3891de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled)++;
3892de4a1d01951937632098a6cda45859afa587a06fsewardj	  APPEND_BLANK (result);
3893de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_append (result, "__complex");
3894de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
3895de4a1d01951937632098a6cda45859afa587a06fsewardj	default:
3896de4a1d01951937632098a6cda45859afa587a06fsewardj	  done = 1;
3897de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
3898de4a1d01951937632098a6cda45859afa587a06fsewardj	}
3899de4a1d01951937632098a6cda45859afa587a06fsewardj    }
3900de4a1d01951937632098a6cda45859afa587a06fsewardj
3901de4a1d01951937632098a6cda45859afa587a06fsewardj  /* Now pick off the fundamental type.  There can be only one.  */
3902de4a1d01951937632098a6cda45859afa587a06fsewardj
3903de4a1d01951937632098a6cda45859afa587a06fsewardj  switch (**mangled)
3904de4a1d01951937632098a6cda45859afa587a06fsewardj    {
3905de4a1d01951937632098a6cda45859afa587a06fsewardj    case '\0':
3906de4a1d01951937632098a6cda45859afa587a06fsewardj    case '_':
3907de4a1d01951937632098a6cda45859afa587a06fsewardj      break;
3908de4a1d01951937632098a6cda45859afa587a06fsewardj    case 'v':
3909de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
3910de4a1d01951937632098a6cda45859afa587a06fsewardj      APPEND_BLANK (result);
3911de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (result, "void");
3912de4a1d01951937632098a6cda45859afa587a06fsewardj      break;
3913de4a1d01951937632098a6cda45859afa587a06fsewardj    case 'x':
3914de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
3915de4a1d01951937632098a6cda45859afa587a06fsewardj      APPEND_BLANK (result);
3916de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (result, "long long");
3917de4a1d01951937632098a6cda45859afa587a06fsewardj      break;
3918de4a1d01951937632098a6cda45859afa587a06fsewardj    case 'l':
3919de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
3920de4a1d01951937632098a6cda45859afa587a06fsewardj      APPEND_BLANK (result);
3921de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (result, "long");
3922de4a1d01951937632098a6cda45859afa587a06fsewardj      break;
3923de4a1d01951937632098a6cda45859afa587a06fsewardj    case 'i':
3924de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
3925de4a1d01951937632098a6cda45859afa587a06fsewardj      APPEND_BLANK (result);
3926de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (result, "int");
3927de4a1d01951937632098a6cda45859afa587a06fsewardj      break;
3928de4a1d01951937632098a6cda45859afa587a06fsewardj    case 's':
3929de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
3930de4a1d01951937632098a6cda45859afa587a06fsewardj      APPEND_BLANK (result);
3931de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (result, "short");
3932de4a1d01951937632098a6cda45859afa587a06fsewardj      break;
3933de4a1d01951937632098a6cda45859afa587a06fsewardj    case 'b':
3934de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
3935de4a1d01951937632098a6cda45859afa587a06fsewardj      APPEND_BLANK (result);
3936de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (result, "bool");
3937de4a1d01951937632098a6cda45859afa587a06fsewardj      tk = tk_bool;
3938de4a1d01951937632098a6cda45859afa587a06fsewardj      break;
3939de4a1d01951937632098a6cda45859afa587a06fsewardj    case 'c':
3940de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
3941de4a1d01951937632098a6cda45859afa587a06fsewardj      APPEND_BLANK (result);
3942de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (result, "char");
3943de4a1d01951937632098a6cda45859afa587a06fsewardj      tk = tk_char;
3944de4a1d01951937632098a6cda45859afa587a06fsewardj      break;
3945de4a1d01951937632098a6cda45859afa587a06fsewardj    case 'w':
3946de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
3947de4a1d01951937632098a6cda45859afa587a06fsewardj      APPEND_BLANK (result);
3948de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (result, "wchar_t");
3949de4a1d01951937632098a6cda45859afa587a06fsewardj      tk = tk_char;
3950de4a1d01951937632098a6cda45859afa587a06fsewardj      break;
3951de4a1d01951937632098a6cda45859afa587a06fsewardj    case 'r':
3952de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
3953de4a1d01951937632098a6cda45859afa587a06fsewardj      APPEND_BLANK (result);
3954de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (result, "long double");
3955de4a1d01951937632098a6cda45859afa587a06fsewardj      tk = tk_real;
3956de4a1d01951937632098a6cda45859afa587a06fsewardj      break;
3957de4a1d01951937632098a6cda45859afa587a06fsewardj    case 'd':
3958de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
3959de4a1d01951937632098a6cda45859afa587a06fsewardj      APPEND_BLANK (result);
3960de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (result, "double");
3961de4a1d01951937632098a6cda45859afa587a06fsewardj      tk = tk_real;
3962de4a1d01951937632098a6cda45859afa587a06fsewardj      break;
3963de4a1d01951937632098a6cda45859afa587a06fsewardj    case 'f':
3964de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
3965de4a1d01951937632098a6cda45859afa587a06fsewardj      APPEND_BLANK (result);
3966de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (result, "float");
3967de4a1d01951937632098a6cda45859afa587a06fsewardj      tk = tk_real;
3968de4a1d01951937632098a6cda45859afa587a06fsewardj      break;
3969de4a1d01951937632098a6cda45859afa587a06fsewardj    case 'G':
3970de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
3971de4a1d01951937632098a6cda45859afa587a06fsewardj      if (!ISDIGIT ((unsigned char)**mangled))
3972de4a1d01951937632098a6cda45859afa587a06fsewardj	{
3973de4a1d01951937632098a6cda45859afa587a06fsewardj	  success = 0;
3974de4a1d01951937632098a6cda45859afa587a06fsewardj	  break;
3975de4a1d01951937632098a6cda45859afa587a06fsewardj	}
3976de4a1d01951937632098a6cda45859afa587a06fsewardj    case 'I':
3977de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
3978de4a1d01951937632098a6cda45859afa587a06fsewardj      if (**mangled == '_')
3979de4a1d01951937632098a6cda45859afa587a06fsewardj	{
3980de4a1d01951937632098a6cda45859afa587a06fsewardj	  int i;
3981de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled)++;
3982de4a1d01951937632098a6cda45859afa587a06fsewardj	  for (i = 0;
3983de4a1d01951937632098a6cda45859afa587a06fsewardj	       i < (long) sizeof (buf) - 1 && **mangled && **mangled != '_';
3984de4a1d01951937632098a6cda45859afa587a06fsewardj	       (*mangled)++, i++)
3985de4a1d01951937632098a6cda45859afa587a06fsewardj	    buf[i] = **mangled;
3986de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (**mangled != '_')
3987de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
3988de4a1d01951937632098a6cda45859afa587a06fsewardj	      success = 0;
3989de4a1d01951937632098a6cda45859afa587a06fsewardj	      break;
3990de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
3991de4a1d01951937632098a6cda45859afa587a06fsewardj	  buf[i] = '\0';
3992de4a1d01951937632098a6cda45859afa587a06fsewardj	  (*mangled)++;
3993de4a1d01951937632098a6cda45859afa587a06fsewardj	}
3994de4a1d01951937632098a6cda45859afa587a06fsewardj      else
3995de4a1d01951937632098a6cda45859afa587a06fsewardj	{
3996de4a1d01951937632098a6cda45859afa587a06fsewardj	  strncpy (buf, *mangled, 2);
3997de4a1d01951937632098a6cda45859afa587a06fsewardj	  buf[2] = '\0';
3998de4a1d01951937632098a6cda45859afa587a06fsewardj	  *mangled += min (strlen (*mangled), 2);
3999de4a1d01951937632098a6cda45859afa587a06fsewardj	}
40004f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      /* JRS 2008-Oct-26: the next two commented out lines have been
40014f2683ace412ca2c8266f2dd860dee4461df3cafsewardj         replaced by the sprintf that follows.  This is to avoid use
40024f2683ace412ca2c8266f2dd860dee4461df3cafsewardj         of sscanf.  This hack is merely copied from the old demangler
40034f2683ace412ca2c8266f2dd860dee4461df3cafsewardj         port (by Michael Matz, Simon Hausmann?) -- I have no idea if
40044f2683ace412ca2c8266f2dd860dee4461df3cafsewardj         it is really correct/safe, but it looks ok. */
4005de4a1d01951937632098a6cda45859afa587a06fsewardj      /*sscanf (buf, "%x", &dec);
4006de4a1d01951937632098a6cda45859afa587a06fsewardj      sprintf (buf, "int%u_t", dec);*/
40074f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      sprintf (buf, "%s", "intXX_t");
40084f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      /* end JRS 2008-Oct-26 */
4009de4a1d01951937632098a6cda45859afa587a06fsewardj      APPEND_BLANK (result);
4010de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (result, buf);
4011de4a1d01951937632098a6cda45859afa587a06fsewardj      break;
4012de4a1d01951937632098a6cda45859afa587a06fsewardj
4013de4a1d01951937632098a6cda45859afa587a06fsewardj      /* fall through */
4014de4a1d01951937632098a6cda45859afa587a06fsewardj      /* An explicit type, such as "6mytype" or "7integer" */
4015de4a1d01951937632098a6cda45859afa587a06fsewardj    case '0':
4016de4a1d01951937632098a6cda45859afa587a06fsewardj    case '1':
4017de4a1d01951937632098a6cda45859afa587a06fsewardj    case '2':
4018de4a1d01951937632098a6cda45859afa587a06fsewardj    case '3':
4019de4a1d01951937632098a6cda45859afa587a06fsewardj    case '4':
4020de4a1d01951937632098a6cda45859afa587a06fsewardj    case '5':
4021de4a1d01951937632098a6cda45859afa587a06fsewardj    case '6':
4022de4a1d01951937632098a6cda45859afa587a06fsewardj    case '7':
4023de4a1d01951937632098a6cda45859afa587a06fsewardj    case '8':
4024de4a1d01951937632098a6cda45859afa587a06fsewardj    case '9':
4025de4a1d01951937632098a6cda45859afa587a06fsewardj      {
4026de4a1d01951937632098a6cda45859afa587a06fsewardj        int bindex = register_Btype (work);
40274f2683ace412ca2c8266f2dd860dee4461df3cafsewardj        string btype;
40284f2683ace412ca2c8266f2dd860dee4461df3cafsewardj        string_init (&btype);
40294f2683ace412ca2c8266f2dd860dee4461df3cafsewardj        if (demangle_class_name (work, mangled, &btype)) {
40304f2683ace412ca2c8266f2dd860dee4461df3cafsewardj          remember_Btype (work, btype.b, LEN_STRING (&btype), bindex);
4031de4a1d01951937632098a6cda45859afa587a06fsewardj          APPEND_BLANK (result);
40324f2683ace412ca2c8266f2dd860dee4461df3cafsewardj          string_appends (result, &btype);
4033de4a1d01951937632098a6cda45859afa587a06fsewardj        }
4034de4a1d01951937632098a6cda45859afa587a06fsewardj        else
4035de4a1d01951937632098a6cda45859afa587a06fsewardj          success = 0;
40364f2683ace412ca2c8266f2dd860dee4461df3cafsewardj        string_delete (&btype);
4037de4a1d01951937632098a6cda45859afa587a06fsewardj        break;
4038de4a1d01951937632098a6cda45859afa587a06fsewardj      }
4039de4a1d01951937632098a6cda45859afa587a06fsewardj    case 't':
4040de4a1d01951937632098a6cda45859afa587a06fsewardj      {
40414f2683ace412ca2c8266f2dd860dee4461df3cafsewardj        string btype;
40424f2683ace412ca2c8266f2dd860dee4461df3cafsewardj        string_init (&btype);
4043de4a1d01951937632098a6cda45859afa587a06fsewardj        success = demangle_template (work, mangled, &btype, 0, 1, 1);
4044de4a1d01951937632098a6cda45859afa587a06fsewardj        string_appends (result, &btype);
40454f2683ace412ca2c8266f2dd860dee4461df3cafsewardj        string_delete (&btype);
4046de4a1d01951937632098a6cda45859afa587a06fsewardj        break;
4047de4a1d01951937632098a6cda45859afa587a06fsewardj      }
4048de4a1d01951937632098a6cda45859afa587a06fsewardj    default:
4049de4a1d01951937632098a6cda45859afa587a06fsewardj      success = 0;
4050de4a1d01951937632098a6cda45859afa587a06fsewardj      break;
4051de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4052de4a1d01951937632098a6cda45859afa587a06fsewardj
4053de4a1d01951937632098a6cda45859afa587a06fsewardj  return success ? ((int) tk) : 0;
4054de4a1d01951937632098a6cda45859afa587a06fsewardj}
4055de4a1d01951937632098a6cda45859afa587a06fsewardj
4056de4a1d01951937632098a6cda45859afa587a06fsewardj
4057de4a1d01951937632098a6cda45859afa587a06fsewardj/* Handle a template's value parameter for HP aCC (extension from ARM)
4058de4a1d01951937632098a6cda45859afa587a06fsewardj   **mangled points to 'S' or 'U' */
4059de4a1d01951937632098a6cda45859afa587a06fsewardj
4060de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
40614f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdo_hpacc_template_const_value (struct work_stuff *work ATTRIBUTE_UNUSED,
40624f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                               const char **mangled, string *result)
4063de4a1d01951937632098a6cda45859afa587a06fsewardj{
4064de4a1d01951937632098a6cda45859afa587a06fsewardj  int unsigned_const;
4065de4a1d01951937632098a6cda45859afa587a06fsewardj
4066de4a1d01951937632098a6cda45859afa587a06fsewardj  if (**mangled != 'U' && **mangled != 'S')
4067de4a1d01951937632098a6cda45859afa587a06fsewardj    return 0;
4068de4a1d01951937632098a6cda45859afa587a06fsewardj
4069de4a1d01951937632098a6cda45859afa587a06fsewardj  unsigned_const = (**mangled == 'U');
4070de4a1d01951937632098a6cda45859afa587a06fsewardj
4071de4a1d01951937632098a6cda45859afa587a06fsewardj  (*mangled)++;
4072de4a1d01951937632098a6cda45859afa587a06fsewardj
4073de4a1d01951937632098a6cda45859afa587a06fsewardj  switch (**mangled)
4074de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4075de4a1d01951937632098a6cda45859afa587a06fsewardj      case 'N':
4076de4a1d01951937632098a6cda45859afa587a06fsewardj        string_append (result, "-");
4077de4a1d01951937632098a6cda45859afa587a06fsewardj        /* fall through */
4078de4a1d01951937632098a6cda45859afa587a06fsewardj      case 'P':
4079de4a1d01951937632098a6cda45859afa587a06fsewardj        (*mangled)++;
4080de4a1d01951937632098a6cda45859afa587a06fsewardj        break;
4081de4a1d01951937632098a6cda45859afa587a06fsewardj      case 'M':
4082de4a1d01951937632098a6cda45859afa587a06fsewardj        /* special case for -2^31 */
4083de4a1d01951937632098a6cda45859afa587a06fsewardj        string_append (result, "-2147483648");
4084de4a1d01951937632098a6cda45859afa587a06fsewardj        (*mangled)++;
4085de4a1d01951937632098a6cda45859afa587a06fsewardj        return 1;
4086de4a1d01951937632098a6cda45859afa587a06fsewardj      default:
4087de4a1d01951937632098a6cda45859afa587a06fsewardj        return 0;
4088de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4089de4a1d01951937632098a6cda45859afa587a06fsewardj
4090de4a1d01951937632098a6cda45859afa587a06fsewardj  /* We have to be looking at an integer now */
4091de4a1d01951937632098a6cda45859afa587a06fsewardj  if (!(ISDIGIT ((unsigned char)**mangled)))
4092de4a1d01951937632098a6cda45859afa587a06fsewardj    return 0;
4093de4a1d01951937632098a6cda45859afa587a06fsewardj
4094de4a1d01951937632098a6cda45859afa587a06fsewardj  /* We only deal with integral values for template
4095de4a1d01951937632098a6cda45859afa587a06fsewardj     parameters -- so it's OK to look only for digits */
4096de4a1d01951937632098a6cda45859afa587a06fsewardj  while (ISDIGIT ((unsigned char)**mangled))
4097de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4098de4a1d01951937632098a6cda45859afa587a06fsewardj      char_str[0] = **mangled;
4099de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (result, char_str);
4100de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
4101de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4102de4a1d01951937632098a6cda45859afa587a06fsewardj
4103de4a1d01951937632098a6cda45859afa587a06fsewardj  if (unsigned_const)
4104de4a1d01951937632098a6cda45859afa587a06fsewardj    string_append (result, "U");
4105de4a1d01951937632098a6cda45859afa587a06fsewardj
4106de4a1d01951937632098a6cda45859afa587a06fsewardj  /* FIXME? Some day we may have 64-bit (or larger :-) ) constants
4107de4a1d01951937632098a6cda45859afa587a06fsewardj     with L or LL suffixes. pai/1997-09-03 */
4108de4a1d01951937632098a6cda45859afa587a06fsewardj
4109de4a1d01951937632098a6cda45859afa587a06fsewardj  return 1; /* success */
4110de4a1d01951937632098a6cda45859afa587a06fsewardj}
4111de4a1d01951937632098a6cda45859afa587a06fsewardj
4112de4a1d01951937632098a6cda45859afa587a06fsewardj/* Handle a template's literal parameter for HP aCC (extension from ARM)
4113de4a1d01951937632098a6cda45859afa587a06fsewardj   **mangled is pointing to the 'A' */
4114de4a1d01951937632098a6cda45859afa587a06fsewardj
4115de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
41164f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdo_hpacc_template_literal (struct work_stuff *work, const char **mangled,
41174f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                           string *result)
4118de4a1d01951937632098a6cda45859afa587a06fsewardj{
4119de4a1d01951937632098a6cda45859afa587a06fsewardj  int literal_len = 0;
4120de4a1d01951937632098a6cda45859afa587a06fsewardj  char * recurse;
4121de4a1d01951937632098a6cda45859afa587a06fsewardj  char * recurse_dem;
4122de4a1d01951937632098a6cda45859afa587a06fsewardj
4123de4a1d01951937632098a6cda45859afa587a06fsewardj  if (**mangled != 'A')
4124de4a1d01951937632098a6cda45859afa587a06fsewardj    return 0;
4125de4a1d01951937632098a6cda45859afa587a06fsewardj
4126de4a1d01951937632098a6cda45859afa587a06fsewardj  (*mangled)++;
4127de4a1d01951937632098a6cda45859afa587a06fsewardj
4128de4a1d01951937632098a6cda45859afa587a06fsewardj  literal_len = consume_count (mangled);
4129de4a1d01951937632098a6cda45859afa587a06fsewardj
4130de4a1d01951937632098a6cda45859afa587a06fsewardj  if (literal_len <= 0)
4131de4a1d01951937632098a6cda45859afa587a06fsewardj    return 0;
4132de4a1d01951937632098a6cda45859afa587a06fsewardj
4133de4a1d01951937632098a6cda45859afa587a06fsewardj  /* Literal parameters are names of arrays, functions, etc.  and the
4134de4a1d01951937632098a6cda45859afa587a06fsewardj     canonical representation uses the address operator */
4135de4a1d01951937632098a6cda45859afa587a06fsewardj  string_append (result, "&");
4136de4a1d01951937632098a6cda45859afa587a06fsewardj
4137de4a1d01951937632098a6cda45859afa587a06fsewardj  /* Now recursively demangle the literal name */
41384f2683ace412ca2c8266f2dd860dee4461df3cafsewardj  recurse = XNEWVEC (char, literal_len + 1);
4139de4a1d01951937632098a6cda45859afa587a06fsewardj  memcpy (recurse, *mangled, literal_len);
4140de4a1d01951937632098a6cda45859afa587a06fsewardj  recurse[literal_len] = '\000';
4141de4a1d01951937632098a6cda45859afa587a06fsewardj
414244fae838401cd4993b8e4b1cac152ebbd37f28e7sewardj  recurse_dem = ML_(cplus_demangle) (recurse, work->options);
4143de4a1d01951937632098a6cda45859afa587a06fsewardj
4144de4a1d01951937632098a6cda45859afa587a06fsewardj  if (recurse_dem)
4145de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4146de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (result, recurse_dem);
4147de4a1d01951937632098a6cda45859afa587a06fsewardj      free (recurse_dem);
4148de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4149de4a1d01951937632098a6cda45859afa587a06fsewardj  else
4150de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4151de4a1d01951937632098a6cda45859afa587a06fsewardj      string_appendn (result, *mangled, literal_len);
4152de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4153de4a1d01951937632098a6cda45859afa587a06fsewardj  (*mangled) += literal_len;
4154de4a1d01951937632098a6cda45859afa587a06fsewardj  free (recurse);
4155de4a1d01951937632098a6cda45859afa587a06fsewardj
4156de4a1d01951937632098a6cda45859afa587a06fsewardj  return 1;
4157de4a1d01951937632098a6cda45859afa587a06fsewardj}
4158de4a1d01951937632098a6cda45859afa587a06fsewardj
4159de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
41604f2683ace412ca2c8266f2dd860dee4461df3cafsewardjsnarf_numeric_literal (const char **args, string *arg)
4161de4a1d01951937632098a6cda45859afa587a06fsewardj{
4162de4a1d01951937632098a6cda45859afa587a06fsewardj  if (**args == '-')
4163de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4164de4a1d01951937632098a6cda45859afa587a06fsewardj      char_str[0] = '-';
4165de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (arg, char_str);
4166de4a1d01951937632098a6cda45859afa587a06fsewardj      (*args)++;
4167de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4168de4a1d01951937632098a6cda45859afa587a06fsewardj  else if (**args == '+')
4169de4a1d01951937632098a6cda45859afa587a06fsewardj    (*args)++;
4170de4a1d01951937632098a6cda45859afa587a06fsewardj
4171de4a1d01951937632098a6cda45859afa587a06fsewardj  if (!ISDIGIT ((unsigned char)**args))
4172de4a1d01951937632098a6cda45859afa587a06fsewardj    return 0;
4173de4a1d01951937632098a6cda45859afa587a06fsewardj
4174de4a1d01951937632098a6cda45859afa587a06fsewardj  while (ISDIGIT ((unsigned char)**args))
4175de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4176de4a1d01951937632098a6cda45859afa587a06fsewardj      char_str[0] = **args;
4177de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (arg, char_str);
4178de4a1d01951937632098a6cda45859afa587a06fsewardj      (*args)++;
4179de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4180de4a1d01951937632098a6cda45859afa587a06fsewardj
4181de4a1d01951937632098a6cda45859afa587a06fsewardj  return 1;
4182de4a1d01951937632098a6cda45859afa587a06fsewardj}
4183de4a1d01951937632098a6cda45859afa587a06fsewardj
4184de4a1d01951937632098a6cda45859afa587a06fsewardj/* Demangle the next argument, given by MANGLED into RESULT, which
4185de4a1d01951937632098a6cda45859afa587a06fsewardj   *should be an uninitialized* string.  It will be initialized here,
4186de4a1d01951937632098a6cda45859afa587a06fsewardj   and free'd should anything go wrong.  */
4187de4a1d01951937632098a6cda45859afa587a06fsewardj
4188de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
41894f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdo_arg (struct work_stuff *work, const char **mangled, string *result)
4190de4a1d01951937632098a6cda45859afa587a06fsewardj{
4191de4a1d01951937632098a6cda45859afa587a06fsewardj  /* Remember where we started so that we can record the type, for
4192de4a1d01951937632098a6cda45859afa587a06fsewardj     non-squangling type remembering.  */
4193de4a1d01951937632098a6cda45859afa587a06fsewardj  const char *start = *mangled;
4194de4a1d01951937632098a6cda45859afa587a06fsewardj
4195de4a1d01951937632098a6cda45859afa587a06fsewardj  string_init (result);
4196de4a1d01951937632098a6cda45859afa587a06fsewardj
4197de4a1d01951937632098a6cda45859afa587a06fsewardj  if (work->nrepeats > 0)
4198de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4199de4a1d01951937632098a6cda45859afa587a06fsewardj      --work->nrepeats;
4200de4a1d01951937632098a6cda45859afa587a06fsewardj
4201de4a1d01951937632098a6cda45859afa587a06fsewardj      if (work->previous_argument == 0)
4202de4a1d01951937632098a6cda45859afa587a06fsewardj	return 0;
4203de4a1d01951937632098a6cda45859afa587a06fsewardj
4204de4a1d01951937632098a6cda45859afa587a06fsewardj      /* We want to reissue the previous type in this argument list.  */
4205de4a1d01951937632098a6cda45859afa587a06fsewardj      string_appends (result, work->previous_argument);
4206de4a1d01951937632098a6cda45859afa587a06fsewardj      return 1;
4207de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4208de4a1d01951937632098a6cda45859afa587a06fsewardj
4209de4a1d01951937632098a6cda45859afa587a06fsewardj  if (**mangled == 'n')
4210de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4211de4a1d01951937632098a6cda45859afa587a06fsewardj      /* A squangling-style repeat.  */
4212de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
4213de4a1d01951937632098a6cda45859afa587a06fsewardj      work->nrepeats = consume_count(mangled);
4214de4a1d01951937632098a6cda45859afa587a06fsewardj
4215de4a1d01951937632098a6cda45859afa587a06fsewardj      if (work->nrepeats <= 0)
4216de4a1d01951937632098a6cda45859afa587a06fsewardj	/* This was not a repeat count after all.  */
4217de4a1d01951937632098a6cda45859afa587a06fsewardj	return 0;
4218de4a1d01951937632098a6cda45859afa587a06fsewardj
4219de4a1d01951937632098a6cda45859afa587a06fsewardj      if (work->nrepeats > 9)
4220de4a1d01951937632098a6cda45859afa587a06fsewardj	{
4221de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (**mangled != '_')
4222de4a1d01951937632098a6cda45859afa587a06fsewardj	    /* The repeat count should be followed by an '_' in this
4223de4a1d01951937632098a6cda45859afa587a06fsewardj	       case.  */
4224de4a1d01951937632098a6cda45859afa587a06fsewardj	    return 0;
4225de4a1d01951937632098a6cda45859afa587a06fsewardj	  else
4226de4a1d01951937632098a6cda45859afa587a06fsewardj	    (*mangled)++;
4227de4a1d01951937632098a6cda45859afa587a06fsewardj	}
4228de4a1d01951937632098a6cda45859afa587a06fsewardj
4229de4a1d01951937632098a6cda45859afa587a06fsewardj      /* Now, the repeat is all set up.  */
4230de4a1d01951937632098a6cda45859afa587a06fsewardj      return do_arg (work, mangled, result);
4231de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4232de4a1d01951937632098a6cda45859afa587a06fsewardj
4233de4a1d01951937632098a6cda45859afa587a06fsewardj  /* Save the result in WORK->previous_argument so that we can find it
4234de4a1d01951937632098a6cda45859afa587a06fsewardj     if it's repeated.  Note that saving START is not good enough: we
4235de4a1d01951937632098a6cda45859afa587a06fsewardj     do not want to add additional types to the back-referenceable
4236de4a1d01951937632098a6cda45859afa587a06fsewardj     type vector when processing a repeated type.  */
4237de4a1d01951937632098a6cda45859afa587a06fsewardj  if (work->previous_argument)
42384f2683ace412ca2c8266f2dd860dee4461df3cafsewardj    string_delete (work->previous_argument);
4239de4a1d01951937632098a6cda45859afa587a06fsewardj  else
42404f2683ace412ca2c8266f2dd860dee4461df3cafsewardj    work->previous_argument = XNEW (string);
4241de4a1d01951937632098a6cda45859afa587a06fsewardj
42424f2683ace412ca2c8266f2dd860dee4461df3cafsewardj  if (!do_type (work, mangled, work->previous_argument))
42434f2683ace412ca2c8266f2dd860dee4461df3cafsewardj    return 0;
4244de4a1d01951937632098a6cda45859afa587a06fsewardj
4245de4a1d01951937632098a6cda45859afa587a06fsewardj  string_appends (result, work->previous_argument);
4246de4a1d01951937632098a6cda45859afa587a06fsewardj
4247de4a1d01951937632098a6cda45859afa587a06fsewardj  remember_type (work, start, *mangled - start);
4248de4a1d01951937632098a6cda45859afa587a06fsewardj  return 1;
4249de4a1d01951937632098a6cda45859afa587a06fsewardj}
4250de4a1d01951937632098a6cda45859afa587a06fsewardj
4251de4a1d01951937632098a6cda45859afa587a06fsewardjstatic void
42524f2683ace412ca2c8266f2dd860dee4461df3cafsewardjremember_type (struct work_stuff *work, const char *start, int len)
4253de4a1d01951937632098a6cda45859afa587a06fsewardj{
4254de4a1d01951937632098a6cda45859afa587a06fsewardj  char *tem;
4255de4a1d01951937632098a6cda45859afa587a06fsewardj
4256de4a1d01951937632098a6cda45859afa587a06fsewardj  if (work->forgetting_types)
4257de4a1d01951937632098a6cda45859afa587a06fsewardj    return;
4258de4a1d01951937632098a6cda45859afa587a06fsewardj
4259de4a1d01951937632098a6cda45859afa587a06fsewardj  if (work -> ntypes >= work -> typevec_size)
4260de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4261de4a1d01951937632098a6cda45859afa587a06fsewardj      if (work -> typevec_size == 0)
4262de4a1d01951937632098a6cda45859afa587a06fsewardj	{
4263de4a1d01951937632098a6cda45859afa587a06fsewardj	  work -> typevec_size = 3;
42644f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	  work -> typevec = XNEWVEC (char *, work->typevec_size);
4265de4a1d01951937632098a6cda45859afa587a06fsewardj	}
4266de4a1d01951937632098a6cda45859afa587a06fsewardj      else
4267de4a1d01951937632098a6cda45859afa587a06fsewardj	{
4268de4a1d01951937632098a6cda45859afa587a06fsewardj	  work -> typevec_size *= 2;
4269de4a1d01951937632098a6cda45859afa587a06fsewardj	  work -> typevec
42704f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	    = XRESIZEVEC (char *, work->typevec, work->typevec_size);
4271de4a1d01951937632098a6cda45859afa587a06fsewardj	}
4272de4a1d01951937632098a6cda45859afa587a06fsewardj    }
42734f2683ace412ca2c8266f2dd860dee4461df3cafsewardj  tem = XNEWVEC (char, len + 1);
4274de4a1d01951937632098a6cda45859afa587a06fsewardj  memcpy (tem, start, len);
4275de4a1d01951937632098a6cda45859afa587a06fsewardj  tem[len] = '\0';
4276de4a1d01951937632098a6cda45859afa587a06fsewardj  work -> typevec[work -> ntypes++] = tem;
4277de4a1d01951937632098a6cda45859afa587a06fsewardj}
4278de4a1d01951937632098a6cda45859afa587a06fsewardj
4279de4a1d01951937632098a6cda45859afa587a06fsewardj
4280de4a1d01951937632098a6cda45859afa587a06fsewardj/* Remember a K type class qualifier. */
4281de4a1d01951937632098a6cda45859afa587a06fsewardjstatic void
42824f2683ace412ca2c8266f2dd860dee4461df3cafsewardjremember_Ktype (struct work_stuff *work, const char *start, int len)
4283de4a1d01951937632098a6cda45859afa587a06fsewardj{
4284de4a1d01951937632098a6cda45859afa587a06fsewardj  char *tem;
4285de4a1d01951937632098a6cda45859afa587a06fsewardj
4286de4a1d01951937632098a6cda45859afa587a06fsewardj  if (work -> numk >= work -> ksize)
4287de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4288de4a1d01951937632098a6cda45859afa587a06fsewardj      if (work -> ksize == 0)
4289de4a1d01951937632098a6cda45859afa587a06fsewardj	{
4290de4a1d01951937632098a6cda45859afa587a06fsewardj	  work -> ksize = 5;
42914f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	  work -> ktypevec = XNEWVEC (char *, work->ksize);
4292de4a1d01951937632098a6cda45859afa587a06fsewardj	}
4293de4a1d01951937632098a6cda45859afa587a06fsewardj      else
4294de4a1d01951937632098a6cda45859afa587a06fsewardj	{
4295de4a1d01951937632098a6cda45859afa587a06fsewardj	  work -> ksize *= 2;
4296de4a1d01951937632098a6cda45859afa587a06fsewardj	  work -> ktypevec
42974f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	    = XRESIZEVEC (char *, work->ktypevec, work->ksize);
4298de4a1d01951937632098a6cda45859afa587a06fsewardj	}
4299de4a1d01951937632098a6cda45859afa587a06fsewardj    }
43004f2683ace412ca2c8266f2dd860dee4461df3cafsewardj  tem = XNEWVEC (char, len + 1);
4301de4a1d01951937632098a6cda45859afa587a06fsewardj  memcpy (tem, start, len);
4302de4a1d01951937632098a6cda45859afa587a06fsewardj  tem[len] = '\0';
4303de4a1d01951937632098a6cda45859afa587a06fsewardj  work -> ktypevec[work -> numk++] = tem;
4304de4a1d01951937632098a6cda45859afa587a06fsewardj}
4305de4a1d01951937632098a6cda45859afa587a06fsewardj
4306de4a1d01951937632098a6cda45859afa587a06fsewardj/* Register a B code, and get an index for it. B codes are registered
4307de4a1d01951937632098a6cda45859afa587a06fsewardj   as they are seen, rather than as they are completed, so map<temp<char> >
4308de4a1d01951937632098a6cda45859afa587a06fsewardj   registers map<temp<char> > as B0, and temp<char> as B1 */
4309de4a1d01951937632098a6cda45859afa587a06fsewardj
4310de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
43114f2683ace412ca2c8266f2dd860dee4461df3cafsewardjregister_Btype (struct work_stuff *work)
4312de4a1d01951937632098a6cda45859afa587a06fsewardj{
4313de4a1d01951937632098a6cda45859afa587a06fsewardj  int ret;
4314de4a1d01951937632098a6cda45859afa587a06fsewardj
4315de4a1d01951937632098a6cda45859afa587a06fsewardj  if (work -> numb >= work -> bsize)
4316de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4317de4a1d01951937632098a6cda45859afa587a06fsewardj      if (work -> bsize == 0)
4318de4a1d01951937632098a6cda45859afa587a06fsewardj	{
4319de4a1d01951937632098a6cda45859afa587a06fsewardj	  work -> bsize = 5;
43204f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	  work -> btypevec = XNEWVEC (char *, work->bsize);
4321de4a1d01951937632098a6cda45859afa587a06fsewardj	}
4322de4a1d01951937632098a6cda45859afa587a06fsewardj      else
4323de4a1d01951937632098a6cda45859afa587a06fsewardj	{
4324de4a1d01951937632098a6cda45859afa587a06fsewardj	  work -> bsize *= 2;
4325de4a1d01951937632098a6cda45859afa587a06fsewardj	  work -> btypevec
43264f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	    = XRESIZEVEC (char *, work->btypevec, work->bsize);
4327de4a1d01951937632098a6cda45859afa587a06fsewardj	}
4328de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4329de4a1d01951937632098a6cda45859afa587a06fsewardj  ret = work -> numb++;
4330de4a1d01951937632098a6cda45859afa587a06fsewardj  work -> btypevec[ret] = NULL;
4331de4a1d01951937632098a6cda45859afa587a06fsewardj  return(ret);
4332de4a1d01951937632098a6cda45859afa587a06fsewardj}
4333de4a1d01951937632098a6cda45859afa587a06fsewardj
4334de4a1d01951937632098a6cda45859afa587a06fsewardj/* Store a value into a previously registered B code type. */
4335de4a1d01951937632098a6cda45859afa587a06fsewardj
4336de4a1d01951937632098a6cda45859afa587a06fsewardjstatic void
43374f2683ace412ca2c8266f2dd860dee4461df3cafsewardjremember_Btype (struct work_stuff *work, const char *start,
43388669fd38673be80b022b5730092970fee8cf66d1sewardj                int len, int indx)
4339de4a1d01951937632098a6cda45859afa587a06fsewardj{
4340de4a1d01951937632098a6cda45859afa587a06fsewardj  char *tem;
4341de4a1d01951937632098a6cda45859afa587a06fsewardj
43424f2683ace412ca2c8266f2dd860dee4461df3cafsewardj  tem = XNEWVEC (char, len + 1);
4343de4a1d01951937632098a6cda45859afa587a06fsewardj  memcpy (tem, start, len);
4344de4a1d01951937632098a6cda45859afa587a06fsewardj  tem[len] = '\0';
43458669fd38673be80b022b5730092970fee8cf66d1sewardj  work -> btypevec[indx] = tem;
4346de4a1d01951937632098a6cda45859afa587a06fsewardj}
4347de4a1d01951937632098a6cda45859afa587a06fsewardj
4348de4a1d01951937632098a6cda45859afa587a06fsewardj/* Lose all the info related to B and K type codes. */
4349de4a1d01951937632098a6cda45859afa587a06fsewardjstatic void
43504f2683ace412ca2c8266f2dd860dee4461df3cafsewardjforget_B_and_K_types (struct work_stuff *work)
4351de4a1d01951937632098a6cda45859afa587a06fsewardj{
4352de4a1d01951937632098a6cda45859afa587a06fsewardj  int i;
4353de4a1d01951937632098a6cda45859afa587a06fsewardj
4354de4a1d01951937632098a6cda45859afa587a06fsewardj  while (work -> numk > 0)
4355de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4356de4a1d01951937632098a6cda45859afa587a06fsewardj      i = --(work -> numk);
4357de4a1d01951937632098a6cda45859afa587a06fsewardj      if (work -> ktypevec[i] != NULL)
4358de4a1d01951937632098a6cda45859afa587a06fsewardj	{
4359de4a1d01951937632098a6cda45859afa587a06fsewardj	  free (work -> ktypevec[i]);
4360de4a1d01951937632098a6cda45859afa587a06fsewardj	  work -> ktypevec[i] = NULL;
4361de4a1d01951937632098a6cda45859afa587a06fsewardj	}
4362de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4363de4a1d01951937632098a6cda45859afa587a06fsewardj
4364de4a1d01951937632098a6cda45859afa587a06fsewardj  while (work -> numb > 0)
4365de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4366de4a1d01951937632098a6cda45859afa587a06fsewardj      i = --(work -> numb);
4367de4a1d01951937632098a6cda45859afa587a06fsewardj      if (work -> btypevec[i] != NULL)
4368de4a1d01951937632098a6cda45859afa587a06fsewardj	{
4369de4a1d01951937632098a6cda45859afa587a06fsewardj	  free (work -> btypevec[i]);
4370de4a1d01951937632098a6cda45859afa587a06fsewardj	  work -> btypevec[i] = NULL;
4371de4a1d01951937632098a6cda45859afa587a06fsewardj	}
4372de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4373de4a1d01951937632098a6cda45859afa587a06fsewardj}
4374de4a1d01951937632098a6cda45859afa587a06fsewardj/* Forget the remembered types, but not the type vector itself.  */
4375de4a1d01951937632098a6cda45859afa587a06fsewardj
4376de4a1d01951937632098a6cda45859afa587a06fsewardjstatic void
43774f2683ace412ca2c8266f2dd860dee4461df3cafsewardjforget_types (struct work_stuff *work)
4378de4a1d01951937632098a6cda45859afa587a06fsewardj{
4379de4a1d01951937632098a6cda45859afa587a06fsewardj  int i;
4380de4a1d01951937632098a6cda45859afa587a06fsewardj
4381de4a1d01951937632098a6cda45859afa587a06fsewardj  while (work -> ntypes > 0)
4382de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4383de4a1d01951937632098a6cda45859afa587a06fsewardj      i = --(work -> ntypes);
4384de4a1d01951937632098a6cda45859afa587a06fsewardj      if (work -> typevec[i] != NULL)
4385de4a1d01951937632098a6cda45859afa587a06fsewardj	{
4386de4a1d01951937632098a6cda45859afa587a06fsewardj	  free (work -> typevec[i]);
4387de4a1d01951937632098a6cda45859afa587a06fsewardj	  work -> typevec[i] = NULL;
4388de4a1d01951937632098a6cda45859afa587a06fsewardj	}
4389de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4390de4a1d01951937632098a6cda45859afa587a06fsewardj}
4391de4a1d01951937632098a6cda45859afa587a06fsewardj
4392de4a1d01951937632098a6cda45859afa587a06fsewardj/* Process the argument list part of the signature, after any class spec
4393de4a1d01951937632098a6cda45859afa587a06fsewardj   has been consumed, as well as the first 'F' character (if any).  For
4394de4a1d01951937632098a6cda45859afa587a06fsewardj   example:
4395de4a1d01951937632098a6cda45859afa587a06fsewardj
4396de4a1d01951937632098a6cda45859afa587a06fsewardj   "__als__3fooRT0"		=>	process "RT0"
4397de4a1d01951937632098a6cda45859afa587a06fsewardj   "complexfunc5__FPFPc_PFl_i"	=>	process "PFPc_PFl_i"
4398de4a1d01951937632098a6cda45859afa587a06fsewardj
4399de4a1d01951937632098a6cda45859afa587a06fsewardj   DECLP must be already initialised, usually non-empty.  It won't be freed
4400de4a1d01951937632098a6cda45859afa587a06fsewardj   on failure.
4401de4a1d01951937632098a6cda45859afa587a06fsewardj
4402de4a1d01951937632098a6cda45859afa587a06fsewardj   Note that g++ differs significantly from ARM and lucid style mangling
4403de4a1d01951937632098a6cda45859afa587a06fsewardj   with regards to references to previously seen types.  For example, given
4404de4a1d01951937632098a6cda45859afa587a06fsewardj   the source fragment:
4405de4a1d01951937632098a6cda45859afa587a06fsewardj
4406de4a1d01951937632098a6cda45859afa587a06fsewardj     class foo {
4407de4a1d01951937632098a6cda45859afa587a06fsewardj       public:
4408de4a1d01951937632098a6cda45859afa587a06fsewardj       foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
4409de4a1d01951937632098a6cda45859afa587a06fsewardj     };
4410de4a1d01951937632098a6cda45859afa587a06fsewardj
4411de4a1d01951937632098a6cda45859afa587a06fsewardj     foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
4412de4a1d01951937632098a6cda45859afa587a06fsewardj     void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
4413de4a1d01951937632098a6cda45859afa587a06fsewardj
4414de4a1d01951937632098a6cda45859afa587a06fsewardj   g++ produces the names:
4415de4a1d01951937632098a6cda45859afa587a06fsewardj
4416de4a1d01951937632098a6cda45859afa587a06fsewardj     __3fooiRT0iT2iT2
4417de4a1d01951937632098a6cda45859afa587a06fsewardj     foo__FiR3fooiT1iT1
4418de4a1d01951937632098a6cda45859afa587a06fsewardj
4419de4a1d01951937632098a6cda45859afa587a06fsewardj   while lcc (and presumably other ARM style compilers as well) produces:
4420de4a1d01951937632098a6cda45859afa587a06fsewardj
4421de4a1d01951937632098a6cda45859afa587a06fsewardj     foo__FiR3fooT1T2T1T2
4422de4a1d01951937632098a6cda45859afa587a06fsewardj     __ct__3fooFiR3fooT1T2T1T2
4423de4a1d01951937632098a6cda45859afa587a06fsewardj
4424de4a1d01951937632098a6cda45859afa587a06fsewardj   Note that g++ bases its type numbers starting at zero and counts all
4425de4a1d01951937632098a6cda45859afa587a06fsewardj   previously seen types, while lucid/ARM bases its type numbers starting
4426de4a1d01951937632098a6cda45859afa587a06fsewardj   at one and only considers types after it has seen the 'F' character
4427de4a1d01951937632098a6cda45859afa587a06fsewardj   indicating the start of the function args.  For lucid/ARM style, we
4428de4a1d01951937632098a6cda45859afa587a06fsewardj   account for this difference by discarding any previously seen types when
4429de4a1d01951937632098a6cda45859afa587a06fsewardj   we see the 'F' character, and subtracting one from the type number
4430de4a1d01951937632098a6cda45859afa587a06fsewardj   reference.
4431de4a1d01951937632098a6cda45859afa587a06fsewardj
4432de4a1d01951937632098a6cda45859afa587a06fsewardj */
4433de4a1d01951937632098a6cda45859afa587a06fsewardj
4434de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
44354f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_args (struct work_stuff *work, const char **mangled,
44364f2683ace412ca2c8266f2dd860dee4461df3cafsewardj               string *declp)
4437de4a1d01951937632098a6cda45859afa587a06fsewardj{
4438de4a1d01951937632098a6cda45859afa587a06fsewardj  string arg;
4439de4a1d01951937632098a6cda45859afa587a06fsewardj  int need_comma = 0;
4440de4a1d01951937632098a6cda45859afa587a06fsewardj  int r;
4441de4a1d01951937632098a6cda45859afa587a06fsewardj  int t;
4442de4a1d01951937632098a6cda45859afa587a06fsewardj  const char *tem;
4443de4a1d01951937632098a6cda45859afa587a06fsewardj  char temptype;
4444de4a1d01951937632098a6cda45859afa587a06fsewardj
4445de4a1d01951937632098a6cda45859afa587a06fsewardj  if (PRINT_ARG_TYPES)
4446de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4447de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (declp, "(");
4448de4a1d01951937632098a6cda45859afa587a06fsewardj      if (**mangled == '\0')
4449de4a1d01951937632098a6cda45859afa587a06fsewardj	{
4450de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_append (declp, "void");
4451de4a1d01951937632098a6cda45859afa587a06fsewardj	}
4452de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4453de4a1d01951937632098a6cda45859afa587a06fsewardj
4454de4a1d01951937632098a6cda45859afa587a06fsewardj  while ((**mangled != '_' && **mangled != '\0' && **mangled != 'e')
4455de4a1d01951937632098a6cda45859afa587a06fsewardj	 || work->nrepeats > 0)
4456de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4457de4a1d01951937632098a6cda45859afa587a06fsewardj      if ((**mangled == 'N') || (**mangled == 'T'))
4458de4a1d01951937632098a6cda45859afa587a06fsewardj	{
4459de4a1d01951937632098a6cda45859afa587a06fsewardj	  temptype = *(*mangled)++;
4460de4a1d01951937632098a6cda45859afa587a06fsewardj
4461de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (temptype == 'N')
4462de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
4463de4a1d01951937632098a6cda45859afa587a06fsewardj	      if (!get_count (mangled, &r))
4464de4a1d01951937632098a6cda45859afa587a06fsewardj		{
4465de4a1d01951937632098a6cda45859afa587a06fsewardj		  return (0);
4466de4a1d01951937632098a6cda45859afa587a06fsewardj		}
4467de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
4468de4a1d01951937632098a6cda45859afa587a06fsewardj	  else
4469de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
4470de4a1d01951937632098a6cda45859afa587a06fsewardj	      r = 1;
4471de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
4472de4a1d01951937632098a6cda45859afa587a06fsewardj          if ((HP_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING) && work -> ntypes >= 10)
4473de4a1d01951937632098a6cda45859afa587a06fsewardj            {
4474de4a1d01951937632098a6cda45859afa587a06fsewardj              /* If we have 10 or more types we might have more than a 1 digit
4475de4a1d01951937632098a6cda45859afa587a06fsewardj                 index so we'll have to consume the whole count here. This
4476de4a1d01951937632098a6cda45859afa587a06fsewardj                 will lose if the next thing is a type name preceded by a
4477de4a1d01951937632098a6cda45859afa587a06fsewardj                 count but it's impossible to demangle that case properly
4478de4a1d01951937632098a6cda45859afa587a06fsewardj                 anyway. Eg if we already have 12 types is T12Pc "(..., type1,
4479de4a1d01951937632098a6cda45859afa587a06fsewardj                 Pc, ...)"  or "(..., type12, char *, ...)" */
4480de4a1d01951937632098a6cda45859afa587a06fsewardj              if ((t = consume_count(mangled)) <= 0)
4481de4a1d01951937632098a6cda45859afa587a06fsewardj                {
4482de4a1d01951937632098a6cda45859afa587a06fsewardj                  return (0);
4483de4a1d01951937632098a6cda45859afa587a06fsewardj                }
4484de4a1d01951937632098a6cda45859afa587a06fsewardj            }
4485de4a1d01951937632098a6cda45859afa587a06fsewardj          else
4486de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
4487de4a1d01951937632098a6cda45859afa587a06fsewardj	      if (!get_count (mangled, &t))
4488de4a1d01951937632098a6cda45859afa587a06fsewardj	    	{
4489de4a1d01951937632098a6cda45859afa587a06fsewardj	          return (0);
4490de4a1d01951937632098a6cda45859afa587a06fsewardj	    	}
4491de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
4492de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
4493de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
4494de4a1d01951937632098a6cda45859afa587a06fsewardj	      t--;
4495de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
4496de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* Validate the type index.  Protect against illegal indices from
4497de4a1d01951937632098a6cda45859afa587a06fsewardj	     malformed type strings.  */
4498de4a1d01951937632098a6cda45859afa587a06fsewardj	  if ((t < 0) || (t >= work -> ntypes))
4499de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
4500de4a1d01951937632098a6cda45859afa587a06fsewardj	      return (0);
4501de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
4502de4a1d01951937632098a6cda45859afa587a06fsewardj	  while (work->nrepeats > 0 || --r >= 0)
4503de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
4504de4a1d01951937632098a6cda45859afa587a06fsewardj	      tem = work -> typevec[t];
4505de4a1d01951937632098a6cda45859afa587a06fsewardj	      if (need_comma && PRINT_ARG_TYPES)
4506de4a1d01951937632098a6cda45859afa587a06fsewardj		{
4507de4a1d01951937632098a6cda45859afa587a06fsewardj		  string_append (declp, ", ");
4508de4a1d01951937632098a6cda45859afa587a06fsewardj		}
4509de4a1d01951937632098a6cda45859afa587a06fsewardj	      if (!do_arg (work, &tem, &arg))
4510de4a1d01951937632098a6cda45859afa587a06fsewardj		{
4511de4a1d01951937632098a6cda45859afa587a06fsewardj		  return (0);
4512de4a1d01951937632098a6cda45859afa587a06fsewardj		}
4513de4a1d01951937632098a6cda45859afa587a06fsewardj	      if (PRINT_ARG_TYPES)
4514de4a1d01951937632098a6cda45859afa587a06fsewardj		{
4515de4a1d01951937632098a6cda45859afa587a06fsewardj		  string_appends (declp, &arg);
4516de4a1d01951937632098a6cda45859afa587a06fsewardj		}
4517de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_delete (&arg);
4518de4a1d01951937632098a6cda45859afa587a06fsewardj	      need_comma = 1;
4519de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
4520de4a1d01951937632098a6cda45859afa587a06fsewardj	}
4521de4a1d01951937632098a6cda45859afa587a06fsewardj      else
4522de4a1d01951937632098a6cda45859afa587a06fsewardj	{
4523de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (need_comma && PRINT_ARG_TYPES)
4524de4a1d01951937632098a6cda45859afa587a06fsewardj	    string_append (declp, ", ");
4525de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (!do_arg (work, mangled, &arg))
45264f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	    return (0);
4527de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (PRINT_ARG_TYPES)
4528de4a1d01951937632098a6cda45859afa587a06fsewardj	    string_appends (declp, &arg);
4529de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_delete (&arg);
4530de4a1d01951937632098a6cda45859afa587a06fsewardj	  need_comma = 1;
4531de4a1d01951937632098a6cda45859afa587a06fsewardj	}
4532de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4533de4a1d01951937632098a6cda45859afa587a06fsewardj
4534de4a1d01951937632098a6cda45859afa587a06fsewardj  if (**mangled == 'e')
4535de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4536de4a1d01951937632098a6cda45859afa587a06fsewardj      (*mangled)++;
4537de4a1d01951937632098a6cda45859afa587a06fsewardj      if (PRINT_ARG_TYPES)
4538de4a1d01951937632098a6cda45859afa587a06fsewardj	{
4539de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (need_comma)
4540de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
4541de4a1d01951937632098a6cda45859afa587a06fsewardj	      string_append (declp, ",");
4542de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
4543de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_append (declp, "...");
4544de4a1d01951937632098a6cda45859afa587a06fsewardj	}
4545de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4546de4a1d01951937632098a6cda45859afa587a06fsewardj
4547de4a1d01951937632098a6cda45859afa587a06fsewardj  if (PRINT_ARG_TYPES)
4548de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4549de4a1d01951937632098a6cda45859afa587a06fsewardj      string_append (declp, ")");
4550de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4551de4a1d01951937632098a6cda45859afa587a06fsewardj  return (1);
4552de4a1d01951937632098a6cda45859afa587a06fsewardj}
4553de4a1d01951937632098a6cda45859afa587a06fsewardj
4554de4a1d01951937632098a6cda45859afa587a06fsewardj/* Like demangle_args, but for demangling the argument lists of function
4555de4a1d01951937632098a6cda45859afa587a06fsewardj   and method pointers or references, not top-level declarations.  */
4556de4a1d01951937632098a6cda45859afa587a06fsewardj
4557de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
45584f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_nested_args (struct work_stuff *work, const char **mangled,
45594f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                      string *declp)
4560de4a1d01951937632098a6cda45859afa587a06fsewardj{
4561de4a1d01951937632098a6cda45859afa587a06fsewardj  string* saved_previous_argument;
4562de4a1d01951937632098a6cda45859afa587a06fsewardj  int result;
4563de4a1d01951937632098a6cda45859afa587a06fsewardj  int saved_nrepeats;
4564de4a1d01951937632098a6cda45859afa587a06fsewardj
4565de4a1d01951937632098a6cda45859afa587a06fsewardj  /* The G++ name-mangling algorithm does not remember types on nested
4566de4a1d01951937632098a6cda45859afa587a06fsewardj     argument lists, unless -fsquangling is used, and in that case the
4567de4a1d01951937632098a6cda45859afa587a06fsewardj     type vector updated by remember_type is not used.  So, we turn
4568de4a1d01951937632098a6cda45859afa587a06fsewardj     off remembering of types here.  */
4569de4a1d01951937632098a6cda45859afa587a06fsewardj  ++work->forgetting_types;
4570de4a1d01951937632098a6cda45859afa587a06fsewardj
4571de4a1d01951937632098a6cda45859afa587a06fsewardj  /* For the repeat codes used with -fsquangling, we must keep track of
4572de4a1d01951937632098a6cda45859afa587a06fsewardj     the last argument.  */
4573de4a1d01951937632098a6cda45859afa587a06fsewardj  saved_previous_argument = work->previous_argument;
4574de4a1d01951937632098a6cda45859afa587a06fsewardj  saved_nrepeats = work->nrepeats;
4575de4a1d01951937632098a6cda45859afa587a06fsewardj  work->previous_argument = 0;
4576de4a1d01951937632098a6cda45859afa587a06fsewardj  work->nrepeats = 0;
4577de4a1d01951937632098a6cda45859afa587a06fsewardj
4578de4a1d01951937632098a6cda45859afa587a06fsewardj  /* Actually demangle the arguments.  */
4579de4a1d01951937632098a6cda45859afa587a06fsewardj  result = demangle_args (work, mangled, declp);
4580de4a1d01951937632098a6cda45859afa587a06fsewardj
4581de4a1d01951937632098a6cda45859afa587a06fsewardj  /* Restore the previous_argument field.  */
4582de4a1d01951937632098a6cda45859afa587a06fsewardj  if (work->previous_argument)
4583de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4584de4a1d01951937632098a6cda45859afa587a06fsewardj      string_delete (work->previous_argument);
45854f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      free ((char *) work->previous_argument);
4586de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4587de4a1d01951937632098a6cda45859afa587a06fsewardj  work->previous_argument = saved_previous_argument;
4588de4a1d01951937632098a6cda45859afa587a06fsewardj  --work->forgetting_types;
4589de4a1d01951937632098a6cda45859afa587a06fsewardj  work->nrepeats = saved_nrepeats;
4590de4a1d01951937632098a6cda45859afa587a06fsewardj
4591de4a1d01951937632098a6cda45859afa587a06fsewardj  return result;
4592de4a1d01951937632098a6cda45859afa587a06fsewardj}
4593de4a1d01951937632098a6cda45859afa587a06fsewardj
45944f2683ace412ca2c8266f2dd860dee4461df3cafsewardj/* Returns 1 if a valid function name was found or 0 otherwise.  */
45954f2683ace412ca2c8266f2dd860dee4461df3cafsewardj
45964f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstatic int
45974f2683ace412ca2c8266f2dd860dee4461df3cafsewardjdemangle_function_name (struct work_stuff *work, const char **mangled,
45984f2683ace412ca2c8266f2dd860dee4461df3cafsewardj                        string *declp, const char *scan)
4599de4a1d01951937632098a6cda45859afa587a06fsewardj{
4600de4a1d01951937632098a6cda45859afa587a06fsewardj  size_t i;
4601de4a1d01951937632098a6cda45859afa587a06fsewardj  string type;
4602de4a1d01951937632098a6cda45859afa587a06fsewardj  const char *tem;
4603de4a1d01951937632098a6cda45859afa587a06fsewardj
4604de4a1d01951937632098a6cda45859afa587a06fsewardj  string_appendn (declp, (*mangled), scan - (*mangled));
4605de4a1d01951937632098a6cda45859afa587a06fsewardj  string_need (declp, 1);
4606de4a1d01951937632098a6cda45859afa587a06fsewardj  *(declp -> p) = '\0';
4607de4a1d01951937632098a6cda45859afa587a06fsewardj
4608de4a1d01951937632098a6cda45859afa587a06fsewardj  /* Consume the function name, including the "__" separating the name
4609de4a1d01951937632098a6cda45859afa587a06fsewardj     from the signature.  We are guaranteed that SCAN points to the
4610de4a1d01951937632098a6cda45859afa587a06fsewardj     separator.  */
4611de4a1d01951937632098a6cda45859afa587a06fsewardj
4612de4a1d01951937632098a6cda45859afa587a06fsewardj  (*mangled) = scan + 2;
4613de4a1d01951937632098a6cda45859afa587a06fsewardj  /* We may be looking at an instantiation of a template function:
4614de4a1d01951937632098a6cda45859afa587a06fsewardj     foo__Xt1t2_Ft3t4, where t1, t2, ... are template arguments and a
4615de4a1d01951937632098a6cda45859afa587a06fsewardj     following _F marks the start of the function arguments.  Handle
4616de4a1d01951937632098a6cda45859afa587a06fsewardj     the template arguments first. */
4617de4a1d01951937632098a6cda45859afa587a06fsewardj
4618de4a1d01951937632098a6cda45859afa587a06fsewardj  if (HP_DEMANGLING && (**mangled == 'X'))
4619de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4620de4a1d01951937632098a6cda45859afa587a06fsewardj      demangle_arm_hp_template (work, mangled, 0, declp);
4621de4a1d01951937632098a6cda45859afa587a06fsewardj      /* This leaves MANGLED pointing to the 'F' marking func args */
4622de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4623de4a1d01951937632098a6cda45859afa587a06fsewardj
4624de4a1d01951937632098a6cda45859afa587a06fsewardj  if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
4625de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4626de4a1d01951937632098a6cda45859afa587a06fsewardj
4627de4a1d01951937632098a6cda45859afa587a06fsewardj      /* See if we have an ARM style constructor or destructor operator.
4628de4a1d01951937632098a6cda45859afa587a06fsewardj	 If so, then just record it, clear the decl, and return.
4629de4a1d01951937632098a6cda45859afa587a06fsewardj	 We can't build the actual constructor/destructor decl until later,
4630de4a1d01951937632098a6cda45859afa587a06fsewardj	 when we recover the class name from the signature.  */
4631de4a1d01951937632098a6cda45859afa587a06fsewardj
4632de4a1d01951937632098a6cda45859afa587a06fsewardj      if (strcmp (declp -> b, "__ct") == 0)
4633de4a1d01951937632098a6cda45859afa587a06fsewardj	{
4634de4a1d01951937632098a6cda45859afa587a06fsewardj	  work -> constructor += 1;
4635de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_clear (declp);
46364f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	  return 1;
4637de4a1d01951937632098a6cda45859afa587a06fsewardj	}
4638de4a1d01951937632098a6cda45859afa587a06fsewardj      else if (strcmp (declp -> b, "__dt") == 0)
4639de4a1d01951937632098a6cda45859afa587a06fsewardj	{
4640de4a1d01951937632098a6cda45859afa587a06fsewardj	  work -> destructor += 1;
4641de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_clear (declp);
46424f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	  return 1;
4643de4a1d01951937632098a6cda45859afa587a06fsewardj	}
4644de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4645de4a1d01951937632098a6cda45859afa587a06fsewardj
4646de4a1d01951937632098a6cda45859afa587a06fsewardj  if (declp->p - declp->b >= 3
4647de4a1d01951937632098a6cda45859afa587a06fsewardj      && declp->b[0] == 'o'
4648de4a1d01951937632098a6cda45859afa587a06fsewardj      && declp->b[1] == 'p'
4649de4a1d01951937632098a6cda45859afa587a06fsewardj      && strchr (cplus_markers, declp->b[2]) != NULL)
4650de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4651de4a1d01951937632098a6cda45859afa587a06fsewardj      /* see if it's an assignment expression */
4652de4a1d01951937632098a6cda45859afa587a06fsewardj      if (declp->p - declp->b >= 10 /* op$assign_ */
4653de4a1d01951937632098a6cda45859afa587a06fsewardj	  && memcmp (declp->b + 3, "assign_", 7) == 0)
4654de4a1d01951937632098a6cda45859afa587a06fsewardj	{
46554f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	  for (i = 0; i < ARRAY_SIZE (optable); i++)
4656de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
4657de4a1d01951937632098a6cda45859afa587a06fsewardj	      int len = declp->p - declp->b - 10;
4658de4a1d01951937632098a6cda45859afa587a06fsewardj	      if ((int) strlen (optable[i].in) == len
4659de4a1d01951937632098a6cda45859afa587a06fsewardj		  && memcmp (optable[i].in, declp->b + 10, len) == 0)
4660de4a1d01951937632098a6cda45859afa587a06fsewardj		{
4661de4a1d01951937632098a6cda45859afa587a06fsewardj		  string_clear (declp);
4662de4a1d01951937632098a6cda45859afa587a06fsewardj		  string_append (declp, "operator");
4663de4a1d01951937632098a6cda45859afa587a06fsewardj		  string_append (declp, optable[i].out);
4664de4a1d01951937632098a6cda45859afa587a06fsewardj		  string_append (declp, "=");
4665de4a1d01951937632098a6cda45859afa587a06fsewardj		  break;
4666de4a1d01951937632098a6cda45859afa587a06fsewardj		}
4667de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
4668de4a1d01951937632098a6cda45859afa587a06fsewardj	}
4669de4a1d01951937632098a6cda45859afa587a06fsewardj      else
4670de4a1d01951937632098a6cda45859afa587a06fsewardj	{
46714f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	  for (i = 0; i < ARRAY_SIZE (optable); i++)
4672de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
4673de4a1d01951937632098a6cda45859afa587a06fsewardj	      int len = declp->p - declp->b - 3;
4674de4a1d01951937632098a6cda45859afa587a06fsewardj	      if ((int) strlen (optable[i].in) == len
4675de4a1d01951937632098a6cda45859afa587a06fsewardj		  && memcmp (optable[i].in, declp->b + 3, len) == 0)
4676de4a1d01951937632098a6cda45859afa587a06fsewardj		{
4677de4a1d01951937632098a6cda45859afa587a06fsewardj		  string_clear (declp);
4678de4a1d01951937632098a6cda45859afa587a06fsewardj		  string_append (declp, "operator");
4679de4a1d01951937632098a6cda45859afa587a06fsewardj		  string_append (declp, optable[i].out);
4680de4a1d01951937632098a6cda45859afa587a06fsewardj		  break;
4681de4a1d01951937632098a6cda45859afa587a06fsewardj		}
4682de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
4683de4a1d01951937632098a6cda45859afa587a06fsewardj	}
4684de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4685de4a1d01951937632098a6cda45859afa587a06fsewardj  else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0
4686de4a1d01951937632098a6cda45859afa587a06fsewardj	   && strchr (cplus_markers, declp->b[4]) != NULL)
4687de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4688de4a1d01951937632098a6cda45859afa587a06fsewardj      /* type conversion operator */
4689de4a1d01951937632098a6cda45859afa587a06fsewardj      tem = declp->b + 5;
4690de4a1d01951937632098a6cda45859afa587a06fsewardj      if (do_type (work, &tem, &type))
4691de4a1d01951937632098a6cda45859afa587a06fsewardj	{
4692de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_clear (declp);
4693de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_append (declp, "operator ");
4694de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_appends (declp, &type);
4695de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_delete (&type);
4696de4a1d01951937632098a6cda45859afa587a06fsewardj	}
4697de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4698de4a1d01951937632098a6cda45859afa587a06fsewardj  else if (declp->b[0] == '_' && declp->b[1] == '_'
4699de4a1d01951937632098a6cda45859afa587a06fsewardj	   && declp->b[2] == 'o' && declp->b[3] == 'p')
4700de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4701de4a1d01951937632098a6cda45859afa587a06fsewardj      /* ANSI.  */
4702de4a1d01951937632098a6cda45859afa587a06fsewardj      /* type conversion operator.  */
4703de4a1d01951937632098a6cda45859afa587a06fsewardj      tem = declp->b + 4;
4704de4a1d01951937632098a6cda45859afa587a06fsewardj      if (do_type (work, &tem, &type))
4705de4a1d01951937632098a6cda45859afa587a06fsewardj	{
4706de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_clear (declp);
4707de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_append (declp, "operator ");
4708de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_appends (declp, &type);
4709de4a1d01951937632098a6cda45859afa587a06fsewardj	  string_delete (&type);
4710de4a1d01951937632098a6cda45859afa587a06fsewardj	}
4711de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4712de4a1d01951937632098a6cda45859afa587a06fsewardj  else if (declp->b[0] == '_' && declp->b[1] == '_'
4713de4a1d01951937632098a6cda45859afa587a06fsewardj	   && ISLOWER((unsigned char)declp->b[2])
4714de4a1d01951937632098a6cda45859afa587a06fsewardj	   && ISLOWER((unsigned char)declp->b[3]))
4715de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4716de4a1d01951937632098a6cda45859afa587a06fsewardj      if (declp->b[4] == '\0')
4717de4a1d01951937632098a6cda45859afa587a06fsewardj	{
4718de4a1d01951937632098a6cda45859afa587a06fsewardj	  /* Operator.  */
47194f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	  for (i = 0; i < ARRAY_SIZE (optable); i++)
4720de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
4721de4a1d01951937632098a6cda45859afa587a06fsewardj	      if (strlen (optable[i].in) == 2
4722de4a1d01951937632098a6cda45859afa587a06fsewardj		  && memcmp (optable[i].in, declp->b + 2, 2) == 0)
4723de4a1d01951937632098a6cda45859afa587a06fsewardj		{
4724de4a1d01951937632098a6cda45859afa587a06fsewardj		  string_clear (declp);
4725de4a1d01951937632098a6cda45859afa587a06fsewardj		  string_append (declp, "operator");
4726de4a1d01951937632098a6cda45859afa587a06fsewardj		  string_append (declp, optable[i].out);
4727de4a1d01951937632098a6cda45859afa587a06fsewardj		  break;
4728de4a1d01951937632098a6cda45859afa587a06fsewardj		}
4729de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
4730de4a1d01951937632098a6cda45859afa587a06fsewardj	}
4731695baafe15fd28cc09b19af4b79a6417be76a15dsewardj
4732695baafe15fd28cc09b19af4b79a6417be76a15dsewardj      /* BEGIN hack inserted 20050403 by JRS to deal with apparently
4733695baafe15fd28cc09b19af4b79a6417be76a15dsewardj         non-cfront compliant new[]/delete[] manglings generated by
4734695baafe15fd28cc09b19af4b79a6417be76a15dsewardj         the Portland Group's C++ compiler. */
4735695baafe15fd28cc09b19af4b79a6417be76a15dsewardj      else
4736695baafe15fd28cc09b19af4b79a6417be76a15dsewardj      if (strcmp (declp -> b, "__nwa") == 0) {
4737695baafe15fd28cc09b19af4b79a6417be76a15dsewardj         string_clear (declp);
4738695baafe15fd28cc09b19af4b79a6417be76a15dsewardj         string_append (declp, "operator new[]");
4739695baafe15fd28cc09b19af4b79a6417be76a15dsewardj      }
4740695baafe15fd28cc09b19af4b79a6417be76a15dsewardj      else
4741695baafe15fd28cc09b19af4b79a6417be76a15dsewardj      if (strcmp (declp -> b, "__dla") == 0) {
4742695baafe15fd28cc09b19af4b79a6417be76a15dsewardj         string_clear (declp);
4743695baafe15fd28cc09b19af4b79a6417be76a15dsewardj         string_append (declp, "operator delete[]");
4744695baafe15fd28cc09b19af4b79a6417be76a15dsewardj      }
4745695baafe15fd28cc09b19af4b79a6417be76a15dsewardj      /* END hack */
4746695baafe15fd28cc09b19af4b79a6417be76a15dsewardj
4747de4a1d01951937632098a6cda45859afa587a06fsewardj      else
4748de4a1d01951937632098a6cda45859afa587a06fsewardj	{
4749de4a1d01951937632098a6cda45859afa587a06fsewardj	  if (declp->b[2] == 'a' && declp->b[5] == '\0')
4750de4a1d01951937632098a6cda45859afa587a06fsewardj	    {
4751de4a1d01951937632098a6cda45859afa587a06fsewardj	      /* Assignment.  */
47524f2683ace412ca2c8266f2dd860dee4461df3cafsewardj	      for (i = 0; i < ARRAY_SIZE (optable); i++)
4753de4a1d01951937632098a6cda45859afa587a06fsewardj		{
4754de4a1d01951937632098a6cda45859afa587a06fsewardj		  if (strlen (optable[i].in) == 3
4755de4a1d01951937632098a6cda45859afa587a06fsewardj		      && memcmp (optable[i].in, declp->b + 2, 3) == 0)
4756de4a1d01951937632098a6cda45859afa587a06fsewardj		    {
4757de4a1d01951937632098a6cda45859afa587a06fsewardj		      string_clear (declp);
4758de4a1d01951937632098a6cda45859afa587a06fsewardj		      string_append (declp, "operator");
4759de4a1d01951937632098a6cda45859afa587a06fsewardj		      string_append (declp, optable[i].out);
4760de4a1d01951937632098a6cda45859afa587a06fsewardj		      break;
4761de4a1d01951937632098a6cda45859afa587a06fsewardj		    }
4762de4a1d01951937632098a6cda45859afa587a06fsewardj		}
4763de4a1d01951937632098a6cda45859afa587a06fsewardj	    }
4764de4a1d01951937632098a6cda45859afa587a06fsewardj	}
4765de4a1d01951937632098a6cda45859afa587a06fsewardj    }
47664f2683ace412ca2c8266f2dd860dee4461df3cafsewardj
47674f2683ace412ca2c8266f2dd860dee4461df3cafsewardj  /* If a function name was obtained but it's not valid, we were not
47684f2683ace412ca2c8266f2dd860dee4461df3cafsewardj     successful.  */
47694f2683ace412ca2c8266f2dd860dee4461df3cafsewardj  if (LEN_STRING (declp) == 1 && declp->b[0] == '.')
47704f2683ace412ca2c8266f2dd860dee4461df3cafsewardj    return 0;
47714f2683ace412ca2c8266f2dd860dee4461df3cafsewardj  else
47724f2683ace412ca2c8266f2dd860dee4461df3cafsewardj    return 1;
4773de4a1d01951937632098a6cda45859afa587a06fsewardj}
4774de4a1d01951937632098a6cda45859afa587a06fsewardj
4775de4a1d01951937632098a6cda45859afa587a06fsewardj/* a mini string-handling package */
4776de4a1d01951937632098a6cda45859afa587a06fsewardj
4777de4a1d01951937632098a6cda45859afa587a06fsewardjstatic void
47784f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstring_need (string *s, int n)
4779de4a1d01951937632098a6cda45859afa587a06fsewardj{
4780de4a1d01951937632098a6cda45859afa587a06fsewardj  int tem;
4781de4a1d01951937632098a6cda45859afa587a06fsewardj
4782de4a1d01951937632098a6cda45859afa587a06fsewardj  if (s->b == NULL)
4783de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4784de4a1d01951937632098a6cda45859afa587a06fsewardj      if (n < 32)
4785de4a1d01951937632098a6cda45859afa587a06fsewardj	{
4786de4a1d01951937632098a6cda45859afa587a06fsewardj	  n = 32;
4787de4a1d01951937632098a6cda45859afa587a06fsewardj	}
47884f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      s->p = s->b = XNEWVEC (char, n);
4789de4a1d01951937632098a6cda45859afa587a06fsewardj      s->e = s->b + n;
4790de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4791de4a1d01951937632098a6cda45859afa587a06fsewardj  else if (s->e - s->p < n)
4792de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4793de4a1d01951937632098a6cda45859afa587a06fsewardj      tem = s->p - s->b;
4794de4a1d01951937632098a6cda45859afa587a06fsewardj      n += tem;
4795de4a1d01951937632098a6cda45859afa587a06fsewardj      n *= 2;
47964f2683ace412ca2c8266f2dd860dee4461df3cafsewardj      s->b = XRESIZEVEC (char, s->b, n);
4797de4a1d01951937632098a6cda45859afa587a06fsewardj      s->p = s->b + tem;
4798de4a1d01951937632098a6cda45859afa587a06fsewardj      s->e = s->b + n;
4799de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4800de4a1d01951937632098a6cda45859afa587a06fsewardj}
4801de4a1d01951937632098a6cda45859afa587a06fsewardj
4802de4a1d01951937632098a6cda45859afa587a06fsewardjstatic void
48034f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstring_delete (string *s)
4804de4a1d01951937632098a6cda45859afa587a06fsewardj{
4805de4a1d01951937632098a6cda45859afa587a06fsewardj  if (s->b != NULL)
4806de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4807de4a1d01951937632098a6cda45859afa587a06fsewardj      free (s->b);
4808de4a1d01951937632098a6cda45859afa587a06fsewardj      s->b = s->e = s->p = NULL;
4809de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4810de4a1d01951937632098a6cda45859afa587a06fsewardj}
4811de4a1d01951937632098a6cda45859afa587a06fsewardj
4812de4a1d01951937632098a6cda45859afa587a06fsewardjstatic void
48134f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstring_init (string *s)
4814de4a1d01951937632098a6cda45859afa587a06fsewardj{
4815de4a1d01951937632098a6cda45859afa587a06fsewardj  s->b = s->p = s->e = NULL;
4816de4a1d01951937632098a6cda45859afa587a06fsewardj}
4817de4a1d01951937632098a6cda45859afa587a06fsewardj
4818de4a1d01951937632098a6cda45859afa587a06fsewardjstatic void
48194f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstring_clear (string *s)
4820de4a1d01951937632098a6cda45859afa587a06fsewardj{
4821de4a1d01951937632098a6cda45859afa587a06fsewardj  s->p = s->b;
4822de4a1d01951937632098a6cda45859afa587a06fsewardj}
4823de4a1d01951937632098a6cda45859afa587a06fsewardj
4824de4a1d01951937632098a6cda45859afa587a06fsewardj#if 0
4825de4a1d01951937632098a6cda45859afa587a06fsewardj
4826de4a1d01951937632098a6cda45859afa587a06fsewardjstatic int
48274f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstring_empty (string *s)
4828de4a1d01951937632098a6cda45859afa587a06fsewardj{
4829de4a1d01951937632098a6cda45859afa587a06fsewardj  return (s->b == s->p);
4830de4a1d01951937632098a6cda45859afa587a06fsewardj}
4831de4a1d01951937632098a6cda45859afa587a06fsewardj
4832de4a1d01951937632098a6cda45859afa587a06fsewardj#endif
4833de4a1d01951937632098a6cda45859afa587a06fsewardj
4834de4a1d01951937632098a6cda45859afa587a06fsewardjstatic void
48354f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstring_append (string *p, const char *s)
4836de4a1d01951937632098a6cda45859afa587a06fsewardj{
4837de4a1d01951937632098a6cda45859afa587a06fsewardj  int n;
4838de4a1d01951937632098a6cda45859afa587a06fsewardj  if (s == NULL || *s == '\0')
4839de4a1d01951937632098a6cda45859afa587a06fsewardj    return;
4840de4a1d01951937632098a6cda45859afa587a06fsewardj  n = strlen (s);
4841de4a1d01951937632098a6cda45859afa587a06fsewardj  string_need (p, n);
4842de4a1d01951937632098a6cda45859afa587a06fsewardj  memcpy (p->p, s, n);
4843de4a1d01951937632098a6cda45859afa587a06fsewardj  p->p += n;
4844de4a1d01951937632098a6cda45859afa587a06fsewardj}
4845de4a1d01951937632098a6cda45859afa587a06fsewardj
4846de4a1d01951937632098a6cda45859afa587a06fsewardjstatic void
48474f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstring_appends (string *p, string *s)
4848de4a1d01951937632098a6cda45859afa587a06fsewardj{
4849de4a1d01951937632098a6cda45859afa587a06fsewardj  int n;
4850de4a1d01951937632098a6cda45859afa587a06fsewardj
4851de4a1d01951937632098a6cda45859afa587a06fsewardj  if (s->b != s->p)
4852de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4853de4a1d01951937632098a6cda45859afa587a06fsewardj      n = s->p - s->b;
4854de4a1d01951937632098a6cda45859afa587a06fsewardj      string_need (p, n);
4855de4a1d01951937632098a6cda45859afa587a06fsewardj      memcpy (p->p, s->b, n);
4856de4a1d01951937632098a6cda45859afa587a06fsewardj      p->p += n;
4857de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4858de4a1d01951937632098a6cda45859afa587a06fsewardj}
4859de4a1d01951937632098a6cda45859afa587a06fsewardj
4860de4a1d01951937632098a6cda45859afa587a06fsewardjstatic void
48614f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstring_appendn (string *p, const char *s, int n)
4862de4a1d01951937632098a6cda45859afa587a06fsewardj{
4863de4a1d01951937632098a6cda45859afa587a06fsewardj  if (n != 0)
4864de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4865de4a1d01951937632098a6cda45859afa587a06fsewardj      string_need (p, n);
4866de4a1d01951937632098a6cda45859afa587a06fsewardj      memcpy (p->p, s, n);
4867de4a1d01951937632098a6cda45859afa587a06fsewardj      p->p += n;
4868de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4869de4a1d01951937632098a6cda45859afa587a06fsewardj}
4870de4a1d01951937632098a6cda45859afa587a06fsewardj
4871de4a1d01951937632098a6cda45859afa587a06fsewardjstatic void
48724f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstring_prepend (string *p, const char *s)
4873de4a1d01951937632098a6cda45859afa587a06fsewardj{
4874de4a1d01951937632098a6cda45859afa587a06fsewardj  if (s != NULL && *s != '\0')
4875de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4876de4a1d01951937632098a6cda45859afa587a06fsewardj      string_prependn (p, s, strlen (s));
4877de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4878de4a1d01951937632098a6cda45859afa587a06fsewardj}
4879de4a1d01951937632098a6cda45859afa587a06fsewardj
4880de4a1d01951937632098a6cda45859afa587a06fsewardjstatic void
48814f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstring_prepends (string *p, string *s)
4882de4a1d01951937632098a6cda45859afa587a06fsewardj{
4883de4a1d01951937632098a6cda45859afa587a06fsewardj  if (s->b != s->p)
4884de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4885de4a1d01951937632098a6cda45859afa587a06fsewardj      string_prependn (p, s->b, s->p - s->b);
4886de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4887de4a1d01951937632098a6cda45859afa587a06fsewardj}
4888de4a1d01951937632098a6cda45859afa587a06fsewardj
4889de4a1d01951937632098a6cda45859afa587a06fsewardjstatic void
48904f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstring_prependn (string *p, const char *s, int n)
4891de4a1d01951937632098a6cda45859afa587a06fsewardj{
4892de4a1d01951937632098a6cda45859afa587a06fsewardj  char *q;
4893de4a1d01951937632098a6cda45859afa587a06fsewardj
4894de4a1d01951937632098a6cda45859afa587a06fsewardj  if (n != 0)
4895de4a1d01951937632098a6cda45859afa587a06fsewardj    {
4896de4a1d01951937632098a6cda45859afa587a06fsewardj      string_need (p, n);
4897de4a1d01951937632098a6cda45859afa587a06fsewardj      for (q = p->p - 1; q >= p->b; q--)
4898de4a1d01951937632098a6cda45859afa587a06fsewardj	{
4899de4a1d01951937632098a6cda45859afa587a06fsewardj	  q[n] = q[0];
4900de4a1d01951937632098a6cda45859afa587a06fsewardj	}
4901de4a1d01951937632098a6cda45859afa587a06fsewardj      memcpy (p->b, s, n);
4902de4a1d01951937632098a6cda45859afa587a06fsewardj      p->p += n;
4903de4a1d01951937632098a6cda45859afa587a06fsewardj    }
4904de4a1d01951937632098a6cda45859afa587a06fsewardj}
4905de4a1d01951937632098a6cda45859afa587a06fsewardj
4906de4a1d01951937632098a6cda45859afa587a06fsewardjstatic void
49074f2683ace412ca2c8266f2dd860dee4461df3cafsewardjstring_append_template_idx (string *s, int idx)
4908de4a1d01951937632098a6cda45859afa587a06fsewardj{
4909de4a1d01951937632098a6cda45859afa587a06fsewardj  char buf[INTBUF_SIZE + 1 /* 'T' */];
4910de4a1d01951937632098a6cda45859afa587a06fsewardj  sprintf(buf, "T%d", idx);
4911de4a1d01951937632098a6cda45859afa587a06fsewardj  string_append (s, buf);
4912de4a1d01951937632098a6cda45859afa587a06fsewardj}
4913