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 const_type
; /* A const member function */
130 int volatile_type
; /* A volatile member function */
131 int dllimported
; /* Symbol imported from a PE DLL */
132 char **tmpl_argvec
; /* Template function arguments. */
133 int ntmpl_args
; /* The number of template function arguments. */
134 int forgetting_types
; /* Nonzero if we are not remembering the types
136 string
* previous_argument
; /* The last function argument demangled. */
137 int nrepeats
; /* The number of times to repeat the previous
141 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
142 #define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS)
144 static const struct optable
150 {"nw", " new", DMGL_ANSI
}, /* new (1.92, ansi) */
151 {"dl", " delete", DMGL_ANSI
}, /* new (1.92, ansi) */
152 {"new", " new", 0}, /* old (1.91, and 1.x) */
153 {"delete", " delete", 0}, /* old (1.91, and 1.x) */
154 {"vn", " new []", DMGL_ANSI
}, /* GNU, pending ansi */
155 {"vd", " delete []", DMGL_ANSI
}, /* GNU, pending ansi */
156 {"as", "=", DMGL_ANSI
}, /* ansi */
157 {"ne", "!=", DMGL_ANSI
}, /* old, ansi */
158 {"eq", "==", DMGL_ANSI
}, /* old, ansi */
159 {"ge", ">=", DMGL_ANSI
}, /* old, ansi */
160 {"gt", ">", DMGL_ANSI
}, /* old, ansi */
161 {"le", "<=", DMGL_ANSI
}, /* old, ansi */
162 {"lt", "<", DMGL_ANSI
}, /* old, ansi */
163 {"plus", "+", 0}, /* old */
164 {"pl", "+", DMGL_ANSI
}, /* ansi */
165 {"apl", "+=", DMGL_ANSI
}, /* ansi */
166 {"minus", "-", 0}, /* old */
167 {"mi", "-", DMGL_ANSI
}, /* ansi */
168 {"ami", "-=", DMGL_ANSI
}, /* ansi */
169 {"mult", "*", 0}, /* old */
170 {"ml", "*", DMGL_ANSI
}, /* ansi */
171 {"amu", "*=", DMGL_ANSI
}, /* ansi (ARM/Lucid) */
172 {"aml", "*=", DMGL_ANSI
}, /* ansi (GNU/g++) */
173 {"convert", "+", 0}, /* old (unary +) */
174 {"negate", "-", 0}, /* old (unary -) */
175 {"trunc_mod", "%", 0}, /* old */
176 {"md", "%", DMGL_ANSI
}, /* ansi */
177 {"amd", "%=", DMGL_ANSI
}, /* ansi */
178 {"trunc_div", "/", 0}, /* old */
179 {"dv", "/", DMGL_ANSI
}, /* ansi */
180 {"adv", "/=", DMGL_ANSI
}, /* ansi */
181 {"truth_andif", "&&", 0}, /* old */
182 {"aa", "&&", DMGL_ANSI
}, /* ansi */
183 {"truth_orif", "||", 0}, /* old */
184 {"oo", "||", DMGL_ANSI
}, /* ansi */
185 {"truth_not", "!", 0}, /* old */
186 {"nt", "!", DMGL_ANSI
}, /* ansi */
187 {"postincrement","++", 0}, /* old */
188 {"pp", "++", DMGL_ANSI
}, /* ansi */
189 {"postdecrement","--", 0}, /* old */
190 {"mm", "--", DMGL_ANSI
}, /* ansi */
191 {"bit_ior", "|", 0}, /* old */
192 {"or", "|", DMGL_ANSI
}, /* ansi */
193 {"aor", "|=", DMGL_ANSI
}, /* ansi */
194 {"bit_xor", "^", 0}, /* old */
195 {"er", "^", DMGL_ANSI
}, /* ansi */
196 {"aer", "^=", DMGL_ANSI
}, /* ansi */
197 {"bit_and", "&", 0}, /* old */
198 {"ad", "&", DMGL_ANSI
}, /* ansi */
199 {"aad", "&=", DMGL_ANSI
}, /* ansi */
200 {"bit_not", "~", 0}, /* old */
201 {"co", "~", DMGL_ANSI
}, /* ansi */
202 {"call", "()", 0}, /* old */
203 {"cl", "()", DMGL_ANSI
}, /* ansi */
204 {"alshift", "<<", 0}, /* old */
205 {"ls", "<<", DMGL_ANSI
}, /* ansi */
206 {"als", "<<=", DMGL_ANSI
}, /* ansi */
207 {"arshift", ">>", 0}, /* old */
208 {"rs", ">>", DMGL_ANSI
}, /* ansi */
209 {"ars", ">>=", DMGL_ANSI
}, /* ansi */
210 {"component", "->", 0}, /* old */
211 {"pt", "->", DMGL_ANSI
}, /* ansi; Lucid C++ form */
212 {"rf", "->", DMGL_ANSI
}, /* ansi; ARM/GNU form */
213 {"indirect", "*", 0}, /* old */
214 {"method_call", "->()", 0}, /* old */
215 {"addr", "&", 0}, /* old (unary &) */
216 {"array", "[]", 0}, /* old */
217 {"vc", "[]", DMGL_ANSI
}, /* ansi */
218 {"compound", ", ", 0}, /* old */
219 {"cm", ", ", DMGL_ANSI
}, /* ansi */
220 {"cond", "?:", 0}, /* old */
221 {"cn", "?:", DMGL_ANSI
}, /* pseudo-ansi */
222 {"max", ">?", 0}, /* old */
223 {"mx", ">?", DMGL_ANSI
}, /* pseudo-ansi */
224 {"min", "<?", 0}, /* old */
225 {"mn", "<?", DMGL_ANSI
}, /* pseudo-ansi */
226 {"nop", "", 0}, /* old (for operator=) */
227 {"rm", "->*", DMGL_ANSI
}, /* ansi */
228 {"sz", "sizeof ", DMGL_ANSI
} /* pseudo-ansi */
231 /* These values are used to indicate the various type varieties.
232 They are all non-zero so that they can be used as `success'
234 typedef enum type_kind_t
244 #define STRING_EMPTY(str) ((str) -> b == (str) -> p)
245 #define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
246 string_prepend(str, " ");}
247 #define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
248 string_append(str, " ");}
249 #define LEN_STRING(str) ( (STRING_EMPTY(str))?0:((str)->p - (str)->b))
251 /* The scope separator appropriate for the language being demangled. */
252 #define SCOPE_STRING(work) "::"
254 #define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */
255 #define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */
257 /* Prototypes for local functions */
260 mop_up
PARAMS ((struct work_stuff
*, string
*, int));
263 squangle_mop_up
PARAMS ((struct work_stuff
*));
267 demangle_method_args
PARAMS ((struct work_stuff
*, const char **, string
*));
271 internal_cplus_demangle
PARAMS ((struct work_stuff
*, const char *));
274 demangle_template_template_parm
PARAMS ((struct work_stuff
*work
,
275 const char **, string
*));
278 demangle_template
PARAMS ((struct work_stuff
*work
, const char **, string
*,
279 string
*, int, int));
282 arm_pt
PARAMS ((struct work_stuff
*, const char *, int, const char **,
286 demangle_arm_pt
PARAMS ((struct work_stuff
*, const char **, int, string
*));
289 demangle_class_name
PARAMS ((struct work_stuff
*, const char **, string
*));
292 demangle_qualified
PARAMS ((struct work_stuff
*, const char **, string
*,
296 demangle_class
PARAMS ((struct work_stuff
*, const char **, string
*));
299 demangle_fund_type
PARAMS ((struct work_stuff
*, const char **, string
*));
302 demangle_signature
PARAMS ((struct work_stuff
*, const char **, string
*));
305 demangle_prefix
PARAMS ((struct work_stuff
*, const char **, string
*));
308 gnu_special
PARAMS ((struct work_stuff
*, const char **, string
*));
311 arm_special
PARAMS ((const char **, string
*));
314 string_need
PARAMS ((string
*, int));
317 string_delete
PARAMS ((string
*));
320 string_init
PARAMS ((string
*));
323 string_clear
PARAMS ((string
*));
327 string_empty
PARAMS ((string
*));
331 string_append
PARAMS ((string
*, const char *));
334 string_appends
PARAMS ((string
*, string
*));
337 string_appendn
PARAMS ((string
*, const char *, int));
340 string_prepend
PARAMS ((string
*, const char *));
343 string_prependn
PARAMS ((string
*, const char *, int));
346 get_count
PARAMS ((const char **, int *));
349 consume_count
PARAMS ((const char **));
352 consume_count_with_underscores
PARAMS ((const char**));
355 demangle_args
PARAMS ((struct work_stuff
*, const char **, string
*));
358 demangle_nested_args
PARAMS ((struct work_stuff
*, const char**, string
*));
361 do_type
PARAMS ((struct work_stuff
*, const char **, string
*));
364 do_arg
PARAMS ((struct work_stuff
*, const char **, string
*));
367 demangle_function_name
PARAMS ((struct work_stuff
*, const char **, string
*,
371 remember_type
PARAMS ((struct work_stuff
*, const char *, int));
374 remember_Btype
PARAMS ((struct work_stuff
*, const char *, int, int));
377 register_Btype
PARAMS ((struct work_stuff
*));
380 remember_Ktype
PARAMS ((struct work_stuff
*, const char *, int));
383 forget_types
PARAMS ((struct work_stuff
*));
386 forget_B_and_K_types
PARAMS ((struct work_stuff
*));
389 string_prepends
PARAMS ((string
*, string
*));
392 demangle_template_value_parm
PARAMS ((struct work_stuff
*, const char**,
393 string
*, type_kind_t
));
395 /* Translate count to integer, consuming tokens in the process.
396 Conversion terminates on the first non-digit character.
397 Trying to consume something that isn't a count results in
398 no consumption of input and a return of 0. */
406 while (isdigit (**type
))
409 count
+= **type
- '0';
416 /* Like consume_count, but for counts that are preceded and followed
417 by '_' if they are greater than 10. Also, -1 is returned for
418 failure, since 0 can be a valid value. */
421 consume_count_with_underscores (mangled
)
422 const char **mangled
;
426 if (**mangled
== '_')
429 if (!isdigit (**mangled
))
432 idx
= consume_count (mangled
);
433 if (**mangled
!= '_')
434 /* The trailing underscore was missing. */
441 if (**mangled
< '0' || **mangled
> '9')
444 idx
= **mangled
- '0';
452 cplus_demangle_opname (opname
, result
, options
)
459 struct work_stuff work
[1];
462 len
= strlen(opname
);
465 memset ((char *) work
, 0, sizeof (work
));
466 work
->options
= options
;
468 if (opname
[0] == '_' && opname
[1] == '_'
469 && opname
[2] == 'o' && opname
[3] == 'p')
472 /* type conversion operator. */
474 if (do_type (work
, &tem
, &type
))
476 strcat (result
, "operator ");
477 strncat (result
, type
.b
, type
.p
- type
.b
);
478 string_delete (&type
);
482 else if (opname
[0] == '_' && opname
[1] == '_'
483 && opname
[2] >= 'a' && opname
[2] <= 'z'
484 && opname
[3] >= 'a' && opname
[3] <= 'z')
486 if (opname
[4] == '\0')
490 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
492 if (strlen (optable
[i
].in
) == 2
493 && memcmp (optable
[i
].in
, opname
+ 2, 2) == 0)
495 strcat (result
, "operator");
496 strcat (result
, optable
[i
].out
);
504 if (opname
[2] == 'a' && opname
[5] == '\0')
508 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
510 if (strlen (optable
[i
].in
) == 3
511 && memcmp (optable
[i
].in
, opname
+ 2, 3) == 0)
513 strcat (result
, "operator");
514 strcat (result
, optable
[i
].out
);
525 && strchr (cplus_markers
, opname
[2]) != NULL
)
527 /* see if it's an assignment expression */
528 if (len
>= 10 /* op$assign_ */
529 && memcmp (opname
+ 3, "assign_", 7) == 0)
532 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
535 if (strlen (optable
[i
].in
) == len1
536 && memcmp (optable
[i
].in
, opname
+ 10, len1
) == 0)
538 strcat (result
, "operator");
539 strcat (result
, optable
[i
].out
);
540 strcat (result
, "=");
549 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
552 if (strlen (optable
[i
].in
) == len1
553 && memcmp (optable
[i
].in
, opname
+ 3, len1
) == 0)
555 strcat (result
, "operator");
556 strcat (result
, optable
[i
].out
);
563 else if (len
>= 5 && memcmp (opname
, "type", 4) == 0
564 && strchr (cplus_markers
, opname
[4]) != NULL
)
566 /* type conversion operator */
568 if (do_type (work
, &tem
, &type
))
570 strcat (result
, "operator ");
571 strncat (result
, type
.b
, type
.p
- type
.b
);
572 string_delete (&type
);
576 squangle_mop_up (work
);
580 /* Takes operator name as e.g. "++" and returns mangled
581 operator name (e.g. "postincrement_expr"), or NULL if not found.
583 If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
584 if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */
587 cplus_mangle_opname (opname
, options
)
594 len
= strlen (opname
);
595 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
597 if (strlen (optable
[i
].out
) == len
598 && (options
& DMGL_ANSI
) == (optable
[i
].flags
& DMGL_ANSI
)
599 && memcmp (optable
[i
].out
, opname
, len
) == 0)
600 return optable
[i
].in
;
605 /* char *cplus_demangle (const char *mangled, int options)
607 If MANGLED is a mangled function name produced by GNU C++, then
608 a pointer to a malloced string giving a C++ representation
609 of the name will be returned; otherwise NULL will be returned.
610 It is the caller's responsibility to free the string which
613 The OPTIONS arg may contain one or more of the following bits:
615 DMGL_ANSI ANSI qualifiers such as `const' and `void' are
617 DMGL_PARAMS Function parameters are included.
621 cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)"
622 cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
623 cplus_demangle ("foo__1Ai", 0) => "A::foo"
625 cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)"
626 cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
627 cplus_demangle ("foo__1Afe", 0) => "A::foo"
629 Note that any leading underscores, or other such characters prepended by
630 the compilation system, are presumed to have already been stripped from
634 cplus_demangle (mangled
, options
)
639 struct work_stuff work
[1];
640 memset ((char *) work
, 0, sizeof (work
));
641 work
-> options
= options
;
642 if ((work
-> options
& DMGL_STYLE_MASK
) == 0)
643 work
-> options
|= (int) current_demangling_style
& DMGL_STYLE_MASK
;
645 ret
= internal_cplus_demangle (work
, mangled
);
646 squangle_mop_up (work
);
651 /* This function performs most of what cplus_demangle use to do, but
652 to be able to demangle a name with a B, K or n code, we need to
653 have a longer term memory of what types have been seen. The original
654 now intializes and cleans up the squangle code info, while internal
655 calls go directly to this routine to avoid resetting that info. */
658 internal_cplus_demangle (work
, mangled
)
659 struct work_stuff
*work
;
665 char *demangled
= NULL
;
667 int saved_volatile_type
;
668 s1
= work
->constructor
;
669 s2
= work
->destructor
;
670 s3
= work
->static_type
;
671 s4
= work
->const_type
;
672 saved_volatile_type
= work
->volatile_type
;
673 work
->constructor
= work
->destructor
= 0;
674 work
->static_type
= work
->const_type
= 0;
675 work
->volatile_type
= 0;
676 work
->dllimported
= 0;
678 if ((mangled
!= NULL
) && (*mangled
!= '\0'))
682 /* First check to see if gnu style demangling is active and if the
683 string to be demangled contains a CPLUS_MARKER. If so, attempt to
684 recognize one of the gnu special forms rather than looking for a
685 standard prefix. In particular, don't worry about whether there
686 is a "__" string in the mangled string. Consider "_$_5__foo" for
689 if ((AUTO_DEMANGLING
|| GNU_DEMANGLING
))
691 success
= gnu_special (work
, &mangled
, &decl
);
695 success
= demangle_prefix (work
, &mangled
, &decl
);
697 if (success
&& (*mangled
!= '\0'))
699 success
= demangle_signature (work
, &mangled
, &decl
);
701 if (work
->constructor
== 2)
703 string_prepend (&decl
, "global constructors keyed to ");
704 work
->constructor
= 0;
706 else if (work
->destructor
== 2)
708 string_prepend (&decl
, "global destructors keyed to ");
709 work
->destructor
= 0;
711 else if (work
->dllimported
== 1)
713 string_prepend (&decl
, "import stub for ");
714 work
->dllimported
= 0;
716 demangled
= mop_up (work
, &decl
, success
);
718 work
->constructor
= s1
;
719 work
->destructor
= s2
;
720 work
->static_type
= s3
;
721 work
->const_type
= s4
;
722 work
->volatile_type
= saved_volatile_type
;
727 /* Clear out and squangling related storage */
729 squangle_mop_up (work
)
730 struct work_stuff
*work
;
732 /* clean up the B and K type mangling types. */
733 forget_B_and_K_types (work
);
734 if (work
-> btypevec
!= NULL
)
736 free ((char *) work
-> btypevec
);
738 if (work
-> ktypevec
!= NULL
)
740 free ((char *) work
-> ktypevec
);
744 /* Clear out any mangled storage */
747 mop_up (work
, declp
, success
)
748 struct work_stuff
*work
;
752 char *demangled
= NULL
;
754 /* Discard the remembered types, if any. */
757 if (work
-> typevec
!= NULL
)
759 free ((char *) work
-> typevec
);
760 work
-> typevec
= NULL
;
762 if (work
->tmpl_argvec
)
766 for (i
= 0; i
< work
->ntmpl_args
; i
++)
767 if (work
->tmpl_argvec
[i
])
768 free ((char*) work
->tmpl_argvec
[i
]);
770 free ((char*) work
->tmpl_argvec
);
771 work
->tmpl_argvec
= NULL
;
773 if (work
->previous_argument
)
775 string_delete (work
->previous_argument
);
776 free ((char*) work
->previous_argument
);
779 /* If demangling was successful, ensure that the demangled string is null
780 terminated and return it. Otherwise, free the demangling decl. */
784 string_delete (declp
);
788 string_appendn (declp
, "", 1);
789 demangled
= declp
-> b
;
798 demangle_signature -- demangle the signature part of a mangled name
803 demangle_signature (struct work_stuff *work, const char **mangled,
808 Consume and demangle the signature portion of the mangled name.
810 DECLP is the string where demangled output is being built. At
811 entry it contains the demangled root name from the mangled name
812 prefix. I.E. either a demangled operator name or the root function
813 name. In some special cases, it may contain nothing.
815 *MANGLED points to the current unconsumed location in the mangled
816 name. As tokens are consumed and demangling is performed, the
817 pointer is updated to continuously point at the next token to
820 Demangling GNU style mangled names is nasty because there is no
821 explicit token that marks the start of the outermost function
825 demangle_signature (work
, mangled
, declp
)
826 struct work_stuff
*work
;
827 const char **mangled
;
833 int expect_return_type
= 0;
834 const char *oldmangled
= NULL
;
838 while (success
&& (**mangled
!= '\0'))
843 oldmangled
= *mangled
;
844 success
= demangle_qualified (work
, mangled
, declp
, 1, 0);
846 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
847 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
853 oldmangled
= *mangled
;
854 success
= demangle_qualified (work
, mangled
, declp
, 1, 0);
855 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
863 /* Static member function */
864 if (oldmangled
== NULL
)
866 oldmangled
= *mangled
;
869 work
-> static_type
= 1;
874 if (**mangled
== 'C')
875 work
-> const_type
= 1;
877 work
->volatile_type
= 1;
879 /* a qualified member function */
880 if (oldmangled
== NULL
)
881 oldmangled
= *mangled
;
885 case '0': case '1': case '2': case '3': case '4':
886 case '5': case '6': case '7': case '8': case '9':
887 if (oldmangled
== NULL
)
889 oldmangled
= *mangled
;
891 success
= demangle_class (work
, mangled
, declp
);
894 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
896 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
906 success
= do_type (work
, mangled
, &s
);
909 string_append (&s
, SCOPE_STRING (work
));
910 string_prepends (declp
, &s
);
919 /* ARM style demangling includes a specific 'F' character after
920 the class name. For GNU style, it is just implied. So we can
921 safely just consume any 'F' at this point and be compatible
922 with either style. */
928 /* For lucid/ARM style we have to forget any types we might
929 have remembered up to this point, since they were not argument
930 types. GNU style considers all types seen as available for
931 back references. See comment in demangle_args() */
933 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
937 success
= demangle_args (work
, mangled
, declp
);
942 string_init(&trawname
);
944 if (oldmangled
== NULL
)
946 oldmangled
= *mangled
;
948 success
= demangle_template (work
, mangled
, &tname
,
952 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
954 string_append (&tname
, SCOPE_STRING (work
));
956 string_prepends(declp
, &tname
);
957 if (work
-> destructor
& 1)
959 string_prepend (&trawname
, "~");
960 string_appends (declp
, &trawname
);
961 work
->destructor
-= 1;
963 if ((work
->constructor
& 1) || (work
->destructor
& 1))
965 string_appends (declp
, &trawname
);
966 work
->constructor
-= 1;
968 string_delete(&trawname
);
969 string_delete(&tname
);
975 if (GNU_DEMANGLING
&& expect_return_type
)
977 /* Read the return type. */
979 string_init (&return_type
);
982 success
= do_type (work
, mangled
, &return_type
);
983 APPEND_BLANK (&return_type
);
985 string_prepends (declp
, &return_type
);
986 string_delete (&return_type
);
990 /* At the outermost level, we cannot have a return type specified,
991 so if we run into another '_' at this point we are dealing with
992 a mangled name that is either bogus, or has been mangled by
993 some algorithm we don't know how to deal with. So just
994 reject the entire demangling. */
1001 /* A G++ template function. Read the template arguments. */
1002 success
= demangle_template (work
, mangled
, declp
, 0, 0,
1004 if (!(work
->constructor
& 1))
1005 expect_return_type
= 1;
1014 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
1016 /* Assume we have stumbled onto the first outermost function
1017 argument token, and start processing args. */
1019 success
= demangle_args (work
, mangled
, declp
);
1023 /* Non-GNU demanglers use a specific token to mark the start
1024 of the outermost function argument tokens. Typically 'F',
1025 for ARM-demangling, for example. So if we find something
1026 we are not prepared for, it must be an error. */
1032 if (AUTO_DEMANGLING || GNU_DEMANGLING)
1035 if (success
&& expect_func
)
1038 success
= demangle_args (work
, mangled
, declp
);
1039 /* Since template include the mangling of their return types,
1040 we must set expect_func to 0 so that we don't try do
1041 demangle more arguments the next time we get here. */
1046 if (success
&& !func_done
)
1048 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
1050 /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
1051 bar__3fooi is 'foo::bar(int)'. We get here when we find the
1052 first case, and need to ensure that the '(void)' gets added to
1053 the current declp. Note that with ARM, the first case
1054 represents the name of a static data member 'foo::bar',
1055 which is in the current declp, so we leave it alone. */
1056 success
= demangle_args (work
, mangled
, declp
);
1059 if (success
&& work
-> static_type
&& PRINT_ARG_TYPES
)
1060 string_append (declp
, " static");
1061 if (success
&& work
-> const_type
&& PRINT_ARG_TYPES
)
1062 string_append (declp
, " const");
1063 else if (success
&& work
->volatile_type
&& PRINT_ARG_TYPES
)
1064 string_append (declp
, " volatile");
1072 demangle_method_args (work
, mangled
, declp
)
1073 struct work_stuff
*work
;
1074 const char **mangled
;
1079 if (work
-> static_type
)
1081 string_append (declp
, *mangled
+ 1);
1082 *mangled
+= strlen (*mangled
);
1087 success
= demangle_args (work
, mangled
, declp
);
1095 demangle_template_template_parm (work
, mangled
, tname
)
1096 struct work_stuff
*work
;
1097 const char **mangled
;
1106 string_append (tname
, "template <");
1107 /* get size of template parameter list */
1108 if (get_count (mangled
, &r
))
1110 for (i
= 0; i
< r
; i
++)
1114 string_append (tname
, ", ");
1117 /* Z for type parameters */
1118 if (**mangled
== 'Z')
1121 string_append (tname
, "class");
1123 /* z for template parameters */
1124 else if (**mangled
== 'z')
1128 demangle_template_template_parm (work
, mangled
, tname
);
1136 /* temp is initialized in do_type */
1137 success
= do_type (work
, mangled
, &temp
);
1140 string_appends (tname
, &temp
);
1142 string_delete(&temp
);
1152 if (tname
->p
[-1] == '>')
1153 string_append (tname
, " ");
1154 string_append (tname
, "> class");
1159 demangle_integral_value (work
, mangled
, s
)
1160 struct work_stuff
*work
;
1161 const char** mangled
;
1166 if (**mangled
== 'E')
1168 int need_operator
= 0;
1171 string_appendn (s
, "(", 1);
1173 while (success
&& **mangled
!= 'W' && **mangled
!= '\0')
1182 len
= strlen (*mangled
);
1185 i
< sizeof (optable
) / sizeof (optable
[0]);
1188 size_t l
= strlen (optable
[i
].in
);
1191 && memcmp (optable
[i
].in
, *mangled
, l
) == 0)
1193 string_appendn (s
, " ", 1);
1194 string_append (s
, optable
[i
].out
);
1195 string_appendn (s
, " ", 1);
1208 success
= demangle_template_value_parm (work
, mangled
, s
,
1212 if (**mangled
!= 'W')
1216 string_appendn (s
, ")", 1);
1220 else if (**mangled
== 'Q' || **mangled
== 'K')
1221 success
= demangle_qualified (work
, mangled
, s
, 0, 1);
1226 if (**mangled
== 'm')
1228 string_appendn (s
, "-", 1);
1231 while (isdigit (**mangled
))
1233 string_appendn (s
, *mangled
, 1);
1243 demangle_template_value_parm (work
, mangled
, s
, tk
)
1244 struct work_stuff
*work
;
1245 const char **mangled
;
1251 if (**mangled
== 'Y')
1253 /* The next argument is a template parameter. */
1257 idx
= consume_count_with_underscores (mangled
);
1259 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
1260 || consume_count_with_underscores (mangled
) == -1)
1262 if (work
->tmpl_argvec
)
1263 string_append (s
, work
->tmpl_argvec
[idx
]);
1267 sprintf(buf
, "T%d", idx
);
1268 string_append (s
, buf
);
1271 else if (tk
== tk_integral
)
1272 success
= demangle_integral_value (work
, mangled
, s
);
1273 else if (tk
== tk_char
)
1277 if (**mangled
== 'm')
1279 string_appendn (s
, "-", 1);
1282 string_appendn (s
, "'", 1);
1283 val
= consume_count(mangled
);
1288 string_appendn (s
, &tmp
[0], 1);
1289 string_appendn (s
, "'", 1);
1291 else if (tk
== tk_bool
)
1293 int val
= consume_count (mangled
);
1295 string_appendn (s
, "false", 5);
1297 string_appendn (s
, "true", 4);
1301 else if (tk
== tk_real
)
1303 if (**mangled
== 'm')
1305 string_appendn (s
, "-", 1);
1308 while (isdigit (**mangled
))
1310 string_appendn (s
, *mangled
, 1);
1313 if (**mangled
== '.') /* fraction */
1315 string_appendn (s
, ".", 1);
1317 while (isdigit (**mangled
))
1319 string_appendn (s
, *mangled
, 1);
1323 if (**mangled
== 'e') /* exponent */
1325 string_appendn (s
, "e", 1);
1327 while (isdigit (**mangled
))
1329 string_appendn (s
, *mangled
, 1);
1334 else if (tk
== tk_pointer
)
1336 int symbol_len
= consume_count (mangled
);
1337 if (symbol_len
== 0)
1339 if (symbol_len
== 0)
1340 string_appendn (s
, "0", 1);
1343 char *p
= xmalloc (symbol_len
+ 1), *q
;
1344 strncpy (p
, *mangled
, symbol_len
);
1345 p
[symbol_len
] = '\0';
1346 q
= internal_cplus_demangle (work
, p
);
1347 string_appendn (s
, "&", 1);
1350 string_append (s
, q
);
1354 string_append (s
, p
);
1357 *mangled
+= symbol_len
;
1363 /* Demangle the template name in MANGLED. The full name of the
1364 template (e.g., S<int>) is placed in TNAME. The name without the
1365 template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is
1366 non-NULL. If IS_TYPE is nonzero, this template is a type template,
1367 not a function template. If both IS_TYPE and REMEMBER are nonzero,
1368 the tmeplate is remembered in the list of back-referenceable
1372 demangle_template (work
, mangled
, tname
, trawname
, is_type
, remember
)
1373 struct work_stuff
*work
;
1374 const char **mangled
;
1392 bindex
= register_Btype (work
);
1394 /* get template name */
1395 if (**mangled
== 'z')
1401 idx
= consume_count_with_underscores (mangled
);
1403 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
1404 || consume_count_with_underscores (mangled
) == -1)
1407 if (work
->tmpl_argvec
)
1409 string_append (tname
, work
->tmpl_argvec
[idx
]);
1411 string_append (trawname
, work
->tmpl_argvec
[idx
]);
1416 sprintf(buf
, "T%d", idx
);
1417 string_append (tname
, buf
);
1419 string_append (trawname
, buf
);
1424 if ((r
= consume_count (mangled
)) == 0 || strlen (*mangled
) < r
)
1428 string_appendn (tname
, *mangled
, r
);
1430 string_appendn (trawname
, *mangled
, r
);
1434 string_append (tname
, "<");
1435 /* get size of template parameter list */
1436 if (!get_count (mangled
, &r
))
1442 /* Create an array for saving the template argument values. */
1443 work
->tmpl_argvec
= (char**) xmalloc (r
* sizeof (char *));
1444 work
->ntmpl_args
= r
;
1445 for (i
= 0; i
< r
; i
++)
1446 work
->tmpl_argvec
[i
] = 0;
1448 for (i
= 0; i
< r
; i
++)
1452 string_append (tname
, ", ");
1454 /* Z for type parameters */
1455 if (**mangled
== 'Z')
1458 /* temp is initialized in do_type */
1459 success
= do_type (work
, mangled
, &temp
);
1462 string_appends (tname
, &temp
);
1466 /* Save the template argument. */
1467 int len
= temp
.p
- temp
.b
;
1468 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1469 memcpy (work
->tmpl_argvec
[i
], temp
.b
, len
);
1470 work
->tmpl_argvec
[i
][len
] = '\0';
1473 string_delete(&temp
);
1479 /* z for template parameters */
1480 else if (**mangled
== 'z')
1484 success
= demangle_template_template_parm (work
, mangled
, tname
);
1487 && (r2
= consume_count (mangled
)) > 0 && strlen (*mangled
) >= r2
)
1489 string_append (tname
, " ");
1490 string_appendn (tname
, *mangled
, r2
);
1493 /* Save the template argument. */
1495 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1496 memcpy (work
->tmpl_argvec
[i
], *mangled
, len
);
1497 work
->tmpl_argvec
[i
][len
] = '\0';
1510 const char* start_of_value_parm
= *mangled
;
1512 /* otherwise, value parameter */
1514 /* temp is initialized in do_type */
1515 success
= do_type (work
, mangled
, &temp
);
1516 string_delete(&temp
);
1528 success
= demangle_template_value_parm (work
, mangled
, s
,
1529 (type_kind_t
) success
);
1541 int len
= s
->p
- s
->b
;
1542 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1543 memcpy (work
->tmpl_argvec
[i
], s
->b
, len
);
1544 work
->tmpl_argvec
[i
][len
] = '\0';
1546 string_appends (tname
, s
);
1553 if (tname
->p
[-1] == '>')
1554 string_append (tname
, " ");
1555 string_append (tname
, ">");
1558 if (is_type
&& remember
)
1559 remember_Btype (work
, tname
->b
, LEN_STRING (tname
), bindex
);
1562 if (work -> static_type)
1564 string_append (declp, *mangled + 1);
1565 *mangled += strlen (*mangled);
1570 success = demangle_args (work, mangled, declp);
1578 arm_pt (work
, mangled
, n
, anchor
, args
)
1579 struct work_stuff
*work
;
1580 const char *mangled
;
1582 const char **anchor
, **args
;
1585 if (ARM_DEMANGLING
&& (*anchor
= mystrstr (mangled
, "__pt__")))
1588 *args
= *anchor
+ 6;
1589 len
= consume_count (args
);
1590 if (*args
+ len
== mangled
+ n
&& **args
== '_')
1600 demangle_arm_pt (work
, mangled
, n
, declp
)
1601 struct work_stuff
*work
;
1602 const char **mangled
;
1608 const char *e
= *mangled
+ n
;
1611 if (arm_pt (work
, *mangled
, n
, &p
, &args
))
1615 string_appendn (declp
, *mangled
, p
- *mangled
);
1616 string_append (declp
, "<");
1617 /* should do error checking here */
1619 string_clear (&arg
);
1620 do_type (work
, &args
, &arg
);
1621 string_appends (declp
, &arg
);
1622 string_append (declp
, ",");
1624 string_delete (&arg
);
1626 string_append (declp
, ">");
1630 string_appendn (declp
, *mangled
, n
);
1636 demangle_class_name (work
, mangled
, declp
)
1637 struct work_stuff
*work
;
1638 const char **mangled
;
1644 n
= consume_count (mangled
);
1645 if (strlen (*mangled
) >= n
)
1647 demangle_arm_pt (work
, mangled
, n
, declp
);
1658 demangle_class -- demangle a mangled class sequence
1663 demangle_class (struct work_stuff *work, const char **mangled,
1668 DECLP points to the buffer into which demangling is being done.
1670 *MANGLED points to the current token to be demangled. On input,
1671 it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
1672 On exit, it points to the next token after the mangled class on
1673 success, or the first unconsumed token on failure.
1675 If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
1676 we are demangling a constructor or destructor. In this case
1677 we prepend "class::class" or "class::~class" to DECLP.
1679 Otherwise, we prepend "class::" to the current DECLP.
1681 Reset the constructor/destructor flags once they have been
1682 "consumed". This allows demangle_class to be called later during
1683 the same demangling, to do normal class demangling.
1685 Returns 1 if demangling is successful, 0 otherwise.
1690 demangle_class (work
, mangled
, declp
)
1691 struct work_stuff
*work
;
1692 const char **mangled
;
1699 string_init (&class_name
);
1700 btype
= register_Btype (work
);
1701 if (demangle_class_name (work
, mangled
, &class_name
))
1703 if ((work
->constructor
& 1) || (work
->destructor
& 1))
1705 string_prepends (declp
, &class_name
);
1706 if (work
-> destructor
& 1)
1708 string_prepend (declp
, "~");
1709 work
-> destructor
-= 1;
1713 work
-> constructor
-= 1;
1716 remember_Ktype (work
, class_name
.b
, LEN_STRING(&class_name
));
1717 remember_Btype (work
, class_name
.b
, LEN_STRING(&class_name
), btype
);
1718 string_prepend (declp
, SCOPE_STRING (work
));
1719 string_prepends (declp
, &class_name
);
1722 string_delete (&class_name
);
1730 demangle_prefix -- consume the mangled name prefix and find signature
1735 demangle_prefix (struct work_stuff *work, const char **mangled,
1740 Consume and demangle the prefix of the mangled name.
1742 DECLP points to the string buffer into which demangled output is
1743 placed. On entry, the buffer is empty. On exit it contains
1744 the root function name, the demangled operator name, or in some
1745 special cases either nothing or the completely demangled result.
1747 MANGLED points to the current pointer into the mangled name. As each
1748 token of the mangled name is consumed, it is updated. Upon entry
1749 the current mangled name pointer points to the first character of
1750 the mangled name. Upon exit, it should point to the first character
1751 of the signature if demangling was successful, or to the first
1752 unconsumed character if demangling of the prefix was unsuccessful.
1754 Returns 1 on success, 0 otherwise.
1758 demangle_prefix (work
, mangled
, declp
)
1759 struct work_stuff
*work
;
1760 const char **mangled
;
1767 if (strlen(*mangled
) > 6
1768 && (strncmp(*mangled
, "_imp__", 6) == 0
1769 || strncmp(*mangled
, "__imp_", 6) == 0))
1771 /* it's a symbol imported from a PE dynamic library. Check for both
1772 new style prefix _imp__ and legacy __imp_ used by older versions
1775 work
->dllimported
= 1;
1777 else if (strlen(*mangled
) >= 11 && strncmp(*mangled
, "_GLOBAL_", 8) == 0)
1779 char *marker
= strchr (cplus_markers
, (*mangled
)[8]);
1780 if (marker
!= NULL
&& *marker
== (*mangled
)[10])
1782 if ((*mangled
)[9] == 'D')
1784 /* it's a GNU global destructor to be executed at program exit */
1786 work
->destructor
= 2;
1787 if (gnu_special (work
, mangled
, declp
))
1790 else if ((*mangled
)[9] == 'I')
1792 /* it's a GNU global constructor to be executed at program init */
1794 work
->constructor
= 2;
1795 if (gnu_special (work
, mangled
, declp
))
1800 else if (ARM_DEMANGLING
&& strncmp(*mangled
, "__std__", 7) == 0)
1802 /* it's a ARM global destructor to be executed at program exit */
1804 work
->destructor
= 2;
1806 else if (ARM_DEMANGLING
&& strncmp(*mangled
, "__sti__", 7) == 0)
1808 /* it's a ARM global constructor to be executed at program initial */
1810 work
->constructor
= 2;
1813 /* This block of code is a reduction in strength time optimization
1815 scan = mystrstr (*mangled, "__"); */
1821 scan
= strchr (scan
, '_');
1822 } while (scan
!= NULL
&& *++scan
!= '_');
1824 if (scan
!= NULL
) --scan
;
1829 /* We found a sequence of two or more '_', ensure that we start at
1830 the last pair in the sequence. */
1831 i
= strspn (scan
, "_");
1842 else if (work
-> static_type
)
1844 if (!isdigit (scan
[0]) && (scan
[0] != 't'))
1849 else if ((scan
== *mangled
)
1850 && (isdigit (scan
[2]) || (scan
[2] == 'Q') || (scan
[2] == 't')
1851 || (scan
[2] == 'K') || (scan
[2] == 'H')))
1853 /* The ARM says nothing about the mangling of local variables.
1854 But cfront mangles local variables by prepending __<nesting_level>
1855 to them. As an extension to ARM demangling we handle this case. */
1856 if ((LUCID_DEMANGLING
|| ARM_DEMANGLING
) && isdigit (scan
[2]))
1858 *mangled
= scan
+ 2;
1859 consume_count (mangled
);
1860 string_append (declp
, *mangled
);
1861 *mangled
+= strlen (*mangled
);
1866 /* A GNU style constructor starts with __[0-9Qt]. But cfront uses
1867 names like __Q2_3foo3bar for nested type names. So don't accept
1868 this style of constructor for cfront demangling. A GNU
1869 style member-template constructor starts with 'H'. */
1870 if (!(LUCID_DEMANGLING
|| ARM_DEMANGLING
))
1871 work
-> constructor
+= 1;
1872 *mangled
= scan
+ 2;
1875 else if ((scan
== *mangled
) && !isdigit (scan
[2]) && (scan
[2] != 't'))
1877 /* Mangled name starts with "__". Skip over any leading '_' characters,
1878 then find the next "__" that separates the prefix from the signature.
1880 if (!(ARM_DEMANGLING
|| LUCID_DEMANGLING
)
1881 || (arm_special (mangled
, declp
) == 0))
1883 while (*scan
== '_')
1887 if ((scan
= mystrstr (scan
, "__")) == NULL
|| (*(scan
+ 2) == '\0'))
1889 /* No separator (I.E. "__not_mangled"), or empty signature
1890 (I.E. "__not_mangled_either__") */
1895 demangle_function_name (work
, mangled
, declp
, scan
);
1899 else if (ARM_DEMANGLING
&& scan
[2] == 'p' && scan
[3] == 't')
1901 /* Cfront-style parameterized type. Handled later as a signature. */
1905 demangle_arm_pt (work
, mangled
, strlen (*mangled
), declp
);
1907 else if (*(scan
+ 2) != '\0')
1909 /* Mangled name does not start with "__" but does have one somewhere
1910 in there with non empty stuff after it. Looks like a global
1912 demangle_function_name (work
, mangled
, declp
, scan
);
1916 /* Doesn't look like a mangled name */
1920 if (!success
&& (work
->constructor
== 2 || work
->destructor
== 2))
1922 string_append (declp
, *mangled
);
1923 *mangled
+= strlen (*mangled
);
1933 gnu_special -- special handling of gnu mangled strings
1938 gnu_special (struct work_stuff *work, const char **mangled,
1944 Process some special GNU style mangling forms that don't fit
1945 the normal pattern. For example:
1947 _$_3foo (destructor for class foo)
1948 _vt$foo (foo virtual table)
1949 _vt$foo$bar (foo::bar virtual table)
1950 __vt_foo (foo virtual table, new style with thunks)
1951 _3foo$varname (static data member)
1952 _Q22rs2tu$vw (static data member)
1953 __t6vector1Zii (constructor with template)
1954 __thunk_4__$_7ostream (virtual function thunk)
1958 gnu_special (work
, mangled
, declp
)
1959 struct work_stuff
*work
;
1960 const char **mangled
;
1967 if ((*mangled
)[0] == '_'
1968 && strchr (cplus_markers
, (*mangled
)[1]) != NULL
1969 && (*mangled
)[2] == '_')
1971 /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
1973 work
-> destructor
+= 1;
1975 else if ((*mangled
)[0] == '_'
1976 && (((*mangled
)[1] == '_'
1977 && (*mangled
)[2] == 'v'
1978 && (*mangled
)[3] == 't'
1979 && (*mangled
)[4] == '_')
1980 || ((*mangled
)[1] == 'v'
1981 && (*mangled
)[2] == 't'
1982 && strchr (cplus_markers
, (*mangled
)[3]) != NULL
)))
1984 /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
1985 and create the decl. Note that we consume the entire mangled
1986 input string, which means that demangle_signature has no work
1988 if ((*mangled
)[2] == 'v')
1989 (*mangled
) += 5; /* New style, with thunks: "__vt_" */
1991 (*mangled
) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
1992 while (**mangled
!= '\0')
1994 p
= strpbrk (*mangled
, cplus_markers
);
1999 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
2002 success
= demangle_template (work
, mangled
, declp
, 0, 1,
2006 if (isdigit(*mangled
[0]))
2008 n
= consume_count(mangled
);
2009 /* We may be seeing a too-large size, or else a
2010 ".<digits>" indicating a static local symbol. In
2011 any case, declare victory and move on; *don't* try
2012 to use n to allocate. */
2013 if (n
> strlen (*mangled
))
2021 n
= strcspn (*mangled
, cplus_markers
);
2023 string_appendn (declp
, *mangled
, n
);
2027 if (success
&& ((p
== NULL
) || (p
== *mangled
)))
2031 string_append (declp
, SCOPE_STRING (work
));
2042 string_append (declp
, " virtual table");
2044 else if ((*mangled
)[0] == '_'
2045 && (strchr("0123456789Qt", (*mangled
)[1]) != NULL
)
2046 && (p
= strpbrk (*mangled
, cplus_markers
)) != NULL
)
2048 /* static data member, "_3foo$varname" for example */
2054 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
2057 success
= demangle_template (work
, mangled
, declp
, 0, 1, 1);
2060 n
= consume_count (mangled
);
2061 string_appendn (declp
, *mangled
, n
);
2064 if (success
&& (p
== *mangled
))
2066 /* Consumed everything up to the cplus_marker, append the
2069 string_append (declp
, SCOPE_STRING (work
));
2070 n
= strlen (*mangled
);
2071 string_appendn (declp
, *mangled
, n
);
2079 else if (strncmp (*mangled
, "__thunk_", 8) == 0)
2081 int delta
= ((*mangled
) += 8, consume_count (mangled
));
2082 char *method
= internal_cplus_demangle (work
, ++*mangled
);
2086 sprintf (buf
, "virtual function thunk (delta:%d) for ", -delta
);
2087 string_append (declp
, buf
);
2088 string_append (declp
, method
);
2090 n
= strlen (*mangled
);
2098 else if (strncmp (*mangled
, "__t", 3) == 0
2099 && ((*mangled
)[3] == 'i' || (*mangled
)[3] == 'f'))
2101 p
= (*mangled
)[3] == 'i' ? " type_info node" : " type_info function";
2107 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
2110 success
= demangle_template (work
, mangled
, declp
, 0, 1, 1);
2113 success
= demangle_fund_type (work
, mangled
, declp
);
2116 if (success
&& **mangled
!= '\0')
2119 string_append (declp
, p
);
2132 arm_special -- special handling of ARM/lucid mangled strings
2137 arm_special (const char **mangled,
2143 Process some special ARM style mangling forms that don't fit
2144 the normal pattern. For example:
2146 __vtbl__3foo (foo virtual table)
2147 __vtbl__3foo__3bar (bar::foo virtual table)
2152 arm_special (mangled
, declp
)
2153 const char **mangled
;
2160 if (strncmp (*mangled
, ARM_VTABLE_STRING
, ARM_VTABLE_STRLEN
) == 0)
2162 /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
2163 and create the decl. Note that we consume the entire mangled
2164 input string, which means that demangle_signature has no work
2166 scan
= *mangled
+ ARM_VTABLE_STRLEN
;
2167 while (*scan
!= '\0') /* first check it can be demangled */
2169 n
= consume_count (&scan
);
2172 return (0); /* no good */
2175 if (scan
[0] == '_' && scan
[1] == '_')
2180 (*mangled
) += ARM_VTABLE_STRLEN
;
2181 while (**mangled
!= '\0')
2183 n
= consume_count (mangled
);
2184 string_prependn (declp
, *mangled
, n
);
2186 if ((*mangled
)[0] == '_' && (*mangled
)[1] == '_')
2188 string_prepend (declp
, "::");
2192 string_append (declp
, " virtual table");
2205 demangle_qualified -- demangle 'Q' qualified name strings
2210 demangle_qualified (struct work_stuff *, const char *mangled,
2211 string *result, int isfuncname, int append);
2215 Demangle a qualified name, such as "Q25Outer5Inner" which is
2216 the mangled form of "Outer::Inner". The demangled output is
2217 prepended or appended to the result string according to the
2218 state of the append flag.
2220 If isfuncname is nonzero, then the qualified name we are building
2221 is going to be used as a member function name, so if it is a
2222 constructor or destructor function, append an appropriate
2223 constructor or destructor name. I.E. for the above example,
2224 the result for use as a constructor is "Outer::Inner::Inner"
2225 and the result for use as a destructor is "Outer::Inner::~Inner".
2229 Numeric conversion is ASCII dependent (FIXME).
2234 demangle_qualified (work
, mangled
, result
, isfuncname
, append
)
2235 struct work_stuff
*work
;
2236 const char **mangled
;
2247 int bindex
= register_Btype (work
);
2249 /* We only make use of ISFUNCNAME if the entity is a constructor or
2251 isfuncname
= (isfuncname
2252 && ((work
->constructor
& 1) || (work
->destructor
& 1)));
2254 string_init (&temp
);
2255 string_init (&last_name
);
2257 if ((*mangled
)[0] == 'K')
2259 /* Squangling qualified name reuse */
2262 idx
= consume_count_with_underscores (mangled
);
2263 if (idx
== -1 || idx
> work
-> numk
)
2266 string_append (&temp
, work
-> ktypevec
[idx
]);
2269 switch ((*mangled
)[1])
2272 /* GNU mangled name with more than 9 classes. The count is preceded
2273 by an underscore (to distinguish it from the <= 9 case) and followed
2274 by an underscore. */
2276 qualifiers
= atoi (p
);
2277 if (!isdigit (*p
) || *p
== '0')
2280 /* Skip the digits. */
2281 while (isdigit (*p
))
2299 /* The count is in a single digit. */
2300 num
[0] = (*mangled
)[1];
2302 qualifiers
= atoi (num
);
2304 /* If there is an underscore after the digit, skip it. This is
2305 said to be for ARM-qualified names, but the ARM makes no
2306 mention of such an underscore. Perhaps cfront uses one. */
2307 if ((*mangled
)[2] == '_')
2322 /* Pick off the names and collect them in the temp buffer in the order
2323 in which they are found, separated by '::'. */
2325 while (qualifiers
-- > 0)
2328 string_clear (&last_name
);
2330 if (*mangled
[0] == '_')
2333 if (*mangled
[0] == 't')
2335 /* Here we always append to TEMP since we will want to use
2336 the template name without the template parameters as a
2337 constructor or destructor name. The appropriate
2338 (parameter-less) value is returned by demangle_template
2339 in LAST_NAME. We do not remember the template type here,
2340 in order to match the G++ mangling algorithm. */
2341 success
= demangle_template(work
, mangled
, &temp
,
2346 else if (*mangled
[0] == 'K')
2350 idx
= consume_count_with_underscores (mangled
);
2351 if (idx
== -1 || idx
> work
->numk
)
2354 string_append (&temp
, work
->ktypevec
[idx
]);
2357 if (!success
) break;
2361 success
= do_type (work
, mangled
, &last_name
);
2364 string_appends (&temp
, &last_name
);
2368 remember_Ktype (work
, temp
.b
, LEN_STRING (&temp
));
2371 string_append (&temp
, SCOPE_STRING (work
));
2374 remember_Btype (work
, temp
.b
, LEN_STRING (&temp
), bindex
);
2376 /* If we are using the result as a function name, we need to append
2377 the appropriate '::' separated constructor or destructor name.
2378 We do this here because this is the most convenient place, where
2379 we already have a pointer to the name and the length of the name. */
2383 string_append (&temp
, SCOPE_STRING (work
));
2384 if (work
-> destructor
& 1)
2385 string_append (&temp
, "~");
2386 string_appends (&temp
, &last_name
);
2389 /* Now either prepend the temp buffer to the result, or append it,
2390 depending upon the state of the append flag. */
2393 string_appends (result
, &temp
);
2396 if (!STRING_EMPTY (result
))
2397 string_append (&temp
, SCOPE_STRING (work
));
2398 string_prepends (result
, &temp
);
2401 string_delete (&last_name
);
2402 string_delete (&temp
);
2410 get_count -- convert an ascii count to integer, consuming tokens
2415 get_count (const char **type, int *count)
2419 Return 0 if no conversion is performed, 1 if a string is converted.
2423 get_count (type
, count
)
2430 if (!isdigit (**type
))
2436 *count
= **type
- '0';
2438 if (isdigit (**type
))
2448 while (isdigit (*p
));
2459 /* RESULT will be initialised here; it will be freed on failure. The
2460 value returned is really a type_kind_t. */
2463 do_type (work
, mangled
, result
)
2464 struct work_stuff
*work
;
2465 const char **mangled
;
2472 const char *remembered_type
;
2476 type_kind_t tk
= tk_none
;
2478 string_init (&btype
);
2479 string_init (&decl
);
2480 string_init (result
);
2484 while (success
&& !done
)
2490 /* A pointer type */
2494 string_prepend (&decl
, "*");
2499 /* A reference type */
2502 string_prepend (&decl
, "&");
2511 if (!STRING_EMPTY (&decl
)
2512 && (decl
.b
[0] == '*' || decl
.b
[0] == '&'))
2514 string_prepend (&decl
, "(");
2515 string_append (&decl
, ")");
2517 string_append (&decl
, "[");
2518 if (**mangled
!= '_')
2519 success
= demangle_template_value_parm (work
, mangled
, &decl
,
2521 if (**mangled
== '_')
2523 string_append (&decl
, "]");
2527 /* A back reference to a previously seen type */
2530 if (!get_count (mangled
, &n
) || n
>= work
-> ntypes
)
2536 remembered_type
= work
-> typevec
[n
];
2537 mangled
= &remembered_type
;
2544 if (!STRING_EMPTY (&decl
)
2545 && (decl
.b
[0] == '*' || decl
.b
[0] == '&'))
2547 string_prepend (&decl
, "(");
2548 string_append (&decl
, ")");
2550 /* After picking off the function args, we expect to either find the
2551 function return type (preceded by an '_') or the end of the
2553 if (!demangle_nested_args (work
, mangled
, &decl
)
2554 || (**mangled
!= '_' && **mangled
!= '\0'))
2559 if (success
&& (**mangled
== '_'))
2569 member
= **mangled
== 'M';
2571 if (!isdigit (**mangled
) && **mangled
!= 't')
2577 string_append (&decl
, ")");
2578 string_prepend (&decl
, SCOPE_STRING (work
));
2579 if (isdigit (**mangled
))
2581 n
= consume_count (mangled
);
2582 if (strlen (*mangled
) < n
)
2587 string_prependn (&decl
, *mangled
, n
);
2593 string_init (&temp
);
2594 success
= demangle_template (work
, mangled
, &temp
,
2598 string_prependn (&decl
, temp
.b
, temp
.p
- temp
.b
);
2599 string_clear (&temp
);
2604 string_prepend (&decl
, "(");
2607 if (**mangled
== 'C')
2612 if (**mangled
== 'V')
2617 if (*(*mangled
)++ != 'F')
2623 if ((member
&& !demangle_nested_args (work
, mangled
, &decl
))
2624 || **mangled
!= '_')
2630 if (! PRINT_ANSI_QUALIFIERS
)
2636 APPEND_BLANK (&decl
);
2637 string_append (&decl
, "const");
2641 APPEND_BLANK (&decl
);
2642 string_append (&decl
, "volatile");
2653 if ((*mangled)[1] == 'P')
2656 if (PRINT_ANSI_QUALIFIERS
)
2658 if (!STRING_EMPTY (&decl
))
2660 string_prepend (&decl
, " ");
2662 string_prepend (&decl
,
2663 (**mangled
) == 'C' ? "const" : "volatile");
2678 if (success
) switch (**mangled
)
2680 /* A qualified name, such as "Outer::Inner". */
2684 success
= demangle_qualified (work
, mangled
, result
, 0, 1);
2688 /* A back reference to a previously seen squangled type */
2691 if (!get_count (mangled
, &n
) || n
>= work
-> numb
)
2694 string_append (result
, work
->btypevec
[n
]);
2699 /* A template parm. We substitute the corresponding argument. */
2704 idx
= consume_count_with_underscores (mangled
);
2707 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
2708 || consume_count_with_underscores (mangled
) == -1)
2714 if (work
->tmpl_argvec
)
2715 string_append (result
, work
->tmpl_argvec
[idx
]);
2719 sprintf(buf
, "T%d", idx
);
2720 string_append (result
, buf
);
2728 success
= demangle_fund_type (work
, mangled
, result
);
2730 tk
= (type_kind_t
) success
;
2736 if (!STRING_EMPTY (&decl
))
2738 string_append (result
, " ");
2739 string_appends (result
, &decl
);
2743 string_delete (result
);
2744 string_delete (&decl
);
2747 /* Assume an integral type, if we're not sure. */
2748 return (int) ((tk
== tk_none
) ? tk_integral
: tk
);
2753 /* Given a pointer to a type string that represents a fundamental type
2754 argument (int, long, unsigned int, etc) in TYPE, a pointer to the
2755 string in which the demangled output is being built in RESULT, and
2756 the WORK structure, decode the types and add them to the result.
2761 "Sl" => "signed long"
2762 "CUs" => "const unsigned short"
2764 The value returned is really a type_kind_t. */
2767 demangle_fund_type (work
, mangled
, result
)
2768 struct work_stuff
*work
;
2769 const char **mangled
;
2775 type_kind_t tk
= tk_integral
;
2777 string_init (&btype
);
2779 /* First pick off any type qualifiers. There can be more than one. */
2787 if (PRINT_ANSI_QUALIFIERS
)
2789 APPEND_BLANK (result
);
2790 string_append (result
, "const");
2795 APPEND_BLANK (result
);
2796 string_append (result
, "unsigned");
2798 case 'S': /* signed char only */
2800 APPEND_BLANK (result
);
2801 string_append (result
, "signed");
2805 if (PRINT_ANSI_QUALIFIERS
)
2807 APPEND_BLANK (result
);
2808 string_append (result
, "volatile");
2813 APPEND_BLANK (result
);
2814 string_append (result
, "__complex");
2822 /* Now pick off the fundamental type. There can be only one. */
2831 APPEND_BLANK (result
);
2832 string_append (result
, "void");
2836 APPEND_BLANK (result
);
2837 string_append (result
, "long long");
2841 APPEND_BLANK (result
);
2842 string_append (result
, "long");
2846 APPEND_BLANK (result
);
2847 string_append (result
, "int");
2851 APPEND_BLANK (result
);
2852 string_append (result
, "short");
2856 APPEND_BLANK (result
);
2857 string_append (result
, "bool");
2862 APPEND_BLANK (result
);
2863 string_append (result
, "char");
2868 APPEND_BLANK (result
);
2869 string_append (result
, "wchar_t");
2874 APPEND_BLANK (result
);
2875 string_append (result
, "long double");
2880 APPEND_BLANK (result
);
2881 string_append (result
, "double");
2886 APPEND_BLANK (result
);
2887 string_append (result
, "float");
2892 if (!isdigit (**mangled
))
2898 /* An explicit type, such as "6mytype" or "7integer" */
2910 int bindex
= register_Btype (work
);
2912 string_init (&btype
);
2913 if (demangle_class_name (work
, mangled
, &btype
)) {
2914 remember_Btype (work
, btype
.b
, LEN_STRING (&btype
), bindex
);
2915 APPEND_BLANK (result
);
2916 string_appends (result
, &btype
);
2920 string_delete (&btype
);
2925 success
= demangle_template (work
, mangled
, &btype
, 0, 1, 1);
2926 string_appends (result
, &btype
);
2934 return success
? ((int) tk
) : 0;
2937 /* Demangle the next argument, given by MANGLED into RESULT, which
2938 *should be an uninitialized* string. It will be initialized here,
2939 and free'd should anything go wrong. */
2942 do_arg (work
, mangled
, result
)
2943 struct work_stuff
*work
;
2944 const char **mangled
;
2947 /* Remember where we started so that we can record the type, for
2948 non-squangling type remembering. */
2949 const char *start
= *mangled
;
2951 string_init (result
);
2953 if (work
->nrepeats
> 0)
2957 if (work
->previous_argument
== 0)
2960 /* We want to reissue the previous type in this argument list. */
2961 string_appends (result
, work
->previous_argument
);
2965 if (**mangled
== 'n')
2967 /* A squangling-style repeat. */
2969 work
->nrepeats
= consume_count(mangled
);
2971 if (work
->nrepeats
== 0)
2972 /* This was not a repeat count after all. */
2975 if (work
->nrepeats
> 9)
2977 if (**mangled
!= '_')
2978 /* The repeat count should be followed by an '_' in this
2985 /* Now, the repeat is all set up. */
2986 return do_arg (work
, mangled
, result
);
2989 /* Save the result in WORK->previous_argument so that we can find it
2990 if it's repeated. Note that saving START is not good enough: we
2991 do not want to add additional types to the back-referenceable
2992 type vector when processing a repeated type. */
2993 if (work
->previous_argument
)
2994 string_clear (work
->previous_argument
);
2997 work
->previous_argument
= (string
*) xmalloc (sizeof (string
));
2998 string_init (work
->previous_argument
);
3001 if (!do_type (work
, mangled
, work
->previous_argument
))
3004 string_appends (result
, work
->previous_argument
);
3006 remember_type (work
, start
, *mangled
- start
);
3011 remember_type (work
, start
, len
)
3012 struct work_stuff
*work
;
3018 if (work
->forgetting_types
)
3021 if (work
-> ntypes
>= work
-> typevec_size
)
3023 if (work
-> typevec_size
== 0)
3025 work
-> typevec_size
= 3;
3027 = (char **) xmalloc (sizeof (char *) * work
-> typevec_size
);
3031 work
-> typevec_size
*= 2;
3033 = (char **) xrealloc ((char *)work
-> typevec
,
3034 sizeof (char *) * work
-> typevec_size
);
3037 tem
= xmalloc (len
+ 1);
3038 memcpy (tem
, start
, len
);
3040 work
-> typevec
[work
-> ntypes
++] = tem
;
3044 /* Remember a K type class qualifier. */
3046 remember_Ktype (work
, start
, len
)
3047 struct work_stuff
*work
;
3053 if (work
-> numk
>= work
-> ksize
)
3055 if (work
-> ksize
== 0)
3059 = (char **) xmalloc (sizeof (char *) * work
-> ksize
);
3065 = (char **) xrealloc ((char *)work
-> ktypevec
,
3066 sizeof (char *) * work
-> ksize
);
3069 tem
= xmalloc (len
+ 1);
3070 memcpy (tem
, start
, len
);
3072 work
-> ktypevec
[work
-> numk
++] = tem
;
3075 /* Register a B code, and get an index for it. B codes are registered
3076 as they are seen, rather than as they are completed, so map<temp<char> >
3077 registers map<temp<char> > as B0, and temp<char> as B1 */
3080 register_Btype (work
)
3081 struct work_stuff
*work
;
3085 if (work
-> numb
>= work
-> bsize
)
3087 if (work
-> bsize
== 0)
3091 = (char **) xmalloc (sizeof (char *) * work
-> bsize
);
3097 = (char **) xrealloc ((char *)work
-> btypevec
,
3098 sizeof (char *) * work
-> bsize
);
3101 ret
= work
-> numb
++;
3102 work
-> btypevec
[ret
] = NULL
;
3106 /* Store a value into a previously registered B code type. */
3109 remember_Btype (work
, start
, len
, index
)
3110 struct work_stuff
*work
;
3116 tem
= xmalloc (len
+ 1);
3117 memcpy (tem
, start
, len
);
3119 work
-> btypevec
[index
] = tem
;
3122 /* Lose all the info related to B and K type codes. */
3124 forget_B_and_K_types (work
)
3125 struct work_stuff
*work
;
3129 while (work
-> numk
> 0)
3131 i
= --(work
-> numk
);
3132 if (work
-> ktypevec
[i
] != NULL
)
3134 free (work
-> ktypevec
[i
]);
3135 work
-> ktypevec
[i
] = NULL
;
3139 while (work
-> numb
> 0)
3141 i
= --(work
-> numb
);
3142 if (work
-> btypevec
[i
] != NULL
)
3144 free (work
-> btypevec
[i
]);
3145 work
-> btypevec
[i
] = NULL
;
3149 /* Forget the remembered types, but not the type vector itself. */
3153 struct work_stuff
*work
;
3157 while (work
-> ntypes
> 0)
3159 i
= --(work
-> ntypes
);
3160 if (work
-> typevec
[i
] != NULL
)
3162 free (work
-> typevec
[i
]);
3163 work
-> typevec
[i
] = NULL
;
3168 /* Process the argument list part of the signature, after any class spec
3169 has been consumed, as well as the first 'F' character (if any). For
3172 "__als__3fooRT0" => process "RT0"
3173 "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i"
3175 DECLP must be already initialised, usually non-empty. It won't be freed
3178 Note that g++ differs significantly from ARM and lucid style mangling
3179 with regards to references to previously seen types. For example, given
3180 the source fragment:
3184 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
3187 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3188 void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3190 g++ produces the names:
3195 while lcc (and presumably other ARM style compilers as well) produces:
3197 foo__FiR3fooT1T2T1T2
3198 __ct__3fooFiR3fooT1T2T1T2
3200 Note that g++ bases its type numbers starting at zero and counts all
3201 previously seen types, while lucid/ARM bases its type numbers starting
3202 at one and only considers types after it has seen the 'F' character
3203 indicating the start of the function args. For lucid/ARM style, we
3204 account for this difference by discarding any previously seen types when
3205 we see the 'F' character, and subtracting one from the type number
3211 demangle_args (work
, mangled
, declp
)
3212 struct work_stuff
*work
;
3213 const char **mangled
;
3223 if (PRINT_ARG_TYPES
)
3225 string_append (declp
, "(");
3226 if (**mangled
== '\0')
3228 string_append (declp
, "void");
3232 while ((**mangled
!= '_' && **mangled
!= '\0' && **mangled
!= 'e')
3233 || work
->nrepeats
> 0)
3235 if ((**mangled
== 'N') || (**mangled
== 'T'))
3237 temptype
= *(*mangled
)++;
3239 if (temptype
== 'N')
3241 if (!get_count (mangled
, &r
))
3250 if (ARM_DEMANGLING
&& work
-> ntypes
>= 10)
3252 /* If we have 10 or more types we might have more than a 1 digit
3253 index so we'll have to consume the whole count here. This
3254 will lose if the next thing is a type name preceded by a
3255 count but it's impossible to demangle that case properly
3256 anyway. Eg if we already have 12 types is T12Pc "(..., type1,
3257 Pc, ...)" or "(..., type12, char *, ...)" */
3258 if ((t
= consume_count(mangled
)) == 0)
3265 if (!get_count (mangled
, &t
))
3270 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
3274 /* Validate the type index. Protect against illegal indices from
3275 malformed type strings. */
3276 if ((t
< 0) || (t
>= work
-> ntypes
))
3280 while (work
->nrepeats
> 0 || --r
>= 0)
3282 tem
= work
-> typevec
[t
];
3283 if (need_comma
&& PRINT_ARG_TYPES
)
3285 string_append (declp
, ", ");
3287 if (!do_arg (work
, &tem
, &arg
))
3291 if (PRINT_ARG_TYPES
)
3293 string_appends (declp
, &arg
);
3295 string_delete (&arg
);
3301 if (need_comma
&& PRINT_ARG_TYPES
)
3302 string_append (declp
, ", ");
3303 if (!do_arg (work
, mangled
, &arg
))
3305 if (PRINT_ARG_TYPES
)
3306 string_appends (declp
, &arg
);
3307 string_delete (&arg
);
3312 if (**mangled
== 'e')
3315 if (PRINT_ARG_TYPES
)
3319 string_append (declp
, ",");
3321 string_append (declp
, "...");
3325 if (PRINT_ARG_TYPES
)
3327 string_append (declp
, ")");
3332 /* Like demangle_args, but for demangling the argument lists of function
3333 and method pointers or references, not top-level declarations. */
3336 demangle_nested_args (work
, mangled
, declp
)
3337 struct work_stuff
*work
;
3338 const char **mangled
;
3341 string
* saved_previous_argument
;
3345 /* The G++ name-mangling algorithm does not remember types on nested
3346 argument lists, unless -fsquangling is used, and in that case the
3347 type vector updated by remember_type is not used. So, we turn
3348 off remembering of types here. */
3349 ++work
->forgetting_types
;
3351 /* For the repeat codes used with -fsquangling, we must keep track of
3352 the last argument. */
3353 saved_previous_argument
= work
->previous_argument
;
3354 saved_nrepeats
= work
->nrepeats
;
3355 work
->previous_argument
= 0;
3358 /* Actually demangle the arguments. */
3359 result
= demangle_args (work
, mangled
, declp
);
3361 /* Restore the previous_argument field. */
3362 if (work
->previous_argument
)
3363 string_delete (work
->previous_argument
);
3364 work
->previous_argument
= saved_previous_argument
;
3365 work
->nrepeats
= saved_nrepeats
;
3371 demangle_function_name (work
, mangled
, declp
, scan
)
3372 struct work_stuff
*work
;
3373 const char **mangled
;
3381 string_appendn (declp
, (*mangled
), scan
- (*mangled
));
3382 string_need (declp
, 1);
3383 *(declp
-> p
) = '\0';
3385 /* Consume the function name, including the "__" separating the name
3386 from the signature. We are guaranteed that SCAN points to the
3389 (*mangled
) = scan
+ 2;
3391 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
3394 /* See if we have an ARM style constructor or destructor operator.
3395 If so, then just record it, clear the decl, and return.
3396 We can't build the actual constructor/destructor decl until later,
3397 when we recover the class name from the signature. */
3399 if (strcmp (declp
-> b
, "__ct") == 0)
3401 work
-> constructor
+= 1;
3402 string_clear (declp
);
3405 else if (strcmp (declp
-> b
, "__dt") == 0)
3407 work
-> destructor
+= 1;
3408 string_clear (declp
);
3413 if (declp
->p
- declp
->b
>= 3
3414 && declp
->b
[0] == 'o'
3415 && declp
->b
[1] == 'p'
3416 && strchr (cplus_markers
, declp
->b
[2]) != NULL
)
3418 /* see if it's an assignment expression */
3419 if (declp
->p
- declp
->b
>= 10 /* op$assign_ */
3420 && memcmp (declp
->b
+ 3, "assign_", 7) == 0)
3422 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3424 int len
= declp
->p
- declp
->b
- 10;
3425 if (strlen (optable
[i
].in
) == len
3426 && memcmp (optable
[i
].in
, declp
->b
+ 10, len
) == 0)
3428 string_clear (declp
);
3429 string_append (declp
, "operator");
3430 string_append (declp
, optable
[i
].out
);
3431 string_append (declp
, "=");
3438 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3440 int len
= declp
->p
- declp
->b
- 3;
3441 if (strlen (optable
[i
].in
) == len
3442 && memcmp (optable
[i
].in
, declp
->b
+ 3, len
) == 0)
3444 string_clear (declp
);
3445 string_append (declp
, "operator");
3446 string_append (declp
, optable
[i
].out
);
3452 else if (declp
->p
- declp
->b
>= 5 && memcmp (declp
->b
, "type", 4) == 0
3453 && strchr (cplus_markers
, declp
->b
[4]) != NULL
)
3455 /* type conversion operator */
3457 if (do_type (work
, &tem
, &type
))
3459 string_clear (declp
);
3460 string_append (declp
, "operator ");
3461 string_appends (declp
, &type
);
3462 string_delete (&type
);
3465 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
3466 && declp
->b
[2] == 'o' && declp
->b
[3] == 'p')
3469 /* type conversion operator. */
3471 if (do_type (work
, &tem
, &type
))
3473 string_clear (declp
);
3474 string_append (declp
, "operator ");
3475 string_appends (declp
, &type
);
3476 string_delete (&type
);
3479 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
3480 && declp
->b
[2] >= 'a' && declp
->b
[2] <= 'z'
3481 && declp
->b
[3] >= 'a' && declp
->b
[3] <= 'z')
3483 if (declp
->b
[4] == '\0')
3486 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3488 if (strlen (optable
[i
].in
) == 2
3489 && memcmp (optable
[i
].in
, declp
->b
+ 2, 2) == 0)
3491 string_clear (declp
);
3492 string_append (declp
, "operator");
3493 string_append (declp
, optable
[i
].out
);
3500 if (declp
->b
[2] == 'a' && declp
->b
[5] == '\0')
3503 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3505 if (strlen (optable
[i
].in
) == 3
3506 && memcmp (optable
[i
].in
, declp
->b
+ 2, 3) == 0)
3508 string_clear (declp
);
3509 string_append (declp
, "operator");
3510 string_append (declp
, optable
[i
].out
);
3519 /* a mini string-handling package */
3534 s
->p
= s
->b
= xmalloc (n
);
3537 else if (s
->e
- s
->p
< n
)
3542 s
->b
= xrealloc (s
->b
, n
);
3555 s
->b
= s
->e
= s
->p
= NULL
;
3563 s
->b
= s
->p
= s
->e
= NULL
;
3579 return (s
->b
== s
->p
);
3585 string_append (p
, s
)
3590 if (s
== NULL
|| *s
== '\0')
3594 memcpy (p
->p
, s
, n
);
3599 string_appends (p
, s
)
3608 memcpy (p
->p
, s
->b
, n
);
3614 string_appendn (p
, s
, n
)
3622 memcpy (p
->p
, s
, n
);
3628 string_prepend (p
, s
)
3632 if (s
!= NULL
&& *s
!= '\0')
3634 string_prependn (p
, s
, strlen (s
));
3639 string_prepends (p
, s
)
3644 string_prependn (p
, s
->b
, s
->p
- s
->b
);
3649 string_prependn (p
, s
, n
)
3659 for (q
= p
->p
- 1; q
>= p
->b
; q
--)
3663 memcpy (p
->b
, s
, n
);
3668 /* To generate a standalone demangler program for testing purposes,
3669 just compile and link this file with -DMAIN and libiberty.a. When
3670 run, it demangles each command line arg, or each stdin string, and
3671 prints the result on stdout. */
3677 static char *program_name
;
3678 static char *program_version
= VERSION
;
3679 static int flags
= DMGL_PARAMS
| DMGL_ANSI
;
3681 static void demangle_it
PARAMS ((char *));
3682 static void usage
PARAMS ((FILE *, int));
3683 static void fatal
PARAMS ((char *));
3686 demangle_it (mangled_name
)
3691 result
= cplus_demangle (mangled_name
, flags
);
3694 printf ("%s\n", mangled_name
);
3698 printf ("%s\n", result
);
3704 usage (stream
, status
)
3709 Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
3710 [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\
3711 [--help] [--version] [arg...]\n",
3716 #define MBUF_SIZE 32767
3717 char mbuffer
[MBUF_SIZE
];
3719 /* Defined in the automatically-generated underscore.c. */
3720 extern int prepends_underscore
;
3722 int strip_underscore
= 0;
3724 static struct option long_options
[] = {
3725 {"strip-underscores", no_argument
, 0, '_'},
3726 {"format", required_argument
, 0, 's'},
3727 {"help", no_argument
, 0, 'h'},
3728 {"no-strip-underscores", no_argument
, 0, 'n'},
3729 {"version", no_argument
, 0, 'v'},
3730 {0, no_argument
, 0, 0}
3733 /* More 'friendly' abort that prints the line and file.
3734 config.h can #define abort fancy_abort if you like that sort of thing. */
3739 fatal ("Internal gcc abort.");
3750 program_name
= argv
[0];
3752 strip_underscore
= prepends_underscore
;
3754 while ((c
= getopt_long (argc
, argv
, "_ns:j", long_options
, (int *) 0)) != EOF
)
3764 strip_underscore
= 0;
3767 printf ("GNU %s version %s\n", program_name
, program_version
);
3770 strip_underscore
= 1;
3773 if (strcmp (optarg
, "gnu") == 0)
3775 current_demangling_style
= gnu_demangling
;
3777 else if (strcmp (optarg
, "lucid") == 0)
3779 current_demangling_style
= lucid_demangling
;
3781 else if (strcmp (optarg
, "arm") == 0)
3783 current_demangling_style
= arm_demangling
;
3787 fprintf (stderr
, "%s: unknown demangling style `%s'\n",
3788 program_name
, optarg
);
3797 for ( ; optind
< argc
; optind
++)
3799 demangle_it (argv
[optind
]);
3808 /* Try to read a label. */
3809 while (c
!= EOF
&& (isalnum(c
) || c
== '_' || c
== '$' || c
== '.'))
3811 if (i
>= MBUF_SIZE
-1)
3820 if (mbuffer
[0] == '.')
3822 if (strip_underscore
&& mbuffer
[skip_first
] == '_')
3830 result
= cplus_demangle (mbuffer
+ skip_first
, flags
);
3833 if (mbuffer
[0] == '.')
3835 fputs (result
, stdout
);
3839 fputs (mbuffer
, stdout
);
3856 fprintf (stderr
, "%s: %s\n", program_name
, str
);
3864 register char *value
= (char *) malloc (size
);
3866 fatal ("virtual memory exhausted");
3871 xrealloc (ptr
, size
)
3875 register char *value
= (char *) realloc (ptr
, size
);
3877 fatal ("virtual memory exhausted");