]> git.ipfire.org Git - thirdparty/gcc.git/blame - libiberty/cplus-dem.c
libiberty: Add Rust symbol demangling.
[thirdparty/gcc.git] / libiberty / cplus-dem.c
CommitLineData
2363489c 1/* Demangler for GNU C++
2f26c11d 2 Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999,
d652f226 3 2000, 2001, 2002, 2003, 2004, 2010 Free Software Foundation, Inc.
6599da04
JM
4 Written by James Clark (jjc@jclark.uucp)
5 Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
70d5ccef 6 Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
2363489c 7
6599da04
JM
8This file is part of the libiberty library.
9Libiberty is free software; you can redistribute it and/or
10modify it under the terms of the GNU Library General Public
11License as published by the Free Software Foundation; either
12version 2 of the License, or (at your option) any later version.
13
3bf27822
MM
14In addition to the permissions in the GNU Library General Public
15License, the Free Software Foundation gives you unlimited permission
16to link the compiled version of this file into combinations with other
17programs, and to distribute those combinations without any restriction
18coming from the use of this file. (The Library Public License
19restrictions do apply in other respects; for example, they cover
20modification of the file, and distribution when not linked into a
21combined executable.)
22
6599da04
JM
23Libiberty is distributed in the hope that it will be useful,
24but WITHOUT ANY WARRANTY; without even the implied warranty of
25MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26Library General Public License for more details.
27
28You should have received a copy of the GNU Library General Public
29License along with libiberty; see the file COPYING.LIB. If
ee58dffd
NC
30not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
31Boston, MA 02110-1301, USA. */
6599da04
JM
32
33/* This file exports two functions; cplus_mangle_opname and cplus_demangle.
34
35 This file imports xmalloc and xrealloc, which are like malloc and
36 realloc except that they generate a fatal error if there is no
37 available memory. */
38
39/* This file lives in both GCC and libiberty. When making changes, please
40 try not to break either. */
41
a7825625
KG
42#ifdef HAVE_CONFIG_H
43#include "config.h"
44#endif
45
f6bbde28
ZW
46#include "safe-ctype.h"
47
9ee02b5c 48#include <sys/types.h>
6599da04
JM
49#include <string.h>
50#include <stdio.h>
51
9ee02b5c
JL
52#ifdef HAVE_STDLIB_H
53#include <stdlib.h>
a7825625 54#else
5a9340fd
SP
55void * malloc ();
56void * realloc ();
9ee02b5c
JL
57#endif
58
bdf66f77
MB
59#ifdef HAVE_LIMITS_H
60#include <limits.h>
61#endif
62#ifndef INT_MAX
63# define INT_MAX (int)(((unsigned int) ~0) >> 1) /* 0x7FFFFFFF */
64#endif
65
6599da04
JM
66#include <demangle.h>
67#undef CURRENT_DEMANGLING_STYLE
68#define CURRENT_DEMANGLING_STYLE work->options
69
9b1a92d8 70#include "libiberty.h"
6599da04 71
53504016
SG
72#define min(X,Y) (((X) < (Y)) ? (X) : (Y))
73
b60fe4a7
MM
74/* A value at least one greater than the maximum number of characters
75 that will be output when using the `%d' format with `printf'. */
76#define INTBUF_SIZE 32
77
500d7701 78extern void fancy_abort (void) ATTRIBUTE_NORETURN;
2a138827 79
6599da04
JM
80/* In order to allow a single demangler executable to demangle strings
81 using various common values of CPLUS_MARKER, as well as any specific
82 one set at compile time, we maintain a string containing all the
83 commonly used ones, and check to see if the marker we are looking for
84 is in that string. CPLUS_MARKER is usually '$' on systems where the
85 assembler can deal with that. Where the assembler can't, it's usually
86 '.' (but on many systems '.' is used for other things). We put the
87 current defined CPLUS_MARKER first (which defaults to '$'), followed
88 by the next most common value, followed by an explicit '$' in case
89 the value of CPLUS_MARKER is not '$'.
90
91 We could avoid this if we could just get g++ to tell us what the actual
92 cplus marker character is as part of the debug information, perhaps by
93 ensuring that it is the character that terminates the gcc<n>_compiled
94 marker symbol (FIXME). */
95
96#if !defined (CPLUS_MARKER)
97#define CPLUS_MARKER '$'
98#endif
99
c6e13630 100enum demangling_styles current_demangling_style = auto_demangling;
6599da04
JM
101
102static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
103
70d5ccef
DT
104static char char_str[2] = { '\000', '\000' };
105
6599da04 106void
500d7701 107set_cplus_marker_for_demangling (int ch)
6599da04
JM
108{
109 cplus_markers[0] = ch;
110}
111
9923cc56
MM
112typedef struct string /* Beware: these aren't required to be */
113{ /* '\0' terminated. */
114 char *b; /* pointer to start of string */
115 char *p; /* pointer after last character */
116 char *e; /* pointer after end of allocated space */
117} string;
118
6599da04
JM
119/* Stuff that is shared between sub-routines.
120 Using a shared structure allows cplus_demangle to be reentrant. */
121
122struct work_stuff
123{
124 int options;
125 char **typevec;
5e5199e8
AM
126 char **ktypevec;
127 char **btypevec;
128 int numk;
129 int numb;
130 int ksize;
131 int bsize;
6599da04
JM
132 int ntypes;
133 int typevec_size;
134 int constructor;
135 int destructor;
136 int static_type; /* A static member function */
2363489c 137 int temp_start; /* index in demangled to start of template args */
91063b51 138 int type_quals; /* The type qualifiers. */
9b559a27 139 int dllimported; /* Symbol imported from a PE DLL */
a3a5b5b7
MM
140 char **tmpl_argvec; /* Template function arguments. */
141 int ntmpl_args; /* The number of template function arguments. */
9923cc56
MM
142 int forgetting_types; /* Nonzero if we are not remembering the types
143 we see. */
144 string* previous_argument; /* The last function argument demangled. */
145 int nrepeats; /* The number of times to repeat the previous
146 argument. */
1841e25c
MB
147 int *proctypevec; /* Indices of currently processed remembered typevecs. */
148 int proctypevec_size;
149 int nproctypes;
6599da04
JM
150};
151
152#define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
153#define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS)
154
155static const struct optable
156{
0be6abca
KG
157 const char *const in;
158 const char *const out;
159 const int flags;
6599da04
JM
160} optable[] = {
161 {"nw", " new", DMGL_ANSI}, /* new (1.92, ansi) */
162 {"dl", " delete", DMGL_ANSI}, /* new (1.92, ansi) */
163 {"new", " new", 0}, /* old (1.91, and 1.x) */
164 {"delete", " delete", 0}, /* old (1.91, and 1.x) */
165 {"vn", " new []", DMGL_ANSI}, /* GNU, pending ansi */
166 {"vd", " delete []", DMGL_ANSI}, /* GNU, pending ansi */
167 {"as", "=", DMGL_ANSI}, /* ansi */
168 {"ne", "!=", DMGL_ANSI}, /* old, ansi */
169 {"eq", "==", DMGL_ANSI}, /* old, ansi */
170 {"ge", ">=", DMGL_ANSI}, /* old, ansi */
171 {"gt", ">", DMGL_ANSI}, /* old, ansi */
172 {"le", "<=", DMGL_ANSI}, /* old, ansi */
173 {"lt", "<", DMGL_ANSI}, /* old, ansi */
174 {"plus", "+", 0}, /* old */
175 {"pl", "+", DMGL_ANSI}, /* ansi */
176 {"apl", "+=", DMGL_ANSI}, /* ansi */
177 {"minus", "-", 0}, /* old */
178 {"mi", "-", DMGL_ANSI}, /* ansi */
179 {"ami", "-=", DMGL_ANSI}, /* ansi */
180 {"mult", "*", 0}, /* old */
181 {"ml", "*", DMGL_ANSI}, /* ansi */
182 {"amu", "*=", DMGL_ANSI}, /* ansi (ARM/Lucid) */
183 {"aml", "*=", DMGL_ANSI}, /* ansi (GNU/g++) */
184 {"convert", "+", 0}, /* old (unary +) */
185 {"negate", "-", 0}, /* old (unary -) */
186 {"trunc_mod", "%", 0}, /* old */
187 {"md", "%", DMGL_ANSI}, /* ansi */
188 {"amd", "%=", DMGL_ANSI}, /* ansi */
189 {"trunc_div", "/", 0}, /* old */
190 {"dv", "/", DMGL_ANSI}, /* ansi */
191 {"adv", "/=", DMGL_ANSI}, /* ansi */
192 {"truth_andif", "&&", 0}, /* old */
193 {"aa", "&&", DMGL_ANSI}, /* ansi */
194 {"truth_orif", "||", 0}, /* old */
195 {"oo", "||", DMGL_ANSI}, /* ansi */
196 {"truth_not", "!", 0}, /* old */
197 {"nt", "!", DMGL_ANSI}, /* ansi */
198 {"postincrement","++", 0}, /* old */
199 {"pp", "++", DMGL_ANSI}, /* ansi */
200 {"postdecrement","--", 0}, /* old */
201 {"mm", "--", DMGL_ANSI}, /* ansi */
202 {"bit_ior", "|", 0}, /* old */
203 {"or", "|", DMGL_ANSI}, /* ansi */
204 {"aor", "|=", DMGL_ANSI}, /* ansi */
205 {"bit_xor", "^", 0}, /* old */
206 {"er", "^", DMGL_ANSI}, /* ansi */
207 {"aer", "^=", DMGL_ANSI}, /* ansi */
208 {"bit_and", "&", 0}, /* old */
209 {"ad", "&", DMGL_ANSI}, /* ansi */
210 {"aad", "&=", DMGL_ANSI}, /* ansi */
211 {"bit_not", "~", 0}, /* old */
212 {"co", "~", DMGL_ANSI}, /* ansi */
213 {"call", "()", 0}, /* old */
214 {"cl", "()", DMGL_ANSI}, /* ansi */
215 {"alshift", "<<", 0}, /* old */
216 {"ls", "<<", DMGL_ANSI}, /* ansi */
217 {"als", "<<=", DMGL_ANSI}, /* ansi */
218 {"arshift", ">>", 0}, /* old */
219 {"rs", ">>", DMGL_ANSI}, /* ansi */
220 {"ars", ">>=", DMGL_ANSI}, /* ansi */
221 {"component", "->", 0}, /* old */
222 {"pt", "->", DMGL_ANSI}, /* ansi; Lucid C++ form */
223 {"rf", "->", DMGL_ANSI}, /* ansi; ARM/GNU form */
224 {"indirect", "*", 0}, /* old */
225 {"method_call", "->()", 0}, /* old */
226 {"addr", "&", 0}, /* old (unary &) */
227 {"array", "[]", 0}, /* old */
228 {"vc", "[]", DMGL_ANSI}, /* ansi */
229 {"compound", ", ", 0}, /* old */
230 {"cm", ", ", DMGL_ANSI}, /* ansi */
231 {"cond", "?:", 0}, /* old */
232 {"cn", "?:", DMGL_ANSI}, /* pseudo-ansi */
233 {"max", ">?", 0}, /* old */
234 {"mx", ">?", DMGL_ANSI}, /* pseudo-ansi */
235 {"min", "<?", 0}, /* old */
236 {"mn", "<?", DMGL_ANSI}, /* pseudo-ansi */
237 {"nop", "", 0}, /* old (for operator=) */
f9c85454
MM
238 {"rm", "->*", DMGL_ANSI}, /* ansi */
239 {"sz", "sizeof ", DMGL_ANSI} /* pseudo-ansi */
6599da04
JM
240};
241
4d17a06f
MM
242/* These values are used to indicate the various type varieties.
243 They are all non-zero so that they can be used as `success'
244 values. */
2363489c
UD
245typedef enum type_kind_t
246{
4d17a06f
MM
247 tk_none,
248 tk_pointer,
ec2288ff 249 tk_reference,
9b27f113 250 tk_rvalue_reference,
2363489c 251 tk_integral,
4d17a06f 252 tk_bool,
2363489c 253 tk_char,
4d17a06f
MM
254 tk_real
255} type_kind_t;
2363489c 256
0be6abca 257const struct demangler_engine libiberty_demanglers[] =
24eaa47a 258{
d06ba3c7
RH
259 {
260 NO_DEMANGLING_STYLE_STRING,
261 no_demangling,
262 "Demangling disabled"
263 }
264 ,
24eaa47a
KB
265 {
266 AUTO_DEMANGLING_STYLE_STRING,
267 auto_demangling,
268 "Automatic selection based on executable"
269 }
270 ,
271 {
272 GNU_DEMANGLING_STYLE_STRING,
273 gnu_demangling,
274 "GNU (g++) style demangling"
275 }
276 ,
277 {
278 LUCID_DEMANGLING_STYLE_STRING,
279 lucid_demangling,
280 "Lucid (lcc) style demangling"
281 }
282 ,
283 {
284 ARM_DEMANGLING_STYLE_STRING,
285 arm_demangling,
286 "ARM style demangling"
287 }
288 ,
289 {
290 HP_DEMANGLING_STYLE_STRING,
291 hp_demangling,
292 "HP (aCC) style demangling"
293 }
294 ,
295 {
296 EDG_DEMANGLING_STYLE_STRING,
297 edg_demangling,
298 "EDG style demangling"
299 }
300 ,
69afa80d 301 {
c6e13630
JM
302 GNU_V3_DEMANGLING_STYLE_STRING,
303 gnu_v3_demangling,
304 "GNU (g++) V3 ABI-style demangling"
69afa80d
AS
305 }
306 ,
61ab980a
KB
307 {
308 JAVA_DEMANGLING_STYLE_STRING,
309 java_demangling,
310 "Java style demangling"
311 }
312 ,
313 {
314 GNAT_DEMANGLING_STYLE_STRING,
315 gnat_demangling,
316 "GNAT style demangling"
317 }
318 ,
43b1b9ed
IB
319 {
320 DLANG_DEMANGLING_STYLE_STRING,
321 dlang_demangling,
322 "DLANG style demangling"
323 }
324 ,
10d48c59
DT
325 {
326 RUST_DEMANGLING_STYLE_STRING,
327 rust_demangling,
328 "Rust style demangling"
329 }
330 ,
24eaa47a
KB
331 {
332 NULL, unknown_demangling, NULL
333 }
334};
335
6599da04 336#define STRING_EMPTY(str) ((str) -> b == (str) -> p)
6599da04
JM
337#define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
338 string_append(str, " ");}
5e5199e8 339#define LEN_STRING(str) ( (STRING_EMPTY(str))?0:((str)->p - (str)->b))
6599da04 340
9923cc56 341/* The scope separator appropriate for the language being demangled. */
3510075c
JL
342
343#define SCOPE_STRING(work) ((work->options & DMGL_JAVA) ? "." : "::")
9923cc56 344
6599da04
JM
345#define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */
346#define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */
347
348/* Prototypes for local functions */
349
500d7701 350static void delete_work_stuff (struct work_stuff *);
3388651c 351
500d7701 352static void delete_non_B_K_work_stuff (struct work_stuff *);
3388651c 353
500d7701 354static char *mop_up (struct work_stuff *, string *, int);
6599da04 355
500d7701 356static void squangle_mop_up (struct work_stuff *);
5e5199e8 357
500d7701 358static void work_stuff_copy_to_from (struct work_stuff *, struct work_stuff *);
3388651c 359
6599da04
JM
360#if 0
361static int
500d7701 362demangle_method_args (struct work_stuff *, const char **, string *);
6599da04
JM
363#endif
364
5e5199e8 365static char *
500d7701 366internal_cplus_demangle (struct work_stuff *, const char *);
5e5199e8 367
9ee02b5c 368static int
500d7701
GDR
369demangle_template_template_parm (struct work_stuff *work,
370 const char **, string *);
9ee02b5c 371
6599da04 372static int
500d7701
GDR
373demangle_template (struct work_stuff *work, const char **, string *,
374 string *, int, int);
6599da04
JM
375
376static int
500d7701
GDR
377arm_pt (struct work_stuff *, const char *, int, const char **,
378 const char **);
6599da04 379
6599da04 380static int
500d7701 381demangle_class_name (struct work_stuff *, const char **, string *);
6599da04
JM
382
383static int
500d7701
GDR
384demangle_qualified (struct work_stuff *, const char **, string *,
385 int, int);
6599da04 386
500d7701 387static int demangle_class (struct work_stuff *, const char **, string *);
6599da04 388
500d7701 389static int demangle_fund_type (struct work_stuff *, const char **, string *);
6599da04 390
500d7701 391static int demangle_signature (struct work_stuff *, const char **, string *);
6599da04 392
500d7701 393static int demangle_prefix (struct work_stuff *, const char **, string *);
6599da04 394
500d7701 395static int gnu_special (struct work_stuff *, const char **, string *);
6599da04 396
500d7701 397static int arm_special (const char **, string *);
6599da04 398
500d7701 399static void string_need (string *, int);
6599da04 400
500d7701 401static void string_delete (string *);
6599da04
JM
402
403static void
500d7701 404string_init (string *);
6599da04 405
500d7701 406static void string_clear (string *);
6599da04
JM
407
408#if 0
500d7701 409static int string_empty (string *);
6599da04
JM
410#endif
411
500d7701 412static void string_append (string *, const char *);
6599da04 413
500d7701 414static void string_appends (string *, string *);
6599da04 415
500d7701 416static void string_appendn (string *, const char *, int);
6599da04 417
500d7701 418static void string_prepend (string *, const char *);
6599da04 419
500d7701 420static void string_prependn (string *, const char *, int);
6599da04 421
500d7701 422static void string_append_template_idx (string *, int);
b60fe4a7 423
500d7701 424static int get_count (const char **, int *);
6599da04 425
500d7701 426static int consume_count (const char **);
6599da04 427
500d7701 428static int consume_count_with_underscores (const char**);
a3a5b5b7 429
500d7701 430static int demangle_args (struct work_stuff *, const char **, string *);
6599da04 431
500d7701 432static int demangle_nested_args (struct work_stuff*, const char**, string*);
9923cc56 433
500d7701 434static int do_type (struct work_stuff *, const char **, string *);
6599da04 435
500d7701 436static int do_arg (struct work_stuff *, const char **, string *);
6599da04 437
62b445b3 438static int
500d7701
GDR
439demangle_function_name (struct work_stuff *, const char **, string *,
440 const char *);
6599da04 441
3388651c 442static int
500d7701
GDR
443iterate_demangle_function (struct work_stuff *,
444 const char **, string *, const char *);
3388651c 445
500d7701 446static void remember_type (struct work_stuff *, const char *, int);
6599da04 447
1841e25c
MB
448static void push_processed_type (struct work_stuff *, int);
449
450static void pop_processed_type (struct work_stuff *);
451
500d7701 452static void remember_Btype (struct work_stuff *, const char *, int, int);
5e5199e8 453
500d7701 454static int register_Btype (struct work_stuff *);
5e5199e8 455
500d7701 456static void remember_Ktype (struct work_stuff *, const char *, int);
5e5199e8 457
500d7701 458static void forget_types (struct work_stuff *);
6599da04 459
500d7701 460static void forget_B_and_K_types (struct work_stuff *);
5e5199e8 461
500d7701 462static void string_prepends (string *, string *);
6599da04 463
2363489c 464static int
500d7701
GDR
465demangle_template_value_parm (struct work_stuff*, const char**,
466 string*, type_kind_t);
f9c85454 467
2363489c 468static int
500d7701 469do_hpacc_template_const_value (struct work_stuff *, const char **, string *);
70d5ccef 470
2363489c 471static int
500d7701 472do_hpacc_template_literal (struct work_stuff *, const char **, string *);
70d5ccef 473
500d7701 474static int snarf_numeric_literal (const char **, string *);
70d5ccef 475
91063b51
MM
476/* There is a TYPE_QUAL value for each type qualifier. They can be
477 combined by bitwise-or to form the complete set of qualifiers for a
478 type. */
479
480#define TYPE_UNQUALIFIED 0x0
481#define TYPE_QUAL_CONST 0x1
482#define TYPE_QUAL_VOLATILE 0x2
483#define TYPE_QUAL_RESTRICT 0x4
484
500d7701 485static int code_for_qualifier (int);
91063b51 486
500d7701 487static const char* qualifier_string (int);
91063b51 488
500d7701 489static const char* demangle_qualifier (int);
91063b51 490
500d7701
GDR
491static int demangle_expression (struct work_stuff *, const char **, string *,
492 type_kind_t);
b60fe4a7 493
2a138827 494static int
500d7701 495demangle_integral_value (struct work_stuff *, const char **, string *);
2a138827 496
b60fe4a7 497static int
500d7701 498demangle_real_value (struct work_stuff *, const char **, string *);
b60fe4a7 499
2a138827 500static void
500d7701 501demangle_arm_hp_template (struct work_stuff *, const char **, int, string *);
2a138827
KG
502
503static void
500d7701 504recursively_demangle (struct work_stuff *, const char **, string *, int);
2a138827 505
9d229989
JB
506/* Translate count to integer, consuming tokens in the process.
507 Conversion terminates on the first non-digit character.
508
509 Trying to consume something that isn't a count results in no
510 consumption of input and a return of -1.
511
512 Overflow consumes the rest of the digits, and returns -1. */
6599da04
JM
513
514static int
500d7701 515consume_count (const char **type)
6599da04 516{
9d229989
JB
517 int count = 0;
518
f6bbde28 519 if (! ISDIGIT ((unsigned char)**type))
9d229989 520 return -1;
6599da04 521
f6bbde28 522 while (ISDIGIT ((unsigned char)**type))
6599da04
JM
523 {
524 count *= 10;
9d229989
JB
525
526 /* Check for overflow.
527 We assume that count is represented using two's-complement;
528 no power of two is divisible by ten, so if an overflow occurs
529 when multiplying by ten, the result will not be a multiple of
530 ten. */
531 if ((count % 10) != 0)
4cc48683 532 {
f6bbde28 533 while (ISDIGIT ((unsigned char) **type))
9d229989
JB
534 (*type)++;
535 return -1;
4cc48683 536 }
9d229989
JB
537
538 count += **type - '0';
6599da04
JM
539 (*type)++;
540 }
9d229989 541
63de15a4
CR
542 if (count < 0)
543 count = -1;
544
6599da04
JM
545 return (count);
546}
547
a3a5b5b7 548
9ee02b5c 549/* Like consume_count, but for counts that are preceded and followed
a3a5b5b7
MM
550 by '_' if they are greater than 10. Also, -1 is returned for
551 failure, since 0 can be a valid value. */
552
553static int
500d7701 554consume_count_with_underscores (const char **mangled)
a3a5b5b7
MM
555{
556 int idx;
557
558 if (**mangled == '_')
559 {
560 (*mangled)++;
f6bbde28 561 if (!ISDIGIT ((unsigned char)**mangled))
a3a5b5b7
MM
562 return -1;
563
564 idx = consume_count (mangled);
565 if (**mangled != '_')
566 /* The trailing underscore was missing. */
567 return -1;
2363489c 568
a3a5b5b7
MM
569 (*mangled)++;
570 }
571 else
572 {
573 if (**mangled < '0' || **mangled > '9')
574 return -1;
2363489c 575
a3a5b5b7
MM
576 idx = **mangled - '0';
577 (*mangled)++;
578 }
579
580 return idx;
581}
582
91063b51
MM
583/* C is the code for a type-qualifier. Return the TYPE_QUAL
584 corresponding to this qualifier. */
585
586static int
500d7701 587code_for_qualifier (int c)
91063b51 588{
2363489c 589 switch (c)
91063b51
MM
590 {
591 case 'C':
592 return TYPE_QUAL_CONST;
593
594 case 'V':
595 return TYPE_QUAL_VOLATILE;
2363489c 596
91063b51
MM
597 case 'u':
598 return TYPE_QUAL_RESTRICT;
599
600 default:
601 break;
602 }
603
604 /* C was an invalid qualifier. */
605 abort ();
606}
607
608/* Return the string corresponding to the qualifiers given by
609 TYPE_QUALS. */
610
611static const char*
500d7701 612qualifier_string (int type_quals)
91063b51
MM
613{
614 switch (type_quals)
615 {
616 case TYPE_UNQUALIFIED:
617 return "";
618
619 case TYPE_QUAL_CONST:
620 return "const";
621
622 case TYPE_QUAL_VOLATILE:
623 return "volatile";
624
625 case TYPE_QUAL_RESTRICT:
626 return "__restrict";
627
628 case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE:
629 return "const volatile";
630
631 case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT:
632 return "const __restrict";
633
634 case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
635 return "volatile __restrict";
636
637 case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
638 return "const volatile __restrict";
639
640 default:
641 break;
642 }
643
644 /* TYPE_QUALS was an invalid qualifier set. */
645 abort ();
646}
647
648/* C is the code for a type-qualifier. Return the string
649 corresponding to this qualifier. This function should only be
650 called with a valid qualifier code. */
651
652static const char*
500d7701 653demangle_qualifier (int c)
91063b51
MM
654{
655 return qualifier_string (code_for_qualifier (c));
656}
657
6599da04 658int
500d7701 659cplus_demangle_opname (const char *opname, char *result, int options)
6599da04 660{
d6f4ec51 661 int len, len1, ret;
6599da04
JM
662 string type;
663 struct work_stuff work[1];
664 const char *tem;
665
666 len = strlen(opname);
667 result[0] = '\0';
668 ret = 0;
63586755 669 memset ((char *) work, 0, sizeof (work));
6599da04 670 work->options = options;
2363489c 671
6599da04
JM
672 if (opname[0] == '_' && opname[1] == '_'
673 && opname[2] == 'o' && opname[3] == 'p')
674 {
675 /* ANSI. */
676 /* type conversion operator. */
677 tem = opname + 4;
678 if (do_type (work, &tem, &type))
679 {
680 strcat (result, "operator ");
681 strncat (result, type.b, type.p - type.b);
682 string_delete (&type);
683 ret = 1;
684 }
685 }
686 else if (opname[0] == '_' && opname[1] == '_'
f6bbde28
ZW
687 && ISLOWER((unsigned char)opname[2])
688 && ISLOWER((unsigned char)opname[3]))
6599da04
JM
689 {
690 if (opname[4] == '\0')
691 {
692 /* Operator. */
d6f4ec51 693 size_t i;
2f26c11d 694 for (i = 0; i < ARRAY_SIZE (optable); i++)
6599da04
JM
695 {
696 if (strlen (optable[i].in) == 2
697 && memcmp (optable[i].in, opname + 2, 2) == 0)
698 {
699 strcat (result, "operator");
700 strcat (result, optable[i].out);
701 ret = 1;
702 break;
703 }
704 }
705 }
706 else
707 {
708 if (opname[2] == 'a' && opname[5] == '\0')
709 {
710 /* Assignment. */
d6f4ec51 711 size_t i;
2f26c11d 712 for (i = 0; i < ARRAY_SIZE (optable); i++)
6599da04
JM
713 {
714 if (strlen (optable[i].in) == 3
715 && memcmp (optable[i].in, opname + 2, 3) == 0)
716 {
717 strcat (result, "operator");
718 strcat (result, optable[i].out);
719 ret = 1;
720 break;
2363489c 721 }
6599da04
JM
722 }
723 }
724 }
725 }
2363489c 726 else if (len >= 3
6599da04
JM
727 && opname[0] == 'o'
728 && opname[1] == 'p'
729 && strchr (cplus_markers, opname[2]) != NULL)
730 {
731 /* see if it's an assignment expression */
732 if (len >= 10 /* op$assign_ */
733 && memcmp (opname + 3, "assign_", 7) == 0)
734 {
d6f4ec51 735 size_t i;
2f26c11d 736 for (i = 0; i < ARRAY_SIZE (optable); i++)
6599da04
JM
737 {
738 len1 = len - 10;
91e0f659 739 if ((int) strlen (optable[i].in) == len1
6599da04
JM
740 && memcmp (optable[i].in, opname + 10, len1) == 0)
741 {
742 strcat (result, "operator");
743 strcat (result, optable[i].out);
744 strcat (result, "=");
745 ret = 1;
746 break;
747 }
748 }
749 }
750 else
751 {
d6f4ec51 752 size_t i;
2f26c11d 753 for (i = 0; i < ARRAY_SIZE (optable); i++)
6599da04
JM
754 {
755 len1 = len - 3;
2363489c 756 if ((int) strlen (optable[i].in) == len1
6599da04
JM
757 && memcmp (optable[i].in, opname + 3, len1) == 0)
758 {
759 strcat (result, "operator");
760 strcat (result, optable[i].out);
761 ret = 1;
762 break;
763 }
764 }
765 }
766 }
767 else if (len >= 5 && memcmp (opname, "type", 4) == 0
768 && strchr (cplus_markers, opname[4]) != NULL)
769 {
770 /* type conversion operator */
771 tem = opname + 5;
772 if (do_type (work, &tem, &type))
773 {
774 strcat (result, "operator ");
775 strncat (result, type.b, type.p - type.b);
776 string_delete (&type);
777 ret = 1;
778 }
779 }
5e5199e8 780 squangle_mop_up (work);
6599da04
JM
781 return ret;
782
783}
24eaa47a 784
6599da04
JM
785/* Takes operator name as e.g. "++" and returns mangled
786 operator name (e.g. "postincrement_expr"), or NULL if not found.
787
788 If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
789 if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */
790
791const char *
500d7701 792cplus_mangle_opname (const char *opname, int options)
6599da04 793{
d6f4ec51 794 size_t i;
6599da04
JM
795 int len;
796
797 len = strlen (opname);
2f26c11d 798 for (i = 0; i < ARRAY_SIZE (optable); i++)
6599da04 799 {
91e0f659 800 if ((int) strlen (optable[i].out) == len
6599da04
JM
801 && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
802 && memcmp (optable[i].out, opname, len) == 0)
803 return optable[i].in;
804 }
805 return (0);
806}
807
24eaa47a
KB
808/* Add a routine to set the demangling style to be sure it is valid and
809 allow for any demangler initialization that maybe necessary. */
810
811enum demangling_styles
500d7701 812cplus_demangle_set_style (enum demangling_styles style)
24eaa47a 813{
0be6abca 814 const struct demangler_engine *demangler = libiberty_demanglers;
24eaa47a
KB
815
816 for (; demangler->demangling_style != unknown_demangling; ++demangler)
817 if (style == demangler->demangling_style)
818 {
819 current_demangling_style = style;
820 return current_demangling_style;
821 }
822
823 return unknown_demangling;
824}
825
826/* Do string name to style translation */
827
828enum demangling_styles
500d7701 829cplus_demangle_name_to_style (const char *name)
24eaa47a 830{
0be6abca 831 const struct demangler_engine *demangler = libiberty_demanglers;
24eaa47a
KB
832
833 for (; demangler->demangling_style != unknown_demangling; ++demangler)
834 if (strcmp (name, demangler->demangling_style_name) == 0)
835 return demangler->demangling_style;
836
837 return unknown_demangling;
838}
839
6599da04
JM
840/* char *cplus_demangle (const char *mangled, int options)
841
842 If MANGLED is a mangled function name produced by GNU C++, then
5bed56d9 843 a pointer to a @code{malloc}ed string giving a C++ representation
6599da04
JM
844 of the name will be returned; otherwise NULL will be returned.
845 It is the caller's responsibility to free the string which
846 is returned.
847
848 The OPTIONS arg may contain one or more of the following bits:
849
850 DMGL_ANSI ANSI qualifiers such as `const' and `void' are
851 included.
852 DMGL_PARAMS Function parameters are included.
853
854 For example,
2363489c 855
6599da04
JM
856 cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)"
857 cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
858 cplus_demangle ("foo__1Ai", 0) => "A::foo"
859
860 cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)"
861 cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
862 cplus_demangle ("foo__1Afe", 0) => "A::foo"
863
864 Note that any leading underscores, or other such characters prepended by
865 the compilation system, are presumed to have already been stripped from
866 MANGLED. */
867
868char *
500d7701 869cplus_demangle (const char *mangled, int options)
6599da04 870{
5e5199e8
AM
871 char *ret;
872 struct work_stuff work[1];
d06ba3c7
RH
873
874 if (current_demangling_style == no_demangling)
875 return xstrdup (mangled);
876
5e5199e8 877 memset ((char *) work, 0, sizeof (work));
cf183ac2
HPN
878 work->options = options;
879 if ((work->options & DMGL_STYLE_MASK) == 0)
880 work->options |= (int) current_demangling_style & DMGL_STYLE_MASK;
5e5199e8 881
c6e13630 882 /* The V3 ABI demangling is implemented elsewhere. */
10d48c59 883 if (GNU_V3_DEMANGLING || RUST_DEMANGLING || AUTO_DEMANGLING)
c6e13630 884 {
c13db5d1 885 ret = cplus_demangle_v3 (mangled, work->options);
10d48c59
DT
886 if (GNU_V3_DEMANGLING)
887 return ret;
888
889 if (ret)
890 {
891 /* Rust symbols are GNU_V3 mangled plus some extra subtitutions.
892 The subtitutions are always smaller, so do in place changes. */
893 if (rust_is_mangled (ret))
894 rust_demangle_sym (ret);
895 else if (RUST_DEMANGLING)
896 {
897 free (ret);
898 ret = NULL;
899 }
900 }
901
902 if (ret || RUST_DEMANGLING)
c6e13630
JM
903 return ret;
904 }
69afa80d 905
3b60dd8e
BM
906 if (JAVA_DEMANGLING)
907 {
908 ret = java_demangle_v3 (mangled);
909 if (ret)
910 return ret;
911 }
912
61ab980a 913 if (GNAT_DEMANGLING)
5b40c067 914 return ada_demangle (mangled, options);
61ab980a 915
43b1b9ed
IB
916 if (DLANG_DEMANGLING)
917 {
918 ret = dlang_demangle (mangled, options);
919 if (ret)
920 return ret;
921 }
922
d6f4ec51 923 ret = internal_cplus_demangle (work, mangled);
5e5199e8
AM
924 squangle_mop_up (work);
925 return (ret);
926}
5e5199e8 927
10d48c59
DT
928char *
929rust_demangle (const char *mangled, int options)
930{
931 /* Rust symbols are GNU_V3 mangled plus some extra subtitutions. */
932 char *ret = cplus_demangle_v3 (mangled, options);
933
934 /* The Rust subtitutions are always smaller, so do in place changes. */
935 if (ret != NULL)
936 {
937 if (rust_is_mangled (ret))
938 rust_demangle_sym (ret);
939 else
940 {
941 free (ret);
942 ret = NULL;
943 }
944 }
945
946 return ret;
947}
948
5b40c067 949/* Demangle ada names. The encoding is documented in gcc/ada/exp_dbug.ads. */
2363489c 950
5b40c067 951char *
500d7701 952ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
61ab980a 953{
61ab980a
KB
954 int len0;
955 const char* p;
5b40c067 956 char *d;
a3f3eec0 957 char *demangled = NULL;
61ab980a 958
5b40c067 959 /* Discard leading _ada_, which is used for library level subprograms. */
61ab980a 960 if (strncmp (mangled, "_ada_", 5) == 0)
5b40c067
TG
961 mangled += 5;
962
963 /* All ada unit names are lower-case. */
964 if (!ISLOWER (mangled[0]))
965 goto unknown;
966
967 /* Most of the demangling will trivially remove chars. Operator names
968 may add one char but because they are always preceeded by '__' which is
a69d9775
TG
969 replaced by '.', they eventually never expand the size.
970 A few special names such as '___elabs' add a few chars (at most 7), but
971 they occur only once. */
972 len0 = strlen (mangled) + 7 + 1;
5b40c067 973 demangled = XNEWVEC (char, len0);
61ab980a 974
5b40c067
TG
975 d = demangled;
976 p = mangled;
977 while (1)
61ab980a 978 {
a69d9775 979 /* An entity names is expected. */
5b40c067
TG
980 if (ISLOWER (*p))
981 {
a69d9775 982 /* An identifier, which is always lower case. */
5b40c067
TG
983 do
984 *d++ = *p++;
985 while (ISLOWER(*p) || ISDIGIT (*p)
986 || (p[0] == '_' && (ISLOWER (p[1]) || ISDIGIT (p[1]))));
987 }
988 else if (p[0] == 'O')
989 {
a69d9775 990 /* An operator name. */
5b40c067
TG
991 static const char * const operators[][2] =
992 {{"Oabs", "abs"}, {"Oand", "and"}, {"Omod", "mod"},
993 {"Onot", "not"}, {"Oor", "or"}, {"Orem", "rem"},
994 {"Oxor", "xor"}, {"Oeq", "="}, {"One", "/="},
995 {"Olt", "<"}, {"Ole", "<="}, {"Ogt", ">"},
996 {"Oge", ">="}, {"Oadd", "+"}, {"Osubtract", "-"},
997 {"Oconcat", "&"}, {"Omultiply", "*"}, {"Odivide", "/"},
998 {"Oexpon", "**"}, {NULL, NULL}};
999 int k;
1000
a69d9775 1001 for (k = 0; operators[k][0] != NULL; k++)
5b40c067 1002 {
a69d9775
TG
1003 size_t slen = strlen (operators[k][0]);
1004 if (strncmp (p, operators[k][0], slen) == 0)
5b40c067 1005 {
a69d9775
TG
1006 p += slen;
1007 slen = strlen (operators[k][1]);
5b40c067 1008 *d++ = '"';
a69d9775
TG
1009 memcpy (d, operators[k][1], slen);
1010 d += slen;
5b40c067
TG
1011 *d++ = '"';
1012 break;
1013 }
1014 }
1015 /* Operator not found. */
a69d9775 1016 if (operators[k][0] == NULL)
5b40c067
TG
1017 goto unknown;
1018 }
61ab980a 1019 else
5b40c067
TG
1020 {
1021 /* Not a GNAT encoding. */
1022 goto unknown;
1023 }
1024
a69d9775
TG
1025 /* The name can be directly followed by some uppercase letters. */
1026 if (p[0] == 'T' && p[1] == 'K')
1027 {
1028 /* Task stuff. */
1029 if (p[2] == 'B' && p[3] == 0)
1030 {
1031 /* Subprogram for task body. */
1032 break;
1033 }
1034 else if (p[2] == '_' && p[3] == '_')
1035 {
1036 /* Inner declarations in a task. */
1037 p += 4;
1038 *d++ = '.';
1039 continue;
1040 }
1041 else
1042 goto unknown;
1043 }
1044 if (p[0] == 'E' && p[1] == 0)
1045 {
1046 /* Exception name. */
1047 goto unknown;
1048 }
1049 if ((p[0] == 'P' || p[0] == 'N') && p[1] == 0)
1050 {
1051 /* Protected type subprogram. */
1052 break;
1053 }
1054 if ((*p == 'N' || *p == 'S') && p[1] == 0)
1055 {
1056 /* Enumerated type name table. */
1057 goto unknown;
1058 }
1059 if (p[0] == 'X')
1060 {
1061 /* Body nested. */
1062 p++;
1063 while (p[0] == 'n' || p[0] == 'b')
1064 p++;
1065 }
1066 if (p[0] == 'S' && p[1] != 0 && (p[2] == '_' || p[2] == 0))
1067 {
1068 /* Stream operations. */
1069 const char *name;
1070 switch (p[1])
1071 {
1072 case 'R':
1073 name = "'Read";
1074 break;
1075 case 'W':
1076 name = "'Write";
1077 break;
1078 case 'I':
1079 name = "'Input";
1080 break;
1081 case 'O':
1082 name = "'Output";
1083 break;
1084 default:
1085 goto unknown;
1086 }
1087 p += 2;
1088 strcpy (d, name);
1089 d += strlen (name);
1090 }
1091 else if (p[0] == 'D')
1092 {
1093 /* Controlled type operation. */
1094 const char *name;
1095 switch (p[1])
1096 {
1097 case 'F':
1098 name = ".Finalize";
1099 break;
1100 case 'A':
1101 name = ".Adjust";
1102 break;
1103 default:
1104 goto unknown;
1105 }
1106 strcpy (d, name);
1107 d += strlen (name);
1108 break;
1109 }
1110
5b40c067
TG
1111 if (p[0] == '_')
1112 {
1113 /* Separator. */
1114 if (p[1] == '_')
1115 {
1116 /* Standard separator. Handled first. */
1117 p += 2;
a69d9775 1118
5b40c067
TG
1119 if (ISDIGIT (*p))
1120 {
a69d9775 1121 /* Overloading number. */
5b40c067
TG
1122 do
1123 p++;
1124 while (ISDIGIT (*p) || (p[0] == '_' && ISDIGIT (p[1])));
a69d9775
TG
1125 if (*p == 'X')
1126 {
1127 p++;
1128 while (p[0] == 'n' || p[0] == 'b')
1129 p++;
1130 }
5b40c067 1131 }
a69d9775 1132 else if (p[0] == '_' && p[1] != '_')
5b40c067 1133 {
a69d9775
TG
1134 /* Special names. */
1135 static const char * const special[][2] = {
1136 { "_elabb", "'Elab_Body" },
1137 { "_elabs", "'Elab_Spec" },
1138 { "_size", "'Size" },
1139 { "_alignment", "'Alignment" },
1140 { "_assign", ".\":=\"" },
1141 { NULL, NULL }
1142 };
1143 int k;
1144
1145 for (k = 0; special[k][0] != NULL; k++)
1146 {
1147 size_t slen = strlen (special[k][0]);
1148 if (strncmp (p, special[k][0], slen) == 0)
1149 {
1150 p += slen;
1151 slen = strlen (special[k][1]);
1152 memcpy (d, special[k][1], slen);
1153 d += slen;
1154 break;
1155 }
1156 }
1157 if (special[k][0] != NULL)
1158 break;
1159 else
1160 goto unknown;
5b40c067
TG
1161 }
1162 else
1163 {
1164 *d++ = '.';
1165 continue;
1166 }
1167 }
1168 else if (p[1] == 'B' || p[1] == 'E')
1169 {
1170 /* Entry Body or barrier Evaluation. */
1171 p += 2;
1172 while (ISDIGIT (*p))
1173 p++;
1174 if (p[0] == 's' && p[1] == 0)
1175 break;
1176 else
1177 goto unknown;
1178 }
1179 else
1180 goto unknown;
1181 }
1182
5b40c067
TG
1183 if (p[0] == '.' && ISDIGIT (p[1]))
1184 {
1185 /* Nested subprogram. */
1186 p += 2;
1187 while (ISDIGIT (*p))
1188 p++;
1189 }
1190 if (*p == 0)
1191 {
1192 /* End of mangled name. */
1193 break;
1194 }
61ab980a 1195 else
5b40c067 1196 goto unknown;
61ab980a 1197 }
5b40c067
TG
1198 *d = 0;
1199 return demangled;
61ab980a 1200
5b40c067 1201 unknown:
a3f3eec0 1202 XDELETEVEC (demangled);
5b40c067
TG
1203 len0 = strlen (mangled);
1204 demangled = XNEWVEC (char, len0 + 3);
de78f58b 1205
61ab980a
KB
1206 if (mangled[0] == '<')
1207 strcpy (demangled, mangled);
1208 else
1209 sprintf (demangled, "<%s>", mangled);
1210
1211 return demangled;
1212}
1213
2363489c 1214/* This function performs most of what cplus_demangle use to do, but
5e5199e8
AM
1215 to be able to demangle a name with a B, K or n code, we need to
1216 have a longer term memory of what types have been seen. The original
e182f0a3 1217 now initializes and cleans up the squangle code info, while internal
5e5199e8
AM
1218 calls go directly to this routine to avoid resetting that info. */
1219
1220static char *
500d7701 1221internal_cplus_demangle (struct work_stuff *work, const char *mangled)
5e5199e8
AM
1222{
1223
6599da04
JM
1224 string decl;
1225 int success = 0;
6599da04 1226 char *demangled = NULL;
cf183ac2 1227 int s1, s2, s3, s4;
5e5199e8
AM
1228 s1 = work->constructor;
1229 s2 = work->destructor;
1230 s3 = work->static_type;
91063b51 1231 s4 = work->type_quals;
5e5199e8 1232 work->constructor = work->destructor = 0;
91063b51 1233 work->type_quals = TYPE_UNQUALIFIED;
9b559a27 1234 work->dllimported = 0;
6599da04
JM
1235
1236 if ((mangled != NULL) && (*mangled != '\0'))
1237 {
6599da04
JM
1238 string_init (&decl);
1239
1240 /* First check to see if gnu style demangling is active and if the
1241 string to be demangled contains a CPLUS_MARKER. If so, attempt to
1242 recognize one of the gnu special forms rather than looking for a
1243 standard prefix. In particular, don't worry about whether there
1244 is a "__" string in the mangled string. Consider "_$_5__foo" for
1245 example. */
1246
1247 if ((AUTO_DEMANGLING || GNU_DEMANGLING))
1248 {
1249 success = gnu_special (work, &mangled, &decl);
70c8c2b9
AB
1250 if (!success)
1251 {
1252 delete_work_stuff (work);
1253 string_delete (&decl);
1254 }
6599da04
JM
1255 }
1256 if (!success)
1257 {
1258 success = demangle_prefix (work, &mangled, &decl);
1259 }
1260 if (success && (*mangled != '\0'))
1261 {
1262 success = demangle_signature (work, &mangled, &decl);
1263 }
1264 if (work->constructor == 2)
1265 {
5e5199e8 1266 string_prepend (&decl, "global constructors keyed to ");
6599da04
JM
1267 work->constructor = 0;
1268 }
1269 else if (work->destructor == 2)
1270 {
5e5199e8 1271 string_prepend (&decl, "global destructors keyed to ");
6599da04
JM
1272 work->destructor = 0;
1273 }
9b559a27
MK
1274 else if (work->dllimported == 1)
1275 {
1276 string_prepend (&decl, "import stub for ");
1277 work->dllimported = 0;
1278 }
6599da04
JM
1279 demangled = mop_up (work, &decl, success);
1280 }
5e5199e8
AM
1281 work->constructor = s1;
1282 work->destructor = s2;
1283 work->static_type = s3;
91063b51 1284 work->type_quals = s4;
cf183ac2 1285 return demangled;
6599da04
JM
1286}
1287
5e5199e8
AM
1288
1289/* Clear out and squangling related storage */
d6f4ec51 1290static void
500d7701 1291squangle_mop_up (struct work_stuff *work)
5e5199e8
AM
1292{
1293 /* clean up the B and K type mangling types. */
1294 forget_B_and_K_types (work);
1295 if (work -> btypevec != NULL)
1296 {
1297 free ((char *) work -> btypevec);
70c8c2b9 1298 work->btypevec = NULL;
916268f1 1299 work->bsize = 0;
5e5199e8
AM
1300 }
1301 if (work -> ktypevec != NULL)
1302 {
1303 free ((char *) work -> ktypevec);
70c8c2b9 1304 work->ktypevec = NULL;
916268f1 1305 work->ksize = 0;
5e5199e8
AM
1306 }
1307}
1308
5e5199e8 1309
3388651c
DB
1310/* Copy the work state and storage. */
1311
1312static void
500d7701 1313work_stuff_copy_to_from (struct work_stuff *to, struct work_stuff *from)
6599da04 1314{
3388651c
DB
1315 int i;
1316
1317 delete_work_stuff (to);
1318
1319 /* Shallow-copy scalars. */
1320 memcpy (to, from, sizeof (*to));
1321
1322 /* Deep-copy dynamic storage. */
1323 if (from->typevec_size)
d7cf8390 1324 to->typevec = XNEWVEC (char *, from->typevec_size);
3388651c
DB
1325
1326 for (i = 0; i < from->ntypes; i++)
1327 {
1328 int len = strlen (from->typevec[i]) + 1;
1329
d7cf8390 1330 to->typevec[i] = XNEWVEC (char, len);
3388651c
DB
1331 memcpy (to->typevec[i], from->typevec[i], len);
1332 }
1333
1334 if (from->ksize)
d7cf8390 1335 to->ktypevec = XNEWVEC (char *, from->ksize);
3388651c
DB
1336
1337 for (i = 0; i < from->numk; i++)
1338 {
1339 int len = strlen (from->ktypevec[i]) + 1;
1340
d7cf8390 1341 to->ktypevec[i] = XNEWVEC (char, len);
3388651c
DB
1342 memcpy (to->ktypevec[i], from->ktypevec[i], len);
1343 }
6599da04 1344
3388651c 1345 if (from->bsize)
d7cf8390 1346 to->btypevec = XNEWVEC (char *, from->bsize);
3388651c
DB
1347
1348 for (i = 0; i < from->numb; i++)
1349 {
1350 int len = strlen (from->btypevec[i]) + 1;
1351
d7cf8390 1352 to->btypevec[i] = XNEWVEC (char , len);
3388651c
DB
1353 memcpy (to->btypevec[i], from->btypevec[i], len);
1354 }
1355
1841e25c
MB
1356 if (from->proctypevec)
1357 to->proctypevec =
1358 XDUPVEC (int, from->proctypevec, from->proctypevec_size);
1359
3388651c 1360 if (from->ntmpl_args)
d7cf8390 1361 to->tmpl_argvec = XNEWVEC (char *, from->ntmpl_args);
3388651c
DB
1362
1363 for (i = 0; i < from->ntmpl_args; i++)
1364 {
1365 int len = strlen (from->tmpl_argvec[i]) + 1;
1366
d7cf8390 1367 to->tmpl_argvec[i] = XNEWVEC (char, len);
3388651c
DB
1368 memcpy (to->tmpl_argvec[i], from->tmpl_argvec[i], len);
1369 }
1370
1371 if (from->previous_argument)
1372 {
d7cf8390 1373 to->previous_argument = XNEW (string);
3388651c
DB
1374 string_init (to->previous_argument);
1375 string_appends (to->previous_argument, from->previous_argument);
1376 }
1377}
1378
1379
1380/* Delete dynamic stuff in work_stuff that is not to be re-used. */
1381
1382static void
500d7701 1383delete_non_B_K_work_stuff (struct work_stuff *work)
3388651c 1384{
6599da04 1385 /* Discard the remembered types, if any. */
2363489c 1386
6599da04 1387 forget_types (work);
1841e25c 1388 if (work->typevec != NULL)
6599da04 1389 {
1841e25c
MB
1390 free ((char *) work->typevec);
1391 work->typevec = NULL;
1392 work->typevec_size = 0;
1393 }
1394 if (work->proctypevec != NULL)
1395 {
1396 free (work->proctypevec);
1397 work->proctypevec = NULL;
1398 work->proctypevec_size = 0;
6599da04 1399 }
a3a5b5b7
MM
1400 if (work->tmpl_argvec)
1401 {
1402 int i;
1403
1404 for (i = 0; i < work->ntmpl_args; i++)
04695783 1405 free ((char*) work->tmpl_argvec[i]);
2363489c 1406
a3a5b5b7 1407 free ((char*) work->tmpl_argvec);
5e5199e8 1408 work->tmpl_argvec = NULL;
a3a5b5b7 1409 }
9923cc56
MM
1410 if (work->previous_argument)
1411 {
1412 string_delete (work->previous_argument);
1413 free ((char*) work->previous_argument);
2363489c 1414 work->previous_argument = NULL;
9923cc56 1415 }
3388651c
DB
1416}
1417
1418
1419/* Delete all dynamic storage in work_stuff. */
1420static void
500d7701 1421delete_work_stuff (struct work_stuff *work)
3388651c
DB
1422{
1423 delete_non_B_K_work_stuff (work);
1424 squangle_mop_up (work);
1425}
1426
1427
1428/* Clear out any mangled storage */
1429
1430static char *
500d7701 1431mop_up (struct work_stuff *work, string *declp, int success)
3388651c
DB
1432{
1433 char *demangled = NULL;
1434
1435 delete_non_B_K_work_stuff (work);
a3a5b5b7 1436
6599da04
JM
1437 /* If demangling was successful, ensure that the demangled string is null
1438 terminated and return it. Otherwise, free the demangling decl. */
2363489c 1439
6599da04
JM
1440 if (!success)
1441 {
1442 string_delete (declp);
1443 }
1444 else
1445 {
1446 string_appendn (declp, "", 1);
cf183ac2 1447 demangled = declp->b;
6599da04
JM
1448 }
1449 return (demangled);
1450}
1451
1452/*
1453
1454LOCAL FUNCTION
1455
1456 demangle_signature -- demangle the signature part of a mangled name
1457
1458SYNOPSIS
1459
1460 static int
1461 demangle_signature (struct work_stuff *work, const char **mangled,
1462 string *declp);
1463
1464DESCRIPTION
1465
1466 Consume and demangle the signature portion of the mangled name.
1467
1468 DECLP is the string where demangled output is being built. At
1469 entry it contains the demangled root name from the mangled name
1470 prefix. I.E. either a demangled operator name or the root function
1471 name. In some special cases, it may contain nothing.
1472
1473 *MANGLED points to the current unconsumed location in the mangled
1474 name. As tokens are consumed and demangling is performed, the
1475 pointer is updated to continuously point at the next token to
1476 be consumed.
1477
1478 Demangling GNU style mangled names is nasty because there is no
1479 explicit token that marks the start of the outermost function
1480 argument list. */
1481
1482static int
500d7701
GDR
1483demangle_signature (struct work_stuff *work,
1484 const char **mangled, string *declp)
6599da04
JM
1485{
1486 int success = 1;
1487 int func_done = 0;
1488 int expect_func = 0;
a3a5b5b7 1489 int expect_return_type = 0;
6599da04
JM
1490 const char *oldmangled = NULL;
1491 string trawname;
1492 string tname;
1493
1494 while (success && (**mangled != '\0'))
1495 {
1496 switch (**mangled)
1497 {
1498 case 'Q':
1499 oldmangled = *mangled;
1500 success = demangle_qualified (work, mangled, declp, 1, 0);
1501 if (success)
9923cc56 1502 remember_type (work, oldmangled, *mangled - oldmangled);
6599da04 1503 if (AUTO_DEMANGLING || GNU_DEMANGLING)
9923cc56 1504 expect_func = 1;
6599da04
JM
1505 oldmangled = NULL;
1506 break;
5e5199e8
AM
1507
1508 case 'K':
1509 oldmangled = *mangled;
1510 success = demangle_qualified (work, mangled, declp, 1, 0);
1511 if (AUTO_DEMANGLING || GNU_DEMANGLING)
1512 {
1513 expect_func = 1;
1514 }
1515 oldmangled = NULL;
1516 break;
2363489c 1517
6599da04
JM
1518 case 'S':
1519 /* Static member function */
1520 if (oldmangled == NULL)
1521 {
1522 oldmangled = *mangled;
1523 }
1524 (*mangled)++;
1525 work -> static_type = 1;
1526 break;
1527
1528 case 'C':
9923cc56 1529 case 'V':
91063b51
MM
1530 case 'u':
1531 work->type_quals |= code_for_qualifier (**mangled);
9923cc56
MM
1532
1533 /* a qualified member function */
6599da04 1534 if (oldmangled == NULL)
9923cc56 1535 oldmangled = *mangled;
6599da04 1536 (*mangled)++;
6599da04 1537 break;
70d5ccef
DT
1538
1539 case 'L':
1540 /* Local class name follows after "Lnnn_" */
1541 if (HP_DEMANGLING)
1542 {
1543 while (**mangled && (**mangled != '_'))
1544 (*mangled)++;
1545 if (!**mangled)
1546 success = 0;
1547 else
1548 (*mangled)++;
1549 }
1550 else
1551 success = 0;
1552 break;
2363489c 1553
6599da04
JM
1554 case '0': case '1': case '2': case '3': case '4':
1555 case '5': case '6': case '7': case '8': case '9':
1556 if (oldmangled == NULL)
1557 {
1558 oldmangled = *mangled;
1559 }
2363489c 1560 work->temp_start = -1; /* uppermost call to demangle_class */
6599da04
JM
1561 success = demangle_class (work, mangled, declp);
1562 if (success)
1563 {
1564 remember_type (work, oldmangled, *mangled - oldmangled);
1565 }
70d5ccef 1566 if (AUTO_DEMANGLING || GNU_DEMANGLING || EDG_DEMANGLING)
6599da04 1567 {
2363489c 1568 /* EDG and others will have the "F", so we let the loop cycle
70d5ccef
DT
1569 if we are looking at one. */
1570 if (**mangled != 'F')
1571 expect_func = 1;
6599da04
JM
1572 }
1573 oldmangled = NULL;
1574 break;
9923cc56
MM
1575
1576 case 'B':
1577 {
1578 string s;
1579 success = do_type (work, mangled, &s);
1580 if (success)
1581 {
1582 string_append (&s, SCOPE_STRING (work));
1583 string_prepends (declp, &s);
902cf50c 1584 string_delete (&s);
9923cc56
MM
1585 }
1586 oldmangled = NULL;
1587 expect_func = 1;
1588 }
1589 break;
1590
6599da04
JM
1591 case 'F':
1592 /* Function */
70d5ccef 1593 /* ARM/HP style demangling includes a specific 'F' character after
6599da04
JM
1594 the class name. For GNU style, it is just implied. So we can
1595 safely just consume any 'F' at this point and be compatible
1596 with either style. */
1597
1598 oldmangled = NULL;
1599 func_done = 1;
1600 (*mangled)++;
1601
70d5ccef 1602 /* For lucid/ARM/HP style we have to forget any types we might
6599da04
JM
1603 have remembered up to this point, since they were not argument
1604 types. GNU style considers all types seen as available for
1605 back references. See comment in demangle_args() */
1606
70d5ccef 1607 if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
6599da04
JM
1608 {
1609 forget_types (work);
1610 }
1611 success = demangle_args (work, mangled, declp);
70d5ccef
DT
1612 /* After picking off the function args, we expect to either
1613 find the function return type (preceded by an '_') or the
1614 end of the string. */
1615 if (success && (AUTO_DEMANGLING || EDG_DEMANGLING) && **mangled == '_')
1616 {
1617 ++(*mangled);
1618 /* At this level, we do not care about the return type. */
1619 success = do_type (work, mangled, &tname);
1620 string_delete (&tname);
1621 }
1622
6599da04 1623 break;
2363489c 1624
6599da04
JM
1625 case 't':
1626 /* G++ Template */
2363489c 1627 string_init(&trawname);
6599da04
JM
1628 string_init(&tname);
1629 if (oldmangled == NULL)
1630 {
1631 oldmangled = *mangled;
1632 }
9923cc56
MM
1633 success = demangle_template (work, mangled, &tname,
1634 &trawname, 1, 1);
6599da04
JM
1635 if (success)
1636 {
1637 remember_type (work, oldmangled, *mangled - oldmangled);
1638 }
4d59ab3f
JM
1639 string_append (&tname, SCOPE_STRING (work));
1640
6599da04
JM
1641 string_prepends(declp, &tname);
1642 if (work -> destructor & 1)
1643 {
1644 string_prepend (&trawname, "~");
1645 string_appends (declp, &trawname);
1646 work->destructor -= 1;
1647 }
1648 if ((work->constructor & 1) || (work->destructor & 1))
1649 {
1650 string_appends (declp, &trawname);
1651 work->constructor -= 1;
1652 }
1653 string_delete(&trawname);
1654 string_delete(&tname);
1655 oldmangled = NULL;
1656 expect_func = 1;
1657 break;
1658
1659 case '_':
3388651c 1660 if ((AUTO_DEMANGLING || GNU_DEMANGLING) && expect_return_type)
a3a5b5b7
MM
1661 {
1662 /* Read the return type. */
1663 string return_type;
a3a5b5b7
MM
1664
1665 (*mangled)++;
1666 success = do_type (work, mangled, &return_type);
1667 APPEND_BLANK (&return_type);
1668
1669 string_prepends (declp, &return_type);
1670 string_delete (&return_type);
1671 break;
1672 }
1673 else
1674 /* At the outermost level, we cannot have a return type specified,
1675 so if we run into another '_' at this point we are dealing with
1676 a mangled name that is either bogus, or has been mangled by
1677 some algorithm we don't know how to deal with. So just
1678 reject the entire demangling. */
70d5ccef
DT
1679 /* However, "_nnn" is an expected suffix for alternate entry point
1680 numbered nnn for a function, with HP aCC, so skip over that
1681 without reporting failure. pai/1997-09-04 */
1682 if (HP_DEMANGLING)
1683 {
1684 (*mangled)++;
f6bbde28 1685 while (**mangled && ISDIGIT ((unsigned char)**mangled))
70d5ccef
DT
1686 (*mangled)++;
1687 }
1688 else
1689 success = 0;
6599da04
JM
1690 break;
1691
a3a5b5b7 1692 case 'H':
3388651c 1693 if (AUTO_DEMANGLING || GNU_DEMANGLING)
a3a5b5b7
MM
1694 {
1695 /* A G++ template function. Read the template arguments. */
9923cc56
MM
1696 success = demangle_template (work, mangled, declp, 0, 0,
1697 0);
19ddc834
JM
1698 if (!(work->constructor & 1))
1699 expect_return_type = 1;
0d0bfbf4
MW
1700 if (!**mangled)
1701 success = 0;
1702 else
1703 (*mangled)++;
a3a5b5b7
MM
1704 break;
1705 }
c4ec8585 1706 /* fall through */
a3a5b5b7 1707
6599da04
JM
1708 default:
1709 if (AUTO_DEMANGLING || GNU_DEMANGLING)
1710 {
1711 /* Assume we have stumbled onto the first outermost function
1712 argument token, and start processing args. */
1713 func_done = 1;
1714 success = demangle_args (work, mangled, declp);
1715 }
1716 else
1717 {
1718 /* Non-GNU demanglers use a specific token to mark the start
1719 of the outermost function argument tokens. Typically 'F',
70d5ccef 1720 for ARM/HP-demangling, for example. So if we find something
6599da04
JM
1721 we are not prepared for, it must be an error. */
1722 success = 0;
1723 }
1724 break;
1725 }
1726 /*
1727 if (AUTO_DEMANGLING || GNU_DEMANGLING)
1728 */
1729 {
1730 if (success && expect_func)
1731 {
1732 func_done = 1;
70d5ccef
DT
1733 if (LUCID_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING)
1734 {
1735 forget_types (work);
1736 }
6599da04 1737 success = demangle_args (work, mangled, declp);
a3a5b5b7
MM
1738 /* Since template include the mangling of their return types,
1739 we must set expect_func to 0 so that we don't try do
1740 demangle more arguments the next time we get here. */
1741 expect_func = 0;
6599da04
JM
1742 }
1743 }
1744 }
1745 if (success && !func_done)
1746 {
1747 if (AUTO_DEMANGLING || GNU_DEMANGLING)
1748 {
1749 /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
1750 bar__3fooi is 'foo::bar(int)'. We get here when we find the
1751 first case, and need to ensure that the '(void)' gets added to
70d5ccef 1752 the current declp. Note that with ARM/HP, the first case
6599da04
JM
1753 represents the name of a static data member 'foo::bar',
1754 which is in the current declp, so we leave it alone. */
1755 success = demangle_args (work, mangled, declp);
1756 }
1757 }
91063b51
MM
1758 if (success && PRINT_ARG_TYPES)
1759 {
1760 if (work->static_type)
1761 string_append (declp, " static");
1762 if (work->type_quals != TYPE_UNQUALIFIED)
1763 {
1764 APPEND_BLANK (declp);
1765 string_append (declp, qualifier_string (work->type_quals));
1766 }
1767 }
9923cc56 1768
6599da04
JM
1769 return (success);
1770}
1771
1772#if 0
1773
1774static int
500d7701
GDR
1775demangle_method_args (struct work_stuff *work, const char **mangled,
1776 string *declp)
6599da04
JM
1777{
1778 int success = 0;
1779
1780 if (work -> static_type)
1781 {
1782 string_append (declp, *mangled + 1);
1783 *mangled += strlen (*mangled);
1784 success = 1;
1785 }
1786 else
1787 {
1788 success = demangle_args (work, mangled, declp);
1789 }
1790 return (success);
1791}
1792
1793#endif
1794
9ee02b5c 1795static int
500d7701
GDR
1796demangle_template_template_parm (struct work_stuff *work,
1797 const char **mangled, string *tname)
9ee02b5c
JL
1798{
1799 int i;
1800 int r;
1801 int need_comma = 0;
1802 int success = 1;
1803 string temp;
1804
1805 string_append (tname, "template <");
1806 /* get size of template parameter list */
1807 if (get_count (mangled, &r))
1808 {
1809 for (i = 0; i < r; i++)
1810 {
1811 if (need_comma)
1812 {
1813 string_append (tname, ", ");
1814 }
1815
1816 /* Z for type parameters */
1817 if (**mangled == 'Z')
1818 {
1819 (*mangled)++;
1820 string_append (tname, "class");
1821 }
1822 /* z for template parameters */
1823 else if (**mangled == 'z')
1824 {
1825 (*mangled)++;
2363489c 1826 success =
9ee02b5c
JL
1827 demangle_template_template_parm (work, mangled, tname);
1828 if (!success)
1829 {
1830 break;
1831 }
1832 }
1833 else
1834 {
1835 /* temp is initialized in do_type */
1836 success = do_type (work, mangled, &temp);
1837 if (success)
1838 {
1839 string_appends (tname, &temp);
1840 }
1841 string_delete(&temp);
1842 if (!success)
1843 {
1844 break;
1845 }
1846 }
1847 need_comma = 1;
1848 }
1849
1850 }
1851 if (tname->p[-1] == '>')
1852 string_append (tname, " ");
1853 string_append (tname, "> class");
1854 return (success);
1855}
1856
f9c85454 1857static int
500d7701
GDR
1858demangle_expression (struct work_stuff *work, const char **mangled,
1859 string *s, type_kind_t tk)
f9c85454 1860{
b60fe4a7 1861 int need_operator = 0;
f9c85454
MM
1862 int success;
1863
b60fe4a7
MM
1864 success = 1;
1865 string_appendn (s, "(", 1);
1866 (*mangled)++;
1867 while (success && **mangled != 'W' && **mangled != '\0')
f9c85454 1868 {
b60fe4a7 1869 if (need_operator)
f9c85454 1870 {
b60fe4a7
MM
1871 size_t i;
1872 size_t len;
f9c85454 1873
b60fe4a7 1874 success = 0;
f9c85454 1875
b60fe4a7 1876 len = strlen (*mangled);
f9c85454 1877
2f26c11d 1878 for (i = 0; i < ARRAY_SIZE (optable); ++i)
b60fe4a7
MM
1879 {
1880 size_t l = strlen (optable[i].in);
f9c85454 1881
b60fe4a7
MM
1882 if (l <= len
1883 && memcmp (optable[i].in, *mangled, l) == 0)
1884 {
1885 string_appendn (s, " ", 1);
1886 string_append (s, optable[i].out);
1887 string_appendn (s, " ", 1);
1888 success = 1;
1889 (*mangled) += l;
1890 break;
f9c85454 1891 }
f9c85454 1892 }
f9c85454 1893
b60fe4a7
MM
1894 if (!success)
1895 break;
f9c85454 1896 }
2363489c 1897 else
b60fe4a7
MM
1898 need_operator = 1;
1899
1900 success = demangle_template_value_parm (work, mangled, s, tk);
1901 }
1902
1903 if (**mangled != 'W')
1904 success = 0;
1905 else
1906 {
1907 string_appendn (s, ")", 1);
1908 (*mangled)++;
f9c85454 1909 }
b60fe4a7
MM
1910
1911 return success;
1912}
1913
1914static int
500d7701
GDR
1915demangle_integral_value (struct work_stuff *work,
1916 const char **mangled, string *s)
b60fe4a7
MM
1917{
1918 int success;
1919
1920 if (**mangled == 'E')
1921 success = demangle_expression (work, mangled, s, tk_integral);
5e5199e8 1922 else if (**mangled == 'Q' || **mangled == 'K')
f9c85454
MM
1923 success = demangle_qualified (work, mangled, s, 0, 1);
1924 else
1925 {
b60fe4a7
MM
1926 int value;
1927
3388651c
DB
1928 /* By default, we let the number decide whether we shall consume an
1929 underscore. */
336669e7 1930 int multidigit_without_leading_underscore = 0;
3388651c
DB
1931 int leave_following_underscore = 0;
1932
f9c85454
MM
1933 success = 0;
1934
8fe85775
CW
1935 if (**mangled == '_')
1936 {
1937 if (mangled[0][1] == 'm')
1938 {
1939 /* Since consume_count_with_underscores does not handle the
1940 `m'-prefix we must do it here, using consume_count and
1941 adjusting underscores: we have to consume the underscore
1942 matching the prepended one. */
1943 multidigit_without_leading_underscore = 1;
1944 string_appendn (s, "-", 1);
1945 (*mangled) += 2;
1946 }
1947 else
1948 {
1949 /* Do not consume a following underscore;
1950 consume_count_with_underscores will consume what
1951 should be consumed. */
1952 leave_following_underscore = 1;
1953 }
3388651c 1954 }
336669e7
CW
1955 else
1956 {
8fe85775
CW
1957 /* Negative numbers are indicated with a leading `m'. */
1958 if (**mangled == 'm')
1959 {
1960 string_appendn (s, "-", 1);
1961 (*mangled)++;
1962 }
336669e7
CW
1963 /* Since consume_count_with_underscores does not handle
1964 multi-digit numbers that do not start with an underscore,
1965 and this number can be an integer template parameter,
1966 we have to call consume_count. */
1967 multidigit_without_leading_underscore = 1;
1968 /* These multi-digit numbers never end on an underscore,
1969 so if there is one then don't eat it. */
1970 leave_following_underscore = 1;
1971 }
3388651c
DB
1972
1973 /* We must call consume_count if we expect to remove a trailing
1974 underscore, since consume_count_with_underscores expects
1975 the leading underscore (that we consumed) if it is to handle
1976 multi-digit numbers. */
336669e7 1977 if (multidigit_without_leading_underscore)
3388651c
DB
1978 value = consume_count (mangled);
1979 else
1980 value = consume_count_with_underscores (mangled);
b60fe4a7 1981
b60fe4a7
MM
1982 if (value != -1)
1983 {
1984 char buf[INTBUF_SIZE];
1985 sprintf (buf, "%d", value);
1986 string_append (s, buf);
1987
3388651c
DB
1988 /* Numbers not otherwise delimited, might have an underscore
1989 appended as a delimeter, which we should skip.
1990
1991 ??? This used to always remove a following underscore, which
1992 is wrong. If other (arbitrary) cases are followed by an
1993 underscore, we need to do something more radical. */
1994
336669e7 1995 if ((value > 9 || multidigit_without_leading_underscore)
3388651c
DB
1996 && ! leave_following_underscore
1997 && **mangled == '_')
b60fe4a7
MM
1998 (*mangled)++;
1999
2000 /* All is well. */
2001 success = 1;
2002 }
8fe85775 2003 }
b60fe4a7
MM
2004
2005 return success;
2006}
2007
2008/* Demangle the real value in MANGLED. */
2009
2010static int
500d7701
GDR
2011demangle_real_value (struct work_stuff *work,
2012 const char **mangled, string *s)
b60fe4a7
MM
2013{
2014 if (**mangled == 'E')
2015 return demangle_expression (work, mangled, s, tk_real);
2016
2017 if (**mangled == 'm')
2018 {
2019 string_appendn (s, "-", 1);
2020 (*mangled)++;
2021 }
f6bbde28 2022 while (ISDIGIT ((unsigned char)**mangled))
b60fe4a7
MM
2023 {
2024 string_appendn (s, *mangled, 1);
2025 (*mangled)++;
2026 }
2027 if (**mangled == '.') /* fraction */
2028 {
2029 string_appendn (s, ".", 1);
2030 (*mangled)++;
f6bbde28 2031 while (ISDIGIT ((unsigned char)**mangled))
b60fe4a7
MM
2032 {
2033 string_appendn (s, *mangled, 1);
2034 (*mangled)++;
2035 }
2036 }
2037 if (**mangled == 'e') /* exponent */
2038 {
2039 string_appendn (s, "e", 1);
2040 (*mangled)++;
f6bbde28 2041 while (ISDIGIT ((unsigned char)**mangled))
f9c85454
MM
2042 {
2043 string_appendn (s, *mangled, 1);
2044 (*mangled)++;
f9c85454
MM
2045 }
2046 }
2363489c 2047
b60fe4a7 2048 return 1;
f9c85454
MM
2049}
2050
2363489c 2051static int
500d7701
GDR
2052demangle_template_value_parm (struct work_stuff *work, const char **mangled,
2053 string *s, type_kind_t tk)
f9c85454 2054{
f9c85454
MM
2055 int success = 1;
2056
f9c85454
MM
2057 if (**mangled == 'Y')
2058 {
2059 /* The next argument is a template parameter. */
2060 int idx;
2061
2062 (*mangled)++;
2063 idx = consume_count_with_underscores (mangled);
2363489c 2064 if (idx == -1
f9c85454
MM
2065 || (work->tmpl_argvec && idx >= work->ntmpl_args)
2066 || consume_count_with_underscores (mangled) == -1)
2067 return -1;
2068 if (work->tmpl_argvec)
2069 string_append (s, work->tmpl_argvec[idx]);
2070 else
b60fe4a7 2071 string_append_template_idx (s, idx);
f9c85454 2072 }
4d17a06f 2073 else if (tk == tk_integral)
f9c85454 2074 success = demangle_integral_value (work, mangled, s);
4d17a06f 2075 else if (tk == tk_char)
f9c85454
MM
2076 {
2077 char tmp[2];
2078 int val;
2079 if (**mangled == 'm')
2080 {
2081 string_appendn (s, "-", 1);
2082 (*mangled)++;
2083 }
2084 string_appendn (s, "'", 1);
2085 val = consume_count(mangled);
9d229989
JB
2086 if (val <= 0)
2087 success = 0;
2088 else
2089 {
2090 tmp[0] = (char)val;
2091 tmp[1] = '\0';
2092 string_appendn (s, &tmp[0], 1);
2093 string_appendn (s, "'", 1);
2094 }
f9c85454 2095 }
4d17a06f 2096 else if (tk == tk_bool)
f9c85454
MM
2097 {
2098 int val = consume_count (mangled);
2099 if (val == 0)
2100 string_appendn (s, "false", 5);
2101 else if (val == 1)
2102 string_appendn (s, "true", 4);
2103 else
2104 success = 0;
2105 }
4d17a06f 2106 else if (tk == tk_real)
b60fe4a7 2107 success = demangle_real_value (work, mangled, s);
9b27f113
AV
2108 else if (tk == tk_pointer || tk == tk_reference
2109 || tk == tk_rvalue_reference)
f9c85454 2110 {
391cdef0
MM
2111 if (**mangled == 'Q')
2112 success = demangle_qualified (work, mangled, s,
2113 /*isfuncname=*/0,
2114 /*append=*/1);
f9c85454
MM
2115 else
2116 {
391cdef0 2117 int symbol_len = consume_count (mangled);
03ef0c6c
MB
2118 if (symbol_len == -1
2119 || symbol_len > (long) strlen (*mangled))
391cdef0
MM
2120 return -1;
2121 if (symbol_len == 0)
2122 string_appendn (s, "0", 1);
2123 else
f9c85454 2124 {
d7cf8390 2125 char *p = XNEWVEC (char, symbol_len + 1), *q;
391cdef0
MM
2126 strncpy (p, *mangled, symbol_len);
2127 p [symbol_len] = '\0';
2128 /* We use cplus_demangle here, rather than
2129 internal_cplus_demangle, because the name of the entity
2130 mangled here does not make use of any of the squangling
2131 or type-code information we have built up thus far; it is
2132 mangled independently. */
2133 q = cplus_demangle (p, work->options);
2134 if (tk == tk_pointer)
2135 string_appendn (s, "&", 1);
2136 /* FIXME: Pointer-to-member constants should get a
2137 qualifying class name here. */
2138 if (q)
2139 {
2140 string_append (s, q);
2141 free (q);
2142 }
2143 else
2144 string_append (s, p);
2145 free (p);
f9c85454 2146 }
391cdef0 2147 *mangled += symbol_len;
f9c85454 2148 }
f9c85454
MM
2149 }
2150
2151 return success;
2152}
2153
9923cc56
MM
2154/* Demangle the template name in MANGLED. The full name of the
2155 template (e.g., S<int>) is placed in TNAME. The name without the
2156 template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is
2157 non-NULL. If IS_TYPE is nonzero, this template is a type template,
2158 not a function template. If both IS_TYPE and REMEMBER are nonzero,
3388651c 2159 the template is remembered in the list of back-referenceable
9923cc56
MM
2160 types. */
2161
6599da04 2162static int
500d7701
GDR
2163demangle_template (struct work_stuff *work, const char **mangled,
2164 string *tname, string *trawname,
2165 int is_type, int remember)
6599da04
JM
2166{
2167 int i;
6599da04
JM
2168 int r;
2169 int need_comma = 0;
2170 int success = 0;
3510075c 2171 int is_java_array = 0;
6599da04
JM
2172 string temp;
2173
2174 (*mangled)++;
a3a5b5b7 2175 if (is_type)
6599da04 2176 {
a3a5b5b7 2177 /* get template name */
9ee02b5c 2178 if (**mangled == 'z')
a3a5b5b7 2179 {
9ee02b5c
JL
2180 int idx;
2181 (*mangled)++;
0d0bfbf4
MW
2182 if (**mangled == '\0')
2183 return (0);
9ee02b5c
JL
2184 (*mangled)++;
2185
2186 idx = consume_count_with_underscores (mangled);
2363489c 2187 if (idx == -1
9ee02b5c
JL
2188 || (work->tmpl_argvec && idx >= work->ntmpl_args)
2189 || consume_count_with_underscores (mangled) == -1)
9923cc56
MM
2190 return (0);
2191
9ee02b5c
JL
2192 if (work->tmpl_argvec)
2193 {
2194 string_append (tname, work->tmpl_argvec[idx]);
2195 if (trawname)
2196 string_append (trawname, work->tmpl_argvec[idx]);
2197 }
2198 else
2199 {
b60fe4a7 2200 string_append_template_idx (tname, idx);
9ee02b5c 2201 if (trawname)
b60fe4a7 2202 string_append_template_idx (trawname, idx);
9ee02b5c 2203 }
a3a5b5b7 2204 }
9ee02b5c 2205 else
a3a5b5b7 2206 {
9d229989 2207 if ((r = consume_count (mangled)) <= 0
91e0f659 2208 || (int) strlen (*mangled) < r)
9ee02b5c
JL
2209 {
2210 return (0);
2211 }
3510075c
JL
2212 is_java_array = (work -> options & DMGL_JAVA)
2213 && strncmp (*mangled, "JArray1Z", 8) == 0;
2214 if (! is_java_array)
2215 {
2216 string_appendn (tname, *mangled, r);
2217 }
9ee02b5c
JL
2218 if (trawname)
2219 string_appendn (trawname, *mangled, r);
9ee02b5c 2220 *mangled += r;
a3a5b5b7 2221 }
6599da04 2222 }
3510075c
JL
2223 if (!is_java_array)
2224 string_append (tname, "<");
6599da04
JM
2225 /* get size of template parameter list */
2226 if (!get_count (mangled, &r))
2227 {
2228 return (0);
2229 }
a3a5b5b7
MM
2230 if (!is_type)
2231 {
2232 /* Create an array for saving the template argument values. */
d7cf8390 2233 work->tmpl_argvec = XNEWVEC (char *, r);
a3a5b5b7
MM
2234 work->ntmpl_args = r;
2235 for (i = 0; i < r; i++)
2236 work->tmpl_argvec[i] = 0;
2237 }
6599da04
JM
2238 for (i = 0; i < r; i++)
2239 {
2240 if (need_comma)
2241 {
2242 string_append (tname, ", ");
2243 }
2244 /* Z for type parameters */
2245 if (**mangled == 'Z')
2246 {
2247 (*mangled)++;
2248 /* temp is initialized in do_type */
2249 success = do_type (work, mangled, &temp);
2250 if (success)
2251 {
2252 string_appends (tname, &temp);
a3a5b5b7
MM
2253
2254 if (!is_type)
2255 {
2256 /* Save the template argument. */
2257 int len = temp.p - temp.b;
d7cf8390 2258 work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
a3a5b5b7
MM
2259 memcpy (work->tmpl_argvec[i], temp.b, len);
2260 work->tmpl_argvec[i][len] = '\0';
2261 }
6599da04
JM
2262 }
2263 string_delete(&temp);
2264 if (!success)
2265 {
2266 break;
2267 }
2268 }
9ee02b5c
JL
2269 /* z for template parameters */
2270 else if (**mangled == 'z')
2271 {
2272 int r2;
2273 (*mangled)++;
2274 success = demangle_template_template_parm (work, mangled, tname);
2363489c 2275
9ee02b5c 2276 if (success
91e0f659
KG
2277 && (r2 = consume_count (mangled)) > 0
2278 && (int) strlen (*mangled) >= r2)
9ee02b5c
JL
2279 {
2280 string_append (tname, " ");
2281 string_appendn (tname, *mangled, r2);
2282 if (!is_type)
2283 {
2284 /* Save the template argument. */
2285 int len = r2;
d7cf8390 2286 work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
9ee02b5c
JL
2287 memcpy (work->tmpl_argvec[i], *mangled, len);
2288 work->tmpl_argvec[i][len] = '\0';
2289 }
2290 *mangled += r2;
2291 }
2292 if (!success)
2293 {
2294 break;
2295 }
2296 }
6599da04
JM
2297 else
2298 {
a3a5b5b7
MM
2299 string param;
2300 string* s;
2301
6599da04 2302 /* otherwise, value parameter */
f9c85454 2303
6599da04
JM
2304 /* temp is initialized in do_type */
2305 success = do_type (work, mangled, &temp);
6599da04
JM
2306 string_delete(&temp);
2307 if (!success)
4d17a06f 2308 break;
a3a5b5b7
MM
2309
2310 if (!is_type)
2311 {
2312 s = &param;
2313 string_init (s);
2314 }
2315 else
2316 s = tname;
2317
4d17a06f
MM
2318 success = demangle_template_value_parm (work, mangled, s,
2319 (type_kind_t) success);
a3a5b5b7 2320
f9c85454 2321 if (!success)
6599da04 2322 {
f9c85454
MM
2323 if (!is_type)
2324 string_delete (s);
2325 success = 0;
2326 break;
6599da04 2327 }
f9c85454 2328
a3a5b5b7
MM
2329 if (!is_type)
2330 {
2331 int len = s->p - s->b;
d7cf8390 2332 work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
a3a5b5b7
MM
2333 memcpy (work->tmpl_argvec[i], s->b, len);
2334 work->tmpl_argvec[i][len] = '\0';
2363489c 2335
a3a5b5b7
MM
2336 string_appends (tname, s);
2337 string_delete (s);
2338 }
6599da04
JM
2339 }
2340 need_comma = 1;
2341 }
3510075c 2342 if (is_java_array)
4d59ab3f 2343 {
3510075c
JL
2344 string_append (tname, "[]");
2345 }
2346 else
2347 {
2348 if (tname->p[-1] == '>')
2349 string_append (tname, " ");
2350 string_append (tname, ">");
4d59ab3f 2351 }
2363489c 2352
9923cc56 2353 if (is_type && remember)
08c5b96d
B
2354 {
2355 const int bindex = register_Btype (work);
2356 remember_Btype (work, tname->b, LEN_STRING (tname), bindex);
2357 }
9923cc56 2358
6599da04
JM
2359 /*
2360 if (work -> static_type)
2361 {
2362 string_append (declp, *mangled + 1);
2363 *mangled += strlen (*mangled);
2364 success = 1;
2365 }
2366 else
2367 {
2368 success = demangle_args (work, mangled, declp);
2369 }
2370 }
2371 */
2372 return (success);
2373}
2374
2375static int
500d7701
GDR
2376arm_pt (struct work_stuff *work, const char *mangled,
2377 int n, const char **anchor, const char **args)
6599da04 2378{
70d5ccef
DT
2379 /* Check if ARM template with "__pt__" in it ("parameterized type") */
2380 /* Allow HP also here, because HP's cfront compiler follows ARM to some extent */
adddf5bf 2381 if ((ARM_DEMANGLING || HP_DEMANGLING) && (*anchor = strstr (mangled, "__pt__")))
6599da04
JM
2382 {
2383 int len;
2384 *args = *anchor + 6;
2385 len = consume_count (args);
9d229989
JB
2386 if (len == -1)
2387 return 0;
6599da04
JM
2388 if (*args + len == mangled + n && **args == '_')
2389 {
2390 ++*args;
2391 return 1;
2392 }
2393 }
70d5ccef
DT
2394 if (AUTO_DEMANGLING || EDG_DEMANGLING)
2395 {
adddf5bf
KG
2396 if ((*anchor = strstr (mangled, "__tm__"))
2397 || (*anchor = strstr (mangled, "__ps__"))
2398 || (*anchor = strstr (mangled, "__pt__")))
70d5ccef
DT
2399 {
2400 int len;
2401 *args = *anchor + 6;
2402 len = consume_count (args);
9d229989
JB
2403 if (len == -1)
2404 return 0;
70d5ccef
DT
2405 if (*args + len == mangled + n && **args == '_')
2406 {
2407 ++*args;
2408 return 1;
2409 }
2410 }
adddf5bf 2411 else if ((*anchor = strstr (mangled, "__S")))
70d5ccef
DT
2412 {
2413 int len;
2414 *args = *anchor + 3;
2415 len = consume_count (args);
9d229989
JB
2416 if (len == -1)
2417 return 0;
70d5ccef
DT
2418 if (*args + len == mangled + n && **args == '_')
2419 {
2420 ++*args;
2421 return 1;
2422 }
2423 }
2424 }
2425
6599da04
JM
2426 return 0;
2427}
2428
2429static void
500d7701
GDR
2430demangle_arm_hp_template (struct work_stuff *work, const char **mangled,
2431 int n, string *declp)
6599da04
JM
2432{
2433 const char *p;
087aa398 2434 const char *args;
6599da04 2435 const char *e = *mangled + n;
70d5ccef 2436 string arg;
6599da04 2437
70d5ccef
DT
2438 /* Check for HP aCC template spec: classXt1t2 where t1, t2 are
2439 template args */
2440 if (HP_DEMANGLING && ((*mangled)[n] == 'X'))
6599da04 2441 {
70d5ccef 2442 char *start_spec_args = NULL;
e4796f1c 2443 int hold_options;
70d5ccef
DT
2444
2445 /* First check for and omit template specialization pseudo-arguments,
2446 such as in "Spec<#1,#1.*>" */
2447 start_spec_args = strchr (*mangled, '<');
2448 if (start_spec_args && (start_spec_args - *mangled < n))
2449 string_appendn (declp, *mangled, start_spec_args - *mangled);
2450 else
2451 string_appendn (declp, *mangled, n);
2452 (*mangled) += n + 1;
2453 string_init (&arg);
2363489c 2454 if (work->temp_start == -1) /* non-recursive call */
70d5ccef 2455 work->temp_start = declp->p - declp->b;
e4796f1c
ILT
2456
2457 /* We want to unconditionally demangle parameter types in
2458 template parameters. */
2459 hold_options = work->options;
2460 work->options |= DMGL_PARAMS;
2461
70d5ccef
DT
2462 string_append (declp, "<");
2463 while (1)
2464 {
902cf50c 2465 string_delete (&arg);
70d5ccef
DT
2466 switch (**mangled)
2467 {
2468 case 'T':
2469 /* 'T' signals a type parameter */
2470 (*mangled)++;
2471 if (!do_type (work, mangled, &arg))
2472 goto hpacc_template_args_done;
2473 break;
2363489c 2474
70d5ccef
DT
2475 case 'U':
2476 case 'S':
2477 /* 'U' or 'S' signals an integral value */
2478 if (!do_hpacc_template_const_value (work, mangled, &arg))
2479 goto hpacc_template_args_done;
2480 break;
2363489c 2481
70d5ccef
DT
2482 case 'A':
2483 /* 'A' signals a named constant expression (literal) */
2484 if (!do_hpacc_template_literal (work, mangled, &arg))
2485 goto hpacc_template_args_done;
2486 break;
2363489c 2487
70d5ccef
DT
2488 default:
2489 /* Today, 1997-09-03, we have only the above types
2363489c
UD
2490 of template parameters */
2491 /* FIXME: maybe this should fail and return null */
70d5ccef
DT
2492 goto hpacc_template_args_done;
2493 }
2494 string_appends (declp, &arg);
2495 /* Check if we're at the end of template args.
2496 0 if at end of static member of template class,
2363489c
UD
2497 _ if done with template args for a function */
2498 if ((**mangled == '\000') || (**mangled == '_'))
2499 break;
70d5ccef
DT
2500 else
2501 string_append (declp, ",");
2502 }
2503 hpacc_template_args_done:
2504 string_append (declp, ">");
2505 string_delete (&arg);
2506 if (**mangled == '_')
2507 (*mangled)++;
e4796f1c 2508 work->options = hold_options;
70d5ccef
DT
2509 return;
2510 }
2511 /* ARM template? (Also handles HP cfront extensions) */
2512 else if (arm_pt (work, *mangled, n, &p, &args))
2513 {
e4796f1c 2514 int hold_options;
70d5ccef
DT
2515 string type_str;
2516
6599da04
JM
2517 string_init (&arg);
2518 string_appendn (declp, *mangled, p - *mangled);
70d5ccef 2519 if (work->temp_start == -1) /* non-recursive call */
2363489c 2520 work->temp_start = declp->p - declp->b;
e4796f1c
ILT
2521
2522 /* We want to unconditionally demangle parameter types in
2523 template parameters. */
2524 hold_options = work->options;
2525 work->options |= DMGL_PARAMS;
2526
6599da04
JM
2527 string_append (declp, "<");
2528 /* should do error checking here */
2529 while (args < e) {
902cf50c 2530 string_delete (&arg);
70d5ccef
DT
2531
2532 /* Check for type or literal here */
2533 switch (*args)
2534 {
2535 /* HP cfront extensions to ARM for template args */
2536 /* spec: Xt1Lv1 where t1 is a type, v1 is a literal value */
2537 /* FIXME: We handle only numeric literals for HP cfront */
2538 case 'X':
2363489c 2539 /* A typed constant value follows */
70d5ccef
DT
2540 args++;
2541 if (!do_type (work, &args, &type_str))
2542 goto cfront_template_args_done;
2543 string_append (&arg, "(");
2544 string_appends (&arg, &type_str);
902cf50c 2545 string_delete (&type_str);
70d5ccef
DT
2546 string_append (&arg, ")");
2547 if (*args != 'L')
2548 goto cfront_template_args_done;
2549 args++;
2550 /* Now snarf a literal value following 'L' */
2551 if (!snarf_numeric_literal (&args, &arg))
2552 goto cfront_template_args_done;
2553 break;
2554
2555 case 'L':
2556 /* Snarf a literal following 'L' */
2557 args++;
2558 if (!snarf_numeric_literal (&args, &arg))
2559 goto cfront_template_args_done;
2560 break;
2561 default:
2363489c 2562 /* Not handling other HP cfront stuff */
b1c1a22f
SS
2563 {
2564 const char* old_args = args;
2565 if (!do_type (work, &args, &arg))
2566 goto cfront_template_args_done;
2567
2568 /* Fail if we didn't make any progress: prevent infinite loop. */
2569 if (args == old_args)
e4796f1c
ILT
2570 {
2571 work->options = hold_options;
2572 return;
2573 }
b1c1a22f 2574 }
70d5ccef 2575 }
6599da04
JM
2576 string_appends (declp, &arg);
2577 string_append (declp, ",");
2578 }
70d5ccef 2579 cfront_template_args_done:
6599da04 2580 string_delete (&arg);
70d5ccef 2581 if (args >= e)
2363489c 2582 --declp->p; /* remove extra comma */
6599da04 2583 string_append (declp, ">");
e4796f1c 2584 work->options = hold_options;
6599da04 2585 }
ab4856b1
ML
2586 else if (n>10 && strncmp (*mangled, "_GLOBAL_", 8) == 0
2587 && (*mangled)[9] == 'N'
2588 && (*mangled)[8] == (*mangled)[10]
2589 && strchr (cplus_markers, (*mangled)[8]))
2590 {
2591 /* A member of the anonymous namespace. */
2592 string_append (declp, "{anonymous}");
2593 }
6599da04
JM
2594 else
2595 {
2363489c
UD
2596 if (work->temp_start == -1) /* non-recursive call only */
2597 work->temp_start = 0; /* disable in recursive calls */
6599da04
JM
2598 string_appendn (declp, *mangled, n);
2599 }
2600 *mangled += n;
2601}
2602
70d5ccef
DT
2603/* Extract a class name, possibly a template with arguments, from the
2604 mangled string; qualifiers, local class indicators, etc. have
2605 already been dealt with */
2606
6599da04 2607static int
500d7701
GDR
2608demangle_class_name (struct work_stuff *work, const char **mangled,
2609 string *declp)
6599da04
JM
2610{
2611 int n;
2612 int success = 0;
2613
2614 n = consume_count (mangled);
9d229989
JB
2615 if (n == -1)
2616 return 0;
2617 if ((int) strlen (*mangled) >= n)
6599da04 2618 {
70d5ccef 2619 demangle_arm_hp_template (work, mangled, n, declp);
6599da04
JM
2620 success = 1;
2621 }
2622
2623 return (success);
2624}
2625
2626/*
2627
2628LOCAL FUNCTION
2629
2630 demangle_class -- demangle a mangled class sequence
2631
2632SYNOPSIS
2633
2634 static int
2635 demangle_class (struct work_stuff *work, const char **mangled,
2636 strint *declp)
2637
2638DESCRIPTION
2639
2640 DECLP points to the buffer into which demangling is being done.
2641
2642 *MANGLED points to the current token to be demangled. On input,
2643 it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
2644 On exit, it points to the next token after the mangled class on
2645 success, or the first unconsumed token on failure.
2646
2647 If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
2648 we are demangling a constructor or destructor. In this case
2649 we prepend "class::class" or "class::~class" to DECLP.
2650
2651 Otherwise, we prepend "class::" to the current DECLP.
2652
2653 Reset the constructor/destructor flags once they have been
2654 "consumed". This allows demangle_class to be called later during
2655 the same demangling, to do normal class demangling.
2656
2657 Returns 1 if demangling is successful, 0 otherwise.
2658
2659*/
2660
2661static int
500d7701 2662demangle_class (struct work_stuff *work, const char **mangled, string *declp)
6599da04
JM
2663{
2664 int success = 0;
5e5199e8 2665 int btype;
6599da04 2666 string class_name;
2363489c 2667 char *save_class_name_end = 0;
6599da04
JM
2668
2669 string_init (&class_name);
5e5199e8 2670 btype = register_Btype (work);
6599da04
JM
2671 if (demangle_class_name (work, mangled, &class_name))
2672 {
70d5ccef 2673 save_class_name_end = class_name.p;
6599da04
JM
2674 if ((work->constructor & 1) || (work->destructor & 1))
2675 {
70d5ccef
DT
2676 /* adjust so we don't include template args */
2677 if (work->temp_start && (work->temp_start != -1))
2678 {
2679 class_name.p = class_name.b + work->temp_start;
2680 }
6599da04
JM
2681 string_prepends (declp, &class_name);
2682 if (work -> destructor & 1)
2683 {
2684 string_prepend (declp, "~");
2685 work -> destructor -= 1;
2686 }
2687 else
2688 {
2363489c 2689 work -> constructor -= 1;
6599da04
JM
2690 }
2691 }
70d5ccef 2692 class_name.p = save_class_name_end;
5e5199e8
AM
2693 remember_Ktype (work, class_name.b, LEN_STRING(&class_name));
2694 remember_Btype (work, class_name.b, LEN_STRING(&class_name), btype);
9923cc56 2695 string_prepend (declp, SCOPE_STRING (work));
6599da04
JM
2696 string_prepends (declp, &class_name);
2697 success = 1;
2698 }
2699 string_delete (&class_name);
2700 return (success);
2701}
2702
3388651c
DB
2703
2704/* Called when there's a "__" in the mangled name, with `scan' pointing to
2705 the rightmost guess.
2706
2707 Find the correct "__"-sequence where the function name ends and the
2708 signature starts, which is ambiguous with GNU mangling.
2709 Call demangle_signature here, so we can make sure we found the right
2710 one; *mangled will be consumed so caller will not make further calls to
2711 demangle_signature. */
2712
2713static int
500d7701
GDR
2714iterate_demangle_function (struct work_stuff *work, const char **mangled,
2715 string *declp, const char *scan)
3388651c
DB
2716{
2717 const char *mangle_init = *mangled;
2718 int success = 0;
2719 string decl_init;
2720 struct work_stuff work_init;
2721
2722 if (*(scan + 2) == '\0')
2723 return 0;
2724
2725 /* Do not iterate for some demangling modes, or if there's only one
2726 "__"-sequence. This is the normal case. */
2727 if (ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING
adddf5bf 2728 || strstr (scan + 2, "__") == NULL)
62b445b3 2729 return demangle_function_name (work, mangled, declp, scan);
3388651c
DB
2730
2731 /* Save state so we can restart if the guess at the correct "__" was
2732 wrong. */
2733 string_init (&decl_init);
2734 string_appends (&decl_init, declp);
2735 memset (&work_init, 0, sizeof work_init);
2736 work_stuff_copy_to_from (&work_init, work);
2737
2738 /* Iterate over occurrences of __, allowing names and types to have a
2739 "__" sequence in them. We must start with the first (not the last)
2740 occurrence, since "__" most often occur between independent mangled
2741 parts, hence starting at the last occurence inside a signature
2742 might get us a "successful" demangling of the signature. */
2743
2744 while (scan[2])
2745 {
62b445b3
TJB
2746 if (demangle_function_name (work, mangled, declp, scan))
2747 {
2748 success = demangle_signature (work, mangled, declp);
2749 if (success)
2750 break;
2751 }
3388651c
DB
2752
2753 /* Reset demangle state for the next round. */
2754 *mangled = mangle_init;
2755 string_clear (declp);
2756 string_appends (declp, &decl_init);
2757 work_stuff_copy_to_from (work, &work_init);
2758
2759 /* Leave this underscore-sequence. */
2760 scan += 2;
2761
2762 /* Scan for the next "__" sequence. */
2763 while (*scan && (scan[0] != '_' || scan[1] != '_'))
2764 scan++;
2765
2766 /* Move to last "__" in this sequence. */
2767 while (*scan && *scan == '_')
2768 scan++;
2769 scan -= 2;
2770 }
2771
2772 /* Delete saved state. */
2773 delete_work_stuff (&work_init);
2774 string_delete (&decl_init);
2775
2776 return success;
2777}
2778
6599da04
JM
2779/*
2780
2781LOCAL FUNCTION
2782
2783 demangle_prefix -- consume the mangled name prefix and find signature
2784
2785SYNOPSIS
2786
2787 static int
2788 demangle_prefix (struct work_stuff *work, const char **mangled,
2789 string *declp);
2790
2791DESCRIPTION
2792
2793 Consume and demangle the prefix of the mangled name.
3388651c
DB
2794 While processing the function name root, arrange to call
2795 demangle_signature if the root is ambiguous.
6599da04
JM
2796
2797 DECLP points to the string buffer into which demangled output is
2798 placed. On entry, the buffer is empty. On exit it contains
2799 the root function name, the demangled operator name, or in some
2800 special cases either nothing or the completely demangled result.
2801
2802 MANGLED points to the current pointer into the mangled name. As each
2803 token of the mangled name is consumed, it is updated. Upon entry
2804 the current mangled name pointer points to the first character of
2805 the mangled name. Upon exit, it should point to the first character
2806 of the signature if demangling was successful, or to the first
2807 unconsumed character if demangling of the prefix was unsuccessful.
2363489c 2808
6599da04
JM
2809 Returns 1 on success, 0 otherwise.
2810 */
2811
2812static int
500d7701
GDR
2813demangle_prefix (struct work_stuff *work, const char **mangled,
2814 string *declp)
6599da04
JM
2815{
2816 int success = 1;
2817 const char *scan;
2818 int i;
2819
9b559a27 2820 if (strlen(*mangled) > 6
2363489c 2821 && (strncmp(*mangled, "_imp__", 6) == 0
9b559a27
MK
2822 || strncmp(*mangled, "__imp_", 6) == 0))
2823 {
2824 /* it's a symbol imported from a PE dynamic library. Check for both
2825 new style prefix _imp__ and legacy __imp_ used by older versions
2826 of dlltool. */
2827 (*mangled) += 6;
2828 work->dllimported = 1;
2829 }
2830 else if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0)
6599da04
JM
2831 {
2832 char *marker = strchr (cplus_markers, (*mangled)[8]);
2833 if (marker != NULL && *marker == (*mangled)[10])
2834 {
2835 if ((*mangled)[9] == 'D')
2836 {
2837 /* it's a GNU global destructor to be executed at program exit */
2838 (*mangled) += 11;
2839 work->destructor = 2;
2840 if (gnu_special (work, mangled, declp))
2841 return success;
2842 }
2843 else if ((*mangled)[9] == 'I')
2844 {
2845 /* it's a GNU global constructor to be executed at program init */
2846 (*mangled) += 11;
2847 work->constructor = 2;
2848 if (gnu_special (work, mangled, declp))
2849 return success;
2850 }
2851 }
2852 }
70d5ccef 2853 else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__std__", 7) == 0)
6599da04
JM
2854 {
2855 /* it's a ARM global destructor to be executed at program exit */
2856 (*mangled) += 7;
2857 work->destructor = 2;
2858 }
70d5ccef 2859 else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__sti__", 7) == 0)
6599da04
JM
2860 {
2861 /* it's a ARM global constructor to be executed at program initial */
2862 (*mangled) += 7;
2863 work->constructor = 2;
2864 }
2865
2866 /* This block of code is a reduction in strength time optimization
2867 of:
adddf5bf 2868 scan = strstr (*mangled, "__"); */
6599da04
JM
2869
2870 {
2871 scan = *mangled;
2872
2873 do {
2874 scan = strchr (scan, '_');
2875 } while (scan != NULL && *++scan != '_');
2876
2877 if (scan != NULL) --scan;
2878 }
2879
2880 if (scan != NULL)
2881 {
2882 /* We found a sequence of two or more '_', ensure that we start at
2883 the last pair in the sequence. */
2884 i = strspn (scan, "_");
2885 if (i > 2)
2886 {
2363489c 2887 scan += (i - 2);
6599da04
JM
2888 }
2889 }
2363489c 2890
6599da04
JM
2891 if (scan == NULL)
2892 {
2893 success = 0;
2894 }
2895 else if (work -> static_type)
2896 {
f6bbde28 2897 if (!ISDIGIT ((unsigned char)scan[0]) && (scan[0] != 't'))
6599da04
JM
2898 {
2899 success = 0;
2900 }
2901 }
2902 else if ((scan == *mangled)
f6bbde28 2903 && (ISDIGIT ((unsigned char)scan[2]) || (scan[2] == 'Q')
91e0f659 2904 || (scan[2] == 't') || (scan[2] == 'K') || (scan[2] == 'H')))
6599da04
JM
2905 {
2906 /* The ARM says nothing about the mangling of local variables.
2907 But cfront mangles local variables by prepending __<nesting_level>
2908 to them. As an extension to ARM demangling we handle this case. */
70d5ccef 2909 if ((LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING)
f6bbde28 2910 && ISDIGIT ((unsigned char)scan[2]))
6599da04
JM
2911 {
2912 *mangled = scan + 2;
2913 consume_count (mangled);
2914 string_append (declp, *mangled);
2915 *mangled += strlen (*mangled);
2363489c 2916 success = 1;
6599da04
JM
2917 }
2918 else
2919 {
2920 /* A GNU style constructor starts with __[0-9Qt]. But cfront uses
2921 names like __Q2_3foo3bar for nested type names. So don't accept
19ddc834
JM
2922 this style of constructor for cfront demangling. A GNU
2923 style member-template constructor starts with 'H'. */
70d5ccef 2924 if (!(LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING))
6599da04
JM
2925 work -> constructor += 1;
2926 *mangled = scan + 2;
2927 }
2928 }
70d5ccef
DT
2929 else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't')
2930 {
2931 /* Cfront-style parameterized type. Handled later as a signature. */
2932 success = 1;
2363489c 2933
70d5ccef
DT
2934 /* ARM template? */
2935 demangle_arm_hp_template (work, mangled, strlen (*mangled), declp);
2936 }
2937 else if (EDG_DEMANGLING && ((scan[2] == 't' && scan[3] == 'm')
2938 || (scan[2] == 'p' && scan[3] == 's')
2939 || (scan[2] == 'p' && scan[3] == 't')))
2940 {
2941 /* EDG-style parameterized type. Handled later as a signature. */
2942 success = 1;
2363489c 2943
70d5ccef
DT
2944 /* EDG template? */
2945 demangle_arm_hp_template (work, mangled, strlen (*mangled), declp);
2946 }
f6bbde28 2947 else if ((scan == *mangled) && !ISDIGIT ((unsigned char)scan[2])
91e0f659 2948 && (scan[2] != 't'))
6599da04
JM
2949 {
2950 /* Mangled name starts with "__". Skip over any leading '_' characters,
2951 then find the next "__" that separates the prefix from the signature.
2952 */
70d5ccef 2953 if (!(ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
9ee02b5c 2954 || (arm_special (mangled, declp) == 0))
6599da04
JM
2955 {
2956 while (*scan == '_')
2957 {
2958 scan++;
2959 }
adddf5bf 2960 if ((scan = strstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
6599da04
JM
2961 {
2962 /* No separator (I.E. "__not_mangled"), or empty signature
2963 (I.E. "__not_mangled_either__") */
2964 success = 0;
2965 }
2966 else
3388651c 2967 return iterate_demangle_function (work, mangled, declp, scan);
6599da04
JM
2968 }
2969 }
6599da04
JM
2970 else if (*(scan + 2) != '\0')
2971 {
2972 /* Mangled name does not start with "__" but does have one somewhere
2973 in there with non empty stuff after it. Looks like a global
3388651c
DB
2974 function name. Iterate over all "__":s until the right
2975 one is found. */
2976 return iterate_demangle_function (work, mangled, declp, scan);
6599da04
JM
2977 }
2978 else
2979 {
2980 /* Doesn't look like a mangled name */
2981 success = 0;
2982 }
2983
2984 if (!success && (work->constructor == 2 || work->destructor == 2))
2985 {
2986 string_append (declp, *mangled);
2987 *mangled += strlen (*mangled);
2988 success = 1;
2363489c 2989 }
6599da04
JM
2990 return (success);
2991}
2992
2993/*
2994
2995LOCAL FUNCTION
2996
2997 gnu_special -- special handling of gnu mangled strings
2998
2999SYNOPSIS
3000
3001 static int
3002 gnu_special (struct work_stuff *work, const char **mangled,
3003 string *declp);
3004
3005
3006DESCRIPTION
3007
3008 Process some special GNU style mangling forms that don't fit
3009 the normal pattern. For example:
3010
3011 _$_3foo (destructor for class foo)
3012 _vt$foo (foo virtual table)
3013 _vt$foo$bar (foo::bar virtual table)
3014 __vt_foo (foo virtual table, new style with thunks)
3015 _3foo$varname (static data member)
3016 _Q22rs2tu$vw (static data member)
3017 __t6vector1Zii (constructor with template)
3018 __thunk_4__$_7ostream (virtual function thunk)
3019 */
3020
3021static int
500d7701 3022gnu_special (struct work_stuff *work, const char **mangled, string *declp)
6599da04
JM
3023{
3024 int n;
3025 int success = 1;
3026 const char *p;
3027
0d0bfbf4 3028 if ((*mangled)[0] == '_' && (*mangled)[1] != '\0'
6599da04
JM
3029 && strchr (cplus_markers, (*mangled)[1]) != NULL
3030 && (*mangled)[2] == '_')
3031 {
3032 /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
3033 (*mangled) += 3;
3034 work -> destructor += 1;
3035 }
3036 else if ((*mangled)[0] == '_'
3037 && (((*mangled)[1] == '_'
3038 && (*mangled)[2] == 'v'
3039 && (*mangled)[3] == 't'
3040 && (*mangled)[4] == '_')
3041 || ((*mangled)[1] == 'v'
0d0bfbf4 3042 && (*mangled)[2] == 't' && (*mangled)[3] != '\0'
6599da04
JM
3043 && strchr (cplus_markers, (*mangled)[3]) != NULL)))
3044 {
3045 /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
3046 and create the decl. Note that we consume the entire mangled
3047 input string, which means that demangle_signature has no work
3048 to do. */
3049 if ((*mangled)[2] == 'v')
3050 (*mangled) += 5; /* New style, with thunks: "__vt_" */
3051 else
3052 (*mangled) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
3053 while (**mangled != '\0')
3054 {
6599da04
JM
3055 switch (**mangled)
3056 {
3057 case 'Q':
5e5199e8 3058 case 'K':
6599da04
JM
3059 success = demangle_qualified (work, mangled, declp, 0, 1);
3060 break;
3061 case 't':
9923cc56
MM
3062 success = demangle_template (work, mangled, declp, 0, 1,
3063 1);
6599da04
JM
3064 break;
3065 default:
f6bbde28 3066 if (ISDIGIT((unsigned char)*mangled[0]))
6599da04
JM
3067 {
3068 n = consume_count(mangled);
5890bc92
JL
3069 /* We may be seeing a too-large size, or else a
3070 ".<digits>" indicating a static local symbol. In
3071 any case, declare victory and move on; *don't* try
3072 to use n to allocate. */
91e0f659 3073 if (n > (int) strlen (*mangled))
5890bc92
JL
3074 {
3075 success = 1;
3076 break;
3077 }
59dad006
MB
3078 else if (n == -1)
3079 {
3080 success = 0;
3081 break;
3082 }
6599da04
JM
3083 }
3084 else
3085 {
3086 n = strcspn (*mangled, cplus_markers);
3087 }
3088 string_appendn (declp, *mangled, n);
3089 (*mangled) += n;
3090 }
3091
224301c1 3092 p = strpbrk (*mangled, cplus_markers);
6599da04
JM
3093 if (success && ((p == NULL) || (p == *mangled)))
3094 {
3095 if (p != NULL)
3096 {
9923cc56 3097 string_append (declp, SCOPE_STRING (work));
6599da04
JM
3098 (*mangled)++;
3099 }
3100 }
3101 else
3102 {
3103 success = 0;
3104 break;
3105 }
3106 }
3107 if (success)
3108 string_append (declp, " virtual table");
3109 }
3110 else if ((*mangled)[0] == '_'
3111 && (strchr("0123456789Qt", (*mangled)[1]) != NULL)
3112 && (p = strpbrk (*mangled, cplus_markers)) != NULL)
3113 {
3114 /* static data member, "_3foo$varname" for example */
3115 (*mangled)++;
3116 switch (**mangled)
3117 {
3118 case 'Q':
5e5199e8 3119 case 'K':
6599da04
JM
3120 success = demangle_qualified (work, mangled, declp, 0, 1);
3121 break;
3122 case 't':
9923cc56 3123 success = demangle_template (work, mangled, declp, 0, 1, 1);
6599da04
JM
3124 break;
3125 default:
3126 n = consume_count (mangled);
e797ff70 3127 if (n < 0 || n > (long) strlen (*mangled))
9d229989
JB
3128 {
3129 success = 0;
3130 break;
3131 }
29791078
HPN
3132
3133 if (n > 10 && strncmp (*mangled, "_GLOBAL_", 8) == 0
3134 && (*mangled)[9] == 'N'
3135 && (*mangled)[8] == (*mangled)[10]
3136 && strchr (cplus_markers, (*mangled)[8]))
3137 {
3138 /* A member of the anonymous namespace. There's information
3139 about what identifier or filename it was keyed to, but
3140 it's just there to make the mangled name unique; we just
3141 step over it. */
3142 string_append (declp, "{anonymous}");
3143 (*mangled) += n;
3144
3145 /* Now p points to the marker before the N, so we need to
3146 update it to the first marker after what we consumed. */
3147 p = strpbrk (*mangled, cplus_markers);
3148 break;
3149 }
3150
6599da04
JM
3151 string_appendn (declp, *mangled, n);
3152 (*mangled) += n;
3153 }
3154 if (success && (p == *mangled))
3155 {
3156 /* Consumed everything up to the cplus_marker, append the
3157 variable name. */
3158 (*mangled)++;
9923cc56 3159 string_append (declp, SCOPE_STRING (work));
6599da04
JM
3160 n = strlen (*mangled);
3161 string_appendn (declp, *mangled, n);
3162 (*mangled) += n;
3163 }
3164 else
3165 {
3166 success = 0;
3167 }
3168 }
3169 else if (strncmp (*mangled, "__thunk_", 8) == 0)
3170 {
9d229989
JB
3171 int delta;
3172
3173 (*mangled) += 8;
3174 delta = consume_count (mangled);
3175 if (delta == -1)
3176 success = 0;
6599da04
JM
3177 else
3178 {
9d229989
JB
3179 char *method = internal_cplus_demangle (work, ++*mangled);
3180
3181 if (method)
3182 {
3183 char buf[50];
3184 sprintf (buf, "virtual function thunk (delta:%d) for ", -delta);
3185 string_append (declp, buf);
3186 string_append (declp, method);
3187 free (method);
3188 n = strlen (*mangled);
3189 (*mangled) += n;
3190 }
3191 else
3192 {
3193 success = 0;
3194 }
6599da04
JM
3195 }
3196 }
3197 else if (strncmp (*mangled, "__t", 3) == 0
3198 && ((*mangled)[3] == 'i' || (*mangled)[3] == 'f'))
3199 {
3200 p = (*mangled)[3] == 'i' ? " type_info node" : " type_info function";
3201 (*mangled) += 4;
3202 switch (**mangled)
3203 {
3204 case 'Q':
5e5199e8 3205 case 'K':
6599da04
JM
3206 success = demangle_qualified (work, mangled, declp, 0, 1);
3207 break;
3208 case 't':
9923cc56 3209 success = demangle_template (work, mangled, declp, 0, 1, 1);
6599da04
JM
3210 break;
3211 default:
bb22da4b 3212 success = do_type (work, mangled, declp);
6599da04
JM
3213 break;
3214 }
3215 if (success && **mangled != '\0')
3216 success = 0;
3217 if (success)
3218 string_append (declp, p);
3219 }
3220 else
3221 {
3222 success = 0;
3223 }
3224 return (success);
3225}
3226
70d5ccef 3227static void
500d7701
GDR
3228recursively_demangle(struct work_stuff *work, const char **mangled,
3229 string *result, int namelength)
70d5ccef
DT
3230{
3231 char * recurse = (char *)NULL;
3232 char * recurse_dem = (char *)NULL;
2363489c 3233
d7cf8390 3234 recurse = XNEWVEC (char, namelength + 1);
70d5ccef
DT
3235 memcpy (recurse, *mangled, namelength);
3236 recurse[namelength] = '\000';
2363489c 3237
70d5ccef 3238 recurse_dem = cplus_demangle (recurse, work->options);
2363489c 3239
70d5ccef
DT
3240 if (recurse_dem)
3241 {
3242 string_append (result, recurse_dem);
3243 free (recurse_dem);
3244 }
3245 else
3246 {
3247 string_appendn (result, *mangled, namelength);
3248 }
3249 free (recurse);
3250 *mangled += namelength;
3251}
3252
6599da04
JM
3253/*
3254
3255LOCAL FUNCTION
3256
3257 arm_special -- special handling of ARM/lucid mangled strings
3258
3259SYNOPSIS
3260
3261 static int
9ee02b5c
JL
3262 arm_special (const char **mangled,
3263 string *declp);
6599da04
JM
3264
3265
3266DESCRIPTION
3267
3268 Process some special ARM style mangling forms that don't fit
3269 the normal pattern. For example:
3270
3271 __vtbl__3foo (foo virtual table)
3272 __vtbl__3foo__3bar (bar::foo virtual table)
3273
3274 */
3275
3276static int
500d7701 3277arm_special (const char **mangled, string *declp)
6599da04
JM
3278{
3279 int n;
3280 int success = 1;
3281 const char *scan;
3282
3283 if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
3284 {
3285 /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
3286 and create the decl. Note that we consume the entire mangled
3287 input string, which means that demangle_signature has no work
3288 to do. */
3289 scan = *mangled + ARM_VTABLE_STRLEN;
3290 while (*scan != '\0') /* first check it can be demangled */
3291 {
3292 n = consume_count (&scan);
9d229989 3293 if (n == -1)
6599da04
JM
3294 {
3295 return (0); /* no good */
3296 }
3297 scan += n;
3298 if (scan[0] == '_' && scan[1] == '_')
3299 {
3300 scan += 2;
3301 }
3302 }
3303 (*mangled) += ARM_VTABLE_STRLEN;
3304 while (**mangled != '\0')
3305 {
3306 n = consume_count (mangled);
9d229989 3307 if (n == -1
e797ff70 3308 || n > (long) strlen (*mangled))
9d229989 3309 return 0;
6599da04
JM
3310 string_prependn (declp, *mangled, n);
3311 (*mangled) += n;
3312 if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
3313 {
3314 string_prepend (declp, "::");
3315 (*mangled) += 2;
3316 }
3317 }
3318 string_append (declp, " virtual table");
3319 }
3320 else
3321 {
3322 success = 0;
3323 }
3324 return (success);
3325}
3326
3327/*
3328
3329LOCAL FUNCTION
3330
3331 demangle_qualified -- demangle 'Q' qualified name strings
3332
3333SYNOPSIS
3334
3335 static int
3336 demangle_qualified (struct work_stuff *, const char *mangled,
3337 string *result, int isfuncname, int append);
3338
3339DESCRIPTION
3340
3341 Demangle a qualified name, such as "Q25Outer5Inner" which is
3342 the mangled form of "Outer::Inner". The demangled output is
3343 prepended or appended to the result string according to the
3344 state of the append flag.
3345
3346 If isfuncname is nonzero, then the qualified name we are building
3347 is going to be used as a member function name, so if it is a
3348 constructor or destructor function, append an appropriate
3349 constructor or destructor name. I.E. for the above example,
3350 the result for use as a constructor is "Outer::Inner::Inner"
3351 and the result for use as a destructor is "Outer::Inner::~Inner".
3352
3353BUGS
3354
3355 Numeric conversion is ASCII dependent (FIXME).
3356
3357 */
3358
3359static int
500d7701
GDR
3360demangle_qualified (struct work_stuff *work, const char **mangled,
3361 string *result, int isfuncname, int append)
6599da04 3362{
5e5199e8 3363 int qualifiers = 0;
6599da04 3364 int success = 1;
6599da04
JM
3365 char num[2];
3366 string temp;
9923cc56
MM
3367 string last_name;
3368 int bindex = register_Btype (work);
3369
3370 /* We only make use of ISFUNCNAME if the entity is a constructor or
3371 destructor. */
2363489c 3372 isfuncname = (isfuncname
9923cc56 3373 && ((work->constructor & 1) || (work->destructor & 1)));
6599da04
JM
3374
3375 string_init (&temp);
9923cc56 3376 string_init (&last_name);
5e5199e8
AM
3377
3378 if ((*mangled)[0] == 'K')
3379 {
3380 /* Squangling qualified name reuse */
3381 int idx;
3382 (*mangled)++;
3383 idx = consume_count_with_underscores (mangled);
e0c13971 3384 if (idx == -1 || idx >= work -> numk)
5e5199e8
AM
3385 success = 0;
3386 else
3387 string_append (&temp, work -> ktypevec[idx]);
3388 }
3389 else
3390 switch ((*mangled)[1])
6599da04
JM
3391 {
3392 case '_':
3393 /* GNU mangled name with more than 9 classes. The count is preceded
3394 by an underscore (to distinguish it from the <= 9 case) and followed
3395 by an underscore. */
b60fe4a7
MM
3396 (*mangled)++;
3397 qualifiers = consume_count_with_underscores (mangled);
3398 if (qualifiers == -1)
6599da04 3399 success = 0;
6599da04
JM
3400 break;
3401
3402 case '1':
3403 case '2':
3404 case '3':
3405 case '4':
3406 case '5':
3407 case '6':
3408 case '7':
3409 case '8':
3410 case '9':
3411 /* The count is in a single digit. */
3412 num[0] = (*mangled)[1];
3413 num[1] = '\0';
3414 qualifiers = atoi (num);
3415
3416 /* If there is an underscore after the digit, skip it. This is
3417 said to be for ARM-qualified names, but the ARM makes no
3418 mention of such an underscore. Perhaps cfront uses one. */
3419 if ((*mangled)[2] == '_')
3420 {
3421 (*mangled)++;
3422 }
3423 (*mangled) += 2;
3424 break;
3425
3426 case '0':
3427 default:
3428 success = 0;
3429 }
3430
3431 if (!success)
3432 return success;
3433
3434 /* Pick off the names and collect them in the temp buffer in the order
3435 in which they are found, separated by '::'. */
3436
3437 while (qualifiers-- > 0)
3438 {
5e5199e8 3439 int remember_K = 1;
9923cc56
MM
3440 string_clear (&last_name);
3441
2363489c 3442 if (*mangled[0] == '_')
9923cc56
MM
3443 (*mangled)++;
3444
6599da04
JM
3445 if (*mangled[0] == 't')
3446 {
9923cc56
MM
3447 /* Here we always append to TEMP since we will want to use
3448 the template name without the template parameters as a
3449 constructor or destructor name. The appropriate
3450 (parameter-less) value is returned by demangle_template
3451 in LAST_NAME. We do not remember the template type here,
3452 in order to match the G++ mangling algorithm. */
2363489c 3453 success = demangle_template(work, mangled, &temp,
9923cc56 3454 &last_name, 1, 0);
2363489c 3455 if (!success)
9923cc56 3456 break;
2363489c 3457 }
07623417 3458 else if (*mangled[0] == 'K')
5e5199e8
AM
3459 {
3460 int idx;
3461 (*mangled)++;
3462 idx = consume_count_with_underscores (mangled);
e0c13971 3463 if (idx == -1 || idx >= work->numk)
5e5199e8
AM
3464 success = 0;
3465 else
3466 string_append (&temp, work->ktypevec[idx]);
3467 remember_K = 0;
3468
6599da04
JM
3469 if (!success) break;
3470 }
3471 else
9923cc56 3472 {
70d5ccef
DT
3473 if (EDG_DEMANGLING)
3474 {
3475 int namelength;
3476 /* Now recursively demangle the qualifier
2363489c
UD
3477 * This is necessary to deal with templates in
3478 * mangling styles like EDG */
70d5ccef 3479 namelength = consume_count (mangled);
9d229989
JB
3480 if (namelength == -1)
3481 {
3482 success = 0;
3483 break;
3484 }
70d5ccef
DT
3485 recursively_demangle(work, mangled, &temp, namelength);
3486 }
3487 else
3488 {
902cf50c 3489 string_delete (&last_name);
70d5ccef
DT
3490 success = do_type (work, mangled, &last_name);
3491 if (!success)
3492 break;
3493 string_appends (&temp, &last_name);
3494 }
6599da04 3495 }
5e5199e8
AM
3496
3497 if (remember_K)
9923cc56 3498 remember_Ktype (work, temp.b, LEN_STRING (&temp));
5e5199e8 3499
6599da04 3500 if (qualifiers > 0)
9923cc56 3501 string_append (&temp, SCOPE_STRING (work));
6599da04
JM
3502 }
3503
9923cc56
MM
3504 remember_Btype (work, temp.b, LEN_STRING (&temp), bindex);
3505
6599da04
JM
3506 /* If we are using the result as a function name, we need to append
3507 the appropriate '::' separated constructor or destructor name.
3508 We do this here because this is the most convenient place, where
3509 we already have a pointer to the name and the length of the name. */
3510
2363489c 3511 if (isfuncname)
6599da04 3512 {
9923cc56 3513 string_append (&temp, SCOPE_STRING (work));
6599da04 3514 if (work -> destructor & 1)
9923cc56
MM
3515 string_append (&temp, "~");
3516 string_appends (&temp, &last_name);
6599da04
JM
3517 }
3518
2363489c 3519 /* Now either prepend the temp buffer to the result, or append it,
6599da04
JM
3520 depending upon the state of the append flag. */
3521
3522 if (append)
9923cc56 3523 string_appends (result, &temp);
6599da04
JM
3524 else
3525 {
3526 if (!STRING_EMPTY (result))
9923cc56 3527 string_append (&temp, SCOPE_STRING (work));
6599da04
JM
3528 string_prepends (result, &temp);
3529 }
3530
9923cc56 3531 string_delete (&last_name);
6599da04
JM
3532 string_delete (&temp);
3533 return (success);
3534}
3535
3536/*
3537
3538LOCAL FUNCTION
3539
3540 get_count -- convert an ascii count to integer, consuming tokens
3541
3542SYNOPSIS
3543
3544 static int
3545 get_count (const char **type, int *count)
3546
3547DESCRIPTION
3548
9d229989
JB
3549 Assume that *type points at a count in a mangled name; set
3550 *count to its value, and set *type to the next character after
3551 the count. There are some weird rules in effect here.
3552
3553 If *type does not point at a string of digits, return zero.
3554
3555 If *type points at a string of digits followed by an
3556 underscore, set *count to their value as an integer, advance
3557 *type to point *after the underscore, and return 1.
3558
3559 If *type points at a string of digits not followed by an
3560 underscore, consume only the first digit. Set *count to its
3561 value as an integer, leave *type pointing after that digit,
3562 and return 1.
3563
3564 The excuse for this odd behavior: in the ARM and HP demangling
3565 styles, a type can be followed by a repeat count of the form
3566 `Nxy', where:
3567
3568 `x' is a single digit specifying how many additional copies
3569 of the type to append to the argument list, and
3570
3571 `y' is one or more digits, specifying the zero-based index of
3572 the first repeated argument in the list. Yes, as you're
3573 unmangling the name you can figure this out yourself, but
3574 it's there anyway.
3575
3576 So, for example, in `bar__3fooFPiN51', the first argument is a
3577 pointer to an integer (`Pi'), and then the next five arguments
3578 are the same (`N5'), and the first repeat is the function's
3579 second argument (`1').
6599da04
JM
3580*/
3581
3582static int
500d7701 3583get_count (const char **type, int *count)
6599da04
JM
3584{
3585 const char *p;
3586 int n;
3587
f6bbde28 3588 if (!ISDIGIT ((unsigned char)**type))
b60fe4a7 3589 return (0);
6599da04
JM
3590 else
3591 {
3592 *count = **type - '0';
3593 (*type)++;
f6bbde28 3594 if (ISDIGIT ((unsigned char)**type))
6599da04
JM
3595 {
3596 p = *type;
3597 n = *count;
2363489c 3598 do
6599da04
JM
3599 {
3600 n *= 10;
3601 n += *p - '0';
3602 p++;
2363489c 3603 }
f6bbde28 3604 while (ISDIGIT ((unsigned char)*p));
6599da04
JM
3605 if (*p == '_')
3606 {
3607 *type = p + 1;
3608 *count = n;
3609 }
3610 }
3611 }
3612 return (1);
3613}
3614
4d17a06f
MM
3615/* RESULT will be initialised here; it will be freed on failure. The
3616 value returned is really a type_kind_t. */
6599da04
JM
3617
3618static int
500d7701 3619do_type (struct work_stuff *work, const char **mangled, string *result)
6599da04
JM
3620{
3621 int n;
1841e25c
MB
3622 int i;
3623 int is_proctypevec;
6599da04
JM
3624 int done;
3625 int success;
3626 string decl;
3627 const char *remembered_type;
91063b51 3628 int type_quals;
4d17a06f 3629 type_kind_t tk = tk_none;
6599da04
JM
3630
3631 string_init (&decl);
3632 string_init (result);
3633
3634 done = 0;
3635 success = 1;
1841e25c 3636 is_proctypevec = 0;
6599da04
JM
3637 while (success && !done)
3638 {
3639 int member;
3640 switch (**mangled)
3641 {
3642
3643 /* A pointer type */
3644 case 'P':
3645 case 'p':
3646 (*mangled)++;
3510075c
JL
3647 if (! (work -> options & DMGL_JAVA))
3648 string_prepend (&decl, "*");
4d17a06f
MM
3649 if (tk == tk_none)
3650 tk = tk_pointer;
6599da04
JM
3651 break;
3652
3653 /* A reference type */
3654 case 'R':
3655 (*mangled)++;
3656 string_prepend (&decl, "&");
4d17a06f 3657 if (tk == tk_none)
ec2288ff 3658 tk = tk_reference;
6599da04
JM
3659 break;
3660
9b27f113
AV
3661 /* An rvalue reference type */
3662 case 'O':
3663 (*mangled)++;
3664 string_prepend (&decl, "&&");
3665 if (tk == tk_none)
3666 tk = tk_rvalue_reference;
3667 break;
3668
6599da04
JM
3669 /* An array */
3670 case 'A':
3671 {
4d17a06f 3672 ++(*mangled);
09007174
JM
3673 if (!STRING_EMPTY (&decl)
3674 && (decl.b[0] == '*' || decl.b[0] == '&'))
5210f3d0
JM
3675 {
3676 string_prepend (&decl, "(");
3677 string_append (&decl, ")");
3678 }
3679 string_append (&decl, "[");
3680 if (**mangled != '_')
3681 success = demangle_template_value_parm (work, mangled, &decl,
3682 tk_integral);
6599da04 3683 if (**mangled == '_')
4d17a06f
MM
3684 ++(*mangled);
3685 string_append (&decl, "]");
6599da04
JM
3686 break;
3687 }
3688
3689 /* A back reference to a previously seen type */
3690 case 'T':
3691 (*mangled)++;
03ef0c6c 3692 if (!get_count (mangled, &n) || n < 0 || n >= work -> ntypes)
6599da04
JM
3693 {
3694 success = 0;
3695 }
3696 else
1841e25c
MB
3697 for (i = 0; i < work->nproctypes; i++)
3698 if (work -> proctypevec [i] == n)
3699 success = 0;
3700
3701 if (success)
3702 {
3703 is_proctypevec = 1;
3704 push_processed_type (work, n);
3705 remembered_type = work->typevec[n];
6599da04
JM
3706 mangled = &remembered_type;
3707 }
3708 break;
3709
3710 /* A function */
3711 case 'F':
3712 (*mangled)++;
09007174
JM
3713 if (!STRING_EMPTY (&decl)
3714 && (decl.b[0] == '*' || decl.b[0] == '&'))
6599da04
JM
3715 {
3716 string_prepend (&decl, "(");
3717 string_append (&decl, ")");
3718 }
3719 /* After picking off the function args, we expect to either find the
3720 function return type (preceded by an '_') or the end of the
3721 string. */
9923cc56 3722 if (!demangle_nested_args (work, mangled, &decl)
6599da04
JM
3723 || (**mangled != '_' && **mangled != '\0'))
3724 {
3725 success = 0;
9923cc56 3726 break;
6599da04
JM
3727 }
3728 if (success && (**mangled == '_'))
9923cc56 3729 (*mangled)++;
6599da04
JM
3730 break;
3731
3732 case 'M':
6599da04 3733 {
91063b51 3734 type_quals = TYPE_UNQUALIFIED;
6599da04
JM
3735
3736 member = **mangled == 'M';
3737 (*mangled)++;
6599da04
JM
3738
3739 string_append (&decl, ")");
7c56a6ce
MM
3740
3741 /* We don't need to prepend `::' for a qualified name;
3742 demangle_qualified will do that for us. */
3743 if (**mangled != 'Q')
3744 string_prepend (&decl, SCOPE_STRING (work));
3745
f6bbde28 3746 if (ISDIGIT ((unsigned char)**mangled))
6599da04
JM
3747 {
3748 n = consume_count (mangled);
9d229989
JB
3749 if (n == -1
3750 || (int) strlen (*mangled) < n)
6599da04
JM
3751 {
3752 success = 0;
3753 break;
3754 }
3755 string_prependn (&decl, *mangled, n);
3756 *mangled += n;
3757 }
391cdef0
MM
3758 else if (**mangled == 'X' || **mangled == 'Y')
3759 {
3760 string temp;
3761 do_type (work, mangled, &temp);
3762 string_prepends (&decl, &temp);
902cf50c 3763 string_delete (&temp);
391cdef0
MM
3764 }
3765 else if (**mangled == 't')
6599da04
JM
3766 {
3767 string temp;
3768 string_init (&temp);
9923cc56
MM
3769 success = demangle_template (work, mangled, &temp,
3770 NULL, 1, 1);
6599da04
JM
3771 if (success)
3772 {
3773 string_prependn (&decl, temp.b, temp.p - temp.b);
902cf50c 3774 string_delete (&temp);
6599da04
JM
3775 }
3776 else
ac8345a5
AB
3777 {
3778 string_delete (&temp);
3779 break;
3780 }
6599da04 3781 }
7c56a6ce
MM
3782 else if (**mangled == 'Q')
3783 {
3784 success = demangle_qualified (work, mangled, &decl,
3785 /*isfuncnam=*/0,
3786 /*append=*/0);
3787 if (!success)
3788 break;
3789 }
391cdef0
MM
3790 else
3791 {
3792 success = 0;
3793 break;
3794 }
3795
6599da04
JM
3796 string_prepend (&decl, "(");
3797 if (member)
3798 {
91063b51 3799 switch (**mangled)
6599da04 3800 {
91063b51
MM
3801 case 'C':
3802 case 'V':
3803 case 'u':
3804 type_quals |= code_for_qualifier (**mangled);
6599da04 3805 (*mangled)++;
91063b51
MM
3806 break;
3807
3808 default:
3809 break;
6599da04 3810 }
91063b51 3811
0d0bfbf4 3812 if (*(*mangled) != 'F')
6599da04
JM
3813 {
3814 success = 0;
3815 break;
3816 }
0d0bfbf4 3817 (*mangled)++;
6599da04 3818 }
9923cc56 3819 if ((member && !demangle_nested_args (work, mangled, &decl))
6599da04
JM
3820 || **mangled != '_')
3821 {
3822 success = 0;
3823 break;
3824 }
3825 (*mangled)++;
3826 if (! PRINT_ANSI_QUALIFIERS)
3827 {
3828 break;
3829 }
91063b51 3830 if (type_quals != TYPE_UNQUALIFIED)
6599da04
JM
3831 {
3832 APPEND_BLANK (&decl);
91063b51 3833 string_append (&decl, qualifier_string (type_quals));
6599da04
JM
3834 }
3835 break;
3836 }
3837 case 'G':
3838 (*mangled)++;
3839 break;
3840
3841 case 'C':
1cc75298 3842 case 'V':
91063b51 3843 case 'u':
6599da04
JM
3844 if (PRINT_ANSI_QUALIFIERS)
3845 {
3846 if (!STRING_EMPTY (&decl))
91063b51
MM
3847 string_prepend (&decl, " ");
3848
3849 string_prepend (&decl, demangle_qualifier (**mangled));
6599da04 3850 }
1cc75298 3851 (*mangled)++;
6599da04
JM
3852 break;
3853 /*
3854 }
3855 */
3856
3857 /* fall through */
3858 default:
3859 done = 1;
3860 break;
3861 }
3862 }
3863
5210f3d0 3864 if (success) switch (**mangled)
6599da04
JM
3865 {
3866 /* A qualified name, such as "Outer::Inner". */
3867 case 'Q':
5e5199e8
AM
3868 case 'K':
3869 {
5e5199e8 3870 success = demangle_qualified (work, mangled, result, 0, 1);
5e5199e8
AM
3871 break;
3872 }
3873
3874 /* A back reference to a previously seen squangled type */
3875 case 'B':
3876 (*mangled)++;
03ef0c6c 3877 if (!get_count (mangled, &n) || n < 0 || n >= work -> numb)
5210f3d0 3878 success = 0;
5e5199e8 3879 else
4d17a06f 3880 string_append (result, work->btypevec[n]);
6599da04
JM
3881 break;
3882
19ddc834
JM
3883 case 'X':
3884 case 'Y':
3885 /* A template parm. We substitute the corresponding argument. */
3886 {
3887 int idx;
19ddc834
JM
3888
3889 (*mangled)++;
3890 idx = consume_count_with_underscores (mangled);
3891
2363489c 3892 if (idx == -1
19ddc834
JM
3893 || (work->tmpl_argvec && idx >= work->ntmpl_args)
3894 || consume_count_with_underscores (mangled) == -1)
3895 {
3896 success = 0;
3897 break;
3898 }
3899
3900 if (work->tmpl_argvec)
3901 string_append (result, work->tmpl_argvec[idx]);
3902 else
b60fe4a7 3903 string_append_template_idx (result, idx);
19ddc834
JM
3904
3905 success = 1;
3906 }
3907 break;
3908
6599da04
JM
3909 default:
3910 success = demangle_fund_type (work, mangled, result);
4d17a06f
MM
3911 if (tk == tk_none)
3912 tk = (type_kind_t) success;
6599da04
JM
3913 break;
3914 }
3915
3916 if (success)
3917 {
3918 if (!STRING_EMPTY (&decl))
3919 {
3920 string_append (result, " ");
3921 string_appends (result, &decl);
3922 }
3923 }
3924 else
4d17a06f 3925 string_delete (result);
6599da04 3926 string_delete (&decl);
4d17a06f 3927
1841e25c
MB
3928 if (is_proctypevec)
3929 pop_processed_type (work);
3930
4d17a06f
MM
3931 if (success)
3932 /* Assume an integral type, if we're not sure. */
3933 return (int) ((tk == tk_none) ? tk_integral : tk);
3934 else
3935 return 0;
6599da04
JM
3936}
3937
3938/* Given a pointer to a type string that represents a fundamental type
3939 argument (int, long, unsigned int, etc) in TYPE, a pointer to the
3940 string in which the demangled output is being built in RESULT, and
3941 the WORK structure, decode the types and add them to the result.
3942
3943 For example:
3944
3945 "Ci" => "const int"
3946 "Sl" => "signed long"
3947 "CUs" => "const unsigned short"
3948
4d17a06f 3949 The value returned is really a type_kind_t. */
6599da04
JM
3950
3951static int
500d7701
GDR
3952demangle_fund_type (struct work_stuff *work,
3953 const char **mangled, string *result)
6599da04
JM
3954{
3955 int done = 0;
3956 int success = 1;
824bceb0 3957 char buf[INTBUF_SIZE + 5 /* 'int%u_t' */];
e9958132 3958 unsigned int dec = 0;
4d17a06f
MM
3959 type_kind_t tk = tk_integral;
3960
6599da04
JM
3961 /* First pick off any type qualifiers. There can be more than one. */
3962
3963 while (!done)
3964 {
3965 switch (**mangled)
3966 {
3967 case 'C':
91063b51
MM
3968 case 'V':
3969 case 'u':
6599da04
JM
3970 if (PRINT_ANSI_QUALIFIERS)
3971 {
e8fc8222
AM
3972 if (!STRING_EMPTY (result))
3973 string_prepend (result, " ");
3974 string_prepend (result, demangle_qualifier (**mangled));
6599da04 3975 }
e8fc8222 3976 (*mangled)++;
6599da04
JM
3977 break;
3978 case 'U':
3979 (*mangled)++;
3980 APPEND_BLANK (result);
3981 string_append (result, "unsigned");
3982 break;
3983 case 'S': /* signed char only */
3984 (*mangled)++;
3985 APPEND_BLANK (result);
3986 string_append (result, "signed");
3987 break;
6599da04
JM
3988 case 'J':
3989 (*mangled)++;
3990 APPEND_BLANK (result);
19ddc834 3991 string_append (result, "__complex");
6599da04
JM
3992 break;
3993 default:
3994 done = 1;
3995 break;
3996 }
3997 }
3998
3999 /* Now pick off the fundamental type. There can be only one. */
4000
4001 switch (**mangled)
4002 {
4003 case '\0':
4004 case '_':
4005 break;
4006 case 'v':
4007 (*mangled)++;
4008 APPEND_BLANK (result);
4009 string_append (result, "void");
4010 break;
4011 case 'x':
4012 (*mangled)++;
4013 APPEND_BLANK (result);
4014 string_append (result, "long long");
4015 break;
4016 case 'l':
4017 (*mangled)++;
4018 APPEND_BLANK (result);
4019 string_append (result, "long");
4020 break;
4021 case 'i':
4022 (*mangled)++;
4023 APPEND_BLANK (result);
4024 string_append (result, "int");
4025 break;
4026 case 's':
4027 (*mangled)++;
4028 APPEND_BLANK (result);
4029 string_append (result, "short");
4030 break;
4031 case 'b':
4032 (*mangled)++;
4033 APPEND_BLANK (result);
4034 string_append (result, "bool");
4d17a06f 4035 tk = tk_bool;
6599da04
JM
4036 break;
4037 case 'c':
4038 (*mangled)++;
4039 APPEND_BLANK (result);
4040 string_append (result, "char");
4d17a06f 4041 tk = tk_char;
6599da04
JM
4042 break;
4043 case 'w':
4044 (*mangled)++;
4045 APPEND_BLANK (result);
4046 string_append (result, "wchar_t");
4d17a06f 4047 tk = tk_char;
6599da04
JM
4048 break;
4049 case 'r':
4050 (*mangled)++;
4051 APPEND_BLANK (result);
4052 string_append (result, "long double");
4d17a06f 4053 tk = tk_real;
6599da04
JM
4054 break;
4055 case 'd':
4056 (*mangled)++;
4057 APPEND_BLANK (result);
4058 string_append (result, "double");
4d17a06f 4059 tk = tk_real;
6599da04
JM
4060 break;
4061 case 'f':
4062 (*mangled)++;
4063 APPEND_BLANK (result);
4064 string_append (result, "float");
4d17a06f 4065 tk = tk_real;
6599da04
JM
4066 break;
4067 case 'G':
4068 (*mangled)++;
f6bbde28 4069 if (!ISDIGIT ((unsigned char)**mangled))
6599da04
JM
4070 {
4071 success = 0;
4072 break;
4073 }
c4ec8585 4074 /* fall through */
6e6e34b7 4075 case 'I':
53504016 4076 (*mangled)++;
6e6e34b7
BK
4077 if (**mangled == '_')
4078 {
4079 int i;
53504016 4080 (*mangled)++;
c5a855ce 4081 for (i = 0;
e797ff70 4082 i < (long) sizeof (buf) - 1 && **mangled && **mangled != '_';
53504016 4083 (*mangled)++, i++)
6e6e34b7 4084 buf[i] = **mangled;
c5a855ce
JB
4085 if (**mangled != '_')
4086 {
4087 success = 0;
4088 break;
4089 }
6e6e34b7 4090 buf[i] = '\0';
53504016 4091 (*mangled)++;
6e6e34b7
BK
4092 }
4093 else
4094 {
4095 strncpy (buf, *mangled, 2);
c5a855ce 4096 buf[2] = '\0';
53504016 4097 *mangled += min (strlen (*mangled), 2);
6e6e34b7 4098 }
2363489c 4099 sscanf (buf, "%x", &dec);
e9958132 4100 sprintf (buf, "int%u_t", dec);
6e6e34b7
BK
4101 APPEND_BLANK (result);
4102 string_append (result, buf);
4103 break;
4104
6599da04
JM
4105 /* fall through */
4106 /* An explicit type, such as "6mytype" or "7integer" */
4107 case '0':
4108 case '1':
4109 case '2':
4110 case '3':
4111 case '4':
4112 case '5':
4113 case '6':
4114 case '7':
4115 case '8':
4116 case '9':
5e5199e8
AM
4117 {
4118 int bindex = register_Btype (work);
4119 string btype;
4120 string_init (&btype);
4121 if (demangle_class_name (work, mangled, &btype)) {
4122 remember_Btype (work, btype.b, LEN_STRING (&btype), bindex);
4123 APPEND_BLANK (result);
4124 string_appends (result, &btype);
4125 }
2363489c 4126 else
5e5199e8
AM
4127 success = 0;
4128 string_delete (&btype);
4129 break;
6599da04 4130 }
6599da04 4131 case 't':
5e5199e8 4132 {
902cf50c
DJ
4133 string btype;
4134 string_init (&btype);
9923cc56 4135 success = demangle_template (work, mangled, &btype, 0, 1, 1);
5e5199e8 4136 string_appends (result, &btype);
902cf50c 4137 string_delete (&btype);
5e5199e8
AM
4138 break;
4139 }
6599da04
JM
4140 default:
4141 success = 0;
4142 break;
4143 }
4144
4d17a06f 4145 return success ? ((int) tk) : 0;
6599da04
JM
4146}
4147
70d5ccef
DT
4148
4149/* Handle a template's value parameter for HP aCC (extension from ARM)
4150 **mangled points to 'S' or 'U' */
4151
4152static int
500d7701
GDR
4153do_hpacc_template_const_value (struct work_stuff *work ATTRIBUTE_UNUSED,
4154 const char **mangled, string *result)
70d5ccef
DT
4155{
4156 int unsigned_const;
4157
4158 if (**mangled != 'U' && **mangled != 'S')
4159 return 0;
2363489c 4160
70d5ccef
DT
4161 unsigned_const = (**mangled == 'U');
4162
4163 (*mangled)++;
4164
4165 switch (**mangled)
4166 {
4167 case 'N':
4168 string_append (result, "-");
2363489c 4169 /* fall through */
70d5ccef
DT
4170 case 'P':
4171 (*mangled)++;
4172 break;
4173 case 'M':
2363489c 4174 /* special case for -2^31 */
70d5ccef
DT
4175 string_append (result, "-2147483648");
4176 (*mangled)++;
4177 return 1;
4178 default:
4179 return 0;
4180 }
4181
4182 /* We have to be looking at an integer now */
f6bbde28 4183 if (!(ISDIGIT ((unsigned char)**mangled)))
70d5ccef
DT
4184 return 0;
4185
4186 /* We only deal with integral values for template
4187 parameters -- so it's OK to look only for digits */
f6bbde28 4188 while (ISDIGIT ((unsigned char)**mangled))
70d5ccef
DT
4189 {
4190 char_str[0] = **mangled;
4191 string_append (result, char_str);
4192 (*mangled)++;
4193 }
4194
4195 if (unsigned_const)
4196 string_append (result, "U");
4197
4198 /* FIXME? Some day we may have 64-bit (or larger :-) ) constants
4199 with L or LL suffixes. pai/1997-09-03 */
2363489c
UD
4200
4201 return 1; /* success */
70d5ccef
DT
4202}
4203
4204/* Handle a template's literal parameter for HP aCC (extension from ARM)
4205 **mangled is pointing to the 'A' */
4206
4207static int
500d7701
GDR
4208do_hpacc_template_literal (struct work_stuff *work, const char **mangled,
4209 string *result)
70d5ccef
DT
4210{
4211 int literal_len = 0;
70d5ccef
DT
4212 char * recurse;
4213 char * recurse_dem;
2363489c 4214
70d5ccef
DT
4215 if (**mangled != 'A')
4216 return 0;
4217
4218 (*mangled)++;
4219
4220 literal_len = consume_count (mangled);
4221
03ef0c6c
MB
4222 if (literal_len <= 0
4223 || literal_len > (long) strlen (*mangled))
70d5ccef
DT
4224 return 0;
4225
4226 /* Literal parameters are names of arrays, functions, etc. and the
4227 canonical representation uses the address operator */
4228 string_append (result, "&");
4229
2363489c 4230 /* Now recursively demangle the literal name */
d7cf8390 4231 recurse = XNEWVEC (char, literal_len + 1);
70d5ccef
DT
4232 memcpy (recurse, *mangled, literal_len);
4233 recurse[literal_len] = '\000';
4234
4235 recurse_dem = cplus_demangle (recurse, work->options);
2363489c 4236
70d5ccef
DT
4237 if (recurse_dem)
4238 {
4239 string_append (result, recurse_dem);
4240 free (recurse_dem);
4241 }
4242 else
4243 {
4244 string_appendn (result, *mangled, literal_len);
4245 }
4246 (*mangled) += literal_len;
4247 free (recurse);
4248
4249 return 1;
4250}
4251
4252static int
500d7701 4253snarf_numeric_literal (const char **args, string *arg)
70d5ccef
DT
4254{
4255 if (**args == '-')
4256 {
4257 char_str[0] = '-';
4258 string_append (arg, char_str);
4259 (*args)++;
4260 }
4261 else if (**args == '+')
4262 (*args)++;
2363489c 4263
f6bbde28 4264 if (!ISDIGIT ((unsigned char)**args))
70d5ccef
DT
4265 return 0;
4266
f6bbde28 4267 while (ISDIGIT ((unsigned char)**args))
70d5ccef
DT
4268 {
4269 char_str[0] = **args;
4270 string_append (arg, char_str);
4271 (*args)++;
4272 }
4273
4274 return 1;
4275}
4276
9923cc56
MM
4277/* Demangle the next argument, given by MANGLED into RESULT, which
4278 *should be an uninitialized* string. It will be initialized here,
4279 and free'd should anything go wrong. */
6599da04
JM
4280
4281static int
500d7701 4282do_arg (struct work_stuff *work, const char **mangled, string *result)
6599da04 4283{
9923cc56
MM
4284 /* Remember where we started so that we can record the type, for
4285 non-squangling type remembering. */
6599da04
JM
4286 const char *start = *mangled;
4287
9923cc56
MM
4288 string_init (result);
4289
4290 if (work->nrepeats > 0)
6599da04 4291 {
9923cc56
MM
4292 --work->nrepeats;
4293
4294 if (work->previous_argument == 0)
4295 return 0;
4296
2363489c 4297 /* We want to reissue the previous type in this argument list. */
9923cc56
MM
4298 string_appends (result, work->previous_argument);
4299 return 1;
6599da04 4300 }
9923cc56
MM
4301
4302 if (**mangled == 'n')
4303 {
4304 /* A squangling-style repeat. */
4305 (*mangled)++;
4306 work->nrepeats = consume_count(mangled);
4307
9d229989 4308 if (work->nrepeats <= 0)
9923cc56
MM
4309 /* This was not a repeat count after all. */
4310 return 0;
4311
4312 if (work->nrepeats > 9)
4313 {
4314 if (**mangled != '_')
4315 /* The repeat count should be followed by an '_' in this
4316 case. */
4317 return 0;
4318 else
4319 (*mangled)++;
4320 }
2363489c 4321
9923cc56
MM
4322 /* Now, the repeat is all set up. */
4323 return do_arg (work, mangled, result);
4324 }
4325
4326 /* Save the result in WORK->previous_argument so that we can find it
4327 if it's repeated. Note that saving START is not good enough: we
4328 do not want to add additional types to the back-referenceable
4329 type vector when processing a repeated type. */
4330 if (work->previous_argument)
902cf50c 4331 string_delete (work->previous_argument);
6599da04 4332 else
d7cf8390 4333 work->previous_argument = XNEW (string);
9923cc56
MM
4334
4335 if (!do_type (work, mangled, work->previous_argument))
4336 return 0;
4337
4338 string_appends (result, work->previous_argument);
4339
4340 remember_type (work, start, *mangled - start);
4341 return 1;
6599da04
JM
4342}
4343
1841e25c
MB
4344static void
4345push_processed_type (struct work_stuff *work, int typevec_index)
4346{
4347 if (work->nproctypes >= work->proctypevec_size)
4348 {
4349 if (!work->proctypevec_size)
4350 {
4351 work->proctypevec_size = 4;
4352 work->proctypevec = XNEWVEC (int, work->proctypevec_size);
4353 }
4354 else
4355 {
4356 if (work->proctypevec_size < 16)
4357 /* Double when small. */
4358 work->proctypevec_size *= 2;
4359 else
4360 {
4361 /* Grow slower when large. */
4362 if (work->proctypevec_size > (INT_MAX / 3) * 2)
4363 xmalloc_failed (INT_MAX);
4364 work->proctypevec_size = (work->proctypevec_size * 3 / 2);
4365 }
4366 work->proctypevec
4367 = XRESIZEVEC (int, work->proctypevec, work->proctypevec_size);
4368 }
4369 }
4370 work->proctypevec [work->nproctypes++] = typevec_index;
4371}
4372
4373static void
4374pop_processed_type (struct work_stuff *work)
4375{
4376 work->nproctypes--;
4377}
4378
6599da04 4379static void
500d7701 4380remember_type (struct work_stuff *work, const char *start, int len)
6599da04
JM
4381{
4382 char *tem;
4383
9923cc56
MM
4384 if (work->forgetting_types)
4385 return;
4386
6599da04
JM
4387 if (work -> ntypes >= work -> typevec_size)
4388 {
4389 if (work -> typevec_size == 0)
4390 {
4391 work -> typevec_size = 3;
d7cf8390 4392 work -> typevec = XNEWVEC (char *, work->typevec_size);
6599da04
JM
4393 }
4394 else
4395 {
bdf66f77
MB
4396 if (work -> typevec_size > INT_MAX / 2)
4397 xmalloc_failed (INT_MAX);
6599da04
JM
4398 work -> typevec_size *= 2;
4399 work -> typevec
d7cf8390 4400 = XRESIZEVEC (char *, work->typevec, work->typevec_size);
6599da04
JM
4401 }
4402 }
d7cf8390 4403 tem = XNEWVEC (char, len + 1);
6599da04
JM
4404 memcpy (tem, start, len);
4405 tem[len] = '\0';
4406 work -> typevec[work -> ntypes++] = tem;
4407}
4408
5e5199e8
AM
4409
4410/* Remember a K type class qualifier. */
4411static void
500d7701 4412remember_Ktype (struct work_stuff *work, const char *start, int len)
5e5199e8
AM
4413{
4414 char *tem;
4415
4416 if (work -> numk >= work -> ksize)
4417 {
4418 if (work -> ksize == 0)
4419 {
4420 work -> ksize = 5;
d7cf8390 4421 work -> ktypevec = XNEWVEC (char *, work->ksize);
5e5199e8
AM
4422 }
4423 else
4424 {
bdf66f77
MB
4425 if (work -> ksize > INT_MAX / 2)
4426 xmalloc_failed (INT_MAX);
5e5199e8
AM
4427 work -> ksize *= 2;
4428 work -> ktypevec
d7cf8390 4429 = XRESIZEVEC (char *, work->ktypevec, work->ksize);
5e5199e8
AM
4430 }
4431 }
d7cf8390 4432 tem = XNEWVEC (char, len + 1);
5e5199e8
AM
4433 memcpy (tem, start, len);
4434 tem[len] = '\0';
4435 work -> ktypevec[work -> numk++] = tem;
4436}
4437
4438/* Register a B code, and get an index for it. B codes are registered
2363489c 4439 as they are seen, rather than as they are completed, so map<temp<char> >
5e5199e8
AM
4440 registers map<temp<char> > as B0, and temp<char> as B1 */
4441
4442static int
500d7701 4443register_Btype (struct work_stuff *work)
5e5199e8
AM
4444{
4445 int ret;
2363489c 4446
5e5199e8
AM
4447 if (work -> numb >= work -> bsize)
4448 {
4449 if (work -> bsize == 0)
4450 {
4451 work -> bsize = 5;
d7cf8390 4452 work -> btypevec = XNEWVEC (char *, work->bsize);
5e5199e8
AM
4453 }
4454 else
4455 {
bdf66f77
MB
4456 if (work -> bsize > INT_MAX / 2)
4457 xmalloc_failed (INT_MAX);
5e5199e8
AM
4458 work -> bsize *= 2;
4459 work -> btypevec
d7cf8390 4460 = XRESIZEVEC (char *, work->btypevec, work->bsize);
5e5199e8
AM
4461 }
4462 }
4463 ret = work -> numb++;
4464 work -> btypevec[ret] = NULL;
4465 return(ret);
4466}
4467
4468/* Store a value into a previously registered B code type. */
4469
4470static void
500d7701
GDR
4471remember_Btype (struct work_stuff *work, const char *start,
4472 int len, int index)
5e5199e8
AM
4473{
4474 char *tem;
4475
d7cf8390 4476 tem = XNEWVEC (char, len + 1);
5e5199e8
AM
4477 memcpy (tem, start, len);
4478 tem[len] = '\0';
4479 work -> btypevec[index] = tem;
4480}
4481
4482/* Lose all the info related to B and K type codes. */
4483static void
500d7701 4484forget_B_and_K_types (struct work_stuff *work)
5e5199e8
AM
4485{
4486 int i;
4487
4488 while (work -> numk > 0)
4489 {
4490 i = --(work -> numk);
4491 if (work -> ktypevec[i] != NULL)
4492 {
4493 free (work -> ktypevec[i]);
4494 work -> ktypevec[i] = NULL;
4495 }
4496 }
4497
4498 while (work -> numb > 0)
4499 {
4500 i = --(work -> numb);
4501 if (work -> btypevec[i] != NULL)
4502 {
4503 free (work -> btypevec[i]);
4504 work -> btypevec[i] = NULL;
4505 }
4506 }
4507}
6599da04
JM
4508/* Forget the remembered types, but not the type vector itself. */
4509
4510static void
500d7701 4511forget_types (struct work_stuff *work)
6599da04
JM
4512{
4513 int i;
4514
4515 while (work -> ntypes > 0)
4516 {
4517 i = --(work -> ntypes);
4518 if (work -> typevec[i] != NULL)
4519 {
4520 free (work -> typevec[i]);
4521 work -> typevec[i] = NULL;
4522 }
4523 }
4524}
4525
4526/* Process the argument list part of the signature, after any class spec
4527 has been consumed, as well as the first 'F' character (if any). For
4528 example:
4529
4530 "__als__3fooRT0" => process "RT0"
4531 "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i"
4532
4533 DECLP must be already initialised, usually non-empty. It won't be freed
4534 on failure.
4535
4536 Note that g++ differs significantly from ARM and lucid style mangling
4537 with regards to references to previously seen types. For example, given
4538 the source fragment:
4539
4540 class foo {
4541 public:
4542 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
4543 };
4544
4545 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
4546 void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
4547
4548 g++ produces the names:
4549
4550 __3fooiRT0iT2iT2
4551 foo__FiR3fooiT1iT1
4552
4553 while lcc (and presumably other ARM style compilers as well) produces:
4554
4555 foo__FiR3fooT1T2T1T2
4556 __ct__3fooFiR3fooT1T2T1T2
4557
9923cc56
MM
4558 Note that g++ bases its type numbers starting at zero and counts all
4559 previously seen types, while lucid/ARM bases its type numbers starting
6599da04
JM
4560 at one and only considers types after it has seen the 'F' character
4561 indicating the start of the function args. For lucid/ARM style, we
4562 account for this difference by discarding any previously seen types when
4563 we see the 'F' character, and subtracting one from the type number
4564 reference.
4565
4566 */
4567
4568static int
500d7701
GDR
4569demangle_args (struct work_stuff *work, const char **mangled,
4570 string *declp)
6599da04
JM
4571{
4572 string arg;
4573 int need_comma = 0;
4574 int r;
4575 int t;
4576 const char *tem;
4577 char temptype;
4578
4579 if (PRINT_ARG_TYPES)
4580 {
4581 string_append (declp, "(");
4582 if (**mangled == '\0')
4583 {
4584 string_append (declp, "void");
4585 }
4586 }
4587
9923cc56
MM
4588 while ((**mangled != '_' && **mangled != '\0' && **mangled != 'e')
4589 || work->nrepeats > 0)
6599da04
JM
4590 {
4591 if ((**mangled == 'N') || (**mangled == 'T'))
4592 {
4593 temptype = *(*mangled)++;
2363489c 4594
6599da04
JM
4595 if (temptype == 'N')
4596 {
4597 if (!get_count (mangled, &r))
4598 {
4599 return (0);
4600 }
4601 }
4602 else
4603 {
4604 r = 1;
4605 }
70d5ccef 4606 if ((HP_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING) && work -> ntypes >= 10)
6599da04
JM
4607 {
4608 /* If we have 10 or more types we might have more than a 1 digit
4609 index so we'll have to consume the whole count here. This
4610 will lose if the next thing is a type name preceded by a
4611 count but it's impossible to demangle that case properly
4612 anyway. Eg if we already have 12 types is T12Pc "(..., type1,
4613 Pc, ...)" or "(..., type12, char *, ...)" */
9d229989 4614 if ((t = consume_count(mangled)) <= 0)
6599da04
JM
4615 {
4616 return (0);
4617 }
4618 }
4619 else
4620 {
4621 if (!get_count (mangled, &t))
4622 {
4623 return (0);
4624 }
4625 }
70d5ccef 4626 if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
6599da04
JM
4627 {
4628 t--;
4629 }
4630 /* Validate the type index. Protect against illegal indices from
4631 malformed type strings. */
4632 if ((t < 0) || (t >= work -> ntypes))
4633 {
4634 return (0);
4635 }
9923cc56 4636 while (work->nrepeats > 0 || --r >= 0)
6599da04
JM
4637 {
4638 tem = work -> typevec[t];
4639 if (need_comma && PRINT_ARG_TYPES)
4640 {
4641 string_append (declp, ", ");
4642 }
1841e25c 4643 push_processed_type (work, t);
6599da04
JM
4644 if (!do_arg (work, &tem, &arg))
4645 {
1841e25c 4646 pop_processed_type (work);
6599da04
JM
4647 return (0);
4648 }
1841e25c 4649 pop_processed_type (work);
6599da04
JM
4650 if (PRINT_ARG_TYPES)
4651 {
4652 string_appends (declp, &arg);
4653 }
4654 string_delete (&arg);
4655 need_comma = 1;
4656 }
4657 }
4658 else
4659 {
9923cc56
MM
4660 if (need_comma && PRINT_ARG_TYPES)
4661 string_append (declp, ", ");
6599da04 4662 if (!do_arg (work, mangled, &arg))
9923cc56 4663 return (0);
6599da04 4664 if (PRINT_ARG_TYPES)
9923cc56 4665 string_appends (declp, &arg);
6599da04
JM
4666 string_delete (&arg);
4667 need_comma = 1;
4668 }
4669 }
4670
4671 if (**mangled == 'e')
4672 {
4673 (*mangled)++;
4674 if (PRINT_ARG_TYPES)
4675 {
4676 if (need_comma)
4677 {
4678 string_append (declp, ",");
4679 }
4680 string_append (declp, "...");
4681 }
4682 }
4683
4684 if (PRINT_ARG_TYPES)
4685 {
4686 string_append (declp, ")");
4687 }
4688 return (1);
4689}
4690
9923cc56
MM
4691/* Like demangle_args, but for demangling the argument lists of function
4692 and method pointers or references, not top-level declarations. */
4693
d94f5c58 4694static int
500d7701
GDR
4695demangle_nested_args (struct work_stuff *work, const char **mangled,
4696 string *declp)
9923cc56
MM
4697{
4698 string* saved_previous_argument;
4699 int result;
4700 int saved_nrepeats;
4701
4702 /* The G++ name-mangling algorithm does not remember types on nested
4703 argument lists, unless -fsquangling is used, and in that case the
4704 type vector updated by remember_type is not used. So, we turn
4705 off remembering of types here. */
4706 ++work->forgetting_types;
4707
4708 /* For the repeat codes used with -fsquangling, we must keep track of
4709 the last argument. */
4710 saved_previous_argument = work->previous_argument;
4711 saved_nrepeats = work->nrepeats;
4712 work->previous_argument = 0;
4713 work->nrepeats = 0;
4714
4715 /* Actually demangle the arguments. */
4716 result = demangle_args (work, mangled, declp);
2363489c 4717
9923cc56
MM
4718 /* Restore the previous_argument field. */
4719 if (work->previous_argument)
902cf50c
DJ
4720 {
4721 string_delete (work->previous_argument);
4722 free ((char *) work->previous_argument);
4723 }
9923cc56 4724 work->previous_argument = saved_previous_argument;
3510075c 4725 --work->forgetting_types;
9923cc56
MM
4726 work->nrepeats = saved_nrepeats;
4727
4728 return result;
4729}
4730
62b445b3
TJB
4731/* Returns 1 if a valid function name was found or 0 otherwise. */
4732
4733static int
500d7701
GDR
4734demangle_function_name (struct work_stuff *work, const char **mangled,
4735 string *declp, const char *scan)
6599da04 4736{
9ee02b5c 4737 size_t i;
6599da04
JM
4738 string type;
4739 const char *tem;
4740
4741 string_appendn (declp, (*mangled), scan - (*mangled));
4742 string_need (declp, 1);
4743 *(declp -> p) = '\0';
4744
4745 /* Consume the function name, including the "__" separating the name
4746 from the signature. We are guaranteed that SCAN points to the
4747 separator. */
4748
4749 (*mangled) = scan + 2;
70d5ccef
DT
4750 /* We may be looking at an instantiation of a template function:
4751 foo__Xt1t2_Ft3t4, where t1, t2, ... are template arguments and a
4752 following _F marks the start of the function arguments. Handle
4753 the template arguments first. */
2363489c 4754
70d5ccef
DT
4755 if (HP_DEMANGLING && (**mangled == 'X'))
4756 {
4757 demangle_arm_hp_template (work, mangled, 0, declp);
4758 /* This leaves MANGLED pointing to the 'F' marking func args */
4759 }
6599da04 4760
70d5ccef 4761 if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
6599da04
JM
4762 {
4763
4764 /* See if we have an ARM style constructor or destructor operator.
4765 If so, then just record it, clear the decl, and return.
4766 We can't build the actual constructor/destructor decl until later,
4767 when we recover the class name from the signature. */
4768
4769 if (strcmp (declp -> b, "__ct") == 0)
4770 {
4771 work -> constructor += 1;
4772 string_clear (declp);
62b445b3 4773 return 1;
6599da04
JM
4774 }
4775 else if (strcmp (declp -> b, "__dt") == 0)
4776 {
4777 work -> destructor += 1;
4778 string_clear (declp);
62b445b3 4779 return 1;
6599da04
JM
4780 }
4781 }
4782
2363489c 4783 if (declp->p - declp->b >= 3
6599da04
JM
4784 && declp->b[0] == 'o'
4785 && declp->b[1] == 'p'
4786 && strchr (cplus_markers, declp->b[2]) != NULL)
4787 {
4788 /* see if it's an assignment expression */
4789 if (declp->p - declp->b >= 10 /* op$assign_ */
4790 && memcmp (declp->b + 3, "assign_", 7) == 0)
4791 {
2f26c11d 4792 for (i = 0; i < ARRAY_SIZE (optable); i++)
6599da04 4793 {
9ee02b5c 4794 int len = declp->p - declp->b - 10;
91e0f659 4795 if ((int) strlen (optable[i].in) == len
6599da04
JM
4796 && memcmp (optable[i].in, declp->b + 10, len) == 0)
4797 {
4798 string_clear (declp);
4799 string_append (declp, "operator");
4800 string_append (declp, optable[i].out);
4801 string_append (declp, "=");
4802 break;
4803 }
4804 }
4805 }
4806 else
4807 {
2f26c11d 4808 for (i = 0; i < ARRAY_SIZE (optable); i++)
6599da04
JM
4809 {
4810 int len = declp->p - declp->b - 3;
2363489c 4811 if ((int) strlen (optable[i].in) == len
6599da04
JM
4812 && memcmp (optable[i].in, declp->b + 3, len) == 0)
4813 {
4814 string_clear (declp);
4815 string_append (declp, "operator");
4816 string_append (declp, optable[i].out);
4817 break;
4818 }
4819 }
4820 }
4821 }
4822 else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0
4823 && strchr (cplus_markers, declp->b[4]) != NULL)
4824 {
4825 /* type conversion operator */
4826 tem = declp->b + 5;
4827 if (do_type (work, &tem, &type))
4828 {
4829 string_clear (declp);
4830 string_append (declp, "operator ");
4831 string_appends (declp, &type);
4832 string_delete (&type);
4833 }
4834 }
4835 else if (declp->b[0] == '_' && declp->b[1] == '_'
4836 && declp->b[2] == 'o' && declp->b[3] == 'p')
4837 {
4838 /* ANSI. */
4839 /* type conversion operator. */
4840 tem = declp->b + 4;
4841 if (do_type (work, &tem, &type))
4842 {
4843 string_clear (declp);
4844 string_append (declp, "operator ");
4845 string_appends (declp, &type);
4846 string_delete (&type);
4847 }
4848 }
4849 else if (declp->b[0] == '_' && declp->b[1] == '_'
f6bbde28
ZW
4850 && ISLOWER((unsigned char)declp->b[2])
4851 && ISLOWER((unsigned char)declp->b[3]))
6599da04
JM
4852 {
4853 if (declp->b[4] == '\0')
4854 {
4855 /* Operator. */
2f26c11d 4856 for (i = 0; i < ARRAY_SIZE (optable); i++)
6599da04
JM
4857 {
4858 if (strlen (optable[i].in) == 2
4859 && memcmp (optable[i].in, declp->b + 2, 2) == 0)
4860 {
4861 string_clear (declp);
4862 string_append (declp, "operator");
4863 string_append (declp, optable[i].out);
4864 break;
4865 }
4866 }
4867 }
4868 else
4869 {
4870 if (declp->b[2] == 'a' && declp->b[5] == '\0')
4871 {
4872 /* Assignment. */
2f26c11d 4873 for (i = 0; i < ARRAY_SIZE (optable); i++)
6599da04
JM
4874 {
4875 if (strlen (optable[i].in) == 3
4876 && memcmp (optable[i].in, declp->b + 2, 3) == 0)
4877 {
4878 string_clear (declp);
4879 string_append (declp, "operator");
4880 string_append (declp, optable[i].out);
4881 break;
2363489c 4882 }
6599da04
JM
4883 }
4884 }
4885 }
4886 }
62b445b3
TJB
4887
4888 /* If a function name was obtained but it's not valid, we were not
4889 successful. */
4890 if (LEN_STRING (declp) == 1 && declp->b[0] == '.')
4891 return 0;
4892 else
4893 return 1;
6599da04
JM
4894}
4895
4896/* a mini string-handling package */
4897
4898static void
500d7701 4899string_need (string *s, int n)
6599da04
JM
4900{
4901 int tem;
4902
4903 if (s->b == NULL)
4904 {
4905 if (n < 32)
4906 {
4907 n = 32;
4908 }
d7cf8390 4909 s->p = s->b = XNEWVEC (char, n);
6599da04
JM
4910 s->e = s->b + n;
4911 }
4912 else if (s->e - s->p < n)
4913 {
4914 tem = s->p - s->b;
bdf66f77
MB
4915 if (n > INT_MAX / 2 - tem)
4916 xmalloc_failed (INT_MAX);
6599da04
JM
4917 n += tem;
4918 n *= 2;
d7cf8390 4919 s->b = XRESIZEVEC (char, s->b, n);
6599da04
JM
4920 s->p = s->b + tem;
4921 s->e = s->b + n;
4922 }
4923}
4924
4925static void
500d7701 4926string_delete (string *s)
6599da04
JM
4927{
4928 if (s->b != NULL)
4929 {
4930 free (s->b);
4931 s->b = s->e = s->p = NULL;
4932 }
4933}
4934
4935static void
500d7701 4936string_init (string *s)
6599da04
JM
4937{
4938 s->b = s->p = s->e = NULL;
4939}
4940
2363489c 4941static void
500d7701 4942string_clear (string *s)
6599da04
JM
4943{
4944 s->p = s->b;
4945}
4946
4947#if 0
4948
4949static int
500d7701 4950string_empty (string *s)
6599da04
JM
4951{
4952 return (s->b == s->p);
4953}
4954
4955#endif
4956
4957static void
500d7701 4958string_append (string *p, const char *s)
6599da04
JM
4959{
4960 int n;
4961 if (s == NULL || *s == '\0')
4962 return;
4963 n = strlen (s);
4964 string_need (p, n);
4965 memcpy (p->p, s, n);
4966 p->p += n;
4967}
4968
4969static void
500d7701 4970string_appends (string *p, string *s)
6599da04
JM
4971{
4972 int n;
4973
4974 if (s->b != s->p)
4975 {
4976 n = s->p - s->b;
4977 string_need (p, n);
4978 memcpy (p->p, s->b, n);
4979 p->p += n;
4980 }
4981}
4982
4983static void
500d7701 4984string_appendn (string *p, const char *s, int n)
6599da04
JM
4985{
4986 if (n != 0)
4987 {
4988 string_need (p, n);
4989 memcpy (p->p, s, n);
4990 p->p += n;
4991 }
4992}
4993
4994static void
500d7701 4995string_prepend (string *p, const char *s)
6599da04
JM
4996{
4997 if (s != NULL && *s != '\0')
4998 {
4999 string_prependn (p, s, strlen (s));
5000 }
5001}
5002
5003static void
500d7701 5004string_prepends (string *p, string *s)
6599da04
JM
5005{
5006 if (s->b != s->p)
5007 {
5008 string_prependn (p, s->b, s->p - s->b);
5009 }
5010}
5011
5012static void
500d7701 5013string_prependn (string *p, const char *s, int n)
6599da04
JM
5014{
5015 char *q;
5016
5017 if (n != 0)
5018 {
5019 string_need (p, n);
5020 for (q = p->p - 1; q >= p->b; q--)
5021 {
5022 q[n] = q[0];
5023 }
5024 memcpy (p->b, s, n);
5025 p->p += n;
5026 }
5027}
5028
b60fe4a7 5029static void
500d7701 5030string_append_template_idx (string *s, int idx)
b60fe4a7
MM
5031{
5032 char buf[INTBUF_SIZE + 1 /* 'T' */];
5033 sprintf(buf, "T%d", idx);
5034 string_append (s, buf);
5035}