]>
Commit | Line | Data |
---|---|---|
bd6946d1 | 1 | /* Demangler for g++ V3 ABI. |
f2e6f32e | 2 | Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 |
8935c4b3 | 3 | Free Software Foundation, Inc. |
bd6946d1 | 4 | Written by Ian Lance Taylor <ian@wasabisystems.com>. |
69afa80d | 5 | |
2b81b2c9 | 6 | This file is part of the libiberty library, which is part of GCC. |
759e8187 | 7 | |
2b81b2c9 | 8 | This file is free software; you can redistribute it and/or modify |
69afa80d AS |
9 | it under the terms of the GNU General Public License as published by |
10 | the Free Software Foundation; either version 2 of the License, or | |
11 | (at your option) any later version. | |
12 | ||
b3dd43df MM |
13 | In addition to the permissions in the GNU General Public License, the |
14 | Free Software Foundation gives you unlimited permission to link the | |
15 | compiled version of this file into combinations with other programs, | |
16 | and to distribute those combinations without any restriction coming | |
17 | from the use of this file. (The General Public License restrictions | |
18 | do apply in other respects; for example, they cover modification of | |
19 | the file, and distribution when not linked into a combined | |
20 | executable.) | |
21 | ||
69afa80d AS |
22 | This program is distributed in the hope that it will be useful, |
23 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
24 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
25 | GNU General Public License for more details. | |
26 | ||
27 | You should have received a copy of the GNU General Public License | |
28 | along with this program; if not, write to the Free Software | |
ee58dffd | 29 | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. |
69afa80d AS |
30 | */ |
31 | ||
a51753e4 ILT |
32 | /* This code implements a demangler for the g++ V3 ABI. The ABI is |
33 | described on this web page: | |
34 | http://www.codesourcery.com/cxx-abi/abi.html#mangling | |
35 | ||
36 | This code was written while looking at the demangler written by | |
37 | Alex Samuel <samuel@codesourcery.com>. | |
38 | ||
39 | This code first pulls the mangled name apart into a list of | |
40 | components, and then walks the list generating the demangled | |
41 | name. | |
42 | ||
43 | This file will normally define the following functions, q.v.: | |
44 | char *cplus_demangle_v3(const char *mangled, int options) | |
45 | char *java_demangle_v3(const char *mangled) | |
456cc5cf SB |
46 | int cplus_demangle_v3_callback(const char *mangled, int options, |
47 | demangle_callbackref callback) | |
48 | int java_demangle_v3_callback(const char *mangled, | |
49 | demangle_callbackref callback) | |
a51753e4 ILT |
50 | enum gnu_v3_ctor_kinds is_gnu_v3_mangled_ctor (const char *name) |
51 | enum gnu_v3_dtor_kinds is_gnu_v3_mangled_dtor (const char *name) | |
52 | ||
5e777af5 ILT |
53 | Also, the interface to the component list is public, and defined in |
54 | demangle.h. The interface consists of these types, which are | |
55 | defined in demangle.h: | |
56 | enum demangle_component_type | |
57 | struct demangle_component | |
456cc5cf | 58 | demangle_callbackref |
5e777af5 ILT |
59 | and these functions defined in this file: |
60 | cplus_demangle_fill_name | |
61 | cplus_demangle_fill_extended_operator | |
62 | cplus_demangle_fill_ctor | |
63 | cplus_demangle_fill_dtor | |
64 | cplus_demangle_print | |
456cc5cf | 65 | cplus_demangle_print_callback |
5e777af5 ILT |
66 | and other functions defined in the file cp-demint.c. |
67 | ||
68 | This file also defines some other functions and variables which are | |
69 | only to be used by the file cp-demint.c. | |
70 | ||
a51753e4 ILT |
71 | Preprocessor macros you can define while compiling this file: |
72 | ||
73 | IN_LIBGCC2 | |
456cc5cf | 74 | If defined, this file defines the following functions, q.v.: |
a51753e4 ILT |
75 | char *__cxa_demangle (const char *mangled, char *buf, size_t *len, |
76 | int *status) | |
456cc5cf SB |
77 | int __gcclibcxx_demangle_callback (const char *, |
78 | void (*) | |
79 | (const char *, size_t, void *), | |
80 | void *) | |
81 | instead of cplus_demangle_v3[_callback]() and | |
82 | java_demangle_v3[_callback](). | |
a51753e4 ILT |
83 | |
84 | IN_GLIBCPP_V3 | |
456cc5cf SB |
85 | If defined, this file defines only __cxa_demangle() and |
86 | __gcclibcxx_demangle_callback(), and no other publically visible | |
87 | functions or variables. | |
a51753e4 ILT |
88 | |
89 | STANDALONE_DEMANGLER | |
90 | If defined, this file defines a main() function which demangles | |
91 | any arguments, or, if none, demangles stdin. | |
92 | ||
93 | CP_DEMANGLE_DEBUG | |
94 | If defined, turns on debugging mode, which prints information on | |
95 | stdout about the mangled string. This is not generally useful. | |
96 | */ | |
97 | ||
456cc5cf SB |
98 | #if defined (_AIX) && !defined (__GNUC__) |
99 | #pragma alloca | |
100 | #endif | |
101 | ||
69afa80d AS |
102 | #ifdef HAVE_CONFIG_H |
103 | #include "config.h" | |
104 | #endif | |
105 | ||
bd6946d1 | 106 | #include <stdio.h> |
8502a100 | 107 | |
69afa80d AS |
108 | #ifdef HAVE_STDLIB_H |
109 | #include <stdlib.h> | |
110 | #endif | |
69afa80d AS |
111 | #ifdef HAVE_STRING_H |
112 | #include <string.h> | |
113 | #endif | |
114 | ||
456cc5cf SB |
115 | #ifdef HAVE_ALLOCA_H |
116 | # include <alloca.h> | |
117 | #else | |
118 | # ifndef alloca | |
119 | # ifdef __GNUC__ | |
120 | # define alloca __builtin_alloca | |
121 | # else | |
122 | extern char *alloca (); | |
123 | # endif /* __GNUC__ */ | |
124 | # endif /* alloca */ | |
125 | #endif /* HAVE_ALLOCA_H */ | |
126 | ||
69afa80d AS |
127 | #include "ansidecl.h" |
128 | #include "libiberty.h" | |
7eb23b1f | 129 | #include "demangle.h" |
5e777af5 ILT |
130 | #include "cp-demangle.h" |
131 | ||
132 | /* If IN_GLIBCPP_V3 is defined, some functions are made static. We | |
133 | also rename them via #define to avoid compiler errors when the | |
134 | static definition conflicts with the extern declaration in a header | |
135 | file. */ | |
136 | #ifdef IN_GLIBCPP_V3 | |
137 | ||
138 | #define CP_STATIC_IF_GLIBCPP_V3 static | |
139 | ||
140 | #define cplus_demangle_fill_name d_fill_name | |
9486db4f | 141 | static int d_fill_name (struct demangle_component *, const char *, int); |
5e777af5 ILT |
142 | |
143 | #define cplus_demangle_fill_extended_operator d_fill_extended_operator | |
144 | static int | |
9486db4f GDR |
145 | d_fill_extended_operator (struct demangle_component *, int, |
146 | struct demangle_component *); | |
5e777af5 ILT |
147 | |
148 | #define cplus_demangle_fill_ctor d_fill_ctor | |
149 | static int | |
9486db4f GDR |
150 | d_fill_ctor (struct demangle_component *, enum gnu_v3_ctor_kinds, |
151 | struct demangle_component *); | |
5e777af5 ILT |
152 | |
153 | #define cplus_demangle_fill_dtor d_fill_dtor | |
154 | static int | |
9486db4f GDR |
155 | d_fill_dtor (struct demangle_component *, enum gnu_v3_dtor_kinds, |
156 | struct demangle_component *); | |
5e777af5 ILT |
157 | |
158 | #define cplus_demangle_mangled_name d_mangled_name | |
9486db4f | 159 | static struct demangle_component *d_mangled_name (struct d_info *, int); |
5e777af5 ILT |
160 | |
161 | #define cplus_demangle_type d_type | |
9486db4f | 162 | static struct demangle_component *d_type (struct d_info *); |
5e777af5 ILT |
163 | |
164 | #define cplus_demangle_print d_print | |
9486db4f | 165 | static char *d_print (int, const struct demangle_component *, int, size_t *); |
5e777af5 | 166 | |
456cc5cf SB |
167 | #define cplus_demangle_print_callback d_print_callback |
168 | static int d_print_callback (int, const struct demangle_component *, | |
169 | demangle_callbackref, void *); | |
170 | ||
5e777af5 | 171 | #define cplus_demangle_init_info d_init_info |
9486db4f | 172 | static void d_init_info (const char *, int, size_t, struct d_info *); |
5e777af5 ILT |
173 | |
174 | #else /* ! defined(IN_GLIBCPP_V3) */ | |
175 | #define CP_STATIC_IF_GLIBCPP_V3 | |
176 | #endif /* ! defined(IN_GLIBCPP_V3) */ | |
69afa80d | 177 | |
2d6c4025 ILT |
178 | /* See if the compiler supports dynamic arrays. */ |
179 | ||
180 | #ifdef __GNUC__ | |
181 | #define CP_DYNAMIC_ARRAYS | |
182 | #else | |
183 | #ifdef __STDC__ | |
184 | #ifdef __STDC_VERSION__ | |
185 | #if __STDC_VERSION__ >= 199901L | |
186 | #define CP_DYNAMIC_ARRAYS | |
187 | #endif /* __STDC__VERSION >= 199901L */ | |
188 | #endif /* defined (__STDC_VERSION__) */ | |
189 | #endif /* defined (__STDC__) */ | |
190 | #endif /* ! defined (__GNUC__) */ | |
191 | ||
a51753e4 ILT |
192 | /* We avoid pulling in the ctype tables, to prevent pulling in |
193 | additional unresolved symbols when this code is used in a library. | |
194 | FIXME: Is this really a valid reason? This comes from the original | |
195 | V3 demangler code. | |
bd6946d1 | 196 | |
a51753e4 | 197 | As of this writing this file has the following undefined references |
456cc5cf SB |
198 | when compiled with -DIN_GLIBCPP_V3: realloc, free, memcpy, strcpy, |
199 | strcat, strlen. */ | |
bd6946d1 | 200 | |
bd6946d1 | 201 | #define IS_DIGIT(c) ((c) >= '0' && (c) <= '9') |
a51753e4 ILT |
202 | #define IS_UPPER(c) ((c) >= 'A' && (c) <= 'Z') |
203 | #define IS_LOWER(c) ((c) >= 'a' && (c) <= 'z') | |
051664b0 | 204 | |
31e0ab1f AS |
205 | /* The prefix prepended by GCC to an identifier represnting the |
206 | anonymous namespace. */ | |
207 | #define ANONYMOUS_NAMESPACE_PREFIX "_GLOBAL_" | |
bd6946d1 ILT |
208 | #define ANONYMOUS_NAMESPACE_PREFIX_LEN \ |
209 | (sizeof (ANONYMOUS_NAMESPACE_PREFIX) - 1) | |
31e0ab1f | 210 | |
374caa50 ILT |
211 | /* Information we keep for the standard substitutions. */ |
212 | ||
213 | struct d_standard_sub_info | |
214 | { | |
215 | /* The code for this substitution. */ | |
216 | char code; | |
217 | /* The simple string it expands to. */ | |
218 | const char *simple_expansion; | |
2d6c4025 ILT |
219 | /* The length of the simple expansion. */ |
220 | int simple_len; | |
374caa50 ILT |
221 | /* The results of a full, verbose, expansion. This is used when |
222 | qualifying a constructor/destructor, or when in verbose mode. */ | |
223 | const char *full_expansion; | |
2d6c4025 ILT |
224 | /* The length of the full expansion. */ |
225 | int full_len; | |
374caa50 ILT |
226 | /* What to set the last_name field of d_info to; NULL if we should |
227 | not set it. This is only relevant when qualifying a | |
228 | constructor/destructor. */ | |
229 | const char *set_last_name; | |
2d6c4025 ILT |
230 | /* The length of set_last_name. */ |
231 | int set_last_name_len; | |
374caa50 ILT |
232 | }; |
233 | ||
5e777af5 | 234 | /* Accessors for subtrees of struct demangle_component. */ |
69afa80d | 235 | |
bd6946d1 ILT |
236 | #define d_left(dc) ((dc)->u.s_binary.left) |
237 | #define d_right(dc) ((dc)->u.s_binary.right) | |
238 | ||
bd6946d1 | 239 | /* A list of templates. This is used while printing. */ |
69afa80d | 240 | |
bd6946d1 ILT |
241 | struct d_print_template |
242 | { | |
243 | /* Next template on the list. */ | |
244 | struct d_print_template *next; | |
245 | /* This template. */ | |
d7cf8390 | 246 | const struct demangle_component *template_decl; |
bd6946d1 | 247 | }; |
69afa80d | 248 | |
bd6946d1 | 249 | /* A list of type modifiers. This is used while printing. */ |
69afa80d | 250 | |
bd6946d1 ILT |
251 | struct d_print_mod |
252 | { | |
253 | /* Next modifier on the list. These are in the reverse of the order | |
254 | in which they appeared in the mangled string. */ | |
255 | struct d_print_mod *next; | |
256 | /* The modifier. */ | |
5e777af5 | 257 | const struct demangle_component *mod; |
bd6946d1 ILT |
258 | /* Whether this modifier was printed. */ |
259 | int printed; | |
81dc098b ILT |
260 | /* The list of templates which applies to this modifier. */ |
261 | struct d_print_template *templates; | |
bd6946d1 | 262 | }; |
69afa80d | 263 | |
456cc5cf | 264 | /* We use these structures to hold information during printing. */ |
bd6946d1 | 265 | |
456cc5cf | 266 | struct d_growable_string |
bd6946d1 | 267 | { |
bd6946d1 ILT |
268 | /* Buffer holding the result. */ |
269 | char *buf; | |
270 | /* Current length of data in buffer. */ | |
271 | size_t len; | |
272 | /* Allocated size of buffer. */ | |
273 | size_t alc; | |
456cc5cf SB |
274 | /* Set to 1 if we had a memory allocation failure. */ |
275 | int allocation_failure; | |
276 | }; | |
277 | ||
278 | enum { D_PRINT_BUFFER_LENGTH = 256 }; | |
279 | struct d_print_info | |
280 | { | |
456cc5cf SB |
281 | /* Fixed-length allocated buffer for demangled data, flushed to the |
282 | callback with a NUL termination once full. */ | |
283 | char buf[D_PRINT_BUFFER_LENGTH]; | |
284 | /* Current length of data in buffer. */ | |
285 | size_t len; | |
286 | /* The last character printed, saved individually so that it survives | |
287 | any buffer flush. */ | |
288 | char last_char; | |
289 | /* Callback function to handle demangled buffer flush. */ | |
290 | demangle_callbackref callback; | |
291 | /* Opaque callback argument. */ | |
292 | void *opaque; | |
bd6946d1 ILT |
293 | /* The current list of templates, if any. */ |
294 | struct d_print_template *templates; | |
295 | /* The current list of modifiers (e.g., pointer, reference, etc.), | |
296 | if any. */ | |
297 | struct d_print_mod *modifiers; | |
456cc5cf SB |
298 | /* Set to 1 if we saw a demangling error. */ |
299 | int demangle_failure; | |
38179091 JM |
300 | /* The current index into any template argument packs we are using |
301 | for printing. */ | |
302 | int pack_index; | |
9c4d7e52 JJ |
303 | /* Number of d_print_flush calls so far. */ |
304 | unsigned long int flush_count; | |
bd6946d1 | 305 | }; |
7dce2eff | 306 | |
69afa80d | 307 | #ifdef CP_DEMANGLE_DEBUG |
9486db4f | 308 | static void d_dump (struct demangle_component *, int); |
69afa80d | 309 | #endif |
5e777af5 ILT |
310 | |
311 | static struct demangle_component * | |
9486db4f | 312 | d_make_empty (struct d_info *); |
5e777af5 ILT |
313 | |
314 | static struct demangle_component * | |
9486db4f GDR |
315 | d_make_comp (struct d_info *, enum demangle_component_type, |
316 | struct demangle_component *, | |
317 | struct demangle_component *); | |
5e777af5 ILT |
318 | |
319 | static struct demangle_component * | |
9486db4f | 320 | d_make_name (struct d_info *, const char *, int); |
5e777af5 | 321 | |
431f321f L |
322 | static struct demangle_component * |
323 | d_make_demangle_mangled_name (struct d_info *, const char *); | |
324 | ||
5e777af5 | 325 | static struct demangle_component * |
9486db4f GDR |
326 | d_make_builtin_type (struct d_info *, |
327 | const struct demangle_builtin_type_info *); | |
5e777af5 ILT |
328 | |
329 | static struct demangle_component * | |
9486db4f GDR |
330 | d_make_operator (struct d_info *, |
331 | const struct demangle_operator_info *); | |
5e777af5 ILT |
332 | |
333 | static struct demangle_component * | |
9486db4f GDR |
334 | d_make_extended_operator (struct d_info *, int, |
335 | struct demangle_component *); | |
5e777af5 ILT |
336 | |
337 | static struct demangle_component * | |
9486db4f GDR |
338 | d_make_ctor (struct d_info *, enum gnu_v3_ctor_kinds, |
339 | struct demangle_component *); | |
5e777af5 ILT |
340 | |
341 | static struct demangle_component * | |
9486db4f GDR |
342 | d_make_dtor (struct d_info *, enum gnu_v3_dtor_kinds, |
343 | struct demangle_component *); | |
5e777af5 ILT |
344 | |
345 | static struct demangle_component * | |
9486db4f | 346 | d_make_template_param (struct d_info *, long); |
5e777af5 ILT |
347 | |
348 | static struct demangle_component * | |
9486db4f | 349 | d_make_sub (struct d_info *, const char *, int); |
5e777af5 ILT |
350 | |
351 | static int | |
9486db4f | 352 | has_return_type (struct demangle_component *); |
5e777af5 ILT |
353 | |
354 | static int | |
9486db4f | 355 | is_ctor_dtor_or_conversion (struct demangle_component *); |
5e777af5 | 356 | |
9486db4f | 357 | static struct demangle_component *d_encoding (struct d_info *, int); |
5e777af5 | 358 | |
9486db4f | 359 | static struct demangle_component *d_name (struct d_info *); |
5e777af5 | 360 | |
9486db4f | 361 | static struct demangle_component *d_nested_name (struct d_info *); |
5e777af5 | 362 | |
9486db4f | 363 | static struct demangle_component *d_prefix (struct d_info *); |
5e777af5 | 364 | |
9486db4f | 365 | static struct demangle_component *d_unqualified_name (struct d_info *); |
5e777af5 | 366 | |
9486db4f | 367 | static struct demangle_component *d_source_name (struct d_info *); |
5e777af5 | 368 | |
9486db4f | 369 | static long d_number (struct d_info *); |
5e777af5 | 370 | |
9486db4f | 371 | static struct demangle_component *d_identifier (struct d_info *, int); |
5e777af5 | 372 | |
9486db4f | 373 | static struct demangle_component *d_operator_name (struct d_info *); |
5e777af5 | 374 | |
9486db4f | 375 | static struct demangle_component *d_special_name (struct d_info *); |
5e777af5 | 376 | |
9486db4f | 377 | static int d_call_offset (struct d_info *, int); |
5e777af5 | 378 | |
9486db4f | 379 | static struct demangle_component *d_ctor_dtor_name (struct d_info *); |
5e777af5 ILT |
380 | |
381 | static struct demangle_component ** | |
9486db4f | 382 | d_cv_qualifiers (struct d_info *, struct demangle_component **, int); |
5e777af5 | 383 | |
9eb85f27 JM |
384 | static struct demangle_component * |
385 | d_ref_qualifier (struct d_info *, struct demangle_component *); | |
386 | ||
5e777af5 | 387 | static struct demangle_component * |
9486db4f | 388 | d_function_type (struct d_info *); |
5e777af5 ILT |
389 | |
390 | static struct demangle_component * | |
9486db4f | 391 | d_bare_function_type (struct d_info *, int); |
5e777af5 ILT |
392 | |
393 | static struct demangle_component * | |
9486db4f | 394 | d_class_enum_type (struct d_info *); |
5e777af5 | 395 | |
9486db4f | 396 | static struct demangle_component *d_array_type (struct d_info *); |
5e777af5 | 397 | |
abfe01ce JM |
398 | static struct demangle_component *d_vector_type (struct d_info *); |
399 | ||
5e777af5 | 400 | static struct demangle_component * |
9486db4f | 401 | d_pointer_to_member_type (struct d_info *); |
5e777af5 ILT |
402 | |
403 | static struct demangle_component * | |
9486db4f | 404 | d_template_param (struct d_info *); |
5e777af5 | 405 | |
9486db4f | 406 | static struct demangle_component *d_template_args (struct d_info *); |
5e777af5 ILT |
407 | |
408 | static struct demangle_component * | |
9486db4f | 409 | d_template_arg (struct d_info *); |
5e777af5 | 410 | |
9486db4f | 411 | static struct demangle_component *d_expression (struct d_info *); |
5e777af5 | 412 | |
9486db4f | 413 | static struct demangle_component *d_expr_primary (struct d_info *); |
5e777af5 | 414 | |
9486db4f | 415 | static struct demangle_component *d_local_name (struct d_info *); |
5e777af5 | 416 | |
9486db4f | 417 | static int d_discriminator (struct d_info *); |
5e777af5 | 418 | |
d5f4eddd JM |
419 | static struct demangle_component *d_lambda (struct d_info *); |
420 | ||
421 | static struct demangle_component *d_unnamed_type (struct d_info *); | |
422 | ||
2d2b02c4 CC |
423 | static struct demangle_component * |
424 | d_clone_suffix (struct d_info *, struct demangle_component *); | |
425 | ||
5e777af5 | 426 | static int |
9486db4f | 427 | d_add_substitution (struct d_info *, struct demangle_component *); |
5e777af5 | 428 | |
9486db4f | 429 | static struct demangle_component *d_substitution (struct d_info *, int); |
5e777af5 | 430 | |
456cc5cf | 431 | static void d_growable_string_init (struct d_growable_string *, size_t); |
5e777af5 | 432 | |
456cc5cf SB |
433 | static inline void |
434 | d_growable_string_resize (struct d_growable_string *, size_t); | |
5e777af5 | 435 | |
456cc5cf SB |
436 | static inline void |
437 | d_growable_string_append_buffer (struct d_growable_string *, | |
438 | const char *, size_t); | |
5e777af5 | 439 | static void |
456cc5cf SB |
440 | d_growable_string_callback_adapter (const char *, size_t, void *); |
441 | ||
442 | static void | |
743a99db | 443 | d_print_init (struct d_print_info *, demangle_callbackref, void *); |
456cc5cf SB |
444 | |
445 | static inline void d_print_error (struct d_print_info *); | |
446 | ||
447 | static inline int d_print_saw_error (struct d_print_info *); | |
448 | ||
449 | static inline void d_print_flush (struct d_print_info *); | |
450 | ||
451 | static inline void d_append_char (struct d_print_info *, char); | |
5e777af5 | 452 | |
456cc5cf SB |
453 | static inline void d_append_buffer (struct d_print_info *, |
454 | const char *, size_t); | |
455 | ||
456 | static inline void d_append_string (struct d_print_info *, const char *); | |
457 | ||
458 | static inline char d_last_char (struct d_print_info *); | |
5e777af5 ILT |
459 | |
460 | static void | |
743a99db | 461 | d_print_comp (struct d_print_info *, int, const struct demangle_component *); |
5e777af5 ILT |
462 | |
463 | static void | |
9486db4f | 464 | d_print_java_identifier (struct d_print_info *, const char *, int); |
5e777af5 ILT |
465 | |
466 | static void | |
743a99db | 467 | d_print_mod_list (struct d_print_info *, int, struct d_print_mod *, int); |
5e777af5 ILT |
468 | |
469 | static void | |
743a99db | 470 | d_print_mod (struct d_print_info *, int, const struct demangle_component *); |
5e777af5 ILT |
471 | |
472 | static void | |
743a99db | 473 | d_print_function_type (struct d_print_info *, int, |
9486db4f GDR |
474 | const struct demangle_component *, |
475 | struct d_print_mod *); | |
5e777af5 ILT |
476 | |
477 | static void | |
743a99db | 478 | d_print_array_type (struct d_print_info *, int, |
9486db4f GDR |
479 | const struct demangle_component *, |
480 | struct d_print_mod *); | |
5e777af5 ILT |
481 | |
482 | static void | |
743a99db | 483 | d_print_expr_op (struct d_print_info *, int, const struct demangle_component *); |
5e777af5 ILT |
484 | |
485 | static void | |
743a99db | 486 | d_print_cast (struct d_print_info *, int, const struct demangle_component *); |
5e777af5 | 487 | |
456cc5cf SB |
488 | static int d_demangle_callback (const char *, int, |
489 | demangle_callbackref, void *); | |
9486db4f | 490 | static char *d_demangle (const char *, int, size_t *); |
bd6946d1 | 491 | |
69afa80d | 492 | #ifdef CP_DEMANGLE_DEBUG |
bd6946d1 ILT |
493 | |
494 | static void | |
9486db4f | 495 | d_dump (struct demangle_component *dc, int indent) |
69afa80d AS |
496 | { |
497 | int i; | |
69afa80d | 498 | |
bd6946d1 | 499 | if (dc == NULL) |
456cc5cf SB |
500 | { |
501 | if (indent == 0) | |
502 | printf ("failed demangling\n"); | |
503 | return; | |
504 | } | |
bd6946d1 ILT |
505 | |
506 | for (i = 0; i < indent; ++i) | |
507 | putchar (' '); | |
508 | ||
509 | switch (dc->type) | |
510 | { | |
5e777af5 | 511 | case DEMANGLE_COMPONENT_NAME: |
bd6946d1 ILT |
512 | printf ("name '%.*s'\n", dc->u.s_name.len, dc->u.s_name.s); |
513 | return; | |
7dbb85a7 JM |
514 | case DEMANGLE_COMPONENT_TAGGED_NAME: |
515 | printf ("tagged name\n"); | |
516 | d_dump (dc->u.s_binary.left, indent + 2); | |
517 | d_dump (dc->u.s_binary.right, indent + 2); | |
518 | return; | |
5e777af5 | 519 | case DEMANGLE_COMPONENT_TEMPLATE_PARAM: |
bd6946d1 ILT |
520 | printf ("template parameter %ld\n", dc->u.s_number.number); |
521 | return; | |
5e777af5 | 522 | case DEMANGLE_COMPONENT_CTOR: |
bd6946d1 ILT |
523 | printf ("constructor %d\n", (int) dc->u.s_ctor.kind); |
524 | d_dump (dc->u.s_ctor.name, indent + 2); | |
525 | return; | |
5e777af5 | 526 | case DEMANGLE_COMPONENT_DTOR: |
bd6946d1 ILT |
527 | printf ("destructor %d\n", (int) dc->u.s_dtor.kind); |
528 | d_dump (dc->u.s_dtor.name, indent + 2); | |
529 | return; | |
5e777af5 | 530 | case DEMANGLE_COMPONENT_SUB_STD: |
bd6946d1 ILT |
531 | printf ("standard substitution %s\n", dc->u.s_string.string); |
532 | return; | |
5e777af5 | 533 | case DEMANGLE_COMPONENT_BUILTIN_TYPE: |
bd6946d1 ILT |
534 | printf ("builtin type %s\n", dc->u.s_builtin.type->name); |
535 | return; | |
5e777af5 | 536 | case DEMANGLE_COMPONENT_OPERATOR: |
bd6946d1 ILT |
537 | printf ("operator %s\n", dc->u.s_operator.op->name); |
538 | return; | |
5e777af5 | 539 | case DEMANGLE_COMPONENT_EXTENDED_OPERATOR: |
bd6946d1 ILT |
540 | printf ("extended operator with %d args\n", |
541 | dc->u.s_extended_operator.args); | |
542 | d_dump (dc->u.s_extended_operator.name, indent + 2); | |
543 | return; | |
544 | ||
5e777af5 | 545 | case DEMANGLE_COMPONENT_QUAL_NAME: |
bd6946d1 ILT |
546 | printf ("qualified name\n"); |
547 | break; | |
5e777af5 | 548 | case DEMANGLE_COMPONENT_LOCAL_NAME: |
a91d1af0 ILT |
549 | printf ("local name\n"); |
550 | break; | |
5e777af5 | 551 | case DEMANGLE_COMPONENT_TYPED_NAME: |
bd6946d1 ILT |
552 | printf ("typed name\n"); |
553 | break; | |
5e777af5 | 554 | case DEMANGLE_COMPONENT_TEMPLATE: |
bd6946d1 ILT |
555 | printf ("template\n"); |
556 | break; | |
5e777af5 | 557 | case DEMANGLE_COMPONENT_VTABLE: |
bd6946d1 ILT |
558 | printf ("vtable\n"); |
559 | break; | |
5e777af5 | 560 | case DEMANGLE_COMPONENT_VTT: |
bd6946d1 ILT |
561 | printf ("VTT\n"); |
562 | break; | |
5e777af5 | 563 | case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE: |
bd6946d1 ILT |
564 | printf ("construction vtable\n"); |
565 | break; | |
5e777af5 | 566 | case DEMANGLE_COMPONENT_TYPEINFO: |
bd6946d1 ILT |
567 | printf ("typeinfo\n"); |
568 | break; | |
5e777af5 | 569 | case DEMANGLE_COMPONENT_TYPEINFO_NAME: |
bd6946d1 ILT |
570 | printf ("typeinfo name\n"); |
571 | break; | |
5e777af5 | 572 | case DEMANGLE_COMPONENT_TYPEINFO_FN: |
bd6946d1 ILT |
573 | printf ("typeinfo function\n"); |
574 | break; | |
5e777af5 | 575 | case DEMANGLE_COMPONENT_THUNK: |
bd6946d1 ILT |
576 | printf ("thunk\n"); |
577 | break; | |
5e777af5 | 578 | case DEMANGLE_COMPONENT_VIRTUAL_THUNK: |
bd6946d1 ILT |
579 | printf ("virtual thunk\n"); |
580 | break; | |
5e777af5 | 581 | case DEMANGLE_COMPONENT_COVARIANT_THUNK: |
bd6946d1 ILT |
582 | printf ("covariant thunk\n"); |
583 | break; | |
5e777af5 | 584 | case DEMANGLE_COMPONENT_JAVA_CLASS: |
bd6946d1 ILT |
585 | printf ("java class\n"); |
586 | break; | |
5e777af5 | 587 | case DEMANGLE_COMPONENT_GUARD: |
bd6946d1 ILT |
588 | printf ("guard\n"); |
589 | break; | |
5e777af5 | 590 | case DEMANGLE_COMPONENT_REFTEMP: |
bd6946d1 ILT |
591 | printf ("reference temporary\n"); |
592 | break; | |
15da2806 RH |
593 | case DEMANGLE_COMPONENT_HIDDEN_ALIAS: |
594 | printf ("hidden alias\n"); | |
595 | break; | |
0a35513e AH |
596 | case DEMANGLE_COMPONENT_TRANSACTION_CLONE: |
597 | printf ("transaction clone\n"); | |
598 | break; | |
599 | case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE: | |
600 | printf ("non-transaction clone\n"); | |
601 | break; | |
5e777af5 | 602 | case DEMANGLE_COMPONENT_RESTRICT: |
bd6946d1 ILT |
603 | printf ("restrict\n"); |
604 | break; | |
5e777af5 | 605 | case DEMANGLE_COMPONENT_VOLATILE: |
bd6946d1 ILT |
606 | printf ("volatile\n"); |
607 | break; | |
5e777af5 | 608 | case DEMANGLE_COMPONENT_CONST: |
bd6946d1 ILT |
609 | printf ("const\n"); |
610 | break; | |
5e777af5 | 611 | case DEMANGLE_COMPONENT_RESTRICT_THIS: |
a51753e4 ILT |
612 | printf ("restrict this\n"); |
613 | break; | |
5e777af5 | 614 | case DEMANGLE_COMPONENT_VOLATILE_THIS: |
a51753e4 ILT |
615 | printf ("volatile this\n"); |
616 | break; | |
5e777af5 | 617 | case DEMANGLE_COMPONENT_CONST_THIS: |
a51753e4 ILT |
618 | printf ("const this\n"); |
619 | break; | |
9eb85f27 JM |
620 | case DEMANGLE_COMPONENT_REFERENCE_THIS: |
621 | printf ("reference this\n"); | |
622 | break; | |
623 | case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: | |
624 | printf ("rvalue reference this\n"); | |
625 | break; | |
5e777af5 | 626 | case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: |
bd6946d1 ILT |
627 | printf ("vendor type qualifier\n"); |
628 | break; | |
5e777af5 | 629 | case DEMANGLE_COMPONENT_POINTER: |
bd6946d1 ILT |
630 | printf ("pointer\n"); |
631 | break; | |
5e777af5 | 632 | case DEMANGLE_COMPONENT_REFERENCE: |
bd6946d1 ILT |
633 | printf ("reference\n"); |
634 | break; | |
1ab28be5 DG |
635 | case DEMANGLE_COMPONENT_RVALUE_REFERENCE: |
636 | printf ("rvalue reference\n"); | |
637 | break; | |
5e777af5 | 638 | case DEMANGLE_COMPONENT_COMPLEX: |
bd6946d1 ILT |
639 | printf ("complex\n"); |
640 | break; | |
5e777af5 | 641 | case DEMANGLE_COMPONENT_IMAGINARY: |
bd6946d1 ILT |
642 | printf ("imaginary\n"); |
643 | break; | |
5e777af5 | 644 | case DEMANGLE_COMPONENT_VENDOR_TYPE: |
bd6946d1 ILT |
645 | printf ("vendor type\n"); |
646 | break; | |
5e777af5 | 647 | case DEMANGLE_COMPONENT_FUNCTION_TYPE: |
bd6946d1 ILT |
648 | printf ("function type\n"); |
649 | break; | |
5e777af5 | 650 | case DEMANGLE_COMPONENT_ARRAY_TYPE: |
bd6946d1 ILT |
651 | printf ("array type\n"); |
652 | break; | |
5e777af5 | 653 | case DEMANGLE_COMPONENT_PTRMEM_TYPE: |
bd6946d1 ILT |
654 | printf ("pointer to member type\n"); |
655 | break; | |
07523e7c JM |
656 | case DEMANGLE_COMPONENT_FIXED_TYPE: |
657 | printf ("fixed-point type\n"); | |
658 | break; | |
5e777af5 | 659 | case DEMANGLE_COMPONENT_ARGLIST: |
bd6946d1 ILT |
660 | printf ("argument list\n"); |
661 | break; | |
5e777af5 | 662 | case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: |
bd6946d1 ILT |
663 | printf ("template argument list\n"); |
664 | break; | |
4b6aaa99 JM |
665 | case DEMANGLE_COMPONENT_INITIALIZER_LIST: |
666 | printf ("initializer list\n"); | |
667 | break; | |
5e777af5 | 668 | case DEMANGLE_COMPONENT_CAST: |
bd6946d1 ILT |
669 | printf ("cast\n"); |
670 | break; | |
4b6aaa99 JM |
671 | case DEMANGLE_COMPONENT_NULLARY: |
672 | printf ("nullary operator\n"); | |
673 | break; | |
5e777af5 | 674 | case DEMANGLE_COMPONENT_UNARY: |
bd6946d1 ILT |
675 | printf ("unary operator\n"); |
676 | break; | |
5e777af5 | 677 | case DEMANGLE_COMPONENT_BINARY: |
bd6946d1 ILT |
678 | printf ("binary operator\n"); |
679 | break; | |
5e777af5 | 680 | case DEMANGLE_COMPONENT_BINARY_ARGS: |
bd6946d1 ILT |
681 | printf ("binary operator arguments\n"); |
682 | break; | |
5e777af5 | 683 | case DEMANGLE_COMPONENT_TRINARY: |
bd6946d1 ILT |
684 | printf ("trinary operator\n"); |
685 | break; | |
5e777af5 | 686 | case DEMANGLE_COMPONENT_TRINARY_ARG1: |
bd6946d1 ILT |
687 | printf ("trinary operator arguments 1\n"); |
688 | break; | |
5e777af5 | 689 | case DEMANGLE_COMPONENT_TRINARY_ARG2: |
bd6946d1 ILT |
690 | printf ("trinary operator arguments 1\n"); |
691 | break; | |
5e777af5 | 692 | case DEMANGLE_COMPONENT_LITERAL: |
bd6946d1 ILT |
693 | printf ("literal\n"); |
694 | break; | |
5e777af5 | 695 | case DEMANGLE_COMPONENT_LITERAL_NEG: |
374caa50 ILT |
696 | printf ("negative literal\n"); |
697 | break; | |
e5df4fb1 DD |
698 | case DEMANGLE_COMPONENT_JAVA_RESOURCE: |
699 | printf ("java resource\n"); | |
700 | break; | |
701 | case DEMANGLE_COMPONENT_COMPOUND_NAME: | |
702 | printf ("compound name\n"); | |
703 | break; | |
704 | case DEMANGLE_COMPONENT_CHARACTER: | |
705 | printf ("character '%c'\n", dc->u.s_character.character); | |
706 | return; | |
5a3d7e74 JM |
707 | case DEMANGLE_COMPONENT_DECLTYPE: |
708 | printf ("decltype\n"); | |
709 | break; | |
38179091 JM |
710 | case DEMANGLE_COMPONENT_PACK_EXPANSION: |
711 | printf ("pack expansion\n"); | |
712 | break; | |
7c424acd JM |
713 | case DEMANGLE_COMPONENT_TLS_INIT: |
714 | printf ("tls init function\n"); | |
715 | break; | |
716 | case DEMANGLE_COMPONENT_TLS_WRAPPER: | |
717 | printf ("tls wrapper function\n"); | |
718 | break; | |
622aac0b JM |
719 | case DEMANGLE_COMPONENT_DEFAULT_ARG: |
720 | printf ("default argument %d\n", dc->u.s_unary_num.num); | |
721 | d_dump (dc->u.s_unary_num.sub, indent+2); | |
722 | return; | |
723 | case DEMANGLE_COMPONENT_LAMBDA: | |
724 | printf ("lambda %d\n", dc->u.s_unary_num.num); | |
725 | d_dump (dc->u.s_unary_num.sub, indent+2); | |
726 | return; | |
69afa80d AS |
727 | } |
728 | ||
bd6946d1 ILT |
729 | d_dump (d_left (dc), indent + 2); |
730 | d_dump (d_right (dc), indent + 2); | |
731 | } | |
732 | ||
733 | #endif /* CP_DEMANGLE_DEBUG */ | |
734 | ||
5e777af5 ILT |
735 | /* Fill in a DEMANGLE_COMPONENT_NAME. */ |
736 | ||
737 | CP_STATIC_IF_GLIBCPP_V3 | |
738 | int | |
9486db4f | 739 | cplus_demangle_fill_name (struct demangle_component *p, const char *s, int len) |
5e777af5 ILT |
740 | { |
741 | if (p == NULL || s == NULL || len == 0) | |
742 | return 0; | |
743 | p->type = DEMANGLE_COMPONENT_NAME; | |
744 | p->u.s_name.s = s; | |
745 | p->u.s_name.len = len; | |
746 | return 1; | |
747 | } | |
748 | ||
749 | /* Fill in a DEMANGLE_COMPONENT_EXTENDED_OPERATOR. */ | |
750 | ||
751 | CP_STATIC_IF_GLIBCPP_V3 | |
752 | int | |
9486db4f GDR |
753 | cplus_demangle_fill_extended_operator (struct demangle_component *p, int args, |
754 | struct demangle_component *name) | |
5e777af5 ILT |
755 | { |
756 | if (p == NULL || args < 0 || name == NULL) | |
757 | return 0; | |
758 | p->type = DEMANGLE_COMPONENT_EXTENDED_OPERATOR; | |
759 | p->u.s_extended_operator.args = args; | |
760 | p->u.s_extended_operator.name = name; | |
761 | return 1; | |
762 | } | |
763 | ||
764 | /* Fill in a DEMANGLE_COMPONENT_CTOR. */ | |
765 | ||
766 | CP_STATIC_IF_GLIBCPP_V3 | |
767 | int | |
9486db4f GDR |
768 | cplus_demangle_fill_ctor (struct demangle_component *p, |
769 | enum gnu_v3_ctor_kinds kind, | |
770 | struct demangle_component *name) | |
5e777af5 ILT |
771 | { |
772 | if (p == NULL | |
773 | || name == NULL | |
7859dde7 | 774 | || (int) kind < gnu_v3_complete_object_ctor |
0a35513e | 775 | || (int) kind > gnu_v3_object_ctor_group) |
5e777af5 ILT |
776 | return 0; |
777 | p->type = DEMANGLE_COMPONENT_CTOR; | |
778 | p->u.s_ctor.kind = kind; | |
779 | p->u.s_ctor.name = name; | |
780 | return 1; | |
781 | } | |
782 | ||
783 | /* Fill in a DEMANGLE_COMPONENT_DTOR. */ | |
784 | ||
785 | CP_STATIC_IF_GLIBCPP_V3 | |
786 | int | |
9486db4f GDR |
787 | cplus_demangle_fill_dtor (struct demangle_component *p, |
788 | enum gnu_v3_dtor_kinds kind, | |
789 | struct demangle_component *name) | |
5e777af5 ILT |
790 | { |
791 | if (p == NULL | |
792 | || name == NULL | |
7859dde7 | 793 | || (int) kind < gnu_v3_deleting_dtor |
0a35513e | 794 | || (int) kind > gnu_v3_object_dtor_group) |
5e777af5 ILT |
795 | return 0; |
796 | p->type = DEMANGLE_COMPONENT_DTOR; | |
797 | p->u.s_dtor.kind = kind; | |
798 | p->u.s_dtor.name = name; | |
799 | return 1; | |
800 | } | |
801 | ||
bd6946d1 ILT |
802 | /* Add a new component. */ |
803 | ||
5e777af5 | 804 | static struct demangle_component * |
9486db4f | 805 | d_make_empty (struct d_info *di) |
bd6946d1 | 806 | { |
5e777af5 | 807 | struct demangle_component *p; |
bd6946d1 ILT |
808 | |
809 | if (di->next_comp >= di->num_comps) | |
810 | return NULL; | |
811 | p = &di->comps[di->next_comp]; | |
bd6946d1 ILT |
812 | ++di->next_comp; |
813 | return p; | |
814 | } | |
815 | ||
816 | /* Add a new generic component. */ | |
817 | ||
5e777af5 | 818 | static struct demangle_component * |
9486db4f GDR |
819 | d_make_comp (struct d_info *di, enum demangle_component_type type, |
820 | struct demangle_component *left, | |
821 | struct demangle_component *right) | |
bd6946d1 | 822 | { |
5e777af5 | 823 | struct demangle_component *p; |
bd6946d1 ILT |
824 | |
825 | /* We check for errors here. A typical error would be a NULL return | |
81dc098b ILT |
826 | from a subroutine. We catch those here, and return NULL |
827 | upward. */ | |
bd6946d1 ILT |
828 | switch (type) |
829 | { | |
830 | /* These types require two parameters. */ | |
5e777af5 ILT |
831 | case DEMANGLE_COMPONENT_QUAL_NAME: |
832 | case DEMANGLE_COMPONENT_LOCAL_NAME: | |
833 | case DEMANGLE_COMPONENT_TYPED_NAME: | |
7dbb85a7 | 834 | case DEMANGLE_COMPONENT_TAGGED_NAME: |
5e777af5 | 835 | case DEMANGLE_COMPONENT_TEMPLATE: |
d4f3ce5c | 836 | case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE: |
5e777af5 ILT |
837 | case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: |
838 | case DEMANGLE_COMPONENT_PTRMEM_TYPE: | |
839 | case DEMANGLE_COMPONENT_UNARY: | |
840 | case DEMANGLE_COMPONENT_BINARY: | |
841 | case DEMANGLE_COMPONENT_BINARY_ARGS: | |
842 | case DEMANGLE_COMPONENT_TRINARY: | |
843 | case DEMANGLE_COMPONENT_TRINARY_ARG1: | |
5e777af5 ILT |
844 | case DEMANGLE_COMPONENT_LITERAL: |
845 | case DEMANGLE_COMPONENT_LITERAL_NEG: | |
e5df4fb1 | 846 | case DEMANGLE_COMPONENT_COMPOUND_NAME: |
abfe01ce | 847 | case DEMANGLE_COMPONENT_VECTOR_TYPE: |
2d2b02c4 | 848 | case DEMANGLE_COMPONENT_CLONE: |
bd6946d1 ILT |
849 | if (left == NULL || right == NULL) |
850 | return NULL; | |
851 | break; | |
852 | ||
853 | /* These types only require one parameter. */ | |
5e777af5 ILT |
854 | case DEMANGLE_COMPONENT_VTABLE: |
855 | case DEMANGLE_COMPONENT_VTT: | |
5e777af5 ILT |
856 | case DEMANGLE_COMPONENT_TYPEINFO: |
857 | case DEMANGLE_COMPONENT_TYPEINFO_NAME: | |
858 | case DEMANGLE_COMPONENT_TYPEINFO_FN: | |
859 | case DEMANGLE_COMPONENT_THUNK: | |
860 | case DEMANGLE_COMPONENT_VIRTUAL_THUNK: | |
861 | case DEMANGLE_COMPONENT_COVARIANT_THUNK: | |
862 | case DEMANGLE_COMPONENT_JAVA_CLASS: | |
863 | case DEMANGLE_COMPONENT_GUARD: | |
7c424acd JM |
864 | case DEMANGLE_COMPONENT_TLS_INIT: |
865 | case DEMANGLE_COMPONENT_TLS_WRAPPER: | |
5e777af5 | 866 | case DEMANGLE_COMPONENT_REFTEMP: |
15da2806 | 867 | case DEMANGLE_COMPONENT_HIDDEN_ALIAS: |
0a35513e AH |
868 | case DEMANGLE_COMPONENT_TRANSACTION_CLONE: |
869 | case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE: | |
5e777af5 ILT |
870 | case DEMANGLE_COMPONENT_POINTER: |
871 | case DEMANGLE_COMPONENT_REFERENCE: | |
1ab28be5 | 872 | case DEMANGLE_COMPONENT_RVALUE_REFERENCE: |
5e777af5 ILT |
873 | case DEMANGLE_COMPONENT_COMPLEX: |
874 | case DEMANGLE_COMPONENT_IMAGINARY: | |
875 | case DEMANGLE_COMPONENT_VENDOR_TYPE: | |
5e777af5 | 876 | case DEMANGLE_COMPONENT_CAST: |
e5df4fb1 | 877 | case DEMANGLE_COMPONENT_JAVA_RESOURCE: |
5a3d7e74 | 878 | case DEMANGLE_COMPONENT_DECLTYPE: |
38179091 | 879 | case DEMANGLE_COMPONENT_PACK_EXPANSION: |
23b1a789 JK |
880 | case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS: |
881 | case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS: | |
4b6aaa99 JM |
882 | case DEMANGLE_COMPONENT_NULLARY: |
883 | case DEMANGLE_COMPONENT_TRINARY_ARG2: | |
bd6946d1 ILT |
884 | if (left == NULL) |
885 | return NULL; | |
886 | break; | |
887 | ||
888 | /* This needs a right parameter, but the left parameter can be | |
889 | empty. */ | |
5e777af5 | 890 | case DEMANGLE_COMPONENT_ARRAY_TYPE: |
4b6aaa99 | 891 | case DEMANGLE_COMPONENT_INITIALIZER_LIST: |
bd6946d1 ILT |
892 | if (right == NULL) |
893 | return NULL; | |
894 | break; | |
895 | ||
896 | /* These are allowed to have no parameters--in some cases they | |
897 | will be filled in later. */ | |
5e777af5 ILT |
898 | case DEMANGLE_COMPONENT_FUNCTION_TYPE: |
899 | case DEMANGLE_COMPONENT_RESTRICT: | |
900 | case DEMANGLE_COMPONENT_VOLATILE: | |
901 | case DEMANGLE_COMPONENT_CONST: | |
902 | case DEMANGLE_COMPONENT_RESTRICT_THIS: | |
903 | case DEMANGLE_COMPONENT_VOLATILE_THIS: | |
904 | case DEMANGLE_COMPONENT_CONST_THIS: | |
9eb85f27 JM |
905 | case DEMANGLE_COMPONENT_REFERENCE_THIS: |
906 | case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: | |
38179091 JM |
907 | case DEMANGLE_COMPONENT_ARGLIST: |
908 | case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: | |
bd6946d1 ILT |
909 | break; |
910 | ||
911 | /* Other types should not be seen here. */ | |
912 | default: | |
913 | return NULL; | |
69afa80d | 914 | } |
bd6946d1 | 915 | |
5e777af5 | 916 | p = d_make_empty (di); |
bd6946d1 | 917 | if (p != NULL) |
69afa80d | 918 | { |
5e777af5 | 919 | p->type = type; |
bd6946d1 ILT |
920 | p->u.s_binary.left = left; |
921 | p->u.s_binary.right = right; | |
69afa80d | 922 | } |
bd6946d1 ILT |
923 | return p; |
924 | } | |
69afa80d | 925 | |
431f321f L |
926 | /* Add a new demangle mangled name component. */ |
927 | ||
928 | static struct demangle_component * | |
929 | d_make_demangle_mangled_name (struct d_info *di, const char *s) | |
930 | { | |
931 | if (d_peek_char (di) != '_' || d_peek_next_char (di) != 'Z') | |
932 | return d_make_name (di, s, strlen (s)); | |
933 | d_advance (di, 2); | |
934 | return d_encoding (di, 0); | |
935 | } | |
936 | ||
bd6946d1 | 937 | /* Add a new name component. */ |
051664b0 | 938 | |
5e777af5 | 939 | static struct demangle_component * |
9486db4f | 940 | d_make_name (struct d_info *di, const char *s, int len) |
bd6946d1 | 941 | { |
5e777af5 | 942 | struct demangle_component *p; |
051664b0 | 943 | |
5e777af5 ILT |
944 | p = d_make_empty (di); |
945 | if (! cplus_demangle_fill_name (p, s, len)) | |
a51753e4 | 946 | return NULL; |
bd6946d1 | 947 | return p; |
69afa80d AS |
948 | } |
949 | ||
bd6946d1 | 950 | /* Add a new builtin type component. */ |
69afa80d | 951 | |
5e777af5 | 952 | static struct demangle_component * |
9486db4f GDR |
953 | d_make_builtin_type (struct d_info *di, |
954 | const struct demangle_builtin_type_info *type) | |
69afa80d | 955 | { |
5e777af5 | 956 | struct demangle_component *p; |
bd6946d1 | 957 | |
81dc098b ILT |
958 | if (type == NULL) |
959 | return NULL; | |
5e777af5 | 960 | p = d_make_empty (di); |
bd6946d1 | 961 | if (p != NULL) |
5e777af5 ILT |
962 | { |
963 | p->type = DEMANGLE_COMPONENT_BUILTIN_TYPE; | |
964 | p->u.s_builtin.type = type; | |
965 | } | |
bd6946d1 ILT |
966 | return p; |
967 | } | |
69afa80d | 968 | |
bd6946d1 | 969 | /* Add a new operator component. */ |
69afa80d | 970 | |
5e777af5 | 971 | static struct demangle_component * |
9486db4f | 972 | d_make_operator (struct d_info *di, const struct demangle_operator_info *op) |
69afa80d | 973 | { |
5e777af5 | 974 | struct demangle_component *p; |
bd6946d1 | 975 | |
5e777af5 | 976 | p = d_make_empty (di); |
bd6946d1 | 977 | if (p != NULL) |
5e777af5 ILT |
978 | { |
979 | p->type = DEMANGLE_COMPONENT_OPERATOR; | |
980 | p->u.s_operator.op = op; | |
981 | } | |
bd6946d1 | 982 | return p; |
69afa80d AS |
983 | } |
984 | ||
bd6946d1 | 985 | /* Add a new extended operator component. */ |
69afa80d | 986 | |
5e777af5 | 987 | static struct demangle_component * |
9486db4f GDR |
988 | d_make_extended_operator (struct d_info *di, int args, |
989 | struct demangle_component *name) | |
69afa80d | 990 | { |
5e777af5 | 991 | struct demangle_component *p; |
051664b0 | 992 | |
5e777af5 ILT |
993 | p = d_make_empty (di); |
994 | if (! cplus_demangle_fill_extended_operator (p, args, name)) | |
81dc098b | 995 | return NULL; |
bd6946d1 | 996 | return p; |
69afa80d AS |
997 | } |
998 | ||
d5f4eddd JM |
999 | static struct demangle_component * |
1000 | d_make_default_arg (struct d_info *di, int num, | |
1001 | struct demangle_component *sub) | |
1002 | { | |
1003 | struct demangle_component *p = d_make_empty (di); | |
1004 | if (p) | |
1005 | { | |
1006 | p->type = DEMANGLE_COMPONENT_DEFAULT_ARG; | |
1007 | p->u.s_unary_num.num = num; | |
1008 | p->u.s_unary_num.sub = sub; | |
1009 | } | |
1010 | return p; | |
1011 | } | |
1012 | ||
bd6946d1 | 1013 | /* Add a new constructor component. */ |
69afa80d | 1014 | |
5e777af5 | 1015 | static struct demangle_component * |
9486db4f GDR |
1016 | d_make_ctor (struct d_info *di, enum gnu_v3_ctor_kinds kind, |
1017 | struct demangle_component *name) | |
69afa80d | 1018 | { |
5e777af5 | 1019 | struct demangle_component *p; |
bd6946d1 | 1020 | |
5e777af5 ILT |
1021 | p = d_make_empty (di); |
1022 | if (! cplus_demangle_fill_ctor (p, kind, name)) | |
81dc098b | 1023 | return NULL; |
bd6946d1 | 1024 | return p; |
69afa80d AS |
1025 | } |
1026 | ||
bd6946d1 | 1027 | /* Add a new destructor component. */ |
69afa80d | 1028 | |
5e777af5 | 1029 | static struct demangle_component * |
9486db4f GDR |
1030 | d_make_dtor (struct d_info *di, enum gnu_v3_dtor_kinds kind, |
1031 | struct demangle_component *name) | |
69afa80d | 1032 | { |
5e777af5 | 1033 | struct demangle_component *p; |
bd6946d1 | 1034 | |
5e777af5 ILT |
1035 | p = d_make_empty (di); |
1036 | if (! cplus_demangle_fill_dtor (p, kind, name)) | |
81dc098b | 1037 | return NULL; |
bd6946d1 | 1038 | return p; |
69afa80d AS |
1039 | } |
1040 | ||
bd6946d1 | 1041 | /* Add a new template parameter. */ |
0870bfd6 | 1042 | |
5e777af5 | 1043 | static struct demangle_component * |
9486db4f | 1044 | d_make_template_param (struct d_info *di, long i) |
0870bfd6 | 1045 | { |
5e777af5 | 1046 | struct demangle_component *p; |
bd6946d1 | 1047 | |
5e777af5 | 1048 | p = d_make_empty (di); |
bd6946d1 | 1049 | if (p != NULL) |
5e777af5 ILT |
1050 | { |
1051 | p->type = DEMANGLE_COMPONENT_TEMPLATE_PARAM; | |
1052 | p->u.s_number.number = i; | |
1053 | } | |
bd6946d1 | 1054 | return p; |
0870bfd6 AS |
1055 | } |
1056 | ||
448545cb JM |
1057 | /* Add a new function parameter. */ |
1058 | ||
1059 | static struct demangle_component * | |
1060 | d_make_function_param (struct d_info *di, long i) | |
1061 | { | |
1062 | struct demangle_component *p; | |
1063 | ||
1064 | p = d_make_empty (di); | |
1065 | if (p != NULL) | |
1066 | { | |
1067 | p->type = DEMANGLE_COMPONENT_FUNCTION_PARAM; | |
1068 | p->u.s_number.number = i; | |
1069 | } | |
1070 | return p; | |
1071 | } | |
1072 | ||
bd6946d1 | 1073 | /* Add a new standard substitution component. */ |
0870bfd6 | 1074 | |
5e777af5 | 1075 | static struct demangle_component * |
9486db4f | 1076 | d_make_sub (struct d_info *di, const char *name, int len) |
0870bfd6 | 1077 | { |
5e777af5 | 1078 | struct demangle_component *p; |
bd6946d1 | 1079 | |
5e777af5 | 1080 | p = d_make_empty (di); |
bd6946d1 | 1081 | if (p != NULL) |
2d6c4025 | 1082 | { |
5e777af5 | 1083 | p->type = DEMANGLE_COMPONENT_SUB_STD; |
2d6c4025 ILT |
1084 | p->u.s_string.string = name; |
1085 | p->u.s_string.len = len; | |
1086 | } | |
bd6946d1 | 1087 | return p; |
0870bfd6 AS |
1088 | } |
1089 | ||
2d2b02c4 | 1090 | /* <mangled-name> ::= _Z <encoding> [<clone-suffix>]* |
81dc098b ILT |
1091 | |
1092 | TOP_LEVEL is non-zero when called at the top level. */ | |
0870bfd6 | 1093 | |
5e777af5 ILT |
1094 | CP_STATIC_IF_GLIBCPP_V3 |
1095 | struct demangle_component * | |
9486db4f | 1096 | cplus_demangle_mangled_name (struct d_info *di, int top_level) |
0870bfd6 | 1097 | { |
2d2b02c4 CC |
1098 | struct demangle_component *p; |
1099 | ||
448545cb JM |
1100 | if (! d_check_char (di, '_') |
1101 | /* Allow missing _ if not at toplevel to work around a | |
1102 | bug in G++ abi-version=2 mangling; see the comment in | |
1103 | write_template_arg. */ | |
1104 | && top_level) | |
bd6946d1 | 1105 | return NULL; |
5165f125 | 1106 | if (! d_check_char (di, 'Z')) |
bd6946d1 | 1107 | return NULL; |
2d2b02c4 CC |
1108 | p = d_encoding (di, top_level); |
1109 | ||
1110 | /* If at top level and parsing parameters, check for a clone | |
1111 | suffix. */ | |
1112 | if (top_level && (di->options & DMGL_PARAMS) != 0) | |
1113 | while (d_peek_char (di) == '.' | |
1114 | && (IS_LOWER (d_peek_next_char (di)) | |
1115 | || d_peek_next_char (di) == '_' | |
1116 | || IS_DIGIT (d_peek_next_char (di)))) | |
1117 | p = d_clone_suffix (di, p); | |
1118 | ||
1119 | return p; | |
0870bfd6 AS |
1120 | } |
1121 | ||
bd6946d1 ILT |
1122 | /* Return whether a function should have a return type. The argument |
1123 | is the function name, which may be qualified in various ways. The | |
1124 | rules are that template functions have return types with some | |
1125 | exceptions, function types which are not part of a function name | |
1126 | mangling have return types with some exceptions, and non-template | |
1127 | function names do not have return types. The exceptions are that | |
1128 | constructors, destructors, and conversion operators do not have | |
1129 | return types. */ | |
0870bfd6 AS |
1130 | |
1131 | static int | |
9486db4f | 1132 | has_return_type (struct demangle_component *dc) |
0870bfd6 | 1133 | { |
bd6946d1 ILT |
1134 | if (dc == NULL) |
1135 | return 0; | |
1136 | switch (dc->type) | |
1137 | { | |
1138 | default: | |
1139 | return 0; | |
5e777af5 | 1140 | case DEMANGLE_COMPONENT_TEMPLATE: |
bd6946d1 | 1141 | return ! is_ctor_dtor_or_conversion (d_left (dc)); |
5e777af5 ILT |
1142 | case DEMANGLE_COMPONENT_RESTRICT_THIS: |
1143 | case DEMANGLE_COMPONENT_VOLATILE_THIS: | |
1144 | case DEMANGLE_COMPONENT_CONST_THIS: | |
9eb85f27 JM |
1145 | case DEMANGLE_COMPONENT_REFERENCE_THIS: |
1146 | case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: | |
0ba5c8a2 | 1147 | return has_return_type (d_left (dc)); |
bd6946d1 | 1148 | } |
0870bfd6 AS |
1149 | } |
1150 | ||
bd6946d1 ILT |
1151 | /* Return whether a name is a constructor, a destructor, or a |
1152 | conversion operator. */ | |
69afa80d AS |
1153 | |
1154 | static int | |
9486db4f | 1155 | is_ctor_dtor_or_conversion (struct demangle_component *dc) |
69afa80d | 1156 | { |
bd6946d1 ILT |
1157 | if (dc == NULL) |
1158 | return 0; | |
1159 | switch (dc->type) | |
1160 | { | |
1161 | default: | |
1162 | return 0; | |
5e777af5 ILT |
1163 | case DEMANGLE_COMPONENT_QUAL_NAME: |
1164 | case DEMANGLE_COMPONENT_LOCAL_NAME: | |
bd6946d1 | 1165 | return is_ctor_dtor_or_conversion (d_right (dc)); |
5e777af5 ILT |
1166 | case DEMANGLE_COMPONENT_CTOR: |
1167 | case DEMANGLE_COMPONENT_DTOR: | |
1168 | case DEMANGLE_COMPONENT_CAST: | |
bd6946d1 ILT |
1169 | return 1; |
1170 | } | |
69afa80d AS |
1171 | } |
1172 | ||
bd6946d1 ILT |
1173 | /* <encoding> ::= <(function) name> <bare-function-type> |
1174 | ::= <(data) name> | |
ad07f5e5 ILT |
1175 | ::= <special-name> |
1176 | ||
1177 | TOP_LEVEL is non-zero when called at the top level, in which case | |
1178 | if DMGL_PARAMS is not set we do not demangle the function | |
1179 | parameters. We only set this at the top level, because otherwise | |
1180 | we would not correctly demangle names in local scopes. */ | |
69afa80d | 1181 | |
5e777af5 | 1182 | static struct demangle_component * |
9486db4f | 1183 | d_encoding (struct d_info *di, int top_level) |
69afa80d | 1184 | { |
bd6946d1 | 1185 | char peek = d_peek_char (di); |
051664b0 | 1186 | |
bd6946d1 ILT |
1187 | if (peek == 'G' || peek == 'T') |
1188 | return d_special_name (di); | |
1189 | else | |
051664b0 | 1190 | { |
5e777af5 | 1191 | struct demangle_component *dc; |
bd6946d1 ILT |
1192 | |
1193 | dc = d_name (di); | |
81dc098b ILT |
1194 | |
1195 | if (dc != NULL && top_level && (di->options & DMGL_PARAMS) == 0) | |
1196 | { | |
1197 | /* Strip off any initial CV-qualifiers, as they really apply | |
1198 | to the `this' parameter, and they were not output by the | |
1199 | v2 demangler without DMGL_PARAMS. */ | |
5e777af5 ILT |
1200 | while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS |
1201 | || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS | |
9eb85f27 JM |
1202 | || dc->type == DEMANGLE_COMPONENT_CONST_THIS |
1203 | || dc->type == DEMANGLE_COMPONENT_REFERENCE_THIS | |
1204 | || dc->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS) | |
81dc098b | 1205 | dc = d_left (dc); |
e4796f1c | 1206 | |
5e777af5 ILT |
1207 | /* If the top level is a DEMANGLE_COMPONENT_LOCAL_NAME, then |
1208 | there may be CV-qualifiers on its right argument which | |
1209 | really apply here; this happens when parsing a class | |
1210 | which is local to a function. */ | |
1211 | if (dc->type == DEMANGLE_COMPONENT_LOCAL_NAME) | |
e4796f1c | 1212 | { |
5e777af5 | 1213 | struct demangle_component *dcr; |
e4796f1c ILT |
1214 | |
1215 | dcr = d_right (dc); | |
5e777af5 ILT |
1216 | while (dcr->type == DEMANGLE_COMPONENT_RESTRICT_THIS |
1217 | || dcr->type == DEMANGLE_COMPONENT_VOLATILE_THIS | |
9eb85f27 JM |
1218 | || dcr->type == DEMANGLE_COMPONENT_CONST_THIS |
1219 | || dcr->type == DEMANGLE_COMPONENT_REFERENCE_THIS | |
1220 | || dcr->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS) | |
e4796f1c ILT |
1221 | dcr = d_left (dcr); |
1222 | dc->u.s_binary.right = dcr; | |
1223 | } | |
1224 | ||
81dc098b ILT |
1225 | return dc; |
1226 | } | |
1227 | ||
bd6946d1 | 1228 | peek = d_peek_char (di); |
771904f1 | 1229 | if (dc == NULL || peek == '\0' || peek == 'E') |
bd6946d1 | 1230 | return dc; |
5e777af5 | 1231 | return d_make_comp (di, DEMANGLE_COMPONENT_TYPED_NAME, dc, |
bd6946d1 | 1232 | d_bare_function_type (di, has_return_type (dc))); |
051664b0 | 1233 | } |
bd6946d1 ILT |
1234 | } |
1235 | ||
7dbb85a7 JM |
1236 | /* <tagged-name> ::= <name> B <source-name> */ |
1237 | ||
1238 | static struct demangle_component * | |
1239 | d_abi_tags (struct d_info *di, struct demangle_component *dc) | |
1240 | { | |
1241 | char peek; | |
1242 | while (peek = d_peek_char (di), | |
1243 | peek == 'B') | |
1244 | { | |
1245 | struct demangle_component *tag; | |
1246 | d_advance (di, 1); | |
1247 | tag = d_source_name (di); | |
1248 | dc = d_make_comp (di, DEMANGLE_COMPONENT_TAGGED_NAME, dc, tag); | |
1249 | } | |
1250 | return dc; | |
1251 | } | |
1252 | ||
bd6946d1 ILT |
1253 | /* <name> ::= <nested-name> |
1254 | ::= <unscoped-name> | |
1255 | ::= <unscoped-template-name> <template-args> | |
1256 | ::= <local-name> | |
1257 | ||
1258 | <unscoped-name> ::= <unqualified-name> | |
1259 | ::= St <unqualified-name> | |
69afa80d | 1260 | |
bd6946d1 ILT |
1261 | <unscoped-template-name> ::= <unscoped-name> |
1262 | ::= <substitution> | |
1263 | */ | |
1264 | ||
5e777af5 | 1265 | static struct demangle_component * |
9486db4f | 1266 | d_name (struct d_info *di) |
bd6946d1 ILT |
1267 | { |
1268 | char peek = d_peek_char (di); | |
5e777af5 | 1269 | struct demangle_component *dc; |
bd6946d1 ILT |
1270 | |
1271 | switch (peek) | |
69afa80d | 1272 | { |
bd6946d1 | 1273 | case 'N': |
c61e8502 | 1274 | return d_nested_name (di); |
bd6946d1 ILT |
1275 | |
1276 | case 'Z': | |
c61e8502 | 1277 | return d_local_name (di); |
bd6946d1 | 1278 | |
a2aa65f0 | 1279 | case 'L': |
d5f4eddd | 1280 | case 'U': |
c61e8502 | 1281 | return d_unqualified_name (di); |
d5f4eddd | 1282 | |
bd6946d1 ILT |
1283 | case 'S': |
1284 | { | |
1285 | int subst; | |
1286 | ||
1287 | if (d_peek_next_char (di) != 't') | |
1288 | { | |
374caa50 | 1289 | dc = d_substitution (di, 0); |
bd6946d1 ILT |
1290 | subst = 1; |
1291 | } | |
1292 | else | |
1293 | { | |
1294 | d_advance (di, 2); | |
5e777af5 ILT |
1295 | dc = d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, |
1296 | d_make_name (di, "std", 3), | |
bd6946d1 | 1297 | d_unqualified_name (di)); |
2d6c4025 | 1298 | di->expansion += 3; |
bd6946d1 ILT |
1299 | subst = 0; |
1300 | } | |
1301 | ||
1302 | if (d_peek_char (di) != 'I') | |
1303 | { | |
1304 | /* The grammar does not permit this case to occur if we | |
1305 | called d_substitution() above (i.e., subst == 1). We | |
1306 | don't bother to check. */ | |
1307 | } | |
1308 | else | |
1309 | { | |
1310 | /* This is <template-args>, which means that we just saw | |
1311 | <unscoped-template-name>, which is a substitution | |
1312 | candidate if we didn't just get it from a | |
1313 | substitution. */ | |
1314 | if (! subst) | |
1315 | { | |
1316 | if (! d_add_substitution (di, dc)) | |
1317 | return NULL; | |
1318 | } | |
5e777af5 ILT |
1319 | dc = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, dc, |
1320 | d_template_args (di)); | |
bd6946d1 ILT |
1321 | } |
1322 | ||
c61e8502 | 1323 | return dc; |
bd6946d1 ILT |
1324 | } |
1325 | ||
1326 | default: | |
1327 | dc = d_unqualified_name (di); | |
1328 | if (d_peek_char (di) == 'I') | |
051664b0 | 1329 | { |
bd6946d1 ILT |
1330 | /* This is <template-args>, which means that we just saw |
1331 | <unscoped-template-name>, which is a substitution | |
1332 | candidate. */ | |
1333 | if (! d_add_substitution (di, dc)) | |
1334 | return NULL; | |
5e777af5 ILT |
1335 | dc = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, dc, |
1336 | d_template_args (di)); | |
051664b0 | 1337 | } |
c61e8502 | 1338 | return dc; |
69afa80d | 1339 | } |
bd6946d1 | 1340 | } |
69afa80d | 1341 | |
9eb85f27 JM |
1342 | /* <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E |
1343 | ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E | |
bd6946d1 | 1344 | */ |
69afa80d | 1345 | |
5e777af5 | 1346 | static struct demangle_component * |
9486db4f | 1347 | d_nested_name (struct d_info *di) |
bd6946d1 | 1348 | { |
5e777af5 ILT |
1349 | struct demangle_component *ret; |
1350 | struct demangle_component **pret; | |
9eb85f27 | 1351 | struct demangle_component *rqual; |
051664b0 | 1352 | |
5165f125 | 1353 | if (! d_check_char (di, 'N')) |
bd6946d1 | 1354 | return NULL; |
69afa80d | 1355 | |
a51753e4 | 1356 | pret = d_cv_qualifiers (di, &ret, 1); |
bd6946d1 ILT |
1357 | if (pret == NULL) |
1358 | return NULL; | |
1359 | ||
9eb85f27 JM |
1360 | /* Parse the ref-qualifier now and then attach it |
1361 | once we have something to attach it to. */ | |
1362 | rqual = d_ref_qualifier (di, NULL); | |
1363 | ||
bd6946d1 ILT |
1364 | *pret = d_prefix (di); |
1365 | if (*pret == NULL) | |
1366 | return NULL; | |
69afa80d | 1367 | |
9eb85f27 JM |
1368 | if (rqual) |
1369 | { | |
1370 | d_left (rqual) = ret; | |
1371 | ret = rqual; | |
1372 | } | |
1373 | ||
5165f125 | 1374 | if (! d_check_char (di, 'E')) |
69afa80d AS |
1375 | return NULL; |
1376 | ||
bd6946d1 | 1377 | return ret; |
69afa80d AS |
1378 | } |
1379 | ||
bd6946d1 ILT |
1380 | /* <prefix> ::= <prefix> <unqualified-name> |
1381 | ::= <template-prefix> <template-args> | |
1382 | ::= <template-param> | |
4bbff96e | 1383 | ::= <decltype> |
bd6946d1 ILT |
1384 | ::= |
1385 | ::= <substitution> | |
69afa80d | 1386 | |
bd6946d1 ILT |
1387 | <template-prefix> ::= <prefix> <(template) unqualified-name> |
1388 | ::= <template-param> | |
1389 | ::= <substitution> | |
1390 | */ | |
1391 | ||
5e777af5 | 1392 | static struct demangle_component * |
9486db4f | 1393 | d_prefix (struct d_info *di) |
69afa80d | 1394 | { |
5e777af5 | 1395 | struct demangle_component *ret = NULL; |
69afa80d | 1396 | |
bd6946d1 | 1397 | while (1) |
69afa80d | 1398 | { |
bd6946d1 | 1399 | char peek; |
5e777af5 ILT |
1400 | enum demangle_component_type comb_type; |
1401 | struct demangle_component *dc; | |
bd6946d1 ILT |
1402 | |
1403 | peek = d_peek_char (di); | |
1404 | if (peek == '\0') | |
1405 | return NULL; | |
1406 | ||
1407 | /* The older code accepts a <local-name> here, but I don't see | |
1408 | that in the grammar. The older code does not accept a | |
1409 | <template-param> here. */ | |
69afa80d | 1410 | |
5e777af5 | 1411 | comb_type = DEMANGLE_COMPONENT_QUAL_NAME; |
4bbff96e JM |
1412 | if (peek == 'D') |
1413 | { | |
1414 | char peek2 = d_peek_next_char (di); | |
1415 | if (peek2 == 'T' || peek2 == 't') | |
1416 | /* Decltype. */ | |
1417 | dc = cplus_demangle_type (di); | |
1418 | else | |
1419 | /* Destructor name. */ | |
1420 | dc = d_unqualified_name (di); | |
1421 | } | |
1422 | else if (IS_DIGIT (peek) | |
a51753e4 | 1423 | || IS_LOWER (peek) |
bd6946d1 | 1424 | || peek == 'C' |
d5f4eddd | 1425 | || peek == 'U' |
a2aa65f0 | 1426 | || peek == 'L') |
bd6946d1 ILT |
1427 | dc = d_unqualified_name (di); |
1428 | else if (peek == 'S') | |
374caa50 | 1429 | dc = d_substitution (di, 1); |
bd6946d1 ILT |
1430 | else if (peek == 'I') |
1431 | { | |
1432 | if (ret == NULL) | |
1433 | return NULL; | |
5e777af5 | 1434 | comb_type = DEMANGLE_COMPONENT_TEMPLATE; |
bd6946d1 ILT |
1435 | dc = d_template_args (di); |
1436 | } | |
1437 | else if (peek == 'T') | |
1438 | dc = d_template_param (di); | |
1439 | else if (peek == 'E') | |
1440 | return ret; | |
d5f4eddd JM |
1441 | else if (peek == 'M') |
1442 | { | |
1443 | /* Initializer scope for a lambda. We don't need to represent | |
1444 | this; the normal code will just treat the variable as a type | |
1445 | scope, which gives appropriate output. */ | |
1446 | if (ret == NULL) | |
1447 | return NULL; | |
1448 | d_advance (di, 1); | |
1449 | continue; | |
1450 | } | |
bd6946d1 ILT |
1451 | else |
1452 | return NULL; | |
1453 | ||
1454 | if (ret == NULL) | |
1455 | ret = dc; | |
69afa80d | 1456 | else |
bd6946d1 ILT |
1457 | ret = d_make_comp (di, comb_type, ret, dc); |
1458 | ||
1459 | if (peek != 'S' && d_peek_char (di) != 'E') | |
1460 | { | |
1461 | if (! d_add_substitution (di, ret)) | |
1462 | return NULL; | |
1463 | } | |
69afa80d AS |
1464 | } |
1465 | } | |
1466 | ||
bd6946d1 ILT |
1467 | /* <unqualified-name> ::= <operator-name> |
1468 | ::= <ctor-dtor-name> | |
1469 | ::= <source-name> | |
a2aa65f0 GK |
1470 | ::= <local-source-name> |
1471 | ||
1472 | <local-source-name> ::= L <source-name> <discriminator> | |
bd6946d1 | 1473 | */ |
69afa80d | 1474 | |
5e777af5 | 1475 | static struct demangle_component * |
9486db4f | 1476 | d_unqualified_name (struct d_info *di) |
69afa80d | 1477 | { |
c61e8502 | 1478 | struct demangle_component *ret; |
bd6946d1 ILT |
1479 | char peek; |
1480 | ||
1481 | peek = d_peek_char (di); | |
1482 | if (IS_DIGIT (peek)) | |
c61e8502 | 1483 | ret = d_source_name (di); |
a51753e4 | 1484 | else if (IS_LOWER (peek)) |
2d6c4025 | 1485 | { |
2d6c4025 | 1486 | ret = d_operator_name (di); |
5e777af5 | 1487 | if (ret != NULL && ret->type == DEMANGLE_COMPONENT_OPERATOR) |
c93ea196 JM |
1488 | { |
1489 | di->expansion += sizeof "operator" + ret->u.s_operator.op->len - 2; | |
1490 | if (!strcmp (ret->u.s_operator.op->code, "li")) | |
1491 | ret = d_make_comp (di, DEMANGLE_COMPONENT_UNARY, ret, | |
1492 | d_source_name (di)); | |
1493 | } | |
2d6c4025 | 1494 | } |
bd6946d1 | 1495 | else if (peek == 'C' || peek == 'D') |
c61e8502 | 1496 | ret = d_ctor_dtor_name (di); |
a2aa65f0 GK |
1497 | else if (peek == 'L') |
1498 | { | |
a2aa65f0 GK |
1499 | d_advance (di, 1); |
1500 | ||
1501 | ret = d_source_name (di); | |
1502 | if (ret == NULL) | |
1503 | return NULL; | |
1504 | if (! d_discriminator (di)) | |
1505 | return NULL; | |
a2aa65f0 | 1506 | } |
d5f4eddd JM |
1507 | else if (peek == 'U') |
1508 | { | |
1509 | switch (d_peek_next_char (di)) | |
1510 | { | |
1511 | case 'l': | |
c61e8502 JM |
1512 | ret = d_lambda (di); |
1513 | break; | |
d5f4eddd | 1514 | case 't': |
c61e8502 JM |
1515 | ret = d_unnamed_type (di); |
1516 | break; | |
d5f4eddd JM |
1517 | default: |
1518 | return NULL; | |
1519 | } | |
1520 | } | |
bd6946d1 | 1521 | else |
051664b0 | 1522 | return NULL; |
c61e8502 JM |
1523 | |
1524 | if (d_peek_char (di) == 'B') | |
1525 | ret = d_abi_tags (di, ret); | |
1526 | return ret; | |
69afa80d AS |
1527 | } |
1528 | ||
bd6946d1 | 1529 | /* <source-name> ::= <(positive length) number> <identifier> */ |
69afa80d | 1530 | |
5e777af5 | 1531 | static struct demangle_component * |
9486db4f | 1532 | d_source_name (struct d_info *di) |
69afa80d | 1533 | { |
bd6946d1 | 1534 | long len; |
5e777af5 | 1535 | struct demangle_component *ret; |
bd6946d1 ILT |
1536 | |
1537 | len = d_number (di); | |
1538 | if (len <= 0) | |
1539 | return NULL; | |
1540 | ret = d_identifier (di, len); | |
1541 | di->last_name = ret; | |
1542 | return ret; | |
69afa80d AS |
1543 | } |
1544 | ||
bd6946d1 | 1545 | /* number ::= [n] <(non-negative decimal integer)> */ |
69afa80d | 1546 | |
bd6946d1 | 1547 | static long |
9486db4f | 1548 | d_number (struct d_info *di) |
69afa80d | 1549 | { |
2d6c4025 | 1550 | int negative; |
bd6946d1 ILT |
1551 | char peek; |
1552 | long ret; | |
69afa80d | 1553 | |
2d6c4025 | 1554 | negative = 0; |
bd6946d1 ILT |
1555 | peek = d_peek_char (di); |
1556 | if (peek == 'n') | |
1557 | { | |
2d6c4025 | 1558 | negative = 1; |
bd6946d1 ILT |
1559 | d_advance (di, 1); |
1560 | peek = d_peek_char (di); | |
1561 | } | |
69afa80d | 1562 | |
bd6946d1 ILT |
1563 | ret = 0; |
1564 | while (1) | |
69afa80d | 1565 | { |
bd6946d1 | 1566 | if (! IS_DIGIT (peek)) |
2d6c4025 ILT |
1567 | { |
1568 | if (negative) | |
1569 | ret = - ret; | |
1570 | return ret; | |
1571 | } | |
bd6946d1 ILT |
1572 | ret = ret * 10 + peek - '0'; |
1573 | d_advance (di, 1); | |
1574 | peek = d_peek_char (di); | |
69afa80d | 1575 | } |
69afa80d AS |
1576 | } |
1577 | ||
abfe01ce JM |
1578 | /* Like d_number, but returns a demangle_component. */ |
1579 | ||
1580 | static struct demangle_component * | |
1581 | d_number_component (struct d_info *di) | |
1582 | { | |
1583 | struct demangle_component *ret = d_make_empty (di); | |
1584 | if (ret) | |
1585 | { | |
1586 | ret->type = DEMANGLE_COMPONENT_NUMBER; | |
1587 | ret->u.s_number.number = d_number (di); | |
1588 | } | |
1589 | return ret; | |
1590 | } | |
1591 | ||
bd6946d1 | 1592 | /* identifier ::= <(unqualified source code identifier)> */ |
69afa80d | 1593 | |
5e777af5 | 1594 | static struct demangle_component * |
9486db4f | 1595 | d_identifier (struct d_info *di, int len) |
69afa80d | 1596 | { |
bd6946d1 | 1597 | const char *name; |
69afa80d | 1598 | |
bd6946d1 | 1599 | name = d_str (di); |
2d6c4025 ILT |
1600 | |
1601 | if (di->send - name < len) | |
1602 | return NULL; | |
1603 | ||
bd6946d1 | 1604 | d_advance (di, len); |
69afa80d | 1605 | |
2307e075 ILT |
1606 | /* A Java mangled name may have a trailing '$' if it is a C++ |
1607 | keyword. This '$' is not included in the length count. We just | |
1608 | ignore the '$'. */ | |
1609 | if ((di->options & DMGL_JAVA) != 0 | |
1610 | && d_peek_char (di) == '$') | |
1611 | d_advance (di, 1); | |
1612 | ||
bd6946d1 ILT |
1613 | /* Look for something which looks like a gcc encoding of an |
1614 | anonymous namespace, and replace it with a more user friendly | |
1615 | name. */ | |
1616 | if (len >= (int) ANONYMOUS_NAMESPACE_PREFIX_LEN + 2 | |
1617 | && memcmp (name, ANONYMOUS_NAMESPACE_PREFIX, | |
1618 | ANONYMOUS_NAMESPACE_PREFIX_LEN) == 0) | |
69afa80d | 1619 | { |
bd6946d1 ILT |
1620 | const char *s; |
1621 | ||
1622 | s = name + ANONYMOUS_NAMESPACE_PREFIX_LEN; | |
1623 | if ((*s == '.' || *s == '_' || *s == '$') | |
1624 | && s[1] == 'N') | |
2d6c4025 ILT |
1625 | { |
1626 | di->expansion -= len - sizeof "(anonymous namespace)"; | |
1627 | return d_make_name (di, "(anonymous namespace)", | |
1628 | sizeof "(anonymous namespace)" - 1); | |
1629 | } | |
69afa80d | 1630 | } |
bd6946d1 ILT |
1631 | |
1632 | return d_make_name (di, name, len); | |
69afa80d AS |
1633 | } |
1634 | ||
bd6946d1 ILT |
1635 | /* operator_name ::= many different two character encodings. |
1636 | ::= cv <type> | |
1637 | ::= v <digit> <source-name> | |
49f2da1a JM |
1638 | |
1639 | This list is sorted for binary search. */ | |
69afa80d | 1640 | |
2d6c4025 ILT |
1641 | #define NL(s) s, (sizeof s) - 1 |
1642 | ||
5e777af5 ILT |
1643 | CP_STATIC_IF_GLIBCPP_V3 |
1644 | const struct demangle_operator_info cplus_demangle_operators[] = | |
bd6946d1 | 1645 | { |
2d6c4025 ILT |
1646 | { "aN", NL ("&="), 2 }, |
1647 | { "aS", NL ("="), 2 }, | |
1648 | { "aa", NL ("&&"), 2 }, | |
1649 | { "ad", NL ("&"), 1 }, | |
1650 | { "an", NL ("&"), 2 }, | |
49f2da1a JM |
1651 | { "at", NL ("alignof "), 1 }, |
1652 | { "az", NL ("alignof "), 1 }, | |
aefa74bd | 1653 | { "cc", NL ("const_cast"), 2 }, |
5a3d7e74 | 1654 | { "cl", NL ("()"), 2 }, |
2d6c4025 ILT |
1655 | { "cm", NL (","), 2 }, |
1656 | { "co", NL ("~"), 1 }, | |
1657 | { "dV", NL ("/="), 2 }, | |
4b6aaa99 | 1658 | { "da", NL ("delete[] "), 1 }, |
aefa74bd | 1659 | { "dc", NL ("dynamic_cast"), 2 }, |
2d6c4025 | 1660 | { "de", NL ("*"), 1 }, |
4b6aaa99 JM |
1661 | { "dl", NL ("delete "), 1 }, |
1662 | { "ds", NL (".*"), 2 }, | |
38179091 | 1663 | { "dt", NL ("."), 2 }, |
2d6c4025 ILT |
1664 | { "dv", NL ("/"), 2 }, |
1665 | { "eO", NL ("^="), 2 }, | |
1666 | { "eo", NL ("^"), 2 }, | |
1667 | { "eq", NL ("=="), 2 }, | |
1668 | { "ge", NL (">="), 2 }, | |
4b6aaa99 | 1669 | { "gs", NL ("::"), 1 }, |
2d6c4025 ILT |
1670 | { "gt", NL (">"), 2 }, |
1671 | { "ix", NL ("[]"), 2 }, | |
1672 | { "lS", NL ("<<="), 2 }, | |
1673 | { "le", NL ("<="), 2 }, | |
c93ea196 | 1674 | { "li", NL ("operator\"\" "), 1 }, |
2d6c4025 ILT |
1675 | { "ls", NL ("<<"), 2 }, |
1676 | { "lt", NL ("<"), 2 }, | |
1677 | { "mI", NL ("-="), 2 }, | |
1678 | { "mL", NL ("*="), 2 }, | |
1679 | { "mi", NL ("-"), 2 }, | |
1680 | { "ml", NL ("*"), 2 }, | |
1681 | { "mm", NL ("--"), 1 }, | |
4b6aaa99 | 1682 | { "na", NL ("new[]"), 3 }, |
2d6c4025 ILT |
1683 | { "ne", NL ("!="), 2 }, |
1684 | { "ng", NL ("-"), 1 }, | |
1685 | { "nt", NL ("!"), 1 }, | |
4b6aaa99 | 1686 | { "nw", NL ("new"), 3 }, |
2d6c4025 ILT |
1687 | { "oR", NL ("|="), 2 }, |
1688 | { "oo", NL ("||"), 2 }, | |
1689 | { "or", NL ("|"), 2 }, | |
1690 | { "pL", NL ("+="), 2 }, | |
1691 | { "pl", NL ("+"), 2 }, | |
1692 | { "pm", NL ("->*"), 2 }, | |
1693 | { "pp", NL ("++"), 1 }, | |
1694 | { "ps", NL ("+"), 1 }, | |
1695 | { "pt", NL ("->"), 2 }, | |
1696 | { "qu", NL ("?"), 3 }, | |
1697 | { "rM", NL ("%="), 2 }, | |
1698 | { "rS", NL (">>="), 2 }, | |
aefa74bd | 1699 | { "rc", NL ("reinterpret_cast"), 2 }, |
2d6c4025 ILT |
1700 | { "rm", NL ("%"), 2 }, |
1701 | { "rs", NL (">>"), 2 }, | |
aefa74bd | 1702 | { "sc", NL ("static_cast"), 2 }, |
2d6c4025 | 1703 | { "st", NL ("sizeof "), 1 }, |
5e777af5 | 1704 | { "sz", NL ("sizeof "), 1 }, |
4b6aaa99 JM |
1705 | { "tr", NL ("throw"), 0 }, |
1706 | { "tw", NL ("throw "), 1 }, | |
5e777af5 | 1707 | { NULL, NULL, 0, 0 } |
bd6946d1 | 1708 | }; |
69afa80d | 1709 | |
5e777af5 | 1710 | static struct demangle_component * |
9486db4f | 1711 | d_operator_name (struct d_info *di) |
69afa80d | 1712 | { |
bd6946d1 ILT |
1713 | char c1; |
1714 | char c2; | |
69afa80d | 1715 | |
bd6946d1 ILT |
1716 | c1 = d_next_char (di); |
1717 | c2 = d_next_char (di); | |
1718 | if (c1 == 'v' && IS_DIGIT (c2)) | |
1719 | return d_make_extended_operator (di, c2 - '0', d_source_name (di)); | |
1720 | else if (c1 == 'c' && c2 == 'v') | |
5e777af5 ILT |
1721 | return d_make_comp (di, DEMANGLE_COMPONENT_CAST, |
1722 | cplus_demangle_type (di), NULL); | |
bd6946d1 | 1723 | else |
69afa80d | 1724 | { |
5e777af5 | 1725 | /* LOW is the inclusive lower bound. */ |
bd6946d1 | 1726 | int low = 0; |
5e777af5 ILT |
1727 | /* HIGH is the exclusive upper bound. We subtract one to ignore |
1728 | the sentinel at the end of the array. */ | |
1729 | int high = ((sizeof (cplus_demangle_operators) | |
1730 | / sizeof (cplus_demangle_operators[0])) | |
1731 | - 1); | |
69afa80d | 1732 | |
bd6946d1 ILT |
1733 | while (1) |
1734 | { | |
1735 | int i; | |
5e777af5 | 1736 | const struct demangle_operator_info *p; |
69afa80d | 1737 | |
bd6946d1 | 1738 | i = low + (high - low) / 2; |
5e777af5 | 1739 | p = cplus_demangle_operators + i; |
69afa80d | 1740 | |
bd6946d1 ILT |
1741 | if (c1 == p->code[0] && c2 == p->code[1]) |
1742 | return d_make_operator (di, p); | |
1743 | ||
1744 | if (c1 < p->code[0] || (c1 == p->code[0] && c2 < p->code[1])) | |
1745 | high = i; | |
1746 | else | |
1747 | low = i + 1; | |
1748 | if (low == high) | |
1749 | return NULL; | |
1750 | } | |
1751 | } | |
69afa80d AS |
1752 | } |
1753 | ||
e5df4fb1 DD |
1754 | static struct demangle_component * |
1755 | d_make_character (struct d_info *di, int c) | |
1756 | { | |
1757 | struct demangle_component *p; | |
1758 | p = d_make_empty (di); | |
1759 | if (p != NULL) | |
1760 | { | |
1761 | p->type = DEMANGLE_COMPONENT_CHARACTER; | |
1762 | p->u.s_character.character = c; | |
1763 | } | |
1764 | return p; | |
1765 | } | |
1766 | ||
1767 | static struct demangle_component * | |
1768 | d_java_resource (struct d_info *di) | |
1769 | { | |
1770 | struct demangle_component *p = NULL; | |
1771 | struct demangle_component *next = NULL; | |
1772 | long len, i; | |
1773 | char c; | |
1774 | const char *str; | |
1775 | ||
1776 | len = d_number (di); | |
1777 | if (len <= 1) | |
1778 | return NULL; | |
1779 | ||
1780 | /* Eat the leading '_'. */ | |
1781 | if (d_next_char (di) != '_') | |
1782 | return NULL; | |
1783 | len--; | |
1784 | ||
1785 | str = d_str (di); | |
1786 | i = 0; | |
1787 | ||
1788 | while (len > 0) | |
1789 | { | |
1790 | c = str[i]; | |
1791 | if (!c) | |
1792 | return NULL; | |
1793 | ||
1794 | /* Each chunk is either a '$' escape... */ | |
1795 | if (c == '$') | |
1796 | { | |
1797 | i++; | |
1798 | switch (str[i++]) | |
1799 | { | |
1800 | case 'S': | |
1801 | c = '/'; | |
1802 | break; | |
1803 | case '_': | |
1804 | c = '.'; | |
1805 | break; | |
1806 | case '$': | |
1807 | c = '$'; | |
1808 | break; | |
1809 | default: | |
1810 | return NULL; | |
1811 | } | |
1812 | next = d_make_character (di, c); | |
1813 | d_advance (di, i); | |
1814 | str = d_str (di); | |
1815 | len -= i; | |
1816 | i = 0; | |
1817 | if (next == NULL) | |
1818 | return NULL; | |
1819 | } | |
1820 | /* ... or a sequence of characters. */ | |
1821 | else | |
1822 | { | |
1823 | while (i < len && str[i] && str[i] != '$') | |
1824 | i++; | |
1825 | ||
1826 | next = d_make_name (di, str, i); | |
1827 | d_advance (di, i); | |
1828 | str = d_str (di); | |
1829 | len -= i; | |
1830 | i = 0; | |
1831 | if (next == NULL) | |
1832 | return NULL; | |
1833 | } | |
1834 | ||
1835 | if (p == NULL) | |
1836 | p = next; | |
1837 | else | |
1838 | { | |
1839 | p = d_make_comp (di, DEMANGLE_COMPONENT_COMPOUND_NAME, p, next); | |
1840 | if (p == NULL) | |
1841 | return NULL; | |
1842 | } | |
1843 | } | |
1844 | ||
1845 | p = d_make_comp (di, DEMANGLE_COMPONENT_JAVA_RESOURCE, p, NULL); | |
1846 | ||
1847 | return p; | |
1848 | } | |
1849 | ||
bd6946d1 ILT |
1850 | /* <special-name> ::= TV <type> |
1851 | ::= TT <type> | |
1852 | ::= TI <type> | |
1853 | ::= TS <type> | |
1854 | ::= GV <(object) name> | |
1855 | ::= T <call-offset> <(base) encoding> | |
1856 | ::= Tc <call-offset> <call-offset> <(base) encoding> | |
1857 | Also g++ extensions: | |
1858 | ::= TC <type> <(offset) number> _ <(base) type> | |
1859 | ::= TF <type> | |
1860 | ::= TJ <type> | |
1861 | ::= GR <name> | |
15da2806 | 1862 | ::= GA <encoding> |
e5df4fb1 | 1863 | ::= Gr <resource name> |
0a35513e AH |
1864 | ::= GTt <encoding> |
1865 | ::= GTn <encoding> | |
bd6946d1 | 1866 | */ |
69afa80d | 1867 | |
5e777af5 | 1868 | static struct demangle_component * |
9486db4f | 1869 | d_special_name (struct d_info *di) |
69afa80d | 1870 | { |
2d6c4025 | 1871 | di->expansion += 20; |
5165f125 | 1872 | if (d_check_char (di, 'T')) |
051664b0 | 1873 | { |
bd6946d1 ILT |
1874 | switch (d_next_char (di)) |
1875 | { | |
1876 | case 'V': | |
2d6c4025 | 1877 | di->expansion -= 5; |
5e777af5 ILT |
1878 | return d_make_comp (di, DEMANGLE_COMPONENT_VTABLE, |
1879 | cplus_demangle_type (di), NULL); | |
bd6946d1 | 1880 | case 'T': |
2d6c4025 | 1881 | di->expansion -= 10; |
5e777af5 ILT |
1882 | return d_make_comp (di, DEMANGLE_COMPONENT_VTT, |
1883 | cplus_demangle_type (di), NULL); | |
bd6946d1 | 1884 | case 'I': |
5e777af5 ILT |
1885 | return d_make_comp (di, DEMANGLE_COMPONENT_TYPEINFO, |
1886 | cplus_demangle_type (di), NULL); | |
bd6946d1 | 1887 | case 'S': |
5e777af5 ILT |
1888 | return d_make_comp (di, DEMANGLE_COMPONENT_TYPEINFO_NAME, |
1889 | cplus_demangle_type (di), NULL); | |
69afa80d | 1890 | |
bd6946d1 ILT |
1891 | case 'h': |
1892 | if (! d_call_offset (di, 'h')) | |
1893 | return NULL; | |
5e777af5 ILT |
1894 | return d_make_comp (di, DEMANGLE_COMPONENT_THUNK, |
1895 | d_encoding (di, 0), NULL); | |
69afa80d | 1896 | |
bd6946d1 ILT |
1897 | case 'v': |
1898 | if (! d_call_offset (di, 'v')) | |
1899 | return NULL; | |
5e777af5 ILT |
1900 | return d_make_comp (di, DEMANGLE_COMPONENT_VIRTUAL_THUNK, |
1901 | d_encoding (di, 0), NULL); | |
69afa80d | 1902 | |
bd6946d1 ILT |
1903 | case 'c': |
1904 | if (! d_call_offset (di, '\0')) | |
1905 | return NULL; | |
1906 | if (! d_call_offset (di, '\0')) | |
1907 | return NULL; | |
5e777af5 ILT |
1908 | return d_make_comp (di, DEMANGLE_COMPONENT_COVARIANT_THUNK, |
1909 | d_encoding (di, 0), NULL); | |
69afa80d | 1910 | |
bd6946d1 ILT |
1911 | case 'C': |
1912 | { | |
5e777af5 | 1913 | struct demangle_component *derived_type; |
bd6946d1 | 1914 | long offset; |
5e777af5 | 1915 | struct demangle_component *base_type; |
bd6946d1 | 1916 | |
5e777af5 | 1917 | derived_type = cplus_demangle_type (di); |
bd6946d1 ILT |
1918 | offset = d_number (di); |
1919 | if (offset < 0) | |
1920 | return NULL; | |
5165f125 | 1921 | if (! d_check_char (di, '_')) |
bd6946d1 | 1922 | return NULL; |
5e777af5 | 1923 | base_type = cplus_demangle_type (di); |
bd6946d1 ILT |
1924 | /* We don't display the offset. FIXME: We should display |
1925 | it in verbose mode. */ | |
2d6c4025 | 1926 | di->expansion += 5; |
5e777af5 ILT |
1927 | return d_make_comp (di, DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE, |
1928 | base_type, derived_type); | |
bd6946d1 | 1929 | } |
69afa80d | 1930 | |
bd6946d1 | 1931 | case 'F': |
5e777af5 ILT |
1932 | return d_make_comp (di, DEMANGLE_COMPONENT_TYPEINFO_FN, |
1933 | cplus_demangle_type (di), NULL); | |
bd6946d1 | 1934 | case 'J': |
5e777af5 ILT |
1935 | return d_make_comp (di, DEMANGLE_COMPONENT_JAVA_CLASS, |
1936 | cplus_demangle_type (di), NULL); | |
69afa80d | 1937 | |
7c424acd JM |
1938 | case 'H': |
1939 | return d_make_comp (di, DEMANGLE_COMPONENT_TLS_INIT, | |
1940 | d_name (di), NULL); | |
1941 | ||
1942 | case 'W': | |
1943 | return d_make_comp (di, DEMANGLE_COMPONENT_TLS_WRAPPER, | |
1944 | d_name (di), NULL); | |
1945 | ||
bd6946d1 ILT |
1946 | default: |
1947 | return NULL; | |
1948 | } | |
69afa80d | 1949 | } |
5165f125 | 1950 | else if (d_check_char (di, 'G')) |
69afa80d | 1951 | { |
bd6946d1 ILT |
1952 | switch (d_next_char (di)) |
1953 | { | |
1954 | case 'V': | |
5e777af5 | 1955 | return d_make_comp (di, DEMANGLE_COMPONENT_GUARD, d_name (di), NULL); |
bd6946d1 ILT |
1956 | |
1957 | case 'R': | |
b25dd954 JM |
1958 | { |
1959 | struct demangle_component *name = d_name (di); | |
1960 | return d_make_comp (di, DEMANGLE_COMPONENT_REFTEMP, name, | |
1961 | d_number_component (di)); | |
1962 | } | |
bd6946d1 | 1963 | |
15da2806 RH |
1964 | case 'A': |
1965 | return d_make_comp (di, DEMANGLE_COMPONENT_HIDDEN_ALIAS, | |
1966 | d_encoding (di, 0), NULL); | |
1967 | ||
0a35513e AH |
1968 | case 'T': |
1969 | switch (d_next_char (di)) | |
1970 | { | |
1971 | case 'n': | |
1972 | return d_make_comp (di, DEMANGLE_COMPONENT_NONTRANSACTION_CLONE, | |
1973 | d_encoding (di, 0), NULL); | |
1974 | default: | |
1975 | /* ??? The proposal is that other letters (such as 'h') stand | |
1976 | for different variants of transaction cloning, such as | |
1977 | compiling directly for hardware transaction support. But | |
1978 | they still should all be transactional clones of some sort | |
1979 | so go ahead and call them that. */ | |
1980 | case 't': | |
1981 | return d_make_comp (di, DEMANGLE_COMPONENT_TRANSACTION_CLONE, | |
1982 | d_encoding (di, 0), NULL); | |
1983 | } | |
1984 | ||
e5df4fb1 DD |
1985 | case 'r': |
1986 | return d_java_resource (di); | |
1987 | ||
bd6946d1 ILT |
1988 | default: |
1989 | return NULL; | |
1990 | } | |
69afa80d | 1991 | } |
bd6946d1 ILT |
1992 | else |
1993 | return NULL; | |
69afa80d AS |
1994 | } |
1995 | ||
bd6946d1 ILT |
1996 | /* <call-offset> ::= h <nv-offset> _ |
1997 | ::= v <v-offset> _ | |
69afa80d | 1998 | |
bd6946d1 | 1999 | <nv-offset> ::= <(offset) number> |
69afa80d | 2000 | |
bd6946d1 | 2001 | <v-offset> ::= <(offset) number> _ <(virtual offset) number> |
69afa80d | 2002 | |
bd6946d1 ILT |
2003 | The C parameter, if not '\0', is a character we just read which is |
2004 | the start of the <call-offset>. | |
69afa80d | 2005 | |
bd6946d1 ILT |
2006 | We don't display the offset information anywhere. FIXME: We should |
2007 | display it in verbose mode. */ | |
69afa80d | 2008 | |
bd6946d1 | 2009 | static int |
9486db4f | 2010 | d_call_offset (struct d_info *di, int c) |
69afa80d | 2011 | { |
bd6946d1 ILT |
2012 | if (c == '\0') |
2013 | c = d_next_char (di); | |
69afa80d | 2014 | |
bd6946d1 | 2015 | if (c == 'h') |
0b167d51 | 2016 | d_number (di); |
bd6946d1 | 2017 | else if (c == 'v') |
69afa80d | 2018 | { |
0b167d51 | 2019 | d_number (di); |
5165f125 | 2020 | if (! d_check_char (di, '_')) |
bd6946d1 | 2021 | return 0; |
0b167d51 | 2022 | d_number (di); |
69afa80d | 2023 | } |
bd6946d1 ILT |
2024 | else |
2025 | return 0; | |
69afa80d | 2026 | |
5165f125 | 2027 | if (! d_check_char (di, '_')) |
bd6946d1 | 2028 | return 0; |
69afa80d | 2029 | |
bd6946d1 | 2030 | return 1; |
69afa80d AS |
2031 | } |
2032 | ||
bd6946d1 ILT |
2033 | /* <ctor-dtor-name> ::= C1 |
2034 | ::= C2 | |
2035 | ::= C3 | |
2036 | ::= D0 | |
2037 | ::= D1 | |
2038 | ::= D2 | |
2039 | */ | |
2040 | ||
5e777af5 | 2041 | static struct demangle_component * |
9486db4f | 2042 | d_ctor_dtor_name (struct d_info *di) |
bd6946d1 | 2043 | { |
2d6c4025 ILT |
2044 | if (di->last_name != NULL) |
2045 | { | |
5e777af5 | 2046 | if (di->last_name->type == DEMANGLE_COMPONENT_NAME) |
2d6c4025 | 2047 | di->expansion += di->last_name->u.s_name.len; |
5e777af5 | 2048 | else if (di->last_name->type == DEMANGLE_COMPONENT_SUB_STD) |
2d6c4025 ILT |
2049 | di->expansion += di->last_name->u.s_string.len; |
2050 | } | |
5165f125 | 2051 | switch (d_peek_char (di)) |
bd6946d1 ILT |
2052 | { |
2053 | case 'C': | |
2054 | { | |
2055 | enum gnu_v3_ctor_kinds kind; | |
2056 | ||
5165f125 | 2057 | switch (d_peek_next_char (di)) |
bd6946d1 ILT |
2058 | { |
2059 | case '1': | |
2060 | kind = gnu_v3_complete_object_ctor; | |
2061 | break; | |
2062 | case '2': | |
2063 | kind = gnu_v3_base_object_ctor; | |
2064 | break; | |
2065 | case '3': | |
2066 | kind = gnu_v3_complete_object_allocating_ctor; | |
2067 | break; | |
0a35513e AH |
2068 | case '5': |
2069 | kind = gnu_v3_object_ctor_group; | |
2070 | break; | |
bd6946d1 ILT |
2071 | default: |
2072 | return NULL; | |
2073 | } | |
5165f125 | 2074 | d_advance (di, 2); |
bd6946d1 ILT |
2075 | return d_make_ctor (di, kind, di->last_name); |
2076 | } | |
2077 | ||
2078 | case 'D': | |
2079 | { | |
2080 | enum gnu_v3_dtor_kinds kind; | |
2081 | ||
5165f125 | 2082 | switch (d_peek_next_char (di)) |
bd6946d1 ILT |
2083 | { |
2084 | case '0': | |
2085 | kind = gnu_v3_deleting_dtor; | |
2086 | break; | |
2087 | case '1': | |
2088 | kind = gnu_v3_complete_object_dtor; | |
2089 | break; | |
2090 | case '2': | |
2091 | kind = gnu_v3_base_object_dtor; | |
2092 | break; | |
0a35513e AH |
2093 | case '5': |
2094 | kind = gnu_v3_object_dtor_group; | |
2095 | break; | |
bd6946d1 ILT |
2096 | default: |
2097 | return NULL; | |
2098 | } | |
5165f125 | 2099 | d_advance (di, 2); |
bd6946d1 ILT |
2100 | return d_make_dtor (di, kind, di->last_name); |
2101 | } | |
69afa80d | 2102 | |
bd6946d1 ILT |
2103 | default: |
2104 | return NULL; | |
2105 | } | |
2106 | } | |
69afa80d | 2107 | |
bd6946d1 ILT |
2108 | /* <type> ::= <builtin-type> |
2109 | ::= <function-type> | |
2110 | ::= <class-enum-type> | |
2111 | ::= <array-type> | |
2112 | ::= <pointer-to-member-type> | |
2113 | ::= <template-param> | |
2114 | ::= <template-template-param> <template-args> | |
2115 | ::= <substitution> | |
2116 | ::= <CV-qualifiers> <type> | |
2117 | ::= P <type> | |
2118 | ::= R <type> | |
1ab28be5 | 2119 | ::= O <type> (C++0x) |
bd6946d1 ILT |
2120 | ::= C <type> |
2121 | ::= G <type> | |
2122 | ::= U <source-name> <type> | |
2123 | ||
2124 | <builtin-type> ::= various one letter codes | |
2125 | ::= u <source-name> | |
2126 | */ | |
69afa80d | 2127 | |
5e777af5 ILT |
2128 | CP_STATIC_IF_GLIBCPP_V3 |
2129 | const struct demangle_builtin_type_info | |
2130 | cplus_demangle_builtin_types[D_BUILTIN_TYPE_COUNT] = | |
bd6946d1 | 2131 | { |
31058ee3 | 2132 | /* a */ { NL ("signed char"), NL ("signed char"), D_PRINT_DEFAULT }, |
2d6c4025 | 2133 | /* b */ { NL ("bool"), NL ("boolean"), D_PRINT_BOOL }, |
31058ee3 ILT |
2134 | /* c */ { NL ("char"), NL ("byte"), D_PRINT_DEFAULT }, |
2135 | /* d */ { NL ("double"), NL ("double"), D_PRINT_FLOAT }, | |
2136 | /* e */ { NL ("long double"), NL ("long double"), D_PRINT_FLOAT }, | |
2137 | /* f */ { NL ("float"), NL ("float"), D_PRINT_FLOAT }, | |
2138 | /* g */ { NL ("__float128"), NL ("__float128"), D_PRINT_FLOAT }, | |
2139 | /* h */ { NL ("unsigned char"), NL ("unsigned char"), D_PRINT_DEFAULT }, | |
2d6c4025 | 2140 | /* i */ { NL ("int"), NL ("int"), D_PRINT_INT }, |
31058ee3 | 2141 | /* j */ { NL ("unsigned int"), NL ("unsigned"), D_PRINT_UNSIGNED }, |
2d6c4025 ILT |
2142 | /* k */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT }, |
2143 | /* l */ { NL ("long"), NL ("long"), D_PRINT_LONG }, | |
31058ee3 | 2144 | /* m */ { NL ("unsigned long"), NL ("unsigned long"), D_PRINT_UNSIGNED_LONG }, |
2d6c4025 | 2145 | /* n */ { NL ("__int128"), NL ("__int128"), D_PRINT_DEFAULT }, |
31058ee3 ILT |
2146 | /* o */ { NL ("unsigned __int128"), NL ("unsigned __int128"), |
2147 | D_PRINT_DEFAULT }, | |
38179091 JM |
2148 | /* p */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT }, |
2149 | /* q */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT }, | |
2150 | /* r */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT }, | |
31058ee3 ILT |
2151 | /* s */ { NL ("short"), NL ("short"), D_PRINT_DEFAULT }, |
2152 | /* t */ { NL ("unsigned short"), NL ("unsigned short"), D_PRINT_DEFAULT }, | |
38179091 | 2153 | /* u */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT }, |
2d6c4025 | 2154 | /* v */ { NL ("void"), NL ("void"), D_PRINT_VOID }, |
31058ee3 ILT |
2155 | /* w */ { NL ("wchar_t"), NL ("char"), D_PRINT_DEFAULT }, |
2156 | /* x */ { NL ("long long"), NL ("long"), D_PRINT_LONG_LONG }, | |
2157 | /* y */ { NL ("unsigned long long"), NL ("unsigned long long"), | |
2158 | D_PRINT_UNSIGNED_LONG_LONG }, | |
2d6c4025 | 2159 | /* z */ { NL ("..."), NL ("..."), D_PRINT_DEFAULT }, |
38179091 JM |
2160 | /* 26 */ { NL ("decimal32"), NL ("decimal32"), D_PRINT_DEFAULT }, |
2161 | /* 27 */ { NL ("decimal64"), NL ("decimal64"), D_PRINT_DEFAULT }, | |
2162 | /* 28 */ { NL ("decimal128"), NL ("decimal128"), D_PRINT_DEFAULT }, | |
2163 | /* 29 */ { NL ("half"), NL ("half"), D_PRINT_FLOAT }, | |
2164 | /* 30 */ { NL ("char16_t"), NL ("char16_t"), D_PRINT_DEFAULT }, | |
2165 | /* 31 */ { NL ("char32_t"), NL ("char32_t"), D_PRINT_DEFAULT }, | |
14c2101d JM |
2166 | /* 32 */ { NL ("decltype(nullptr)"), NL ("decltype(nullptr)"), |
2167 | D_PRINT_DEFAULT }, | |
bd6946d1 | 2168 | }; |
69afa80d | 2169 | |
5e777af5 ILT |
2170 | CP_STATIC_IF_GLIBCPP_V3 |
2171 | struct demangle_component * | |
9486db4f | 2172 | cplus_demangle_type (struct d_info *di) |
69afa80d | 2173 | { |
bd6946d1 | 2174 | char peek; |
5e777af5 | 2175 | struct demangle_component *ret; |
bd6946d1 ILT |
2176 | int can_subst; |
2177 | ||
2178 | /* The ABI specifies that when CV-qualifiers are used, the base type | |
2179 | is substitutable, and the fully qualified type is substitutable, | |
2180 | but the base type with a strict subset of the CV-qualifiers is | |
2181 | not substitutable. The natural recursive implementation of the | |
2182 | CV-qualifiers would cause subsets to be substitutable, so instead | |
2183 | we pull them all off now. | |
2184 | ||
81dc098b ILT |
2185 | FIXME: The ABI says that order-insensitive vendor qualifiers |
2186 | should be handled in the same way, but we have no way to tell | |
2187 | which vendor qualifiers are order-insensitive and which are | |
2188 | order-sensitive. So we just assume that they are all | |
2189 | order-sensitive. g++ 3.4 supports only one vendor qualifier, | |
2190 | __vector, and it treats it as order-sensitive when mangling | |
2191 | names. */ | |
bd6946d1 ILT |
2192 | |
2193 | peek = d_peek_char (di); | |
2194 | if (peek == 'r' || peek == 'V' || peek == 'K') | |
2195 | { | |
5e777af5 | 2196 | struct demangle_component **pret; |
69afa80d | 2197 | |
a51753e4 | 2198 | pret = d_cv_qualifiers (di, &ret, 0); |
81dc098b ILT |
2199 | if (pret == NULL) |
2200 | return NULL; | |
5e777af5 | 2201 | *pret = cplus_demangle_type (di); |
9eb85f27 JM |
2202 | if (! *pret) |
2203 | return NULL; | |
2204 | if ((*pret)->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS | |
2205 | || (*pret)->type == DEMANGLE_COMPONENT_REFERENCE_THIS) | |
2206 | { | |
2207 | /* Move the ref-qualifier outside the cv-qualifiers so that | |
2208 | they are printed in the right order. */ | |
2209 | struct demangle_component *fn = d_left (*pret); | |
2210 | d_left (*pret) = ret; | |
2211 | ret = *pret; | |
2212 | *pret = fn; | |
2213 | } | |
2214 | if (! d_add_substitution (di, ret)) | |
bd6946d1 ILT |
2215 | return NULL; |
2216 | return ret; | |
2217 | } | |
1056d228 | 2218 | |
bd6946d1 | 2219 | can_subst = 1; |
69afa80d | 2220 | |
a440fd19 | 2221 | switch (peek) |
69afa80d | 2222 | { |
bd6946d1 ILT |
2223 | case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': |
2224 | case 'h': case 'i': case 'j': case 'l': case 'm': case 'n': | |
2225 | case 'o': case 's': case 't': | |
2226 | case 'v': case 'w': case 'x': case 'y': case 'z': | |
5e777af5 ILT |
2227 | ret = d_make_builtin_type (di, |
2228 | &cplus_demangle_builtin_types[peek - 'a']); | |
2d6c4025 | 2229 | di->expansion += ret->u.s_builtin.type->len; |
bd6946d1 ILT |
2230 | can_subst = 0; |
2231 | d_advance (di, 1); | |
2232 | break; | |
2233 | ||
2234 | case 'u': | |
2235 | d_advance (di, 1); | |
5e777af5 ILT |
2236 | ret = d_make_comp (di, DEMANGLE_COMPONENT_VENDOR_TYPE, |
2237 | d_source_name (di), NULL); | |
bd6946d1 ILT |
2238 | break; |
2239 | ||
2240 | case 'F': | |
2241 | ret = d_function_type (di); | |
69afa80d AS |
2242 | break; |
2243 | ||
bd6946d1 ILT |
2244 | case '0': case '1': case '2': case '3': case '4': |
2245 | case '5': case '6': case '7': case '8': case '9': | |
2246 | case 'N': | |
69afa80d | 2247 | case 'Z': |
bd6946d1 | 2248 | ret = d_class_enum_type (di); |
69afa80d AS |
2249 | break; |
2250 | ||
bd6946d1 ILT |
2251 | case 'A': |
2252 | ret = d_array_type (di); | |
2253 | break; | |
2254 | ||
2255 | case 'M': | |
2256 | ret = d_pointer_to_member_type (di); | |
2257 | break; | |
2258 | ||
2259 | case 'T': | |
2260 | ret = d_template_param (di); | |
2261 | if (d_peek_char (di) == 'I') | |
bece74bd | 2262 | { |
bd6946d1 ILT |
2263 | /* This is <template-template-param> <template-args>. The |
2264 | <template-template-param> part is a substitution | |
2265 | candidate. */ | |
2266 | if (! d_add_substitution (di, ret)) | |
2267 | return NULL; | |
5e777af5 ILT |
2268 | ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret, |
2269 | d_template_args (di)); | |
bece74bd | 2270 | } |
bd6946d1 ILT |
2271 | break; |
2272 | ||
2273 | case 'S': | |
2274 | /* If this is a special substitution, then it is the start of | |
2275 | <class-enum-type>. */ | |
2276 | { | |
2277 | char peek_next; | |
d01ce591 | 2278 | |
bd6946d1 ILT |
2279 | peek_next = d_peek_next_char (di); |
2280 | if (IS_DIGIT (peek_next) | |
2281 | || peek_next == '_' | |
a51753e4 | 2282 | || IS_UPPER (peek_next)) |
bd6946d1 | 2283 | { |
374caa50 | 2284 | ret = d_substitution (di, 0); |
bd6946d1 ILT |
2285 | /* The substituted name may have been a template name and |
2286 | may be followed by tepmlate args. */ | |
2287 | if (d_peek_char (di) == 'I') | |
5e777af5 | 2288 | ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret, |
bd6946d1 ILT |
2289 | d_template_args (di)); |
2290 | else | |
2291 | can_subst = 0; | |
2292 | } | |
2293 | else | |
2294 | { | |
2295 | ret = d_class_enum_type (di); | |
2296 | /* If the substitution was a complete type, then it is not | |
2297 | a new substitution candidate. However, if the | |
2298 | substitution was followed by template arguments, then | |
2299 | the whole thing is a substitution candidate. */ | |
5e777af5 | 2300 | if (ret != NULL && ret->type == DEMANGLE_COMPONENT_SUB_STD) |
bd6946d1 ILT |
2301 | can_subst = 0; |
2302 | } | |
2303 | } | |
69afa80d AS |
2304 | break; |
2305 | ||
1ab28be5 DG |
2306 | case 'O': |
2307 | d_advance (di, 1); | |
2308 | ret = d_make_comp (di, DEMANGLE_COMPONENT_RVALUE_REFERENCE, | |
2309 | cplus_demangle_type (di), NULL); | |
2310 | break; | |
2311 | ||
bd6946d1 ILT |
2312 | case 'P': |
2313 | d_advance (di, 1); | |
5e777af5 ILT |
2314 | ret = d_make_comp (di, DEMANGLE_COMPONENT_POINTER, |
2315 | cplus_demangle_type (di), NULL); | |
bd6946d1 | 2316 | break; |
69afa80d | 2317 | |
bd6946d1 ILT |
2318 | case 'R': |
2319 | d_advance (di, 1); | |
5e777af5 | 2320 | ret = d_make_comp (di, DEMANGLE_COMPONENT_REFERENCE, |
1ab28be5 | 2321 | cplus_demangle_type (di), NULL); |
bd6946d1 | 2322 | break; |
69afa80d | 2323 | |
bd6946d1 ILT |
2324 | case 'C': |
2325 | d_advance (di, 1); | |
5e777af5 ILT |
2326 | ret = d_make_comp (di, DEMANGLE_COMPONENT_COMPLEX, |
2327 | cplus_demangle_type (di), NULL); | |
bd6946d1 ILT |
2328 | break; |
2329 | ||
2330 | case 'G': | |
2331 | d_advance (di, 1); | |
5e777af5 ILT |
2332 | ret = d_make_comp (di, DEMANGLE_COMPONENT_IMAGINARY, |
2333 | cplus_demangle_type (di), NULL); | |
bd6946d1 | 2334 | break; |
69afa80d | 2335 | |
bd6946d1 ILT |
2336 | case 'U': |
2337 | d_advance (di, 1); | |
2338 | ret = d_source_name (di); | |
5e777af5 ILT |
2339 | ret = d_make_comp (di, DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL, |
2340 | cplus_demangle_type (di), ret); | |
69afa80d | 2341 | break; |
bd6946d1 | 2342 | |
5a3d7e74 JM |
2343 | case 'D': |
2344 | can_subst = 0; | |
2345 | d_advance (di, 1); | |
2346 | peek = d_next_char (di); | |
2347 | switch (peek) | |
2348 | { | |
2349 | case 'T': | |
2350 | case 't': | |
2351 | /* decltype (expression) */ | |
2352 | ret = d_make_comp (di, DEMANGLE_COMPONENT_DECLTYPE, | |
2353 | d_expression (di), NULL); | |
2354 | if (ret && d_next_char (di) != 'E') | |
2355 | ret = NULL; | |
49f2da1a | 2356 | can_subst = 1; |
5a3d7e74 JM |
2357 | break; |
2358 | ||
2359 | case 'p': | |
2360 | /* Pack expansion. */ | |
38179091 JM |
2361 | ret = d_make_comp (di, DEMANGLE_COMPONENT_PACK_EXPANSION, |
2362 | cplus_demangle_type (di), NULL); | |
49f2da1a | 2363 | can_subst = 1; |
38179091 | 2364 | break; |
c19267cb JM |
2365 | |
2366 | case 'a': | |
2367 | /* auto */ | |
2368 | ret = d_make_name (di, "auto", 4); | |
2369 | break; | |
5a3d7e74 JM |
2370 | |
2371 | case 'f': | |
38179091 JM |
2372 | /* 32-bit decimal floating point */ |
2373 | ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[26]); | |
5a3d7e74 JM |
2374 | di->expansion += ret->u.s_builtin.type->len; |
2375 | break; | |
2376 | case 'd': | |
38179091 JM |
2377 | /* 64-bit DFP */ |
2378 | ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[27]); | |
5a3d7e74 JM |
2379 | di->expansion += ret->u.s_builtin.type->len; |
2380 | break; | |
2381 | case 'e': | |
2382 | /* 128-bit DFP */ | |
38179091 | 2383 | ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[28]); |
5a3d7e74 JM |
2384 | di->expansion += ret->u.s_builtin.type->len; |
2385 | break; | |
2386 | case 'h': | |
2387 | /* 16-bit half-precision FP */ | |
38179091 JM |
2388 | ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[29]); |
2389 | di->expansion += ret->u.s_builtin.type->len; | |
2390 | break; | |
2391 | case 's': | |
2392 | /* char16_t */ | |
2393 | ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[30]); | |
2394 | di->expansion += ret->u.s_builtin.type->len; | |
2395 | break; | |
2396 | case 'i': | |
2397 | /* char32_t */ | |
2398 | ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[31]); | |
5a3d7e74 JM |
2399 | di->expansion += ret->u.s_builtin.type->len; |
2400 | break; | |
07523e7c JM |
2401 | |
2402 | case 'F': | |
2403 | /* Fixed point types. DF<int bits><length><fract bits><sat> */ | |
2404 | ret = d_make_empty (di); | |
2405 | ret->type = DEMANGLE_COMPONENT_FIXED_TYPE; | |
2406 | if ((ret->u.s_fixed.accum = IS_DIGIT (d_peek_char (di)))) | |
2407 | /* For demangling we don't care about the bits. */ | |
2408 | d_number (di); | |
2409 | ret->u.s_fixed.length = cplus_demangle_type (di); | |
79b754d4 ILT |
2410 | if (ret->u.s_fixed.length == NULL) |
2411 | return NULL; | |
07523e7c JM |
2412 | d_number (di); |
2413 | peek = d_next_char (di); | |
2414 | ret->u.s_fixed.sat = (peek == 's'); | |
2415 | break; | |
381009fe | 2416 | |
abfe01ce JM |
2417 | case 'v': |
2418 | ret = d_vector_type (di); | |
49f2da1a | 2419 | can_subst = 1; |
abfe01ce JM |
2420 | break; |
2421 | ||
14c2101d JM |
2422 | case 'n': |
2423 | /* decltype(nullptr) */ | |
2424 | ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[32]); | |
2425 | di->expansion += ret->u.s_builtin.type->len; | |
2426 | break; | |
2427 | ||
381009fe BE |
2428 | default: |
2429 | return NULL; | |
5a3d7e74 JM |
2430 | } |
2431 | break; | |
2432 | ||
bd6946d1 ILT |
2433 | default: |
2434 | return NULL; | |
69afa80d AS |
2435 | } |
2436 | ||
bd6946d1 ILT |
2437 | if (can_subst) |
2438 | { | |
2439 | if (! d_add_substitution (di, ret)) | |
2440 | return NULL; | |
2441 | } | |
69afa80d | 2442 | |
bd6946d1 ILT |
2443 | return ret; |
2444 | } | |
69afa80d | 2445 | |
bd6946d1 | 2446 | /* <CV-qualifiers> ::= [r] [V] [K] */ |
69afa80d | 2447 | |
5e777af5 | 2448 | static struct demangle_component ** |
9486db4f GDR |
2449 | d_cv_qualifiers (struct d_info *di, |
2450 | struct demangle_component **pret, int member_fn) | |
69afa80d | 2451 | { |
d58818f7 | 2452 | struct demangle_component **pstart; |
69afa80d AS |
2453 | char peek; |
2454 | ||
d58818f7 | 2455 | pstart = pret; |
bd6946d1 ILT |
2456 | peek = d_peek_char (di); |
2457 | while (peek == 'r' || peek == 'V' || peek == 'K') | |
69afa80d | 2458 | { |
5e777af5 | 2459 | enum demangle_component_type t; |
0870bfd6 | 2460 | |
bd6946d1 ILT |
2461 | d_advance (di, 1); |
2462 | if (peek == 'r') | |
2d6c4025 | 2463 | { |
5e777af5 ILT |
2464 | t = (member_fn |
2465 | ? DEMANGLE_COMPONENT_RESTRICT_THIS | |
2466 | : DEMANGLE_COMPONENT_RESTRICT); | |
2d6c4025 ILT |
2467 | di->expansion += sizeof "restrict"; |
2468 | } | |
bd6946d1 | 2469 | else if (peek == 'V') |
2d6c4025 | 2470 | { |
5e777af5 ILT |
2471 | t = (member_fn |
2472 | ? DEMANGLE_COMPONENT_VOLATILE_THIS | |
2473 | : DEMANGLE_COMPONENT_VOLATILE); | |
2d6c4025 ILT |
2474 | di->expansion += sizeof "volatile"; |
2475 | } | |
bd6946d1 | 2476 | else |
2d6c4025 | 2477 | { |
5e777af5 ILT |
2478 | t = (member_fn |
2479 | ? DEMANGLE_COMPONENT_CONST_THIS | |
2480 | : DEMANGLE_COMPONENT_CONST); | |
2d6c4025 ILT |
2481 | di->expansion += sizeof "const"; |
2482 | } | |
69afa80d | 2483 | |
bd6946d1 ILT |
2484 | *pret = d_make_comp (di, t, NULL, NULL); |
2485 | if (*pret == NULL) | |
2486 | return NULL; | |
2487 | pret = &d_left (*pret); | |
69afa80d | 2488 | |
bd6946d1 ILT |
2489 | peek = d_peek_char (di); |
2490 | } | |
69afa80d | 2491 | |
d58818f7 ILT |
2492 | if (!member_fn && peek == 'F') |
2493 | { | |
2494 | while (pstart != pret) | |
2495 | { | |
2496 | switch ((*pstart)->type) | |
2497 | { | |
2498 | case DEMANGLE_COMPONENT_RESTRICT: | |
2499 | (*pstart)->type = DEMANGLE_COMPONENT_RESTRICT_THIS; | |
2500 | break; | |
2501 | case DEMANGLE_COMPONENT_VOLATILE: | |
2502 | (*pstart)->type = DEMANGLE_COMPONENT_VOLATILE_THIS; | |
2503 | break; | |
2504 | case DEMANGLE_COMPONENT_CONST: | |
2505 | (*pstart)->type = DEMANGLE_COMPONENT_CONST_THIS; | |
2506 | break; | |
2507 | default: | |
2508 | break; | |
2509 | } | |
2510 | pstart = &d_left (*pstart); | |
2511 | } | |
2512 | } | |
2513 | ||
bd6946d1 ILT |
2514 | return pret; |
2515 | } | |
69afa80d | 2516 | |
9eb85f27 JM |
2517 | /* <ref-qualifier> ::= R |
2518 | ::= O */ | |
2519 | ||
2520 | static struct demangle_component * | |
2521 | d_ref_qualifier (struct d_info *di, struct demangle_component *sub) | |
2522 | { | |
2523 | struct demangle_component *ret = sub; | |
2524 | char peek; | |
2525 | ||
2526 | peek = d_peek_char (di); | |
2527 | if (peek == 'R' || peek == 'O') | |
2528 | { | |
2529 | enum demangle_component_type t; | |
2530 | if (peek == 'R') | |
2531 | { | |
2532 | t = DEMANGLE_COMPONENT_REFERENCE_THIS; | |
2533 | di->expansion += sizeof "&"; | |
2534 | } | |
2535 | else | |
2536 | { | |
2537 | t = DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS; | |
2538 | di->expansion += sizeof "&&"; | |
2539 | } | |
2540 | d_advance (di, 1); | |
2541 | ||
2542 | ret = d_make_comp (di, t, ret, NULL); | |
2543 | } | |
2544 | ||
2545 | return ret; | |
2546 | } | |
2547 | ||
2548 | /* <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E */ | |
69afa80d | 2549 | |
5e777af5 | 2550 | static struct demangle_component * |
9486db4f | 2551 | d_function_type (struct d_info *di) |
69afa80d | 2552 | { |
5e777af5 | 2553 | struct demangle_component *ret; |
69afa80d | 2554 | |
5165f125 | 2555 | if (! d_check_char (di, 'F')) |
bd6946d1 ILT |
2556 | return NULL; |
2557 | if (d_peek_char (di) == 'Y') | |
2558 | { | |
2559 | /* Function has C linkage. We don't print this information. | |
2560 | FIXME: We should print it in verbose mode. */ | |
2561 | d_advance (di, 1); | |
2562 | } | |
2563 | ret = d_bare_function_type (di, 1); | |
9eb85f27 JM |
2564 | ret = d_ref_qualifier (di, ret); |
2565 | ||
5165f125 | 2566 | if (! d_check_char (di, 'E')) |
bd6946d1 ILT |
2567 | return NULL; |
2568 | return ret; | |
2569 | } | |
e282c9c9 | 2570 | |
d5f4eddd | 2571 | /* <type>+ */ |
69afa80d | 2572 | |
5e777af5 | 2573 | static struct demangle_component * |
d5f4eddd | 2574 | d_parmlist (struct d_info *di) |
bd6946d1 | 2575 | { |
5e777af5 ILT |
2576 | struct demangle_component *tl; |
2577 | struct demangle_component **ptl; | |
92aed1cb | 2578 | |
bd6946d1 ILT |
2579 | tl = NULL; |
2580 | ptl = &tl; | |
69afa80d AS |
2581 | while (1) |
2582 | { | |
5e777af5 | 2583 | struct demangle_component *type; |
69afa80d | 2584 | |
d5f4eddd | 2585 | char peek = d_peek_char (di); |
2d2b02c4 | 2586 | if (peek == '\0' || peek == 'E' || peek == '.') |
bd6946d1 | 2587 | break; |
9eb85f27 JM |
2588 | if ((peek == 'R' || peek == 'O') |
2589 | && d_peek_next_char (di) == 'E') | |
2590 | /* Function ref-qualifier, not a ref prefix for a parameter type. */ | |
2591 | break; | |
5e777af5 | 2592 | type = cplus_demangle_type (di); |
bd6946d1 ILT |
2593 | if (type == NULL) |
2594 | return NULL; | |
d5f4eddd JM |
2595 | *ptl = d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, type, NULL); |
2596 | if (*ptl == NULL) | |
2597 | return NULL; | |
2598 | ptl = &d_right (*ptl); | |
69afa80d | 2599 | } |
69afa80d | 2600 | |
bd6946d1 ILT |
2601 | /* There should be at least one parameter type besides the optional |
2602 | return type. A function which takes no arguments will have a | |
2603 | single parameter type void. */ | |
2604 | if (tl == NULL) | |
2605 | return NULL; | |
69afa80d | 2606 | |
bd6946d1 ILT |
2607 | /* If we have a single parameter type void, omit it. */ |
2608 | if (d_right (tl) == NULL | |
5e777af5 | 2609 | && d_left (tl)->type == DEMANGLE_COMPONENT_BUILTIN_TYPE |
bd6946d1 | 2610 | && d_left (tl)->u.s_builtin.type->print == D_PRINT_VOID) |
2d6c4025 ILT |
2611 | { |
2612 | di->expansion -= d_left (tl)->u.s_builtin.type->len; | |
d5f4eddd | 2613 | d_left (tl) = NULL; |
2d6c4025 | 2614 | } |
69afa80d | 2615 | |
d5f4eddd JM |
2616 | return tl; |
2617 | } | |
2618 | ||
2619 | /* <bare-function-type> ::= [J]<type>+ */ | |
2620 | ||
2621 | static struct demangle_component * | |
2622 | d_bare_function_type (struct d_info *di, int has_return_type) | |
2623 | { | |
2624 | struct demangle_component *return_type; | |
2625 | struct demangle_component *tl; | |
2626 | char peek; | |
2627 | ||
2628 | /* Detect special qualifier indicating that the first argument | |
2629 | is the return type. */ | |
2630 | peek = d_peek_char (di); | |
2631 | if (peek == 'J') | |
2632 | { | |
2633 | d_advance (di, 1); | |
2634 | has_return_type = 1; | |
2635 | } | |
2636 | ||
2637 | if (has_return_type) | |
2638 | { | |
2639 | return_type = cplus_demangle_type (di); | |
2640 | if (return_type == NULL) | |
2641 | return NULL; | |
2642 | } | |
2643 | else | |
2644 | return_type = NULL; | |
2645 | ||
2646 | tl = d_parmlist (di); | |
2647 | if (tl == NULL) | |
2648 | return NULL; | |
2649 | ||
2650 | return d_make_comp (di, DEMANGLE_COMPONENT_FUNCTION_TYPE, | |
2651 | return_type, tl); | |
bd6946d1 | 2652 | } |
69afa80d | 2653 | |
bd6946d1 | 2654 | /* <class-enum-type> ::= <name> */ |
69afa80d | 2655 | |
5e777af5 | 2656 | static struct demangle_component * |
9486db4f | 2657 | d_class_enum_type (struct d_info *di) |
bd6946d1 ILT |
2658 | { |
2659 | return d_name (di); | |
2660 | } | |
1056d228 | 2661 | |
bd6946d1 ILT |
2662 | /* <array-type> ::= A <(positive dimension) number> _ <(element) type> |
2663 | ::= A [<(dimension) expression>] _ <(element) type> | |
2664 | */ | |
1056d228 | 2665 | |
5e777af5 | 2666 | static struct demangle_component * |
9486db4f | 2667 | d_array_type (struct d_info *di) |
bd6946d1 ILT |
2668 | { |
2669 | char peek; | |
5e777af5 | 2670 | struct demangle_component *dim; |
1056d228 | 2671 | |
5165f125 | 2672 | if (! d_check_char (di, 'A')) |
bd6946d1 ILT |
2673 | return NULL; |
2674 | ||
2675 | peek = d_peek_char (di); | |
2676 | if (peek == '_') | |
2677 | dim = NULL; | |
2678 | else if (IS_DIGIT (peek)) | |
1056d228 | 2679 | { |
bd6946d1 | 2680 | const char *s; |
1056d228 | 2681 | |
bd6946d1 ILT |
2682 | s = d_str (di); |
2683 | do | |
2684 | { | |
2685 | d_advance (di, 1); | |
2686 | peek = d_peek_char (di); | |
2687 | } | |
2688 | while (IS_DIGIT (peek)); | |
2689 | dim = d_make_name (di, s, d_str (di) - s); | |
81dc098b ILT |
2690 | if (dim == NULL) |
2691 | return NULL; | |
1056d228 | 2692 | } |
69afa80d | 2693 | else |
bd6946d1 ILT |
2694 | { |
2695 | dim = d_expression (di); | |
2696 | if (dim == NULL) | |
2697 | return NULL; | |
2698 | } | |
69afa80d | 2699 | |
5165f125 | 2700 | if (! d_check_char (di, '_')) |
bd6946d1 | 2701 | return NULL; |
69afa80d | 2702 | |
5e777af5 ILT |
2703 | return d_make_comp (di, DEMANGLE_COMPONENT_ARRAY_TYPE, dim, |
2704 | cplus_demangle_type (di)); | |
bd6946d1 | 2705 | } |
69afa80d | 2706 | |
abfe01ce JM |
2707 | /* <vector-type> ::= Dv <number> _ <type> |
2708 | ::= Dv _ <expression> _ <type> */ | |
2709 | ||
2710 | static struct demangle_component * | |
2711 | d_vector_type (struct d_info *di) | |
2712 | { | |
2713 | char peek; | |
2714 | struct demangle_component *dim; | |
2715 | ||
2716 | peek = d_peek_char (di); | |
2717 | if (peek == '_') | |
2718 | { | |
2719 | d_advance (di, 1); | |
2720 | dim = d_expression (di); | |
2721 | } | |
2722 | else | |
2723 | dim = d_number_component (di); | |
2724 | ||
2725 | if (dim == NULL) | |
2726 | return NULL; | |
2727 | ||
2728 | if (! d_check_char (di, '_')) | |
2729 | return NULL; | |
2730 | ||
2731 | return d_make_comp (di, DEMANGLE_COMPONENT_VECTOR_TYPE, dim, | |
2732 | cplus_demangle_type (di)); | |
2733 | } | |
2734 | ||
bd6946d1 | 2735 | /* <pointer-to-member-type> ::= M <(class) type> <(member) type> */ |
69afa80d | 2736 | |
5e777af5 | 2737 | static struct demangle_component * |
9486db4f | 2738 | d_pointer_to_member_type (struct d_info *di) |
69afa80d | 2739 | { |
5e777af5 ILT |
2740 | struct demangle_component *cl; |
2741 | struct demangle_component *mem; | |
2742 | struct demangle_component **pmem; | |
69afa80d | 2743 | |
5165f125 | 2744 | if (! d_check_char (di, 'M')) |
bd6946d1 | 2745 | return NULL; |
69afa80d | 2746 | |
5e777af5 | 2747 | cl = cplus_demangle_type (di); |
69afa80d | 2748 | |
bd6946d1 ILT |
2749 | /* The ABI specifies that any type can be a substitution source, and |
2750 | that M is followed by two types, and that when a CV-qualified | |
2751 | type is seen both the base type and the CV-qualified types are | |
2752 | substitution sources. The ABI also specifies that for a pointer | |
2753 | to a CV-qualified member function, the qualifiers are attached to | |
2754 | the second type. Given the grammar, a plain reading of the ABI | |
2755 | suggests that both the CV-qualified member function and the | |
2756 | non-qualified member function are substitution sources. However, | |
2757 | g++ does not work that way. g++ treats only the CV-qualified | |
2758 | member function as a substitution source. FIXME. So to work | |
2759 | with g++, we need to pull off the CV-qualifiers here, in order to | |
022d4166 ILT |
2760 | avoid calling add_substitution() in cplus_demangle_type(). But |
2761 | for a CV-qualified member which is not a function, g++ does | |
2762 | follow the ABI, so we need to handle that case here by calling | |
2763 | d_add_substitution ourselves. */ | |
69afa80d | 2764 | |
a51753e4 | 2765 | pmem = d_cv_qualifiers (di, &mem, 1); |
81dc098b ILT |
2766 | if (pmem == NULL) |
2767 | return NULL; | |
5e777af5 | 2768 | *pmem = cplus_demangle_type (di); |
771904f1 GK |
2769 | if (*pmem == NULL) |
2770 | return NULL; | |
69afa80d | 2771 | |
9eb85f27 JM |
2772 | if (pmem != &mem |
2773 | && ((*pmem)->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS | |
2774 | || (*pmem)->type == DEMANGLE_COMPONENT_REFERENCE_THIS)) | |
2775 | { | |
2776 | /* Move the ref-qualifier outside the cv-qualifiers so that | |
2777 | they are printed in the right order. */ | |
2778 | struct demangle_component *fn = d_left (*pmem); | |
2779 | d_left (*pmem) = mem; | |
2780 | mem = *pmem; | |
2781 | *pmem = fn; | |
2782 | } | |
2783 | ||
022d4166 ILT |
2784 | if (pmem != &mem && (*pmem)->type != DEMANGLE_COMPONENT_FUNCTION_TYPE) |
2785 | { | |
2786 | if (! d_add_substitution (di, mem)) | |
2787 | return NULL; | |
2788 | } | |
2789 | ||
5e777af5 | 2790 | return d_make_comp (di, DEMANGLE_COMPONENT_PTRMEM_TYPE, cl, mem); |
69afa80d AS |
2791 | } |
2792 | ||
d5f4eddd JM |
2793 | /* <non-negative number> _ */ |
2794 | ||
2795 | static long | |
2796 | d_compact_number (struct d_info *di) | |
2797 | { | |
2798 | long num; | |
2799 | if (d_peek_char (di) == '_') | |
2800 | num = 0; | |
2801 | else if (d_peek_char (di) == 'n') | |
2802 | return -1; | |
2803 | else | |
2804 | num = d_number (di) + 1; | |
2805 | ||
2806 | if (! d_check_char (di, '_')) | |
2807 | return -1; | |
2808 | return num; | |
2809 | } | |
2810 | ||
bd6946d1 ILT |
2811 | /* <template-param> ::= T_ |
2812 | ::= T <(parameter-2 non-negative) number> _ | |
2813 | */ | |
69afa80d | 2814 | |
5e777af5 | 2815 | static struct demangle_component * |
9486db4f | 2816 | d_template_param (struct d_info *di) |
69afa80d | 2817 | { |
bd6946d1 | 2818 | long param; |
69afa80d | 2819 | |
5165f125 | 2820 | if (! d_check_char (di, 'T')) |
bd6946d1 | 2821 | return NULL; |
69afa80d | 2822 | |
d5f4eddd JM |
2823 | param = d_compact_number (di); |
2824 | if (param < 0) | |
bd6946d1 | 2825 | return NULL; |
69afa80d | 2826 | |
2d6c4025 ILT |
2827 | ++di->did_subs; |
2828 | ||
bd6946d1 | 2829 | return d_make_template_param (di, param); |
69afa80d AS |
2830 | } |
2831 | ||
bd6946d1 ILT |
2832 | /* <template-args> ::= I <template-arg>+ E */ |
2833 | ||
5e777af5 | 2834 | static struct demangle_component * |
9486db4f | 2835 | d_template_args (struct d_info *di) |
69afa80d | 2836 | { |
5e777af5 ILT |
2837 | struct demangle_component *hold_last_name; |
2838 | struct demangle_component *al; | |
2839 | struct demangle_component **pal; | |
69afa80d | 2840 | |
bd6946d1 ILT |
2841 | /* Preserve the last name we saw--don't let the template arguments |
2842 | clobber it, as that would give us the wrong name for a subsequent | |
2843 | constructor or destructor. */ | |
2844 | hold_last_name = di->last_name; | |
69afa80d | 2845 | |
4b6aaa99 JM |
2846 | if (d_peek_char (di) != 'I' |
2847 | && d_peek_char (di) != 'J') | |
bd6946d1 | 2848 | return NULL; |
4b6aaa99 | 2849 | d_advance (di, 1); |
69afa80d | 2850 | |
38179091 JM |
2851 | if (d_peek_char (di) == 'E') |
2852 | { | |
2853 | /* An argument pack can be empty. */ | |
2854 | d_advance (di, 1); | |
2855 | return d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, NULL, NULL); | |
2856 | } | |
2857 | ||
bd6946d1 ILT |
2858 | al = NULL; |
2859 | pal = &al; | |
69afa80d AS |
2860 | while (1) |
2861 | { | |
5e777af5 | 2862 | struct demangle_component *a; |
bd6946d1 ILT |
2863 | |
2864 | a = d_template_arg (di); | |
2865 | if (a == NULL) | |
2866 | return NULL; | |
2867 | ||
5e777af5 | 2868 | *pal = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, a, NULL); |
81dc098b ILT |
2869 | if (*pal == NULL) |
2870 | return NULL; | |
bd6946d1 ILT |
2871 | pal = &d_right (*pal); |
2872 | ||
2873 | if (d_peek_char (di) == 'E') | |
051664b0 | 2874 | { |
bd6946d1 ILT |
2875 | d_advance (di, 1); |
2876 | break; | |
051664b0 | 2877 | } |
69afa80d AS |
2878 | } |
2879 | ||
bd6946d1 ILT |
2880 | di->last_name = hold_last_name; |
2881 | ||
2882 | return al; | |
69afa80d AS |
2883 | } |
2884 | ||
bd6946d1 ILT |
2885 | /* <template-arg> ::= <type> |
2886 | ::= X <expression> E | |
2887 | ::= <expr-primary> | |
2888 | */ | |
69afa80d | 2889 | |
5e777af5 | 2890 | static struct demangle_component * |
9486db4f | 2891 | d_template_arg (struct d_info *di) |
69afa80d | 2892 | { |
5e777af5 | 2893 | struct demangle_component *ret; |
051664b0 | 2894 | |
bd6946d1 | 2895 | switch (d_peek_char (di)) |
69afa80d | 2896 | { |
bd6946d1 ILT |
2897 | case 'X': |
2898 | d_advance (di, 1); | |
2899 | ret = d_expression (di); | |
5165f125 | 2900 | if (! d_check_char (di, 'E')) |
bd6946d1 ILT |
2901 | return NULL; |
2902 | return ret; | |
28a34ec1 | 2903 | |
bd6946d1 ILT |
2904 | case 'L': |
2905 | return d_expr_primary (di); | |
69afa80d | 2906 | |
38179091 | 2907 | case 'I': |
4b6aaa99 | 2908 | case 'J': |
38179091 JM |
2909 | /* An argument pack. */ |
2910 | return d_template_args (di); | |
2911 | ||
bd6946d1 | 2912 | default: |
5e777af5 | 2913 | return cplus_demangle_type (di); |
31e0ab1f | 2914 | } |
69afa80d AS |
2915 | } |
2916 | ||
4b6aaa99 JM |
2917 | /* Parse a sequence of expressions until we hit the terminator |
2918 | character. */ | |
5a3d7e74 JM |
2919 | |
2920 | static struct demangle_component * | |
4b6aaa99 | 2921 | d_exprlist (struct d_info *di, char terminator) |
5a3d7e74 JM |
2922 | { |
2923 | struct demangle_component *list = NULL; | |
2924 | struct demangle_component **p = &list; | |
2925 | ||
4b6aaa99 | 2926 | if (d_peek_char (di) == terminator) |
38179091 JM |
2927 | { |
2928 | d_advance (di, 1); | |
2929 | return d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, NULL, NULL); | |
2930 | } | |
2931 | ||
5a3d7e74 JM |
2932 | while (1) |
2933 | { | |
2934 | struct demangle_component *arg = d_expression (di); | |
2935 | if (arg == NULL) | |
2936 | return NULL; | |
2937 | ||
2938 | *p = d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, arg, NULL); | |
2939 | if (*p == NULL) | |
2940 | return NULL; | |
2941 | p = &d_right (*p); | |
2942 | ||
4b6aaa99 | 2943 | if (d_peek_char (di) == terminator) |
5a3d7e74 JM |
2944 | { |
2945 | d_advance (di, 1); | |
2946 | break; | |
2947 | } | |
2948 | } | |
2949 | ||
2950 | return list; | |
2951 | } | |
2952 | ||
aefa74bd JM |
2953 | /* Returns nonzero iff OP is an operator for a C++ cast: const_cast, |
2954 | dynamic_cast, static_cast or reinterpret_cast. */ | |
2955 | ||
2956 | static int | |
2957 | op_is_new_cast (struct demangle_component *op) | |
2958 | { | |
2959 | const char *code = op->u.s_operator.op->code; | |
2960 | return (code[1] == 'c' | |
2961 | && (code[0] == 's' || code[0] == 'd' | |
2962 | || code[0] == 'c' || code[0] == 'r')); | |
2963 | } | |
2964 | ||
bd6946d1 ILT |
2965 | /* <expression> ::= <(unary) operator-name> <expression> |
2966 | ::= <(binary) operator-name> <expression> <expression> | |
2967 | ::= <(trinary) operator-name> <expression> <expression> <expression> | |
5a3d7e74 | 2968 | ::= cl <expression>+ E |
bd6946d1 ILT |
2969 | ::= st <type> |
2970 | ::= <template-param> | |
2971 | ::= sr <type> <unqualified-name> | |
2972 | ::= sr <type> <unqualified-name> <template-args> | |
2973 | ::= <expr-primary> | |
2974 | */ | |
2975 | ||
5e777af5 | 2976 | static struct demangle_component * |
9486db4f | 2977 | d_expression (struct d_info *di) |
69afa80d | 2978 | { |
bd6946d1 | 2979 | char peek; |
69afa80d | 2980 | |
bd6946d1 ILT |
2981 | peek = d_peek_char (di); |
2982 | if (peek == 'L') | |
2983 | return d_expr_primary (di); | |
2984 | else if (peek == 'T') | |
2985 | return d_template_param (di); | |
2986 | else if (peek == 's' && d_peek_next_char (di) == 'r') | |
69afa80d | 2987 | { |
5e777af5 ILT |
2988 | struct demangle_component *type; |
2989 | struct demangle_component *name; | |
69afa80d | 2990 | |
bd6946d1 | 2991 | d_advance (di, 2); |
5e777af5 | 2992 | type = cplus_demangle_type (di); |
bd6946d1 ILT |
2993 | name = d_unqualified_name (di); |
2994 | if (d_peek_char (di) != 'I') | |
5e777af5 | 2995 | return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type, name); |
bd6946d1 | 2996 | else |
5e777af5 ILT |
2997 | return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type, |
2998 | d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name, | |
bd6946d1 | 2999 | d_template_args (di))); |
5d69ba1f | 3000 | } |
6afcfe0a JM |
3001 | else if (peek == 's' && d_peek_next_char (di) == 'p') |
3002 | { | |
3003 | d_advance (di, 2); | |
3004 | return d_make_comp (di, DEMANGLE_COMPONENT_PACK_EXPANSION, | |
3005 | d_expression (di), NULL); | |
3006 | } | |
448545cb | 3007 | else if (peek == 'f' && d_peek_next_char (di) == 'p') |
5a3d7e74 | 3008 | { |
448545cb JM |
3009 | /* Function parameter used in a late-specified return type. */ |
3010 | int index; | |
5a3d7e74 | 3011 | d_advance (di, 2); |
a517066d JM |
3012 | if (d_peek_char (di) == 'T') |
3013 | { | |
3014 | /* 'this' parameter. */ | |
3015 | d_advance (di, 1); | |
3016 | index = 0; | |
3017 | } | |
3018 | else | |
3019 | { | |
3020 | index = d_compact_number (di) + 1; | |
3021 | if (index == 0) | |
3022 | return NULL; | |
3023 | } | |
448545cb | 3024 | return d_make_function_param (di, index); |
5a3d7e74 | 3025 | } |
f000c6a7 JM |
3026 | else if (IS_DIGIT (peek) |
3027 | || (peek == 'o' && d_peek_next_char (di) == 'n')) | |
38179091 JM |
3028 | { |
3029 | /* We can get an unqualified name as an expression in the case of | |
f000c6a7 JM |
3030 | a dependent function call, i.e. decltype(f(t)). */ |
3031 | struct demangle_component *name; | |
3032 | ||
3033 | if (peek == 'o') | |
3034 | /* operator-function-id, i.e. operator+(t). */ | |
3035 | d_advance (di, 2); | |
3036 | ||
3037 | name = d_unqualified_name (di); | |
38179091 JM |
3038 | if (name == NULL) |
3039 | return NULL; | |
3040 | if (d_peek_char (di) == 'I') | |
3041 | return d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name, | |
3042 | d_template_args (di)); | |
3043 | else | |
3044 | return name; | |
3045 | } | |
4b6aaa99 JM |
3046 | else if ((peek == 'i' || peek == 't') |
3047 | && d_peek_next_char (di) == 'l') | |
3048 | { | |
3049 | /* Brace-enclosed initializer list, untyped or typed. */ | |
3050 | struct demangle_component *type = NULL; | |
3051 | if (peek == 't') | |
3052 | type = cplus_demangle_type (di); | |
3053 | d_advance (di, 2); | |
3054 | return d_make_comp (di, DEMANGLE_COMPONENT_INITIALIZER_LIST, | |
3055 | type, d_exprlist (di, 'E')); | |
3056 | } | |
bd6946d1 | 3057 | else |
69afa80d | 3058 | { |
5e777af5 | 3059 | struct demangle_component *op; |
4b6aaa99 | 3060 | const char *code = NULL; |
bd6946d1 | 3061 | int args; |
69afa80d | 3062 | |
bd6946d1 ILT |
3063 | op = d_operator_name (di); |
3064 | if (op == NULL) | |
3065 | return NULL; | |
69afa80d | 3066 | |
5e777af5 | 3067 | if (op->type == DEMANGLE_COMPONENT_OPERATOR) |
4b6aaa99 JM |
3068 | { |
3069 | code = op->u.s_operator.op->code; | |
3070 | di->expansion += op->u.s_operator.op->len - 2; | |
3071 | if (strcmp (code, "st") == 0) | |
3072 | return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op, | |
3073 | cplus_demangle_type (di)); | |
3074 | } | |
69afa80d | 3075 | |
bd6946d1 ILT |
3076 | switch (op->type) |
3077 | { | |
3078 | default: | |
3079 | return NULL; | |
5e777af5 | 3080 | case DEMANGLE_COMPONENT_OPERATOR: |
bd6946d1 ILT |
3081 | args = op->u.s_operator.op->args; |
3082 | break; | |
5e777af5 | 3083 | case DEMANGLE_COMPONENT_EXTENDED_OPERATOR: |
bd6946d1 ILT |
3084 | args = op->u.s_extended_operator.args; |
3085 | break; | |
5e777af5 | 3086 | case DEMANGLE_COMPONENT_CAST: |
30471e01 | 3087 | args = 1; |
bd6946d1 ILT |
3088 | break; |
3089 | } | |
3090 | ||
3091 | switch (args) | |
3092 | { | |
4b6aaa99 JM |
3093 | case 0: |
3094 | return d_make_comp (di, DEMANGLE_COMPONENT_NULLARY, op, NULL); | |
3095 | ||
bd6946d1 | 3096 | case 1: |
448545cb JM |
3097 | { |
3098 | struct demangle_component *operand; | |
4b6aaa99 JM |
3099 | int suffix = 0; |
3100 | ||
3101 | if (code && (code[0] == 'p' || code[0] == 'm') | |
3102 | && code[1] == code[0]) | |
3103 | /* pp_ and mm_ are the prefix variants. */ | |
3104 | suffix = !d_check_char (di, '_'); | |
3105 | ||
448545cb JM |
3106 | if (op->type == DEMANGLE_COMPONENT_CAST |
3107 | && d_check_char (di, '_')) | |
4b6aaa99 | 3108 | operand = d_exprlist (di, 'E'); |
448545cb JM |
3109 | else |
3110 | operand = d_expression (di); | |
4b6aaa99 JM |
3111 | |
3112 | if (suffix) | |
3113 | /* Indicate the suffix variant for d_print_comp. */ | |
3114 | return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op, | |
3115 | d_make_comp (di, | |
3116 | DEMANGLE_COMPONENT_BINARY_ARGS, | |
3117 | operand, operand)); | |
3118 | else | |
3119 | return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op, | |
3120 | operand); | |
448545cb | 3121 | } |
bd6946d1 ILT |
3122 | case 2: |
3123 | { | |
5e777af5 | 3124 | struct demangle_component *left; |
5a3d7e74 | 3125 | struct demangle_component *right; |
bd6946d1 | 3126 | |
aefa74bd JM |
3127 | if (op_is_new_cast (op)) |
3128 | left = cplus_demangle_type (di); | |
3129 | else | |
3130 | left = d_expression (di); | |
f000c6a7 | 3131 | if (!strcmp (code, "cl")) |
4b6aaa99 | 3132 | right = d_exprlist (di, 'E'); |
f000c6a7 JM |
3133 | else if (!strcmp (code, "dt") || !strcmp (code, "pt")) |
3134 | { | |
3135 | right = d_unqualified_name (di); | |
3136 | if (d_peek_char (di) == 'I') | |
3137 | right = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, | |
3138 | right, d_template_args (di)); | |
3139 | } | |
5a3d7e74 JM |
3140 | else |
3141 | right = d_expression (di); | |
3142 | ||
5e777af5 ILT |
3143 | return d_make_comp (di, DEMANGLE_COMPONENT_BINARY, op, |
3144 | d_make_comp (di, | |
3145 | DEMANGLE_COMPONENT_BINARY_ARGS, | |
5a3d7e74 | 3146 | left, right)); |
bd6946d1 ILT |
3147 | } |
3148 | case 3: | |
3149 | { | |
5e777af5 ILT |
3150 | struct demangle_component *first; |
3151 | struct demangle_component *second; | |
4b6aaa99 | 3152 | struct demangle_component *third; |
bd6946d1 | 3153 | |
4b6aaa99 JM |
3154 | if (!strcmp (code, "qu")) |
3155 | { | |
3156 | /* ?: expression. */ | |
3157 | first = d_expression (di); | |
3158 | second = d_expression (di); | |
3159 | third = d_expression (di); | |
3160 | } | |
3161 | else if (code[0] == 'n') | |
3162 | { | |
3163 | /* new-expression. */ | |
3164 | if (code[1] != 'w' && code[1] != 'a') | |
3165 | return NULL; | |
3166 | first = d_exprlist (di, '_'); | |
3167 | second = cplus_demangle_type (di); | |
3168 | if (d_peek_char (di) == 'E') | |
3169 | { | |
3170 | d_advance (di, 1); | |
3171 | third = NULL; | |
3172 | } | |
3173 | else if (d_peek_char (di) == 'p' | |
3174 | && d_peek_next_char (di) == 'i') | |
3175 | { | |
3176 | /* Parenthesized initializer. */ | |
3177 | d_advance (di, 2); | |
3178 | third = d_exprlist (di, 'E'); | |
3179 | } | |
3180 | else if (d_peek_char (di) == 'i' | |
3181 | && d_peek_next_char (di) == 'l') | |
3182 | /* initializer-list. */ | |
3183 | third = d_expression (di); | |
3184 | else | |
3185 | return NULL; | |
3186 | } | |
3187 | else | |
3188 | return NULL; | |
5e777af5 ILT |
3189 | return d_make_comp (di, DEMANGLE_COMPONENT_TRINARY, op, |
3190 | d_make_comp (di, | |
3191 | DEMANGLE_COMPONENT_TRINARY_ARG1, | |
3192 | first, | |
bd6946d1 | 3193 | d_make_comp (di, |
5e777af5 | 3194 | DEMANGLE_COMPONENT_TRINARY_ARG2, |
4b6aaa99 | 3195 | second, third))); |
bd6946d1 ILT |
3196 | } |
3197 | default: | |
3198 | return NULL; | |
3199 | } | |
69afa80d AS |
3200 | } |
3201 | } | |
3202 | ||
bd6946d1 ILT |
3203 | /* <expr-primary> ::= L <type> <(value) number> E |
3204 | ::= L <type> <(value) float> E | |
3205 | ::= L <mangled-name> E | |
3206 | */ | |
92a16bbe | 3207 | |
5e777af5 | 3208 | static struct demangle_component * |
9486db4f | 3209 | d_expr_primary (struct d_info *di) |
92a16bbe | 3210 | { |
5e777af5 | 3211 | struct demangle_component *ret; |
92a16bbe | 3212 | |
5165f125 | 3213 | if (! d_check_char (di, 'L')) |
bd6946d1 | 3214 | return NULL; |
448545cb JM |
3215 | if (d_peek_char (di) == '_' |
3216 | /* Workaround for G++ bug; see comment in write_template_arg. */ | |
3217 | || d_peek_char (di) == 'Z') | |
5e777af5 | 3218 | ret = cplus_demangle_mangled_name (di, 0); |
bd6946d1 | 3219 | else |
92a16bbe | 3220 | { |
5e777af5 ILT |
3221 | struct demangle_component *type; |
3222 | enum demangle_component_type t; | |
bd6946d1 ILT |
3223 | const char *s; |
3224 | ||
5e777af5 | 3225 | type = cplus_demangle_type (di); |
00a5aa9c ILT |
3226 | if (type == NULL) |
3227 | return NULL; | |
bd6946d1 | 3228 | |
2d6c4025 ILT |
3229 | /* If we have a type we know how to print, we aren't going to |
3230 | print the type name itself. */ | |
5e777af5 | 3231 | if (type->type == DEMANGLE_COMPONENT_BUILTIN_TYPE |
2d6c4025 ILT |
3232 | && type->u.s_builtin.type->print != D_PRINT_DEFAULT) |
3233 | di->expansion -= type->u.s_builtin.type->len; | |
3234 | ||
bd6946d1 ILT |
3235 | /* Rather than try to interpret the literal value, we just |
3236 | collect it as a string. Note that it's possible to have a | |
3237 | floating point literal here. The ABI specifies that the | |
3238 | format of such literals is machine independent. That's fine, | |
3239 | but what's not fine is that versions of g++ up to 3.2 with | |
3240 | -fabi-version=1 used upper case letters in the hex constant, | |
3241 | and dumped out gcc's internal representation. That makes it | |
3242 | hard to tell where the constant ends, and hard to dump the | |
3243 | constant in any readable form anyhow. We don't attempt to | |
3244 | handle these cases. */ | |
3245 | ||
5e777af5 | 3246 | t = DEMANGLE_COMPONENT_LITERAL; |
374caa50 ILT |
3247 | if (d_peek_char (di) == 'n') |
3248 | { | |
5e777af5 | 3249 | t = DEMANGLE_COMPONENT_LITERAL_NEG; |
374caa50 ILT |
3250 | d_advance (di, 1); |
3251 | } | |
bd6946d1 ILT |
3252 | s = d_str (di); |
3253 | while (d_peek_char (di) != 'E') | |
8c7262af ILT |
3254 | { |
3255 | if (d_peek_char (di) == '\0') | |
3256 | return NULL; | |
3257 | d_advance (di, 1); | |
3258 | } | |
374caa50 | 3259 | ret = d_make_comp (di, t, type, d_make_name (di, s, d_str (di) - s)); |
bd6946d1 | 3260 | } |
5165f125 | 3261 | if (! d_check_char (di, 'E')) |
bd6946d1 ILT |
3262 | return NULL; |
3263 | return ret; | |
92a16bbe AS |
3264 | } |
3265 | ||
bd6946d1 ILT |
3266 | /* <local-name> ::= Z <(function) encoding> E <(entity) name> [<discriminator>] |
3267 | ::= Z <(function) encoding> E s [<discriminator>] | |
622aac0b | 3268 | ::= Z <(function) encoding> E d [<parameter> number>] _ <entity name> |
bd6946d1 | 3269 | */ |
92a16bbe | 3270 | |
5e777af5 | 3271 | static struct demangle_component * |
9486db4f | 3272 | d_local_name (struct d_info *di) |
92a16bbe | 3273 | { |
5e777af5 | 3274 | struct demangle_component *function; |
92a16bbe | 3275 | |
5165f125 | 3276 | if (! d_check_char (di, 'Z')) |
bd6946d1 | 3277 | return NULL; |
92a16bbe | 3278 | |
ad07f5e5 | 3279 | function = d_encoding (di, 0); |
92a16bbe | 3280 | |
5165f125 | 3281 | if (! d_check_char (di, 'E')) |
bd6946d1 | 3282 | return NULL; |
92a16bbe | 3283 | |
bd6946d1 | 3284 | if (d_peek_char (di) == 's') |
92a16bbe | 3285 | { |
bd6946d1 ILT |
3286 | d_advance (di, 1); |
3287 | if (! d_discriminator (di)) | |
3288 | return NULL; | |
5e777af5 | 3289 | return d_make_comp (di, DEMANGLE_COMPONENT_LOCAL_NAME, function, |
bd6946d1 ILT |
3290 | d_make_name (di, "string literal", |
3291 | sizeof "string literal" - 1)); | |
92a16bbe | 3292 | } |
bd6946d1 | 3293 | else |
92a16bbe | 3294 | { |
5e777af5 | 3295 | struct demangle_component *name; |
d5f4eddd JM |
3296 | int num = -1; |
3297 | ||
3298 | if (d_peek_char (di) == 'd') | |
3299 | { | |
3300 | /* Default argument scope: d <number> _. */ | |
3301 | d_advance (di, 1); | |
3302 | num = d_compact_number (di); | |
3303 | if (num < 0) | |
3304 | return NULL; | |
3305 | } | |
92a16bbe | 3306 | |
bd6946d1 | 3307 | name = d_name (di); |
d5f4eddd JM |
3308 | if (name) |
3309 | switch (name->type) | |
3310 | { | |
3311 | /* Lambdas and unnamed types have internal discriminators. */ | |
3312 | case DEMANGLE_COMPONENT_LAMBDA: | |
3313 | case DEMANGLE_COMPONENT_UNNAMED_TYPE: | |
3314 | break; | |
3315 | default: | |
3316 | if (! d_discriminator (di)) | |
3317 | return NULL; | |
3318 | } | |
3319 | if (num >= 0) | |
3320 | name = d_make_default_arg (di, num, name); | |
5e777af5 | 3321 | return d_make_comp (di, DEMANGLE_COMPONENT_LOCAL_NAME, function, name); |
92a16bbe | 3322 | } |
92a16bbe AS |
3323 | } |
3324 | ||
bd6946d1 | 3325 | /* <discriminator> ::= _ <(non-negative) number> |
69afa80d | 3326 | |
bd6946d1 ILT |
3327 | We demangle the discriminator, but we don't print it out. FIXME: |
3328 | We should print it out in verbose mode. */ | |
92a16bbe | 3329 | |
bd6946d1 | 3330 | static int |
9486db4f | 3331 | d_discriminator (struct d_info *di) |
bd6946d1 ILT |
3332 | { |
3333 | long discrim; | |
92a16bbe | 3334 | |
bd6946d1 ILT |
3335 | if (d_peek_char (di) != '_') |
3336 | return 1; | |
3337 | d_advance (di, 1); | |
3338 | discrim = d_number (di); | |
3339 | if (discrim < 0) | |
3340 | return 0; | |
3341 | return 1; | |
3342 | } | |
69afa80d | 3343 | |
d5f4eddd JM |
3344 | /* <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _ */ |
3345 | ||
3346 | static struct demangle_component * | |
3347 | d_lambda (struct d_info *di) | |
3348 | { | |
3349 | struct demangle_component *tl; | |
3350 | struct demangle_component *ret; | |
3351 | int num; | |
3352 | ||
3353 | if (! d_check_char (di, 'U')) | |
3354 | return NULL; | |
3355 | if (! d_check_char (di, 'l')) | |
3356 | return NULL; | |
3357 | ||
3358 | tl = d_parmlist (di); | |
3359 | if (tl == NULL) | |
3360 | return NULL; | |
3361 | ||
3362 | if (! d_check_char (di, 'E')) | |
3363 | return NULL; | |
3364 | ||
3365 | num = d_compact_number (di); | |
3366 | if (num < 0) | |
3367 | return NULL; | |
3368 | ||
3369 | ret = d_make_empty (di); | |
3370 | if (ret) | |
3371 | { | |
3372 | ret->type = DEMANGLE_COMPONENT_LAMBDA; | |
3373 | ret->u.s_unary_num.sub = tl; | |
3374 | ret->u.s_unary_num.num = num; | |
3375 | } | |
3376 | ||
3377 | if (! d_add_substitution (di, ret)) | |
3378 | return NULL; | |
3379 | ||
3380 | return ret; | |
3381 | } | |
3382 | ||
3383 | /* <unnamed-type-name> ::= Ut [ <nonnegative number> ] _ */ | |
3384 | ||
3385 | static struct demangle_component * | |
3386 | d_unnamed_type (struct d_info *di) | |
3387 | { | |
3388 | struct demangle_component *ret; | |
3389 | long num; | |
3390 | ||
3391 | if (! d_check_char (di, 'U')) | |
3392 | return NULL; | |
3393 | if (! d_check_char (di, 't')) | |
3394 | return NULL; | |
3395 | ||
3396 | num = d_compact_number (di); | |
3397 | if (num < 0) | |
3398 | return NULL; | |
3399 | ||
3400 | ret = d_make_empty (di); | |
3401 | if (ret) | |
3402 | { | |
3403 | ret->type = DEMANGLE_COMPONENT_UNNAMED_TYPE; | |
3404 | ret->u.s_number.number = num; | |
3405 | } | |
3406 | ||
3407 | if (! d_add_substitution (di, ret)) | |
3408 | return NULL; | |
3409 | ||
3410 | return ret; | |
3411 | } | |
3412 | ||
2d2b02c4 CC |
3413 | /* <clone-suffix> ::= [ . <clone-type-identifier> ] [ . <nonnegative number> ]* |
3414 | */ | |
3415 | ||
3416 | static struct demangle_component * | |
3417 | d_clone_suffix (struct d_info *di, struct demangle_component *encoding) | |
3418 | { | |
3419 | const char *suffix = d_str (di); | |
3420 | const char *pend = suffix; | |
3421 | struct demangle_component *n; | |
3422 | ||
3423 | if (*pend == '.' && (IS_LOWER (pend[1]) || pend[1] == '_')) | |
3424 | { | |
3425 | pend += 2; | |
3426 | while (IS_LOWER (*pend) || *pend == '_') | |
3427 | ++pend; | |
3428 | } | |
3429 | while (*pend == '.' && IS_DIGIT (pend[1])) | |
3430 | { | |
3431 | pend += 2; | |
3432 | while (IS_DIGIT (*pend)) | |
3433 | ++pend; | |
3434 | } | |
3435 | d_advance (di, pend - suffix); | |
3436 | n = d_make_name (di, suffix, pend - suffix); | |
3437 | return d_make_comp (di, DEMANGLE_COMPONENT_CLONE, encoding, n); | |
3438 | } | |
3439 | ||
bd6946d1 | 3440 | /* Add a new substitution. */ |
69afa80d | 3441 | |
bd6946d1 | 3442 | static int |
9486db4f | 3443 | d_add_substitution (struct d_info *di, struct demangle_component *dc) |
69afa80d | 3444 | { |
81dc098b ILT |
3445 | if (dc == NULL) |
3446 | return 0; | |
bd6946d1 ILT |
3447 | if (di->next_sub >= di->num_subs) |
3448 | return 0; | |
3449 | di->subs[di->next_sub] = dc; | |
3450 | ++di->next_sub; | |
3451 | return 1; | |
3452 | } | |
3453 | ||
3454 | /* <substitution> ::= S <seq-id> _ | |
3455 | ::= S_ | |
3456 | ::= St | |
3457 | ::= Sa | |
3458 | ::= Sb | |
3459 | ::= Ss | |
3460 | ::= Si | |
3461 | ::= So | |
3462 | ::= Sd | |
374caa50 ILT |
3463 | |
3464 | If PREFIX is non-zero, then this type is being used as a prefix in | |
3465 | a qualified name. In this case, for the standard substitutions, we | |
3466 | need to check whether we are being used as a prefix for a | |
3467 | constructor or destructor, and return a full template name. | |
3468 | Otherwise we will get something like std::iostream::~iostream() | |
3469 | which does not correspond particularly well to any function which | |
3470 | actually appears in the source. | |
bd6946d1 | 3471 | */ |
69afa80d | 3472 | |
374caa50 ILT |
3473 | static const struct d_standard_sub_info standard_subs[] = |
3474 | { | |
2d6c4025 ILT |
3475 | { 't', NL ("std"), |
3476 | NL ("std"), | |
3477 | NULL, 0 }, | |
3478 | { 'a', NL ("std::allocator"), | |
3479 | NL ("std::allocator"), | |
3480 | NL ("allocator") }, | |
3481 | { 'b', NL ("std::basic_string"), | |
3482 | NL ("std::basic_string"), | |
3483 | NL ("basic_string") }, | |
3484 | { 's', NL ("std::string"), | |
3485 | NL ("std::basic_string<char, std::char_traits<char>, std::allocator<char> >"), | |
3486 | NL ("basic_string") }, | |
3487 | { 'i', NL ("std::istream"), | |
3488 | NL ("std::basic_istream<char, std::char_traits<char> >"), | |
3489 | NL ("basic_istream") }, | |
3490 | { 'o', NL ("std::ostream"), | |
3491 | NL ("std::basic_ostream<char, std::char_traits<char> >"), | |
3492 | NL ("basic_ostream") }, | |
3493 | { 'd', NL ("std::iostream"), | |
3494 | NL ("std::basic_iostream<char, std::char_traits<char> >"), | |
3495 | NL ("basic_iostream") } | |
374caa50 ILT |
3496 | }; |
3497 | ||
5e777af5 | 3498 | static struct demangle_component * |
9486db4f | 3499 | d_substitution (struct d_info *di, int prefix) |
bd6946d1 ILT |
3500 | { |
3501 | char c; | |
69afa80d | 3502 | |
5165f125 | 3503 | if (! d_check_char (di, 'S')) |
bd6946d1 | 3504 | return NULL; |
056400f1 | 3505 | |
bd6946d1 | 3506 | c = d_next_char (di); |
a51753e4 | 3507 | if (c == '_' || IS_DIGIT (c) || IS_UPPER (c)) |
69afa80d | 3508 | { |
eeda7b98 | 3509 | unsigned int id; |
69afa80d | 3510 | |
bd6946d1 ILT |
3511 | id = 0; |
3512 | if (c != '_') | |
69afa80d | 3513 | { |
bd6946d1 | 3514 | do |
69afa80d | 3515 | { |
eeda7b98 ILT |
3516 | unsigned int new_id; |
3517 | ||
bd6946d1 | 3518 | if (IS_DIGIT (c)) |
eeda7b98 | 3519 | new_id = id * 36 + c - '0'; |
a51753e4 | 3520 | else if (IS_UPPER (c)) |
eeda7b98 | 3521 | new_id = id * 36 + c - 'A' + 10; |
bd6946d1 ILT |
3522 | else |
3523 | return NULL; | |
eeda7b98 | 3524 | if (new_id < id) |
53e3e587 | 3525 | return NULL; |
eeda7b98 | 3526 | id = new_id; |
bd6946d1 | 3527 | c = d_next_char (di); |
69afa80d | 3528 | } |
bd6946d1 | 3529 | while (c != '_'); |
69afa80d | 3530 | |
bd6946d1 | 3531 | ++id; |
69afa80d | 3532 | } |
69afa80d | 3533 | |
eeda7b98 | 3534 | if (id >= (unsigned int) di->next_sub) |
bd6946d1 | 3535 | return NULL; |
69afa80d | 3536 | |
2d6c4025 ILT |
3537 | ++di->did_subs; |
3538 | ||
bd6946d1 | 3539 | return di->subs[id]; |
69afa80d | 3540 | } |
bd6946d1 | 3541 | else |
69afa80d | 3542 | { |
374caa50 ILT |
3543 | int verbose; |
3544 | const struct d_standard_sub_info *p; | |
3545 | const struct d_standard_sub_info *pend; | |
3546 | ||
3547 | verbose = (di->options & DMGL_VERBOSE) != 0; | |
3548 | if (! verbose && prefix) | |
7dce2eff | 3549 | { |
374caa50 ILT |
3550 | char peek; |
3551 | ||
3552 | peek = d_peek_char (di); | |
3553 | if (peek == 'C' || peek == 'D') | |
3554 | verbose = 1; | |
69afa80d | 3555 | } |
374caa50 ILT |
3556 | |
3557 | pend = (&standard_subs[0] | |
3558 | + sizeof standard_subs / sizeof standard_subs[0]); | |
3559 | for (p = &standard_subs[0]; p < pend; ++p) | |
3560 | { | |
3561 | if (c == p->code) | |
3562 | { | |
2d6c4025 ILT |
3563 | const char *s; |
3564 | int len; | |
3565 | ||
374caa50 | 3566 | if (p->set_last_name != NULL) |
2d6c4025 ILT |
3567 | di->last_name = d_make_sub (di, p->set_last_name, |
3568 | p->set_last_name_len); | |
374caa50 | 3569 | if (verbose) |
2d6c4025 ILT |
3570 | { |
3571 | s = p->full_expansion; | |
3572 | len = p->full_len; | |
3573 | } | |
374caa50 | 3574 | else |
2d6c4025 ILT |
3575 | { |
3576 | s = p->simple_expansion; | |
3577 | len = p->simple_len; | |
3578 | } | |
3579 | di->expansion += len; | |
3580 | return d_make_sub (di, s, len); | |
374caa50 ILT |
3581 | } |
3582 | } | |
3583 | ||
3584 | return NULL; | |
69afa80d | 3585 | } |
69afa80d AS |
3586 | } |
3587 | ||
456cc5cf | 3588 | /* Initialize a growable string. */ |
69afa80d | 3589 | |
bd6946d1 | 3590 | static void |
456cc5cf | 3591 | d_growable_string_init (struct d_growable_string *dgs, size_t estimate) |
bd6946d1 | 3592 | { |
456cc5cf SB |
3593 | dgs->buf = NULL; |
3594 | dgs->len = 0; | |
3595 | dgs->alc = 0; | |
3596 | dgs->allocation_failure = 0; | |
69afa80d | 3597 | |
456cc5cf SB |
3598 | if (estimate > 0) |
3599 | d_growable_string_resize (dgs, estimate); | |
3600 | } | |
3601 | ||
3602 | /* Grow a growable string to a given size. */ | |
3603 | ||
3604 | static inline void | |
3605 | d_growable_string_resize (struct d_growable_string *dgs, size_t need) | |
3606 | { | |
3607 | size_t newalc; | |
3608 | char *newbuf; | |
3609 | ||
3610 | if (dgs->allocation_failure) | |
81dc098b | 3611 | return; |
0870bfd6 | 3612 | |
456cc5cf SB |
3613 | /* Start allocation at two bytes to avoid any possibility of confusion |
3614 | with the special value of 1 used as a return in *palc to indicate | |
3615 | allocation failures. */ | |
3616 | newalc = dgs->alc > 0 ? dgs->alc : 2; | |
3617 | while (newalc < need) | |
3618 | newalc <<= 1; | |
3619 | ||
3620 | newbuf = (char *) realloc (dgs->buf, newalc); | |
3621 | if (newbuf == NULL) | |
3622 | { | |
3623 | free (dgs->buf); | |
3624 | dgs->buf = NULL; | |
3625 | dgs->len = 0; | |
3626 | dgs->alc = 0; | |
3627 | dgs->allocation_failure = 1; | |
3628 | return; | |
31e0ab1f | 3629 | } |
456cc5cf SB |
3630 | dgs->buf = newbuf; |
3631 | dgs->alc = newalc; | |
bd6946d1 | 3632 | } |
820555e6 | 3633 | |
456cc5cf | 3634 | /* Append a buffer to a growable string. */ |
820555e6 | 3635 | |
456cc5cf SB |
3636 | static inline void |
3637 | d_growable_string_append_buffer (struct d_growable_string *dgs, | |
3638 | const char *s, size_t l) | |
bd6946d1 | 3639 | { |
456cc5cf | 3640 | size_t need; |
820555e6 | 3641 | |
456cc5cf SB |
3642 | need = dgs->len + l + 1; |
3643 | if (need > dgs->alc) | |
3644 | d_growable_string_resize (dgs, need); | |
3645 | ||
3646 | if (dgs->allocation_failure) | |
3647 | return; | |
3648 | ||
3649 | memcpy (dgs->buf + dgs->len, s, l); | |
3650 | dgs->buf[dgs->len + l] = '\0'; | |
3651 | dgs->len += l; | |
69afa80d AS |
3652 | } |
3653 | ||
456cc5cf | 3654 | /* Bridge growable strings to the callback mechanism. */ |
bd6946d1 ILT |
3655 | |
3656 | static void | |
456cc5cf | 3657 | d_growable_string_callback_adapter (const char *s, size_t l, void *opaque) |
69afa80d | 3658 | { |
456cc5cf | 3659 | struct d_growable_string *dgs = (struct d_growable_string*) opaque; |
69afa80d | 3660 | |
456cc5cf | 3661 | d_growable_string_append_buffer (dgs, s, l); |
69afa80d AS |
3662 | } |
3663 | ||
456cc5cf | 3664 | /* Initialize a print information structure. */ |
69afa80d | 3665 | |
bd6946d1 | 3666 | static void |
743a99db JK |
3667 | d_print_init (struct d_print_info *dpi, demangle_callbackref callback, |
3668 | void *opaque) | |
456cc5cf | 3669 | { |
456cc5cf SB |
3670 | dpi->len = 0; |
3671 | dpi->last_char = '\0'; | |
3672 | dpi->templates = NULL; | |
3673 | dpi->modifiers = NULL; | |
f2e6f32e | 3674 | dpi->pack_index = 0; |
9c4d7e52 | 3675 | dpi->flush_count = 0; |
456cc5cf SB |
3676 | |
3677 | dpi->callback = callback; | |
3678 | dpi->opaque = opaque; | |
3679 | ||
3680 | dpi->demangle_failure = 0; | |
3681 | } | |
3682 | ||
3683 | /* Indicate that an error occurred during printing, and test for error. */ | |
3684 | ||
3685 | static inline void | |
9486db4f | 3686 | d_print_error (struct d_print_info *dpi) |
3b60dd8e | 3687 | { |
456cc5cf SB |
3688 | dpi->demangle_failure = 1; |
3689 | } | |
3690 | ||
3691 | static inline int | |
3692 | d_print_saw_error (struct d_print_info *dpi) | |
3693 | { | |
3694 | return dpi->demangle_failure != 0; | |
3695 | } | |
3696 | ||
3697 | /* Flush buffered characters to the callback. */ | |
3698 | ||
3699 | static inline void | |
3700 | d_print_flush (struct d_print_info *dpi) | |
3701 | { | |
3702 | dpi->buf[dpi->len] = '\0'; | |
3703 | dpi->callback (dpi->buf, dpi->len, dpi->opaque); | |
3704 | dpi->len = 0; | |
9c4d7e52 | 3705 | dpi->flush_count++; |
456cc5cf SB |
3706 | } |
3707 | ||
3708 | /* Append characters and buffers for printing. */ | |
3709 | ||
3710 | static inline void | |
3711 | d_append_char (struct d_print_info *dpi, char c) | |
3712 | { | |
3713 | if (dpi->len == sizeof (dpi->buf) - 1) | |
3714 | d_print_flush (dpi); | |
3715 | ||
3716 | dpi->buf[dpi->len++] = c; | |
3717 | dpi->last_char = c; | |
3718 | } | |
3719 | ||
3720 | static inline void | |
3721 | d_append_buffer (struct d_print_info *dpi, const char *s, size_t l) | |
3722 | { | |
3723 | size_t i; | |
3724 | ||
3725 | for (i = 0; i < l; i++) | |
3726 | d_append_char (dpi, s[i]); | |
3727 | } | |
3728 | ||
3729 | static inline void | |
3730 | d_append_string (struct d_print_info *dpi, const char *s) | |
3731 | { | |
3732 | d_append_buffer (dpi, s, strlen (s)); | |
3733 | } | |
3734 | ||
d5f4eddd JM |
3735 | static inline void |
3736 | d_append_num (struct d_print_info *dpi, long l) | |
3737 | { | |
3738 | char buf[25]; | |
3739 | sprintf (buf,"%ld", l); | |
3740 | d_append_string (dpi, buf); | |
3741 | } | |
3742 | ||
456cc5cf SB |
3743 | static inline char |
3744 | d_last_char (struct d_print_info *dpi) | |
3745 | { | |
3746 | return dpi->last_char; | |
3747 | } | |
3748 | ||
3749 | /* Turn components into a human readable string. OPTIONS is the | |
3750 | options bits passed to the demangler. DC is the tree to print. | |
3751 | CALLBACK is a function to call to flush demangled string segments | |
3752 | as they fill the intermediate buffer, and OPAQUE is a generalized | |
3753 | callback argument. On success, this returns 1. On failure, | |
3754 | it returns 0, indicating a bad parse. It does not use heap | |
3755 | memory to build an output string, so cannot encounter memory | |
3756 | allocation failure. */ | |
3757 | ||
3758 | CP_STATIC_IF_GLIBCPP_V3 | |
3759 | int | |
3760 | cplus_demangle_print_callback (int options, | |
3761 | const struct demangle_component *dc, | |
3762 | demangle_callbackref callback, void *opaque) | |
3763 | { | |
3764 | struct d_print_info dpi; | |
3765 | ||
743a99db | 3766 | d_print_init (&dpi, callback, opaque); |
456cc5cf | 3767 | |
743a99db | 3768 | d_print_comp (&dpi, options, dc); |
456cc5cf SB |
3769 | |
3770 | d_print_flush (&dpi); | |
3771 | ||
3772 | return ! d_print_saw_error (&dpi); | |
bd6946d1 | 3773 | } |
3b60dd8e | 3774 | |
2d6c4025 ILT |
3775 | /* Turn components into a human readable string. OPTIONS is the |
3776 | options bits passed to the demangler. DC is the tree to print. | |
3777 | ESTIMATE is a guess at the length of the result. This returns a | |
3778 | string allocated by malloc, or NULL on error. On success, this | |
3779 | sets *PALC to the size of the allocated buffer. On failure, this | |
3780 | sets *PALC to 0 for a bad parse, or to 1 for a memory allocation | |
3781 | failure. */ | |
69afa80d | 3782 | |
5e777af5 ILT |
3783 | CP_STATIC_IF_GLIBCPP_V3 |
3784 | char * | |
9486db4f GDR |
3785 | cplus_demangle_print (int options, const struct demangle_component *dc, |
3786 | int estimate, size_t *palc) | |
bd6946d1 | 3787 | { |
456cc5cf | 3788 | struct d_growable_string dgs; |
69afa80d | 3789 | |
456cc5cf | 3790 | d_growable_string_init (&dgs, estimate); |
69afa80d | 3791 | |
456cc5cf SB |
3792 | if (! cplus_demangle_print_callback (options, dc, |
3793 | d_growable_string_callback_adapter, | |
3794 | &dgs)) | |
69afa80d | 3795 | { |
456cc5cf SB |
3796 | free (dgs.buf); |
3797 | *palc = 0; | |
bd6946d1 | 3798 | return NULL; |
69afa80d | 3799 | } |
69afa80d | 3800 | |
456cc5cf SB |
3801 | *palc = dgs.allocation_failure ? 1 : dgs.alc; |
3802 | return dgs.buf; | |
69afa80d AS |
3803 | } |
3804 | ||
38179091 JM |
3805 | /* Returns the I'th element of the template arglist ARGS, or NULL on |
3806 | failure. */ | |
3807 | ||
3808 | static struct demangle_component * | |
3809 | d_index_template_argument (struct demangle_component *args, int i) | |
3810 | { | |
3811 | struct demangle_component *a; | |
3812 | ||
3813 | for (a = args; | |
3814 | a != NULL; | |
3815 | a = d_right (a)) | |
3816 | { | |
3817 | if (a->type != DEMANGLE_COMPONENT_TEMPLATE_ARGLIST) | |
3818 | return NULL; | |
3819 | if (i <= 0) | |
3820 | break; | |
3821 | --i; | |
3822 | } | |
3823 | if (i != 0 || a == NULL) | |
3824 | return NULL; | |
3825 | ||
3826 | return d_left (a); | |
3827 | } | |
3828 | ||
3829 | /* Returns the template argument from the current context indicated by DC, | |
3830 | which is a DEMANGLE_COMPONENT_TEMPLATE_PARAM, or NULL. */ | |
3831 | ||
3832 | static struct demangle_component * | |
3833 | d_lookup_template_argument (struct d_print_info *dpi, | |
3834 | const struct demangle_component *dc) | |
3835 | { | |
3836 | if (dpi->templates == NULL) | |
3837 | { | |
3838 | d_print_error (dpi); | |
3839 | return NULL; | |
3840 | } | |
3841 | ||
3842 | return d_index_template_argument | |
3843 | (d_right (dpi->templates->template_decl), | |
3844 | dc->u.s_number.number); | |
3845 | } | |
3846 | ||
3847 | /* Returns a template argument pack used in DC (any will do), or NULL. */ | |
3848 | ||
3849 | static struct demangle_component * | |
3850 | d_find_pack (struct d_print_info *dpi, | |
3851 | const struct demangle_component *dc) | |
3852 | { | |
3853 | struct demangle_component *a; | |
3854 | if (dc == NULL) | |
3855 | return NULL; | |
3856 | ||
3857 | switch (dc->type) | |
3858 | { | |
3859 | case DEMANGLE_COMPONENT_TEMPLATE_PARAM: | |
3860 | a = d_lookup_template_argument (dpi, dc); | |
3861 | if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST) | |
3862 | return a; | |
3863 | return NULL; | |
3864 | ||
3865 | case DEMANGLE_COMPONENT_PACK_EXPANSION: | |
3866 | return NULL; | |
3867 | ||
48255616 | 3868 | case DEMANGLE_COMPONENT_LAMBDA: |
38179091 | 3869 | case DEMANGLE_COMPONENT_NAME: |
7dbb85a7 | 3870 | case DEMANGLE_COMPONENT_TAGGED_NAME: |
38179091 JM |
3871 | case DEMANGLE_COMPONENT_OPERATOR: |
3872 | case DEMANGLE_COMPONENT_BUILTIN_TYPE: | |
3873 | case DEMANGLE_COMPONENT_SUB_STD: | |
3874 | case DEMANGLE_COMPONENT_CHARACTER: | |
6afcfe0a | 3875 | case DEMANGLE_COMPONENT_FUNCTION_PARAM: |
d931f693 | 3876 | case DEMANGLE_COMPONENT_UNNAMED_TYPE: |
38179091 JM |
3877 | return NULL; |
3878 | ||
3879 | case DEMANGLE_COMPONENT_EXTENDED_OPERATOR: | |
3880 | return d_find_pack (dpi, dc->u.s_extended_operator.name); | |
3881 | case DEMANGLE_COMPONENT_CTOR: | |
3882 | return d_find_pack (dpi, dc->u.s_ctor.name); | |
3883 | case DEMANGLE_COMPONENT_DTOR: | |
3884 | return d_find_pack (dpi, dc->u.s_dtor.name); | |
3885 | ||
3886 | default: | |
3887 | a = d_find_pack (dpi, d_left (dc)); | |
3888 | if (a) | |
3889 | return a; | |
3890 | return d_find_pack (dpi, d_right (dc)); | |
3891 | } | |
3892 | } | |
3893 | ||
3894 | /* Returns the length of the template argument pack DC. */ | |
3895 | ||
3896 | static int | |
3897 | d_pack_length (const struct demangle_component *dc) | |
3898 | { | |
3899 | int count = 0; | |
3900 | while (dc && dc->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST | |
3901 | && d_left (dc) != NULL) | |
3902 | { | |
3903 | ++count; | |
3904 | dc = d_right (dc); | |
3905 | } | |
3906 | return count; | |
3907 | } | |
3908 | ||
3909 | /* DC is a component of a mangled expression. Print it, wrapped in parens | |
3910 | if needed. */ | |
3911 | ||
3912 | static void | |
743a99db | 3913 | d_print_subexpr (struct d_print_info *dpi, int options, |
38179091 JM |
3914 | const struct demangle_component *dc) |
3915 | { | |
3916 | int simple = 0; | |
6afcfe0a | 3917 | if (dc->type == DEMANGLE_COMPONENT_NAME |
4b6aaa99 JM |
3918 | || dc->type == DEMANGLE_COMPONENT_QUAL_NAME |
3919 | || dc->type == DEMANGLE_COMPONENT_INITIALIZER_LIST | |
6afcfe0a | 3920 | || dc->type == DEMANGLE_COMPONENT_FUNCTION_PARAM) |
38179091 JM |
3921 | simple = 1; |
3922 | if (!simple) | |
3923 | d_append_char (dpi, '('); | |
743a99db | 3924 | d_print_comp (dpi, options, dc); |
38179091 JM |
3925 | if (!simple) |
3926 | d_append_char (dpi, ')'); | |
3927 | } | |
3928 | ||
bd6946d1 | 3929 | /* Subroutine to handle components. */ |
69afa80d | 3930 | |
bd6946d1 | 3931 | static void |
743a99db | 3932 | d_print_comp (struct d_print_info *dpi, int options, |
9486db4f | 3933 | const struct demangle_component *dc) |
69afa80d | 3934 | { |
dd70e080 JM |
3935 | /* Magic variable to let reference smashing skip over the next modifier |
3936 | without needing to modify *dc. */ | |
3937 | const struct demangle_component *mod_inner = NULL; | |
3938 | ||
bd6946d1 | 3939 | if (dc == NULL) |
69afa80d | 3940 | { |
bd6946d1 ILT |
3941 | d_print_error (dpi); |
3942 | return; | |
69afa80d | 3943 | } |
bd6946d1 ILT |
3944 | if (d_print_saw_error (dpi)) |
3945 | return; | |
69afa80d | 3946 | |
bd6946d1 | 3947 | switch (dc->type) |
69afa80d | 3948 | { |
5e777af5 | 3949 | case DEMANGLE_COMPONENT_NAME: |
743a99db | 3950 | if ((options & DMGL_JAVA) == 0) |
2d6c4025 ILT |
3951 | d_append_buffer (dpi, dc->u.s_name.s, dc->u.s_name.len); |
3952 | else | |
3953 | d_print_java_identifier (dpi, dc->u.s_name.s, dc->u.s_name.len); | |
bd6946d1 | 3954 | return; |
69afa80d | 3955 | |
7dbb85a7 JM |
3956 | case DEMANGLE_COMPONENT_TAGGED_NAME: |
3957 | d_print_comp (dpi, options, d_left (dc)); | |
3958 | d_append_string (dpi, "[abi:"); | |
3959 | d_print_comp (dpi, options, d_right (dc)); | |
3960 | d_append_char (dpi, ']'); | |
3961 | return; | |
3962 | ||
5e777af5 ILT |
3963 | case DEMANGLE_COMPONENT_QUAL_NAME: |
3964 | case DEMANGLE_COMPONENT_LOCAL_NAME: | |
743a99db JK |
3965 | d_print_comp (dpi, options, d_left (dc)); |
3966 | if ((options & DMGL_JAVA) == 0) | |
456cc5cf | 3967 | d_append_string (dpi, "::"); |
2d6c4025 ILT |
3968 | else |
3969 | d_append_char (dpi, '.'); | |
622aac0b JM |
3970 | { |
3971 | struct demangle_component *local_name = d_right (dc); | |
3972 | if (local_name->type == DEMANGLE_COMPONENT_DEFAULT_ARG) | |
3973 | { | |
3974 | d_append_string (dpi, "{default arg#"); | |
3975 | d_append_num (dpi, local_name->u.s_unary_num.num + 1); | |
3976 | d_append_string (dpi, "}::"); | |
3977 | local_name = local_name->u.s_unary_num.sub; | |
3978 | } | |
3979 | d_print_comp (dpi, options, local_name); | |
3980 | } | |
bd6946d1 | 3981 | return; |
69afa80d | 3982 | |
5e777af5 | 3983 | case DEMANGLE_COMPONENT_TYPED_NAME: |
bd6946d1 | 3984 | { |
a51753e4 | 3985 | struct d_print_mod *hold_modifiers; |
5e777af5 | 3986 | struct demangle_component *typed_name; |
a51753e4 ILT |
3987 | struct d_print_mod adpm[4]; |
3988 | unsigned int i; | |
bd6946d1 ILT |
3989 | struct d_print_template dpt; |
3990 | ||
3991 | /* Pass the name down to the type so that it can be printed in | |
a51753e4 ILT |
3992 | the right place for the type. We also have to pass down |
3993 | any CV-qualifiers, which apply to the this parameter. */ | |
3994 | hold_modifiers = dpi->modifiers; | |
448545cb | 3995 | dpi->modifiers = 0; |
a51753e4 | 3996 | i = 0; |
bd6946d1 | 3997 | typed_name = d_left (dc); |
a51753e4 ILT |
3998 | while (typed_name != NULL) |
3999 | { | |
4000 | if (i >= sizeof adpm / sizeof adpm[0]) | |
4001 | { | |
4002 | d_print_error (dpi); | |
4003 | return; | |
4004 | } | |
bd6946d1 | 4005 | |
a51753e4 ILT |
4006 | adpm[i].next = dpi->modifiers; |
4007 | dpi->modifiers = &adpm[i]; | |
4008 | adpm[i].mod = typed_name; | |
4009 | adpm[i].printed = 0; | |
4010 | adpm[i].templates = dpi->templates; | |
4011 | ++i; | |
4012 | ||
5e777af5 ILT |
4013 | if (typed_name->type != DEMANGLE_COMPONENT_RESTRICT_THIS |
4014 | && typed_name->type != DEMANGLE_COMPONENT_VOLATILE_THIS | |
9eb85f27 JM |
4015 | && typed_name->type != DEMANGLE_COMPONENT_CONST_THIS |
4016 | && typed_name->type != DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS | |
4017 | && typed_name->type != DEMANGLE_COMPONENT_REFERENCE_THIS) | |
a51753e4 ILT |
4018 | break; |
4019 | ||
4020 | typed_name = d_left (typed_name); | |
4021 | } | |
bd6946d1 | 4022 | |
ac847e32 MS |
4023 | if (typed_name == NULL) |
4024 | { | |
4025 | d_print_error (dpi); | |
4026 | return; | |
4027 | } | |
4028 | ||
bd6946d1 ILT |
4029 | /* If typed_name is a template, then it applies to the |
4030 | function type as well. */ | |
5e777af5 | 4031 | if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE) |
bd6946d1 ILT |
4032 | { |
4033 | dpt.next = dpi->templates; | |
4034 | dpi->templates = &dpt; | |
d7cf8390 | 4035 | dpt.template_decl = typed_name; |
bd6946d1 | 4036 | } |
69afa80d | 4037 | |
5e777af5 ILT |
4038 | /* If typed_name is a DEMANGLE_COMPONENT_LOCAL_NAME, then |
4039 | there may be CV-qualifiers on its right argument which | |
4040 | really apply here; this happens when parsing a class which | |
4041 | is local to a function. */ | |
4042 | if (typed_name->type == DEMANGLE_COMPONENT_LOCAL_NAME) | |
a91d1af0 | 4043 | { |
5e777af5 | 4044 | struct demangle_component *local_name; |
a91d1af0 ILT |
4045 | |
4046 | local_name = d_right (typed_name); | |
d5f4eddd JM |
4047 | if (local_name->type == DEMANGLE_COMPONENT_DEFAULT_ARG) |
4048 | local_name = local_name->u.s_unary_num.sub; | |
5e777af5 ILT |
4049 | while (local_name->type == DEMANGLE_COMPONENT_RESTRICT_THIS |
4050 | || local_name->type == DEMANGLE_COMPONENT_VOLATILE_THIS | |
9eb85f27 JM |
4051 | || local_name->type == DEMANGLE_COMPONENT_CONST_THIS |
4052 | || local_name->type == DEMANGLE_COMPONENT_REFERENCE_THIS | |
4053 | || (local_name->type | |
4054 | == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)) | |
a91d1af0 ILT |
4055 | { |
4056 | if (i >= sizeof adpm / sizeof adpm[0]) | |
4057 | { | |
4058 | d_print_error (dpi); | |
4059 | return; | |
4060 | } | |
4061 | ||
4062 | adpm[i] = adpm[i - 1]; | |
4063 | adpm[i].next = &adpm[i - 1]; | |
4064 | dpi->modifiers = &adpm[i]; | |
4065 | ||
4066 | adpm[i - 1].mod = local_name; | |
4067 | adpm[i - 1].printed = 0; | |
4068 | adpm[i - 1].templates = dpi->templates; | |
4069 | ++i; | |
4070 | ||
4071 | local_name = d_left (local_name); | |
4072 | } | |
4073 | } | |
4074 | ||
743a99db | 4075 | d_print_comp (dpi, options, d_right (dc)); |
1056d228 | 4076 | |
5e777af5 | 4077 | if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE) |
bd6946d1 | 4078 | dpi->templates = dpt.next; |
69afa80d | 4079 | |
a51753e4 | 4080 | /* If the modifiers didn't get printed by the type, print them |
bd6946d1 | 4081 | now. */ |
a51753e4 | 4082 | while (i > 0) |
bd6946d1 | 4083 | { |
a51753e4 ILT |
4084 | --i; |
4085 | if (! adpm[i].printed) | |
4086 | { | |
4087 | d_append_char (dpi, ' '); | |
743a99db | 4088 | d_print_mod (dpi, options, adpm[i].mod); |
a51753e4 | 4089 | } |
bd6946d1 | 4090 | } |
69afa80d | 4091 | |
a51753e4 | 4092 | dpi->modifiers = hold_modifiers; |
69afa80d | 4093 | |
bd6946d1 ILT |
4094 | return; |
4095 | } | |
69afa80d | 4096 | |
5e777af5 | 4097 | case DEMANGLE_COMPONENT_TEMPLATE: |
81dc098b ILT |
4098 | { |
4099 | struct d_print_mod *hold_dpm; | |
456cc5cf | 4100 | struct demangle_component *dcl; |
81dc098b ILT |
4101 | |
4102 | /* Don't push modifiers into a template definition. Doing so | |
4103 | could give the wrong definition for a template argument. | |
4104 | Instead, treat the template essentially as a name. */ | |
4105 | ||
4106 | hold_dpm = dpi->modifiers; | |
4107 | dpi->modifiers = NULL; | |
4108 | ||
456cc5cf SB |
4109 | dcl = d_left (dc); |
4110 | ||
743a99db | 4111 | if ((options & DMGL_JAVA) != 0 |
456cc5cf SB |
4112 | && dcl->type == DEMANGLE_COMPONENT_NAME |
4113 | && dcl->u.s_name.len == 6 | |
4114 | && strncmp (dcl->u.s_name.s, "JArray", 6) == 0) | |
4115 | { | |
4116 | /* Special-case Java arrays, so that JArray<TYPE> appears | |
4117 | instead as TYPE[]. */ | |
4118 | ||
743a99db | 4119 | d_print_comp (dpi, options, d_right (dc)); |
456cc5cf SB |
4120 | d_append_string (dpi, "[]"); |
4121 | } | |
4122 | else | |
4123 | { | |
743a99db | 4124 | d_print_comp (dpi, options, dcl); |
456cc5cf SB |
4125 | if (d_last_char (dpi) == '<') |
4126 | d_append_char (dpi, ' '); | |
4127 | d_append_char (dpi, '<'); | |
743a99db | 4128 | d_print_comp (dpi, options, d_right (dc)); |
456cc5cf SB |
4129 | /* Avoid generating two consecutive '>' characters, to avoid |
4130 | the C++ syntactic ambiguity. */ | |
4131 | if (d_last_char (dpi) == '>') | |
4132 | d_append_char (dpi, ' '); | |
4133 | d_append_char (dpi, '>'); | |
4134 | } | |
81dc098b ILT |
4135 | |
4136 | dpi->modifiers = hold_dpm; | |
4137 | ||
4138 | return; | |
4139 | } | |
bd6946d1 | 4140 | |
5e777af5 | 4141 | case DEMANGLE_COMPONENT_TEMPLATE_PARAM: |
bd6946d1 | 4142 | { |
bd6946d1 | 4143 | struct d_print_template *hold_dpt; |
38179091 | 4144 | struct demangle_component *a = d_lookup_template_argument (dpi, dc); |
69afa80d | 4145 | |
38179091 JM |
4146 | if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST) |
4147 | a = d_index_template_argument (a, dpi->pack_index); | |
4148 | ||
4149 | if (a == NULL) | |
bd6946d1 ILT |
4150 | { |
4151 | d_print_error (dpi); | |
4152 | return; | |
4153 | } | |
0870bfd6 | 4154 | |
bd6946d1 ILT |
4155 | /* While processing this parameter, we need to pop the list of |
4156 | templates. This is because the template parameter may | |
4157 | itself be a reference to a parameter of an outer | |
4158 | template. */ | |
0870bfd6 | 4159 | |
bd6946d1 ILT |
4160 | hold_dpt = dpi->templates; |
4161 | dpi->templates = hold_dpt->next; | |
69afa80d | 4162 | |
743a99db | 4163 | d_print_comp (dpi, options, a); |
051664b0 | 4164 | |
bd6946d1 | 4165 | dpi->templates = hold_dpt; |
0870bfd6 | 4166 | |
bd6946d1 ILT |
4167 | return; |
4168 | } | |
69afa80d | 4169 | |
5e777af5 | 4170 | case DEMANGLE_COMPONENT_CTOR: |
743a99db | 4171 | d_print_comp (dpi, options, dc->u.s_ctor.name); |
bd6946d1 ILT |
4172 | return; |
4173 | ||
5e777af5 | 4174 | case DEMANGLE_COMPONENT_DTOR: |
bd6946d1 | 4175 | d_append_char (dpi, '~'); |
743a99db | 4176 | d_print_comp (dpi, options, dc->u.s_dtor.name); |
bd6946d1 ILT |
4177 | return; |
4178 | ||
5e777af5 | 4179 | case DEMANGLE_COMPONENT_VTABLE: |
456cc5cf | 4180 | d_append_string (dpi, "vtable for "); |
743a99db | 4181 | d_print_comp (dpi, options, d_left (dc)); |
bd6946d1 ILT |
4182 | return; |
4183 | ||
5e777af5 | 4184 | case DEMANGLE_COMPONENT_VTT: |
456cc5cf | 4185 | d_append_string (dpi, "VTT for "); |
743a99db | 4186 | d_print_comp (dpi, options, d_left (dc)); |
bd6946d1 ILT |
4187 | return; |
4188 | ||
5e777af5 | 4189 | case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE: |
456cc5cf | 4190 | d_append_string (dpi, "construction vtable for "); |
743a99db | 4191 | d_print_comp (dpi, options, d_left (dc)); |
456cc5cf | 4192 | d_append_string (dpi, "-in-"); |
743a99db | 4193 | d_print_comp (dpi, options, d_right (dc)); |
bd6946d1 ILT |
4194 | return; |
4195 | ||
5e777af5 | 4196 | case DEMANGLE_COMPONENT_TYPEINFO: |
456cc5cf | 4197 | d_append_string (dpi, "typeinfo for "); |
743a99db | 4198 | d_print_comp (dpi, options, d_left (dc)); |
bd6946d1 ILT |
4199 | return; |
4200 | ||
5e777af5 | 4201 | case DEMANGLE_COMPONENT_TYPEINFO_NAME: |
456cc5cf | 4202 | d_append_string (dpi, "typeinfo name for "); |
743a99db | 4203 | d_print_comp (dpi, options, d_left (dc)); |
bd6946d1 ILT |
4204 | return; |
4205 | ||
5e777af5 | 4206 | case DEMANGLE_COMPONENT_TYPEINFO_FN: |
456cc5cf | 4207 | d_append_string (dpi, "typeinfo fn for "); |
743a99db | 4208 | d_print_comp (dpi, options, d_left (dc)); |
bd6946d1 ILT |
4209 | return; |
4210 | ||
5e777af5 | 4211 | case DEMANGLE_COMPONENT_THUNK: |
456cc5cf | 4212 | d_append_string (dpi, "non-virtual thunk to "); |
743a99db | 4213 | d_print_comp (dpi, options, d_left (dc)); |
bd6946d1 ILT |
4214 | return; |
4215 | ||
5e777af5 | 4216 | case DEMANGLE_COMPONENT_VIRTUAL_THUNK: |
456cc5cf | 4217 | d_append_string (dpi, "virtual thunk to "); |
743a99db | 4218 | d_print_comp (dpi, options, d_left (dc)); |
bd6946d1 ILT |
4219 | return; |
4220 | ||
5e777af5 | 4221 | case DEMANGLE_COMPONENT_COVARIANT_THUNK: |
456cc5cf | 4222 | d_append_string (dpi, "covariant return thunk to "); |
743a99db | 4223 | d_print_comp (dpi, options, d_left (dc)); |
bd6946d1 ILT |
4224 | return; |
4225 | ||
5e777af5 | 4226 | case DEMANGLE_COMPONENT_JAVA_CLASS: |
456cc5cf | 4227 | d_append_string (dpi, "java Class for "); |
743a99db | 4228 | d_print_comp (dpi, options, d_left (dc)); |
bd6946d1 ILT |
4229 | return; |
4230 | ||
5e777af5 | 4231 | case DEMANGLE_COMPONENT_GUARD: |
456cc5cf | 4232 | d_append_string (dpi, "guard variable for "); |
743a99db | 4233 | d_print_comp (dpi, options, d_left (dc)); |
bd6946d1 ILT |
4234 | return; |
4235 | ||
7c424acd JM |
4236 | case DEMANGLE_COMPONENT_TLS_INIT: |
4237 | d_append_string (dpi, "TLS init function for "); | |
4238 | d_print_comp (dpi, options, d_left (dc)); | |
4239 | return; | |
4240 | ||
4241 | case DEMANGLE_COMPONENT_TLS_WRAPPER: | |
4242 | d_append_string (dpi, "TLS wrapper function for "); | |
4243 | d_print_comp (dpi, options, d_left (dc)); | |
4244 | return; | |
4245 | ||
5e777af5 | 4246 | case DEMANGLE_COMPONENT_REFTEMP: |
b25dd954 JM |
4247 | d_append_string (dpi, "reference temporary #"); |
4248 | d_print_comp (dpi, options, d_right (dc)); | |
4249 | d_append_string (dpi, " for "); | |
743a99db | 4250 | d_print_comp (dpi, options, d_left (dc)); |
bd6946d1 ILT |
4251 | return; |
4252 | ||
15da2806 | 4253 | case DEMANGLE_COMPONENT_HIDDEN_ALIAS: |
456cc5cf | 4254 | d_append_string (dpi, "hidden alias for "); |
743a99db | 4255 | d_print_comp (dpi, options, d_left (dc)); |
15da2806 RH |
4256 | return; |
4257 | ||
0a35513e AH |
4258 | case DEMANGLE_COMPONENT_TRANSACTION_CLONE: |
4259 | d_append_string (dpi, "transaction clone for "); | |
4260 | d_print_comp (dpi, options, d_left (dc)); | |
4261 | return; | |
4262 | ||
4263 | case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE: | |
4264 | d_append_string (dpi, "non-transaction clone for "); | |
4265 | d_print_comp (dpi, options, d_left (dc)); | |
4266 | return; | |
4267 | ||
5e777af5 | 4268 | case DEMANGLE_COMPONENT_SUB_STD: |
2d6c4025 | 4269 | d_append_buffer (dpi, dc->u.s_string.string, dc->u.s_string.len); |
bd6946d1 ILT |
4270 | return; |
4271 | ||
5e777af5 ILT |
4272 | case DEMANGLE_COMPONENT_RESTRICT: |
4273 | case DEMANGLE_COMPONENT_VOLATILE: | |
4274 | case DEMANGLE_COMPONENT_CONST: | |
80a19ac8 ILT |
4275 | { |
4276 | struct d_print_mod *pdpm; | |
4277 | ||
4278 | /* When printing arrays, it's possible to have cases where the | |
4279 | same CV-qualifier gets pushed on the stack multiple times. | |
4280 | We only need to print it once. */ | |
4281 | ||
4282 | for (pdpm = dpi->modifiers; pdpm != NULL; pdpm = pdpm->next) | |
4283 | { | |
4284 | if (! pdpm->printed) | |
4285 | { | |
4286 | if (pdpm->mod->type != DEMANGLE_COMPONENT_RESTRICT | |
4287 | && pdpm->mod->type != DEMANGLE_COMPONENT_VOLATILE | |
4288 | && pdpm->mod->type != DEMANGLE_COMPONENT_CONST) | |
4289 | break; | |
4290 | if (pdpm->mod->type == dc->type) | |
4291 | { | |
743a99db | 4292 | d_print_comp (dpi, options, d_left (dc)); |
80a19ac8 ILT |
4293 | return; |
4294 | } | |
4295 | } | |
4296 | } | |
4297 | } | |
dd70e080 JM |
4298 | goto modifier; |
4299 | ||
4300 | case DEMANGLE_COMPONENT_REFERENCE: | |
4301 | case DEMANGLE_COMPONENT_RVALUE_REFERENCE: | |
4302 | { | |
4303 | /* Handle reference smashing: & + && = &. */ | |
4304 | const struct demangle_component *sub = d_left (dc); | |
4305 | if (sub->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM) | |
4306 | { | |
4307 | struct demangle_component *a = d_lookup_template_argument (dpi, sub); | |
4308 | if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST) | |
4309 | a = d_index_template_argument (a, dpi->pack_index); | |
f2e6f32e ILT |
4310 | |
4311 | if (a == NULL) | |
4312 | { | |
4313 | d_print_error (dpi); | |
4314 | return; | |
4315 | } | |
4316 | ||
dd70e080 JM |
4317 | sub = a; |
4318 | } | |
4319 | ||
4320 | if (sub->type == DEMANGLE_COMPONENT_REFERENCE | |
4321 | || sub->type == dc->type) | |
4322 | dc = sub; | |
4323 | else if (sub->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE) | |
4324 | mod_inner = d_left (sub); | |
4325 | } | |
80a19ac8 | 4326 | /* Fall through. */ |
dd70e080 | 4327 | |
5e777af5 ILT |
4328 | case DEMANGLE_COMPONENT_RESTRICT_THIS: |
4329 | case DEMANGLE_COMPONENT_VOLATILE_THIS: | |
4330 | case DEMANGLE_COMPONENT_CONST_THIS: | |
9eb85f27 JM |
4331 | case DEMANGLE_COMPONENT_REFERENCE_THIS: |
4332 | case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: | |
5e777af5 ILT |
4333 | case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: |
4334 | case DEMANGLE_COMPONENT_POINTER: | |
5e777af5 ILT |
4335 | case DEMANGLE_COMPONENT_COMPLEX: |
4336 | case DEMANGLE_COMPONENT_IMAGINARY: | |
dd70e080 | 4337 | modifier: |
bd6946d1 ILT |
4338 | { |
4339 | /* We keep a list of modifiers on the stack. */ | |
4340 | struct d_print_mod dpm; | |
69afa80d | 4341 | |
bd6946d1 ILT |
4342 | dpm.next = dpi->modifiers; |
4343 | dpi->modifiers = &dpm; | |
4344 | dpm.mod = dc; | |
4345 | dpm.printed = 0; | |
81dc098b | 4346 | dpm.templates = dpi->templates; |
69afa80d | 4347 | |
dd70e080 JM |
4348 | if (!mod_inner) |
4349 | mod_inner = d_left (dc); | |
4350 | ||
4351 | d_print_comp (dpi, options, mod_inner); | |
0870bfd6 | 4352 | |
bd6946d1 ILT |
4353 | /* If the modifier didn't get printed by the type, print it |
4354 | now. */ | |
4355 | if (! dpm.printed) | |
743a99db | 4356 | d_print_mod (dpi, options, dc); |
69afa80d | 4357 | |
bd6946d1 | 4358 | dpi->modifiers = dpm.next; |
69afa80d | 4359 | |
bd6946d1 ILT |
4360 | return; |
4361 | } | |
69afa80d | 4362 | |
5e777af5 | 4363 | case DEMANGLE_COMPONENT_BUILTIN_TYPE: |
743a99db | 4364 | if ((options & DMGL_JAVA) == 0) |
2d6c4025 ILT |
4365 | d_append_buffer (dpi, dc->u.s_builtin.type->name, |
4366 | dc->u.s_builtin.type->len); | |
bd6946d1 | 4367 | else |
2d6c4025 ILT |
4368 | d_append_buffer (dpi, dc->u.s_builtin.type->java_name, |
4369 | dc->u.s_builtin.type->java_len); | |
bd6946d1 | 4370 | return; |
69afa80d | 4371 | |
5e777af5 | 4372 | case DEMANGLE_COMPONENT_VENDOR_TYPE: |
743a99db | 4373 | d_print_comp (dpi, options, d_left (dc)); |
bd6946d1 | 4374 | return; |
69afa80d | 4375 | |
5e777af5 | 4376 | case DEMANGLE_COMPONENT_FUNCTION_TYPE: |
bd6946d1 | 4377 | { |
743a99db | 4378 | if ((options & DMGL_RET_POSTFIX) != 0) |
f019462c JK |
4379 | d_print_function_type (dpi, |
4380 | options & ~(DMGL_RET_POSTFIX | DMGL_RET_DROP), | |
4381 | dc, dpi->modifiers); | |
92aed1cb TL |
4382 | |
4383 | /* Print return type if present */ | |
5fe8e1e9 JK |
4384 | if (d_left (dc) != NULL && (options & DMGL_RET_POSTFIX) != 0) |
4385 | d_print_comp (dpi, options & ~(DMGL_RET_POSTFIX | DMGL_RET_DROP), | |
4386 | d_left (dc)); | |
4387 | else if (d_left (dc) != NULL && (options & DMGL_RET_DROP) == 0) | |
bd6946d1 ILT |
4388 | { |
4389 | struct d_print_mod dpm; | |
69afa80d | 4390 | |
bd6946d1 ILT |
4391 | /* We must pass this type down as a modifier in order to |
4392 | print it in the right location. */ | |
bd6946d1 ILT |
4393 | dpm.next = dpi->modifiers; |
4394 | dpi->modifiers = &dpm; | |
4395 | dpm.mod = dc; | |
4396 | dpm.printed = 0; | |
81dc098b | 4397 | dpm.templates = dpi->templates; |
69afa80d | 4398 | |
f019462c JK |
4399 | d_print_comp (dpi, options & ~(DMGL_RET_POSTFIX | DMGL_RET_DROP), |
4400 | d_left (dc)); | |
69afa80d | 4401 | |
bd6946d1 | 4402 | dpi->modifiers = dpm.next; |
69afa80d | 4403 | |
bd6946d1 ILT |
4404 | if (dpm.printed) |
4405 | return; | |
69afa80d | 4406 | |
92aed1cb TL |
4407 | /* In standard prefix notation, there is a space between the |
4408 | return type and the function signature. */ | |
743a99db | 4409 | if ((options & DMGL_RET_POSTFIX) == 0) |
92aed1cb | 4410 | d_append_char (dpi, ' '); |
bd6946d1 | 4411 | } |
69afa80d | 4412 | |
743a99db | 4413 | if ((options & DMGL_RET_POSTFIX) == 0) |
f019462c JK |
4414 | d_print_function_type (dpi, |
4415 | options & ~(DMGL_RET_POSTFIX | DMGL_RET_DROP), | |
4416 | dc, dpi->modifiers); | |
051664b0 | 4417 | |
bd6946d1 ILT |
4418 | return; |
4419 | } | |
69afa80d | 4420 | |
5e777af5 | 4421 | case DEMANGLE_COMPONENT_ARRAY_TYPE: |
bd6946d1 | 4422 | { |
80a19ac8 ILT |
4423 | struct d_print_mod *hold_modifiers; |
4424 | struct d_print_mod adpm[4]; | |
4425 | unsigned int i; | |
4426 | struct d_print_mod *pdpm; | |
69afa80d | 4427 | |
bd6946d1 | 4428 | /* We must pass this type down as a modifier in order to print |
80a19ac8 ILT |
4429 | multi-dimensional arrays correctly. If the array itself is |
4430 | CV-qualified, we act as though the element type were | |
4431 | CV-qualified. We do this by copying the modifiers down | |
4432 | rather than fiddling pointers, so that we don't wind up | |
4433 | with a d_print_mod higher on the stack pointing into our | |
4434 | stack frame after we return. */ | |
051664b0 | 4435 | |
80a19ac8 ILT |
4436 | hold_modifiers = dpi->modifiers; |
4437 | ||
4438 | adpm[0].next = hold_modifiers; | |
4439 | dpi->modifiers = &adpm[0]; | |
4440 | adpm[0].mod = dc; | |
4441 | adpm[0].printed = 0; | |
4442 | adpm[0].templates = dpi->templates; | |
4443 | ||
4444 | i = 1; | |
4445 | pdpm = hold_modifiers; | |
4446 | while (pdpm != NULL | |
4447 | && (pdpm->mod->type == DEMANGLE_COMPONENT_RESTRICT | |
4448 | || pdpm->mod->type == DEMANGLE_COMPONENT_VOLATILE | |
4449 | || pdpm->mod->type == DEMANGLE_COMPONENT_CONST)) | |
4450 | { | |
4451 | if (! pdpm->printed) | |
4452 | { | |
4453 | if (i >= sizeof adpm / sizeof adpm[0]) | |
4454 | { | |
4455 | d_print_error (dpi); | |
4456 | return; | |
4457 | } | |
4458 | ||
4459 | adpm[i] = *pdpm; | |
4460 | adpm[i].next = dpi->modifiers; | |
4461 | dpi->modifiers = &adpm[i]; | |
4462 | pdpm->printed = 1; | |
4463 | ++i; | |
4464 | } | |
4465 | ||
4466 | pdpm = pdpm->next; | |
4467 | } | |
69afa80d | 4468 | |
743a99db | 4469 | d_print_comp (dpi, options, d_right (dc)); |
69afa80d | 4470 | |
80a19ac8 | 4471 | dpi->modifiers = hold_modifiers; |
69afa80d | 4472 | |
80a19ac8 | 4473 | if (adpm[0].printed) |
bd6946d1 | 4474 | return; |
69afa80d | 4475 | |
80a19ac8 ILT |
4476 | while (i > 1) |
4477 | { | |
4478 | --i; | |
743a99db | 4479 | d_print_mod (dpi, options, adpm[i].mod); |
80a19ac8 ILT |
4480 | } |
4481 | ||
743a99db | 4482 | d_print_array_type (dpi, options, dc, dpi->modifiers); |
69afa80d | 4483 | |
bd6946d1 ILT |
4484 | return; |
4485 | } | |
69afa80d | 4486 | |
5e777af5 | 4487 | case DEMANGLE_COMPONENT_PTRMEM_TYPE: |
abfe01ce | 4488 | case DEMANGLE_COMPONENT_VECTOR_TYPE: |
bd6946d1 | 4489 | { |
bd6946d1 ILT |
4490 | struct d_print_mod dpm; |
4491 | ||
bd6946d1 ILT |
4492 | dpm.next = dpi->modifiers; |
4493 | dpi->modifiers = &dpm; | |
4494 | dpm.mod = dc; | |
4495 | dpm.printed = 0; | |
81dc098b | 4496 | dpm.templates = dpi->templates; |
bd6946d1 | 4497 | |
743a99db | 4498 | d_print_comp (dpi, options, d_right (dc)); |
bd6946d1 ILT |
4499 | |
4500 | /* If the modifier didn't get printed by the type, print it | |
4501 | now. */ | |
4502 | if (! dpm.printed) | |
743a99db | 4503 | d_print_mod (dpi, options, dc); |
69afa80d | 4504 | |
bd6946d1 | 4505 | dpi->modifiers = dpm.next; |
69afa80d | 4506 | |
bd6946d1 ILT |
4507 | return; |
4508 | } | |
69afa80d | 4509 | |
07523e7c JM |
4510 | case DEMANGLE_COMPONENT_FIXED_TYPE: |
4511 | if (dc->u.s_fixed.sat) | |
4512 | d_append_string (dpi, "_Sat "); | |
4513 | /* Don't print "int _Accum". */ | |
4514 | if (dc->u.s_fixed.length->u.s_builtin.type | |
4515 | != &cplus_demangle_builtin_types['i'-'a']) | |
4516 | { | |
743a99db | 4517 | d_print_comp (dpi, options, dc->u.s_fixed.length); |
07523e7c JM |
4518 | d_append_char (dpi, ' '); |
4519 | } | |
4520 | if (dc->u.s_fixed.accum) | |
4521 | d_append_string (dpi, "_Accum"); | |
4522 | else | |
4523 | d_append_string (dpi, "_Fract"); | |
4524 | return; | |
4525 | ||
5e777af5 ILT |
4526 | case DEMANGLE_COMPONENT_ARGLIST: |
4527 | case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: | |
38179091 | 4528 | if (d_left (dc) != NULL) |
743a99db | 4529 | d_print_comp (dpi, options, d_left (dc)); |
bd6946d1 ILT |
4530 | if (d_right (dc) != NULL) |
4531 | { | |
a77f94e2 | 4532 | size_t len; |
9c4d7e52 JJ |
4533 | unsigned long int flush_count; |
4534 | /* Make sure ", " isn't flushed by d_append_string, otherwise | |
4535 | dpi->len -= 2 wouldn't work. */ | |
4536 | if (dpi->len >= sizeof (dpi->buf) - 2) | |
4537 | d_print_flush (dpi); | |
456cc5cf | 4538 | d_append_string (dpi, ", "); |
a77f94e2 | 4539 | len = dpi->len; |
9c4d7e52 | 4540 | flush_count = dpi->flush_count; |
743a99db | 4541 | d_print_comp (dpi, options, d_right (dc)); |
a77f94e2 JM |
4542 | /* If that didn't print anything (which can happen with empty |
4543 | template argument packs), remove the comma and space. */ | |
9c4d7e52 | 4544 | if (dpi->flush_count == flush_count && dpi->len == len) |
a77f94e2 | 4545 | dpi->len -= 2; |
bd6946d1 ILT |
4546 | } |
4547 | return; | |
69afa80d | 4548 | |
4b6aaa99 JM |
4549 | case DEMANGLE_COMPONENT_INITIALIZER_LIST: |
4550 | { | |
4551 | struct demangle_component *type = d_left (dc); | |
4552 | struct demangle_component *list = d_right (dc); | |
4553 | ||
4554 | if (type) | |
4555 | d_print_comp (dpi, options, type); | |
4556 | d_append_char (dpi, '{'); | |
4557 | d_print_comp (dpi, options, list); | |
4558 | d_append_char (dpi, '}'); | |
4559 | } | |
4560 | return; | |
4561 | ||
5e777af5 | 4562 | case DEMANGLE_COMPONENT_OPERATOR: |
bd6946d1 | 4563 | { |
3abbe458 JM |
4564 | const struct demangle_operator_info *op = dc->u.s_operator.op; |
4565 | int len = op->len; | |
bd6946d1 | 4566 | |
456cc5cf | 4567 | d_append_string (dpi, "operator"); |
3abbe458 JM |
4568 | /* Add a space before new/delete. */ |
4569 | if (IS_LOWER (op->name[0])) | |
bd6946d1 | 4570 | d_append_char (dpi, ' '); |
3abbe458 JM |
4571 | /* Omit a trailing space. */ |
4572 | if (op->name[len-1] == ' ') | |
4573 | --len; | |
4574 | d_append_buffer (dpi, op->name, len); | |
bd6946d1 ILT |
4575 | return; |
4576 | } | |
69afa80d | 4577 | |
5e777af5 | 4578 | case DEMANGLE_COMPONENT_EXTENDED_OPERATOR: |
456cc5cf | 4579 | d_append_string (dpi, "operator "); |
743a99db | 4580 | d_print_comp (dpi, options, dc->u.s_extended_operator.name); |
bd6946d1 | 4581 | return; |
69afa80d | 4582 | |
5e777af5 | 4583 | case DEMANGLE_COMPONENT_CAST: |
456cc5cf | 4584 | d_append_string (dpi, "operator "); |
743a99db | 4585 | d_print_cast (dpi, options, dc); |
bd6946d1 | 4586 | return; |
69afa80d | 4587 | |
4b6aaa99 JM |
4588 | case DEMANGLE_COMPONENT_NULLARY: |
4589 | d_print_expr_op (dpi, options, d_left (dc)); | |
4590 | return; | |
4591 | ||
5e777af5 | 4592 | case DEMANGLE_COMPONENT_UNARY: |
4b6aaa99 JM |
4593 | { |
4594 | struct demangle_component *op = d_left (dc); | |
4595 | struct demangle_component *operand = d_right (dc); | |
4596 | const char *code = NULL; | |
cb0ad104 | 4597 | |
4b6aaa99 JM |
4598 | if (op->type == DEMANGLE_COMPONENT_OPERATOR) |
4599 | { | |
4600 | code = op->u.s_operator.op->code; | |
4601 | if (!strcmp (code, "ad")) | |
4602 | { | |
4603 | /* Don't print the argument list for the address of a | |
4604 | function. */ | |
4605 | if (operand->type == DEMANGLE_COMPONENT_TYPED_NAME | |
4606 | && d_left (operand)->type == DEMANGLE_COMPONENT_QUAL_NAME | |
4607 | && d_right (operand)->type == DEMANGLE_COMPONENT_FUNCTION_TYPE) | |
4608 | operand = d_left (operand); | |
4609 | } | |
4610 | if (operand->type == DEMANGLE_COMPONENT_BINARY_ARGS) | |
4611 | { | |
4612 | /* This indicates a suffix operator. */ | |
4613 | operand = d_left (operand); | |
4614 | d_print_subexpr (dpi, options, operand); | |
4615 | d_print_expr_op (dpi, options, op); | |
4616 | return; | |
4617 | } | |
4618 | } | |
cb0ad104 | 4619 | |
4b6aaa99 JM |
4620 | if (op->type != DEMANGLE_COMPONENT_CAST) |
4621 | d_print_expr_op (dpi, options, op); | |
4622 | else | |
4623 | { | |
4624 | d_append_char (dpi, '('); | |
4625 | d_print_cast (dpi, options, op); | |
4626 | d_append_char (dpi, ')'); | |
4627 | } | |
4628 | if (code && !strcmp (code, "gs")) | |
4629 | /* Avoid parens after '::'. */ | |
4630 | d_print_comp (dpi, options, operand); | |
4631 | else if (code && !strcmp (code, "st")) | |
4632 | /* Always print parens for sizeof (type). */ | |
4633 | { | |
4634 | d_append_char (dpi, '('); | |
4635 | d_print_comp (dpi, options, operand); | |
4636 | d_append_char (dpi, ')'); | |
4637 | } | |
4638 | else | |
4639 | d_print_subexpr (dpi, options, operand); | |
4640 | } | |
bd6946d1 ILT |
4641 | return; |
4642 | ||
5e777af5 ILT |
4643 | case DEMANGLE_COMPONENT_BINARY: |
4644 | if (d_right (dc)->type != DEMANGLE_COMPONENT_BINARY_ARGS) | |
69afa80d | 4645 | { |
bd6946d1 ILT |
4646 | d_print_error (dpi); |
4647 | return; | |
69afa80d | 4648 | } |
a51753e4 | 4649 | |
aefa74bd JM |
4650 | if (op_is_new_cast (d_left (dc))) |
4651 | { | |
4652 | d_print_expr_op (dpi, options, d_left (dc)); | |
4653 | d_append_char (dpi, '<'); | |
4654 | d_print_comp (dpi, options, d_left (d_right (dc))); | |
4655 | d_append_string (dpi, ">("); | |
4656 | d_print_comp (dpi, options, d_right (d_right (dc))); | |
4657 | d_append_char (dpi, ')'); | |
4658 | return; | |
4659 | } | |
4660 | ||
a51753e4 ILT |
4661 | /* We wrap an expression which uses the greater-than operator in |
4662 | an extra layer of parens so that it does not get confused | |
4663 | with the '>' which ends the template parameters. */ | |
5e777af5 | 4664 | if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR |
2d6c4025 ILT |
4665 | && d_left (dc)->u.s_operator.op->len == 1 |
4666 | && d_left (dc)->u.s_operator.op->name[0] == '>') | |
a51753e4 ILT |
4667 | d_append_char (dpi, '('); |
4668 | ||
cb0ad104 JK |
4669 | if (strcmp (d_left (dc)->u.s_operator.op->code, "cl") == 0 |
4670 | && d_left (d_right (dc))->type == DEMANGLE_COMPONENT_TYPED_NAME) | |
4671 | { | |
4672 | /* Function call used in an expression should not have printed types | |
4673 | of the function arguments. Values of the function arguments still | |
4674 | get printed below. */ | |
4675 | ||
4676 | const struct demangle_component *func = d_left (d_right (dc)); | |
4677 | ||
4678 | if (d_right (func)->type != DEMANGLE_COMPONENT_FUNCTION_TYPE) | |
4679 | d_print_error (dpi); | |
4680 | d_print_subexpr (dpi, options, d_left (func)); | |
4681 | } | |
4682 | else | |
4683 | d_print_subexpr (dpi, options, d_left (d_right (dc))); | |
4d43dcde JM |
4684 | if (strcmp (d_left (dc)->u.s_operator.op->code, "ix") == 0) |
4685 | { | |
4686 | d_append_char (dpi, '['); | |
743a99db | 4687 | d_print_comp (dpi, options, d_right (d_right (dc))); |
4d43dcde JM |
4688 | d_append_char (dpi, ']'); |
4689 | } | |
4690 | else | |
4691 | { | |
4692 | if (strcmp (d_left (dc)->u.s_operator.op->code, "cl") != 0) | |
743a99db JK |
4693 | d_print_expr_op (dpi, options, d_left (dc)); |
4694 | d_print_subexpr (dpi, options, d_right (d_right (dc))); | |
4d43dcde | 4695 | } |
a51753e4 | 4696 | |
5e777af5 | 4697 | if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR |
2d6c4025 ILT |
4698 | && d_left (dc)->u.s_operator.op->len == 1 |
4699 | && d_left (dc)->u.s_operator.op->name[0] == '>') | |
a51753e4 ILT |
4700 | d_append_char (dpi, ')'); |
4701 | ||
bd6946d1 ILT |
4702 | return; |
4703 | ||
5e777af5 ILT |
4704 | case DEMANGLE_COMPONENT_BINARY_ARGS: |
4705 | /* We should only see this as part of DEMANGLE_COMPONENT_BINARY. */ | |
bd6946d1 ILT |
4706 | d_print_error (dpi); |
4707 | return; | |
4708 | ||
5e777af5 ILT |
4709 | case DEMANGLE_COMPONENT_TRINARY: |
4710 | if (d_right (dc)->type != DEMANGLE_COMPONENT_TRINARY_ARG1 | |
4711 | || d_right (d_right (dc))->type != DEMANGLE_COMPONENT_TRINARY_ARG2) | |
bd6946d1 ILT |
4712 | { |
4713 | d_print_error (dpi); | |
4714 | return; | |
4715 | } | |
4b6aaa99 JM |
4716 | { |
4717 | struct demangle_component *op = d_left (dc); | |
4718 | struct demangle_component *first = d_left (d_right (dc)); | |
4719 | struct demangle_component *second = d_left (d_right (d_right (dc))); | |
4720 | struct demangle_component *third = d_right (d_right (d_right (dc))); | |
4721 | ||
4722 | if (!strcmp (op->u.s_operator.op->code, "qu")) | |
4723 | { | |
4724 | d_print_subexpr (dpi, options, first); | |
4725 | d_print_expr_op (dpi, options, op); | |
4726 | d_print_subexpr (dpi, options, second); | |
4727 | d_append_string (dpi, " : "); | |
4728 | d_print_subexpr (dpi, options, third); | |
4729 | } | |
4730 | else | |
4731 | { | |
4732 | d_append_string (dpi, "new "); | |
4733 | if (d_left (first) != NULL) | |
4734 | { | |
4735 | d_print_subexpr (dpi, options, first); | |
4736 | d_append_char (dpi, ' '); | |
4737 | } | |
4738 | d_print_comp (dpi, options, second); | |
4739 | if (third) | |
4740 | d_print_subexpr (dpi, options, third); | |
4741 | } | |
4742 | } | |
bd6946d1 ILT |
4743 | return; |
4744 | ||
5e777af5 ILT |
4745 | case DEMANGLE_COMPONENT_TRINARY_ARG1: |
4746 | case DEMANGLE_COMPONENT_TRINARY_ARG2: | |
4747 | /* We should only see these are part of DEMANGLE_COMPONENT_TRINARY. */ | |
bd6946d1 ILT |
4748 | d_print_error (dpi); |
4749 | return; | |
4750 | ||
5e777af5 ILT |
4751 | case DEMANGLE_COMPONENT_LITERAL: |
4752 | case DEMANGLE_COMPONENT_LITERAL_NEG: | |
31058ee3 ILT |
4753 | { |
4754 | enum d_builtin_type_print tp; | |
bd6946d1 | 4755 | |
31058ee3 ILT |
4756 | /* For some builtin types, produce simpler output. */ |
4757 | tp = D_PRINT_DEFAULT; | |
4758 | if (d_left (dc)->type == DEMANGLE_COMPONENT_BUILTIN_TYPE) | |
4759 | { | |
4760 | tp = d_left (dc)->u.s_builtin.type->print; | |
4761 | switch (tp) | |
4762 | { | |
4763 | case D_PRINT_INT: | |
4764 | case D_PRINT_UNSIGNED: | |
4765 | case D_PRINT_LONG: | |
4766 | case D_PRINT_UNSIGNED_LONG: | |
4767 | case D_PRINT_LONG_LONG: | |
4768 | case D_PRINT_UNSIGNED_LONG_LONG: | |
4769 | if (d_right (dc)->type == DEMANGLE_COMPONENT_NAME) | |
4770 | { | |
4771 | if (dc->type == DEMANGLE_COMPONENT_LITERAL_NEG) | |
4772 | d_append_char (dpi, '-'); | |
743a99db | 4773 | d_print_comp (dpi, options, d_right (dc)); |
31058ee3 ILT |
4774 | switch (tp) |
4775 | { | |
4776 | default: | |
4777 | break; | |
4778 | case D_PRINT_UNSIGNED: | |
4779 | d_append_char (dpi, 'u'); | |
4780 | break; | |
4781 | case D_PRINT_LONG: | |
4782 | d_append_char (dpi, 'l'); | |
4783 | break; | |
4784 | case D_PRINT_UNSIGNED_LONG: | |
456cc5cf | 4785 | d_append_string (dpi, "ul"); |
31058ee3 ILT |
4786 | break; |
4787 | case D_PRINT_LONG_LONG: | |
456cc5cf | 4788 | d_append_string (dpi, "ll"); |
31058ee3 ILT |
4789 | break; |
4790 | case D_PRINT_UNSIGNED_LONG_LONG: | |
456cc5cf | 4791 | d_append_string (dpi, "ull"); |
31058ee3 ILT |
4792 | break; |
4793 | } | |
4794 | return; | |
4795 | } | |
4796 | break; | |
69afa80d | 4797 | |
31058ee3 ILT |
4798 | case D_PRINT_BOOL: |
4799 | if (d_right (dc)->type == DEMANGLE_COMPONENT_NAME | |
4800 | && d_right (dc)->u.s_name.len == 1 | |
4801 | && dc->type == DEMANGLE_COMPONENT_LITERAL) | |
4802 | { | |
4803 | switch (d_right (dc)->u.s_name.s[0]) | |
4804 | { | |
4805 | case '0': | |
456cc5cf | 4806 | d_append_string (dpi, "false"); |
31058ee3 ILT |
4807 | return; |
4808 | case '1': | |
456cc5cf | 4809 | d_append_string (dpi, "true"); |
31058ee3 ILT |
4810 | return; |
4811 | default: | |
4812 | break; | |
4813 | } | |
4814 | } | |
4815 | break; | |
051664b0 | 4816 | |
31058ee3 ILT |
4817 | default: |
4818 | break; | |
4819 | } | |
4820 | } | |
69afa80d | 4821 | |
31058ee3 | 4822 | d_append_char (dpi, '('); |
743a99db | 4823 | d_print_comp (dpi, options, d_left (dc)); |
31058ee3 ILT |
4824 | d_append_char (dpi, ')'); |
4825 | if (dc->type == DEMANGLE_COMPONENT_LITERAL_NEG) | |
4826 | d_append_char (dpi, '-'); | |
4827 | if (tp == D_PRINT_FLOAT) | |
4828 | d_append_char (dpi, '['); | |
743a99db | 4829 | d_print_comp (dpi, options, d_right (dc)); |
31058ee3 ILT |
4830 | if (tp == D_PRINT_FLOAT) |
4831 | d_append_char (dpi, ']'); | |
4832 | } | |
bd6946d1 | 4833 | return; |
69afa80d | 4834 | |
abfe01ce JM |
4835 | case DEMANGLE_COMPONENT_NUMBER: |
4836 | d_append_num (dpi, dc->u.s_number.number); | |
4837 | return; | |
4838 | ||
e5df4fb1 DD |
4839 | case DEMANGLE_COMPONENT_JAVA_RESOURCE: |
4840 | d_append_string (dpi, "java resource "); | |
743a99db | 4841 | d_print_comp (dpi, options, d_left (dc)); |
e5df4fb1 DD |
4842 | return; |
4843 | ||
4844 | case DEMANGLE_COMPONENT_COMPOUND_NAME: | |
743a99db JK |
4845 | d_print_comp (dpi, options, d_left (dc)); |
4846 | d_print_comp (dpi, options, d_right (dc)); | |
e5df4fb1 DD |
4847 | return; |
4848 | ||
4849 | case DEMANGLE_COMPONENT_CHARACTER: | |
4850 | d_append_char (dpi, dc->u.s_character.character); | |
4851 | return; | |
4852 | ||
5a3d7e74 JM |
4853 | case DEMANGLE_COMPONENT_DECLTYPE: |
4854 | d_append_string (dpi, "decltype ("); | |
743a99db | 4855 | d_print_comp (dpi, options, d_left (dc)); |
5a3d7e74 JM |
4856 | d_append_char (dpi, ')'); |
4857 | return; | |
4858 | ||
38179091 JM |
4859 | case DEMANGLE_COMPONENT_PACK_EXPANSION: |
4860 | { | |
6afcfe0a | 4861 | int len; |
38179091 | 4862 | int i; |
6afcfe0a JM |
4863 | struct demangle_component *a = d_find_pack (dpi, d_left (dc)); |
4864 | if (a == NULL) | |
4865 | { | |
4866 | /* d_find_pack won't find anything if the only packs involved | |
4867 | in this expansion are function parameter packs; in that | |
4868 | case, just print the pattern and "...". */ | |
743a99db | 4869 | d_print_subexpr (dpi, options, d_left (dc)); |
6afcfe0a JM |
4870 | d_append_string (dpi, "..."); |
4871 | return; | |
4872 | } | |
38179091 | 4873 | |
6afcfe0a | 4874 | len = d_pack_length (a); |
38179091 JM |
4875 | dc = d_left (dc); |
4876 | for (i = 0; i < len; ++i) | |
4877 | { | |
4878 | dpi->pack_index = i; | |
743a99db | 4879 | d_print_comp (dpi, options, dc); |
38179091 JM |
4880 | if (i < len-1) |
4881 | d_append_string (dpi, ", "); | |
4882 | } | |
4883 | } | |
4884 | return; | |
4885 | ||
448545cb | 4886 | case DEMANGLE_COMPONENT_FUNCTION_PARAM: |
a517066d JM |
4887 | { |
4888 | long num = dc->u.s_number.number; | |
4889 | if (num == 0) | |
4890 | d_append_string (dpi, "this"); | |
4891 | else | |
4892 | { | |
4893 | d_append_string (dpi, "{parm#"); | |
4894 | d_append_num (dpi, num); | |
4895 | d_append_char (dpi, '}'); | |
4896 | } | |
4897 | } | |
d5f4eddd | 4898 | return; |
448545cb | 4899 | |
23b1a789 JK |
4900 | case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS: |
4901 | d_append_string (dpi, "global constructors keyed to "); | |
743a99db | 4902 | d_print_comp (dpi, options, dc->u.s_binary.left); |
23b1a789 JK |
4903 | return; |
4904 | ||
4905 | case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS: | |
4906 | d_append_string (dpi, "global destructors keyed to "); | |
743a99db | 4907 | d_print_comp (dpi, options, dc->u.s_binary.left); |
23b1a789 JK |
4908 | return; |
4909 | ||
d5f4eddd JM |
4910 | case DEMANGLE_COMPONENT_LAMBDA: |
4911 | d_append_string (dpi, "{lambda("); | |
743a99db | 4912 | d_print_comp (dpi, options, dc->u.s_unary_num.sub); |
d5f4eddd JM |
4913 | d_append_string (dpi, ")#"); |
4914 | d_append_num (dpi, dc->u.s_unary_num.num + 1); | |
4915 | d_append_char (dpi, '}'); | |
4916 | return; | |
4917 | ||
4918 | case DEMANGLE_COMPONENT_UNNAMED_TYPE: | |
4919 | d_append_string (dpi, "{unnamed type#"); | |
4920 | d_append_num (dpi, dc->u.s_number.number + 1); | |
4921 | d_append_char (dpi, '}'); | |
4922 | return; | |
4923 | ||
2d2b02c4 CC |
4924 | case DEMANGLE_COMPONENT_CLONE: |
4925 | d_print_comp (dpi, options, d_left (dc)); | |
4926 | d_append_string (dpi, " [clone "); | |
4927 | d_print_comp (dpi, options, d_right (dc)); | |
4928 | d_append_char (dpi, ']'); | |
4929 | return; | |
4930 | ||
bd6946d1 ILT |
4931 | default: |
4932 | d_print_error (dpi); | |
4933 | return; | |
4934 | } | |
69afa80d AS |
4935 | } |
4936 | ||
2d6c4025 ILT |
4937 | /* Print a Java dentifier. For Java we try to handle encoded extended |
4938 | Unicode characters. The C++ ABI doesn't mention Unicode encoding, | |
4939 | so we don't it for C++. Characters are encoded as | |
4940 | __U<hex-char>+_. */ | |
69afa80d | 4941 | |
bd6946d1 | 4942 | static void |
9486db4f | 4943 | d_print_java_identifier (struct d_print_info *dpi, const char *name, int len) |
69afa80d | 4944 | { |
2d6c4025 ILT |
4945 | const char *p; |
4946 | const char *end; | |
69afa80d | 4947 | |
2d6c4025 ILT |
4948 | end = name + len; |
4949 | for (p = name; p < end; ++p) | |
4950 | { | |
4951 | if (end - p > 3 | |
4952 | && p[0] == '_' | |
4953 | && p[1] == '_' | |
4954 | && p[2] == 'U') | |
69afa80d | 4955 | { |
2d6c4025 ILT |
4956 | unsigned long c; |
4957 | const char *q; | |
4958 | ||
4959 | c = 0; | |
4960 | for (q = p + 3; q < end; ++q) | |
bd6946d1 | 4961 | { |
2d6c4025 ILT |
4962 | int dig; |
4963 | ||
4964 | if (IS_DIGIT (*q)) | |
4965 | dig = *q - '0'; | |
4966 | else if (*q >= 'A' && *q <= 'F') | |
4967 | dig = *q - 'A' + 10; | |
4968 | else if (*q >= 'a' && *q <= 'f') | |
4969 | dig = *q - 'a' + 10; | |
4970 | else | |
4971 | break; | |
69afa80d | 4972 | |
2d6c4025 ILT |
4973 | c = c * 16 + dig; |
4974 | } | |
4975 | /* If the Unicode character is larger than 256, we don't try | |
4976 | to deal with it here. FIXME. */ | |
4977 | if (q < end && *q == '_' && c < 256) | |
4978 | { | |
4979 | d_append_char (dpi, c); | |
4980 | p = q; | |
4981 | continue; | |
bd6946d1 | 4982 | } |
bd6946d1 | 4983 | } |
2d6c4025 ILT |
4984 | |
4985 | d_append_char (dpi, *p); | |
69afa80d | 4986 | } |
69afa80d AS |
4987 | } |
4988 | ||
a51753e4 ILT |
4989 | /* Print a list of modifiers. SUFFIX is 1 if we are printing |
4990 | qualifiers on this after printing a function. */ | |
69afa80d | 4991 | |
bd6946d1 | 4992 | static void |
743a99db | 4993 | d_print_mod_list (struct d_print_info *dpi, int options, |
9486db4f | 4994 | struct d_print_mod *mods, int suffix) |
69afa80d | 4995 | { |
81dc098b ILT |
4996 | struct d_print_template *hold_dpt; |
4997 | ||
a51753e4 | 4998 | if (mods == NULL || d_print_saw_error (dpi)) |
bd6946d1 | 4999 | return; |
69afa80d | 5000 | |
a51753e4 ILT |
5001 | if (mods->printed |
5002 | || (! suffix | |
5e777af5 ILT |
5003 | && (mods->mod->type == DEMANGLE_COMPONENT_RESTRICT_THIS |
5004 | || mods->mod->type == DEMANGLE_COMPONENT_VOLATILE_THIS | |
9eb85f27 JM |
5005 | || mods->mod->type == DEMANGLE_COMPONENT_CONST_THIS |
5006 | || mods->mod->type == DEMANGLE_COMPONENT_REFERENCE_THIS | |
5007 | || (mods->mod->type | |
5008 | == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)))) | |
a51753e4 | 5009 | { |
743a99db | 5010 | d_print_mod_list (dpi, options, mods->next, suffix); |
a51753e4 ILT |
5011 | return; |
5012 | } | |
5013 | ||
81dc098b ILT |
5014 | mods->printed = 1; |
5015 | ||
5016 | hold_dpt = dpi->templates; | |
5017 | dpi->templates = mods->templates; | |
5018 | ||
5e777af5 | 5019 | if (mods->mod->type == DEMANGLE_COMPONENT_FUNCTION_TYPE) |
69afa80d | 5020 | { |
743a99db | 5021 | d_print_function_type (dpi, options, mods->mod, mods->next); |
81dc098b | 5022 | dpi->templates = hold_dpt; |
bd6946d1 ILT |
5023 | return; |
5024 | } | |
5e777af5 | 5025 | else if (mods->mod->type == DEMANGLE_COMPONENT_ARRAY_TYPE) |
bd6946d1 | 5026 | { |
743a99db | 5027 | d_print_array_type (dpi, options, mods->mod, mods->next); |
81dc098b | 5028 | dpi->templates = hold_dpt; |
bd6946d1 ILT |
5029 | return; |
5030 | } | |
5e777af5 | 5031 | else if (mods->mod->type == DEMANGLE_COMPONENT_LOCAL_NAME) |
a91d1af0 ILT |
5032 | { |
5033 | struct d_print_mod *hold_modifiers; | |
5e777af5 | 5034 | struct demangle_component *dc; |
a91d1af0 ILT |
5035 | |
5036 | /* When this is on the modifier stack, we have pulled any | |
5037 | qualifiers off the right argument already. Otherwise, we | |
5038 | print it as usual, but don't let the left argument see any | |
5039 | modifiers. */ | |
5040 | ||
5041 | hold_modifiers = dpi->modifiers; | |
5042 | dpi->modifiers = NULL; | |
743a99db | 5043 | d_print_comp (dpi, options, d_left (mods->mod)); |
a91d1af0 ILT |
5044 | dpi->modifiers = hold_modifiers; |
5045 | ||
743a99db | 5046 | if ((options & DMGL_JAVA) == 0) |
456cc5cf | 5047 | d_append_string (dpi, "::"); |
2d6c4025 ILT |
5048 | else |
5049 | d_append_char (dpi, '.'); | |
a91d1af0 ILT |
5050 | |
5051 | dc = d_right (mods->mod); | |
d5f4eddd JM |
5052 | |
5053 | if (dc->type == DEMANGLE_COMPONENT_DEFAULT_ARG) | |
5054 | { | |
5055 | d_append_string (dpi, "{default arg#"); | |
5056 | d_append_num (dpi, dc->u.s_unary_num.num + 1); | |
5057 | d_append_string (dpi, "}::"); | |
5058 | dc = dc->u.s_unary_num.sub; | |
5059 | } | |
5060 | ||
5e777af5 ILT |
5061 | while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS |
5062 | || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS | |
9eb85f27 JM |
5063 | || dc->type == DEMANGLE_COMPONENT_CONST_THIS |
5064 | || dc->type == DEMANGLE_COMPONENT_REFERENCE_THIS | |
5065 | || dc->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS) | |
a91d1af0 ILT |
5066 | dc = d_left (dc); |
5067 | ||
743a99db | 5068 | d_print_comp (dpi, options, dc); |
a91d1af0 ILT |
5069 | |
5070 | dpi->templates = hold_dpt; | |
5071 | return; | |
5072 | } | |
69afa80d | 5073 | |
743a99db | 5074 | d_print_mod (dpi, options, mods->mod); |
69afa80d | 5075 | |
81dc098b ILT |
5076 | dpi->templates = hold_dpt; |
5077 | ||
743a99db | 5078 | d_print_mod_list (dpi, options, mods->next, suffix); |
69afa80d | 5079 | } |
81dc098b | 5080 | |
bd6946d1 | 5081 | /* Print a modifier. */ |
69afa80d | 5082 | |
bd6946d1 | 5083 | static void |
743a99db | 5084 | d_print_mod (struct d_print_info *dpi, int options, |
9486db4f | 5085 | const struct demangle_component *mod) |
bd6946d1 ILT |
5086 | { |
5087 | switch (mod->type) | |
5088 | { | |
5e777af5 ILT |
5089 | case DEMANGLE_COMPONENT_RESTRICT: |
5090 | case DEMANGLE_COMPONENT_RESTRICT_THIS: | |
456cc5cf | 5091 | d_append_string (dpi, " restrict"); |
bd6946d1 | 5092 | return; |
5e777af5 ILT |
5093 | case DEMANGLE_COMPONENT_VOLATILE: |
5094 | case DEMANGLE_COMPONENT_VOLATILE_THIS: | |
456cc5cf | 5095 | d_append_string (dpi, " volatile"); |
bd6946d1 | 5096 | return; |
5e777af5 ILT |
5097 | case DEMANGLE_COMPONENT_CONST: |
5098 | case DEMANGLE_COMPONENT_CONST_THIS: | |
456cc5cf | 5099 | d_append_string (dpi, " const"); |
bd6946d1 | 5100 | return; |
5e777af5 | 5101 | case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: |
bd6946d1 | 5102 | d_append_char (dpi, ' '); |
743a99db | 5103 | d_print_comp (dpi, options, d_right (mod)); |
bd6946d1 | 5104 | return; |
5e777af5 | 5105 | case DEMANGLE_COMPONENT_POINTER: |
bd6946d1 | 5106 | /* There is no pointer symbol in Java. */ |
743a99db | 5107 | if ((options & DMGL_JAVA) == 0) |
bd6946d1 ILT |
5108 | d_append_char (dpi, '*'); |
5109 | return; | |
9eb85f27 JM |
5110 | case DEMANGLE_COMPONENT_REFERENCE_THIS: |
5111 | /* For the ref-qualifier, put a space before the &. */ | |
5112 | d_append_char (dpi, ' '); | |
5e777af5 | 5113 | case DEMANGLE_COMPONENT_REFERENCE: |
bd6946d1 ILT |
5114 | d_append_char (dpi, '&'); |
5115 | return; | |
9eb85f27 JM |
5116 | case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: |
5117 | d_append_char (dpi, ' '); | |
1ab28be5 DG |
5118 | case DEMANGLE_COMPONENT_RVALUE_REFERENCE: |
5119 | d_append_string (dpi, "&&"); | |
5120 | return; | |
5e777af5 | 5121 | case DEMANGLE_COMPONENT_COMPLEX: |
456cc5cf | 5122 | d_append_string (dpi, "complex "); |
bd6946d1 | 5123 | return; |
5e777af5 | 5124 | case DEMANGLE_COMPONENT_IMAGINARY: |
456cc5cf | 5125 | d_append_string (dpi, "imaginary "); |
bd6946d1 | 5126 | return; |
5e777af5 | 5127 | case DEMANGLE_COMPONENT_PTRMEM_TYPE: |
a51753e4 | 5128 | if (d_last_char (dpi) != '(') |
bd6946d1 | 5129 | d_append_char (dpi, ' '); |
743a99db | 5130 | d_print_comp (dpi, options, d_left (mod)); |
456cc5cf | 5131 | d_append_string (dpi, "::*"); |
bd6946d1 | 5132 | return; |
5e777af5 | 5133 | case DEMANGLE_COMPONENT_TYPED_NAME: |
743a99db | 5134 | d_print_comp (dpi, options, d_left (mod)); |
bd6946d1 | 5135 | return; |
abfe01ce | 5136 | case DEMANGLE_COMPONENT_VECTOR_TYPE: |
ce30e6fd | 5137 | d_append_string (dpi, " __vector("); |
743a99db | 5138 | d_print_comp (dpi, options, d_left (mod)); |
ce30e6fd | 5139 | d_append_char (dpi, ')'); |
abfe01ce JM |
5140 | return; |
5141 | ||
bd6946d1 ILT |
5142 | default: |
5143 | /* Otherwise, we have something that won't go back on the | |
5144 | modifier stack, so we can just print it. */ | |
743a99db | 5145 | d_print_comp (dpi, options, mod); |
bd6946d1 ILT |
5146 | return; |
5147 | } | |
5148 | } | |
69afa80d | 5149 | |
bd6946d1 | 5150 | /* Print a function type, except for the return type. */ |
69afa80d | 5151 | |
bd6946d1 | 5152 | static void |
743a99db | 5153 | d_print_function_type (struct d_print_info *dpi, int options, |
9486db4f GDR |
5154 | const struct demangle_component *dc, |
5155 | struct d_print_mod *mods) | |
69afa80d | 5156 | { |
81dc098b | 5157 | int need_paren; |
31058ee3 | 5158 | int need_space; |
81dc098b | 5159 | struct d_print_mod *p; |
a91d1af0 | 5160 | struct d_print_mod *hold_modifiers; |
81dc098b ILT |
5161 | |
5162 | need_paren = 0; | |
31058ee3 | 5163 | need_space = 0; |
81dc098b | 5164 | for (p = mods; p != NULL; p = p->next) |
bd6946d1 | 5165 | { |
81dc098b ILT |
5166 | if (p->printed) |
5167 | break; | |
69afa80d | 5168 | |
81dc098b | 5169 | switch (p->mod->type) |
bd6946d1 | 5170 | { |
31058ee3 ILT |
5171 | case DEMANGLE_COMPONENT_POINTER: |
5172 | case DEMANGLE_COMPONENT_REFERENCE: | |
1ab28be5 | 5173 | case DEMANGLE_COMPONENT_RVALUE_REFERENCE: |
31058ee3 ILT |
5174 | need_paren = 1; |
5175 | break; | |
5e777af5 ILT |
5176 | case DEMANGLE_COMPONENT_RESTRICT: |
5177 | case DEMANGLE_COMPONENT_VOLATILE: | |
5178 | case DEMANGLE_COMPONENT_CONST: | |
5179 | case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: | |
5e777af5 ILT |
5180 | case DEMANGLE_COMPONENT_COMPLEX: |
5181 | case DEMANGLE_COMPONENT_IMAGINARY: | |
5182 | case DEMANGLE_COMPONENT_PTRMEM_TYPE: | |
31058ee3 | 5183 | need_space = 1; |
81dc098b ILT |
5184 | need_paren = 1; |
5185 | break; | |
5e777af5 ILT |
5186 | case DEMANGLE_COMPONENT_RESTRICT_THIS: |
5187 | case DEMANGLE_COMPONENT_VOLATILE_THIS: | |
5188 | case DEMANGLE_COMPONENT_CONST_THIS: | |
9eb85f27 JM |
5189 | case DEMANGLE_COMPONENT_REFERENCE_THIS: |
5190 | case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: | |
a51753e4 | 5191 | break; |
81dc098b ILT |
5192 | default: |
5193 | break; | |
bd6946d1 | 5194 | } |
81dc098b ILT |
5195 | if (need_paren) |
5196 | break; | |
5197 | } | |
69afa80d | 5198 | |
81dc098b | 5199 | if (need_paren) |
a51753e4 | 5200 | { |
31058ee3 | 5201 | if (! need_space) |
a51753e4 | 5202 | { |
31058ee3 ILT |
5203 | if (d_last_char (dpi) != '(' |
5204 | && d_last_char (dpi) != '*') | |
5205 | need_space = 1; | |
a51753e4 | 5206 | } |
31058ee3 ILT |
5207 | if (need_space && d_last_char (dpi) != ' ') |
5208 | d_append_char (dpi, ' '); | |
a51753e4 ILT |
5209 | d_append_char (dpi, '('); |
5210 | } | |
69afa80d | 5211 | |
a91d1af0 ILT |
5212 | hold_modifiers = dpi->modifiers; |
5213 | dpi->modifiers = NULL; | |
5214 | ||
743a99db | 5215 | d_print_mod_list (dpi, options, mods, 0); |
69afa80d | 5216 | |
81dc098b ILT |
5217 | if (need_paren) |
5218 | d_append_char (dpi, ')'); | |
69afa80d | 5219 | |
bd6946d1 | 5220 | d_append_char (dpi, '('); |
69afa80d | 5221 | |
bd6946d1 | 5222 | if (d_right (dc) != NULL) |
743a99db | 5223 | d_print_comp (dpi, options, d_right (dc)); |
69afa80d | 5224 | |
bd6946d1 | 5225 | d_append_char (dpi, ')'); |
a51753e4 | 5226 | |
743a99db | 5227 | d_print_mod_list (dpi, options, mods, 1); |
a91d1af0 ILT |
5228 | |
5229 | dpi->modifiers = hold_modifiers; | |
bd6946d1 | 5230 | } |
69afa80d | 5231 | |
bd6946d1 | 5232 | /* Print an array type, except for the element type. */ |
69afa80d | 5233 | |
bd6946d1 | 5234 | static void |
743a99db | 5235 | d_print_array_type (struct d_print_info *dpi, int options, |
9486db4f GDR |
5236 | const struct demangle_component *dc, |
5237 | struct d_print_mod *mods) | |
bd6946d1 ILT |
5238 | { |
5239 | int need_space; | |
69afa80d | 5240 | |
bd6946d1 ILT |
5241 | need_space = 1; |
5242 | if (mods != NULL) | |
69afa80d | 5243 | { |
bd6946d1 ILT |
5244 | int need_paren; |
5245 | struct d_print_mod *p; | |
051664b0 | 5246 | |
bd6946d1 ILT |
5247 | need_paren = 0; |
5248 | for (p = mods; p != NULL; p = p->next) | |
69afa80d | 5249 | { |
80a19ac8 | 5250 | if (! p->printed) |
69afa80d | 5251 | { |
80a19ac8 ILT |
5252 | if (p->mod->type == DEMANGLE_COMPONENT_ARRAY_TYPE) |
5253 | { | |
5254 | need_space = 0; | |
5255 | break; | |
5256 | } | |
5257 | else | |
5258 | { | |
5259 | need_paren = 1; | |
5260 | need_space = 1; | |
5261 | break; | |
5262 | } | |
69afa80d | 5263 | } |
bd6946d1 | 5264 | } |
69afa80d | 5265 | |
bd6946d1 | 5266 | if (need_paren) |
456cc5cf | 5267 | d_append_string (dpi, " ("); |
69afa80d | 5268 | |
743a99db | 5269 | d_print_mod_list (dpi, options, mods, 0); |
69afa80d | 5270 | |
bd6946d1 ILT |
5271 | if (need_paren) |
5272 | d_append_char (dpi, ')'); | |
5273 | } | |
69afa80d | 5274 | |
bd6946d1 ILT |
5275 | if (need_space) |
5276 | d_append_char (dpi, ' '); | |
051664b0 | 5277 | |
bd6946d1 | 5278 | d_append_char (dpi, '['); |
051664b0 | 5279 | |
bd6946d1 | 5280 | if (d_left (dc) != NULL) |
743a99db | 5281 | d_print_comp (dpi, options, d_left (dc)); |
69afa80d | 5282 | |
bd6946d1 ILT |
5283 | d_append_char (dpi, ']'); |
5284 | } | |
69afa80d | 5285 | |
bd6946d1 | 5286 | /* Print an operator in an expression. */ |
69afa80d | 5287 | |
bd6946d1 | 5288 | static void |
743a99db | 5289 | d_print_expr_op (struct d_print_info *dpi, int options, |
9486db4f | 5290 | const struct demangle_component *dc) |
bd6946d1 | 5291 | { |
5e777af5 | 5292 | if (dc->type == DEMANGLE_COMPONENT_OPERATOR) |
2d6c4025 ILT |
5293 | d_append_buffer (dpi, dc->u.s_operator.op->name, |
5294 | dc->u.s_operator.op->len); | |
bd6946d1 | 5295 | else |
743a99db | 5296 | d_print_comp (dpi, options, dc); |
69afa80d AS |
5297 | } |
5298 | ||
bd6946d1 | 5299 | /* Print a cast. */ |
69afa80d | 5300 | |
bd6946d1 | 5301 | static void |
743a99db | 5302 | d_print_cast (struct d_print_info *dpi, int options, |
9486db4f | 5303 | const struct demangle_component *dc) |
69afa80d | 5304 | { |
5e777af5 | 5305 | if (d_left (dc)->type != DEMANGLE_COMPONENT_TEMPLATE) |
743a99db | 5306 | d_print_comp (dpi, options, d_left (dc)); |
bd6946d1 ILT |
5307 | else |
5308 | { | |
81dc098b | 5309 | struct d_print_mod *hold_dpm; |
bd6946d1 | 5310 | struct d_print_template dpt; |
820555e6 | 5311 | |
bd6946d1 ILT |
5312 | /* It appears that for a templated cast operator, we need to put |
5313 | the template parameters in scope for the operator name, but | |
5314 | not for the parameters. The effect is that we need to handle | |
f26deb3d | 5315 | the template printing here. */ |
69afa80d | 5316 | |
81dc098b ILT |
5317 | hold_dpm = dpi->modifiers; |
5318 | dpi->modifiers = NULL; | |
5319 | ||
bd6946d1 ILT |
5320 | dpt.next = dpi->templates; |
5321 | dpi->templates = &dpt; | |
d7cf8390 | 5322 | dpt.template_decl = d_left (dc); |
820555e6 | 5323 | |
743a99db | 5324 | d_print_comp (dpi, options, d_left (d_left (dc))); |
820555e6 | 5325 | |
bd6946d1 | 5326 | dpi->templates = dpt.next; |
69afa80d | 5327 | |
a51753e4 ILT |
5328 | if (d_last_char (dpi) == '<') |
5329 | d_append_char (dpi, ' '); | |
bd6946d1 | 5330 | d_append_char (dpi, '<'); |
743a99db | 5331 | d_print_comp (dpi, options, d_right (d_left (dc))); |
bd6946d1 ILT |
5332 | /* Avoid generating two consecutive '>' characters, to avoid |
5333 | the C++ syntactic ambiguity. */ | |
a51753e4 | 5334 | if (d_last_char (dpi) == '>') |
bd6946d1 ILT |
5335 | d_append_char (dpi, ' '); |
5336 | d_append_char (dpi, '>'); | |
81dc098b ILT |
5337 | |
5338 | dpi->modifiers = hold_dpm; | |
69afa80d | 5339 | } |
bd6946d1 ILT |
5340 | } |
5341 | ||
5342 | /* Initialize the information structure we use to pass around | |
5343 | information. */ | |
5344 | ||
5e777af5 ILT |
5345 | CP_STATIC_IF_GLIBCPP_V3 |
5346 | void | |
9486db4f GDR |
5347 | cplus_demangle_init_info (const char *mangled, int options, size_t len, |
5348 | struct d_info *di) | |
69afa80d | 5349 | { |
bd6946d1 | 5350 | di->s = mangled; |
2d6c4025 | 5351 | di->send = mangled + len; |
bd6946d1 | 5352 | di->options = options; |
69afa80d | 5353 | |
bd6946d1 ILT |
5354 | di->n = mangled; |
5355 | ||
5356 | /* We can not need more components than twice the number of chars in | |
5357 | the mangled string. Most components correspond directly to | |
5358 | chars, but the ARGLIST types are exceptions. */ | |
5359 | di->num_comps = 2 * len; | |
bd6946d1 ILT |
5360 | di->next_comp = 0; |
5361 | ||
5362 | /* Similarly, we can not need more substitutions than there are | |
81dc098b ILT |
5363 | chars in the mangled string. */ |
5364 | di->num_subs = len; | |
bd6946d1 | 5365 | di->next_sub = 0; |
2d6c4025 | 5366 | di->did_subs = 0; |
bd6946d1 ILT |
5367 | |
5368 | di->last_name = NULL; | |
5369 | ||
2d6c4025 | 5370 | di->expansion = 0; |
69afa80d AS |
5371 | } |
5372 | ||
456cc5cf SB |
5373 | /* Internal implementation for the demangler. If MANGLED is a g++ v3 ABI |
5374 | mangled name, return strings in repeated callback giving the demangled | |
5375 | name. OPTIONS is the usual libiberty demangler options. On success, | |
5376 | this returns 1. On failure, returns 0. */ | |
69afa80d | 5377 | |
456cc5cf SB |
5378 | static int |
5379 | d_demangle_callback (const char *mangled, int options, | |
5380 | demangle_callbackref callback, void *opaque) | |
69afa80d | 5381 | { |
23b1a789 JK |
5382 | enum |
5383 | { | |
5384 | DCT_TYPE, | |
5385 | DCT_MANGLED, | |
5386 | DCT_GLOBAL_CTORS, | |
5387 | DCT_GLOBAL_DTORS | |
5388 | } | |
5389 | type; | |
bd6946d1 | 5390 | struct d_info di; |
5e777af5 | 5391 | struct demangle_component *dc; |
456cc5cf | 5392 | int status; |
bd6946d1 ILT |
5393 | |
5394 | if (mangled[0] == '_' && mangled[1] == 'Z') | |
23b1a789 | 5395 | type = DCT_MANGLED; |
bd6946d1 ILT |
5396 | else if (strncmp (mangled, "_GLOBAL_", 8) == 0 |
5397 | && (mangled[8] == '.' || mangled[8] == '_' || mangled[8] == '$') | |
5398 | && (mangled[9] == 'D' || mangled[9] == 'I') | |
5399 | && mangled[10] == '_') | |
23b1a789 | 5400 | type = mangled[9] == 'I' ? DCT_GLOBAL_CTORS : DCT_GLOBAL_DTORS; |
69afa80d AS |
5401 | else |
5402 | { | |
bd6946d1 | 5403 | if ((options & DMGL_TYPES) == 0) |
456cc5cf | 5404 | return 0; |
23b1a789 | 5405 | type = DCT_TYPE; |
69afa80d AS |
5406 | } |
5407 | ||
456cc5cf | 5408 | cplus_demangle_init_info (mangled, options, strlen (mangled), &di); |
051664b0 | 5409 | |
2d6c4025 ILT |
5410 | { |
5411 | #ifdef CP_DYNAMIC_ARRAYS | |
5e777af5 ILT |
5412 | __extension__ struct demangle_component comps[di.num_comps]; |
5413 | __extension__ struct demangle_component *subs[di.num_subs]; | |
2d6c4025 | 5414 | |
456cc5cf SB |
5415 | di.comps = comps; |
5416 | di.subs = subs; | |
2d6c4025 | 5417 | #else |
456cc5cf SB |
5418 | di.comps = alloca (di.num_comps * sizeof (*di.comps)); |
5419 | di.subs = alloca (di.num_subs * sizeof (*di.subs)); | |
2d6c4025 ILT |
5420 | #endif |
5421 | ||
23b1a789 JK |
5422 | switch (type) |
5423 | { | |
5424 | case DCT_TYPE: | |
5425 | dc = cplus_demangle_type (&di); | |
5426 | break; | |
5427 | case DCT_MANGLED: | |
5428 | dc = cplus_demangle_mangled_name (&di, 1); | |
5429 | break; | |
5430 | case DCT_GLOBAL_CTORS: | |
5431 | case DCT_GLOBAL_DTORS: | |
5432 | d_advance (&di, 11); | |
5433 | dc = d_make_comp (&di, | |
5434 | (type == DCT_GLOBAL_CTORS | |
5435 | ? DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS | |
5436 | : DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS), | |
431f321f | 5437 | d_make_demangle_mangled_name (&di, d_str (&di)), |
23b1a789 JK |
5438 | NULL); |
5439 | d_advance (&di, strlen (d_str (&di))); | |
5440 | break; | |
5441 | } | |
bd6946d1 | 5442 | |
2d6c4025 ILT |
5443 | /* If DMGL_PARAMS is set, then if we didn't consume the entire |
5444 | mangled string, then we didn't successfully demangle it. If | |
5445 | DMGL_PARAMS is not set, we didn't look at the trailing | |
5446 | parameters. */ | |
5447 | if (((options & DMGL_PARAMS) != 0) && d_peek_char (&di) != '\0') | |
5448 | dc = NULL; | |
f26deb3d | 5449 | |
bd6946d1 | 5450 | #ifdef CP_DEMANGLE_DEBUG |
456cc5cf | 5451 | d_dump (dc, 0); |
bd6946d1 ILT |
5452 | #endif |
5453 | ||
456cc5cf SB |
5454 | status = (dc != NULL) |
5455 | ? cplus_demangle_print_callback (options, dc, callback, opaque) | |
5456 | : 0; | |
5457 | } | |
051664b0 | 5458 | |
456cc5cf SB |
5459 | return status; |
5460 | } | |
051664b0 | 5461 | |
456cc5cf SB |
5462 | /* Entry point for the demangler. If MANGLED is a g++ v3 ABI mangled |
5463 | name, return a buffer allocated with malloc holding the demangled | |
5464 | name. OPTIONS is the usual libiberty demangler options. On | |
5465 | success, this sets *PALC to the allocated size of the returned | |
5466 | buffer. On failure, this sets *PALC to 0 for a bad name, or 1 for | |
5467 | a memory allocation failure, and returns NULL. */ | |
2d6c4025 | 5468 | |
456cc5cf SB |
5469 | static char * |
5470 | d_demangle (const char *mangled, int options, size_t *palc) | |
5471 | { | |
5472 | struct d_growable_string dgs; | |
5473 | int status; | |
051664b0 | 5474 | |
456cc5cf SB |
5475 | d_growable_string_init (&dgs, 0); |
5476 | ||
5477 | status = d_demangle_callback (mangled, options, | |
5478 | d_growable_string_callback_adapter, &dgs); | |
5479 | if (status == 0) | |
5480 | { | |
5481 | free (dgs.buf); | |
5482 | *palc = 0; | |
5483 | return NULL; | |
5484 | } | |
5485 | ||
9b2adcdb | 5486 | *palc = dgs.allocation_failure ? 1 : dgs.alc; |
456cc5cf | 5487 | return dgs.buf; |
69afa80d AS |
5488 | } |
5489 | ||
bd7e6f2d | 5490 | #if defined(IN_LIBGCC2) || defined(IN_GLIBCPP_V3) |
bd6946d1 | 5491 | |
9486db4f | 5492 | extern char *__cxa_demangle (const char *, char *, size_t *, int *); |
051664b0 | 5493 | |
bd6946d1 ILT |
5494 | /* ia64 ABI-mandated entry point in the C++ runtime library for |
5495 | performing demangling. MANGLED_NAME is a NUL-terminated character | |
5496 | string containing the name to be demangled. | |
051664b0 AS |
5497 | |
5498 | OUTPUT_BUFFER is a region of memory, allocated with malloc, of | |
5499 | *LENGTH bytes, into which the demangled name is stored. If | |
5500 | OUTPUT_BUFFER is not long enough, it is expanded using realloc. | |
5501 | OUTPUT_BUFFER may instead be NULL; in that case, the demangled name | |
bd6946d1 | 5502 | is placed in a region of memory allocated with malloc. |
051664b0 | 5503 | |
456cc5cf | 5504 | If LENGTH is non-NULL, the length of the buffer containing the |
bd6946d1 | 5505 | demangled name, is placed in *LENGTH. |
051664b0 AS |
5506 | |
5507 | The return value is a pointer to the start of the NUL-terminated | |
5508 | demangled name, or NULL if the demangling fails. The caller is | |
bd6946d1 | 5509 | responsible for deallocating this memory using free. |
051664b0 AS |
5510 | |
5511 | *STATUS is set to one of the following values: | |
5512 | 0: The demangling operation succeeded. | |
bd6946d1 | 5513 | -1: A memory allocation failure occurred. |
051664b0 AS |
5514 | -2: MANGLED_NAME is not a valid name under the C++ ABI mangling rules. |
5515 | -3: One of the arguments is invalid. | |
5516 | ||
bd6946d1 | 5517 | The demangling is performed using the C++ ABI mangling rules, with |
051664b0 AS |
5518 | GNU extensions. */ |
5519 | ||
5520 | char * | |
9486db4f GDR |
5521 | __cxa_demangle (const char *mangled_name, char *output_buffer, |
5522 | size_t *length, int *status) | |
051664b0 | 5523 | { |
bd6946d1 ILT |
5524 | char *demangled; |
5525 | size_t alc; | |
051664b0 | 5526 | |
bd6946d1 ILT |
5527 | if (mangled_name == NULL) |
5528 | { | |
4a368ffd ILT |
5529 | if (status != NULL) |
5530 | *status = -3; | |
051664b0 AS |
5531 | return NULL; |
5532 | } | |
051664b0 | 5533 | |
bd6946d1 | 5534 | if (output_buffer != NULL && length == NULL) |
051664b0 | 5535 | { |
4a368ffd ILT |
5536 | if (status != NULL) |
5537 | *status = -3; | |
5538 | return NULL; | |
5539 | } | |
5540 | ||
dbd6ec2b | 5541 | demangled = d_demangle (mangled_name, DMGL_PARAMS | DMGL_TYPES, &alc); |
bd6946d1 ILT |
5542 | |
5543 | if (demangled == NULL) | |
051664b0 | 5544 | { |
4a368ffd ILT |
5545 | if (status != NULL) |
5546 | { | |
5547 | if (alc == 1) | |
5548 | *status = -1; | |
5549 | else | |
5550 | *status = -2; | |
5551 | } | |
051664b0 AS |
5552 | return NULL; |
5553 | } | |
bd6946d1 ILT |
5554 | |
5555 | if (output_buffer == NULL) | |
5556 | { | |
5557 | if (length != NULL) | |
5558 | *length = alc; | |
5559 | } | |
051664b0 | 5560 | else |
051664b0 | 5561 | { |
bd6946d1 ILT |
5562 | if (strlen (demangled) < *length) |
5563 | { | |
5564 | strcpy (output_buffer, demangled); | |
5565 | free (demangled); | |
5566 | demangled = output_buffer; | |
5567 | } | |
5568 | else | |
5569 | { | |
5570 | free (output_buffer); | |
5571 | *length = alc; | |
5572 | } | |
051664b0 | 5573 | } |
bd6946d1 | 5574 | |
4a368ffd ILT |
5575 | if (status != NULL) |
5576 | *status = 0; | |
bd6946d1 ILT |
5577 | |
5578 | return demangled; | |
051664b0 AS |
5579 | } |
5580 | ||
456cc5cf SB |
5581 | extern int __gcclibcxx_demangle_callback (const char *, |
5582 | void (*) | |
5583 | (const char *, size_t, void *), | |
5584 | void *); | |
5585 | ||
5586 | /* Alternative, allocationless entry point in the C++ runtime library | |
5587 | for performing demangling. MANGLED_NAME is a NUL-terminated character | |
5588 | string containing the name to be demangled. | |
5589 | ||
5590 | CALLBACK is a callback function, called with demangled string | |
5591 | segments as demangling progresses; it is called at least once, | |
5592 | but may be called more than once. OPAQUE is a generalized pointer | |
5593 | used as a callback argument. | |
5594 | ||
5595 | The return code is one of the following values, equivalent to | |
5596 | the STATUS values of __cxa_demangle() (excluding -1, since this | |
5597 | function performs no memory allocations): | |
5598 | 0: The demangling operation succeeded. | |
5599 | -2: MANGLED_NAME is not a valid name under the C++ ABI mangling rules. | |
5600 | -3: One of the arguments is invalid. | |
5601 | ||
5602 | The demangling is performed using the C++ ABI mangling rules, with | |
5603 | GNU extensions. */ | |
5604 | ||
5605 | int | |
5606 | __gcclibcxx_demangle_callback (const char *mangled_name, | |
5607 | void (*callback) (const char *, size_t, void *), | |
5608 | void *opaque) | |
5609 | { | |
5610 | int status; | |
5611 | ||
5612 | if (mangled_name == NULL || callback == NULL) | |
5613 | return -3; | |
5614 | ||
5615 | status = d_demangle_callback (mangled_name, DMGL_PARAMS | DMGL_TYPES, | |
5616 | callback, opaque); | |
5617 | if (status == 0) | |
5618 | return -2; | |
5619 | ||
5620 | return 0; | |
5621 | } | |
5622 | ||
bd7e6f2d | 5623 | #else /* ! (IN_LIBGCC2 || IN_GLIBCPP_V3) */ |
051664b0 | 5624 | |
bd6946d1 ILT |
5625 | /* Entry point for libiberty demangler. If MANGLED is a g++ v3 ABI |
5626 | mangled name, return a buffer allocated with malloc holding the | |
5627 | demangled name. Otherwise, return NULL. */ | |
69afa80d AS |
5628 | |
5629 | char * | |
456cc5cf | 5630 | cplus_demangle_v3 (const char *mangled, int options) |
69afa80d | 5631 | { |
bd6946d1 | 5632 | size_t alc; |
b5d1497d | 5633 | |
bd6946d1 | 5634 | return d_demangle (mangled, options, &alc); |
69afa80d AS |
5635 | } |
5636 | ||
456cc5cf SB |
5637 | int |
5638 | cplus_demangle_v3_callback (const char *mangled, int options, | |
5639 | demangle_callbackref callback, void *opaque) | |
5640 | { | |
5641 | return d_demangle_callback (mangled, options, callback, opaque); | |
5642 | } | |
5643 | ||
3b60dd8e BM |
5644 | /* Demangle a Java symbol. Java uses a subset of the V3 ABI C++ mangling |
5645 | conventions, but the output formatting is a little different. | |
456cc5cf SB |
5646 | This instructs the C++ demangler not to emit pointer characters ("*"), to |
5647 | use Java's namespace separator symbol ("." instead of "::"), and to output | |
5648 | JArray<TYPE> as TYPE[]. */ | |
3b60dd8e BM |
5649 | |
5650 | char * | |
456cc5cf | 5651 | java_demangle_v3 (const char *mangled) |
3b60dd8e | 5652 | { |
bd6946d1 | 5653 | size_t alc; |
3b60dd8e | 5654 | |
456cc5cf SB |
5655 | return d_demangle (mangled, DMGL_JAVA | DMGL_PARAMS | DMGL_RET_POSTFIX, &alc); |
5656 | } | |
a8f55e51 | 5657 | |
456cc5cf SB |
5658 | int |
5659 | java_demangle_v3_callback (const char *mangled, | |
5660 | demangle_callbackref callback, void *opaque) | |
5661 | { | |
5662 | return d_demangle_callback (mangled, | |
5663 | DMGL_JAVA | DMGL_PARAMS | DMGL_RET_POSTFIX, | |
5664 | callback, opaque); | |
3b60dd8e BM |
5665 | } |
5666 | ||
bd7e6f2d | 5667 | #endif /* IN_LIBGCC2 || IN_GLIBCPP_V3 */ |
051664b0 | 5668 | |
84326592 | 5669 | #ifndef IN_GLIBCPP_V3 |
bd6946d1 ILT |
5670 | |
5671 | /* Demangle a string in order to find out whether it is a constructor | |
5672 | or destructor. Return non-zero on success. Set *CTOR_KIND and | |
5673 | *DTOR_KIND appropriately. */ | |
5674 | ||
5675 | static int | |
9486db4f GDR |
5676 | is_ctor_or_dtor (const char *mangled, |
5677 | enum gnu_v3_ctor_kinds *ctor_kind, | |
5678 | enum gnu_v3_dtor_kinds *dtor_kind) | |
7dce2eff | 5679 | { |
bd6946d1 | 5680 | struct d_info di; |
5e777af5 | 5681 | struct demangle_component *dc; |
a51753e4 | 5682 | int ret; |
7dce2eff | 5683 | |
bd6946d1 ILT |
5684 | *ctor_kind = (enum gnu_v3_ctor_kinds) 0; |
5685 | *dtor_kind = (enum gnu_v3_dtor_kinds) 0; | |
5686 | ||
5e777af5 | 5687 | cplus_demangle_init_info (mangled, DMGL_GNU_V3, strlen (mangled), &di); |
7dce2eff | 5688 | |
2d6c4025 ILT |
5689 | { |
5690 | #ifdef CP_DYNAMIC_ARRAYS | |
5e777af5 ILT |
5691 | __extension__ struct demangle_component comps[di.num_comps]; |
5692 | __extension__ struct demangle_component *subs[di.num_subs]; | |
2d6c4025 | 5693 | |
456cc5cf SB |
5694 | di.comps = comps; |
5695 | di.subs = subs; | |
2d6c4025 | 5696 | #else |
456cc5cf SB |
5697 | di.comps = alloca (di.num_comps * sizeof (*di.comps)); |
5698 | di.subs = alloca (di.num_subs * sizeof (*di.subs)); | |
2d6c4025 | 5699 | #endif |
bd6946d1 | 5700 | |
5e777af5 | 5701 | dc = cplus_demangle_mangled_name (&di, 1); |
8d686df2 | 5702 | |
2d6c4025 ILT |
5703 | /* Note that because we did not pass DMGL_PARAMS, we don't expect |
5704 | to demangle the entire string. */ | |
7dce2eff | 5705 | |
2d6c4025 ILT |
5706 | ret = 0; |
5707 | while (dc != NULL) | |
5708 | { | |
5709 | switch (dc->type) | |
5710 | { | |
9eb85f27 JM |
5711 | /* These cannot appear on a constructor or destructor. */ |
5712 | case DEMANGLE_COMPONENT_RESTRICT_THIS: | |
5713 | case DEMANGLE_COMPONENT_VOLATILE_THIS: | |
5714 | case DEMANGLE_COMPONENT_CONST_THIS: | |
5715 | case DEMANGLE_COMPONENT_REFERENCE_THIS: | |
5716 | case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: | |
2d6c4025 ILT |
5717 | default: |
5718 | dc = NULL; | |
5719 | break; | |
5e777af5 ILT |
5720 | case DEMANGLE_COMPONENT_TYPED_NAME: |
5721 | case DEMANGLE_COMPONENT_TEMPLATE: | |
2d6c4025 ILT |
5722 | dc = d_left (dc); |
5723 | break; | |
5e777af5 ILT |
5724 | case DEMANGLE_COMPONENT_QUAL_NAME: |
5725 | case DEMANGLE_COMPONENT_LOCAL_NAME: | |
2d6c4025 ILT |
5726 | dc = d_right (dc); |
5727 | break; | |
5e777af5 | 5728 | case DEMANGLE_COMPONENT_CTOR: |
2d6c4025 ILT |
5729 | *ctor_kind = dc->u.s_ctor.kind; |
5730 | ret = 1; | |
5731 | dc = NULL; | |
5732 | break; | |
5e777af5 | 5733 | case DEMANGLE_COMPONENT_DTOR: |
2d6c4025 ILT |
5734 | *dtor_kind = dc->u.s_dtor.kind; |
5735 | ret = 1; | |
5736 | dc = NULL; | |
5737 | break; | |
5738 | } | |
5739 | } | |
2d6c4025 | 5740 | } |
a51753e4 ILT |
5741 | |
5742 | return ret; | |
7dce2eff JB |
5743 | } |
5744 | ||
bd6946d1 ILT |
5745 | /* Return whether NAME is the mangled form of a g++ V3 ABI constructor |
5746 | name. A non-zero return indicates the type of constructor. */ | |
7dce2eff | 5747 | |
7dce2eff | 5748 | enum gnu_v3_ctor_kinds |
9486db4f | 5749 | is_gnu_v3_mangled_ctor (const char *name) |
7dce2eff | 5750 | { |
bd6946d1 ILT |
5751 | enum gnu_v3_ctor_kinds ctor_kind; |
5752 | enum gnu_v3_dtor_kinds dtor_kind; | |
7dce2eff | 5753 | |
bd6946d1 | 5754 | if (! is_ctor_or_dtor (name, &ctor_kind, &dtor_kind)) |
f08b7eee | 5755 | return (enum gnu_v3_ctor_kinds) 0; |
bd6946d1 | 5756 | return ctor_kind; |
7dce2eff JB |
5757 | } |
5758 | ||
5759 | ||
bd6946d1 ILT |
5760 | /* Return whether NAME is the mangled form of a g++ V3 ABI destructor |
5761 | name. A non-zero return indicates the type of destructor. */ | |
5762 | ||
7dce2eff | 5763 | enum gnu_v3_dtor_kinds |
9486db4f | 5764 | is_gnu_v3_mangled_dtor (const char *name) |
7dce2eff | 5765 | { |
bd6946d1 ILT |
5766 | enum gnu_v3_ctor_kinds ctor_kind; |
5767 | enum gnu_v3_dtor_kinds dtor_kind; | |
7dce2eff | 5768 | |
bd6946d1 | 5769 | if (! is_ctor_or_dtor (name, &ctor_kind, &dtor_kind)) |
f08b7eee | 5770 | return (enum gnu_v3_dtor_kinds) 0; |
bd6946d1 | 5771 | return dtor_kind; |
7dce2eff JB |
5772 | } |
5773 | ||
bd6946d1 | 5774 | #endif /* IN_GLIBCPP_V3 */ |
7dce2eff | 5775 | |
69afa80d AS |
5776 | #ifdef STANDALONE_DEMANGLER |
5777 | ||
5778 | #include "getopt.h" | |
bd6946d1 ILT |
5779 | #include "dyn-string.h" |
5780 | ||
93079c81 | 5781 | static void print_usage (FILE* fp, int exit_value); |
69afa80d | 5782 | |
bd6946d1 ILT |
5783 | #define IS_ALPHA(CHAR) \ |
5784 | (((CHAR) >= 'a' && (CHAR) <= 'z') \ | |
5785 | || ((CHAR) >= 'A' && (CHAR) <= 'Z')) | |
69afa80d AS |
5786 | |
5787 | /* Non-zero if CHAR is a character than can occur in a mangled name. */ | |
3faa108c | 5788 | #define is_mangled_char(CHAR) \ |
31e0ab1f AS |
5789 | (IS_ALPHA (CHAR) || IS_DIGIT (CHAR) \ |
5790 | || (CHAR) == '_' || (CHAR) == '.' || (CHAR) == '$') | |
69afa80d AS |
5791 | |
5792 | /* The name of this program, as invoked. */ | |
5793 | const char* program_name; | |
5794 | ||
5795 | /* Prints usage summary to FP and then exits with EXIT_VALUE. */ | |
5796 | ||
5797 | static void | |
9486db4f | 5798 | print_usage (FILE* fp, int exit_value) |
69afa80d AS |
5799 | { |
5800 | fprintf (fp, "Usage: %s [options] [names ...]\n", program_name); | |
d01ce591 | 5801 | fprintf (fp, "Options:\n"); |
69afa80d | 5802 | fprintf (fp, " -h,--help Display this message.\n"); |
ad07f5e5 | 5803 | fprintf (fp, " -p,--no-params Don't display function parameters\n"); |
69afa80d AS |
5804 | fprintf (fp, " -v,--verbose Produce verbose demanglings.\n"); |
5805 | fprintf (fp, "If names are provided, they are demangled. Otherwise filters standard input.\n"); | |
5806 | ||
5807 | exit (exit_value); | |
5808 | } | |
5809 | ||
5810 | /* Option specification for getopt_long. */ | |
5e65297b | 5811 | static const struct option long_options[] = |
69afa80d | 5812 | { |
ad07f5e5 ILT |
5813 | { "help", no_argument, NULL, 'h' }, |
5814 | { "no-params", no_argument, NULL, 'p' }, | |
5815 | { "verbose", no_argument, NULL, 'v' }, | |
5816 | { NULL, no_argument, NULL, 0 }, | |
69afa80d AS |
5817 | }; |
5818 | ||
5819 | /* Main entry for a demangling filter executable. It will demangle | |
5820 | its command line arguments, if any. If none are provided, it will | |
5821 | filter stdin to stdout, replacing any recognized mangled C++ names | |
5822 | with their demangled equivalents. */ | |
5823 | ||
5824 | int | |
9486db4f | 5825 | main (int argc, char *argv[]) |
69afa80d | 5826 | { |
69afa80d AS |
5827 | int i; |
5828 | int opt_char; | |
bd6946d1 | 5829 | int options = DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES; |
69afa80d AS |
5830 | |
5831 | /* Use the program name of this program, as invoked. */ | |
5832 | program_name = argv[0]; | |
5833 | ||
5834 | /* Parse options. */ | |
5835 | do | |
5836 | { | |
ad07f5e5 | 5837 | opt_char = getopt_long (argc, argv, "hpv", long_options, NULL); |
69afa80d AS |
5838 | switch (opt_char) |
5839 | { | |
5840 | case '?': /* Unrecognized option. */ | |
5841 | print_usage (stderr, 1); | |
5842 | break; | |
5843 | ||
5844 | case 'h': | |
5845 | print_usage (stdout, 0); | |
5846 | break; | |
5847 | ||
ad07f5e5 ILT |
5848 | case 'p': |
5849 | options &= ~ DMGL_PARAMS; | |
5850 | break; | |
5851 | ||
69afa80d | 5852 | case 'v': |
bd6946d1 | 5853 | options |= DMGL_VERBOSE; |
69afa80d AS |
5854 | break; |
5855 | } | |
5856 | } | |
5857 | while (opt_char != -1); | |
5858 | ||
5859 | if (optind == argc) | |
5860 | /* No command line arguments were provided. Filter stdin. */ | |
5861 | { | |
5862 | dyn_string_t mangled = dyn_string_new (3); | |
bd6946d1 | 5863 | char *s; |
69afa80d AS |
5864 | |
5865 | /* Read all of input. */ | |
5866 | while (!feof (stdin)) | |
5867 | { | |
bd6946d1 | 5868 | char c; |
69afa80d AS |
5869 | |
5870 | /* Pile characters into mangled until we hit one that can't | |
5871 | occur in a mangled name. */ | |
5872 | c = getchar (); | |
5873 | while (!feof (stdin) && is_mangled_char (c)) | |
5874 | { | |
5875 | dyn_string_append_char (mangled, c); | |
5876 | if (feof (stdin)) | |
5877 | break; | |
5878 | c = getchar (); | |
5879 | } | |
5880 | ||
bd6946d1 | 5881 | if (dyn_string_length (mangled) > 0) |
051664b0 | 5882 | { |
4a368ffd ILT |
5883 | #ifdef IN_GLIBCPP_V3 |
5884 | s = __cxa_demangle (dyn_string_buf (mangled), NULL, NULL, NULL); | |
5885 | #else | |
bd6946d1 | 5886 | s = cplus_demangle_v3 (dyn_string_buf (mangled), options); |
4a368ffd | 5887 | #endif |
bd6946d1 ILT |
5888 | |
5889 | if (s != NULL) | |
5890 | { | |
5891 | fputs (s, stdout); | |
5892 | free (s); | |
5893 | } | |
5894 | else | |
5895 | { | |
5896 | /* It might not have been a mangled name. Print the | |
5897 | original text. */ | |
5898 | fputs (dyn_string_buf (mangled), stdout); | |
5899 | } | |
5900 | ||
5901 | dyn_string_clear (mangled); | |
051664b0 | 5902 | } |
69afa80d AS |
5903 | |
5904 | /* If we haven't hit EOF yet, we've read one character that | |
5905 | can't occur in a mangled name, so print it out. */ | |
5906 | if (!feof (stdin)) | |
5907 | putchar (c); | |
69afa80d AS |
5908 | } |
5909 | ||
5910 | dyn_string_delete (mangled); | |
69afa80d AS |
5911 | } |
5912 | else | |
5913 | /* Demangle command line arguments. */ | |
5914 | { | |
69afa80d AS |
5915 | /* Loop over command line arguments. */ |
5916 | for (i = optind; i < argc; ++i) | |
5917 | { | |
bd6946d1 | 5918 | char *s; |
4a368ffd ILT |
5919 | #ifdef IN_GLIBCPP_V3 |
5920 | int status; | |
5921 | #endif | |
bd6946d1 | 5922 | |
69afa80d | 5923 | /* Attempt to demangle. */ |
4a368ffd ILT |
5924 | #ifdef IN_GLIBCPP_V3 |
5925 | s = __cxa_demangle (argv[i], NULL, NULL, &status); | |
5926 | #else | |
bd6946d1 | 5927 | s = cplus_demangle_v3 (argv[i], options); |
4a368ffd | 5928 | #endif |
69afa80d AS |
5929 | |
5930 | /* If it worked, print the demangled name. */ | |
bd6946d1 | 5931 | if (s != NULL) |
051664b0 | 5932 | { |
bd6946d1 ILT |
5933 | printf ("%s\n", s); |
5934 | free (s); | |
051664b0 | 5935 | } |
bd6946d1 | 5936 | else |
4a368ffd ILT |
5937 | { |
5938 | #ifdef IN_GLIBCPP_V3 | |
5939 | fprintf (stderr, "Failed: %s (status %d)\n", argv[i], status); | |
5940 | #else | |
5941 | fprintf (stderr, "Failed: %s\n", argv[i]); | |
5942 | #endif | |
5943 | } | |
69afa80d | 5944 | } |
69afa80d AS |
5945 | } |
5946 | ||
5947 | return 0; | |
5948 | } | |
5949 | ||
5950 | #endif /* STANDALONE_DEMANGLER */ |