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
, ">");
1628 else if (n
>10 && strncmp (*mangled
, "_GLOBAL_", 8) == 0
1629 && (*mangled
)[9] == 'N'
1630 && (*mangled
)[8] == (*mangled
)[10]
1631 && strchr (cplus_markers
, (*mangled
)[8]))
1633 /* A member of the anonymous namespace. */
1634 string_append (declp
, "{anonymous}");
1638 string_appendn (declp
, *mangled
, n
);
1644 demangle_class_name (work
, mangled
, declp
)
1645 struct work_stuff
*work
;
1646 const char **mangled
;
1652 n
= consume_count (mangled
);
1653 if (strlen (*mangled
) >= n
)
1655 demangle_arm_pt (work
, mangled
, n
, declp
);
1666 demangle_class -- demangle a mangled class sequence
1671 demangle_class (struct work_stuff *work, const char **mangled,
1676 DECLP points to the buffer into which demangling is being done.
1678 *MANGLED points to the current token to be demangled. On input,
1679 it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
1680 On exit, it points to the next token after the mangled class on
1681 success, or the first unconsumed token on failure.
1683 If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
1684 we are demangling a constructor or destructor. In this case
1685 we prepend "class::class" or "class::~class" to DECLP.
1687 Otherwise, we prepend "class::" to the current DECLP.
1689 Reset the constructor/destructor flags once they have been
1690 "consumed". This allows demangle_class to be called later during
1691 the same demangling, to do normal class demangling.
1693 Returns 1 if demangling is successful, 0 otherwise.
1698 demangle_class (work
, mangled
, declp
)
1699 struct work_stuff
*work
;
1700 const char **mangled
;
1707 string_init (&class_name
);
1708 btype
= register_Btype (work
);
1709 if (demangle_class_name (work
, mangled
, &class_name
))
1711 if ((work
->constructor
& 1) || (work
->destructor
& 1))
1713 string_prepends (declp
, &class_name
);
1714 if (work
-> destructor
& 1)
1716 string_prepend (declp
, "~");
1717 work
-> destructor
-= 1;
1721 work
-> constructor
-= 1;
1724 remember_Ktype (work
, class_name
.b
, LEN_STRING(&class_name
));
1725 remember_Btype (work
, class_name
.b
, LEN_STRING(&class_name
), btype
);
1726 string_prepend (declp
, SCOPE_STRING (work
));
1727 string_prepends (declp
, &class_name
);
1730 string_delete (&class_name
);
1738 demangle_prefix -- consume the mangled name prefix and find signature
1743 demangle_prefix (struct work_stuff *work, const char **mangled,
1748 Consume and demangle the prefix of the mangled name.
1750 DECLP points to the string buffer into which demangled output is
1751 placed. On entry, the buffer is empty. On exit it contains
1752 the root function name, the demangled operator name, or in some
1753 special cases either nothing or the completely demangled result.
1755 MANGLED points to the current pointer into the mangled name. As each
1756 token of the mangled name is consumed, it is updated. Upon entry
1757 the current mangled name pointer points to the first character of
1758 the mangled name. Upon exit, it should point to the first character
1759 of the signature if demangling was successful, or to the first
1760 unconsumed character if demangling of the prefix was unsuccessful.
1762 Returns 1 on success, 0 otherwise.
1766 demangle_prefix (work
, mangled
, declp
)
1767 struct work_stuff
*work
;
1768 const char **mangled
;
1775 if (strlen(*mangled
) > 6
1776 && (strncmp(*mangled
, "_imp__", 6) == 0
1777 || strncmp(*mangled
, "__imp_", 6) == 0))
1779 /* it's a symbol imported from a PE dynamic library. Check for both
1780 new style prefix _imp__ and legacy __imp_ used by older versions
1783 work
->dllimported
= 1;
1785 else if (strlen(*mangled
) >= 11 && strncmp(*mangled
, "_GLOBAL_", 8) == 0)
1787 char *marker
= strchr (cplus_markers
, (*mangled
)[8]);
1788 if (marker
!= NULL
&& *marker
== (*mangled
)[10])
1790 if ((*mangled
)[9] == 'D')
1792 /* it's a GNU global destructor to be executed at program exit */
1794 work
->destructor
= 2;
1795 if (gnu_special (work
, mangled
, declp
))
1798 else if ((*mangled
)[9] == 'I')
1800 /* it's a GNU global constructor to be executed at program init */
1802 work
->constructor
= 2;
1803 if (gnu_special (work
, mangled
, declp
))
1808 else if (ARM_DEMANGLING
&& strncmp(*mangled
, "__std__", 7) == 0)
1810 /* it's a ARM global destructor to be executed at program exit */
1812 work
->destructor
= 2;
1814 else if (ARM_DEMANGLING
&& strncmp(*mangled
, "__sti__", 7) == 0)
1816 /* it's a ARM global constructor to be executed at program initial */
1818 work
->constructor
= 2;
1821 /* This block of code is a reduction in strength time optimization
1823 scan = mystrstr (*mangled, "__"); */
1829 scan
= strchr (scan
, '_');
1830 } while (scan
!= NULL
&& *++scan
!= '_');
1832 if (scan
!= NULL
) --scan
;
1837 /* We found a sequence of two or more '_', ensure that we start at
1838 the last pair in the sequence. */
1839 i
= strspn (scan
, "_");
1850 else if (work
-> static_type
)
1852 if (!isdigit (scan
[0]) && (scan
[0] != 't'))
1857 else if ((scan
== *mangled
)
1858 && (isdigit (scan
[2]) || (scan
[2] == 'Q') || (scan
[2] == 't')
1859 || (scan
[2] == 'K') || (scan
[2] == 'H')))
1861 /* The ARM says nothing about the mangling of local variables.
1862 But cfront mangles local variables by prepending __<nesting_level>
1863 to them. As an extension to ARM demangling we handle this case. */
1864 if ((LUCID_DEMANGLING
|| ARM_DEMANGLING
) && isdigit (scan
[2]))
1866 *mangled
= scan
+ 2;
1867 consume_count (mangled
);
1868 string_append (declp
, *mangled
);
1869 *mangled
+= strlen (*mangled
);
1874 /* A GNU style constructor starts with __[0-9Qt]. But cfront uses
1875 names like __Q2_3foo3bar for nested type names. So don't accept
1876 this style of constructor for cfront demangling. A GNU
1877 style member-template constructor starts with 'H'. */
1878 if (!(LUCID_DEMANGLING
|| ARM_DEMANGLING
))
1879 work
-> constructor
+= 1;
1880 *mangled
= scan
+ 2;
1883 else if ((scan
== *mangled
) && !isdigit (scan
[2]) && (scan
[2] != 't'))
1885 /* Mangled name starts with "__". Skip over any leading '_' characters,
1886 then find the next "__" that separates the prefix from the signature.
1888 if (!(ARM_DEMANGLING
|| LUCID_DEMANGLING
)
1889 || (arm_special (mangled
, declp
) == 0))
1891 while (*scan
== '_')
1895 if ((scan
= mystrstr (scan
, "__")) == NULL
|| (*(scan
+ 2) == '\0'))
1897 /* No separator (I.E. "__not_mangled"), or empty signature
1898 (I.E. "__not_mangled_either__") */
1903 demangle_function_name (work
, mangled
, declp
, scan
);
1907 else if (ARM_DEMANGLING
&& scan
[2] == 'p' && scan
[3] == 't')
1909 /* Cfront-style parameterized type. Handled later as a signature. */
1913 demangle_arm_pt (work
, mangled
, strlen (*mangled
), declp
);
1915 else if (*(scan
+ 2) != '\0')
1917 /* Mangled name does not start with "__" but does have one somewhere
1918 in there with non empty stuff after it. Looks like a global
1920 demangle_function_name (work
, mangled
, declp
, scan
);
1924 /* Doesn't look like a mangled name */
1928 if (!success
&& (work
->constructor
== 2 || work
->destructor
== 2))
1930 string_append (declp
, *mangled
);
1931 *mangled
+= strlen (*mangled
);
1941 gnu_special -- special handling of gnu mangled strings
1946 gnu_special (struct work_stuff *work, const char **mangled,
1952 Process some special GNU style mangling forms that don't fit
1953 the normal pattern. For example:
1955 _$_3foo (destructor for class foo)
1956 _vt$foo (foo virtual table)
1957 _vt$foo$bar (foo::bar virtual table)
1958 __vt_foo (foo virtual table, new style with thunks)
1959 _3foo$varname (static data member)
1960 _Q22rs2tu$vw (static data member)
1961 __t6vector1Zii (constructor with template)
1962 __thunk_4__$_7ostream (virtual function thunk)
1966 gnu_special (work
, mangled
, declp
)
1967 struct work_stuff
*work
;
1968 const char **mangled
;
1975 if ((*mangled
)[0] == '_'
1976 && strchr (cplus_markers
, (*mangled
)[1]) != NULL
1977 && (*mangled
)[2] == '_')
1979 /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
1981 work
-> destructor
+= 1;
1983 else if ((*mangled
)[0] == '_'
1984 && (((*mangled
)[1] == '_'
1985 && (*mangled
)[2] == 'v'
1986 && (*mangled
)[3] == 't'
1987 && (*mangled
)[4] == '_')
1988 || ((*mangled
)[1] == 'v'
1989 && (*mangled
)[2] == 't'
1990 && strchr (cplus_markers
, (*mangled
)[3]) != NULL
)))
1992 /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
1993 and create the decl. Note that we consume the entire mangled
1994 input string, which means that demangle_signature has no work
1996 if ((*mangled
)[2] == 'v')
1997 (*mangled
) += 5; /* New style, with thunks: "__vt_" */
1999 (*mangled
) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
2000 while (**mangled
!= '\0')
2002 p
= strpbrk (*mangled
, cplus_markers
);
2007 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
2010 success
= demangle_template (work
, mangled
, declp
, 0, 1,
2014 if (isdigit(*mangled
[0]))
2016 n
= consume_count(mangled
);
2017 /* We may be seeing a too-large size, or else a
2018 ".<digits>" indicating a static local symbol. In
2019 any case, declare victory and move on; *don't* try
2020 to use n to allocate. */
2021 if (n
> strlen (*mangled
))
2029 n
= strcspn (*mangled
, cplus_markers
);
2031 string_appendn (declp
, *mangled
, n
);
2035 if (success
&& ((p
== NULL
) || (p
== *mangled
)))
2039 string_append (declp
, SCOPE_STRING (work
));
2050 string_append (declp
, " virtual table");
2052 else if ((*mangled
)[0] == '_'
2053 && (strchr("0123456789Qt", (*mangled
)[1]) != NULL
)
2054 && (p
= strpbrk (*mangled
, cplus_markers
)) != NULL
)
2056 /* static data member, "_3foo$varname" for example */
2062 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
2065 success
= demangle_template (work
, mangled
, declp
, 0, 1, 1);
2068 n
= consume_count (mangled
);
2069 string_appendn (declp
, *mangled
, n
);
2072 if (success
&& (p
== *mangled
))
2074 /* Consumed everything up to the cplus_marker, append the
2077 string_append (declp
, SCOPE_STRING (work
));
2078 n
= strlen (*mangled
);
2079 string_appendn (declp
, *mangled
, n
);
2087 else if (strncmp (*mangled
, "__thunk_", 8) == 0)
2089 int delta
= ((*mangled
) += 8, consume_count (mangled
));
2090 char *method
= internal_cplus_demangle (work
, ++*mangled
);
2094 sprintf (buf
, "virtual function thunk (delta:%d) for ", -delta
);
2095 string_append (declp
, buf
);
2096 string_append (declp
, method
);
2098 n
= strlen (*mangled
);
2106 else if (strncmp (*mangled
, "__t", 3) == 0
2107 && ((*mangled
)[3] == 'i' || (*mangled
)[3] == 'f'))
2109 p
= (*mangled
)[3] == 'i' ? " type_info node" : " type_info function";
2115 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
2118 success
= demangle_template (work
, mangled
, declp
, 0, 1, 1);
2121 success
= demangle_fund_type (work
, mangled
, declp
);
2124 if (success
&& **mangled
!= '\0')
2127 string_append (declp
, p
);
2140 arm_special -- special handling of ARM/lucid mangled strings
2145 arm_special (const char **mangled,
2151 Process some special ARM style mangling forms that don't fit
2152 the normal pattern. For example:
2154 __vtbl__3foo (foo virtual table)
2155 __vtbl__3foo__3bar (bar::foo virtual table)
2160 arm_special (mangled
, declp
)
2161 const char **mangled
;
2168 if (strncmp (*mangled
, ARM_VTABLE_STRING
, ARM_VTABLE_STRLEN
) == 0)
2170 /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
2171 and create the decl. Note that we consume the entire mangled
2172 input string, which means that demangle_signature has no work
2174 scan
= *mangled
+ ARM_VTABLE_STRLEN
;
2175 while (*scan
!= '\0') /* first check it can be demangled */
2177 n
= consume_count (&scan
);
2180 return (0); /* no good */
2183 if (scan
[0] == '_' && scan
[1] == '_')
2188 (*mangled
) += ARM_VTABLE_STRLEN
;
2189 while (**mangled
!= '\0')
2191 n
= consume_count (mangled
);
2192 string_prependn (declp
, *mangled
, n
);
2194 if ((*mangled
)[0] == '_' && (*mangled
)[1] == '_')
2196 string_prepend (declp
, "::");
2200 string_append (declp
, " virtual table");
2213 demangle_qualified -- demangle 'Q' qualified name strings
2218 demangle_qualified (struct work_stuff *, const char *mangled,
2219 string *result, int isfuncname, int append);
2223 Demangle a qualified name, such as "Q25Outer5Inner" which is
2224 the mangled form of "Outer::Inner". The demangled output is
2225 prepended or appended to the result string according to the
2226 state of the append flag.
2228 If isfuncname is nonzero, then the qualified name we are building
2229 is going to be used as a member function name, so if it is a
2230 constructor or destructor function, append an appropriate
2231 constructor or destructor name. I.E. for the above example,
2232 the result for use as a constructor is "Outer::Inner::Inner"
2233 and the result for use as a destructor is "Outer::Inner::~Inner".
2237 Numeric conversion is ASCII dependent (FIXME).
2242 demangle_qualified (work
, mangled
, result
, isfuncname
, append
)
2243 struct work_stuff
*work
;
2244 const char **mangled
;
2255 int bindex
= register_Btype (work
);
2257 /* We only make use of ISFUNCNAME if the entity is a constructor or
2259 isfuncname
= (isfuncname
2260 && ((work
->constructor
& 1) || (work
->destructor
& 1)));
2262 string_init (&temp
);
2263 string_init (&last_name
);
2265 if ((*mangled
)[0] == 'K')
2267 /* Squangling qualified name reuse */
2270 idx
= consume_count_with_underscores (mangled
);
2271 if (idx
== -1 || idx
> work
-> numk
)
2274 string_append (&temp
, work
-> ktypevec
[idx
]);
2277 switch ((*mangled
)[1])
2280 /* GNU mangled name with more than 9 classes. The count is preceded
2281 by an underscore (to distinguish it from the <= 9 case) and followed
2282 by an underscore. */
2284 qualifiers
= atoi (p
);
2285 if (!isdigit (*p
) || *p
== '0')
2288 /* Skip the digits. */
2289 while (isdigit (*p
))
2307 /* The count is in a single digit. */
2308 num
[0] = (*mangled
)[1];
2310 qualifiers
= atoi (num
);
2312 /* If there is an underscore after the digit, skip it. This is
2313 said to be for ARM-qualified names, but the ARM makes no
2314 mention of such an underscore. Perhaps cfront uses one. */
2315 if ((*mangled
)[2] == '_')
2330 /* Pick off the names and collect them in the temp buffer in the order
2331 in which they are found, separated by '::'. */
2333 while (qualifiers
-- > 0)
2336 string_clear (&last_name
);
2338 if (*mangled
[0] == '_')
2341 if (*mangled
[0] == 't')
2343 /* Here we always append to TEMP since we will want to use
2344 the template name without the template parameters as a
2345 constructor or destructor name. The appropriate
2346 (parameter-less) value is returned by demangle_template
2347 in LAST_NAME. We do not remember the template type here,
2348 in order to match the G++ mangling algorithm. */
2349 success
= demangle_template(work
, mangled
, &temp
,
2354 else if (*mangled
[0] == 'K')
2358 idx
= consume_count_with_underscores (mangled
);
2359 if (idx
== -1 || idx
> work
->numk
)
2362 string_append (&temp
, work
->ktypevec
[idx
]);
2365 if (!success
) break;
2369 success
= do_type (work
, mangled
, &last_name
);
2372 string_appends (&temp
, &last_name
);
2376 remember_Ktype (work
, temp
.b
, LEN_STRING (&temp
));
2379 string_append (&temp
, SCOPE_STRING (work
));
2382 remember_Btype (work
, temp
.b
, LEN_STRING (&temp
), bindex
);
2384 /* If we are using the result as a function name, we need to append
2385 the appropriate '::' separated constructor or destructor name.
2386 We do this here because this is the most convenient place, where
2387 we already have a pointer to the name and the length of the name. */
2391 string_append (&temp
, SCOPE_STRING (work
));
2392 if (work
-> destructor
& 1)
2393 string_append (&temp
, "~");
2394 string_appends (&temp
, &last_name
);
2397 /* Now either prepend the temp buffer to the result, or append it,
2398 depending upon the state of the append flag. */
2401 string_appends (result
, &temp
);
2404 if (!STRING_EMPTY (result
))
2405 string_append (&temp
, SCOPE_STRING (work
));
2406 string_prepends (result
, &temp
);
2409 string_delete (&last_name
);
2410 string_delete (&temp
);
2418 get_count -- convert an ascii count to integer, consuming tokens
2423 get_count (const char **type, int *count)
2427 Return 0 if no conversion is performed, 1 if a string is converted.
2431 get_count (type
, count
)
2438 if (!isdigit (**type
))
2444 *count
= **type
- '0';
2446 if (isdigit (**type
))
2456 while (isdigit (*p
));
2467 /* RESULT will be initialised here; it will be freed on failure. The
2468 value returned is really a type_kind_t. */
2471 do_type (work
, mangled
, result
)
2472 struct work_stuff
*work
;
2473 const char **mangled
;
2480 const char *remembered_type
;
2484 type_kind_t tk
= tk_none
;
2486 string_init (&btype
);
2487 string_init (&decl
);
2488 string_init (result
);
2492 while (success
&& !done
)
2498 /* A pointer type */
2502 string_prepend (&decl
, "*");
2507 /* A reference type */
2510 string_prepend (&decl
, "&");
2519 if (!STRING_EMPTY (&decl
)
2520 && (decl
.b
[0] == '*' || decl
.b
[0] == '&'))
2522 string_prepend (&decl
, "(");
2523 string_append (&decl
, ")");
2525 string_append (&decl
, "[");
2526 if (**mangled
!= '_')
2527 success
= demangle_template_value_parm (work
, mangled
, &decl
,
2529 if (**mangled
== '_')
2531 string_append (&decl
, "]");
2535 /* A back reference to a previously seen type */
2538 if (!get_count (mangled
, &n
) || n
>= work
-> ntypes
)
2544 remembered_type
= work
-> typevec
[n
];
2545 mangled
= &remembered_type
;
2552 if (!STRING_EMPTY (&decl
)
2553 && (decl
.b
[0] == '*' || decl
.b
[0] == '&'))
2555 string_prepend (&decl
, "(");
2556 string_append (&decl
, ")");
2558 /* After picking off the function args, we expect to either find the
2559 function return type (preceded by an '_') or the end of the
2561 if (!demangle_nested_args (work
, mangled
, &decl
)
2562 || (**mangled
!= '_' && **mangled
!= '\0'))
2567 if (success
&& (**mangled
== '_'))
2577 member
= **mangled
== 'M';
2579 if (!isdigit (**mangled
) && **mangled
!= 't')
2585 string_append (&decl
, ")");
2586 string_prepend (&decl
, SCOPE_STRING (work
));
2587 if (isdigit (**mangled
))
2589 n
= consume_count (mangled
);
2590 if (strlen (*mangled
) < n
)
2595 string_prependn (&decl
, *mangled
, n
);
2601 string_init (&temp
);
2602 success
= demangle_template (work
, mangled
, &temp
,
2606 string_prependn (&decl
, temp
.b
, temp
.p
- temp
.b
);
2607 string_clear (&temp
);
2612 string_prepend (&decl
, "(");
2615 if (**mangled
== 'C')
2620 if (**mangled
== 'V')
2625 if (*(*mangled
)++ != 'F')
2631 if ((member
&& !demangle_nested_args (work
, mangled
, &decl
))
2632 || **mangled
!= '_')
2638 if (! PRINT_ANSI_QUALIFIERS
)
2644 APPEND_BLANK (&decl
);
2645 string_append (&decl
, "const");
2649 APPEND_BLANK (&decl
);
2650 string_append (&decl
, "volatile");
2661 if ((*mangled)[1] == 'P')
2664 if (PRINT_ANSI_QUALIFIERS
)
2666 if (!STRING_EMPTY (&decl
))
2668 string_prepend (&decl
, " ");
2670 string_prepend (&decl
,
2671 (**mangled
) == 'C' ? "const" : "volatile");
2686 if (success
) switch (**mangled
)
2688 /* A qualified name, such as "Outer::Inner". */
2692 success
= demangle_qualified (work
, mangled
, result
, 0, 1);
2696 /* A back reference to a previously seen squangled type */
2699 if (!get_count (mangled
, &n
) || n
>= work
-> numb
)
2702 string_append (result
, work
->btypevec
[n
]);
2707 /* A template parm. We substitute the corresponding argument. */
2712 idx
= consume_count_with_underscores (mangled
);
2715 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
2716 || consume_count_with_underscores (mangled
) == -1)
2722 if (work
->tmpl_argvec
)
2723 string_append (result
, work
->tmpl_argvec
[idx
]);
2727 sprintf(buf
, "T%d", idx
);
2728 string_append (result
, buf
);
2736 success
= demangle_fund_type (work
, mangled
, result
);
2738 tk
= (type_kind_t
) success
;
2744 if (!STRING_EMPTY (&decl
))
2746 string_append (result
, " ");
2747 string_appends (result
, &decl
);
2751 string_delete (result
);
2752 string_delete (&decl
);
2755 /* Assume an integral type, if we're not sure. */
2756 return (int) ((tk
== tk_none
) ? tk_integral
: tk
);
2761 /* Given a pointer to a type string that represents a fundamental type
2762 argument (int, long, unsigned int, etc) in TYPE, a pointer to the
2763 string in which the demangled output is being built in RESULT, and
2764 the WORK structure, decode the types and add them to the result.
2769 "Sl" => "signed long"
2770 "CUs" => "const unsigned short"
2772 The value returned is really a type_kind_t. */
2775 demangle_fund_type (work
, mangled
, result
)
2776 struct work_stuff
*work
;
2777 const char **mangled
;
2783 type_kind_t tk
= tk_integral
;
2785 string_init (&btype
);
2787 /* First pick off any type qualifiers. There can be more than one. */
2795 if (PRINT_ANSI_QUALIFIERS
)
2797 APPEND_BLANK (result
);
2798 string_append (result
, "const");
2803 APPEND_BLANK (result
);
2804 string_append (result
, "unsigned");
2806 case 'S': /* signed char only */
2808 APPEND_BLANK (result
);
2809 string_append (result
, "signed");
2813 if (PRINT_ANSI_QUALIFIERS
)
2815 APPEND_BLANK (result
);
2816 string_append (result
, "volatile");
2821 APPEND_BLANK (result
);
2822 string_append (result
, "__complex");
2830 /* Now pick off the fundamental type. There can be only one. */
2839 APPEND_BLANK (result
);
2840 string_append (result
, "void");
2844 APPEND_BLANK (result
);
2845 string_append (result
, "long long");
2849 APPEND_BLANK (result
);
2850 string_append (result
, "long");
2854 APPEND_BLANK (result
);
2855 string_append (result
, "int");
2859 APPEND_BLANK (result
);
2860 string_append (result
, "short");
2864 APPEND_BLANK (result
);
2865 string_append (result
, "bool");
2870 APPEND_BLANK (result
);
2871 string_append (result
, "char");
2876 APPEND_BLANK (result
);
2877 string_append (result
, "wchar_t");
2882 APPEND_BLANK (result
);
2883 string_append (result
, "long double");
2888 APPEND_BLANK (result
);
2889 string_append (result
, "double");
2894 APPEND_BLANK (result
);
2895 string_append (result
, "float");
2900 if (!isdigit (**mangled
))
2906 /* An explicit type, such as "6mytype" or "7integer" */
2918 int bindex
= register_Btype (work
);
2920 string_init (&btype
);
2921 if (demangle_class_name (work
, mangled
, &btype
)) {
2922 remember_Btype (work
, btype
.b
, LEN_STRING (&btype
), bindex
);
2923 APPEND_BLANK (result
);
2924 string_appends (result
, &btype
);
2928 string_delete (&btype
);
2933 success
= demangle_template (work
, mangled
, &btype
, 0, 1, 1);
2934 string_appends (result
, &btype
);
2942 return success
? ((int) tk
) : 0;
2945 /* Demangle the next argument, given by MANGLED into RESULT, which
2946 *should be an uninitialized* string. It will be initialized here,
2947 and free'd should anything go wrong. */
2950 do_arg (work
, mangled
, result
)
2951 struct work_stuff
*work
;
2952 const char **mangled
;
2955 /* Remember where we started so that we can record the type, for
2956 non-squangling type remembering. */
2957 const char *start
= *mangled
;
2959 string_init (result
);
2961 if (work
->nrepeats
> 0)
2965 if (work
->previous_argument
== 0)
2968 /* We want to reissue the previous type in this argument list. */
2969 string_appends (result
, work
->previous_argument
);
2973 if (**mangled
== 'n')
2975 /* A squangling-style repeat. */
2977 work
->nrepeats
= consume_count(mangled
);
2979 if (work
->nrepeats
== 0)
2980 /* This was not a repeat count after all. */
2983 if (work
->nrepeats
> 9)
2985 if (**mangled
!= '_')
2986 /* The repeat count should be followed by an '_' in this
2993 /* Now, the repeat is all set up. */
2994 return do_arg (work
, mangled
, result
);
2997 /* Save the result in WORK->previous_argument so that we can find it
2998 if it's repeated. Note that saving START is not good enough: we
2999 do not want to add additional types to the back-referenceable
3000 type vector when processing a repeated type. */
3001 if (work
->previous_argument
)
3002 string_clear (work
->previous_argument
);
3005 work
->previous_argument
= (string
*) xmalloc (sizeof (string
));
3006 string_init (work
->previous_argument
);
3009 if (!do_type (work
, mangled
, work
->previous_argument
))
3012 string_appends (result
, work
->previous_argument
);
3014 remember_type (work
, start
, *mangled
- start
);
3019 remember_type (work
, start
, len
)
3020 struct work_stuff
*work
;
3026 if (work
->forgetting_types
)
3029 if (work
-> ntypes
>= work
-> typevec_size
)
3031 if (work
-> typevec_size
== 0)
3033 work
-> typevec_size
= 3;
3035 = (char **) xmalloc (sizeof (char *) * work
-> typevec_size
);
3039 work
-> typevec_size
*= 2;
3041 = (char **) xrealloc ((char *)work
-> typevec
,
3042 sizeof (char *) * work
-> typevec_size
);
3045 tem
= xmalloc (len
+ 1);
3046 memcpy (tem
, start
, len
);
3048 work
-> typevec
[work
-> ntypes
++] = tem
;
3052 /* Remember a K type class qualifier. */
3054 remember_Ktype (work
, start
, len
)
3055 struct work_stuff
*work
;
3061 if (work
-> numk
>= work
-> ksize
)
3063 if (work
-> ksize
== 0)
3067 = (char **) xmalloc (sizeof (char *) * work
-> ksize
);
3073 = (char **) xrealloc ((char *)work
-> ktypevec
,
3074 sizeof (char *) * work
-> ksize
);
3077 tem
= xmalloc (len
+ 1);
3078 memcpy (tem
, start
, len
);
3080 work
-> ktypevec
[work
-> numk
++] = tem
;
3083 /* Register a B code, and get an index for it. B codes are registered
3084 as they are seen, rather than as they are completed, so map<temp<char> >
3085 registers map<temp<char> > as B0, and temp<char> as B1 */
3088 register_Btype (work
)
3089 struct work_stuff
*work
;
3093 if (work
-> numb
>= work
-> bsize
)
3095 if (work
-> bsize
== 0)
3099 = (char **) xmalloc (sizeof (char *) * work
-> bsize
);
3105 = (char **) xrealloc ((char *)work
-> btypevec
,
3106 sizeof (char *) * work
-> bsize
);
3109 ret
= work
-> numb
++;
3110 work
-> btypevec
[ret
] = NULL
;
3114 /* Store a value into a previously registered B code type. */
3117 remember_Btype (work
, start
, len
, index
)
3118 struct work_stuff
*work
;
3124 tem
= xmalloc (len
+ 1);
3125 memcpy (tem
, start
, len
);
3127 work
-> btypevec
[index
] = tem
;
3130 /* Lose all the info related to B and K type codes. */
3132 forget_B_and_K_types (work
)
3133 struct work_stuff
*work
;
3137 while (work
-> numk
> 0)
3139 i
= --(work
-> numk
);
3140 if (work
-> ktypevec
[i
] != NULL
)
3142 free (work
-> ktypevec
[i
]);
3143 work
-> ktypevec
[i
] = NULL
;
3147 while (work
-> numb
> 0)
3149 i
= --(work
-> numb
);
3150 if (work
-> btypevec
[i
] != NULL
)
3152 free (work
-> btypevec
[i
]);
3153 work
-> btypevec
[i
] = NULL
;
3157 /* Forget the remembered types, but not the type vector itself. */
3161 struct work_stuff
*work
;
3165 while (work
-> ntypes
> 0)
3167 i
= --(work
-> ntypes
);
3168 if (work
-> typevec
[i
] != NULL
)
3170 free (work
-> typevec
[i
]);
3171 work
-> typevec
[i
] = NULL
;
3176 /* Process the argument list part of the signature, after any class spec
3177 has been consumed, as well as the first 'F' character (if any). For
3180 "__als__3fooRT0" => process "RT0"
3181 "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i"
3183 DECLP must be already initialised, usually non-empty. It won't be freed
3186 Note that g++ differs significantly from ARM and lucid style mangling
3187 with regards to references to previously seen types. For example, given
3188 the source fragment:
3192 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
3195 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3196 void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3198 g++ produces the names:
3203 while lcc (and presumably other ARM style compilers as well) produces:
3205 foo__FiR3fooT1T2T1T2
3206 __ct__3fooFiR3fooT1T2T1T2
3208 Note that g++ bases its type numbers starting at zero and counts all
3209 previously seen types, while lucid/ARM bases its type numbers starting
3210 at one and only considers types after it has seen the 'F' character
3211 indicating the start of the function args. For lucid/ARM style, we
3212 account for this difference by discarding any previously seen types when
3213 we see the 'F' character, and subtracting one from the type number
3219 demangle_args (work
, mangled
, declp
)
3220 struct work_stuff
*work
;
3221 const char **mangled
;
3231 if (PRINT_ARG_TYPES
)
3233 string_append (declp
, "(");
3234 if (**mangled
== '\0')
3236 string_append (declp
, "void");
3240 while ((**mangled
!= '_' && **mangled
!= '\0' && **mangled
!= 'e')
3241 || work
->nrepeats
> 0)
3243 if ((**mangled
== 'N') || (**mangled
== 'T'))
3245 temptype
= *(*mangled
)++;
3247 if (temptype
== 'N')
3249 if (!get_count (mangled
, &r
))
3258 if (ARM_DEMANGLING
&& work
-> ntypes
>= 10)
3260 /* If we have 10 or more types we might have more than a 1 digit
3261 index so we'll have to consume the whole count here. This
3262 will lose if the next thing is a type name preceded by a
3263 count but it's impossible to demangle that case properly
3264 anyway. Eg if we already have 12 types is T12Pc "(..., type1,
3265 Pc, ...)" or "(..., type12, char *, ...)" */
3266 if ((t
= consume_count(mangled
)) == 0)
3273 if (!get_count (mangled
, &t
))
3278 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
3282 /* Validate the type index. Protect against illegal indices from
3283 malformed type strings. */
3284 if ((t
< 0) || (t
>= work
-> ntypes
))
3288 while (work
->nrepeats
> 0 || --r
>= 0)
3290 tem
= work
-> typevec
[t
];
3291 if (need_comma
&& PRINT_ARG_TYPES
)
3293 string_append (declp
, ", ");
3295 if (!do_arg (work
, &tem
, &arg
))
3299 if (PRINT_ARG_TYPES
)
3301 string_appends (declp
, &arg
);
3303 string_delete (&arg
);
3309 if (need_comma
&& PRINT_ARG_TYPES
)
3310 string_append (declp
, ", ");
3311 if (!do_arg (work
, mangled
, &arg
))
3313 if (PRINT_ARG_TYPES
)
3314 string_appends (declp
, &arg
);
3315 string_delete (&arg
);
3320 if (**mangled
== 'e')
3323 if (PRINT_ARG_TYPES
)
3327 string_append (declp
, ",");
3329 string_append (declp
, "...");
3333 if (PRINT_ARG_TYPES
)
3335 string_append (declp
, ")");
3340 /* Like demangle_args, but for demangling the argument lists of function
3341 and method pointers or references, not top-level declarations. */
3344 demangle_nested_args (work
, mangled
, declp
)
3345 struct work_stuff
*work
;
3346 const char **mangled
;
3349 string
* saved_previous_argument
;
3353 /* The G++ name-mangling algorithm does not remember types on nested
3354 argument lists, unless -fsquangling is used, and in that case the
3355 type vector updated by remember_type is not used. So, we turn
3356 off remembering of types here. */
3357 ++work
->forgetting_types
;
3359 /* For the repeat codes used with -fsquangling, we must keep track of
3360 the last argument. */
3361 saved_previous_argument
= work
->previous_argument
;
3362 saved_nrepeats
= work
->nrepeats
;
3363 work
->previous_argument
= 0;
3366 /* Actually demangle the arguments. */
3367 result
= demangle_args (work
, mangled
, declp
);
3369 /* Restore the previous_argument field. */
3370 if (work
->previous_argument
)
3371 string_delete (work
->previous_argument
);
3372 work
->previous_argument
= saved_previous_argument
;
3373 work
->nrepeats
= saved_nrepeats
;
3379 demangle_function_name (work
, mangled
, declp
, scan
)
3380 struct work_stuff
*work
;
3381 const char **mangled
;
3389 string_appendn (declp
, (*mangled
), scan
- (*mangled
));
3390 string_need (declp
, 1);
3391 *(declp
-> p
) = '\0';
3393 /* Consume the function name, including the "__" separating the name
3394 from the signature. We are guaranteed that SCAN points to the
3397 (*mangled
) = scan
+ 2;
3399 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
3402 /* See if we have an ARM style constructor or destructor operator.
3403 If so, then just record it, clear the decl, and return.
3404 We can't build the actual constructor/destructor decl until later,
3405 when we recover the class name from the signature. */
3407 if (strcmp (declp
-> b
, "__ct") == 0)
3409 work
-> constructor
+= 1;
3410 string_clear (declp
);
3413 else if (strcmp (declp
-> b
, "__dt") == 0)
3415 work
-> destructor
+= 1;
3416 string_clear (declp
);
3421 if (declp
->p
- declp
->b
>= 3
3422 && declp
->b
[0] == 'o'
3423 && declp
->b
[1] == 'p'
3424 && strchr (cplus_markers
, declp
->b
[2]) != NULL
)
3426 /* see if it's an assignment expression */
3427 if (declp
->p
- declp
->b
>= 10 /* op$assign_ */
3428 && memcmp (declp
->b
+ 3, "assign_", 7) == 0)
3430 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3432 int len
= declp
->p
- declp
->b
- 10;
3433 if (strlen (optable
[i
].in
) == len
3434 && memcmp (optable
[i
].in
, declp
->b
+ 10, len
) == 0)
3436 string_clear (declp
);
3437 string_append (declp
, "operator");
3438 string_append (declp
, optable
[i
].out
);
3439 string_append (declp
, "=");
3446 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3448 int len
= declp
->p
- declp
->b
- 3;
3449 if (strlen (optable
[i
].in
) == len
3450 && memcmp (optable
[i
].in
, declp
->b
+ 3, len
) == 0)
3452 string_clear (declp
);
3453 string_append (declp
, "operator");
3454 string_append (declp
, optable
[i
].out
);
3460 else if (declp
->p
- declp
->b
>= 5 && memcmp (declp
->b
, "type", 4) == 0
3461 && strchr (cplus_markers
, declp
->b
[4]) != NULL
)
3463 /* type conversion operator */
3465 if (do_type (work
, &tem
, &type
))
3467 string_clear (declp
);
3468 string_append (declp
, "operator ");
3469 string_appends (declp
, &type
);
3470 string_delete (&type
);
3473 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
3474 && declp
->b
[2] == 'o' && declp
->b
[3] == 'p')
3477 /* type conversion operator. */
3479 if (do_type (work
, &tem
, &type
))
3481 string_clear (declp
);
3482 string_append (declp
, "operator ");
3483 string_appends (declp
, &type
);
3484 string_delete (&type
);
3487 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
3488 && declp
->b
[2] >= 'a' && declp
->b
[2] <= 'z'
3489 && declp
->b
[3] >= 'a' && declp
->b
[3] <= 'z')
3491 if (declp
->b
[4] == '\0')
3494 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3496 if (strlen (optable
[i
].in
) == 2
3497 && memcmp (optable
[i
].in
, declp
->b
+ 2, 2) == 0)
3499 string_clear (declp
);
3500 string_append (declp
, "operator");
3501 string_append (declp
, optable
[i
].out
);
3508 if (declp
->b
[2] == 'a' && declp
->b
[5] == '\0')
3511 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3513 if (strlen (optable
[i
].in
) == 3
3514 && memcmp (optable
[i
].in
, declp
->b
+ 2, 3) == 0)
3516 string_clear (declp
);
3517 string_append (declp
, "operator");
3518 string_append (declp
, optable
[i
].out
);
3527 /* a mini string-handling package */
3542 s
->p
= s
->b
= xmalloc (n
);
3545 else if (s
->e
- s
->p
< n
)
3550 s
->b
= xrealloc (s
->b
, n
);
3563 s
->b
= s
->e
= s
->p
= NULL
;
3571 s
->b
= s
->p
= s
->e
= NULL
;
3587 return (s
->b
== s
->p
);
3593 string_append (p
, s
)
3598 if (s
== NULL
|| *s
== '\0')
3602 memcpy (p
->p
, s
, n
);
3607 string_appends (p
, s
)
3616 memcpy (p
->p
, s
->b
, n
);
3622 string_appendn (p
, s
, n
)
3630 memcpy (p
->p
, s
, n
);
3636 string_prepend (p
, s
)
3640 if (s
!= NULL
&& *s
!= '\0')
3642 string_prependn (p
, s
, strlen (s
));
3647 string_prepends (p
, s
)
3652 string_prependn (p
, s
->b
, s
->p
- s
->b
);
3657 string_prependn (p
, s
, n
)
3667 for (q
= p
->p
- 1; q
>= p
->b
; q
--)
3671 memcpy (p
->b
, s
, n
);
3676 /* To generate a standalone demangler program for testing purposes,
3677 just compile and link this file with -DMAIN and libiberty.a. When
3678 run, it demangles each command line arg, or each stdin string, and
3679 prints the result on stdout. */
3685 static char *program_name
;
3686 static char *program_version
= VERSION
;
3687 static int flags
= DMGL_PARAMS
| DMGL_ANSI
;
3689 static void demangle_it
PARAMS ((char *));
3690 static void usage
PARAMS ((FILE *, int));
3691 static void fatal
PARAMS ((char *));
3694 demangle_it (mangled_name
)
3699 result
= cplus_demangle (mangled_name
, flags
);
3702 printf ("%s\n", mangled_name
);
3706 printf ("%s\n", result
);
3712 usage (stream
, status
)
3717 Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
3718 [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\
3719 [--help] [--version] [arg...]\n",
3724 #define MBUF_SIZE 32767
3725 char mbuffer
[MBUF_SIZE
];
3727 /* Defined in the automatically-generated underscore.c. */
3728 extern int prepends_underscore
;
3730 int strip_underscore
= 0;
3732 static struct option long_options
[] = {
3733 {"strip-underscores", no_argument
, 0, '_'},
3734 {"format", required_argument
, 0, 's'},
3735 {"help", no_argument
, 0, 'h'},
3736 {"no-strip-underscores", no_argument
, 0, 'n'},
3737 {"version", no_argument
, 0, 'v'},
3738 {0, no_argument
, 0, 0}
3741 /* More 'friendly' abort that prints the line and file.
3742 config.h can #define abort fancy_abort if you like that sort of thing. */
3747 fatal ("Internal gcc abort.");
3758 program_name
= argv
[0];
3760 strip_underscore
= prepends_underscore
;
3762 while ((c
= getopt_long (argc
, argv
, "_ns:j", long_options
, (int *) 0)) != EOF
)
3772 strip_underscore
= 0;
3775 printf ("GNU %s version %s\n", program_name
, program_version
);
3778 strip_underscore
= 1;
3781 if (strcmp (optarg
, "gnu") == 0)
3783 current_demangling_style
= gnu_demangling
;
3785 else if (strcmp (optarg
, "lucid") == 0)
3787 current_demangling_style
= lucid_demangling
;
3789 else if (strcmp (optarg
, "arm") == 0)
3791 current_demangling_style
= arm_demangling
;
3795 fprintf (stderr
, "%s: unknown demangling style `%s'\n",
3796 program_name
, optarg
);
3805 for ( ; optind
< argc
; optind
++)
3807 demangle_it (argv
[optind
]);
3816 /* Try to read a label. */
3817 while (c
!= EOF
&& (isalnum(c
) || c
== '_' || c
== '$' || c
== '.'))
3819 if (i
>= MBUF_SIZE
-1)
3828 if (mbuffer
[0] == '.')
3830 if (strip_underscore
&& mbuffer
[skip_first
] == '_')
3838 result
= cplus_demangle (mbuffer
+ skip_first
, flags
);
3841 if (mbuffer
[0] == '.')
3843 fputs (result
, stdout
);
3847 fputs (mbuffer
, stdout
);
3864 fprintf (stderr
, "%s: %s\n", program_name
, str
);
3872 register char *value
= (char *) malloc (size
);
3874 fatal ("virtual memory exhausted");
3879 xrealloc (ptr
, size
)
3883 register char *value
= (char *) realloc (ptr
, size
);
3885 fatal ("virtual memory exhausted");