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. */
32 #include <sys/types.h>
41 #undef CURRENT_DEMANGLING_STYLE
42 #define CURRENT_DEMANGLING_STYLE work->options
44 extern char *xmalloc
PARAMS((unsigned));
45 extern char *xrealloc
PARAMS((char *, unsigned));
47 static const char *mystrstr
PARAMS ((const char *, const char *));
53 register const char *p
= s1
;
54 register int len
= strlen (s2
);
56 for (; (p
= strchr (p
, *s2
)) != 0; p
++)
58 if (strncmp (p
, s2
, len
) == 0)
66 /* In order to allow a single demangler executable to demangle strings
67 using various common values of CPLUS_MARKER, as well as any specific
68 one set at compile time, we maintain a string containing all the
69 commonly used ones, and check to see if the marker we are looking for
70 is in that string. CPLUS_MARKER is usually '$' on systems where the
71 assembler can deal with that. Where the assembler can't, it's usually
72 '.' (but on many systems '.' is used for other things). We put the
73 current defined CPLUS_MARKER first (which defaults to '$'), followed
74 by the next most common value, followed by an explicit '$' in case
75 the value of CPLUS_MARKER is not '$'.
77 We could avoid this if we could just get g++ to tell us what the actual
78 cplus marker character is as part of the debug information, perhaps by
79 ensuring that it is the character that terminates the gcc<n>_compiled
80 marker symbol (FIXME). */
82 #if !defined (CPLUS_MARKER)
83 #define CPLUS_MARKER '$'
86 enum demangling_styles current_demangling_style
= gnu_demangling
;
88 static char cplus_markers
[] = { CPLUS_MARKER
, '.', '$', '\0' };
91 set_cplus_marker_for_demangling (ch
)
94 cplus_markers
[0] = ch
;
97 typedef struct string
/* Beware: these aren't required to be */
98 { /* '\0' terminated. */
99 char *b
; /* pointer to start of string */
100 char *p
; /* pointer after last character */
101 char *e
; /* pointer after end of allocated space */
104 /* Stuff that is shared between sub-routines.
105 Using a shared structure allows cplus_demangle to be reentrant. */
121 int static_type
; /* A static member function */
122 int const_type
; /* A const member function */
123 int volatile_type
; /* A volatile member function */
124 char **tmpl_argvec
; /* Template function arguments. */
125 int ntmpl_args
; /* The number of template function arguments. */
126 int forgetting_types
; /* Nonzero if we are not remembering the types
128 string
* previous_argument
; /* The last function argument demangled. */
129 int nrepeats
; /* The number of times to repeat the previous
133 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
134 #define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS)
136 static const struct optable
142 {"nw", " new", DMGL_ANSI
}, /* new (1.92, ansi) */
143 {"dl", " delete", DMGL_ANSI
}, /* new (1.92, ansi) */
144 {"new", " new", 0}, /* old (1.91, and 1.x) */
145 {"delete", " delete", 0}, /* old (1.91, and 1.x) */
146 {"vn", " new []", DMGL_ANSI
}, /* GNU, pending ansi */
147 {"vd", " delete []", DMGL_ANSI
}, /* GNU, pending ansi */
148 {"as", "=", DMGL_ANSI
}, /* ansi */
149 {"ne", "!=", DMGL_ANSI
}, /* old, ansi */
150 {"eq", "==", DMGL_ANSI
}, /* old, ansi */
151 {"ge", ">=", DMGL_ANSI
}, /* old, ansi */
152 {"gt", ">", DMGL_ANSI
}, /* old, ansi */
153 {"le", "<=", DMGL_ANSI
}, /* old, ansi */
154 {"lt", "<", DMGL_ANSI
}, /* old, ansi */
155 {"plus", "+", 0}, /* old */
156 {"pl", "+", DMGL_ANSI
}, /* ansi */
157 {"apl", "+=", DMGL_ANSI
}, /* ansi */
158 {"minus", "-", 0}, /* old */
159 {"mi", "-", DMGL_ANSI
}, /* ansi */
160 {"ami", "-=", DMGL_ANSI
}, /* ansi */
161 {"mult", "*", 0}, /* old */
162 {"ml", "*", DMGL_ANSI
}, /* ansi */
163 {"amu", "*=", DMGL_ANSI
}, /* ansi (ARM/Lucid) */
164 {"aml", "*=", DMGL_ANSI
}, /* ansi (GNU/g++) */
165 {"convert", "+", 0}, /* old (unary +) */
166 {"negate", "-", 0}, /* old (unary -) */
167 {"trunc_mod", "%", 0}, /* old */
168 {"md", "%", DMGL_ANSI
}, /* ansi */
169 {"amd", "%=", DMGL_ANSI
}, /* ansi */
170 {"trunc_div", "/", 0}, /* old */
171 {"dv", "/", DMGL_ANSI
}, /* ansi */
172 {"adv", "/=", DMGL_ANSI
}, /* ansi */
173 {"truth_andif", "&&", 0}, /* old */
174 {"aa", "&&", DMGL_ANSI
}, /* ansi */
175 {"truth_orif", "||", 0}, /* old */
176 {"oo", "||", DMGL_ANSI
}, /* ansi */
177 {"truth_not", "!", 0}, /* old */
178 {"nt", "!", DMGL_ANSI
}, /* ansi */
179 {"postincrement","++", 0}, /* old */
180 {"pp", "++", DMGL_ANSI
}, /* ansi */
181 {"postdecrement","--", 0}, /* old */
182 {"mm", "--", DMGL_ANSI
}, /* ansi */
183 {"bit_ior", "|", 0}, /* old */
184 {"or", "|", DMGL_ANSI
}, /* ansi */
185 {"aor", "|=", DMGL_ANSI
}, /* ansi */
186 {"bit_xor", "^", 0}, /* old */
187 {"er", "^", DMGL_ANSI
}, /* ansi */
188 {"aer", "^=", DMGL_ANSI
}, /* ansi */
189 {"bit_and", "&", 0}, /* old */
190 {"ad", "&", DMGL_ANSI
}, /* ansi */
191 {"aad", "&=", DMGL_ANSI
}, /* ansi */
192 {"bit_not", "~", 0}, /* old */
193 {"co", "~", DMGL_ANSI
}, /* ansi */
194 {"call", "()", 0}, /* old */
195 {"cl", "()", DMGL_ANSI
}, /* ansi */
196 {"alshift", "<<", 0}, /* old */
197 {"ls", "<<", DMGL_ANSI
}, /* ansi */
198 {"als", "<<=", DMGL_ANSI
}, /* ansi */
199 {"arshift", ">>", 0}, /* old */
200 {"rs", ">>", DMGL_ANSI
}, /* ansi */
201 {"ars", ">>=", DMGL_ANSI
}, /* ansi */
202 {"component", "->", 0}, /* old */
203 {"pt", "->", DMGL_ANSI
}, /* ansi; Lucid C++ form */
204 {"rf", "->", DMGL_ANSI
}, /* ansi; ARM/GNU form */
205 {"indirect", "*", 0}, /* old */
206 {"method_call", "->()", 0}, /* old */
207 {"addr", "&", 0}, /* old (unary &) */
208 {"array", "[]", 0}, /* old */
209 {"vc", "[]", DMGL_ANSI
}, /* ansi */
210 {"compound", ", ", 0}, /* old */
211 {"cm", ", ", DMGL_ANSI
}, /* ansi */
212 {"cond", "?:", 0}, /* old */
213 {"cn", "?:", DMGL_ANSI
}, /* pseudo-ansi */
214 {"max", ">?", 0}, /* old */
215 {"mx", ">?", DMGL_ANSI
}, /* pseudo-ansi */
216 {"min", "<?", 0}, /* old */
217 {"mn", "<?", DMGL_ANSI
}, /* pseudo-ansi */
218 {"nop", "", 0}, /* old (for operator=) */
219 {"rm", "->*", DMGL_ANSI
}, /* ansi */
220 {"sz", "sizeof ", DMGL_ANSI
} /* pseudo-ansi */
224 #define STRING_EMPTY(str) ((str) -> b == (str) -> p)
225 #define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
226 string_prepend(str, " ");}
227 #define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
228 string_append(str, " ");}
229 #define LEN_STRING(str) ( (STRING_EMPTY(str))?0:((str)->p - (str)->b))
231 /* The scope separator appropriate for the language being demangled. */
232 #define SCOPE_STRING(work) "::"
234 #define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */
235 #define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */
237 /* Prototypes for local functions */
240 mop_up
PARAMS ((struct work_stuff
*, string
*, int));
243 squangle_mop_up
PARAMS ((struct work_stuff
*));
247 demangle_method_args
PARAMS ((struct work_stuff
*, const char **, string
*));
251 internal_cplus_demangle
PARAMS ((struct work_stuff
*, const char *));
254 demangle_template_template_parm
PARAMS ((struct work_stuff
*work
,
255 const char **, string
*));
258 demangle_template
PARAMS ((struct work_stuff
*work
, const char **, string
*,
259 string
*, int, int));
262 arm_pt
PARAMS ((struct work_stuff
*, const char *, int, const char **,
266 demangle_arm_pt
PARAMS ((struct work_stuff
*, const char **, int, string
*));
269 demangle_class_name
PARAMS ((struct work_stuff
*, const char **, string
*));
272 demangle_qualified
PARAMS ((struct work_stuff
*, const char **, string
*,
276 demangle_class
PARAMS ((struct work_stuff
*, const char **, string
*));
279 demangle_fund_type
PARAMS ((struct work_stuff
*, const char **, string
*));
282 demangle_signature
PARAMS ((struct work_stuff
*, const char **, string
*));
285 demangle_prefix
PARAMS ((struct work_stuff
*, const char **, string
*));
288 gnu_special
PARAMS ((struct work_stuff
*, const char **, string
*));
291 arm_special
PARAMS ((const char **, string
*));
294 string_need
PARAMS ((string
*, int));
297 string_delete
PARAMS ((string
*));
300 string_init
PARAMS ((string
*));
303 string_clear
PARAMS ((string
*));
307 string_empty
PARAMS ((string
*));
311 string_append
PARAMS ((string
*, const char *));
314 string_appends
PARAMS ((string
*, string
*));
317 string_appendn
PARAMS ((string
*, const char *, int));
320 string_prepend
PARAMS ((string
*, const char *));
323 string_prependn
PARAMS ((string
*, const char *, int));
326 get_count
PARAMS ((const char **, int *));
329 consume_count
PARAMS ((const char **));
332 consume_count_with_underscores
PARAMS ((const char**));
335 demangle_args
PARAMS ((struct work_stuff
*, const char **, string
*));
338 demangle_nested_args
PARAMS ((struct work_stuff
*, const char**, string
*));
341 do_type
PARAMS ((struct work_stuff
*, const char **, string
*));
344 do_arg
PARAMS ((struct work_stuff
*, const char **, string
*));
347 demangle_function_name
PARAMS ((struct work_stuff
*, const char **, string
*,
351 remember_type
PARAMS ((struct work_stuff
*, const char *, int));
354 remember_Btype
PARAMS ((struct work_stuff
*, const char *, int, int));
357 register_Btype
PARAMS ((struct work_stuff
*));
360 remember_Ktype
PARAMS ((struct work_stuff
*, const char *, int));
363 forget_types
PARAMS ((struct work_stuff
*));
366 forget_B_and_K_types
PARAMS ((struct work_stuff
*));
369 string_prepends
PARAMS ((string
*, string
*));
372 demangle_template_value_parm
PARAMS ((struct work_stuff
*,
373 const char**, string
*));
375 /* Translate count to integer, consuming tokens in the process.
376 Conversion terminates on the first non-digit character.
377 Trying to consume something that isn't a count results in
378 no consumption of input and a return of 0. */
386 while (isdigit (**type
))
389 count
+= **type
- '0';
396 /* Like consume_count, but for counts that are preceded and followed
397 by '_' if they are greater than 10. Also, -1 is returned for
398 failure, since 0 can be a valid value. */
401 consume_count_with_underscores (mangled
)
402 const char **mangled
;
406 if (**mangled
== '_')
409 if (!isdigit (**mangled
))
412 idx
= consume_count (mangled
);
413 if (**mangled
!= '_')
414 /* The trailing underscore was missing. */
421 if (**mangled
< '0' || **mangled
> '9')
424 idx
= **mangled
- '0';
432 cplus_demangle_opname (opname
, result
, options
)
439 struct work_stuff work
[1];
442 len
= strlen(opname
);
445 memset ((char *) work
, 0, sizeof (work
));
446 work
->options
= options
;
448 if (opname
[0] == '_' && opname
[1] == '_'
449 && opname
[2] == 'o' && opname
[3] == 'p')
452 /* type conversion operator. */
454 if (do_type (work
, &tem
, &type
))
456 strcat (result
, "operator ");
457 strncat (result
, type
.b
, type
.p
- type
.b
);
458 string_delete (&type
);
462 else if (opname
[0] == '_' && opname
[1] == '_'
463 && opname
[2] >= 'a' && opname
[2] <= 'z'
464 && opname
[3] >= 'a' && opname
[3] <= 'z')
466 if (opname
[4] == '\0')
470 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
472 if (strlen (optable
[i
].in
) == 2
473 && memcmp (optable
[i
].in
, opname
+ 2, 2) == 0)
475 strcat (result
, "operator");
476 strcat (result
, optable
[i
].out
);
484 if (opname
[2] == 'a' && opname
[5] == '\0')
488 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
490 if (strlen (optable
[i
].in
) == 3
491 && memcmp (optable
[i
].in
, opname
+ 2, 3) == 0)
493 strcat (result
, "operator");
494 strcat (result
, optable
[i
].out
);
505 && strchr (cplus_markers
, opname
[2]) != NULL
)
507 /* see if it's an assignment expression */
508 if (len
>= 10 /* op$assign_ */
509 && memcmp (opname
+ 3, "assign_", 7) == 0)
512 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
515 if (strlen (optable
[i
].in
) == len1
516 && memcmp (optable
[i
].in
, opname
+ 10, len1
) == 0)
518 strcat (result
, "operator");
519 strcat (result
, optable
[i
].out
);
520 strcat (result
, "=");
529 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
532 if (strlen (optable
[i
].in
) == len1
533 && memcmp (optable
[i
].in
, opname
+ 3, len1
) == 0)
535 strcat (result
, "operator");
536 strcat (result
, optable
[i
].out
);
543 else if (len
>= 5 && memcmp (opname
, "type", 4) == 0
544 && strchr (cplus_markers
, opname
[4]) != NULL
)
546 /* type conversion operator */
548 if (do_type (work
, &tem
, &type
))
550 strcat (result
, "operator ");
551 strncat (result
, type
.b
, type
.p
- type
.b
);
552 string_delete (&type
);
556 squangle_mop_up (work
);
560 /* Takes operator name as e.g. "++" and returns mangled
561 operator name (e.g. "postincrement_expr"), or NULL if not found.
563 If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
564 if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */
567 cplus_mangle_opname (opname
, options
)
574 len
= strlen (opname
);
575 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
577 if (strlen (optable
[i
].out
) == len
578 && (options
& DMGL_ANSI
) == (optable
[i
].flags
& DMGL_ANSI
)
579 && memcmp (optable
[i
].out
, opname
, len
) == 0)
580 return optable
[i
].in
;
585 /* char *cplus_demangle (const char *mangled, int options)
587 If MANGLED is a mangled function name produced by GNU C++, then
588 a pointer to a malloced string giving a C++ representation
589 of the name will be returned; otherwise NULL will be returned.
590 It is the caller's responsibility to free the string which
593 The OPTIONS arg may contain one or more of the following bits:
595 DMGL_ANSI ANSI qualifiers such as `const' and `void' are
597 DMGL_PARAMS Function parameters are included.
601 cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)"
602 cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
603 cplus_demangle ("foo__1Ai", 0) => "A::foo"
605 cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)"
606 cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
607 cplus_demangle ("foo__1Afe", 0) => "A::foo"
609 Note that any leading underscores, or other such characters prepended by
610 the compilation system, are presumed to have already been stripped from
614 cplus_demangle (mangled
, options
)
619 struct work_stuff work
[1];
620 memset ((char *) work
, 0, sizeof (work
));
621 work
-> options
= options
;
622 if ((work
-> options
& DMGL_STYLE_MASK
) == 0)
623 work
-> options
|= (int) current_demangling_style
& DMGL_STYLE_MASK
;
625 ret
= internal_cplus_demangle (work
, mangled
);
626 squangle_mop_up (work
);
631 /* This function performs most of what cplus_demangle use to do, but
632 to be able to demangle a name with a B, K or n code, we need to
633 have a longer term memory of what types have been seen. The original
634 now intializes and cleans up the squangle code info, while internal
635 calls go directly to this routine to avoid resetting that info. */
638 internal_cplus_demangle (work
, mangled
)
639 struct work_stuff
*work
;
645 char *demangled
= NULL
;
647 int saved_volatile_type
;
648 s1
= work
->constructor
;
649 s2
= work
->destructor
;
650 s3
= work
->static_type
;
651 s4
= work
->const_type
;
652 saved_volatile_type
= work
->volatile_type
;
653 work
->constructor
= work
->destructor
= 0;
654 work
->static_type
= work
->const_type
= 0;
655 work
->volatile_type
= 0;
657 if ((mangled
!= NULL
) && (*mangled
!= '\0'))
661 /* First check to see if gnu style demangling is active and if the
662 string to be demangled contains a CPLUS_MARKER. If so, attempt to
663 recognize one of the gnu special forms rather than looking for a
664 standard prefix. In particular, don't worry about whether there
665 is a "__" string in the mangled string. Consider "_$_5__foo" for
668 if ((AUTO_DEMANGLING
|| GNU_DEMANGLING
))
670 success
= gnu_special (work
, &mangled
, &decl
);
674 success
= demangle_prefix (work
, &mangled
, &decl
);
676 if (success
&& (*mangled
!= '\0'))
678 success
= demangle_signature (work
, &mangled
, &decl
);
680 if (work
->constructor
== 2)
682 string_prepend (&decl
, "global constructors keyed to ");
683 work
->constructor
= 0;
685 else if (work
->destructor
== 2)
687 string_prepend (&decl
, "global destructors keyed to ");
688 work
->destructor
= 0;
690 demangled
= mop_up (work
, &decl
, success
);
692 work
->constructor
= s1
;
693 work
->destructor
= s2
;
694 work
->static_type
= s3
;
695 work
->const_type
= s4
;
696 work
->volatile_type
= saved_volatile_type
;
701 /* Clear out and squangling related storage */
703 squangle_mop_up (work
)
704 struct work_stuff
*work
;
706 /* clean up the B and K type mangling types. */
707 forget_B_and_K_types (work
);
708 if (work
-> btypevec
!= NULL
)
710 free ((char *) work
-> btypevec
);
712 if (work
-> ktypevec
!= NULL
)
714 free ((char *) work
-> ktypevec
);
718 /* Clear out any mangled storage */
721 mop_up (work
, declp
, success
)
722 struct work_stuff
*work
;
726 char *demangled
= NULL
;
728 /* Discard the remembered types, if any. */
731 if (work
-> typevec
!= NULL
)
733 free ((char *) work
-> typevec
);
734 work
-> typevec
= NULL
;
736 if (work
->tmpl_argvec
)
740 for (i
= 0; i
< work
->ntmpl_args
; i
++)
741 if (work
->tmpl_argvec
[i
])
742 free ((char*) work
->tmpl_argvec
[i
]);
744 free ((char*) work
->tmpl_argvec
);
745 work
->tmpl_argvec
= NULL
;
747 if (work
->previous_argument
)
749 string_delete (work
->previous_argument
);
750 free ((char*) work
->previous_argument
);
753 /* If demangling was successful, ensure that the demangled string is null
754 terminated and return it. Otherwise, free the demangling decl. */
758 string_delete (declp
);
762 string_appendn (declp
, "", 1);
763 demangled
= declp
-> b
;
772 demangle_signature -- demangle the signature part of a mangled name
777 demangle_signature (struct work_stuff *work, const char **mangled,
782 Consume and demangle the signature portion of the mangled name.
784 DECLP is the string where demangled output is being built. At
785 entry it contains the demangled root name from the mangled name
786 prefix. I.E. either a demangled operator name or the root function
787 name. In some special cases, it may contain nothing.
789 *MANGLED points to the current unconsumed location in the mangled
790 name. As tokens are consumed and demangling is performed, the
791 pointer is updated to continuously point at the next token to
794 Demangling GNU style mangled names is nasty because there is no
795 explicit token that marks the start of the outermost function
799 demangle_signature (work
, mangled
, declp
)
800 struct work_stuff
*work
;
801 const char **mangled
;
807 int expect_return_type
= 0;
808 const char *oldmangled
= NULL
;
812 while (success
&& (**mangled
!= '\0'))
817 oldmangled
= *mangled
;
818 success
= demangle_qualified (work
, mangled
, declp
, 1, 0);
820 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
821 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
827 oldmangled
= *mangled
;
828 success
= demangle_qualified (work
, mangled
, declp
, 1, 0);
829 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
837 /* Static member function */
838 if (oldmangled
== NULL
)
840 oldmangled
= *mangled
;
843 work
-> static_type
= 1;
848 if (**mangled
== 'C')
849 work
-> const_type
= 1;
851 work
->volatile_type
= 1;
853 /* a qualified member function */
854 if (oldmangled
== NULL
)
855 oldmangled
= *mangled
;
859 case '0': case '1': case '2': case '3': case '4':
860 case '5': case '6': case '7': case '8': case '9':
861 if (oldmangled
== NULL
)
863 oldmangled
= *mangled
;
865 success
= demangle_class (work
, mangled
, declp
);
868 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
870 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
880 success
= do_type (work
, mangled
, &s
);
883 string_append (&s
, SCOPE_STRING (work
));
884 string_prepends (declp
, &s
);
893 /* ARM style demangling includes a specific 'F' character after
894 the class name. For GNU style, it is just implied. So we can
895 safely just consume any 'F' at this point and be compatible
896 with either style. */
902 /* For lucid/ARM style we have to forget any types we might
903 have remembered up to this point, since they were not argument
904 types. GNU style considers all types seen as available for
905 back references. See comment in demangle_args() */
907 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
911 success
= demangle_args (work
, mangled
, declp
);
916 string_init(&trawname
);
918 if (oldmangled
== NULL
)
920 oldmangled
= *mangled
;
922 success
= demangle_template (work
, mangled
, &tname
,
926 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
928 string_append (&tname
, SCOPE_STRING (work
));
930 string_prepends(declp
, &tname
);
931 if (work
-> destructor
& 1)
933 string_prepend (&trawname
, "~");
934 string_appends (declp
, &trawname
);
935 work
->destructor
-= 1;
937 if ((work
->constructor
& 1) || (work
->destructor
& 1))
939 string_appends (declp
, &trawname
);
940 work
->constructor
-= 1;
942 string_delete(&trawname
);
943 string_delete(&tname
);
949 if (GNU_DEMANGLING
&& expect_return_type
)
951 /* Read the return type. */
953 string_init (&return_type
);
956 success
= do_type (work
, mangled
, &return_type
);
957 APPEND_BLANK (&return_type
);
959 string_prepends (declp
, &return_type
);
960 string_delete (&return_type
);
964 /* At the outermost level, we cannot have a return type specified,
965 so if we run into another '_' at this point we are dealing with
966 a mangled name that is either bogus, or has been mangled by
967 some algorithm we don't know how to deal with. So just
968 reject the entire demangling. */
975 /* A G++ template function. Read the template arguments. */
976 success
= demangle_template (work
, mangled
, declp
, 0, 0,
978 if (!(work
->constructor
& 1))
979 expect_return_type
= 1;
988 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
990 /* Assume we have stumbled onto the first outermost function
991 argument token, and start processing args. */
993 success
= demangle_args (work
, mangled
, declp
);
997 /* Non-GNU demanglers use a specific token to mark the start
998 of the outermost function argument tokens. Typically 'F',
999 for ARM-demangling, for example. So if we find something
1000 we are not prepared for, it must be an error. */
1006 if (AUTO_DEMANGLING || GNU_DEMANGLING)
1009 if (success
&& expect_func
)
1012 success
= demangle_args (work
, mangled
, declp
);
1013 /* Since template include the mangling of their return types,
1014 we must set expect_func to 0 so that we don't try do
1015 demangle more arguments the next time we get here. */
1020 if (success
&& !func_done
)
1022 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
1024 /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
1025 bar__3fooi is 'foo::bar(int)'. We get here when we find the
1026 first case, and need to ensure that the '(void)' gets added to
1027 the current declp. Note that with ARM, the first case
1028 represents the name of a static data member 'foo::bar',
1029 which is in the current declp, so we leave it alone. */
1030 success
= demangle_args (work
, mangled
, declp
);
1033 if (success
&& work
-> static_type
&& PRINT_ARG_TYPES
)
1034 string_append (declp
, " static");
1035 if (success
&& work
-> const_type
&& PRINT_ARG_TYPES
)
1036 string_append (declp
, " const");
1037 else if (success
&& work
->volatile_type
&& PRINT_ARG_TYPES
)
1038 string_append (declp
, " volatile");
1046 demangle_method_args (work
, mangled
, declp
)
1047 struct work_stuff
*work
;
1048 const char **mangled
;
1053 if (work
-> static_type
)
1055 string_append (declp
, *mangled
+ 1);
1056 *mangled
+= strlen (*mangled
);
1061 success
= demangle_args (work
, mangled
, declp
);
1069 demangle_template_template_parm (work
, mangled
, tname
)
1070 struct work_stuff
*work
;
1071 const char **mangled
;
1080 string_append (tname
, "template <");
1081 /* get size of template parameter list */
1082 if (get_count (mangled
, &r
))
1084 for (i
= 0; i
< r
; i
++)
1088 string_append (tname
, ", ");
1091 /* Z for type parameters */
1092 if (**mangled
== 'Z')
1095 string_append (tname
, "class");
1097 /* z for template parameters */
1098 else if (**mangled
== 'z')
1102 demangle_template_template_parm (work
, mangled
, tname
);
1110 /* temp is initialized in do_type */
1111 success
= do_type (work
, mangled
, &temp
);
1114 string_appends (tname
, &temp
);
1116 string_delete(&temp
);
1126 if (tname
->p
[-1] == '>')
1127 string_append (tname
, " ");
1128 string_append (tname
, "> class");
1133 demangle_integral_value (work
, mangled
, s
)
1134 struct work_stuff
*work
;
1135 const char** mangled
;
1140 if (**mangled
== 'E')
1142 int need_operator
= 0;
1145 string_appendn (s
, "(", 1);
1147 while (success
&& **mangled
!= 'W' && **mangled
!= '\0')
1156 len
= strlen (*mangled
);
1159 i
< sizeof (optable
) / sizeof (optable
[0]);
1162 size_t l
= strlen (optable
[i
].in
);
1165 && memcmp (optable
[i
].in
, *mangled
, l
) == 0)
1167 string_appendn (s
, " ", 1);
1168 string_append (s
, optable
[i
].out
);
1169 string_appendn (s
, " ", 1);
1182 success
= demangle_template_value_parm (work
, mangled
, s
);
1185 if (**mangled
!= 'W')
1189 string_appendn (s
, ")", 1);
1193 else if (**mangled
== 'Q' || **mangled
== 'K')
1194 success
= demangle_qualified (work
, mangled
, s
, 0, 1);
1199 if (**mangled
== 'm')
1201 string_appendn (s
, "-", 1);
1204 while (isdigit (**mangled
))
1206 string_appendn (s
, *mangled
, 1);
1216 demangle_template_value_parm (work
, mangled
, s
)
1217 struct work_stuff
*work
;
1218 const char **mangled
;
1221 const char *old_p
= *mangled
;
1224 int is_integral
= 0;
1230 while (*old_p
&& !done
)
1237 done
= is_pointer
= 1;
1239 case 'C': /* const */
1240 case 'S': /* explicitly signed [char] */
1241 case 'U': /* unsigned */
1242 case 'V': /* volatile */
1243 case 'F': /* function */
1244 case 'M': /* member function */
1246 case 'J': /* complex */
1249 case 'E': /* expression */
1250 case 'Q': /* qualified name */
1251 case 'K': /* qualified name */
1252 done
= is_integral
= 1;
1254 case 'B': /* remembered type */
1255 case 'T': /* remembered type */
1258 case 'v': /* void */
1261 case 'x': /* long long */
1262 case 'l': /* long */
1264 case 's': /* short */
1265 case 'w': /* wchar_t */
1266 done
= is_integral
= 1;
1268 case 'b': /* bool */
1271 case 'c': /* char */
1274 case 'r': /* long double */
1275 case 'd': /* double */
1276 case 'f': /* float */
1280 /* it's probably user defined type, let's assume
1281 it's integral, it seems hard to figure out
1282 what it really is */
1283 done
= is_integral
= 1;
1286 if (**mangled
== 'Y')
1288 /* The next argument is a template parameter. */
1292 idx
= consume_count_with_underscores (mangled
);
1294 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
1295 || consume_count_with_underscores (mangled
) == -1)
1297 if (work
->tmpl_argvec
)
1298 string_append (s
, work
->tmpl_argvec
[idx
]);
1302 sprintf(buf
, "T%d", idx
);
1303 string_append (s
, buf
);
1306 else if (is_integral
)
1307 success
= demangle_integral_value (work
, mangled
, s
);
1312 if (**mangled
== 'm')
1314 string_appendn (s
, "-", 1);
1317 string_appendn (s
, "'", 1);
1318 val
= consume_count(mangled
);
1323 string_appendn (s
, &tmp
[0], 1);
1324 string_appendn (s
, "'", 1);
1328 int val
= consume_count (mangled
);
1330 string_appendn (s
, "false", 5);
1332 string_appendn (s
, "true", 4);
1338 if (**mangled
== 'm')
1340 string_appendn (s
, "-", 1);
1343 while (isdigit (**mangled
))
1345 string_appendn (s
, *mangled
, 1);
1348 if (**mangled
== '.') /* fraction */
1350 string_appendn (s
, ".", 1);
1352 while (isdigit (**mangled
))
1354 string_appendn (s
, *mangled
, 1);
1358 if (**mangled
== 'e') /* exponent */
1360 string_appendn (s
, "e", 1);
1362 while (isdigit (**mangled
))
1364 string_appendn (s
, *mangled
, 1);
1369 else if (is_pointer
)
1371 int symbol_len
= consume_count (mangled
);
1372 if (symbol_len
== 0)
1374 if (symbol_len
== 0)
1375 string_appendn (s
, "0", 1);
1378 char *p
= xmalloc (symbol_len
+ 1), *q
;
1379 strncpy (p
, *mangled
, symbol_len
);
1380 p
[symbol_len
] = '\0';
1381 q
= internal_cplus_demangle (work
, p
);
1382 string_appendn (s
, "&", 1);
1385 string_append (s
, q
);
1389 string_append (s
, p
);
1392 *mangled
+= symbol_len
;
1398 /* Demangle the template name in MANGLED. The full name of the
1399 template (e.g., S<int>) is placed in TNAME. The name without the
1400 template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is
1401 non-NULL. If IS_TYPE is nonzero, this template is a type template,
1402 not a function template. If both IS_TYPE and REMEMBER are nonzero,
1403 the tmeplate is remembered in the list of back-referenceable
1407 demangle_template (work
, mangled
, tname
, trawname
, is_type
, remember
)
1408 struct work_stuff
*work
;
1409 const char **mangled
;
1427 bindex
= register_Btype (work
);
1429 /* get template name */
1430 if (**mangled
== 'z')
1436 idx
= consume_count_with_underscores (mangled
);
1438 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
1439 || consume_count_with_underscores (mangled
) == -1)
1442 if (work
->tmpl_argvec
)
1444 string_append (tname
, work
->tmpl_argvec
[idx
]);
1446 string_append (trawname
, work
->tmpl_argvec
[idx
]);
1451 sprintf(buf
, "T%d", idx
);
1452 string_append (tname
, buf
);
1454 string_append (trawname
, buf
);
1459 if ((r
= consume_count (mangled
)) == 0 || strlen (*mangled
) < r
)
1463 string_appendn (tname
, *mangled
, r
);
1465 string_appendn (trawname
, *mangled
, r
);
1469 string_append (tname
, "<");
1470 /* get size of template parameter list */
1471 if (!get_count (mangled
, &r
))
1477 /* Create an array for saving the template argument values. */
1478 work
->tmpl_argvec
= (char**) xmalloc (r
* sizeof (char *));
1479 work
->ntmpl_args
= r
;
1480 for (i
= 0; i
< r
; i
++)
1481 work
->tmpl_argvec
[i
] = 0;
1483 for (i
= 0; i
< r
; i
++)
1487 string_append (tname
, ", ");
1489 /* Z for type parameters */
1490 if (**mangled
== 'Z')
1493 /* temp is initialized in do_type */
1494 success
= do_type (work
, mangled
, &temp
);
1497 string_appends (tname
, &temp
);
1501 /* Save the template argument. */
1502 int len
= temp
.p
- temp
.b
;
1503 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1504 memcpy (work
->tmpl_argvec
[i
], temp
.b
, len
);
1505 work
->tmpl_argvec
[i
][len
] = '\0';
1508 string_delete(&temp
);
1514 /* z for template parameters */
1515 else if (**mangled
== 'z')
1519 success
= demangle_template_template_parm (work
, mangled
, tname
);
1522 && (r2
= consume_count (mangled
)) > 0 && strlen (*mangled
) >= r2
)
1524 string_append (tname
, " ");
1525 string_appendn (tname
, *mangled
, r2
);
1528 /* Save the template argument. */
1530 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1531 memcpy (work
->tmpl_argvec
[i
], *mangled
, len
);
1532 work
->tmpl_argvec
[i
][len
] = '\0';
1546 /* otherwise, value parameter */
1548 /* temp is initialized in do_type */
1549 success
= do_type (work
, mangled
, &temp
);
1553 string_appends (s, &temp);
1556 string_delete(&temp
);
1562 string_append (s, "=");
1573 success
= demangle_template_value_parm (work
, mangled
, s
);
1585 int len
= s
->p
- s
->b
;
1586 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1587 memcpy (work
->tmpl_argvec
[i
], s
->b
, len
);
1588 work
->tmpl_argvec
[i
][len
] = '\0';
1590 string_appends (tname
, s
);
1597 if (tname
->p
[-1] == '>')
1598 string_append (tname
, " ");
1599 string_append (tname
, ">");
1602 if (is_type
&& remember
)
1603 remember_Btype (work
, tname
->b
, LEN_STRING (tname
), bindex
);
1606 if (work -> static_type)
1608 string_append (declp, *mangled + 1);
1609 *mangled += strlen (*mangled);
1614 success = demangle_args (work, mangled, declp);
1622 arm_pt (work
, mangled
, n
, anchor
, args
)
1623 struct work_stuff
*work
;
1624 const char *mangled
;
1626 const char **anchor
, **args
;
1629 if (ARM_DEMANGLING
&& (*anchor
= mystrstr (mangled
, "__pt__")))
1632 *args
= *anchor
+ 6;
1633 len
= consume_count (args
);
1634 if (*args
+ len
== mangled
+ n
&& **args
== '_')
1644 demangle_arm_pt (work
, mangled
, n
, declp
)
1645 struct work_stuff
*work
;
1646 const char **mangled
;
1652 const char *e
= *mangled
+ n
;
1655 if (arm_pt (work
, *mangled
, n
, &p
, &args
))
1659 string_appendn (declp
, *mangled
, p
- *mangled
);
1660 string_append (declp
, "<");
1661 /* should do error checking here */
1663 string_clear (&arg
);
1664 do_type (work
, &args
, &arg
);
1665 string_appends (declp
, &arg
);
1666 string_append (declp
, ",");
1668 string_delete (&arg
);
1670 string_append (declp
, ">");
1674 string_appendn (declp
, *mangled
, n
);
1680 demangle_class_name (work
, mangled
, declp
)
1681 struct work_stuff
*work
;
1682 const char **mangled
;
1688 n
= consume_count (mangled
);
1689 if (strlen (*mangled
) >= n
)
1691 demangle_arm_pt (work
, mangled
, n
, declp
);
1702 demangle_class -- demangle a mangled class sequence
1707 demangle_class (struct work_stuff *work, const char **mangled,
1712 DECLP points to the buffer into which demangling is being done.
1714 *MANGLED points to the current token to be demangled. On input,
1715 it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
1716 On exit, it points to the next token after the mangled class on
1717 success, or the first unconsumed token on failure.
1719 If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
1720 we are demangling a constructor or destructor. In this case
1721 we prepend "class::class" or "class::~class" to DECLP.
1723 Otherwise, we prepend "class::" to the current DECLP.
1725 Reset the constructor/destructor flags once they have been
1726 "consumed". This allows demangle_class to be called later during
1727 the same demangling, to do normal class demangling.
1729 Returns 1 if demangling is successful, 0 otherwise.
1734 demangle_class (work
, mangled
, declp
)
1735 struct work_stuff
*work
;
1736 const char **mangled
;
1743 string_init (&class_name
);
1744 btype
= register_Btype (work
);
1745 if (demangle_class_name (work
, mangled
, &class_name
))
1747 if ((work
->constructor
& 1) || (work
->destructor
& 1))
1749 string_prepends (declp
, &class_name
);
1750 if (work
-> destructor
& 1)
1752 string_prepend (declp
, "~");
1753 work
-> destructor
-= 1;
1757 work
-> constructor
-= 1;
1760 remember_Ktype (work
, class_name
.b
, LEN_STRING(&class_name
));
1761 remember_Btype (work
, class_name
.b
, LEN_STRING(&class_name
), btype
);
1762 string_prepend (declp
, SCOPE_STRING (work
));
1763 string_prepends (declp
, &class_name
);
1766 string_delete (&class_name
);
1774 demangle_prefix -- consume the mangled name prefix and find signature
1779 demangle_prefix (struct work_stuff *work, const char **mangled,
1784 Consume and demangle the prefix of the mangled name.
1786 DECLP points to the string buffer into which demangled output is
1787 placed. On entry, the buffer is empty. On exit it contains
1788 the root function name, the demangled operator name, or in some
1789 special cases either nothing or the completely demangled result.
1791 MANGLED points to the current pointer into the mangled name. As each
1792 token of the mangled name is consumed, it is updated. Upon entry
1793 the current mangled name pointer points to the first character of
1794 the mangled name. Upon exit, it should point to the first character
1795 of the signature if demangling was successful, or to the first
1796 unconsumed character if demangling of the prefix was unsuccessful.
1798 Returns 1 on success, 0 otherwise.
1802 demangle_prefix (work
, mangled
, declp
)
1803 struct work_stuff
*work
;
1804 const char **mangled
;
1811 if (strlen(*mangled
) >= 11 && strncmp(*mangled
, "_GLOBAL_", 8) == 0)
1813 char *marker
= strchr (cplus_markers
, (*mangled
)[8]);
1814 if (marker
!= NULL
&& *marker
== (*mangled
)[10])
1816 if ((*mangled
)[9] == 'D')
1818 /* it's a GNU global destructor to be executed at program exit */
1820 work
->destructor
= 2;
1821 if (gnu_special (work
, mangled
, declp
))
1824 else if ((*mangled
)[9] == 'I')
1826 /* it's a GNU global constructor to be executed at program init */
1828 work
->constructor
= 2;
1829 if (gnu_special (work
, mangled
, declp
))
1834 else if (ARM_DEMANGLING
&& strncmp(*mangled
, "__std__", 7) == 0)
1836 /* it's a ARM global destructor to be executed at program exit */
1838 work
->destructor
= 2;
1840 else if (ARM_DEMANGLING
&& strncmp(*mangled
, "__sti__", 7) == 0)
1842 /* it's a ARM global constructor to be executed at program initial */
1844 work
->constructor
= 2;
1847 /* This block of code is a reduction in strength time optimization
1849 scan = mystrstr (*mangled, "__"); */
1855 scan
= strchr (scan
, '_');
1856 } while (scan
!= NULL
&& *++scan
!= '_');
1858 if (scan
!= NULL
) --scan
;
1863 /* We found a sequence of two or more '_', ensure that we start at
1864 the last pair in the sequence. */
1865 i
= strspn (scan
, "_");
1876 else if (work
-> static_type
)
1878 if (!isdigit (scan
[0]) && (scan
[0] != 't'))
1883 else if ((scan
== *mangled
)
1884 && (isdigit (scan
[2]) || (scan
[2] == 'Q') || (scan
[2] == 't')
1885 || (scan
[2] == 'K') || (scan
[2] == 'H')))
1887 /* The ARM says nothing about the mangling of local variables.
1888 But cfront mangles local variables by prepending __<nesting_level>
1889 to them. As an extension to ARM demangling we handle this case. */
1890 if ((LUCID_DEMANGLING
|| ARM_DEMANGLING
) && isdigit (scan
[2]))
1892 *mangled
= scan
+ 2;
1893 consume_count (mangled
);
1894 string_append (declp
, *mangled
);
1895 *mangled
+= strlen (*mangled
);
1900 /* A GNU style constructor starts with __[0-9Qt]. But cfront uses
1901 names like __Q2_3foo3bar for nested type names. So don't accept
1902 this style of constructor for cfront demangling. A GNU
1903 style member-template constructor starts with 'H'. */
1904 if (!(LUCID_DEMANGLING
|| ARM_DEMANGLING
))
1905 work
-> constructor
+= 1;
1906 *mangled
= scan
+ 2;
1909 else if ((scan
== *mangled
) && !isdigit (scan
[2]) && (scan
[2] != 't'))
1911 /* Mangled name starts with "__". Skip over any leading '_' characters,
1912 then find the next "__" that separates the prefix from the signature.
1914 if (!(ARM_DEMANGLING
|| LUCID_DEMANGLING
)
1915 || (arm_special (mangled
, declp
) == 0))
1917 while (*scan
== '_')
1921 if ((scan
= mystrstr (scan
, "__")) == NULL
|| (*(scan
+ 2) == '\0'))
1923 /* No separator (I.E. "__not_mangled"), or empty signature
1924 (I.E. "__not_mangled_either__") */
1929 demangle_function_name (work
, mangled
, declp
, scan
);
1933 else if (ARM_DEMANGLING
&& scan
[2] == 'p' && scan
[3] == 't')
1935 /* Cfront-style parameterized type. Handled later as a signature. */
1939 demangle_arm_pt (work
, mangled
, strlen (*mangled
), declp
);
1941 else if (*(scan
+ 2) != '\0')
1943 /* Mangled name does not start with "__" but does have one somewhere
1944 in there with non empty stuff after it. Looks like a global
1946 demangle_function_name (work
, mangled
, declp
, scan
);
1950 /* Doesn't look like a mangled name */
1954 if (!success
&& (work
->constructor
== 2 || work
->destructor
== 2))
1956 string_append (declp
, *mangled
);
1957 *mangled
+= strlen (*mangled
);
1967 gnu_special -- special handling of gnu mangled strings
1972 gnu_special (struct work_stuff *work, const char **mangled,
1978 Process some special GNU style mangling forms that don't fit
1979 the normal pattern. For example:
1981 _$_3foo (destructor for class foo)
1982 _vt$foo (foo virtual table)
1983 _vt$foo$bar (foo::bar virtual table)
1984 __vt_foo (foo virtual table, new style with thunks)
1985 _3foo$varname (static data member)
1986 _Q22rs2tu$vw (static data member)
1987 __t6vector1Zii (constructor with template)
1988 __thunk_4__$_7ostream (virtual function thunk)
1992 gnu_special (work
, mangled
, declp
)
1993 struct work_stuff
*work
;
1994 const char **mangled
;
2001 if ((*mangled
)[0] == '_'
2002 && strchr (cplus_markers
, (*mangled
)[1]) != NULL
2003 && (*mangled
)[2] == '_')
2005 /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
2007 work
-> destructor
+= 1;
2009 else if ((*mangled
)[0] == '_'
2010 && (((*mangled
)[1] == '_'
2011 && (*mangled
)[2] == 'v'
2012 && (*mangled
)[3] == 't'
2013 && (*mangled
)[4] == '_')
2014 || ((*mangled
)[1] == 'v'
2015 && (*mangled
)[2] == 't'
2016 && strchr (cplus_markers
, (*mangled
)[3]) != NULL
)))
2018 /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
2019 and create the decl. Note that we consume the entire mangled
2020 input string, which means that demangle_signature has no work
2022 if ((*mangled
)[2] == 'v')
2023 (*mangled
) += 5; /* New style, with thunks: "__vt_" */
2025 (*mangled
) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
2026 while (**mangled
!= '\0')
2028 p
= strpbrk (*mangled
, cplus_markers
);
2033 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
2036 success
= demangle_template (work
, mangled
, declp
, 0, 1,
2040 if (isdigit(*mangled
[0]))
2042 n
= consume_count(mangled
);
2043 /* We may be seeing a too-large size, or else a
2044 ".<digits>" indicating a static local symbol. In
2045 any case, declare victory and move on; *don't* try
2046 to use n to allocate. */
2047 if (n
> strlen (*mangled
))
2055 n
= strcspn (*mangled
, cplus_markers
);
2057 string_appendn (declp
, *mangled
, n
);
2061 if (success
&& ((p
== NULL
) || (p
== *mangled
)))
2065 string_append (declp
, SCOPE_STRING (work
));
2076 string_append (declp
, " virtual table");
2078 else if ((*mangled
)[0] == '_'
2079 && (strchr("0123456789Qt", (*mangled
)[1]) != NULL
)
2080 && (p
= strpbrk (*mangled
, cplus_markers
)) != NULL
)
2082 /* static data member, "_3foo$varname" for example */
2088 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
2091 success
= demangle_template (work
, mangled
, declp
, 0, 1, 1);
2094 n
= consume_count (mangled
);
2095 string_appendn (declp
, *mangled
, n
);
2098 if (success
&& (p
== *mangled
))
2100 /* Consumed everything up to the cplus_marker, append the
2103 string_append (declp
, SCOPE_STRING (work
));
2104 n
= strlen (*mangled
);
2105 string_appendn (declp
, *mangled
, n
);
2113 else if (strncmp (*mangled
, "__thunk_", 8) == 0)
2115 int delta
= ((*mangled
) += 8, consume_count (mangled
));
2116 char *method
= internal_cplus_demangle (work
, ++*mangled
);
2120 sprintf (buf
, "virtual function thunk (delta:%d) for ", -delta
);
2121 string_append (declp
, buf
);
2122 string_append (declp
, method
);
2124 n
= strlen (*mangled
);
2132 else if (strncmp (*mangled
, "__t", 3) == 0
2133 && ((*mangled
)[3] == 'i' || (*mangled
)[3] == 'f'))
2135 p
= (*mangled
)[3] == 'i' ? " type_info node" : " type_info function";
2141 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
2144 success
= demangle_template (work
, mangled
, declp
, 0, 1, 1);
2147 success
= demangle_fund_type (work
, mangled
, declp
);
2150 if (success
&& **mangled
!= '\0')
2153 string_append (declp
, p
);
2166 arm_special -- special handling of ARM/lucid mangled strings
2171 arm_special (const char **mangled,
2177 Process some special ARM style mangling forms that don't fit
2178 the normal pattern. For example:
2180 __vtbl__3foo (foo virtual table)
2181 __vtbl__3foo__3bar (bar::foo virtual table)
2186 arm_special (mangled
, declp
)
2187 const char **mangled
;
2194 if (strncmp (*mangled
, ARM_VTABLE_STRING
, ARM_VTABLE_STRLEN
) == 0)
2196 /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
2197 and create the decl. Note that we consume the entire mangled
2198 input string, which means that demangle_signature has no work
2200 scan
= *mangled
+ ARM_VTABLE_STRLEN
;
2201 while (*scan
!= '\0') /* first check it can be demangled */
2203 n
= consume_count (&scan
);
2206 return (0); /* no good */
2209 if (scan
[0] == '_' && scan
[1] == '_')
2214 (*mangled
) += ARM_VTABLE_STRLEN
;
2215 while (**mangled
!= '\0')
2217 n
= consume_count (mangled
);
2218 string_prependn (declp
, *mangled
, n
);
2220 if ((*mangled
)[0] == '_' && (*mangled
)[1] == '_')
2222 string_prepend (declp
, "::");
2226 string_append (declp
, " virtual table");
2239 demangle_qualified -- demangle 'Q' qualified name strings
2244 demangle_qualified (struct work_stuff *, const char *mangled,
2245 string *result, int isfuncname, int append);
2249 Demangle a qualified name, such as "Q25Outer5Inner" which is
2250 the mangled form of "Outer::Inner". The demangled output is
2251 prepended or appended to the result string according to the
2252 state of the append flag.
2254 If isfuncname is nonzero, then the qualified name we are building
2255 is going to be used as a member function name, so if it is a
2256 constructor or destructor function, append an appropriate
2257 constructor or destructor name. I.E. for the above example,
2258 the result for use as a constructor is "Outer::Inner::Inner"
2259 and the result for use as a destructor is "Outer::Inner::~Inner".
2263 Numeric conversion is ASCII dependent (FIXME).
2268 demangle_qualified (work
, mangled
, result
, isfuncname
, append
)
2269 struct work_stuff
*work
;
2270 const char **mangled
;
2281 int bindex
= register_Btype (work
);
2283 /* We only make use of ISFUNCNAME if the entity is a constructor or
2285 isfuncname
= (isfuncname
2286 && ((work
->constructor
& 1) || (work
->destructor
& 1)));
2288 string_init (&temp
);
2289 string_init (&last_name
);
2291 if ((*mangled
)[0] == 'K')
2293 /* Squangling qualified name reuse */
2296 idx
= consume_count_with_underscores (mangled
);
2297 if (idx
== -1 || idx
> work
-> numk
)
2300 string_append (&temp
, work
-> ktypevec
[idx
]);
2303 switch ((*mangled
)[1])
2306 /* GNU mangled name with more than 9 classes. The count is preceded
2307 by an underscore (to distinguish it from the <= 9 case) and followed
2308 by an underscore. */
2310 qualifiers
= atoi (p
);
2311 if (!isdigit (*p
) || *p
== '0')
2314 /* Skip the digits. */
2315 while (isdigit (*p
))
2333 /* The count is in a single digit. */
2334 num
[0] = (*mangled
)[1];
2336 qualifiers
= atoi (num
);
2338 /* If there is an underscore after the digit, skip it. This is
2339 said to be for ARM-qualified names, but the ARM makes no
2340 mention of such an underscore. Perhaps cfront uses one. */
2341 if ((*mangled
)[2] == '_')
2356 /* Pick off the names and collect them in the temp buffer in the order
2357 in which they are found, separated by '::'. */
2359 while (qualifiers
-- > 0)
2362 string_clear (&last_name
);
2364 if (*mangled
[0] == '_')
2367 if (*mangled
[0] == 't')
2369 /* Here we always append to TEMP since we will want to use
2370 the template name without the template parameters as a
2371 constructor or destructor name. The appropriate
2372 (parameter-less) value is returned by demangle_template
2373 in LAST_NAME. We do not remember the template type here,
2374 in order to match the G++ mangling algorithm. */
2375 success
= demangle_template(work
, mangled
, &temp
,
2380 else if (*mangled
[0] == 'K')
2384 idx
= consume_count_with_underscores (mangled
);
2385 if (idx
== -1 || idx
> work
->numk
)
2388 string_append (&temp
, work
->ktypevec
[idx
]);
2391 if (!success
) break;
2395 success
= do_type (work
, mangled
, &last_name
);
2398 string_appends (&temp
, &last_name
);
2402 remember_Ktype (work
, temp
.b
, LEN_STRING (&temp
));
2405 string_append (&temp
, SCOPE_STRING (work
));
2408 remember_Btype (work
, temp
.b
, LEN_STRING (&temp
), bindex
);
2410 /* If we are using the result as a function name, we need to append
2411 the appropriate '::' separated constructor or destructor name.
2412 We do this here because this is the most convenient place, where
2413 we already have a pointer to the name and the length of the name. */
2417 string_append (&temp
, SCOPE_STRING (work
));
2418 if (work
-> destructor
& 1)
2419 string_append (&temp
, "~");
2420 string_appends (&temp
, &last_name
);
2423 /* Now either prepend the temp buffer to the result, or append it,
2424 depending upon the state of the append flag. */
2427 string_appends (result
, &temp
);
2430 if (!STRING_EMPTY (result
))
2431 string_append (&temp
, SCOPE_STRING (work
));
2432 string_prepends (result
, &temp
);
2435 string_delete (&last_name
);
2436 string_delete (&temp
);
2444 get_count -- convert an ascii count to integer, consuming tokens
2449 get_count (const char **type, int *count)
2453 Return 0 if no conversion is performed, 1 if a string is converted.
2457 get_count (type
, count
)
2464 if (!isdigit (**type
))
2470 *count
= **type
- '0';
2472 if (isdigit (**type
))
2482 while (isdigit (*p
));
2493 /* result will be initialised here; it will be freed on failure */
2496 do_type (work
, mangled
, result
)
2497 struct work_stuff
*work
;
2498 const char **mangled
;
2505 const char *remembered_type
;
2510 string_init (&btype
);
2511 string_init (&decl
);
2512 string_init (result
);
2516 while (success
&& !done
)
2522 /* A pointer type */
2526 string_prepend (&decl
, "*");
2529 /* A reference type */
2532 string_prepend (&decl
, "&");
2538 const char *p
= ++(*mangled
);
2540 string_prepend (&decl
, "(");
2541 string_append (&decl
, ")[");
2542 /* Copy anything up until the next underscore (the size of the
2544 while (**mangled
&& **mangled
!= '_')
2546 if (**mangled
== '_')
2548 string_appendn (&decl
, p
, *mangled
- p
);
2549 string_append (&decl
, "]");
2557 /* A back reference to a previously seen type */
2560 if (!get_count (mangled
, &n
) || n
>= work
-> ntypes
)
2566 remembered_type
= work
-> typevec
[n
];
2567 mangled
= &remembered_type
;
2574 if (!STRING_EMPTY (&decl
) && decl
.b
[0] == '*')
2576 string_prepend (&decl
, "(");
2577 string_append (&decl
, ")");
2579 /* After picking off the function args, we expect to either find the
2580 function return type (preceded by an '_') or the end of the
2582 if (!demangle_nested_args (work
, mangled
, &decl
)
2583 || (**mangled
!= '_' && **mangled
!= '\0'))
2588 if (success
&& (**mangled
== '_'))
2598 member
= **mangled
== 'M';
2600 if (!isdigit (**mangled
) && **mangled
!= 't')
2606 string_append (&decl
, ")");
2607 string_prepend (&decl
, SCOPE_STRING (work
));
2608 if (isdigit (**mangled
))
2610 n
= consume_count (mangled
);
2611 if (strlen (*mangled
) < n
)
2616 string_prependn (&decl
, *mangled
, n
);
2622 string_init (&temp
);
2623 success
= demangle_template (work
, mangled
, &temp
,
2627 string_prependn (&decl
, temp
.b
, temp
.p
- temp
.b
);
2628 string_clear (&temp
);
2633 string_prepend (&decl
, "(");
2636 if (**mangled
== 'C')
2641 if (**mangled
== 'V')
2646 if (*(*mangled
)++ != 'F')
2652 if ((member
&& !demangle_nested_args (work
, mangled
, &decl
))
2653 || **mangled
!= '_')
2659 if (! PRINT_ANSI_QUALIFIERS
)
2665 APPEND_BLANK (&decl
);
2666 string_append (&decl
, "const");
2670 APPEND_BLANK (&decl
);
2671 string_append (&decl
, "volatile");
2682 if ((*mangled)[1] == 'P')
2685 if (PRINT_ANSI_QUALIFIERS
)
2687 if (!STRING_EMPTY (&decl
))
2689 string_prepend (&decl
, " ");
2691 string_prepend (&decl
,
2692 (**mangled
) == 'C' ? "const" : "volatile");
2709 /* A qualified name, such as "Outer::Inner". */
2713 success
= demangle_qualified (work
, mangled
, result
, 0, 1);
2717 /* A back reference to a previously seen squangled type */
2720 if (!get_count (mangled
, &n
) || n
>= work
-> numb
)
2724 string_append (result
, work
->btypevec
[n
]);
2730 /* A template parm. We substitute the corresponding argument. */
2735 idx
= consume_count_with_underscores (mangled
);
2738 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
2739 || consume_count_with_underscores (mangled
) == -1)
2745 if (work
->tmpl_argvec
)
2746 string_append (result
, work
->tmpl_argvec
[idx
]);
2750 sprintf(buf
, "T%d", idx
);
2751 string_append (result
, buf
);
2759 success
= demangle_fund_type (work
, mangled
, result
);
2765 if (!STRING_EMPTY (&decl
))
2767 string_append (result
, " ");
2768 string_appends (result
, &decl
);
2773 string_delete (result
);
2775 string_delete (&decl
);
2779 /* Given a pointer to a type string that represents a fundamental type
2780 argument (int, long, unsigned int, etc) in TYPE, a pointer to the
2781 string in which the demangled output is being built in RESULT, and
2782 the WORK structure, decode the types and add them to the result.
2787 "Sl" => "signed long"
2788 "CUs" => "const unsigned short"
2793 demangle_fund_type (work
, mangled
, result
)
2794 struct work_stuff
*work
;
2795 const char **mangled
;
2801 string_init (&btype
);
2803 /* First pick off any type qualifiers. There can be more than one. */
2811 if (PRINT_ANSI_QUALIFIERS
)
2813 APPEND_BLANK (result
);
2814 string_append (result
, "const");
2819 APPEND_BLANK (result
);
2820 string_append (result
, "unsigned");
2822 case 'S': /* signed char only */
2824 APPEND_BLANK (result
);
2825 string_append (result
, "signed");
2829 if (PRINT_ANSI_QUALIFIERS
)
2831 APPEND_BLANK (result
);
2832 string_append (result
, "volatile");
2837 APPEND_BLANK (result
);
2838 string_append (result
, "__complex");
2846 /* Now pick off the fundamental type. There can be only one. */
2855 APPEND_BLANK (result
);
2856 string_append (result
, "void");
2860 APPEND_BLANK (result
);
2861 string_append (result
, "long long");
2865 APPEND_BLANK (result
);
2866 string_append (result
, "long");
2870 APPEND_BLANK (result
);
2871 string_append (result
, "int");
2875 APPEND_BLANK (result
);
2876 string_append (result
, "short");
2880 APPEND_BLANK (result
);
2881 string_append (result
, "bool");
2885 APPEND_BLANK (result
);
2886 string_append (result
, "char");
2890 APPEND_BLANK (result
);
2891 string_append (result
, "wchar_t");
2895 APPEND_BLANK (result
);
2896 string_append (result
, "long double");
2900 APPEND_BLANK (result
);
2901 string_append (result
, "double");
2905 APPEND_BLANK (result
);
2906 string_append (result
, "float");
2910 if (!isdigit (**mangled
))
2916 /* An explicit type, such as "6mytype" or "7integer" */
2928 int bindex
= register_Btype (work
);
2930 string_init (&btype
);
2931 if (demangle_class_name (work
, mangled
, &btype
)) {
2932 remember_Btype (work
, btype
.b
, LEN_STRING (&btype
), bindex
);
2933 APPEND_BLANK (result
);
2934 string_appends (result
, &btype
);
2938 string_delete (&btype
);
2943 success
= demangle_template (work
, mangled
, &btype
, 0, 1, 1);
2944 string_appends (result
, &btype
);
2955 /* Demangle the next argument, given by MANGLED into RESULT, which
2956 *should be an uninitialized* string. It will be initialized here,
2957 and free'd should anything go wrong. */
2960 do_arg (work
, mangled
, result
)
2961 struct work_stuff
*work
;
2962 const char **mangled
;
2965 /* Remember where we started so that we can record the type, for
2966 non-squangling type remembering. */
2967 const char *start
= *mangled
;
2969 string_init (result
);
2971 if (work
->nrepeats
> 0)
2975 if (work
->previous_argument
== 0)
2978 /* We want to reissue the previous type in this argument list. */
2979 string_appends (result
, work
->previous_argument
);
2983 if (**mangled
== 'n')
2985 /* A squangling-style repeat. */
2987 work
->nrepeats
= consume_count(mangled
);
2989 if (work
->nrepeats
== 0)
2990 /* This was not a repeat count after all. */
2993 if (work
->nrepeats
> 9)
2995 if (**mangled
!= '_')
2996 /* The repeat count should be followed by an '_' in this
3003 /* Now, the repeat is all set up. */
3004 return do_arg (work
, mangled
, result
);
3007 /* Save the result in WORK->previous_argument so that we can find it
3008 if it's repeated. Note that saving START is not good enough: we
3009 do not want to add additional types to the back-referenceable
3010 type vector when processing a repeated type. */
3011 if (work
->previous_argument
)
3012 string_clear (work
->previous_argument
);
3015 work
->previous_argument
= (string
*) xmalloc (sizeof (string
));
3016 string_init (work
->previous_argument
);
3019 if (!do_type (work
, mangled
, work
->previous_argument
))
3022 string_appends (result
, work
->previous_argument
);
3024 remember_type (work
, start
, *mangled
- start
);
3029 remember_type (work
, start
, len
)
3030 struct work_stuff
*work
;
3036 if (work
->forgetting_types
)
3039 if (work
-> ntypes
>= work
-> typevec_size
)
3041 if (work
-> typevec_size
== 0)
3043 work
-> typevec_size
= 3;
3045 = (char **) xmalloc (sizeof (char *) * work
-> typevec_size
);
3049 work
-> typevec_size
*= 2;
3051 = (char **) xrealloc ((char *)work
-> typevec
,
3052 sizeof (char *) * work
-> typevec_size
);
3055 tem
= xmalloc (len
+ 1);
3056 memcpy (tem
, start
, len
);
3058 work
-> typevec
[work
-> ntypes
++] = tem
;
3062 /* Remember a K type class qualifier. */
3064 remember_Ktype (work
, start
, len
)
3065 struct work_stuff
*work
;
3071 if (work
-> numk
>= work
-> ksize
)
3073 if (work
-> ksize
== 0)
3077 = (char **) xmalloc (sizeof (char *) * work
-> ksize
);
3083 = (char **) xrealloc ((char *)work
-> ktypevec
,
3084 sizeof (char *) * work
-> ksize
);
3087 tem
= xmalloc (len
+ 1);
3088 memcpy (tem
, start
, len
);
3090 work
-> ktypevec
[work
-> numk
++] = tem
;
3093 /* Register a B code, and get an index for it. B codes are registered
3094 as they are seen, rather than as they are completed, so map<temp<char> >
3095 registers map<temp<char> > as B0, and temp<char> as B1 */
3098 register_Btype (work
)
3099 struct work_stuff
*work
;
3103 if (work
-> numb
>= work
-> bsize
)
3105 if (work
-> bsize
== 0)
3109 = (char **) xmalloc (sizeof (char *) * work
-> bsize
);
3115 = (char **) xrealloc ((char *)work
-> btypevec
,
3116 sizeof (char *) * work
-> bsize
);
3119 ret
= work
-> numb
++;
3120 work
-> btypevec
[ret
] = NULL
;
3124 /* Store a value into a previously registered B code type. */
3127 remember_Btype (work
, start
, len
, index
)
3128 struct work_stuff
*work
;
3134 tem
= xmalloc (len
+ 1);
3135 memcpy (tem
, start
, len
);
3137 work
-> btypevec
[index
] = tem
;
3140 /* Lose all the info related to B and K type codes. */
3142 forget_B_and_K_types (work
)
3143 struct work_stuff
*work
;
3147 while (work
-> numk
> 0)
3149 i
= --(work
-> numk
);
3150 if (work
-> ktypevec
[i
] != NULL
)
3152 free (work
-> ktypevec
[i
]);
3153 work
-> ktypevec
[i
] = NULL
;
3157 while (work
-> numb
> 0)
3159 i
= --(work
-> numb
);
3160 if (work
-> btypevec
[i
] != NULL
)
3162 free (work
-> btypevec
[i
]);
3163 work
-> btypevec
[i
] = NULL
;
3167 /* Forget the remembered types, but not the type vector itself. */
3171 struct work_stuff
*work
;
3175 while (work
-> ntypes
> 0)
3177 i
= --(work
-> ntypes
);
3178 if (work
-> typevec
[i
] != NULL
)
3180 free (work
-> typevec
[i
]);
3181 work
-> typevec
[i
] = NULL
;
3186 /* Process the argument list part of the signature, after any class spec
3187 has been consumed, as well as the first 'F' character (if any). For
3190 "__als__3fooRT0" => process "RT0"
3191 "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i"
3193 DECLP must be already initialised, usually non-empty. It won't be freed
3196 Note that g++ differs significantly from ARM and lucid style mangling
3197 with regards to references to previously seen types. For example, given
3198 the source fragment:
3202 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
3205 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3206 void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3208 g++ produces the names:
3213 while lcc (and presumably other ARM style compilers as well) produces:
3215 foo__FiR3fooT1T2T1T2
3216 __ct__3fooFiR3fooT1T2T1T2
3218 Note that g++ bases its type numbers starting at zero and counts all
3219 previously seen types, while lucid/ARM bases its type numbers starting
3220 at one and only considers types after it has seen the 'F' character
3221 indicating the start of the function args. For lucid/ARM style, we
3222 account for this difference by discarding any previously seen types when
3223 we see the 'F' character, and subtracting one from the type number
3229 demangle_args (work
, mangled
, declp
)
3230 struct work_stuff
*work
;
3231 const char **mangled
;
3241 if (PRINT_ARG_TYPES
)
3243 string_append (declp
, "(");
3244 if (**mangled
== '\0')
3246 string_append (declp
, "void");
3250 while ((**mangled
!= '_' && **mangled
!= '\0' && **mangled
!= 'e')
3251 || work
->nrepeats
> 0)
3253 if ((**mangled
== 'N') || (**mangled
== 'T'))
3255 temptype
= *(*mangled
)++;
3257 if (temptype
== 'N')
3259 if (!get_count (mangled
, &r
))
3268 if (ARM_DEMANGLING
&& work
-> ntypes
>= 10)
3270 /* If we have 10 or more types we might have more than a 1 digit
3271 index so we'll have to consume the whole count here. This
3272 will lose if the next thing is a type name preceded by a
3273 count but it's impossible to demangle that case properly
3274 anyway. Eg if we already have 12 types is T12Pc "(..., type1,
3275 Pc, ...)" or "(..., type12, char *, ...)" */
3276 if ((t
= consume_count(mangled
)) == 0)
3283 if (!get_count (mangled
, &t
))
3288 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
3292 /* Validate the type index. Protect against illegal indices from
3293 malformed type strings. */
3294 if ((t
< 0) || (t
>= work
-> ntypes
))
3298 while (work
->nrepeats
> 0 || --r
>= 0)
3300 tem
= work
-> typevec
[t
];
3301 if (need_comma
&& PRINT_ARG_TYPES
)
3303 string_append (declp
, ", ");
3305 if (!do_arg (work
, &tem
, &arg
))
3309 if (PRINT_ARG_TYPES
)
3311 string_appends (declp
, &arg
);
3313 string_delete (&arg
);
3319 if (need_comma
&& PRINT_ARG_TYPES
)
3320 string_append (declp
, ", ");
3321 if (!do_arg (work
, mangled
, &arg
))
3323 if (PRINT_ARG_TYPES
)
3324 string_appends (declp
, &arg
);
3325 string_delete (&arg
);
3330 if (**mangled
== 'e')
3333 if (PRINT_ARG_TYPES
)
3337 string_append (declp
, ",");
3339 string_append (declp
, "...");
3343 if (PRINT_ARG_TYPES
)
3345 string_append (declp
, ")");
3350 /* Like demangle_args, but for demangling the argument lists of function
3351 and method pointers or references, not top-level declarations. */
3354 demangle_nested_args (work
, mangled
, declp
)
3355 struct work_stuff
*work
;
3356 const char **mangled
;
3359 string
* saved_previous_argument
;
3363 /* The G++ name-mangling algorithm does not remember types on nested
3364 argument lists, unless -fsquangling is used, and in that case the
3365 type vector updated by remember_type is not used. So, we turn
3366 off remembering of types here. */
3367 ++work
->forgetting_types
;
3369 /* For the repeat codes used with -fsquangling, we must keep track of
3370 the last argument. */
3371 saved_previous_argument
= work
->previous_argument
;
3372 saved_nrepeats
= work
->nrepeats
;
3373 work
->previous_argument
= 0;
3376 /* Actually demangle the arguments. */
3377 result
= demangle_args (work
, mangled
, declp
);
3379 /* Restore the previous_argument field. */
3380 if (work
->previous_argument
)
3381 string_delete (work
->previous_argument
);
3382 work
->previous_argument
= saved_previous_argument
;
3383 work
->nrepeats
= saved_nrepeats
;
3389 demangle_function_name (work
, mangled
, declp
, scan
)
3390 struct work_stuff
*work
;
3391 const char **mangled
;
3399 string_appendn (declp
, (*mangled
), scan
- (*mangled
));
3400 string_need (declp
, 1);
3401 *(declp
-> p
) = '\0';
3403 /* Consume the function name, including the "__" separating the name
3404 from the signature. We are guaranteed that SCAN points to the
3407 (*mangled
) = scan
+ 2;
3409 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
3412 /* See if we have an ARM style constructor or destructor operator.
3413 If so, then just record it, clear the decl, and return.
3414 We can't build the actual constructor/destructor decl until later,
3415 when we recover the class name from the signature. */
3417 if (strcmp (declp
-> b
, "__ct") == 0)
3419 work
-> constructor
+= 1;
3420 string_clear (declp
);
3423 else if (strcmp (declp
-> b
, "__dt") == 0)
3425 work
-> destructor
+= 1;
3426 string_clear (declp
);
3431 if (declp
->p
- declp
->b
>= 3
3432 && declp
->b
[0] == 'o'
3433 && declp
->b
[1] == 'p'
3434 && strchr (cplus_markers
, declp
->b
[2]) != NULL
)
3436 /* see if it's an assignment expression */
3437 if (declp
->p
- declp
->b
>= 10 /* op$assign_ */
3438 && memcmp (declp
->b
+ 3, "assign_", 7) == 0)
3440 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3442 int len
= declp
->p
- declp
->b
- 10;
3443 if (strlen (optable
[i
].in
) == len
3444 && memcmp (optable
[i
].in
, declp
->b
+ 10, len
) == 0)
3446 string_clear (declp
);
3447 string_append (declp
, "operator");
3448 string_append (declp
, optable
[i
].out
);
3449 string_append (declp
, "=");
3456 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3458 int len
= declp
->p
- declp
->b
- 3;
3459 if (strlen (optable
[i
].in
) == len
3460 && memcmp (optable
[i
].in
, declp
->b
+ 3, len
) == 0)
3462 string_clear (declp
);
3463 string_append (declp
, "operator");
3464 string_append (declp
, optable
[i
].out
);
3470 else if (declp
->p
- declp
->b
>= 5 && memcmp (declp
->b
, "type", 4) == 0
3471 && strchr (cplus_markers
, declp
->b
[4]) != NULL
)
3473 /* type conversion operator */
3475 if (do_type (work
, &tem
, &type
))
3477 string_clear (declp
);
3478 string_append (declp
, "operator ");
3479 string_appends (declp
, &type
);
3480 string_delete (&type
);
3483 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
3484 && declp
->b
[2] == 'o' && declp
->b
[3] == 'p')
3487 /* type conversion operator. */
3489 if (do_type (work
, &tem
, &type
))
3491 string_clear (declp
);
3492 string_append (declp
, "operator ");
3493 string_appends (declp
, &type
);
3494 string_delete (&type
);
3497 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
3498 && declp
->b
[2] >= 'a' && declp
->b
[2] <= 'z'
3499 && declp
->b
[3] >= 'a' && declp
->b
[3] <= 'z')
3501 if (declp
->b
[4] == '\0')
3504 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3506 if (strlen (optable
[i
].in
) == 2
3507 && memcmp (optable
[i
].in
, declp
->b
+ 2, 2) == 0)
3509 string_clear (declp
);
3510 string_append (declp
, "operator");
3511 string_append (declp
, optable
[i
].out
);
3518 if (declp
->b
[2] == 'a' && declp
->b
[5] == '\0')
3521 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3523 if (strlen (optable
[i
].in
) == 3
3524 && memcmp (optable
[i
].in
, declp
->b
+ 2, 3) == 0)
3526 string_clear (declp
);
3527 string_append (declp
, "operator");
3528 string_append (declp
, optable
[i
].out
);
3537 /* a mini string-handling package */
3552 s
->p
= s
->b
= xmalloc (n
);
3555 else if (s
->e
- s
->p
< n
)
3560 s
->b
= xrealloc (s
->b
, n
);
3573 s
->b
= s
->e
= s
->p
= NULL
;
3581 s
->b
= s
->p
= s
->e
= NULL
;
3597 return (s
->b
== s
->p
);
3603 string_append (p
, s
)
3608 if (s
== NULL
|| *s
== '\0')
3612 memcpy (p
->p
, s
, n
);
3617 string_appends (p
, s
)
3626 memcpy (p
->p
, s
->b
, n
);
3632 string_appendn (p
, s
, n
)
3640 memcpy (p
->p
, s
, n
);
3646 string_prepend (p
, s
)
3650 if (s
!= NULL
&& *s
!= '\0')
3652 string_prependn (p
, s
, strlen (s
));
3657 string_prepends (p
, s
)
3662 string_prependn (p
, s
->b
, s
->p
- s
->b
);
3667 string_prependn (p
, s
, n
)
3677 for (q
= p
->p
- 1; q
>= p
->b
; q
--)
3681 memcpy (p
->b
, s
, n
);
3686 /* To generate a standalone demangler program for testing purposes,
3687 just compile and link this file with -DMAIN and libiberty.a. When
3688 run, it demangles each command line arg, or each stdin string, and
3689 prints the result on stdout. */
3695 static char *program_name
;
3696 static char *program_version
= VERSION
;
3697 static int flags
= DMGL_PARAMS
| DMGL_ANSI
;
3699 static void demangle_it
PARAMS ((char *));
3700 static void usage
PARAMS ((FILE *, int));
3701 static void fatal
PARAMS ((char *));
3704 demangle_it (mangled_name
)
3709 result
= cplus_demangle (mangled_name
, flags
);
3712 printf ("%s\n", mangled_name
);
3716 printf ("%s\n", result
);
3722 usage (stream
, status
)
3727 Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
3728 [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\
3729 [--help] [--version] [arg...]\n",
3734 #define MBUF_SIZE 32767
3735 char mbuffer
[MBUF_SIZE
];
3737 /* Defined in the automatically-generated underscore.c. */
3738 extern int prepends_underscore
;
3740 int strip_underscore
= 0;
3742 static struct option long_options
[] = {
3743 {"strip-underscores", no_argument
, 0, '_'},
3744 {"format", required_argument
, 0, 's'},
3745 {"help", no_argument
, 0, 'h'},
3746 {"no-strip-underscores", no_argument
, 0, 'n'},
3747 {"version", no_argument
, 0, 'v'},
3748 {0, no_argument
, 0, 0}
3751 /* More 'friendly' abort that prints the line and file.
3752 config.h can #define abort fancy_abort if you like that sort of thing. */
3757 fatal ("Internal gcc abort.");
3768 program_name
= argv
[0];
3770 strip_underscore
= prepends_underscore
;
3772 while ((c
= getopt_long (argc
, argv
, "_ns:j", long_options
, (int *) 0)) != EOF
)
3782 strip_underscore
= 0;
3785 printf ("GNU %s version %s\n", program_name
, program_version
);
3788 strip_underscore
= 1;
3791 if (strcmp (optarg
, "gnu") == 0)
3793 current_demangling_style
= gnu_demangling
;
3795 else if (strcmp (optarg
, "lucid") == 0)
3797 current_demangling_style
= lucid_demangling
;
3799 else if (strcmp (optarg
, "arm") == 0)
3801 current_demangling_style
= arm_demangling
;
3805 fprintf (stderr
, "%s: unknown demangling style `%s'\n",
3806 program_name
, optarg
);
3815 for ( ; optind
< argc
; optind
++)
3817 demangle_it (argv
[optind
]);
3826 /* Try to read a label. */
3827 while (c
!= EOF
&& (isalnum(c
) || c
== '_' || c
== '$' || c
== '.'))
3829 if (i
>= MBUF_SIZE
-1)
3838 if (mbuffer
[0] == '.')
3840 if (strip_underscore
&& mbuffer
[skip_first
] == '_')
3848 result
= cplus_demangle (mbuffer
+ skip_first
, flags
);
3851 if (mbuffer
[0] == '.')
3853 fputs (result
, stdout
);
3857 fputs (mbuffer
, stdout
);
3874 fprintf (stderr
, "%s: %s\n", program_name
, str
);
3885 register char *value
= (char *) malloc (size
);
3887 fatal ("virtual memory exhausted");
3892 xrealloc (ptr
, size
)
3896 register char *value
= (char *) realloc (ptr
, size
);
3898 fatal ("virtual memory exhausted");