1 /* Demangler for GNU C++
2 Copyright 1989, 91, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
3 Written by James Clark (jjc@jclark.uucp)
4 Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
6 This file is part of the libiberty library.
7 Libiberty is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
12 Libiberty is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public
18 License along with libiberty; see the file COPYING.LIB. If
19 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* This file exports two functions; cplus_mangle_opname and cplus_demangle.
24 This file imports xmalloc and xrealloc, which are like malloc and
25 realloc except that they generate a fatal error if there is no
28 /* This file lives in both GCC and libiberty. When making changes, please
29 try not to break either. */
36 #include <sys/types.h>
48 #undef CURRENT_DEMANGLING_STYLE
49 #define CURRENT_DEMANGLING_STYLE work->options
51 extern char *xmalloc
PARAMS((unsigned));
52 extern char *xrealloc
PARAMS((char *, unsigned));
54 static const char *mystrstr
PARAMS ((const char *, const char *));
60 register const char *p
= s1
;
61 register int len
= strlen (s2
);
63 for (; (p
= strchr (p
, *s2
)) != 0; p
++)
65 if (strncmp (p
, s2
, len
) == 0)
73 /* In order to allow a single demangler executable to demangle strings
74 using various common values of CPLUS_MARKER, as well as any specific
75 one set at compile time, we maintain a string containing all the
76 commonly used ones, and check to see if the marker we are looking for
77 is in that string. CPLUS_MARKER is usually '$' on systems where the
78 assembler can deal with that. Where the assembler can't, it's usually
79 '.' (but on many systems '.' is used for other things). We put the
80 current defined CPLUS_MARKER first (which defaults to '$'), followed
81 by the next most common value, followed by an explicit '$' in case
82 the value of CPLUS_MARKER is not '$'.
84 We could avoid this if we could just get g++ to tell us what the actual
85 cplus marker character is as part of the debug information, perhaps by
86 ensuring that it is the character that terminates the gcc<n>_compiled
87 marker symbol (FIXME). */
89 #if !defined (CPLUS_MARKER)
90 #define CPLUS_MARKER '$'
93 enum demangling_styles current_demangling_style
= gnu_demangling
;
95 static char cplus_markers
[] = { CPLUS_MARKER
, '.', '$', '\0' };
98 set_cplus_marker_for_demangling (ch
)
101 cplus_markers
[0] = ch
;
104 typedef struct string
/* Beware: these aren't required to be */
105 { /* '\0' terminated. */
106 char *b
; /* pointer to start of string */
107 char *p
; /* pointer after last character */
108 char *e
; /* pointer after end of allocated space */
111 /* Stuff that is shared between sub-routines.
112 Using a shared structure allows cplus_demangle to be reentrant. */
128 int static_type
; /* A static member function */
129 int type_quals
; /* The type qualifiers. */
130 int dllimported
; /* Symbol imported from a PE DLL */
131 char **tmpl_argvec
; /* Template function arguments. */
132 int ntmpl_args
; /* The number of template function arguments. */
133 int forgetting_types
; /* Nonzero if we are not remembering the types
135 string
* previous_argument
; /* The last function argument demangled. */
136 int nrepeats
; /* The number of times to repeat the previous
140 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
141 #define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS)
143 static const struct optable
149 {"nw", " new", DMGL_ANSI
}, /* new (1.92, ansi) */
150 {"dl", " delete", DMGL_ANSI
}, /* new (1.92, ansi) */
151 {"new", " new", 0}, /* old (1.91, and 1.x) */
152 {"delete", " delete", 0}, /* old (1.91, and 1.x) */
153 {"vn", " new []", DMGL_ANSI
}, /* GNU, pending ansi */
154 {"vd", " delete []", DMGL_ANSI
}, /* GNU, pending ansi */
155 {"as", "=", DMGL_ANSI
}, /* ansi */
156 {"ne", "!=", DMGL_ANSI
}, /* old, ansi */
157 {"eq", "==", DMGL_ANSI
}, /* old, ansi */
158 {"ge", ">=", DMGL_ANSI
}, /* old, ansi */
159 {"gt", ">", DMGL_ANSI
}, /* old, ansi */
160 {"le", "<=", DMGL_ANSI
}, /* old, ansi */
161 {"lt", "<", DMGL_ANSI
}, /* old, ansi */
162 {"plus", "+", 0}, /* old */
163 {"pl", "+", DMGL_ANSI
}, /* ansi */
164 {"apl", "+=", DMGL_ANSI
}, /* ansi */
165 {"minus", "-", 0}, /* old */
166 {"mi", "-", DMGL_ANSI
}, /* ansi */
167 {"ami", "-=", DMGL_ANSI
}, /* ansi */
168 {"mult", "*", 0}, /* old */
169 {"ml", "*", DMGL_ANSI
}, /* ansi */
170 {"amu", "*=", DMGL_ANSI
}, /* ansi (ARM/Lucid) */
171 {"aml", "*=", DMGL_ANSI
}, /* ansi (GNU/g++) */
172 {"convert", "+", 0}, /* old (unary +) */
173 {"negate", "-", 0}, /* old (unary -) */
174 {"trunc_mod", "%", 0}, /* old */
175 {"md", "%", DMGL_ANSI
}, /* ansi */
176 {"amd", "%=", DMGL_ANSI
}, /* ansi */
177 {"trunc_div", "/", 0}, /* old */
178 {"dv", "/", DMGL_ANSI
}, /* ansi */
179 {"adv", "/=", DMGL_ANSI
}, /* ansi */
180 {"truth_andif", "&&", 0}, /* old */
181 {"aa", "&&", DMGL_ANSI
}, /* ansi */
182 {"truth_orif", "||", 0}, /* old */
183 {"oo", "||", DMGL_ANSI
}, /* ansi */
184 {"truth_not", "!", 0}, /* old */
185 {"nt", "!", DMGL_ANSI
}, /* ansi */
186 {"postincrement","++", 0}, /* old */
187 {"pp", "++", DMGL_ANSI
}, /* ansi */
188 {"postdecrement","--", 0}, /* old */
189 {"mm", "--", DMGL_ANSI
}, /* ansi */
190 {"bit_ior", "|", 0}, /* old */
191 {"or", "|", DMGL_ANSI
}, /* ansi */
192 {"aor", "|=", DMGL_ANSI
}, /* ansi */
193 {"bit_xor", "^", 0}, /* old */
194 {"er", "^", DMGL_ANSI
}, /* ansi */
195 {"aer", "^=", DMGL_ANSI
}, /* ansi */
196 {"bit_and", "&", 0}, /* old */
197 {"ad", "&", DMGL_ANSI
}, /* ansi */
198 {"aad", "&=", DMGL_ANSI
}, /* ansi */
199 {"bit_not", "~", 0}, /* old */
200 {"co", "~", DMGL_ANSI
}, /* ansi */
201 {"call", "()", 0}, /* old */
202 {"cl", "()", DMGL_ANSI
}, /* ansi */
203 {"alshift", "<<", 0}, /* old */
204 {"ls", "<<", DMGL_ANSI
}, /* ansi */
205 {"als", "<<=", DMGL_ANSI
}, /* ansi */
206 {"arshift", ">>", 0}, /* old */
207 {"rs", ">>", DMGL_ANSI
}, /* ansi */
208 {"ars", ">>=", DMGL_ANSI
}, /* ansi */
209 {"component", "->", 0}, /* old */
210 {"pt", "->", DMGL_ANSI
}, /* ansi; Lucid C++ form */
211 {"rf", "->", DMGL_ANSI
}, /* ansi; ARM/GNU form */
212 {"indirect", "*", 0}, /* old */
213 {"method_call", "->()", 0}, /* old */
214 {"addr", "&", 0}, /* old (unary &) */
215 {"array", "[]", 0}, /* old */
216 {"vc", "[]", DMGL_ANSI
}, /* ansi */
217 {"compound", ", ", 0}, /* old */
218 {"cm", ", ", DMGL_ANSI
}, /* ansi */
219 {"cond", "?:", 0}, /* old */
220 {"cn", "?:", DMGL_ANSI
}, /* pseudo-ansi */
221 {"max", ">?", 0}, /* old */
222 {"mx", ">?", DMGL_ANSI
}, /* pseudo-ansi */
223 {"min", "<?", 0}, /* old */
224 {"mn", "<?", DMGL_ANSI
}, /* pseudo-ansi */
225 {"nop", "", 0}, /* old (for operator=) */
226 {"rm", "->*", DMGL_ANSI
}, /* ansi */
227 {"sz", "sizeof ", DMGL_ANSI
} /* pseudo-ansi */
230 /* These values are used to indicate the various type varieties.
231 They are all non-zero so that they can be used as `success'
233 typedef enum type_kind_t
243 #define STRING_EMPTY(str) ((str) -> b == (str) -> p)
244 #define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
245 string_prepend(str, " ");}
246 #define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
247 string_append(str, " ");}
248 #define LEN_STRING(str) ( (STRING_EMPTY(str))?0:((str)->p - (str)->b))
250 /* The scope separator appropriate for the language being demangled. */
251 #define SCOPE_STRING(work) "::"
253 #define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */
254 #define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */
256 /* Prototypes for local functions */
259 mop_up
PARAMS ((struct work_stuff
*, string
*, int));
262 squangle_mop_up
PARAMS ((struct work_stuff
*));
266 demangle_method_args
PARAMS ((struct work_stuff
*, const char **, string
*));
270 internal_cplus_demangle
PARAMS ((struct work_stuff
*, const char *));
273 demangle_template_template_parm
PARAMS ((struct work_stuff
*work
,
274 const char **, string
*));
277 demangle_template
PARAMS ((struct work_stuff
*work
, const char **, string
*,
278 string
*, int, int));
281 arm_pt
PARAMS ((struct work_stuff
*, const char *, int, const char **,
285 demangle_arm_pt
PARAMS ((struct work_stuff
*, const char **, int, string
*));
288 demangle_class_name
PARAMS ((struct work_stuff
*, const char **, string
*));
291 demangle_qualified
PARAMS ((struct work_stuff
*, const char **, string
*,
295 demangle_class
PARAMS ((struct work_stuff
*, const char **, string
*));
298 demangle_fund_type
PARAMS ((struct work_stuff
*, const char **, string
*));
301 demangle_signature
PARAMS ((struct work_stuff
*, const char **, string
*));
304 demangle_prefix
PARAMS ((struct work_stuff
*, const char **, string
*));
307 gnu_special
PARAMS ((struct work_stuff
*, const char **, string
*));
310 arm_special
PARAMS ((const char **, string
*));
313 string_need
PARAMS ((string
*, int));
316 string_delete
PARAMS ((string
*));
319 string_init
PARAMS ((string
*));
322 string_clear
PARAMS ((string
*));
326 string_empty
PARAMS ((string
*));
330 string_append
PARAMS ((string
*, const char *));
333 string_appends
PARAMS ((string
*, string
*));
336 string_appendn
PARAMS ((string
*, const char *, int));
339 string_prepend
PARAMS ((string
*, const char *));
342 string_prependn
PARAMS ((string
*, const char *, int));
345 get_count
PARAMS ((const char **, int *));
348 consume_count
PARAMS ((const char **));
351 consume_count_with_underscores
PARAMS ((const char**));
354 demangle_args
PARAMS ((struct work_stuff
*, const char **, string
*));
357 demangle_nested_args
PARAMS ((struct work_stuff
*, const char**, string
*));
360 do_type
PARAMS ((struct work_stuff
*, const char **, string
*));
363 do_arg
PARAMS ((struct work_stuff
*, const char **, string
*));
366 demangle_function_name
PARAMS ((struct work_stuff
*, const char **, string
*,
370 remember_type
PARAMS ((struct work_stuff
*, const char *, int));
373 remember_Btype
PARAMS ((struct work_stuff
*, const char *, int, int));
376 register_Btype
PARAMS ((struct work_stuff
*));
379 remember_Ktype
PARAMS ((struct work_stuff
*, const char *, int));
382 forget_types
PARAMS ((struct work_stuff
*));
385 forget_B_and_K_types
PARAMS ((struct work_stuff
*));
388 string_prepends
PARAMS ((string
*, string
*));
391 demangle_template_value_parm
PARAMS ((struct work_stuff
*, const char**,
392 string
*, type_kind_t
));
394 /* There is a TYPE_QUAL value for each type qualifier. They can be
395 combined by bitwise-or to form the complete set of qualifiers for a
398 #define TYPE_UNQUALIFIED 0x0
399 #define TYPE_QUAL_CONST 0x1
400 #define TYPE_QUAL_VOLATILE 0x2
401 #define TYPE_QUAL_RESTRICT 0x4
404 code_for_qualifier
PARAMS ((char));
407 qualifier_string
PARAMS ((int));
410 demangle_qualifier
PARAMS ((char));
412 /* Translate count to integer, consuming tokens in the process.
413 Conversion terminates on the first non-digit character.
414 Trying to consume something that isn't a count results in
415 no consumption of input and a return of 0. */
423 while (isdigit ((unsigned char)**type
))
426 count
+= **type
- '0';
433 /* Like consume_count, but for counts that are preceded and followed
434 by '_' if they are greater than 10. Also, -1 is returned for
435 failure, since 0 can be a valid value. */
438 consume_count_with_underscores (mangled
)
439 const char **mangled
;
443 if (**mangled
== '_')
446 if (!isdigit ((unsigned char)**mangled
))
449 idx
= consume_count (mangled
);
450 if (**mangled
!= '_')
451 /* The trailing underscore was missing. */
458 if (**mangled
< '0' || **mangled
> '9')
461 idx
= **mangled
- '0';
468 /* C is the code for a type-qualifier. Return the TYPE_QUAL
469 corresponding to this qualifier. */
472 code_for_qualifier (c
)
478 return TYPE_QUAL_CONST
;
481 return TYPE_QUAL_VOLATILE
;
484 return TYPE_QUAL_RESTRICT
;
490 /* C was an invalid qualifier. */
494 /* Return the string corresponding to the qualifiers given by
498 qualifier_string (type_quals
)
503 case TYPE_UNQUALIFIED
:
506 case TYPE_QUAL_CONST
:
509 case TYPE_QUAL_VOLATILE
:
512 case TYPE_QUAL_RESTRICT
:
515 case TYPE_QUAL_CONST
| TYPE_QUAL_VOLATILE
:
516 return "const volatile";
518 case TYPE_QUAL_CONST
| TYPE_QUAL_RESTRICT
:
519 return "const __restrict";
521 case TYPE_QUAL_VOLATILE
| TYPE_QUAL_RESTRICT
:
522 return "volatile __restrict";
524 case TYPE_QUAL_CONST
| TYPE_QUAL_VOLATILE
| TYPE_QUAL_RESTRICT
:
525 return "const volatile __restrict";
531 /* TYPE_QUALS was an invalid qualifier set. */
535 /* C is the code for a type-qualifier. Return the string
536 corresponding to this qualifier. This function should only be
537 called with a valid qualifier code. */
540 demangle_qualifier (c
)
543 return qualifier_string (code_for_qualifier (c
));
547 cplus_demangle_opname (opname
, result
, options
)
554 struct work_stuff work
[1];
557 len
= strlen(opname
);
560 memset ((char *) work
, 0, sizeof (work
));
561 work
->options
= options
;
563 if (opname
[0] == '_' && opname
[1] == '_'
564 && opname
[2] == 'o' && opname
[3] == 'p')
567 /* type conversion operator. */
569 if (do_type (work
, &tem
, &type
))
571 strcat (result
, "operator ");
572 strncat (result
, type
.b
, type
.p
- type
.b
);
573 string_delete (&type
);
577 else if (opname
[0] == '_' && opname
[1] == '_'
578 && opname
[2] >= 'a' && opname
[2] <= 'z'
579 && opname
[3] >= 'a' && opname
[3] <= 'z')
581 if (opname
[4] == '\0')
585 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
587 if (strlen (optable
[i
].in
) == 2
588 && memcmp (optable
[i
].in
, opname
+ 2, 2) == 0)
590 strcat (result
, "operator");
591 strcat (result
, optable
[i
].out
);
599 if (opname
[2] == 'a' && opname
[5] == '\0')
603 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
605 if (strlen (optable
[i
].in
) == 3
606 && memcmp (optable
[i
].in
, opname
+ 2, 3) == 0)
608 strcat (result
, "operator");
609 strcat (result
, optable
[i
].out
);
620 && strchr (cplus_markers
, opname
[2]) != NULL
)
622 /* see if it's an assignment expression */
623 if (len
>= 10 /* op$assign_ */
624 && memcmp (opname
+ 3, "assign_", 7) == 0)
627 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
630 if ((int) strlen (optable
[i
].in
) == len1
631 && memcmp (optable
[i
].in
, opname
+ 10, len1
) == 0)
633 strcat (result
, "operator");
634 strcat (result
, optable
[i
].out
);
635 strcat (result
, "=");
644 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
647 if ((int) strlen (optable
[i
].in
) == len1
648 && memcmp (optable
[i
].in
, opname
+ 3, len1
) == 0)
650 strcat (result
, "operator");
651 strcat (result
, optable
[i
].out
);
658 else if (len
>= 5 && memcmp (opname
, "type", 4) == 0
659 && strchr (cplus_markers
, opname
[4]) != NULL
)
661 /* type conversion operator */
663 if (do_type (work
, &tem
, &type
))
665 strcat (result
, "operator ");
666 strncat (result
, type
.b
, type
.p
- type
.b
);
667 string_delete (&type
);
671 squangle_mop_up (work
);
675 /* Takes operator name as e.g. "++" and returns mangled
676 operator name (e.g. "postincrement_expr"), or NULL if not found.
678 If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
679 if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */
682 cplus_mangle_opname (opname
, options
)
689 len
= strlen (opname
);
690 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
692 if ((int) strlen (optable
[i
].out
) == len
693 && (options
& DMGL_ANSI
) == (optable
[i
].flags
& DMGL_ANSI
)
694 && memcmp (optable
[i
].out
, opname
, len
) == 0)
695 return optable
[i
].in
;
700 /* char *cplus_demangle (const char *mangled, int options)
702 If MANGLED is a mangled function name produced by GNU C++, then
703 a pointer to a malloced string giving a C++ representation
704 of the name will be returned; otherwise NULL will be returned.
705 It is the caller's responsibility to free the string which
708 The OPTIONS arg may contain one or more of the following bits:
710 DMGL_ANSI ANSI qualifiers such as `const' and `void' are
712 DMGL_PARAMS Function parameters are included.
716 cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)"
717 cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
718 cplus_demangle ("foo__1Ai", 0) => "A::foo"
720 cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)"
721 cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
722 cplus_demangle ("foo__1Afe", 0) => "A::foo"
724 Note that any leading underscores, or other such characters prepended by
725 the compilation system, are presumed to have already been stripped from
729 cplus_demangle (mangled
, options
)
734 struct work_stuff work
[1];
735 memset ((char *) work
, 0, sizeof (work
));
736 work
-> options
= options
;
737 if ((work
-> options
& DMGL_STYLE_MASK
) == 0)
738 work
-> options
|= (int) current_demangling_style
& DMGL_STYLE_MASK
;
740 ret
= internal_cplus_demangle (work
, mangled
);
741 squangle_mop_up (work
);
746 /* This function performs most of what cplus_demangle use to do, but
747 to be able to demangle a name with a B, K or n code, we need to
748 have a longer term memory of what types have been seen. The original
749 now intializes and cleans up the squangle code info, while internal
750 calls go directly to this routine to avoid resetting that info. */
753 internal_cplus_demangle (work
, mangled
)
754 struct work_stuff
*work
;
760 char *demangled
= NULL
;
762 s1
= work
->constructor
;
763 s2
= work
->destructor
;
764 s3
= work
->static_type
;
765 s4
= work
->type_quals
;
766 work
->constructor
= work
->destructor
= 0;
767 work
->type_quals
= TYPE_UNQUALIFIED
;
768 work
->dllimported
= 0;
770 if ((mangled
!= NULL
) && (*mangled
!= '\0'))
774 /* First check to see if gnu style demangling is active and if the
775 string to be demangled contains a CPLUS_MARKER. If so, attempt to
776 recognize one of the gnu special forms rather than looking for a
777 standard prefix. In particular, don't worry about whether there
778 is a "__" string in the mangled string. Consider "_$_5__foo" for
781 if ((AUTO_DEMANGLING
|| GNU_DEMANGLING
))
783 success
= gnu_special (work
, &mangled
, &decl
);
787 success
= demangle_prefix (work
, &mangled
, &decl
);
789 if (success
&& (*mangled
!= '\0'))
791 success
= demangle_signature (work
, &mangled
, &decl
);
793 if (work
->constructor
== 2)
795 string_prepend (&decl
, "global constructors keyed to ");
796 work
->constructor
= 0;
798 else if (work
->destructor
== 2)
800 string_prepend (&decl
, "global destructors keyed to ");
801 work
->destructor
= 0;
803 else if (work
->dllimported
== 1)
805 string_prepend (&decl
, "import stub for ");
806 work
->dllimported
= 0;
808 demangled
= mop_up (work
, &decl
, success
);
810 work
->constructor
= s1
;
811 work
->destructor
= s2
;
812 work
->static_type
= s3
;
813 work
->type_quals
= s4
;
818 /* Clear out and squangling related storage */
820 squangle_mop_up (work
)
821 struct work_stuff
*work
;
823 /* clean up the B and K type mangling types. */
824 forget_B_and_K_types (work
);
825 if (work
-> btypevec
!= NULL
)
827 free ((char *) work
-> btypevec
);
829 if (work
-> ktypevec
!= NULL
)
831 free ((char *) work
-> ktypevec
);
835 /* Clear out any mangled storage */
838 mop_up (work
, declp
, success
)
839 struct work_stuff
*work
;
843 char *demangled
= NULL
;
845 /* Discard the remembered types, if any. */
848 if (work
-> typevec
!= NULL
)
850 free ((char *) work
-> typevec
);
851 work
-> typevec
= NULL
;
853 if (work
->tmpl_argvec
)
857 for (i
= 0; i
< work
->ntmpl_args
; i
++)
858 if (work
->tmpl_argvec
[i
])
859 free ((char*) work
->tmpl_argvec
[i
]);
861 free ((char*) work
->tmpl_argvec
);
862 work
->tmpl_argvec
= NULL
;
864 if (work
->previous_argument
)
866 string_delete (work
->previous_argument
);
867 free ((char*) work
->previous_argument
);
870 /* If demangling was successful, ensure that the demangled string is null
871 terminated and return it. Otherwise, free the demangling decl. */
875 string_delete (declp
);
879 string_appendn (declp
, "", 1);
880 demangled
= declp
-> b
;
889 demangle_signature -- demangle the signature part of a mangled name
894 demangle_signature (struct work_stuff *work, const char **mangled,
899 Consume and demangle the signature portion of the mangled name.
901 DECLP is the string where demangled output is being built. At
902 entry it contains the demangled root name from the mangled name
903 prefix. I.E. either a demangled operator name or the root function
904 name. In some special cases, it may contain nothing.
906 *MANGLED points to the current unconsumed location in the mangled
907 name. As tokens are consumed and demangling is performed, the
908 pointer is updated to continuously point at the next token to
911 Demangling GNU style mangled names is nasty because there is no
912 explicit token that marks the start of the outermost function
916 demangle_signature (work
, mangled
, declp
)
917 struct work_stuff
*work
;
918 const char **mangled
;
924 int expect_return_type
= 0;
925 const char *oldmangled
= NULL
;
929 while (success
&& (**mangled
!= '\0'))
934 oldmangled
= *mangled
;
935 success
= demangle_qualified (work
, mangled
, declp
, 1, 0);
937 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
938 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
944 oldmangled
= *mangled
;
945 success
= demangle_qualified (work
, mangled
, declp
, 1, 0);
946 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
954 /* Static member function */
955 if (oldmangled
== NULL
)
957 oldmangled
= *mangled
;
960 work
-> static_type
= 1;
966 work
->type_quals
|= code_for_qualifier (**mangled
);
968 /* a qualified member function */
969 if (oldmangled
== NULL
)
970 oldmangled
= *mangled
;
974 case '0': case '1': case '2': case '3': case '4':
975 case '5': case '6': case '7': case '8': case '9':
976 if (oldmangled
== NULL
)
978 oldmangled
= *mangled
;
980 success
= demangle_class (work
, mangled
, declp
);
983 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
985 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
995 success
= do_type (work
, mangled
, &s
);
998 string_append (&s
, SCOPE_STRING (work
));
999 string_prepends (declp
, &s
);
1008 /* ARM style demangling includes a specific 'F' character after
1009 the class name. For GNU style, it is just implied. So we can
1010 safely just consume any 'F' at this point and be compatible
1011 with either style. */
1017 /* For lucid/ARM style we have to forget any types we might
1018 have remembered up to this point, since they were not argument
1019 types. GNU style considers all types seen as available for
1020 back references. See comment in demangle_args() */
1022 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
1024 forget_types (work
);
1026 success
= demangle_args (work
, mangled
, declp
);
1031 string_init(&trawname
);
1032 string_init(&tname
);
1033 if (oldmangled
== NULL
)
1035 oldmangled
= *mangled
;
1037 success
= demangle_template (work
, mangled
, &tname
,
1041 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
1043 string_append (&tname
, SCOPE_STRING (work
));
1045 string_prepends(declp
, &tname
);
1046 if (work
-> destructor
& 1)
1048 string_prepend (&trawname
, "~");
1049 string_appends (declp
, &trawname
);
1050 work
->destructor
-= 1;
1052 if ((work
->constructor
& 1) || (work
->destructor
& 1))
1054 string_appends (declp
, &trawname
);
1055 work
->constructor
-= 1;
1057 string_delete(&trawname
);
1058 string_delete(&tname
);
1064 if (GNU_DEMANGLING
&& expect_return_type
)
1066 /* Read the return type. */
1068 string_init (&return_type
);
1071 success
= do_type (work
, mangled
, &return_type
);
1072 APPEND_BLANK (&return_type
);
1074 string_prepends (declp
, &return_type
);
1075 string_delete (&return_type
);
1079 /* At the outermost level, we cannot have a return type specified,
1080 so if we run into another '_' at this point we are dealing with
1081 a mangled name that is either bogus, or has been mangled by
1082 some algorithm we don't know how to deal with. So just
1083 reject the entire demangling. */
1090 /* A G++ template function. Read the template arguments. */
1091 success
= demangle_template (work
, mangled
, declp
, 0, 0,
1093 if (!(work
->constructor
& 1))
1094 expect_return_type
= 1;
1103 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
1105 /* Assume we have stumbled onto the first outermost function
1106 argument token, and start processing args. */
1108 success
= demangle_args (work
, mangled
, declp
);
1112 /* Non-GNU demanglers use a specific token to mark the start
1113 of the outermost function argument tokens. Typically 'F',
1114 for ARM-demangling, for example. So if we find something
1115 we are not prepared for, it must be an error. */
1121 if (AUTO_DEMANGLING || GNU_DEMANGLING)
1124 if (success
&& expect_func
)
1127 success
= demangle_args (work
, mangled
, declp
);
1128 /* Since template include the mangling of their return types,
1129 we must set expect_func to 0 so that we don't try do
1130 demangle more arguments the next time we get here. */
1135 if (success
&& !func_done
)
1137 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
1139 /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
1140 bar__3fooi is 'foo::bar(int)'. We get here when we find the
1141 first case, and need to ensure that the '(void)' gets added to
1142 the current declp. Note that with ARM, the first case
1143 represents the name of a static data member 'foo::bar',
1144 which is in the current declp, so we leave it alone. */
1145 success
= demangle_args (work
, mangled
, declp
);
1148 if (success
&& PRINT_ARG_TYPES
)
1150 if (work
->static_type
)
1151 string_append (declp
, " static");
1152 if (work
->type_quals
!= TYPE_UNQUALIFIED
)
1154 APPEND_BLANK (declp
);
1155 string_append (declp
, qualifier_string (work
->type_quals
));
1165 demangle_method_args (work
, mangled
, declp
)
1166 struct work_stuff
*work
;
1167 const char **mangled
;
1172 if (work
-> static_type
)
1174 string_append (declp
, *mangled
+ 1);
1175 *mangled
+= strlen (*mangled
);
1180 success
= demangle_args (work
, mangled
, declp
);
1188 demangle_template_template_parm (work
, mangled
, tname
)
1189 struct work_stuff
*work
;
1190 const char **mangled
;
1199 string_append (tname
, "template <");
1200 /* get size of template parameter list */
1201 if (get_count (mangled
, &r
))
1203 for (i
= 0; i
< r
; i
++)
1207 string_append (tname
, ", ");
1210 /* Z for type parameters */
1211 if (**mangled
== 'Z')
1214 string_append (tname
, "class");
1216 /* z for template parameters */
1217 else if (**mangled
== 'z')
1221 demangle_template_template_parm (work
, mangled
, tname
);
1229 /* temp is initialized in do_type */
1230 success
= do_type (work
, mangled
, &temp
);
1233 string_appends (tname
, &temp
);
1235 string_delete(&temp
);
1245 if (tname
->p
[-1] == '>')
1246 string_append (tname
, " ");
1247 string_append (tname
, "> class");
1252 demangle_integral_value (work
, mangled
, s
)
1253 struct work_stuff
*work
;
1254 const char** mangled
;
1259 if (**mangled
== 'E')
1261 int need_operator
= 0;
1264 string_appendn (s
, "(", 1);
1266 while (success
&& **mangled
!= 'W' && **mangled
!= '\0')
1275 len
= strlen (*mangled
);
1278 i
< sizeof (optable
) / sizeof (optable
[0]);
1281 size_t l
= strlen (optable
[i
].in
);
1284 && memcmp (optable
[i
].in
, *mangled
, l
) == 0)
1286 string_appendn (s
, " ", 1);
1287 string_append (s
, optable
[i
].out
);
1288 string_appendn (s
, " ", 1);
1301 success
= demangle_template_value_parm (work
, mangled
, s
,
1305 if (**mangled
!= 'W')
1309 string_appendn (s
, ")", 1);
1313 else if (**mangled
== 'Q' || **mangled
== 'K')
1314 success
= demangle_qualified (work
, mangled
, s
, 0, 1);
1319 if (**mangled
== 'm')
1321 string_appendn (s
, "-", 1);
1324 while (isdigit ((unsigned char)**mangled
))
1326 string_appendn (s
, *mangled
, 1);
1336 demangle_template_value_parm (work
, mangled
, s
, tk
)
1337 struct work_stuff
*work
;
1338 const char **mangled
;
1344 if (**mangled
== 'Y')
1346 /* The next argument is a template parameter. */
1350 idx
= consume_count_with_underscores (mangled
);
1352 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
1353 || consume_count_with_underscores (mangled
) == -1)
1355 if (work
->tmpl_argvec
)
1356 string_append (s
, work
->tmpl_argvec
[idx
]);
1360 sprintf(buf
, "T%d", idx
);
1361 string_append (s
, buf
);
1364 else if (tk
== tk_integral
)
1365 success
= demangle_integral_value (work
, mangled
, s
);
1366 else if (tk
== tk_char
)
1370 if (**mangled
== 'm')
1372 string_appendn (s
, "-", 1);
1375 string_appendn (s
, "'", 1);
1376 val
= consume_count(mangled
);
1381 string_appendn (s
, &tmp
[0], 1);
1382 string_appendn (s
, "'", 1);
1384 else if (tk
== tk_bool
)
1386 int val
= consume_count (mangled
);
1388 string_appendn (s
, "false", 5);
1390 string_appendn (s
, "true", 4);
1394 else if (tk
== tk_real
)
1396 if (**mangled
== 'm')
1398 string_appendn (s
, "-", 1);
1401 while (isdigit ((unsigned char)**mangled
))
1403 string_appendn (s
, *mangled
, 1);
1406 if (**mangled
== '.') /* fraction */
1408 string_appendn (s
, ".", 1);
1410 while (isdigit ((unsigned char)**mangled
))
1412 string_appendn (s
, *mangled
, 1);
1416 if (**mangled
== 'e') /* exponent */
1418 string_appendn (s
, "e", 1);
1420 while (isdigit ((unsigned char)**mangled
))
1422 string_appendn (s
, *mangled
, 1);
1427 else if (tk
== tk_pointer
)
1429 int symbol_len
= consume_count (mangled
);
1430 if (symbol_len
== 0)
1432 if (symbol_len
== 0)
1433 string_appendn (s
, "0", 1);
1436 char *p
= xmalloc (symbol_len
+ 1), *q
;
1437 strncpy (p
, *mangled
, symbol_len
);
1438 p
[symbol_len
] = '\0';
1439 q
= internal_cplus_demangle (work
, p
);
1440 string_appendn (s
, "&", 1);
1441 /* FIXME: Pointer-to-member constants should get a
1442 qualifying class name here. */
1445 string_append (s
, q
);
1449 string_append (s
, p
);
1452 *mangled
+= symbol_len
;
1458 /* Demangle the template name in MANGLED. The full name of the
1459 template (e.g., S<int>) is placed in TNAME. The name without the
1460 template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is
1461 non-NULL. If IS_TYPE is nonzero, this template is a type template,
1462 not a function template. If both IS_TYPE and REMEMBER are nonzero,
1463 the tmeplate is remembered in the list of back-referenceable
1467 demangle_template (work
, mangled
, tname
, trawname
, is_type
, remember
)
1468 struct work_stuff
*work
;
1469 const char **mangled
;
1487 bindex
= register_Btype (work
);
1489 /* get template name */
1490 if (**mangled
== 'z')
1496 idx
= consume_count_with_underscores (mangled
);
1498 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
1499 || consume_count_with_underscores (mangled
) == -1)
1502 if (work
->tmpl_argvec
)
1504 string_append (tname
, work
->tmpl_argvec
[idx
]);
1506 string_append (trawname
, work
->tmpl_argvec
[idx
]);
1511 sprintf(buf
, "T%d", idx
);
1512 string_append (tname
, buf
);
1514 string_append (trawname
, buf
);
1519 if ((r
= consume_count (mangled
)) == 0
1520 || (int) strlen (*mangled
) < r
)
1524 string_appendn (tname
, *mangled
, r
);
1526 string_appendn (trawname
, *mangled
, r
);
1530 string_append (tname
, "<");
1531 /* get size of template parameter list */
1532 if (!get_count (mangled
, &r
))
1538 /* Create an array for saving the template argument values. */
1539 work
->tmpl_argvec
= (char**) xmalloc (r
* sizeof (char *));
1540 work
->ntmpl_args
= r
;
1541 for (i
= 0; i
< r
; i
++)
1542 work
->tmpl_argvec
[i
] = 0;
1544 for (i
= 0; i
< r
; i
++)
1548 string_append (tname
, ", ");
1550 /* Z for type parameters */
1551 if (**mangled
== 'Z')
1554 /* temp is initialized in do_type */
1555 success
= do_type (work
, mangled
, &temp
);
1558 string_appends (tname
, &temp
);
1562 /* Save the template argument. */
1563 int len
= temp
.p
- temp
.b
;
1564 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1565 memcpy (work
->tmpl_argvec
[i
], temp
.b
, len
);
1566 work
->tmpl_argvec
[i
][len
] = '\0';
1569 string_delete(&temp
);
1575 /* z for template parameters */
1576 else if (**mangled
== 'z')
1580 success
= demangle_template_template_parm (work
, mangled
, tname
);
1583 && (r2
= consume_count (mangled
)) > 0
1584 && (int) strlen (*mangled
) >= r2
)
1586 string_append (tname
, " ");
1587 string_appendn (tname
, *mangled
, r2
);
1590 /* Save the template argument. */
1592 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1593 memcpy (work
->tmpl_argvec
[i
], *mangled
, len
);
1594 work
->tmpl_argvec
[i
][len
] = '\0';
1608 /* otherwise, value parameter */
1610 /* temp is initialized in do_type */
1611 success
= do_type (work
, mangled
, &temp
);
1612 string_delete(&temp
);
1624 success
= demangle_template_value_parm (work
, mangled
, s
,
1625 (type_kind_t
) success
);
1637 int len
= s
->p
- s
->b
;
1638 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1639 memcpy (work
->tmpl_argvec
[i
], s
->b
, len
);
1640 work
->tmpl_argvec
[i
][len
] = '\0';
1642 string_appends (tname
, s
);
1649 if (tname
->p
[-1] == '>')
1650 string_append (tname
, " ");
1651 string_append (tname
, ">");
1654 if (is_type
&& remember
)
1655 remember_Btype (work
, tname
->b
, LEN_STRING (tname
), bindex
);
1658 if (work -> static_type)
1660 string_append (declp, *mangled + 1);
1661 *mangled += strlen (*mangled);
1666 success = demangle_args (work, mangled, declp);
1674 arm_pt (work
, mangled
, n
, anchor
, args
)
1675 struct work_stuff
*work
;
1676 const char *mangled
;
1678 const char **anchor
, **args
;
1681 if (ARM_DEMANGLING
&& (*anchor
= mystrstr (mangled
, "__pt__")))
1684 *args
= *anchor
+ 6;
1685 len
= consume_count (args
);
1686 if (*args
+ len
== mangled
+ n
&& **args
== '_')
1696 demangle_arm_pt (work
, mangled
, n
, declp
)
1697 struct work_stuff
*work
;
1698 const char **mangled
;
1704 const char *e
= *mangled
+ n
;
1707 if (arm_pt (work
, *mangled
, n
, &p
, &args
))
1711 string_appendn (declp
, *mangled
, p
- *mangled
);
1712 string_append (declp
, "<");
1713 /* should do error checking here */
1715 string_clear (&arg
);
1716 do_type (work
, &args
, &arg
);
1717 string_appends (declp
, &arg
);
1718 string_append (declp
, ",");
1720 string_delete (&arg
);
1722 string_append (declp
, ">");
1724 else if (n
>10 && strncmp (*mangled
, "_GLOBAL_", 8) == 0
1725 && (*mangled
)[9] == 'N'
1726 && (*mangled
)[8] == (*mangled
)[10]
1727 && strchr (cplus_markers
, (*mangled
)[8]))
1729 /* A member of the anonymous namespace. */
1730 string_append (declp
, "{anonymous}");
1734 string_appendn (declp
, *mangled
, n
);
1740 demangle_class_name (work
, mangled
, declp
)
1741 struct work_stuff
*work
;
1742 const char **mangled
;
1748 n
= consume_count (mangled
);
1749 if ((int) strlen (*mangled
) >= n
)
1751 demangle_arm_pt (work
, mangled
, n
, declp
);
1762 demangle_class -- demangle a mangled class sequence
1767 demangle_class (struct work_stuff *work, const char **mangled,
1772 DECLP points to the buffer into which demangling is being done.
1774 *MANGLED points to the current token to be demangled. On input,
1775 it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
1776 On exit, it points to the next token after the mangled class on
1777 success, or the first unconsumed token on failure.
1779 If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
1780 we are demangling a constructor or destructor. In this case
1781 we prepend "class::class" or "class::~class" to DECLP.
1783 Otherwise, we prepend "class::" to the current DECLP.
1785 Reset the constructor/destructor flags once they have been
1786 "consumed". This allows demangle_class to be called later during
1787 the same demangling, to do normal class demangling.
1789 Returns 1 if demangling is successful, 0 otherwise.
1794 demangle_class (work
, mangled
, declp
)
1795 struct work_stuff
*work
;
1796 const char **mangled
;
1803 string_init (&class_name
);
1804 btype
= register_Btype (work
);
1805 if (demangle_class_name (work
, mangled
, &class_name
))
1807 if ((work
->constructor
& 1) || (work
->destructor
& 1))
1809 string_prepends (declp
, &class_name
);
1810 if (work
-> destructor
& 1)
1812 string_prepend (declp
, "~");
1813 work
-> destructor
-= 1;
1817 work
-> constructor
-= 1;
1820 remember_Ktype (work
, class_name
.b
, LEN_STRING(&class_name
));
1821 remember_Btype (work
, class_name
.b
, LEN_STRING(&class_name
), btype
);
1822 string_prepend (declp
, SCOPE_STRING (work
));
1823 string_prepends (declp
, &class_name
);
1826 string_delete (&class_name
);
1834 demangle_prefix -- consume the mangled name prefix and find signature
1839 demangle_prefix (struct work_stuff *work, const char **mangled,
1844 Consume and demangle the prefix of the mangled name.
1846 DECLP points to the string buffer into which demangled output is
1847 placed. On entry, the buffer is empty. On exit it contains
1848 the root function name, the demangled operator name, or in some
1849 special cases either nothing or the completely demangled result.
1851 MANGLED points to the current pointer into the mangled name. As each
1852 token of the mangled name is consumed, it is updated. Upon entry
1853 the current mangled name pointer points to the first character of
1854 the mangled name. Upon exit, it should point to the first character
1855 of the signature if demangling was successful, or to the first
1856 unconsumed character if demangling of the prefix was unsuccessful.
1858 Returns 1 on success, 0 otherwise.
1862 demangle_prefix (work
, mangled
, declp
)
1863 struct work_stuff
*work
;
1864 const char **mangled
;
1871 if (strlen(*mangled
) > 6
1872 && (strncmp(*mangled
, "_imp__", 6) == 0
1873 || strncmp(*mangled
, "__imp_", 6) == 0))
1875 /* it's a symbol imported from a PE dynamic library. Check for both
1876 new style prefix _imp__ and legacy __imp_ used by older versions
1879 work
->dllimported
= 1;
1881 else if (strlen(*mangled
) >= 11 && strncmp(*mangled
, "_GLOBAL_", 8) == 0)
1883 char *marker
= strchr (cplus_markers
, (*mangled
)[8]);
1884 if (marker
!= NULL
&& *marker
== (*mangled
)[10])
1886 if ((*mangled
)[9] == 'D')
1888 /* it's a GNU global destructor to be executed at program exit */
1890 work
->destructor
= 2;
1891 if (gnu_special (work
, mangled
, declp
))
1894 else if ((*mangled
)[9] == 'I')
1896 /* it's a GNU global constructor to be executed at program init */
1898 work
->constructor
= 2;
1899 if (gnu_special (work
, mangled
, declp
))
1904 else if (ARM_DEMANGLING
&& strncmp(*mangled
, "__std__", 7) == 0)
1906 /* it's a ARM global destructor to be executed at program exit */
1908 work
->destructor
= 2;
1910 else if (ARM_DEMANGLING
&& strncmp(*mangled
, "__sti__", 7) == 0)
1912 /* it's a ARM global constructor to be executed at program initial */
1914 work
->constructor
= 2;
1917 /* This block of code is a reduction in strength time optimization
1919 scan = mystrstr (*mangled, "__"); */
1925 scan
= strchr (scan
, '_');
1926 } while (scan
!= NULL
&& *++scan
!= '_');
1928 if (scan
!= NULL
) --scan
;
1933 /* We found a sequence of two or more '_', ensure that we start at
1934 the last pair in the sequence. */
1935 i
= strspn (scan
, "_");
1946 else if (work
-> static_type
)
1948 if (!isdigit ((unsigned char)scan
[0]) && (scan
[0] != 't'))
1953 else if ((scan
== *mangled
)
1954 && (isdigit ((unsigned char)scan
[2]) || (scan
[2] == 'Q')
1955 || (scan
[2] == 't') || (scan
[2] == 'K') || (scan
[2] == 'H')))
1957 /* The ARM says nothing about the mangling of local variables.
1958 But cfront mangles local variables by prepending __<nesting_level>
1959 to them. As an extension to ARM demangling we handle this case. */
1960 if ((LUCID_DEMANGLING
|| ARM_DEMANGLING
)
1961 && isdigit ((unsigned char)scan
[2]))
1963 *mangled
= scan
+ 2;
1964 consume_count (mangled
);
1965 string_append (declp
, *mangled
);
1966 *mangled
+= strlen (*mangled
);
1971 /* A GNU style constructor starts with __[0-9Qt]. But cfront uses
1972 names like __Q2_3foo3bar for nested type names. So don't accept
1973 this style of constructor for cfront demangling. A GNU
1974 style member-template constructor starts with 'H'. */
1975 if (!(LUCID_DEMANGLING
|| ARM_DEMANGLING
))
1976 work
-> constructor
+= 1;
1977 *mangled
= scan
+ 2;
1980 else if ((scan
== *mangled
) && !isdigit ((unsigned char)scan
[2])
1981 && (scan
[2] != 't'))
1983 /* Mangled name starts with "__". Skip over any leading '_' characters,
1984 then find the next "__" that separates the prefix from the signature.
1986 if (!(ARM_DEMANGLING
|| LUCID_DEMANGLING
)
1987 || (arm_special (mangled
, declp
) == 0))
1989 while (*scan
== '_')
1993 if ((scan
= mystrstr (scan
, "__")) == NULL
|| (*(scan
+ 2) == '\0'))
1995 /* No separator (I.E. "__not_mangled"), or empty signature
1996 (I.E. "__not_mangled_either__") */
2001 demangle_function_name (work
, mangled
, declp
, scan
);
2005 else if (ARM_DEMANGLING
&& scan
[2] == 'p' && scan
[3] == 't')
2007 /* Cfront-style parameterized type. Handled later as a signature. */
2011 demangle_arm_pt (work
, mangled
, strlen (*mangled
), declp
);
2013 else if (*(scan
+ 2) != '\0')
2015 /* Mangled name does not start with "__" but does have one somewhere
2016 in there with non empty stuff after it. Looks like a global
2018 demangle_function_name (work
, mangled
, declp
, scan
);
2022 /* Doesn't look like a mangled name */
2026 if (!success
&& (work
->constructor
== 2 || work
->destructor
== 2))
2028 string_append (declp
, *mangled
);
2029 *mangled
+= strlen (*mangled
);
2039 gnu_special -- special handling of gnu mangled strings
2044 gnu_special (struct work_stuff *work, const char **mangled,
2050 Process some special GNU style mangling forms that don't fit
2051 the normal pattern. For example:
2053 _$_3foo (destructor for class foo)
2054 _vt$foo (foo virtual table)
2055 _vt$foo$bar (foo::bar virtual table)
2056 __vt_foo (foo virtual table, new style with thunks)
2057 _3foo$varname (static data member)
2058 _Q22rs2tu$vw (static data member)
2059 __t6vector1Zii (constructor with template)
2060 __thunk_4__$_7ostream (virtual function thunk)
2064 gnu_special (work
, mangled
, declp
)
2065 struct work_stuff
*work
;
2066 const char **mangled
;
2073 if ((*mangled
)[0] == '_'
2074 && strchr (cplus_markers
, (*mangled
)[1]) != NULL
2075 && (*mangled
)[2] == '_')
2077 /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
2079 work
-> destructor
+= 1;
2081 else if ((*mangled
)[0] == '_'
2082 && (((*mangled
)[1] == '_'
2083 && (*mangled
)[2] == 'v'
2084 && (*mangled
)[3] == 't'
2085 && (*mangled
)[4] == '_')
2086 || ((*mangled
)[1] == 'v'
2087 && (*mangled
)[2] == 't'
2088 && strchr (cplus_markers
, (*mangled
)[3]) != NULL
)))
2090 /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
2091 and create the decl. Note that we consume the entire mangled
2092 input string, which means that demangle_signature has no work
2094 if ((*mangled
)[2] == 'v')
2095 (*mangled
) += 5; /* New style, with thunks: "__vt_" */
2097 (*mangled
) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
2098 while (**mangled
!= '\0')
2100 p
= strpbrk (*mangled
, cplus_markers
);
2105 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
2108 success
= demangle_template (work
, mangled
, declp
, 0, 1,
2112 if (isdigit((unsigned char)*mangled
[0]))
2114 n
= consume_count(mangled
);
2115 /* We may be seeing a too-large size, or else a
2116 ".<digits>" indicating a static local symbol. In
2117 any case, declare victory and move on; *don't* try
2118 to use n to allocate. */
2119 if (n
> (int) strlen (*mangled
))
2127 n
= strcspn (*mangled
, cplus_markers
);
2129 string_appendn (declp
, *mangled
, n
);
2133 if (success
&& ((p
== NULL
) || (p
== *mangled
)))
2137 string_append (declp
, SCOPE_STRING (work
));
2148 string_append (declp
, " virtual table");
2150 else if ((*mangled
)[0] == '_'
2151 && (strchr("0123456789Qt", (*mangled
)[1]) != NULL
)
2152 && (p
= strpbrk (*mangled
, cplus_markers
)) != NULL
)
2154 /* static data member, "_3foo$varname" for example */
2160 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
2163 success
= demangle_template (work
, mangled
, declp
, 0, 1, 1);
2166 n
= consume_count (mangled
);
2167 string_appendn (declp
, *mangled
, n
);
2170 if (success
&& (p
== *mangled
))
2172 /* Consumed everything up to the cplus_marker, append the
2175 string_append (declp
, SCOPE_STRING (work
));
2176 n
= strlen (*mangled
);
2177 string_appendn (declp
, *mangled
, n
);
2185 else if (strncmp (*mangled
, "__thunk_", 8) == 0)
2187 int delta
= ((*mangled
) += 8, consume_count (mangled
));
2188 char *method
= internal_cplus_demangle (work
, ++*mangled
);
2192 sprintf (buf
, "virtual function thunk (delta:%d) for ", -delta
);
2193 string_append (declp
, buf
);
2194 string_append (declp
, method
);
2196 n
= strlen (*mangled
);
2204 else if (strncmp (*mangled
, "__t", 3) == 0
2205 && ((*mangled
)[3] == 'i' || (*mangled
)[3] == 'f'))
2207 p
= (*mangled
)[3] == 'i' ? " type_info node" : " type_info function";
2213 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
2216 success
= demangle_template (work
, mangled
, declp
, 0, 1, 1);
2219 success
= demangle_fund_type (work
, mangled
, declp
);
2222 if (success
&& **mangled
!= '\0')
2225 string_append (declp
, p
);
2238 arm_special -- special handling of ARM/lucid mangled strings
2243 arm_special (const char **mangled,
2249 Process some special ARM style mangling forms that don't fit
2250 the normal pattern. For example:
2252 __vtbl__3foo (foo virtual table)
2253 __vtbl__3foo__3bar (bar::foo virtual table)
2258 arm_special (mangled
, declp
)
2259 const char **mangled
;
2266 if (strncmp (*mangled
, ARM_VTABLE_STRING
, ARM_VTABLE_STRLEN
) == 0)
2268 /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
2269 and create the decl. Note that we consume the entire mangled
2270 input string, which means that demangle_signature has no work
2272 scan
= *mangled
+ ARM_VTABLE_STRLEN
;
2273 while (*scan
!= '\0') /* first check it can be demangled */
2275 n
= consume_count (&scan
);
2278 return (0); /* no good */
2281 if (scan
[0] == '_' && scan
[1] == '_')
2286 (*mangled
) += ARM_VTABLE_STRLEN
;
2287 while (**mangled
!= '\0')
2289 n
= consume_count (mangled
);
2290 string_prependn (declp
, *mangled
, n
);
2292 if ((*mangled
)[0] == '_' && (*mangled
)[1] == '_')
2294 string_prepend (declp
, "::");
2298 string_append (declp
, " virtual table");
2311 demangle_qualified -- demangle 'Q' qualified name strings
2316 demangle_qualified (struct work_stuff *, const char *mangled,
2317 string *result, int isfuncname, int append);
2321 Demangle a qualified name, such as "Q25Outer5Inner" which is
2322 the mangled form of "Outer::Inner". The demangled output is
2323 prepended or appended to the result string according to the
2324 state of the append flag.
2326 If isfuncname is nonzero, then the qualified name we are building
2327 is going to be used as a member function name, so if it is a
2328 constructor or destructor function, append an appropriate
2329 constructor or destructor name. I.E. for the above example,
2330 the result for use as a constructor is "Outer::Inner::Inner"
2331 and the result for use as a destructor is "Outer::Inner::~Inner".
2335 Numeric conversion is ASCII dependent (FIXME).
2340 demangle_qualified (work
, mangled
, result
, isfuncname
, append
)
2341 struct work_stuff
*work
;
2342 const char **mangled
;
2353 int bindex
= register_Btype (work
);
2355 /* We only make use of ISFUNCNAME if the entity is a constructor or
2357 isfuncname
= (isfuncname
2358 && ((work
->constructor
& 1) || (work
->destructor
& 1)));
2360 string_init (&temp
);
2361 string_init (&last_name
);
2363 if ((*mangled
)[0] == 'K')
2365 /* Squangling qualified name reuse */
2368 idx
= consume_count_with_underscores (mangled
);
2369 if (idx
== -1 || idx
>= work
-> numk
)
2372 string_append (&temp
, work
-> ktypevec
[idx
]);
2375 switch ((*mangled
)[1])
2378 /* GNU mangled name with more than 9 classes. The count is preceded
2379 by an underscore (to distinguish it from the <= 9 case) and followed
2380 by an underscore. */
2382 qualifiers
= atoi (p
);
2383 if (!isdigit ((unsigned char)*p
) || *p
== '0')
2386 /* Skip the digits. */
2387 while (isdigit ((unsigned char)*p
))
2405 /* The count is in a single digit. */
2406 num
[0] = (*mangled
)[1];
2408 qualifiers
= atoi (num
);
2410 /* If there is an underscore after the digit, skip it. This is
2411 said to be for ARM-qualified names, but the ARM makes no
2412 mention of such an underscore. Perhaps cfront uses one. */
2413 if ((*mangled
)[2] == '_')
2428 /* Pick off the names and collect them in the temp buffer in the order
2429 in which they are found, separated by '::'. */
2431 while (qualifiers
-- > 0)
2434 string_clear (&last_name
);
2436 if (*mangled
[0] == '_')
2439 if (*mangled
[0] == 't')
2441 /* Here we always append to TEMP since we will want to use
2442 the template name without the template parameters as a
2443 constructor or destructor name. The appropriate
2444 (parameter-less) value is returned by demangle_template
2445 in LAST_NAME. We do not remember the template type here,
2446 in order to match the G++ mangling algorithm. */
2447 success
= demangle_template(work
, mangled
, &temp
,
2452 else if (*mangled
[0] == 'K')
2456 idx
= consume_count_with_underscores (mangled
);
2457 if (idx
== -1 || idx
>= work
->numk
)
2460 string_append (&temp
, work
->ktypevec
[idx
]);
2463 if (!success
) break;
2467 success
= do_type (work
, mangled
, &last_name
);
2470 string_appends (&temp
, &last_name
);
2474 remember_Ktype (work
, temp
.b
, LEN_STRING (&temp
));
2477 string_append (&temp
, SCOPE_STRING (work
));
2480 remember_Btype (work
, temp
.b
, LEN_STRING (&temp
), bindex
);
2482 /* If we are using the result as a function name, we need to append
2483 the appropriate '::' separated constructor or destructor name.
2484 We do this here because this is the most convenient place, where
2485 we already have a pointer to the name and the length of the name. */
2489 string_append (&temp
, SCOPE_STRING (work
));
2490 if (work
-> destructor
& 1)
2491 string_append (&temp
, "~");
2492 string_appends (&temp
, &last_name
);
2495 /* Now either prepend the temp buffer to the result, or append it,
2496 depending upon the state of the append flag. */
2499 string_appends (result
, &temp
);
2502 if (!STRING_EMPTY (result
))
2503 string_append (&temp
, SCOPE_STRING (work
));
2504 string_prepends (result
, &temp
);
2507 string_delete (&last_name
);
2508 string_delete (&temp
);
2516 get_count -- convert an ascii count to integer, consuming tokens
2521 get_count (const char **type, int *count)
2525 Return 0 if no conversion is performed, 1 if a string is converted.
2529 get_count (type
, count
)
2536 if (!isdigit ((unsigned char)**type
))
2542 *count
= **type
- '0';
2544 if (isdigit ((unsigned char)**type
))
2554 while (isdigit ((unsigned char)*p
));
2565 /* RESULT will be initialised here; it will be freed on failure. The
2566 value returned is really a type_kind_t. */
2569 do_type (work
, mangled
, result
)
2570 struct work_stuff
*work
;
2571 const char **mangled
;
2578 const char *remembered_type
;
2581 type_kind_t tk
= tk_none
;
2583 string_init (&btype
);
2584 string_init (&decl
);
2585 string_init (result
);
2589 while (success
&& !done
)
2595 /* A pointer type */
2599 string_prepend (&decl
, "*");
2604 /* A reference type */
2607 string_prepend (&decl
, "&");
2616 if (!STRING_EMPTY (&decl
)
2617 && (decl
.b
[0] == '*' || decl
.b
[0] == '&'))
2619 string_prepend (&decl
, "(");
2620 string_append (&decl
, ")");
2622 string_append (&decl
, "[");
2623 if (**mangled
!= '_')
2624 success
= demangle_template_value_parm (work
, mangled
, &decl
,
2626 if (**mangled
== '_')
2628 string_append (&decl
, "]");
2632 /* A back reference to a previously seen type */
2635 if (!get_count (mangled
, &n
) || n
>= work
-> ntypes
)
2641 remembered_type
= work
-> typevec
[n
];
2642 mangled
= &remembered_type
;
2649 if (!STRING_EMPTY (&decl
)
2650 && (decl
.b
[0] == '*' || decl
.b
[0] == '&'))
2652 string_prepend (&decl
, "(");
2653 string_append (&decl
, ")");
2655 /* After picking off the function args, we expect to either find the
2656 function return type (preceded by an '_') or the end of the
2658 if (!demangle_nested_args (work
, mangled
, &decl
)
2659 || (**mangled
!= '_' && **mangled
!= '\0'))
2664 if (success
&& (**mangled
== '_'))
2671 type_quals
= TYPE_UNQUALIFIED
;
2673 member
= **mangled
== 'M';
2675 if (!isdigit ((unsigned char)**mangled
) && **mangled
!= 't')
2681 string_append (&decl
, ")");
2682 string_prepend (&decl
, SCOPE_STRING (work
));
2683 if (isdigit ((unsigned char)**mangled
))
2685 n
= consume_count (mangled
);
2686 if ((int) strlen (*mangled
) < n
)
2691 string_prependn (&decl
, *mangled
, n
);
2697 string_init (&temp
);
2698 success
= demangle_template (work
, mangled
, &temp
,
2702 string_prependn (&decl
, temp
.b
, temp
.p
- temp
.b
);
2703 string_clear (&temp
);
2708 string_prepend (&decl
, "(");
2716 type_quals
|= code_for_qualifier (**mangled
);
2724 if (*(*mangled
)++ != 'F')
2730 if ((member
&& !demangle_nested_args (work
, mangled
, &decl
))
2731 || **mangled
!= '_')
2737 if (! PRINT_ANSI_QUALIFIERS
)
2741 if (type_quals
!= TYPE_UNQUALIFIED
)
2743 APPEND_BLANK (&decl
);
2744 string_append (&decl
, qualifier_string (type_quals
));
2755 if (PRINT_ANSI_QUALIFIERS
)
2757 if (!STRING_EMPTY (&decl
))
2758 string_prepend (&decl
, " ");
2760 string_prepend (&decl
, demangle_qualifier (**mangled
));
2775 if (success
) switch (**mangled
)
2777 /* A qualified name, such as "Outer::Inner". */
2781 success
= demangle_qualified (work
, mangled
, result
, 0, 1);
2785 /* A back reference to a previously seen squangled type */
2788 if (!get_count (mangled
, &n
) || n
>= work
-> numb
)
2791 string_append (result
, work
->btypevec
[n
]);
2796 /* A template parm. We substitute the corresponding argument. */
2801 idx
= consume_count_with_underscores (mangled
);
2804 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
2805 || consume_count_with_underscores (mangled
) == -1)
2811 if (work
->tmpl_argvec
)
2812 string_append (result
, work
->tmpl_argvec
[idx
]);
2816 sprintf(buf
, "T%d", idx
);
2817 string_append (result
, buf
);
2825 success
= demangle_fund_type (work
, mangled
, result
);
2827 tk
= (type_kind_t
) success
;
2833 if (!STRING_EMPTY (&decl
))
2835 string_append (result
, " ");
2836 string_appends (result
, &decl
);
2840 string_delete (result
);
2841 string_delete (&decl
);
2844 /* Assume an integral type, if we're not sure. */
2845 return (int) ((tk
== tk_none
) ? tk_integral
: tk
);
2850 /* Given a pointer to a type string that represents a fundamental type
2851 argument (int, long, unsigned int, etc) in TYPE, a pointer to the
2852 string in which the demangled output is being built in RESULT, and
2853 the WORK structure, decode the types and add them to the result.
2858 "Sl" => "signed long"
2859 "CUs" => "const unsigned short"
2861 The value returned is really a type_kind_t. */
2864 demangle_fund_type (work
, mangled
, result
)
2865 struct work_stuff
*work
;
2866 const char **mangled
;
2872 type_kind_t tk
= tk_integral
;
2874 string_init (&btype
);
2876 /* First pick off any type qualifiers. There can be more than one. */
2886 if (PRINT_ANSI_QUALIFIERS
)
2888 APPEND_BLANK (result
);
2889 string_append (result
, demangle_qualifier (**mangled
));
2894 APPEND_BLANK (result
);
2895 string_append (result
, "unsigned");
2897 case 'S': /* signed char only */
2899 APPEND_BLANK (result
);
2900 string_append (result
, "signed");
2904 APPEND_BLANK (result
);
2905 string_append (result
, "__complex");
2913 /* Now pick off the fundamental type. There can be only one. */
2922 APPEND_BLANK (result
);
2923 string_append (result
, "void");
2927 APPEND_BLANK (result
);
2928 string_append (result
, "long long");
2932 APPEND_BLANK (result
);
2933 string_append (result
, "long");
2937 APPEND_BLANK (result
);
2938 string_append (result
, "int");
2942 APPEND_BLANK (result
);
2943 string_append (result
, "short");
2947 APPEND_BLANK (result
);
2948 string_append (result
, "bool");
2953 APPEND_BLANK (result
);
2954 string_append (result
, "char");
2959 APPEND_BLANK (result
);
2960 string_append (result
, "wchar_t");
2965 APPEND_BLANK (result
);
2966 string_append (result
, "long double");
2971 APPEND_BLANK (result
);
2972 string_append (result
, "double");
2977 APPEND_BLANK (result
);
2978 string_append (result
, "float");
2983 if (!isdigit ((unsigned char)**mangled
))
2989 /* An explicit type, such as "6mytype" or "7integer" */
3001 int bindex
= register_Btype (work
);
3003 string_init (&btype
);
3004 if (demangle_class_name (work
, mangled
, &btype
)) {
3005 remember_Btype (work
, btype
.b
, LEN_STRING (&btype
), bindex
);
3006 APPEND_BLANK (result
);
3007 string_appends (result
, &btype
);
3011 string_delete (&btype
);
3016 success
= demangle_template (work
, mangled
, &btype
, 0, 1, 1);
3017 string_appends (result
, &btype
);
3025 return success
? ((int) tk
) : 0;
3028 /* Demangle the next argument, given by MANGLED into RESULT, which
3029 *should be an uninitialized* string. It will be initialized here,
3030 and free'd should anything go wrong. */
3033 do_arg (work
, mangled
, result
)
3034 struct work_stuff
*work
;
3035 const char **mangled
;
3038 /* Remember where we started so that we can record the type, for
3039 non-squangling type remembering. */
3040 const char *start
= *mangled
;
3042 string_init (result
);
3044 if (work
->nrepeats
> 0)
3048 if (work
->previous_argument
== 0)
3051 /* We want to reissue the previous type in this argument list. */
3052 string_appends (result
, work
->previous_argument
);
3056 if (**mangled
== 'n')
3058 /* A squangling-style repeat. */
3060 work
->nrepeats
= consume_count(mangled
);
3062 if (work
->nrepeats
== 0)
3063 /* This was not a repeat count after all. */
3066 if (work
->nrepeats
> 9)
3068 if (**mangled
!= '_')
3069 /* The repeat count should be followed by an '_' in this
3076 /* Now, the repeat is all set up. */
3077 return do_arg (work
, mangled
, result
);
3080 /* Save the result in WORK->previous_argument so that we can find it
3081 if it's repeated. Note that saving START is not good enough: we
3082 do not want to add additional types to the back-referenceable
3083 type vector when processing a repeated type. */
3084 if (work
->previous_argument
)
3085 string_clear (work
->previous_argument
);
3088 work
->previous_argument
= (string
*) xmalloc (sizeof (string
));
3089 string_init (work
->previous_argument
);
3092 if (!do_type (work
, mangled
, work
->previous_argument
))
3095 string_appends (result
, work
->previous_argument
);
3097 remember_type (work
, start
, *mangled
- start
);
3102 remember_type (work
, start
, len
)
3103 struct work_stuff
*work
;
3109 if (work
->forgetting_types
)
3112 if (work
-> ntypes
>= work
-> typevec_size
)
3114 if (work
-> typevec_size
== 0)
3116 work
-> typevec_size
= 3;
3118 = (char **) xmalloc (sizeof (char *) * work
-> typevec_size
);
3122 work
-> typevec_size
*= 2;
3124 = (char **) xrealloc ((char *)work
-> typevec
,
3125 sizeof (char *) * work
-> typevec_size
);
3128 tem
= xmalloc (len
+ 1);
3129 memcpy (tem
, start
, len
);
3131 work
-> typevec
[work
-> ntypes
++] = tem
;
3135 /* Remember a K type class qualifier. */
3137 remember_Ktype (work
, start
, len
)
3138 struct work_stuff
*work
;
3144 if (work
-> numk
>= work
-> ksize
)
3146 if (work
-> ksize
== 0)
3150 = (char **) xmalloc (sizeof (char *) * work
-> ksize
);
3156 = (char **) xrealloc ((char *)work
-> ktypevec
,
3157 sizeof (char *) * work
-> ksize
);
3160 tem
= xmalloc (len
+ 1);
3161 memcpy (tem
, start
, len
);
3163 work
-> ktypevec
[work
-> numk
++] = tem
;
3166 /* Register a B code, and get an index for it. B codes are registered
3167 as they are seen, rather than as they are completed, so map<temp<char> >
3168 registers map<temp<char> > as B0, and temp<char> as B1 */
3171 register_Btype (work
)
3172 struct work_stuff
*work
;
3176 if (work
-> numb
>= work
-> bsize
)
3178 if (work
-> bsize
== 0)
3182 = (char **) xmalloc (sizeof (char *) * work
-> bsize
);
3188 = (char **) xrealloc ((char *)work
-> btypevec
,
3189 sizeof (char *) * work
-> bsize
);
3192 ret
= work
-> numb
++;
3193 work
-> btypevec
[ret
] = NULL
;
3197 /* Store a value into a previously registered B code type. */
3200 remember_Btype (work
, start
, len
, index
)
3201 struct work_stuff
*work
;
3207 tem
= xmalloc (len
+ 1);
3208 memcpy (tem
, start
, len
);
3210 work
-> btypevec
[index
] = tem
;
3213 /* Lose all the info related to B and K type codes. */
3215 forget_B_and_K_types (work
)
3216 struct work_stuff
*work
;
3220 while (work
-> numk
> 0)
3222 i
= --(work
-> numk
);
3223 if (work
-> ktypevec
[i
] != NULL
)
3225 free (work
-> ktypevec
[i
]);
3226 work
-> ktypevec
[i
] = NULL
;
3230 while (work
-> numb
> 0)
3232 i
= --(work
-> numb
);
3233 if (work
-> btypevec
[i
] != NULL
)
3235 free (work
-> btypevec
[i
]);
3236 work
-> btypevec
[i
] = NULL
;
3240 /* Forget the remembered types, but not the type vector itself. */
3244 struct work_stuff
*work
;
3248 while (work
-> ntypes
> 0)
3250 i
= --(work
-> ntypes
);
3251 if (work
-> typevec
[i
] != NULL
)
3253 free (work
-> typevec
[i
]);
3254 work
-> typevec
[i
] = NULL
;
3259 /* Process the argument list part of the signature, after any class spec
3260 has been consumed, as well as the first 'F' character (if any). For
3263 "__als__3fooRT0" => process "RT0"
3264 "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i"
3266 DECLP must be already initialised, usually non-empty. It won't be freed
3269 Note that g++ differs significantly from ARM and lucid style mangling
3270 with regards to references to previously seen types. For example, given
3271 the source fragment:
3275 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
3278 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3279 void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3281 g++ produces the names:
3286 while lcc (and presumably other ARM style compilers as well) produces:
3288 foo__FiR3fooT1T2T1T2
3289 __ct__3fooFiR3fooT1T2T1T2
3291 Note that g++ bases its type numbers starting at zero and counts all
3292 previously seen types, while lucid/ARM bases its type numbers starting
3293 at one and only considers types after it has seen the 'F' character
3294 indicating the start of the function args. For lucid/ARM style, we
3295 account for this difference by discarding any previously seen types when
3296 we see the 'F' character, and subtracting one from the type number
3302 demangle_args (work
, mangled
, declp
)
3303 struct work_stuff
*work
;
3304 const char **mangled
;
3314 if (PRINT_ARG_TYPES
)
3316 string_append (declp
, "(");
3317 if (**mangled
== '\0')
3319 string_append (declp
, "void");
3323 while ((**mangled
!= '_' && **mangled
!= '\0' && **mangled
!= 'e')
3324 || work
->nrepeats
> 0)
3326 if ((**mangled
== 'N') || (**mangled
== 'T'))
3328 temptype
= *(*mangled
)++;
3330 if (temptype
== 'N')
3332 if (!get_count (mangled
, &r
))
3341 if (ARM_DEMANGLING
&& work
-> ntypes
>= 10)
3343 /* If we have 10 or more types we might have more than a 1 digit
3344 index so we'll have to consume the whole count here. This
3345 will lose if the next thing is a type name preceded by a
3346 count but it's impossible to demangle that case properly
3347 anyway. Eg if we already have 12 types is T12Pc "(..., type1,
3348 Pc, ...)" or "(..., type12, char *, ...)" */
3349 if ((t
= consume_count(mangled
)) == 0)
3356 if (!get_count (mangled
, &t
))
3361 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
3365 /* Validate the type index. Protect against illegal indices from
3366 malformed type strings. */
3367 if ((t
< 0) || (t
>= work
-> ntypes
))
3371 while (work
->nrepeats
> 0 || --r
>= 0)
3373 tem
= work
-> typevec
[t
];
3374 if (need_comma
&& PRINT_ARG_TYPES
)
3376 string_append (declp
, ", ");
3378 if (!do_arg (work
, &tem
, &arg
))
3382 if (PRINT_ARG_TYPES
)
3384 string_appends (declp
, &arg
);
3386 string_delete (&arg
);
3392 if (need_comma
&& PRINT_ARG_TYPES
)
3393 string_append (declp
, ", ");
3394 if (!do_arg (work
, mangled
, &arg
))
3396 if (PRINT_ARG_TYPES
)
3397 string_appends (declp
, &arg
);
3398 string_delete (&arg
);
3403 if (**mangled
== 'e')
3406 if (PRINT_ARG_TYPES
)
3410 string_append (declp
, ",");
3412 string_append (declp
, "...");
3416 if (PRINT_ARG_TYPES
)
3418 string_append (declp
, ")");
3423 /* Like demangle_args, but for demangling the argument lists of function
3424 and method pointers or references, not top-level declarations. */
3427 demangle_nested_args (work
, mangled
, declp
)
3428 struct work_stuff
*work
;
3429 const char **mangled
;
3432 string
* saved_previous_argument
;
3436 /* The G++ name-mangling algorithm does not remember types on nested
3437 argument lists, unless -fsquangling is used, and in that case the
3438 type vector updated by remember_type is not used. So, we turn
3439 off remembering of types here. */
3440 ++work
->forgetting_types
;
3442 /* For the repeat codes used with -fsquangling, we must keep track of
3443 the last argument. */
3444 saved_previous_argument
= work
->previous_argument
;
3445 saved_nrepeats
= work
->nrepeats
;
3446 work
->previous_argument
= 0;
3449 /* Actually demangle the arguments. */
3450 result
= demangle_args (work
, mangled
, declp
);
3452 /* Restore the previous_argument field. */
3453 if (work
->previous_argument
)
3454 string_delete (work
->previous_argument
);
3455 work
->previous_argument
= saved_previous_argument
;
3456 work
->nrepeats
= saved_nrepeats
;
3462 demangle_function_name (work
, mangled
, declp
, scan
)
3463 struct work_stuff
*work
;
3464 const char **mangled
;
3472 string_appendn (declp
, (*mangled
), scan
- (*mangled
));
3473 string_need (declp
, 1);
3474 *(declp
-> p
) = '\0';
3476 /* Consume the function name, including the "__" separating the name
3477 from the signature. We are guaranteed that SCAN points to the
3480 (*mangled
) = scan
+ 2;
3482 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
3485 /* See if we have an ARM style constructor or destructor operator.
3486 If so, then just record it, clear the decl, and return.
3487 We can't build the actual constructor/destructor decl until later,
3488 when we recover the class name from the signature. */
3490 if (strcmp (declp
-> b
, "__ct") == 0)
3492 work
-> constructor
+= 1;
3493 string_clear (declp
);
3496 else if (strcmp (declp
-> b
, "__dt") == 0)
3498 work
-> destructor
+= 1;
3499 string_clear (declp
);
3504 if (declp
->p
- declp
->b
>= 3
3505 && declp
->b
[0] == 'o'
3506 && declp
->b
[1] == 'p'
3507 && strchr (cplus_markers
, declp
->b
[2]) != NULL
)
3509 /* see if it's an assignment expression */
3510 if (declp
->p
- declp
->b
>= 10 /* op$assign_ */
3511 && memcmp (declp
->b
+ 3, "assign_", 7) == 0)
3513 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3515 int len
= declp
->p
- declp
->b
- 10;
3516 if ((int) strlen (optable
[i
].in
) == len
3517 && memcmp (optable
[i
].in
, declp
->b
+ 10, len
) == 0)
3519 string_clear (declp
);
3520 string_append (declp
, "operator");
3521 string_append (declp
, optable
[i
].out
);
3522 string_append (declp
, "=");
3529 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3531 int len
= declp
->p
- declp
->b
- 3;
3532 if ((int) strlen (optable
[i
].in
) == len
3533 && memcmp (optable
[i
].in
, declp
->b
+ 3, len
) == 0)
3535 string_clear (declp
);
3536 string_append (declp
, "operator");
3537 string_append (declp
, optable
[i
].out
);
3543 else if (declp
->p
- declp
->b
>= 5 && memcmp (declp
->b
, "type", 4) == 0
3544 && strchr (cplus_markers
, declp
->b
[4]) != NULL
)
3546 /* type conversion operator */
3548 if (do_type (work
, &tem
, &type
))
3550 string_clear (declp
);
3551 string_append (declp
, "operator ");
3552 string_appends (declp
, &type
);
3553 string_delete (&type
);
3556 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
3557 && declp
->b
[2] == 'o' && declp
->b
[3] == 'p')
3560 /* type conversion operator. */
3562 if (do_type (work
, &tem
, &type
))
3564 string_clear (declp
);
3565 string_append (declp
, "operator ");
3566 string_appends (declp
, &type
);
3567 string_delete (&type
);
3570 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
3571 && declp
->b
[2] >= 'a' && declp
->b
[2] <= 'z'
3572 && declp
->b
[3] >= 'a' && declp
->b
[3] <= 'z')
3574 if (declp
->b
[4] == '\0')
3577 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3579 if (strlen (optable
[i
].in
) == 2
3580 && memcmp (optable
[i
].in
, declp
->b
+ 2, 2) == 0)
3582 string_clear (declp
);
3583 string_append (declp
, "operator");
3584 string_append (declp
, optable
[i
].out
);
3591 if (declp
->b
[2] == 'a' && declp
->b
[5] == '\0')
3594 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3596 if (strlen (optable
[i
].in
) == 3
3597 && memcmp (optable
[i
].in
, declp
->b
+ 2, 3) == 0)
3599 string_clear (declp
);
3600 string_append (declp
, "operator");
3601 string_append (declp
, optable
[i
].out
);
3610 /* a mini string-handling package */
3625 s
->p
= s
->b
= xmalloc (n
);
3628 else if (s
->e
- s
->p
< n
)
3633 s
->b
= xrealloc (s
->b
, n
);
3646 s
->b
= s
->e
= s
->p
= NULL
;
3654 s
->b
= s
->p
= s
->e
= NULL
;
3670 return (s
->b
== s
->p
);
3676 string_append (p
, s
)
3681 if (s
== NULL
|| *s
== '\0')
3685 memcpy (p
->p
, s
, n
);
3690 string_appends (p
, s
)
3699 memcpy (p
->p
, s
->b
, n
);
3705 string_appendn (p
, s
, n
)
3713 memcpy (p
->p
, s
, n
);
3719 string_prepend (p
, s
)
3723 if (s
!= NULL
&& *s
!= '\0')
3725 string_prependn (p
, s
, strlen (s
));
3730 string_prepends (p
, s
)
3735 string_prependn (p
, s
->b
, s
->p
- s
->b
);
3740 string_prependn (p
, s
, n
)
3750 for (q
= p
->p
- 1; q
>= p
->b
; q
--)
3754 memcpy (p
->b
, s
, n
);
3759 /* To generate a standalone demangler program for testing purposes,
3760 just compile and link this file with -DMAIN and libiberty.a. When
3761 run, it demangles each command line arg, or each stdin string, and
3762 prints the result on stdout. */
3768 static char *program_name
;
3769 static char *program_version
= VERSION
;
3770 static int flags
= DMGL_PARAMS
| DMGL_ANSI
;
3772 static void demangle_it
PARAMS ((char *));
3773 static void usage
PARAMS ((FILE *, int));
3774 static void fatal
PARAMS ((char *));
3777 demangle_it (mangled_name
)
3782 result
= cplus_demangle (mangled_name
, flags
);
3785 printf ("%s\n", mangled_name
);
3789 printf ("%s\n", result
);
3795 usage (stream
, status
)
3800 Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
3801 [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\
3802 [--help] [--version] [arg...]\n",
3807 #define MBUF_SIZE 32767
3808 char mbuffer
[MBUF_SIZE
];
3810 /* Defined in the automatically-generated underscore.c. */
3811 extern int prepends_underscore
;
3813 int strip_underscore
= 0;
3815 static struct option long_options
[] = {
3816 {"strip-underscores", no_argument
, 0, '_'},
3817 {"format", required_argument
, 0, 's'},
3818 {"help", no_argument
, 0, 'h'},
3819 {"no-strip-underscores", no_argument
, 0, 'n'},
3820 {"version", no_argument
, 0, 'v'},
3821 {0, no_argument
, 0, 0}
3824 /* More 'friendly' abort that prints the line and file.
3825 config.h can #define abort fancy_abort if you like that sort of thing. */
3830 fatal ("Internal gcc abort.");
3841 program_name
= argv
[0];
3843 strip_underscore
= prepends_underscore
;
3845 while ((c
= getopt_long (argc
, argv
, "_ns:j", long_options
, (int *) 0)) != EOF
)
3855 strip_underscore
= 0;
3858 printf ("GNU %s version %s\n", program_name
, program_version
);
3861 strip_underscore
= 1;
3864 if (strcmp (optarg
, "gnu") == 0)
3866 current_demangling_style
= gnu_demangling
;
3868 else if (strcmp (optarg
, "lucid") == 0)
3870 current_demangling_style
= lucid_demangling
;
3872 else if (strcmp (optarg
, "arm") == 0)
3874 current_demangling_style
= arm_demangling
;
3878 fprintf (stderr
, "%s: unknown demangling style `%s'\n",
3879 program_name
, optarg
);
3888 for ( ; optind
< argc
; optind
++)
3890 demangle_it (argv
[optind
]);
3899 /* Try to read a label. */
3900 while (c
!= EOF
&& (isalnum(c
) || c
== '_' || c
== '$' || c
== '.'))
3902 if (i
>= MBUF_SIZE
-1)
3911 if (mbuffer
[0] == '.')
3913 if (strip_underscore
&& mbuffer
[skip_first
] == '_')
3921 result
= cplus_demangle (mbuffer
+ skip_first
, flags
);
3924 if (mbuffer
[0] == '.')
3926 fputs (result
, stdout
);
3930 fputs (mbuffer
, stdout
);
3947 fprintf (stderr
, "%s: %s\n", program_name
, str
);
3955 register char *value
= (char *) malloc (size
);
3957 fatal ("virtual memory exhausted");
3962 xrealloc (ptr
, size
)
3966 register char *value
= (char *) realloc (ptr
, size
);
3968 fatal ("virtual memory exhausted");