1 /* Demangler for GNU C++
2 Copyright 1989, 1991, 1994, 1995, 1996, 1997 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 /* Stuff that is shared between sub-routines.
98 Using a shared structure allows cplus_demangle to be reentrant. */
108 int static_type
; /* A static member function */
109 int const_type
; /* A const member function */
110 char **tmpl_argvec
; /* Template function arguments. */
111 int ntmpl_args
; /* The number of template function arguments. */
114 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
115 #define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS)
117 static const struct optable
123 {"nw", " new", DMGL_ANSI
}, /* new (1.92, ansi) */
124 {"dl", " delete", DMGL_ANSI
}, /* new (1.92, ansi) */
125 {"new", " new", 0}, /* old (1.91, and 1.x) */
126 {"delete", " delete", 0}, /* old (1.91, and 1.x) */
127 {"vn", " new []", DMGL_ANSI
}, /* GNU, pending ansi */
128 {"vd", " delete []", DMGL_ANSI
}, /* GNU, pending ansi */
129 {"as", "=", DMGL_ANSI
}, /* ansi */
130 {"ne", "!=", DMGL_ANSI
}, /* old, ansi */
131 {"eq", "==", DMGL_ANSI
}, /* old, ansi */
132 {"ge", ">=", DMGL_ANSI
}, /* old, ansi */
133 {"gt", ">", DMGL_ANSI
}, /* old, ansi */
134 {"le", "<=", DMGL_ANSI
}, /* old, ansi */
135 {"lt", "<", DMGL_ANSI
}, /* old, ansi */
136 {"plus", "+", 0}, /* old */
137 {"pl", "+", DMGL_ANSI
}, /* ansi */
138 {"apl", "+=", DMGL_ANSI
}, /* ansi */
139 {"minus", "-", 0}, /* old */
140 {"mi", "-", DMGL_ANSI
}, /* ansi */
141 {"ami", "-=", DMGL_ANSI
}, /* ansi */
142 {"mult", "*", 0}, /* old */
143 {"ml", "*", DMGL_ANSI
}, /* ansi */
144 {"amu", "*=", DMGL_ANSI
}, /* ansi (ARM/Lucid) */
145 {"aml", "*=", DMGL_ANSI
}, /* ansi (GNU/g++) */
146 {"convert", "+", 0}, /* old (unary +) */
147 {"negate", "-", 0}, /* old (unary -) */
148 {"trunc_mod", "%", 0}, /* old */
149 {"md", "%", DMGL_ANSI
}, /* ansi */
150 {"amd", "%=", DMGL_ANSI
}, /* ansi */
151 {"trunc_div", "/", 0}, /* old */
152 {"dv", "/", DMGL_ANSI
}, /* ansi */
153 {"adv", "/=", DMGL_ANSI
}, /* ansi */
154 {"truth_andif", "&&", 0}, /* old */
155 {"aa", "&&", DMGL_ANSI
}, /* ansi */
156 {"truth_orif", "||", 0}, /* old */
157 {"oo", "||", DMGL_ANSI
}, /* ansi */
158 {"truth_not", "!", 0}, /* old */
159 {"nt", "!", DMGL_ANSI
}, /* ansi */
160 {"postincrement","++", 0}, /* old */
161 {"pp", "++", DMGL_ANSI
}, /* ansi */
162 {"postdecrement","--", 0}, /* old */
163 {"mm", "--", DMGL_ANSI
}, /* ansi */
164 {"bit_ior", "|", 0}, /* old */
165 {"or", "|", DMGL_ANSI
}, /* ansi */
166 {"aor", "|=", DMGL_ANSI
}, /* ansi */
167 {"bit_xor", "^", 0}, /* old */
168 {"er", "^", DMGL_ANSI
}, /* ansi */
169 {"aer", "^=", DMGL_ANSI
}, /* ansi */
170 {"bit_and", "&", 0}, /* old */
171 {"ad", "&", DMGL_ANSI
}, /* ansi */
172 {"aad", "&=", DMGL_ANSI
}, /* ansi */
173 {"bit_not", "~", 0}, /* old */
174 {"co", "~", DMGL_ANSI
}, /* ansi */
175 {"call", "()", 0}, /* old */
176 {"cl", "()", DMGL_ANSI
}, /* ansi */
177 {"alshift", "<<", 0}, /* old */
178 {"ls", "<<", DMGL_ANSI
}, /* ansi */
179 {"als", "<<=", DMGL_ANSI
}, /* ansi */
180 {"arshift", ">>", 0}, /* old */
181 {"rs", ">>", DMGL_ANSI
}, /* ansi */
182 {"ars", ">>=", DMGL_ANSI
}, /* ansi */
183 {"component", "->", 0}, /* old */
184 {"pt", "->", DMGL_ANSI
}, /* ansi; Lucid C++ form */
185 {"rf", "->", DMGL_ANSI
}, /* ansi; ARM/GNU form */
186 {"indirect", "*", 0}, /* old */
187 {"method_call", "->()", 0}, /* old */
188 {"addr", "&", 0}, /* old (unary &) */
189 {"array", "[]", 0}, /* old */
190 {"vc", "[]", DMGL_ANSI
}, /* ansi */
191 {"compound", ", ", 0}, /* old */
192 {"cm", ", ", DMGL_ANSI
}, /* ansi */
193 {"cond", "?:", 0}, /* old */
194 {"cn", "?:", DMGL_ANSI
}, /* pseudo-ansi */
195 {"max", ">?", 0}, /* old */
196 {"mx", ">?", DMGL_ANSI
}, /* pseudo-ansi */
197 {"min", "<?", 0}, /* old */
198 {"mn", "<?", DMGL_ANSI
}, /* pseudo-ansi */
199 {"nop", "", 0}, /* old (for operator=) */
200 {"rm", "->*", DMGL_ANSI
} /* ansi */
204 typedef struct string
/* Beware: these aren't required to be */
205 { /* '\0' terminated. */
206 char *b
; /* pointer to start of string */
207 char *p
; /* pointer after last character */
208 char *e
; /* pointer after end of allocated space */
211 #define STRING_EMPTY(str) ((str) -> b == (str) -> p)
212 #define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
213 string_prepend(str, " ");}
214 #define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
215 string_append(str, " ");}
217 #define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */
218 #define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */
220 /* Prototypes for local functions */
223 mop_up
PARAMS ((struct work_stuff
*, string
*, int));
227 demangle_method_args
PARAMS ((struct work_stuff
*work
, const char **, string
*));
231 demangle_template_template_parm
PARAMS ((struct work_stuff
*work
,
232 const char **, string
*));
235 demangle_template
PARAMS ((struct work_stuff
*work
, const char **, string
*,
239 arm_pt
PARAMS ((struct work_stuff
*, const char *, int, const char **,
243 demangle_arm_pt
PARAMS ((struct work_stuff
*, const char **, int, string
*));
246 demangle_class_name
PARAMS ((struct work_stuff
*, const char **, string
*));
249 demangle_qualified
PARAMS ((struct work_stuff
*, const char **, string
*,
253 demangle_class
PARAMS ((struct work_stuff
*, const char **, string
*));
256 demangle_fund_type
PARAMS ((struct work_stuff
*, const char **, string
*));
259 demangle_signature
PARAMS ((struct work_stuff
*, const char **, string
*));
262 demangle_prefix
PARAMS ((struct work_stuff
*, const char **, string
*));
265 gnu_special
PARAMS ((struct work_stuff
*, const char **, string
*));
268 arm_special
PARAMS ((const char **, string
*));
271 string_need
PARAMS ((string
*, int));
274 string_delete
PARAMS ((string
*));
277 string_init
PARAMS ((string
*));
280 string_clear
PARAMS ((string
*));
284 string_empty
PARAMS ((string
*));
288 string_append
PARAMS ((string
*, const char *));
291 string_appends
PARAMS ((string
*, string
*));
294 string_appendn
PARAMS ((string
*, const char *, int));
297 string_prepend
PARAMS ((string
*, const char *));
300 string_prependn
PARAMS ((string
*, const char *, int));
303 get_count
PARAMS ((const char **, int *));
306 consume_count
PARAMS ((const char **));
309 consume_count_with_underscores
PARAMS ((const char**));
312 demangle_args
PARAMS ((struct work_stuff
*, const char **, string
*));
315 do_type
PARAMS ((struct work_stuff
*, const char **, string
*));
318 do_arg
PARAMS ((struct work_stuff
*, const char **, string
*));
321 demangle_function_name
PARAMS ((struct work_stuff
*, const char **, string
*,
325 remember_type
PARAMS ((struct work_stuff
*, const char *, int));
328 forget_types
PARAMS ((struct work_stuff
*));
331 string_prepends
PARAMS ((string
*, string
*));
333 /* Translate count to integer, consuming tokens in the process.
334 Conversion terminates on the first non-digit character.
335 Trying to consume something that isn't a count results in
336 no consumption of input and a return of 0. */
344 while (isdigit (**type
))
347 count
+= **type
- '0';
354 /* Like consume_count, but for counts that are preceded and followed
355 by '_' if they are greater than 10. Also, -1 is returned for
356 failure, since 0 can be a valid value. */
359 consume_count_with_underscores (mangled
)
360 const char **mangled
;
364 if (**mangled
== '_')
367 if (!isdigit (**mangled
))
370 idx
= consume_count (mangled
);
371 if (**mangled
!= '_')
372 /* The trailing underscore was missing. */
379 if (**mangled
< '0' || **mangled
> '9')
382 idx
= **mangled
- '0';
390 cplus_demangle_opname (opname
, result
, options
)
395 int len
, i
, len1
, ret
;
397 struct work_stuff work
[1];
400 len
= strlen(opname
);
403 work
->options
= options
;
405 if (opname
[0] == '_' && opname
[1] == '_'
406 && opname
[2] == 'o' && opname
[3] == 'p')
409 /* type conversion operator. */
411 if (do_type (work
, &tem
, &type
))
413 strcat (result
, "operator ");
414 strncat (result
, type
.b
, type
.p
- type
.b
);
415 string_delete (&type
);
419 else if (opname
[0] == '_' && opname
[1] == '_'
420 && opname
[2] >= 'a' && opname
[2] <= 'z'
421 && opname
[3] >= 'a' && opname
[3] <= 'z')
423 if (opname
[4] == '\0')
426 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
428 if (strlen (optable
[i
].in
) == 2
429 && memcmp (optable
[i
].in
, opname
+ 2, 2) == 0)
431 strcat (result
, "operator");
432 strcat (result
, optable
[i
].out
);
440 if (opname
[2] == 'a' && opname
[5] == '\0')
443 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
445 if (strlen (optable
[i
].in
) == 3
446 && memcmp (optable
[i
].in
, opname
+ 2, 3) == 0)
448 strcat (result
, "operator");
449 strcat (result
, optable
[i
].out
);
460 && strchr (cplus_markers
, opname
[2]) != NULL
)
462 /* see if it's an assignment expression */
463 if (len
>= 10 /* op$assign_ */
464 && memcmp (opname
+ 3, "assign_", 7) == 0)
466 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
469 if (strlen (optable
[i
].in
) == len1
470 && memcmp (optable
[i
].in
, opname
+ 10, len1
) == 0)
472 strcat (result
, "operator");
473 strcat (result
, optable
[i
].out
);
474 strcat (result
, "=");
482 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
485 if (strlen (optable
[i
].in
) == len1
486 && memcmp (optable
[i
].in
, opname
+ 3, len1
) == 0)
488 strcat (result
, "operator");
489 strcat (result
, optable
[i
].out
);
496 else if (len
>= 5 && memcmp (opname
, "type", 4) == 0
497 && strchr (cplus_markers
, opname
[4]) != NULL
)
499 /* type conversion operator */
501 if (do_type (work
, &tem
, &type
))
503 strcat (result
, "operator ");
504 strncat (result
, type
.b
, type
.p
- type
.b
);
505 string_delete (&type
);
512 /* Takes operator name as e.g. "++" and returns mangled
513 operator name (e.g. "postincrement_expr"), or NULL if not found.
515 If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
516 if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */
519 cplus_mangle_opname (opname
, options
)
526 len
= strlen (opname
);
527 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
529 if (strlen (optable
[i
].out
) == len
530 && (options
& DMGL_ANSI
) == (optable
[i
].flags
& DMGL_ANSI
)
531 && memcmp (optable
[i
].out
, opname
, len
) == 0)
532 return optable
[i
].in
;
537 /* char *cplus_demangle (const char *mangled, int options)
539 If MANGLED is a mangled function name produced by GNU C++, then
540 a pointer to a malloced string giving a C++ representation
541 of the name will be returned; otherwise NULL will be returned.
542 It is the caller's responsibility to free the string which
545 The OPTIONS arg may contain one or more of the following bits:
547 DMGL_ANSI ANSI qualifiers such as `const' and `void' are
549 DMGL_PARAMS Function parameters are included.
553 cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)"
554 cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
555 cplus_demangle ("foo__1Ai", 0) => "A::foo"
557 cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)"
558 cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
559 cplus_demangle ("foo__1Afe", 0) => "A::foo"
561 Note that any leading underscores, or other such characters prepended by
562 the compilation system, are presumed to have already been stripped from
566 cplus_demangle (mangled
, options
)
572 struct work_stuff work
[1];
573 char *demangled
= NULL
;
575 if ((mangled
!= NULL
) && (*mangled
!= '\0'))
577 memset ((char *) work
, 0, sizeof (work
));
578 work
-> options
= options
;
579 if ((work
->options
& DMGL_STYLE_MASK
) == 0)
580 work
->options
|= (int)current_demangling_style
& DMGL_STYLE_MASK
;
584 /* First check to see if gnu style demangling is active and if the
585 string to be demangled contains a CPLUS_MARKER. If so, attempt to
586 recognize one of the gnu special forms rather than looking for a
587 standard prefix. In particular, don't worry about whether there
588 is a "__" string in the mangled string. Consider "_$_5__foo" for
591 if ((AUTO_DEMANGLING
|| GNU_DEMANGLING
))
593 success
= gnu_special (work
, &mangled
, &decl
);
597 success
= demangle_prefix (work
, &mangled
, &decl
);
599 if (success
&& (*mangled
!= '\0'))
601 success
= demangle_signature (work
, &mangled
, &decl
);
603 if (work
->constructor
== 2)
605 string_prepend(&decl
, "global constructors keyed to ");
606 work
->constructor
= 0;
608 else if (work
->destructor
== 2)
610 string_prepend(&decl
, "global destructors keyed to ");
611 work
->destructor
= 0;
613 demangled
= mop_up (work
, &decl
, success
);
619 mop_up (work
, declp
, success
)
620 struct work_stuff
*work
;
624 char *demangled
= NULL
;
626 /* Discard the remembered types, if any. */
629 if (work
-> typevec
!= NULL
)
631 free ((char *) work
-> typevec
);
633 if (work
->tmpl_argvec
)
637 for (i
= 0; i
< work
->ntmpl_args
; i
++)
638 if (work
->tmpl_argvec
[i
])
639 free ((char*) work
->tmpl_argvec
[i
]);
641 free ((char*) work
->tmpl_argvec
);
644 /* If demangling was successful, ensure that the demangled string is null
645 terminated and return it. Otherwise, free the demangling decl. */
649 string_delete (declp
);
653 string_appendn (declp
, "", 1);
654 demangled
= declp
-> b
;
663 demangle_signature -- demangle the signature part of a mangled name
668 demangle_signature (struct work_stuff *work, const char **mangled,
673 Consume and demangle the signature portion of the mangled name.
675 DECLP is the string where demangled output is being built. At
676 entry it contains the demangled root name from the mangled name
677 prefix. I.E. either a demangled operator name or the root function
678 name. In some special cases, it may contain nothing.
680 *MANGLED points to the current unconsumed location in the mangled
681 name. As tokens are consumed and demangling is performed, the
682 pointer is updated to continuously point at the next token to
685 Demangling GNU style mangled names is nasty because there is no
686 explicit token that marks the start of the outermost function
690 demangle_signature (work
, mangled
, declp
)
691 struct work_stuff
*work
;
692 const char **mangled
;
698 int expect_return_type
= 0;
699 const char *oldmangled
= NULL
;
703 while (success
&& (**mangled
!= '\0'))
708 oldmangled
= *mangled
;
709 success
= demangle_qualified (work
, mangled
, declp
, 1, 0);
712 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
714 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
722 /* Static member function */
723 if (oldmangled
== NULL
)
725 oldmangled
= *mangled
;
728 work
-> static_type
= 1;
732 /* a const member function */
733 if (oldmangled
== NULL
)
735 oldmangled
= *mangled
;
738 work
-> const_type
= 1;
741 case '0': case '1': case '2': case '3': case '4':
742 case '5': case '6': case '7': case '8': case '9':
743 if (oldmangled
== NULL
)
745 oldmangled
= *mangled
;
747 success
= demangle_class (work
, mangled
, declp
);
750 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
752 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
761 /* ARM style demangling includes a specific 'F' character after
762 the class name. For GNU style, it is just implied. So we can
763 safely just consume any 'F' at this point and be compatible
764 with either style. */
770 /* For lucid/ARM style we have to forget any types we might
771 have remembered up to this point, since they were not argument
772 types. GNU style considers all types seen as available for
773 back references. See comment in demangle_args() */
775 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
779 success
= demangle_args (work
, mangled
, declp
);
784 string_init(&trawname
);
786 if (oldmangled
== NULL
)
788 oldmangled
= *mangled
;
790 success
= demangle_template (work
, mangled
, &tname
, &trawname
, 1);
793 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
795 string_append(&tname
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
796 string_prepends(declp
, &tname
);
797 if (work
-> destructor
& 1)
799 string_prepend (&trawname
, "~");
800 string_appends (declp
, &trawname
);
801 work
->destructor
-= 1;
803 if ((work
->constructor
& 1) || (work
->destructor
& 1))
805 string_appends (declp
, &trawname
);
806 work
->constructor
-= 1;
808 string_delete(&trawname
);
809 string_delete(&tname
);
815 if (GNU_DEMANGLING
&& expect_return_type
)
817 /* Read the return type. */
819 string_init (&return_type
);
822 success
= do_type (work
, mangled
, &return_type
);
823 APPEND_BLANK (&return_type
);
825 string_prepends (declp
, &return_type
);
826 string_delete (&return_type
);
830 /* At the outermost level, we cannot have a return type specified,
831 so if we run into another '_' at this point we are dealing with
832 a mangled name that is either bogus, or has been mangled by
833 some algorithm we don't know how to deal with. So just
834 reject the entire demangling. */
841 /* A G++ template function. Read the template arguments. */
842 success
= demangle_template (work
, mangled
, declp
, 0, 0);
843 if (!(work
->constructor
& 1))
844 expect_return_type
= 1;
853 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
855 /* Assume we have stumbled onto the first outermost function
856 argument token, and start processing args. */
858 success
= demangle_args (work
, mangled
, declp
);
862 /* Non-GNU demanglers use a specific token to mark the start
863 of the outermost function argument tokens. Typically 'F',
864 for ARM-demangling, for example. So if we find something
865 we are not prepared for, it must be an error. */
871 if (AUTO_DEMANGLING || GNU_DEMANGLING)
874 if (success
&& expect_func
)
877 success
= demangle_args (work
, mangled
, declp
);
878 /* Since template include the mangling of their return types,
879 we must set expect_func to 0 so that we don't try do
880 demangle more arguments the next time we get here. */
885 if (success
&& !func_done
)
887 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
889 /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
890 bar__3fooi is 'foo::bar(int)'. We get here when we find the
891 first case, and need to ensure that the '(void)' gets added to
892 the current declp. Note that with ARM, the first case
893 represents the name of a static data member 'foo::bar',
894 which is in the current declp, so we leave it alone. */
895 success
= demangle_args (work
, mangled
, declp
);
898 if (success
&& work
-> static_type
&& PRINT_ARG_TYPES
)
900 string_append (declp
, " static");
902 if (success
&& work
-> const_type
&& PRINT_ARG_TYPES
)
904 string_append (declp
, " const");
912 demangle_method_args (work
, mangled
, declp
)
913 struct work_stuff
*work
;
914 const char **mangled
;
919 if (work
-> static_type
)
921 string_append (declp
, *mangled
+ 1);
922 *mangled
+= strlen (*mangled
);
927 success
= demangle_args (work
, mangled
, declp
);
935 demangle_template_template_parm (work
, mangled
, tname
)
936 struct work_stuff
*work
;
937 const char **mangled
;
946 string_append (tname
, "template <");
947 /* get size of template parameter list */
948 if (get_count (mangled
, &r
))
950 for (i
= 0; i
< r
; i
++)
954 string_append (tname
, ", ");
957 /* Z for type parameters */
958 if (**mangled
== 'Z')
961 string_append (tname
, "class");
963 /* z for template parameters */
964 else if (**mangled
== 'z')
968 demangle_template_template_parm (work
, mangled
, tname
);
976 /* temp is initialized in do_type */
977 success
= do_type (work
, mangled
, &temp
);
980 string_appends (tname
, &temp
);
982 string_delete(&temp
);
992 if (tname
->p
[-1] == '>')
993 string_append (tname
, " ");
994 string_append (tname
, "> class");
999 demangle_template (work
, mangled
, tname
, trawname
, is_type
)
1000 struct work_stuff
*work
;
1001 const char **mangled
;
1019 int is_java_array
= 0;
1026 /* get template name */
1027 if (**mangled
== 'z')
1033 idx
= consume_count_with_underscores (mangled
);
1035 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
1036 || consume_count_with_underscores (mangled
) == -1)
1040 if (work
->tmpl_argvec
)
1042 string_append (tname
, work
->tmpl_argvec
[idx
]);
1044 string_append (trawname
, work
->tmpl_argvec
[idx
]);
1049 sprintf(buf
, "T%d", idx
);
1050 string_append (tname
, buf
);
1052 string_append (trawname
, work
->tmpl_argvec
[idx
]);
1057 if ((r
= consume_count (mangled
)) == 0 || strlen (*mangled
) < r
)
1062 string_appendn (trawname
, *mangled
, r
);
1063 is_java_array
= (work
-> options
& DMGL_JAVA
)
1064 && strncmp (*mangled
, "JArray1Z", 8) == 0;
1065 if (! is_java_array
)
1067 string_appendn (tname
, *mangled
, r
);
1073 string_append (tname
, "<");
1074 /* get size of template parameter list */
1075 if (!get_count (mangled
, &r
))
1081 /* Create an array for saving the template argument values. */
1082 work
->tmpl_argvec
= (char**) xmalloc (r
* sizeof (char *));
1083 work
->ntmpl_args
= r
;
1084 for (i
= 0; i
< r
; i
++)
1085 work
->tmpl_argvec
[i
] = 0;
1087 for (i
= 0; i
< r
; i
++)
1091 string_append (tname
, ", ");
1093 /* Z for type parameters */
1094 if (**mangled
== 'Z')
1097 /* temp is initialized in do_type */
1098 success
= do_type (work
, mangled
, &temp
);
1101 string_appends (tname
, &temp
);
1105 /* Save the template argument. */
1106 int len
= temp
.p
- temp
.b
;
1107 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1108 memcpy (work
->tmpl_argvec
[i
], temp
.b
, len
);
1109 work
->tmpl_argvec
[i
][len
] = '\0';
1112 string_delete(&temp
);
1118 /* z for template parameters */
1119 else if (**mangled
== 'z')
1123 success
= demangle_template_template_parm (work
, mangled
, tname
);
1126 && (r2
= consume_count (mangled
)) > 0 && strlen (*mangled
) >= r2
)
1128 string_append (tname
, " ");
1129 string_appendn (tname
, *mangled
, r2
);
1132 /* Save the template argument. */
1134 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1135 memcpy (work
->tmpl_argvec
[i
], *mangled
, len
);
1136 work
->tmpl_argvec
[i
][len
] = '\0';
1150 /* otherwise, value parameter */
1158 /* temp is initialized in do_type */
1159 success
= do_type (work
, mangled
, &temp
);
1163 string_appends (s, &temp);
1166 string_delete(&temp
);
1172 string_append (s, "=");
1183 while (*old_p
&& !done
)
1190 done
= is_pointer
= 1;
1192 case 'C': /* const */
1193 case 'S': /* explicitly signed [char] */
1194 case 'U': /* unsigned */
1195 case 'V': /* volatile */
1196 case 'F': /* function */
1197 case 'M': /* member function */
1199 case 'J': /* complex */
1202 case 'Q': /* qualified name */
1203 done
= is_integral
= 1;
1205 case 'T': /* remembered type */
1208 case 'v': /* void */
1211 case 'x': /* long long */
1212 case 'l': /* long */
1214 case 's': /* short */
1215 case 'w': /* wchar_t */
1216 done
= is_integral
= 1;
1218 case 'b': /* bool */
1221 case 'c': /* char */
1224 case 'r': /* long double */
1225 case 'd': /* double */
1226 case 'f': /* float */
1230 /* it's probably user defined type, let's assume
1231 it's integral, it seems hard to figure out
1232 what it really is */
1233 done
= is_integral
= 1;
1236 if (**mangled
== 'Y')
1238 /* The next argument is a template parameter. */
1242 idx
= consume_count_with_underscores (mangled
);
1244 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
1245 || consume_count_with_underscores (mangled
) == -1)
1252 if (work
->tmpl_argvec
)
1253 string_append (s
, work
->tmpl_argvec
[idx
]);
1257 sprintf(buf
, "T%d", idx
);
1258 string_append (s
, buf
);
1261 else if (is_integral
)
1263 if (**mangled
== 'm')
1265 string_appendn (s
, "-", 1);
1268 while (isdigit (**mangled
))
1270 string_appendn (s
, *mangled
, 1);
1278 if (**mangled
== 'm')
1280 string_appendn (s
, "-", 1);
1283 string_appendn (s
, "'", 1);
1284 val
= consume_count(mangled
);
1294 string_appendn (s
, &tmp
[0], 1);
1295 string_appendn (s
, "'", 1);
1299 int val
= consume_count (mangled
);
1301 string_appendn (s
, "false", 5);
1303 string_appendn (s
, "true", 4);
1309 if (**mangled
== 'm')
1311 string_appendn (s
, "-", 1);
1314 while (isdigit (**mangled
))
1316 string_appendn (s
, *mangled
, 1);
1319 if (**mangled
== '.') /* fraction */
1321 string_appendn (s
, ".", 1);
1323 while (isdigit (**mangled
))
1325 string_appendn (s
, *mangled
, 1);
1329 if (**mangled
== 'e') /* exponent */
1331 string_appendn (s
, "e", 1);
1333 while (isdigit (**mangled
))
1335 string_appendn (s
, *mangled
, 1);
1340 else if (is_pointer
)
1342 symbol_len
= consume_count (mangled
);
1343 if (symbol_len
== 0)
1350 if (symbol_len
== 0)
1351 string_appendn (s
, "0", 1);
1354 char *p
= xmalloc (symbol_len
+ 1), *q
;
1355 strncpy (p
, *mangled
, symbol_len
);
1356 p
[symbol_len
] = '\0';
1357 q
= cplus_demangle (p
, work
->options
);
1358 string_appendn (s
, "&", 1);
1361 string_append (s
, q
);
1365 string_append (s
, p
);
1368 *mangled
+= symbol_len
;
1372 int len
= s
->p
- s
->b
;
1373 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1374 memcpy (work
->tmpl_argvec
[i
], s
->b
, len
);
1375 work
->tmpl_argvec
[i
][len
] = '\0';
1377 string_appends (tname
, s
);
1385 string_append (tname
, "[]");
1389 if (tname
->p
[-1] == '>')
1390 string_append (tname
, " ");
1391 string_append (tname
, ">");
1395 if (work -> static_type)
1397 string_append (declp, *mangled + 1);
1398 *mangled += strlen (*mangled);
1403 success = demangle_args (work, mangled, declp);
1411 arm_pt (work
, mangled
, n
, anchor
, args
)
1412 struct work_stuff
*work
;
1413 const char *mangled
;
1415 const char **anchor
, **args
;
1418 if (ARM_DEMANGLING
&& (*anchor
= mystrstr (mangled
, "__pt__")))
1421 *args
= *anchor
+ 6;
1422 len
= consume_count (args
);
1423 if (*args
+ len
== mangled
+ n
&& **args
== '_')
1433 demangle_arm_pt (work
, mangled
, n
, declp
)
1434 struct work_stuff
*work
;
1435 const char **mangled
;
1441 const char *e
= *mangled
+ n
;
1444 if (arm_pt (work
, *mangled
, n
, &p
, &args
))
1448 string_appendn (declp
, *mangled
, p
- *mangled
);
1449 string_append (declp
, "<");
1450 /* should do error checking here */
1452 string_clear (&arg
);
1453 do_type (work
, &args
, &arg
);
1454 string_appends (declp
, &arg
);
1455 string_append (declp
, ",");
1457 string_delete (&arg
);
1459 string_append (declp
, ">");
1463 string_appendn (declp
, *mangled
, n
);
1469 demangle_class_name (work
, mangled
, declp
)
1470 struct work_stuff
*work
;
1471 const char **mangled
;
1477 n
= consume_count (mangled
);
1478 if (strlen (*mangled
) >= n
)
1480 demangle_arm_pt (work
, mangled
, n
, declp
);
1491 demangle_class -- demangle a mangled class sequence
1496 demangle_class (struct work_stuff *work, const char **mangled,
1501 DECLP points to the buffer into which demangling is being done.
1503 *MANGLED points to the current token to be demangled. On input,
1504 it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
1505 On exit, it points to the next token after the mangled class on
1506 success, or the first unconsumed token on failure.
1508 If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
1509 we are demangling a constructor or destructor. In this case
1510 we prepend "class::class" or "class::~class" to DECLP.
1512 Otherwise, we prepend "class::" to the current DECLP.
1514 Reset the constructor/destructor flags once they have been
1515 "consumed". This allows demangle_class to be called later during
1516 the same demangling, to do normal class demangling.
1518 Returns 1 if demangling is successful, 0 otherwise.
1523 demangle_class (work
, mangled
, declp
)
1524 struct work_stuff
*work
;
1525 const char **mangled
;
1531 string_init (&class_name
);
1532 if (demangle_class_name (work
, mangled
, &class_name
))
1534 if ((work
->constructor
& 1) || (work
->destructor
& 1))
1536 string_prepends (declp
, &class_name
);
1537 if (work
-> destructor
& 1)
1539 string_prepend (declp
, "~");
1540 work
-> destructor
-= 1;
1544 work
-> constructor
-= 1;
1547 string_prepend (declp
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
1548 string_prepends (declp
, &class_name
);
1551 string_delete (&class_name
);
1559 demangle_prefix -- consume the mangled name prefix and find signature
1564 demangle_prefix (struct work_stuff *work, const char **mangled,
1569 Consume and demangle the prefix of the mangled name.
1571 DECLP points to the string buffer into which demangled output is
1572 placed. On entry, the buffer is empty. On exit it contains
1573 the root function name, the demangled operator name, or in some
1574 special cases either nothing or the completely demangled result.
1576 MANGLED points to the current pointer into the mangled name. As each
1577 token of the mangled name is consumed, it is updated. Upon entry
1578 the current mangled name pointer points to the first character of
1579 the mangled name. Upon exit, it should point to the first character
1580 of the signature if demangling was successful, or to the first
1581 unconsumed character if demangling of the prefix was unsuccessful.
1583 Returns 1 on success, 0 otherwise.
1587 demangle_prefix (work
, mangled
, declp
)
1588 struct work_stuff
*work
;
1589 const char **mangled
;
1596 if (strlen(*mangled
) >= 11 && strncmp(*mangled
, "_GLOBAL_", 8) == 0)
1598 char *marker
= strchr (cplus_markers
, (*mangled
)[8]);
1599 if (marker
!= NULL
&& *marker
== (*mangled
)[10])
1601 if ((*mangled
)[9] == 'D')
1603 /* it's a GNU global destructor to be executed at program exit */
1605 work
->destructor
= 2;
1606 if (gnu_special (work
, mangled
, declp
))
1609 else if ((*mangled
)[9] == 'I')
1611 /* it's a GNU global constructor to be executed at program init */
1613 work
->constructor
= 2;
1614 if (gnu_special (work
, mangled
, declp
))
1619 else if (ARM_DEMANGLING
&& strncmp(*mangled
, "__std__", 7) == 0)
1621 /* it's a ARM global destructor to be executed at program exit */
1623 work
->destructor
= 2;
1625 else if (ARM_DEMANGLING
&& strncmp(*mangled
, "__sti__", 7) == 0)
1627 /* it's a ARM global constructor to be executed at program initial */
1629 work
->constructor
= 2;
1632 /* This block of code is a reduction in strength time optimization
1634 scan = mystrstr (*mangled, "__"); */
1640 scan
= strchr (scan
, '_');
1641 } while (scan
!= NULL
&& *++scan
!= '_');
1643 if (scan
!= NULL
) --scan
;
1648 /* We found a sequence of two or more '_', ensure that we start at
1649 the last pair in the sequence. */
1650 i
= strspn (scan
, "_");
1661 else if (work
-> static_type
)
1663 if (!isdigit (scan
[0]) && (scan
[0] != 't'))
1668 else if ((scan
== *mangled
)
1669 && (isdigit (scan
[2]) || (scan
[2] == 'Q') || (scan
[2] == 't')
1670 || (scan
[2] == 'H')))
1672 /* The ARM says nothing about the mangling of local variables.
1673 But cfront mangles local variables by prepending __<nesting_level>
1674 to them. As an extension to ARM demangling we handle this case. */
1675 if ((LUCID_DEMANGLING
|| ARM_DEMANGLING
) && isdigit (scan
[2]))
1677 *mangled
= scan
+ 2;
1678 consume_count (mangled
);
1679 string_append (declp
, *mangled
);
1680 *mangled
+= strlen (*mangled
);
1685 /* A GNU style constructor starts with __[0-9Qt]. But cfront uses
1686 names like __Q2_3foo3bar for nested type names. So don't accept
1687 this style of constructor for cfront demangling. A GNU
1688 style member-template constructor starts with 'H'. */
1689 if (!(LUCID_DEMANGLING
|| ARM_DEMANGLING
))
1690 work
-> constructor
+= 1;
1691 *mangled
= scan
+ 2;
1694 else if ((scan
== *mangled
) && !isdigit (scan
[2]) && (scan
[2] != 't'))
1696 /* Mangled name starts with "__". Skip over any leading '_' characters,
1697 then find the next "__" that separates the prefix from the signature.
1699 if (!(ARM_DEMANGLING
|| LUCID_DEMANGLING
)
1700 || (arm_special (mangled
, declp
) == 0))
1702 while (*scan
== '_')
1706 if ((scan
= mystrstr (scan
, "__")) == NULL
|| (*(scan
+ 2) == '\0'))
1708 /* No separator (I.E. "__not_mangled"), or empty signature
1709 (I.E. "__not_mangled_either__") */
1714 demangle_function_name (work
, mangled
, declp
, scan
);
1718 else if (ARM_DEMANGLING
&& scan
[2] == 'p' && scan
[3] == 't')
1720 /* Cfront-style parameterized type. Handled later as a signature. */
1724 demangle_arm_pt (work
, mangled
, strlen (*mangled
), declp
);
1726 else if (*(scan
+ 2) != '\0')
1728 /* Mangled name does not start with "__" but does have one somewhere
1729 in there with non empty stuff after it. Looks like a global
1731 demangle_function_name (work
, mangled
, declp
, scan
);
1735 /* Doesn't look like a mangled name */
1739 if (!success
&& (work
->constructor
== 2 || work
->destructor
== 2))
1741 string_append (declp
, *mangled
);
1742 *mangled
+= strlen (*mangled
);
1752 gnu_special -- special handling of gnu mangled strings
1757 gnu_special (struct work_stuff *work, const char **mangled,
1763 Process some special GNU style mangling forms that don't fit
1764 the normal pattern. For example:
1766 _$_3foo (destructor for class foo)
1767 _vt$foo (foo virtual table)
1768 _vt$foo$bar (foo::bar virtual table)
1769 __vt_foo (foo virtual table, new style with thunks)
1770 _3foo$varname (static data member)
1771 _Q22rs2tu$vw (static data member)
1772 __t6vector1Zii (constructor with template)
1773 __thunk_4__$_7ostream (virtual function thunk)
1777 gnu_special (work
, mangled
, declp
)
1778 struct work_stuff
*work
;
1779 const char **mangled
;
1786 if ((*mangled
)[0] == '_'
1787 && strchr (cplus_markers
, (*mangled
)[1]) != NULL
1788 && (*mangled
)[2] == '_')
1790 /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
1792 work
-> destructor
+= 1;
1794 else if ((*mangled
)[0] == '_'
1795 && (((*mangled
)[1] == '_'
1796 && (*mangled
)[2] == 'v'
1797 && (*mangled
)[3] == 't'
1798 && (*mangled
)[4] == '_')
1799 || ((*mangled
)[1] == 'v'
1800 && (*mangled
)[2] == 't'
1801 && strchr (cplus_markers
, (*mangled
)[3]) != NULL
)))
1803 /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
1804 and create the decl. Note that we consume the entire mangled
1805 input string, which means that demangle_signature has no work
1807 if ((*mangled
)[2] == 'v')
1808 (*mangled
) += 5; /* New style, with thunks: "__vt_" */
1810 (*mangled
) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
1811 while (**mangled
!= '\0')
1813 p
= strpbrk (*mangled
, cplus_markers
);
1817 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
1820 success
= demangle_template (work
, mangled
, declp
, 0, 1);
1823 if (isdigit(*mangled
[0]))
1825 n
= consume_count(mangled
);
1829 n
= strcspn (*mangled
, cplus_markers
);
1831 string_appendn (declp
, *mangled
, n
);
1835 if (success
&& ((p
== NULL
) || (p
== *mangled
)))
1839 string_append (declp
,
1840 (work
-> options
& DMGL_JAVA
) ? "." : "::");
1851 string_append (declp
, " virtual table");
1853 else if ((*mangled
)[0] == '_'
1854 && (strchr("0123456789Qt", (*mangled
)[1]) != NULL
)
1855 && (p
= strpbrk (*mangled
, cplus_markers
)) != NULL
)
1857 /* static data member, "_3foo$varname" for example */
1862 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
1865 success
= demangle_template (work
, mangled
, declp
, 0, 1);
1868 n
= consume_count (mangled
);
1869 string_appendn (declp
, *mangled
, n
);
1872 if (success
&& (p
== *mangled
))
1874 /* Consumed everything up to the cplus_marker, append the
1877 string_append (declp
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
1878 n
= strlen (*mangled
);
1879 string_appendn (declp
, *mangled
, n
);
1887 else if (strncmp (*mangled
, "__thunk_", 8) == 0)
1889 int delta
= ((*mangled
) += 8, consume_count (mangled
));
1890 char *method
= cplus_demangle (++*mangled
, work
->options
);
1894 sprintf (buf
, "virtual function thunk (delta:%d) for ", -delta
);
1895 string_append (declp
, buf
);
1896 string_append (declp
, method
);
1898 n
= strlen (*mangled
);
1906 else if (strncmp (*mangled
, "__t", 3) == 0
1907 && ((*mangled
)[3] == 'i' || (*mangled
)[3] == 'f'))
1909 p
= (*mangled
)[3] == 'i' ? " type_info node" : " type_info function";
1914 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
1917 success
= demangle_template (work
, mangled
, declp
, 0, 1);
1920 success
= demangle_fund_type (work
, mangled
, declp
);
1923 if (success
&& **mangled
!= '\0')
1926 string_append (declp
, p
);
1939 arm_special -- special handling of ARM/lucid mangled strings
1944 arm_special (const char **mangled,
1950 Process some special ARM style mangling forms that don't fit
1951 the normal pattern. For example:
1953 __vtbl__3foo (foo virtual table)
1954 __vtbl__3foo__3bar (bar::foo virtual table)
1959 arm_special (mangled
, declp
)
1960 const char **mangled
;
1967 if (strncmp (*mangled
, ARM_VTABLE_STRING
, ARM_VTABLE_STRLEN
) == 0)
1969 /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
1970 and create the decl. Note that we consume the entire mangled
1971 input string, which means that demangle_signature has no work
1973 scan
= *mangled
+ ARM_VTABLE_STRLEN
;
1974 while (*scan
!= '\0') /* first check it can be demangled */
1976 n
= consume_count (&scan
);
1979 return (0); /* no good */
1982 if (scan
[0] == '_' && scan
[1] == '_')
1987 (*mangled
) += ARM_VTABLE_STRLEN
;
1988 while (**mangled
!= '\0')
1990 n
= consume_count (mangled
);
1991 string_prependn (declp
, *mangled
, n
);
1993 if ((*mangled
)[0] == '_' && (*mangled
)[1] == '_')
1995 string_prepend (declp
, "::");
1999 string_append (declp
, " virtual table");
2012 demangle_qualified -- demangle 'Q' qualified name strings
2017 demangle_qualified (struct work_stuff *, const char *mangled,
2018 string *result, int isfuncname, int append);
2022 Demangle a qualified name, such as "Q25Outer5Inner" which is
2023 the mangled form of "Outer::Inner". The demangled output is
2024 prepended or appended to the result string according to the
2025 state of the append flag.
2027 If isfuncname is nonzero, then the qualified name we are building
2028 is going to be used as a member function name, so if it is a
2029 constructor or destructor function, append an appropriate
2030 constructor or destructor name. I.E. for the above example,
2031 the result for use as a constructor is "Outer::Inner::Inner"
2032 and the result for use as a destructor is "Outer::Inner::~Inner".
2036 Numeric conversion is ASCII dependent (FIXME).
2041 demangle_qualified (work
, mangled
, result
, isfuncname
, append
)
2042 struct work_stuff
*work
;
2043 const char **mangled
;
2055 string_init (&temp
);
2056 switch ((*mangled
)[1])
2059 /* GNU mangled name with more than 9 classes. The count is preceded
2060 by an underscore (to distinguish it from the <= 9 case) and followed
2061 by an underscore. */
2063 qualifiers
= atoi (p
);
2064 if (!isdigit (*p
) || *p
== '0')
2067 /* Skip the digits. */
2068 while (isdigit (*p
))
2086 /* The count is in a single digit. */
2087 num
[0] = (*mangled
)[1];
2089 qualifiers
= atoi (num
);
2091 /* If there is an underscore after the digit, skip it. This is
2092 said to be for ARM-qualified names, but the ARM makes no
2093 mention of such an underscore. Perhaps cfront uses one. */
2094 if ((*mangled
)[2] == '_')
2109 /* Pick off the names and collect them in the temp buffer in the order
2110 in which they are found, separated by '::'. */
2112 while (qualifiers
-- > 0)
2114 if (*mangled
[0] == '_')
2115 *mangled
= *mangled
+ 1;
2116 if (*mangled
[0] == 't')
2118 success
= demangle_template(work
, mangled
, &temp
, 0, 1);
2119 if (!success
) break;
2121 else if (*mangled
[0] == 'X')
2123 success
= do_type (work
, mangled
, &temp
);
2124 if (!success
) break;
2128 namelength
= consume_count (mangled
);
2129 if (strlen (*mangled
) < namelength
)
2131 /* Simple sanity check failed */
2135 string_appendn (&temp
, *mangled
, namelength
);
2136 *mangled
+= namelength
;
2140 string_append (&temp
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
2144 /* If we are using the result as a function name, we need to append
2145 the appropriate '::' separated constructor or destructor name.
2146 We do this here because this is the most convenient place, where
2147 we already have a pointer to the name and the length of the name. */
2149 if (isfuncname
&& (work
->constructor
& 1 || work
->destructor
& 1))
2151 string_append (&temp
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
2152 if (work
-> destructor
& 1)
2154 string_append (&temp
, "~");
2156 string_appendn (&temp
, (*mangled
) - namelength
, namelength
);
2159 /* Now either prepend the temp buffer to the result, or append it,
2160 depending upon the state of the append flag. */
2164 string_appends (result
, &temp
);
2168 if (!STRING_EMPTY (result
))
2170 string_append (&temp
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
2172 string_prepends (result
, &temp
);
2175 string_delete (&temp
);
2183 get_count -- convert an ascii count to integer, consuming tokens
2188 get_count (const char **type, int *count)
2192 Return 0 if no conversion is performed, 1 if a string is converted.
2196 get_count (type
, count
)
2203 if (!isdigit (**type
))
2209 *count
= **type
- '0';
2211 if (isdigit (**type
))
2221 while (isdigit (*p
));
2232 /* result will be initialised here; it will be freed on failure */
2235 do_type (work
, mangled
, result
)
2236 struct work_stuff
*work
;
2237 const char **mangled
;
2244 const char *remembered_type
;
2248 string_init (&decl
);
2249 string_init (result
);
2253 while (success
&& !done
)
2259 /* A pointer type */
2263 if (! (work
-> options
& DMGL_JAVA
))
2264 string_prepend (&decl
, "*");
2267 /* A reference type */
2270 string_prepend (&decl
, "&");
2276 const char *p
= ++(*mangled
);
2278 string_prepend (&decl
, "(");
2279 string_append (&decl
, ")[");
2280 /* Copy anything up until the next underscore (the size of the
2282 while (**mangled
&& **mangled
!= '_')
2284 if (**mangled
== '_')
2286 string_appendn (&decl
, p
, *mangled
- p
);
2287 string_append (&decl
, "]");
2295 /* A back reference to a previously seen type */
2298 if (!get_count (mangled
, &n
) || n
>= work
-> ntypes
)
2304 remembered_type
= work
-> typevec
[n
];
2305 mangled
= &remembered_type
;
2312 if (!STRING_EMPTY (&decl
) && decl
.b
[0] == '*')
2314 string_prepend (&decl
, "(");
2315 string_append (&decl
, ")");
2317 /* After picking off the function args, we expect to either find the
2318 function return type (preceded by an '_') or the end of the
2320 if (!demangle_args (work
, mangled
, &decl
)
2321 || (**mangled
!= '_' && **mangled
!= '\0'))
2325 if (success
&& (**mangled
== '_'))
2337 member
= **mangled
== 'M';
2339 if (!isdigit (**mangled
) && **mangled
!= 't')
2345 string_append (&decl
, ")");
2346 string_prepend (&decl
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
2347 if (isdigit (**mangled
))
2349 n
= consume_count (mangled
);
2350 if (strlen (*mangled
) < n
)
2355 string_prependn (&decl
, *mangled
, n
);
2361 string_init (&temp
);
2362 success
= demangle_template (work
, mangled
, &temp
, NULL
, 1);
2365 string_prependn (&decl
, temp
.b
, temp
.p
- temp
.b
);
2366 string_clear (&temp
);
2371 string_prepend (&decl
, "(");
2374 if (**mangled
== 'C')
2379 if (**mangled
== 'V')
2384 if (*(*mangled
)++ != 'F')
2390 if ((member
&& !demangle_args (work
, mangled
, &decl
))
2391 || **mangled
!= '_')
2397 if (! PRINT_ANSI_QUALIFIERS
)
2403 APPEND_BLANK (&decl
);
2404 string_append (&decl
, "const");
2408 APPEND_BLANK (&decl
);
2409 string_append (&decl
, "volatile");
2420 if ((*mangled)[1] == 'P')
2423 if (PRINT_ANSI_QUALIFIERS
)
2425 if (!STRING_EMPTY (&decl
))
2427 string_prepend (&decl
, " ");
2429 string_prepend (&decl
, "const");
2445 /* A qualified name, such as "Outer::Inner". */
2447 success
= demangle_qualified (work
, mangled
, result
, 0, 1);
2452 /* A template parm. We substitute the corresponding argument. */
2457 idx
= consume_count_with_underscores (mangled
);
2460 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
2461 || consume_count_with_underscores (mangled
) == -1)
2467 if (work
->tmpl_argvec
)
2468 string_append (result
, work
->tmpl_argvec
[idx
]);
2472 sprintf(buf
, "T%d", idx
);
2473 string_append (result
, buf
);
2481 success
= demangle_fund_type (work
, mangled
, result
);
2487 if (!STRING_EMPTY (&decl
))
2489 string_append (result
, " ");
2490 string_appends (result
, &decl
);
2495 string_delete (result
);
2497 string_delete (&decl
);
2501 /* Given a pointer to a type string that represents a fundamental type
2502 argument (int, long, unsigned int, etc) in TYPE, a pointer to the
2503 string in which the demangled output is being built in RESULT, and
2504 the WORK structure, decode the types and add them to the result.
2509 "Sl" => "signed long"
2510 "CUs" => "const unsigned short"
2515 demangle_fund_type (work
, mangled
, result
)
2516 struct work_stuff
*work
;
2517 const char **mangled
;
2523 /* First pick off any type qualifiers. There can be more than one. */
2531 if (PRINT_ANSI_QUALIFIERS
)
2533 APPEND_BLANK (result
);
2534 string_append (result
, "const");
2539 APPEND_BLANK (result
);
2540 string_append (result
, "unsigned");
2542 case 'S': /* signed char only */
2544 APPEND_BLANK (result
);
2545 string_append (result
, "signed");
2549 if (PRINT_ANSI_QUALIFIERS
)
2551 APPEND_BLANK (result
);
2552 string_append (result
, "volatile");
2557 APPEND_BLANK (result
);
2558 string_append (result
, "__complex");
2566 /* Now pick off the fundamental type. There can be only one. */
2575 APPEND_BLANK (result
);
2576 string_append (result
, "void");
2580 APPEND_BLANK (result
);
2581 string_append (result
, "long long");
2585 APPEND_BLANK (result
);
2586 string_append (result
, "long");
2590 APPEND_BLANK (result
);
2591 string_append (result
, "int");
2595 APPEND_BLANK (result
);
2596 string_append (result
, "short");
2600 APPEND_BLANK (result
);
2601 string_append (result
, "bool");
2605 APPEND_BLANK (result
);
2606 string_append (result
, "char");
2610 APPEND_BLANK (result
);
2611 string_append (result
, "wchar_t");
2615 APPEND_BLANK (result
);
2616 string_append (result
, "long double");
2620 APPEND_BLANK (result
);
2621 string_append (result
, "double");
2625 APPEND_BLANK (result
);
2626 string_append (result
, "float");
2630 if (!isdigit (**mangled
))
2636 /* An explicit type, such as "6mytype" or "7integer" */
2647 APPEND_BLANK (result
);
2648 if (!demangle_class_name (work
, mangled
, result
)) {
2654 success
= demangle_template(work
,mangled
, result
, 0, 1);
2664 /* `result' will be initialized in do_type; it will be freed on failure */
2667 do_arg (work
, mangled
, result
)
2668 struct work_stuff
*work
;
2669 const char **mangled
;
2672 const char *start
= *mangled
;
2674 if (!do_type (work
, mangled
, result
))
2680 remember_type (work
, start
, *mangled
- start
);
2686 remember_type (work
, start
, len
)
2687 struct work_stuff
*work
;
2693 if (work
-> ntypes
>= work
-> typevec_size
)
2695 if (work
-> typevec_size
== 0)
2697 work
-> typevec_size
= 3;
2699 = (char **) xmalloc (sizeof (char *) * work
-> typevec_size
);
2703 work
-> typevec_size
*= 2;
2705 = (char **) xrealloc ((char *)work
-> typevec
,
2706 sizeof (char *) * work
-> typevec_size
);
2709 tem
= xmalloc (len
+ 1);
2710 memcpy (tem
, start
, len
);
2712 work
-> typevec
[work
-> ntypes
++] = tem
;
2715 /* Forget the remembered types, but not the type vector itself. */
2719 struct work_stuff
*work
;
2723 while (work
-> ntypes
> 0)
2725 i
= --(work
-> ntypes
);
2726 if (work
-> typevec
[i
] != NULL
)
2728 free (work
-> typevec
[i
]);
2729 work
-> typevec
[i
] = NULL
;
2734 /* Process the argument list part of the signature, after any class spec
2735 has been consumed, as well as the first 'F' character (if any). For
2738 "__als__3fooRT0" => process "RT0"
2739 "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i"
2741 DECLP must be already initialised, usually non-empty. It won't be freed
2744 Note that g++ differs significantly from ARM and lucid style mangling
2745 with regards to references to previously seen types. For example, given
2746 the source fragment:
2750 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
2753 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
2754 void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
2756 g++ produces the names:
2761 while lcc (and presumably other ARM style compilers as well) produces:
2763 foo__FiR3fooT1T2T1T2
2764 __ct__3fooFiR3fooT1T2T1T2
2766 Note that g++ bases it's type numbers starting at zero and counts all
2767 previously seen types, while lucid/ARM bases it's type numbers starting
2768 at one and only considers types after it has seen the 'F' character
2769 indicating the start of the function args. For lucid/ARM style, we
2770 account for this difference by discarding any previously seen types when
2771 we see the 'F' character, and subtracting one from the type number
2777 demangle_args (work
, mangled
, declp
)
2778 struct work_stuff
*work
;
2779 const char **mangled
;
2789 if (PRINT_ARG_TYPES
)
2791 string_append (declp
, "(");
2792 if (**mangled
== '\0')
2794 string_append (declp
, "void");
2798 while (**mangled
!= '_' && **mangled
!= '\0' && **mangled
!= 'e')
2800 if ((**mangled
== 'N') || (**mangled
== 'T'))
2802 temptype
= *(*mangled
)++;
2804 if (temptype
== 'N')
2806 if (!get_count (mangled
, &r
))
2815 if (ARM_DEMANGLING
&& work
-> ntypes
>= 10)
2817 /* If we have 10 or more types we might have more than a 1 digit
2818 index so we'll have to consume the whole count here. This
2819 will lose if the next thing is a type name preceded by a
2820 count but it's impossible to demangle that case properly
2821 anyway. Eg if we already have 12 types is T12Pc "(..., type1,
2822 Pc, ...)" or "(..., type12, char *, ...)" */
2823 if ((t
= consume_count(mangled
)) == 0)
2830 if (!get_count (mangled
, &t
))
2835 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
2839 /* Validate the type index. Protect against illegal indices from
2840 malformed type strings. */
2841 if ((t
< 0) || (t
>= work
-> ntypes
))
2847 tem
= work
-> typevec
[t
];
2848 if (need_comma
&& PRINT_ARG_TYPES
)
2850 string_append (declp
, ", ");
2852 if (!do_arg (work
, &tem
, &arg
))
2856 if (PRINT_ARG_TYPES
)
2858 string_appends (declp
, &arg
);
2860 string_delete (&arg
);
2866 if (need_comma
& PRINT_ARG_TYPES
)
2868 string_append (declp
, ", ");
2870 if (!do_arg (work
, mangled
, &arg
))
2874 if (PRINT_ARG_TYPES
)
2876 string_appends (declp
, &arg
);
2878 string_delete (&arg
);
2883 if (**mangled
== 'e')
2886 if (PRINT_ARG_TYPES
)
2890 string_append (declp
, ",");
2892 string_append (declp
, "...");
2896 if (PRINT_ARG_TYPES
)
2898 string_append (declp
, ")");
2904 demangle_function_name (work
, mangled
, declp
, scan
)
2905 struct work_stuff
*work
;
2906 const char **mangled
;
2914 string_appendn (declp
, (*mangled
), scan
- (*mangled
));
2915 string_need (declp
, 1);
2916 *(declp
-> p
) = '\0';
2918 /* Consume the function name, including the "__" separating the name
2919 from the signature. We are guaranteed that SCAN points to the
2922 (*mangled
) = scan
+ 2;
2924 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
2927 /* See if we have an ARM style constructor or destructor operator.
2928 If so, then just record it, clear the decl, and return.
2929 We can't build the actual constructor/destructor decl until later,
2930 when we recover the class name from the signature. */
2932 if (strcmp (declp
-> b
, "__ct") == 0)
2934 work
-> constructor
+= 1;
2935 string_clear (declp
);
2938 else if (strcmp (declp
-> b
, "__dt") == 0)
2940 work
-> destructor
+= 1;
2941 string_clear (declp
);
2946 if (declp
->p
- declp
->b
>= 3
2947 && declp
->b
[0] == 'o'
2948 && declp
->b
[1] == 'p'
2949 && strchr (cplus_markers
, declp
->b
[2]) != NULL
)
2951 /* see if it's an assignment expression */
2952 if (declp
->p
- declp
->b
>= 10 /* op$assign_ */
2953 && memcmp (declp
->b
+ 3, "assign_", 7) == 0)
2955 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
2957 int len
= declp
->p
- declp
->b
- 10;
2958 if (strlen (optable
[i
].in
) == len
2959 && memcmp (optable
[i
].in
, declp
->b
+ 10, len
) == 0)
2961 string_clear (declp
);
2962 string_append (declp
, "operator");
2963 string_append (declp
, optable
[i
].out
);
2964 string_append (declp
, "=");
2971 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
2973 int len
= declp
->p
- declp
->b
- 3;
2974 if (strlen (optable
[i
].in
) == len
2975 && memcmp (optable
[i
].in
, declp
->b
+ 3, len
) == 0)
2977 string_clear (declp
);
2978 string_append (declp
, "operator");
2979 string_append (declp
, optable
[i
].out
);
2985 else if (declp
->p
- declp
->b
>= 5 && memcmp (declp
->b
, "type", 4) == 0
2986 && strchr (cplus_markers
, declp
->b
[4]) != NULL
)
2988 /* type conversion operator */
2990 if (do_type (work
, &tem
, &type
))
2992 string_clear (declp
);
2993 string_append (declp
, "operator ");
2994 string_appends (declp
, &type
);
2995 string_delete (&type
);
2998 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
2999 && declp
->b
[2] == 'o' && declp
->b
[3] == 'p')
3002 /* type conversion operator. */
3004 if (do_type (work
, &tem
, &type
))
3006 string_clear (declp
);
3007 string_append (declp
, "operator ");
3008 string_appends (declp
, &type
);
3009 string_delete (&type
);
3012 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
3013 && declp
->b
[2] >= 'a' && declp
->b
[2] <= 'z'
3014 && declp
->b
[3] >= 'a' && declp
->b
[3] <= 'z')
3016 if (declp
->b
[4] == '\0')
3019 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3021 if (strlen (optable
[i
].in
) == 2
3022 && memcmp (optable
[i
].in
, declp
->b
+ 2, 2) == 0)
3024 string_clear (declp
);
3025 string_append (declp
, "operator");
3026 string_append (declp
, optable
[i
].out
);
3033 if (declp
->b
[2] == 'a' && declp
->b
[5] == '\0')
3036 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3038 if (strlen (optable
[i
].in
) == 3
3039 && memcmp (optable
[i
].in
, declp
->b
+ 2, 3) == 0)
3041 string_clear (declp
);
3042 string_append (declp
, "operator");
3043 string_append (declp
, optable
[i
].out
);
3052 /* a mini string-handling package */
3067 s
->p
= s
->b
= xmalloc (n
);
3070 else if (s
->e
- s
->p
< n
)
3075 s
->b
= xrealloc (s
->b
, n
);
3088 s
->b
= s
->e
= s
->p
= NULL
;
3096 s
->b
= s
->p
= s
->e
= NULL
;
3112 return (s
->b
== s
->p
);
3118 string_append (p
, s
)
3123 if (s
== NULL
|| *s
== '\0')
3127 memcpy (p
->p
, s
, n
);
3132 string_appends (p
, s
)
3141 memcpy (p
->p
, s
->b
, n
);
3147 string_appendn (p
, s
, n
)
3155 memcpy (p
->p
, s
, n
);
3161 string_prepend (p
, s
)
3165 if (s
!= NULL
&& *s
!= '\0')
3167 string_prependn (p
, s
, strlen (s
));
3172 string_prepends (p
, s
)
3177 string_prependn (p
, s
->b
, s
->p
- s
->b
);
3182 string_prependn (p
, s
, n
)
3192 for (q
= p
->p
- 1; q
>= p
->b
; q
--)
3196 memcpy (p
->b
, s
, n
);
3201 /* To generate a standalone demangler program for testing purposes,
3202 just compile and link this file with -DMAIN and libiberty.a. When
3203 run, it demangles each command line arg, or each stdin string, and
3204 prints the result on stdout. */
3210 static char *program_name
;
3211 static char *program_version
= VERSION
;
3212 static int flags
= DMGL_PARAMS
| DMGL_ANSI
;
3214 static void demangle_it
PARAMS ((char *));
3215 static void usage
PARAMS ((FILE *, int));
3216 static void fatal
PARAMS ((char *));
3219 demangle_it (mangled_name
)
3224 result
= cplus_demangle (mangled_name
, flags
);
3227 printf ("%s\n", mangled_name
);
3231 printf ("%s\n", result
);
3237 usage (stream
, status
)
3242 Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
3243 [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\
3244 [--help] [--version] [arg...]\n",
3249 #define MBUF_SIZE 512
3250 char mbuffer
[MBUF_SIZE
];
3252 /* Defined in the automatically-generated underscore.c. */
3253 extern int prepends_underscore
;
3255 int strip_underscore
= 0;
3257 static struct option long_options
[] = {
3258 {"strip-underscores", no_argument
, 0, '_'},
3259 {"format", required_argument
, 0, 's'},
3260 {"help", no_argument
, 0, 'h'},
3261 {"java", no_argument
, 0, 'j'},
3262 {"no-strip-underscores", no_argument
, 0, 'n'},
3263 {"version", no_argument
, 0, 'v'},
3264 {0, no_argument
, 0, 0}
3267 /* More 'friendly' abort that prints the line and file.
3268 config.h can #define abort fancy_abort if you like that sort of thing. */
3273 fatal ("Internal gcc abort.");
3284 program_name
= argv
[0];
3286 strip_underscore
= prepends_underscore
;
3288 while ((c
= getopt_long (argc
, argv
, "_ns:j", long_options
, (int *) 0)) != EOF
)
3298 strip_underscore
= 0;
3301 printf ("GNU %s version %s\n", program_name
, program_version
);
3304 strip_underscore
= 1;
3310 if (strcmp (optarg
, "gnu") == 0)
3312 current_demangling_style
= gnu_demangling
;
3314 else if (strcmp (optarg
, "lucid") == 0)
3316 current_demangling_style
= lucid_demangling
;
3318 else if (strcmp (optarg
, "arm") == 0)
3320 current_demangling_style
= arm_demangling
;
3324 fprintf (stderr
, "%s: unknown demangling style `%s'\n",
3325 program_name
, optarg
);
3334 for ( ; optind
< argc
; optind
++)
3336 demangle_it (argv
[optind
]);
3345 /* Try to read a label. */
3346 while (c
!= EOF
&& (isalnum(c
) || c
== '_' || c
== '$' || c
== '.'))
3348 if (i
>= MBUF_SIZE
-1)
3357 if (mbuffer
[0] == '.')
3359 if (strip_underscore
&& mbuffer
[skip_first
] == '_')
3367 result
= cplus_demangle (mbuffer
+ skip_first
, flags
);
3370 if (mbuffer
[0] == '.')
3372 fputs (result
, stdout
);
3376 fputs (mbuffer
, stdout
);
3393 fprintf (stderr
, "%s: %s\n", program_name
, str
);
3404 register char *value
= (char *) malloc (size
);
3406 fatal ("virtual memory exhausted");
3411 xrealloc (ptr
, size
)
3415 register char *value
= (char *) realloc (ptr
, size
);
3417 fatal ("virtual memory exhausted");