1 /* Demangler for GNU C++
2 Copyright 1989, 1991, 1994, 1995 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., 675 Mass Ave,
20 Cambridge, MA 02139, 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
33 #undef CURRENT_DEMANGLING_STYLE
34 #define CURRENT_DEMANGLING_STYLE work->options
36 extern char *xmalloc
PARAMS((unsigned));
37 extern char *xrealloc
PARAMS((char *, unsigned));
38 extern char *strstr ();
40 /* In order to allow a single demangler executable to demangle strings
41 using various common values of CPLUS_MARKER, as well as any specific
42 one set at compile time, we maintain a string containing all the
43 commonly used ones, and check to see if the marker we are looking for
44 is in that string. CPLUS_MARKER is usually '$' on systems where the
45 assembler can deal with that. Where the assembler can't, it's usually
46 '.' (but on many systems '.' is used for other things). We put the
47 current defined CPLUS_MARKER first (which defaults to '$'), followed
48 by the next most common value, followed by an explicit '$' in case
49 the value of CPLUS_MARKER is not '$'.
51 We could avoid this if we could just get g++ to tell us what the actual
52 cplus marker character is as part of the debug information, perhaps by
53 ensuring that it is the character that terminates the gcc<n>_compiled
54 marker symbol (FIXME). */
56 #if !defined (CPLUS_MARKER)
57 #define CPLUS_MARKER '$'
60 enum demangling_styles current_demangling_style
= gnu_demangling
;
62 static char cplus_markers
[] = { CPLUS_MARKER
, '.', '$', '\0' };
65 set_cplus_marker_for_demangling (ch
)
68 cplus_markers
[0] = ch
;
71 /* Stuff that is shared between sub-routines.
72 * Using a shared structure allows cplus_demangle to be reentrant. */
82 int static_type
; /* A static member function */
83 int const_type
; /* A const member function */
86 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
87 #define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS)
89 static const struct optable
95 {"nw", " new", DMGL_ANSI
}, /* new (1.92, ansi) */
96 {"dl", " delete", DMGL_ANSI
}, /* new (1.92, ansi) */
97 {"new", " new", 0}, /* old (1.91, and 1.x) */
98 {"delete", " delete", 0}, /* old (1.91, and 1.x) */
99 {"vn", " new []", DMGL_ANSI
}, /* GNU, pending ansi */
100 {"vd", " delete []", DMGL_ANSI
}, /* GNU, pending ansi */
101 {"as", "=", DMGL_ANSI
}, /* ansi */
102 {"ne", "!=", DMGL_ANSI
}, /* old, ansi */
103 {"eq", "==", DMGL_ANSI
}, /* old, ansi */
104 {"ge", ">=", DMGL_ANSI
}, /* old, ansi */
105 {"gt", ">", DMGL_ANSI
}, /* old, ansi */
106 {"le", "<=", DMGL_ANSI
}, /* old, ansi */
107 {"lt", "<", DMGL_ANSI
}, /* old, ansi */
108 {"plus", "+", 0}, /* old */
109 {"pl", "+", DMGL_ANSI
}, /* ansi */
110 {"apl", "+=", DMGL_ANSI
}, /* ansi */
111 {"minus", "-", 0}, /* old */
112 {"mi", "-", DMGL_ANSI
}, /* ansi */
113 {"ami", "-=", DMGL_ANSI
}, /* ansi */
114 {"mult", "*", 0}, /* old */
115 {"ml", "*", DMGL_ANSI
}, /* ansi */
116 {"amu", "*=", DMGL_ANSI
}, /* ansi (ARM/Lucid) */
117 {"aml", "*=", DMGL_ANSI
}, /* ansi (GNU/g++) */
118 {"convert", "+", 0}, /* old (unary +) */
119 {"negate", "-", 0}, /* old (unary -) */
120 {"trunc_mod", "%", 0}, /* old */
121 {"md", "%", DMGL_ANSI
}, /* ansi */
122 {"amd", "%=", DMGL_ANSI
}, /* ansi */
123 {"trunc_div", "/", 0}, /* old */
124 {"dv", "/", DMGL_ANSI
}, /* ansi */
125 {"adv", "/=", DMGL_ANSI
}, /* ansi */
126 {"truth_andif", "&&", 0}, /* old */
127 {"aa", "&&", DMGL_ANSI
}, /* ansi */
128 {"truth_orif", "||", 0}, /* old */
129 {"oo", "||", DMGL_ANSI
}, /* ansi */
130 {"truth_not", "!", 0}, /* old */
131 {"nt", "!", DMGL_ANSI
}, /* ansi */
132 {"postincrement","++", 0}, /* old */
133 {"pp", "++", DMGL_ANSI
}, /* ansi */
134 {"postdecrement","--", 0}, /* old */
135 {"mm", "--", DMGL_ANSI
}, /* ansi */
136 {"bit_ior", "|", 0}, /* old */
137 {"or", "|", DMGL_ANSI
}, /* ansi */
138 {"aor", "|=", DMGL_ANSI
}, /* ansi */
139 {"bit_xor", "^", 0}, /* old */
140 {"er", "^", DMGL_ANSI
}, /* ansi */
141 {"aer", "^=", DMGL_ANSI
}, /* ansi */
142 {"bit_and", "&", 0}, /* old */
143 {"ad", "&", DMGL_ANSI
}, /* ansi */
144 {"aad", "&=", DMGL_ANSI
}, /* ansi */
145 {"bit_not", "~", 0}, /* old */
146 {"co", "~", DMGL_ANSI
}, /* ansi */
147 {"call", "()", 0}, /* old */
148 {"cl", "()", DMGL_ANSI
}, /* ansi */
149 {"alshift", "<<", 0}, /* old */
150 {"ls", "<<", DMGL_ANSI
}, /* ansi */
151 {"als", "<<=", DMGL_ANSI
}, /* ansi */
152 {"arshift", ">>", 0}, /* old */
153 {"rs", ">>", DMGL_ANSI
}, /* ansi */
154 {"ars", ">>=", DMGL_ANSI
}, /* ansi */
155 {"component", "->", 0}, /* old */
156 {"pt", "->", DMGL_ANSI
}, /* ansi; Lucid C++ form */
157 {"rf", "->", DMGL_ANSI
}, /* ansi; ARM/GNU form */
158 {"indirect", "*", 0}, /* old */
159 {"method_call", "->()", 0}, /* old */
160 {"addr", "&", 0}, /* old (unary &) */
161 {"array", "[]", 0}, /* old */
162 {"vc", "[]", DMGL_ANSI
}, /* ansi */
163 {"compound", ", ", 0}, /* old */
164 {"cm", ", ", DMGL_ANSI
}, /* ansi */
165 {"cond", "?:", 0}, /* old */
166 {"cn", "?:", DMGL_ANSI
}, /* psuedo-ansi */
167 {"max", ">?", 0}, /* old */
168 {"mx", ">?", DMGL_ANSI
}, /* psuedo-ansi */
169 {"min", "<?", 0}, /* old */
170 {"mn", "<?", DMGL_ANSI
}, /* psuedo-ansi */
171 {"nop", "", 0}, /* old (for operator=) */
172 {"rm", "->*", DMGL_ANSI
} /* ansi */
176 typedef struct string
/* Beware: these aren't required to be */
177 { /* '\0' terminated. */
178 char *b
; /* pointer to start of string */
179 char *p
; /* pointer after last character */
180 char *e
; /* pointer after end of allocated space */
183 #define STRING_EMPTY(str) ((str) -> b == (str) -> p)
184 #define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
185 string_prepend(str, " ");}
186 #define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
187 string_append(str, " ");}
189 #define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */
190 #define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */
192 /* Prototypes for local functions */
195 mop_up
PARAMS ((struct work_stuff
*, string
*, int));
199 demangle_method_args
PARAMS ((struct work_stuff
*work
, const char **, string
*));
203 demangle_template
PARAMS ((struct work_stuff
*work
, const char **, string
*,
207 demangle_qualified
PARAMS ((struct work_stuff
*, const char **, string
*,
211 demangle_class
PARAMS ((struct work_stuff
*, const char **, string
*));
214 demangle_fund_type
PARAMS ((struct work_stuff
*, const char **, string
*));
217 demangle_signature
PARAMS ((struct work_stuff
*, const char **, string
*));
220 demangle_prefix
PARAMS ((struct work_stuff
*, const char **, string
*));
223 gnu_special
PARAMS ((struct work_stuff
*, const char **, string
*));
226 arm_special
PARAMS ((struct work_stuff
*, const char **, string
*));
229 string_need
PARAMS ((string
*, int));
232 string_delete
PARAMS ((string
*));
235 string_init
PARAMS ((string
*));
238 string_clear
PARAMS ((string
*));
242 string_empty
PARAMS ((string
*));
246 string_append
PARAMS ((string
*, const char *));
249 string_appends
PARAMS ((string
*, string
*));
252 string_appendn
PARAMS ((string
*, const char *, int));
255 string_prepend
PARAMS ((string
*, const char *));
258 string_prependn
PARAMS ((string
*, const char *, int));
261 get_count
PARAMS ((const char **, int *));
264 consume_count
PARAMS ((const char **));
267 demangle_args
PARAMS ((struct work_stuff
*, const char **, string
*));
270 do_type
PARAMS ((struct work_stuff
*, const char **, string
*));
273 do_arg
PARAMS ((struct work_stuff
*, const char **, string
*));
276 demangle_function_name
PARAMS ((struct work_stuff
*, const char **, string
*,
280 remember_type
PARAMS ((struct work_stuff
*, const char *, int));
283 forget_types
PARAMS ((struct work_stuff
*));
286 string_prepends
PARAMS ((string
*, string
*));
288 /* Translate count to integer, consuming tokens in the process.
289 Conversion terminates on the first non-digit character.
290 Trying to consume something that isn't a count results in
291 no consumption of input and a return of 0. */
299 while (isdigit (**type
))
302 count
+= **type
- '0';
309 cplus_demangle_opname (opname
, result
, options
)
314 int len
, i
, len1
, ret
;
316 struct work_stuff work
[1];
319 len
= strlen(opname
);
322 work
->options
= options
;
324 if (opname
[0] == '_' && opname
[1] == '_'
325 && opname
[2] == 'o' && opname
[3] == 'p')
328 /* type conversion operator. */
330 if (do_type (work
, &tem
, &type
))
332 strcat (result
, "operator ");
333 strncat (result
, type
.b
, type
.p
- type
.b
);
334 string_delete (&type
);
338 else if (opname
[0] == '_' && opname
[1] == '_'
339 && opname
[2] >= 'a' && opname
[2] <= 'z'
340 && opname
[3] >= 'a' && opname
[3] <= 'z')
342 if (opname
[4] == '\0')
345 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
347 if (strlen (optable
[i
].in
) == 2
348 && memcmp (optable
[i
].in
, opname
+ 2, 2) == 0)
350 strcat (result
, "operator");
351 strcat (result
, optable
[i
].out
);
359 if (opname
[2] == 'a' && opname
[5] == '\0')
362 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
364 if (strlen (optable
[i
].in
) == 3
365 && memcmp (optable
[i
].in
, opname
+ 2, 3) == 0)
367 strcat (result
, "operator");
368 strcat (result
, optable
[i
].out
);
379 && strchr (cplus_markers
, opname
[2]) != NULL
)
381 /* see if it's an assignment expression */
382 if (len
>= 10 /* op$assign_ */
383 && memcmp (opname
+ 3, "assign_", 7) == 0)
385 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
388 if (strlen (optable
[i
].in
) == len1
389 && memcmp (optable
[i
].in
, opname
+ 10, len1
) == 0)
391 strcat (result
, "operator");
392 strcat (result
, optable
[i
].out
);
393 strcat (result
, "=");
401 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
404 if (strlen (optable
[i
].in
) == len1
405 && memcmp (optable
[i
].in
, opname
+ 3, len1
) == 0)
407 strcat (result
, "operator");
408 strcat (result
, optable
[i
].out
);
415 else if (len
>= 5 && memcmp (opname
, "type", 4) == 0
416 && strchr (cplus_markers
, opname
[4]) != NULL
)
418 /* type conversion operator */
420 if (do_type (work
, &tem
, &type
))
422 strcat (result
, "operator ");
423 strncat (result
, type
.b
, type
.p
- type
.b
);
424 string_delete (&type
);
431 /* Takes operator name as e.g. "++" and returns mangled
432 operator name (e.g. "postincrement_expr"), or NULL if not found.
434 If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
435 if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */
438 cplus_mangle_opname (opname
, options
)
445 len
= strlen (opname
);
446 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
448 if (strlen (optable
[i
].out
) == len
449 && (options
& DMGL_ANSI
) == (optable
[i
].flags
& DMGL_ANSI
)
450 && memcmp (optable
[i
].out
, opname
, len
) == 0)
451 return ((char *)optable
[i
].in
);
456 /* check to see whether MANGLED can match TEXT in the first TEXT_LEN
459 int cplus_match (mangled
, text
, text_len
)
464 if (strncmp (mangled
, text
, text_len
) != 0) {
465 return(0); /* cannot match either */
467 return(1); /* matches mangled, may match demangled */
471 /* char *cplus_demangle (const char *mangled, int options)
473 If MANGLED is a mangled function name produced by GNU C++, then
474 a pointer to a malloced string giving a C++ representation
475 of the name will be returned; otherwise NULL will be returned.
476 It is the caller's responsibility to free the string which
479 The OPTIONS arg may contain one or more of the following bits:
481 DMGL_ANSI ANSI qualifiers such as `const' and `void' are
483 DMGL_PARAMS Function parameters are included.
487 cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)"
488 cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
489 cplus_demangle ("foo__1Ai", 0) => "A::foo"
491 cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)"
492 cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
493 cplus_demangle ("foo__1Afe", 0) => "A::foo"
495 Note that any leading underscores, or other such characters prepended by
496 the compilation system, are presumed to have already been stripped from
500 cplus_demangle (mangled
, options
)
506 struct work_stuff work
[1];
507 char *demangled
= NULL
;
509 if ((mangled
!= NULL
) && (*mangled
!= '\0'))
511 memset ((char *) work
, 0, sizeof (work
));
512 work
-> options
= options
;
513 if ((work
->options
& DMGL_STYLE_MASK
) == 0)
514 work
->options
|= (int)current_demangling_style
& DMGL_STYLE_MASK
;
518 /* First check to see if gnu style demangling is active and if the
519 string to be demangled contains a CPLUS_MARKER. If so, attempt to
520 recognize one of the gnu special forms rather than looking for a
521 standard prefix. In particular, don't worry about whether there
522 is a "__" string in the mangled string. Consider "_$_5__foo" for
525 if ((AUTO_DEMANGLING
|| GNU_DEMANGLING
))
527 success
= gnu_special (work
, &mangled
, &decl
);
531 success
= demangle_prefix (work
, &mangled
, &decl
);
533 if (success
&& (*mangled
!= '\0'))
535 success
= demangle_signature (work
, &mangled
, &decl
);
537 if (work
->constructor
== 2)
539 string_prepend(&decl
, "global constructors keyed to ");
540 work
->constructor
= 0;
542 else if (work
->destructor
== 2)
544 string_prepend(&decl
, "global destructors keyed to ");
545 work
->destructor
= 0;
547 demangled
= mop_up (work
, &decl
, success
);
553 mop_up (work
, declp
, success
)
554 struct work_stuff
*work
;
558 char *demangled
= NULL
;
560 /* Discard the remembered types, if any. */
563 if (work
-> typevec
!= NULL
)
565 free ((char *) work
-> typevec
);
568 /* If demangling was successful, ensure that the demangled string is null
569 terminated and return it. Otherwise, free the demangling decl. */
573 string_delete (declp
);
577 string_appendn (declp
, "", 1);
578 demangled
= declp
-> b
;
587 demangle_signature -- demangle the signature part of a mangled name
592 demangle_signature (struct work_stuff *work, const char **mangled,
597 Consume and demangle the signature portion of the mangled name.
599 DECLP is the string where demangled output is being built. At
600 entry it contains the demangled root name from the mangled name
601 prefix. I.E. either a demangled operator name or the root function
602 name. In some special cases, it may contain nothing.
604 *MANGLED points to the current unconsumed location in the mangled
605 name. As tokens are consumed and demangling is performed, the
606 pointer is updated to continuously point at the next token to
609 Demangling GNU style mangled names is nasty because there is no
610 explicit token that marks the start of the outermost function
615 demangle_signature (work
, mangled
, declp
)
616 struct work_stuff
*work
;
617 const char **mangled
;
623 const char *oldmangled
= NULL
;
627 while (success
&& (**mangled
!= '\0'))
632 oldmangled
= *mangled
;
633 success
= demangle_qualified (work
, mangled
, declp
, 1, 0);
636 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
638 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
646 /* Static member function */
647 if (oldmangled
== NULL
)
649 oldmangled
= *mangled
;
652 work
-> static_type
= 1;
656 /* a const member function */
657 if (oldmangled
== NULL
)
659 oldmangled
= *mangled
;
662 work
-> const_type
= 1;
665 case '0': case '1': case '2': case '3': case '4':
666 case '5': case '6': case '7': case '8': case '9':
667 if (oldmangled
== NULL
)
669 oldmangled
= *mangled
;
671 success
= demangle_class (work
, mangled
, declp
);
674 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
676 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
685 /* ARM style demangling includes a specific 'F' character after
686 the class name. For GNU style, it is just implied. So we can
687 safely just consume any 'F' at this point and be compatible
688 with either style. */
694 /* For lucid/ARM style we have to forget any types we might
695 have remembered up to this point, since they were not argument
696 types. GNU style considers all types seen as available for
697 back references. See comment in demangle_args() */
699 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
703 success
= demangle_args (work
, mangled
, declp
);
708 string_init(&trawname
);
710 if (oldmangled
== NULL
)
712 oldmangled
= *mangled
;
714 success
= demangle_template (work
, mangled
, &tname
, &trawname
);
717 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
719 string_append(&tname
, "::");
720 string_prepends(declp
, &tname
);
721 if (work
-> destructor
& 1)
723 string_prepend (&trawname
, "~");
724 string_appends (declp
, &trawname
);
725 work
->destructor
-= 1;
727 if ((work
->constructor
& 1) || (work
->destructor
& 1))
729 string_appends (declp
, &trawname
);
730 work
->constructor
-= 1;
732 string_delete(&trawname
);
733 string_delete(&tname
);
739 /* At the outermost level, we cannot have a return type specified,
740 so if we run into another '_' at this point we are dealing with
741 a mangled name that is either bogus, or has been mangled by
742 some algorithm we don't know how to deal with. So just
743 reject the entire demangling. */
748 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
750 /* Assume we have stumbled onto the first outermost function
751 argument token, and start processing args. */
753 success
= demangle_args (work
, mangled
, declp
);
757 /* Non-GNU demanglers use a specific token to mark the start
758 of the outermost function argument tokens. Typically 'F',
759 for ARM-demangling, for example. So if we find something
760 we are not prepared for, it must be an error. */
766 if (AUTO_DEMANGLING || GNU_DEMANGLING)
769 if (success
&& expect_func
)
772 success
= demangle_args (work
, mangled
, declp
);
776 if (success
&& !func_done
)
778 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
780 /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
781 bar__3fooi is 'foo::bar(int)'. We get here when we find the
782 first case, and need to ensure that the '(void)' gets added to
783 the current declp. Note that with ARM, the first case
784 represents the name of a static data member 'foo::bar',
785 which is in the current declp, so we leave it alone. */
786 success
= demangle_args (work
, mangled
, declp
);
789 if (success
&& work
-> static_type
&& PRINT_ARG_TYPES
)
791 string_append (declp
, " static");
793 if (success
&& work
-> const_type
&& PRINT_ARG_TYPES
)
795 string_append (declp
, " const");
803 demangle_method_args (work
, mangled
, declp
)
804 struct work_stuff
*work
;
805 const char **mangled
;
810 if (work
-> static_type
)
812 string_append (declp
, *mangled
+ 1);
813 *mangled
+= strlen (*mangled
);
818 success
= demangle_args (work
, mangled
, declp
);
826 demangle_template (work
, mangled
, tname
, trawname
)
827 struct work_stuff
*work
;
828 const char **mangled
;
849 /* get template name */
850 if ((r
= consume_count (mangled
)) == 0 || strlen (*mangled
) < r
)
855 string_appendn (trawname
, *mangled
, r
);
856 string_appendn (tname
, *mangled
, r
);
858 string_append (tname
, "<");
859 /* get size of template parameter list */
860 if (!get_count (mangled
, &r
))
864 for (i
= 0; i
< r
; i
++)
868 string_append (tname
, ", ");
870 /* Z for type parameters */
871 if (**mangled
== 'Z')
874 /* temp is initialized in do_type */
875 success
= do_type (work
, mangled
, &temp
);
878 string_appends (tname
, &temp
);
880 string_delete(&temp
);
888 /* otherwise, value parameter */
895 /* temp is initialized in do_type */
896 success
= do_type (work
, mangled
, &temp
);
900 string_appends (tname, &temp);
903 string_delete(&temp
);
909 string_append (tname, "=");
911 while (*old_p
&& !done
)
918 done
= is_pointer
= 1;
920 case 'C': /* const */
921 case 'S': /* explicitly signed [char] */
922 case 'U': /* unsigned */
923 case 'V': /* volatile */
924 case 'F': /* function */
925 case 'M': /* member function */
929 case 'Q': /* qualified name */
930 done
= is_integral
= 1;
932 case 'T': /* remembered type */
938 case 'x': /* long long */
941 case 's': /* short */
942 case 'w': /* wchar_t */
943 done
= is_integral
= 1;
951 case 'r': /* long double */
952 case 'd': /* double */
953 case 'f': /* float */
957 /* it's probably user defined type, let's assume
958 it's integeral, it seems hard to figure out
960 done
= is_integral
= 1;
965 if (**mangled
== 'm')
967 string_appendn (tname
, "-", 1);
970 while (isdigit (**mangled
))
972 string_appendn (tname
, *mangled
, 1);
980 if (**mangled
== 'm')
982 string_appendn (tname
, "-", 1);
985 string_appendn (tname
, "'", 1);
986 val
= consume_count(mangled
);
994 string_appendn (tname
, &tmp
[0], 1);
995 string_appendn (tname
, "'", 1);
999 int val
= consume_count (mangled
);
1001 string_appendn (tname
, "false", 5);
1003 string_appendn (tname
, "true", 4);
1009 if (**mangled
== 'm')
1011 string_appendn (tname
, "-", 1);
1014 while (isdigit (**mangled
))
1016 string_appendn (tname
, *mangled
, 1);
1019 if (**mangled
== '.') /* fraction */
1021 string_appendn (tname
, ".", 1);
1023 while (isdigit (**mangled
))
1025 string_appendn (tname
, *mangled
, 1);
1029 if (**mangled
== 'e') /* exponent */
1031 string_appendn (tname
, "e", 1);
1033 while (isdigit (**mangled
))
1035 string_appendn (tname
, *mangled
, 1);
1040 else if (is_pointer
)
1042 if (!get_count (mangled
, &symbol_len
))
1047 string_appendn (tname
, *mangled
, symbol_len
);
1048 *mangled
+= symbol_len
;
1053 if (tname
->p
[-1] == '>')
1054 string_append (tname
, " ");
1055 string_append (tname
, ">");
1058 if (work -> static_type)
1060 string_append (declp, *mangled + 1);
1061 *mangled += strlen (*mangled);
1066 success = demangle_args (work, mangled, declp);
1074 arm_pt (work
, mangled
, n
, anchor
, args
)
1075 struct work_stuff
*work
;
1076 const char *mangled
;
1078 const char **anchor
, **args
;
1081 if (ARM_DEMANGLING
&& (*anchor
= strstr(mangled
, "__pt__")))
1084 *args
= *anchor
+ 6;
1085 len
= consume_count (args
);
1086 if (*args
+ len
== mangled
+ n
&& **args
== '_')
1096 demangle_arm_pt (work
, mangled
, n
, declp
)
1097 struct work_stuff
*work
;
1098 const char **mangled
;
1104 const char *e
= *mangled
+ n
;
1107 if (arm_pt (work
, *mangled
, n
, &p
, &args
))
1111 string_appendn (declp
, *mangled
, p
- *mangled
);
1112 string_append (declp
, "<");
1113 /* should do error checking here */
1115 string_clear (&arg
);
1116 do_type (work
, &args
, &arg
);
1117 string_appends (declp
, &arg
);
1118 string_append (declp
, ",");
1120 string_delete (&arg
);
1122 string_append (declp
, ">");
1126 string_appendn (declp
, *mangled
, n
);
1132 demangle_class_name (work
, mangled
, declp
)
1133 struct work_stuff
*work
;
1134 const char **mangled
;
1140 n
= consume_count (mangled
);
1141 if (strlen (*mangled
) >= n
)
1143 demangle_arm_pt (work
, mangled
, n
, declp
);
1154 demangle_class -- demangle a mangled class sequence
1159 demangle_class (struct work_stuff *work, const char **mangled,
1164 DECLP points to the buffer into which demangling is being done.
1166 *MANGLED points to the current token to be demangled. On input,
1167 it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
1168 On exit, it points to the next token after the mangled class on
1169 success, or the first unconsumed token on failure.
1171 If the constRUCTOR or DESTRUCTOR flags are set in WORK, then
1172 we are demangling a constructor or destructor. In this case
1173 we prepend "class::class" or "class::~class" to DECLP.
1175 Otherwise, we prepend "class::" to the current DECLP.
1177 Reset the constructor/destructor flags once they have been
1178 "consumed". This allows demangle_class to be called later during
1179 the same demangling, to do normal class demangling.
1181 Returns 1 if demangling is successful, 0 otherwise.
1186 demangle_class (work
, mangled
, declp
)
1187 struct work_stuff
*work
;
1188 const char **mangled
;
1194 string_init (&class_name
);
1195 if (demangle_class_name (work
, mangled
, &class_name
))
1197 if ((work
->constructor
& 1) || (work
->destructor
& 1))
1199 string_prepends (declp
, &class_name
);
1200 if (work
-> destructor
& 1)
1202 string_prepend (declp
, "~");
1203 work
-> destructor
-= 1;
1207 work
-> constructor
-= 1;
1210 string_prepend (declp
, "::");
1211 string_prepends (declp
, &class_name
);
1214 string_delete (&class_name
);
1222 demangle_prefix -- consume the mangled name prefix and find signature
1227 demangle_prefix (struct work_stuff *work, const char **mangled,
1232 Consume and demangle the prefix of the mangled name.
1234 DECLP points to the string buffer into which demangled output is
1235 placed. On entry, the buffer is empty. On exit it contains
1236 the root function name, the demangled operator name, or in some
1237 special cases either nothing or the completely demangled result.
1239 MANGLED points to the current pointer into the mangled name. As each
1240 token of the mangled name is consumed, it is updated. Upon entry
1241 the current mangled name pointer points to the first character of
1242 the mangled name. Upon exit, it should point to the first character
1243 of the signature if demangling was successful, or to the first
1244 unconsumed character if demangling of the prefix was unsuccessful.
1246 Returns 1 on success, 0 otherwise.
1250 demangle_prefix (work
, mangled
, declp
)
1251 struct work_stuff
*work
;
1252 const char **mangled
;
1259 if (strlen(*mangled
) >= 11 && strncmp(*mangled
, "_GLOBAL_", 8) == 0)
1261 char *marker
= strchr (cplus_markers
, (*mangled
)[8]);
1262 if (marker
!= NULL
&& *marker
== (*mangled
)[10])
1264 if ((*mangled
)[9] == 'D')
1266 /* it's a GNU global destructor to be executed at program exit */
1268 work
->destructor
= 2;
1269 if (gnu_special (work
, mangled
, declp
))
1272 else if ((*mangled
)[9] == 'I')
1274 /* it's a GNU global constructor to be executed at program init */
1276 work
->constructor
= 2;
1277 if (gnu_special (work
, mangled
, declp
))
1282 else if (ARM_DEMANGLING
&& strncmp(*mangled
, "__std__", 7) == 0)
1284 /* it's a ARM global destructor to be executed at program exit */
1286 work
->destructor
= 2;
1288 else if (ARM_DEMANGLING
&& strncmp(*mangled
, "__sti__", 7) == 0)
1290 /* it's a ARM global constructor to be executed at program initial */
1292 work
->constructor
= 2;
1295 /* This block of code is a reduction in strength time optimization
1297 scan = strstr (*mangled, "__"); */
1303 scan
= strchr (scan
, '_');
1304 } while (scan
!= NULL
&& *++scan
!= '_');
1306 if (scan
!= NULL
) --scan
;
1311 /* We found a sequence of two or more '_', ensure that we start at
1312 the last pair in the sequence. */
1313 i
= strspn (scan
, "_");
1324 else if (work
-> static_type
)
1326 if (!isdigit (scan
[0]) && (scan
[0] != 't'))
1331 else if ((scan
== *mangled
) &&
1332 (isdigit (scan
[2]) || (scan
[2] == 'Q') || (scan
[2] == 't')))
1334 /* The ARM says nothing about the mangling of local variables.
1335 But cfront mangles local variables by prepending __<nesting_level>
1336 to them. As an extension to ARM demangling we handle this case. */
1337 if ((LUCID_DEMANGLING
|| ARM_DEMANGLING
) && isdigit (scan
[2]))
1339 *mangled
= scan
+ 2;
1340 consume_count (mangled
);
1341 string_append (declp
, *mangled
);
1342 *mangled
+= strlen (*mangled
);
1347 /* A GNU style constructor starts with __[0-9Qt]. But cfront uses
1348 names like __Q2_3foo3bar for nested type names. So don't accept
1349 this style of constructor for cfront demangling. */
1350 if (!(LUCID_DEMANGLING
|| ARM_DEMANGLING
))
1351 work
-> constructor
+= 1;
1352 *mangled
= scan
+ 2;
1355 else if ((scan
== *mangled
) && !isdigit (scan
[2]) && (scan
[2] != 't'))
1357 /* Mangled name starts with "__". Skip over any leading '_' characters,
1358 then find the next "__" that separates the prefix from the signature.
1360 if (!(ARM_DEMANGLING
|| LUCID_DEMANGLING
)
1361 || (arm_special (work
, mangled
, declp
) == 0))
1363 while (*scan
== '_')
1367 if ((scan
= strstr (scan
, "__")) == NULL
|| (*(scan
+ 2) == '\0'))
1369 /* No separator (I.E. "__not_mangled"), or empty signature
1370 (I.E. "__not_mangled_either__") */
1375 demangle_function_name (work
, mangled
, declp
, scan
);
1379 else if (ARM_DEMANGLING
&& scan
[2] == 'p' && scan
[3] == 't')
1381 /* Cfront-style parameterized type. Handled later as a signature. */
1385 demangle_arm_pt (work
, mangled
, strlen (*mangled
), declp
);
1387 else if (*(scan
+ 2) != '\0')
1389 /* Mangled name does not start with "__" but does have one somewhere
1390 in there with non empty stuff after it. Looks like a global
1392 demangle_function_name (work
, mangled
, declp
, scan
);
1396 /* Doesn't look like a mangled name */
1400 if (!success
&& (work
->constructor
== 2 || work
->destructor
== 2))
1402 string_append (declp
, *mangled
);
1403 *mangled
+= strlen (*mangled
);
1413 gnu_special -- special handling of gnu mangled strings
1418 gnu_special (struct work_stuff *work, const char **mangled,
1424 Process some special GNU style mangling forms that don't fit
1425 the normal pattern. For example:
1427 _$_3foo (destructor for class foo)
1428 _vt$foo (foo virtual table)
1429 _vt$foo$bar (foo::bar virtual table)
1430 __vt_foo (foo virtual table, new style with thunks)
1431 _3foo$varname (static data member)
1432 _Q22rs2tu$vw (static data member)
1433 __t6vector1Zii (constructor with template)
1434 __thunk_4__$_7ostream (virtual function thunk)
1438 gnu_special (work
, mangled
, declp
)
1439 struct work_stuff
*work
;
1440 const char **mangled
;
1447 if ((*mangled
)[0] == '_'
1448 && strchr (cplus_markers
, (*mangled
)[1]) != NULL
1449 && (*mangled
)[2] == '_')
1451 /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
1453 work
-> destructor
+= 1;
1455 else if ((*mangled
)[0] == '_'
1456 && (((*mangled
)[1] == '_'
1457 && (*mangled
)[2] == 'v'
1458 && (*mangled
)[3] == 't'
1459 && (*mangled
)[4] == '_')
1460 || ((*mangled
)[1] == 'v'
1461 && (*mangled
)[2] == 't'
1462 && strchr (cplus_markers
, (*mangled
)[3]) != NULL
)))
1464 /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
1465 and create the decl. Note that we consume the entire mangled
1466 input string, which means that demangle_signature has no work
1468 if ((*mangled
)[2] == 'v')
1469 (*mangled
) += 5; /* New style, with thunks: "__vt_" */
1471 (*mangled
) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
1472 while (**mangled
!= '\0')
1474 p
= strpbrk (*mangled
, cplus_markers
);
1478 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
1481 success
= demangle_template (work
, mangled
, declp
, 0);
1484 if (isdigit(*mangled
[0]))
1486 n
= consume_count(mangled
);
1490 n
= strcspn (*mangled
, cplus_markers
);
1492 string_appendn (declp
, *mangled
, n
);
1496 if (success
&& ((p
== NULL
) || (p
== *mangled
)))
1500 string_append (declp
, "::");
1511 string_append (declp
, " virtual table");
1513 else if ((*mangled
)[0] == '_'
1514 && (strchr("0123456789Qt", (*mangled
)[1]) != NULL
)
1515 && (p
= strpbrk (*mangled
, cplus_markers
)) != NULL
)
1517 /* static data member, "_3foo$varname" for example */
1522 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
1525 success
= demangle_template (work
, mangled
, declp
, 0);
1528 n
= consume_count (mangled
);
1529 string_appendn (declp
, *mangled
, n
);
1532 if (success
&& (p
== *mangled
))
1534 /* Consumed everything up to the cplus_marker, append the
1537 string_append (declp
, "::");
1538 n
= strlen (*mangled
);
1539 string_appendn (declp
, *mangled
, n
);
1547 else if (strncmp (*mangled
, "__thunk_", 8) == 0)
1549 int delta
= ((*mangled
) += 8, consume_count (mangled
));
1550 char *method
= cplus_demangle (++*mangled
, work
->options
);
1554 sprintf (buf
, "virtual function thunk (delta:%d) for ", -delta
);
1555 string_append (declp
, buf
);
1556 string_append (declp
, method
);
1558 n
= strlen (*mangled
);
1577 arm_special -- special handling of ARM/lucid mangled strings
1582 arm_special (struct work_stuff *work, const char **mangled,
1588 Process some special ARM style mangling forms that don't fit
1589 the normal pattern. For example:
1591 __vtbl__3foo (foo virtual table)
1592 __vtbl__3foo__3bar (bar::foo virtual table)
1597 arm_special (work
, mangled
, declp
)
1598 struct work_stuff
*work
;
1599 const char **mangled
;
1606 if (strncmp (*mangled
, ARM_VTABLE_STRING
, ARM_VTABLE_STRLEN
) == 0)
1608 /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
1609 and create the decl. Note that we consume the entire mangled
1610 input string, which means that demangle_signature has no work
1612 scan
= *mangled
+ ARM_VTABLE_STRLEN
;
1613 while (*scan
!= '\0') /* first check it can be demangled */
1615 n
= consume_count (&scan
);
1618 return (0); /* no good */
1621 if (scan
[0] == '_' && scan
[1] == '_')
1626 (*mangled
) += ARM_VTABLE_STRLEN
;
1627 while (**mangled
!= '\0')
1629 n
= consume_count (mangled
);
1630 string_prependn (declp
, *mangled
, n
);
1632 if ((*mangled
)[0] == '_' && (*mangled
)[1] == '_')
1634 string_prepend (declp
, "::");
1638 string_append (declp
, " virtual table");
1651 demangle_qualified -- demangle 'Q' qualified name strings
1656 demangle_qualified (struct work_stuff *, const char *mangled,
1657 string *result, int isfuncname, int append);
1661 Demangle a qualified name, such as "Q25Outer5Inner" which is
1662 the mangled form of "Outer::Inner". The demangled output is
1663 prepended or appended to the result string according to the
1664 state of the append flag.
1666 If isfuncname is nonzero, then the qualified name we are building
1667 is going to be used as a member function name, so if it is a
1668 constructor or destructor function, append an appropriate
1669 constructor or destructor name. I.E. for the above example,
1670 the result for use as a constructor is "Outer::Inner::Inner"
1671 and the result for use as a destructor is "Outer::Inner::~Inner".
1675 Numeric conversion is ASCII dependent (FIXME).
1680 demangle_qualified (work
, mangled
, result
, isfuncname
, append
)
1681 struct work_stuff
*work
;
1682 const char **mangled
;
1694 string_init (&temp
);
1695 switch ((*mangled
)[1])
1698 /* GNU mangled name with more than 9 classes. The count is preceded
1699 by an underscore (to distinguish it from the <= 9 case) and followed
1700 by an underscore. */
1702 qualifiers
= atoi (p
);
1703 if (!isdigit (*p
) || *p
== '0')
1706 /* Skip the digits. */
1707 while (isdigit (*p
))
1725 /* The count is in a single digit. */
1726 num
[0] = (*mangled
)[1];
1728 qualifiers
= atoi (num
);
1730 /* If there is an underscore after the digit, skip it. This is
1731 said to be for ARM-qualified names, but the ARM makes no
1732 mention of such an underscore. Perhaps cfront uses one. */
1733 if ((*mangled
)[2] == '_')
1748 /* Pick off the names and collect them in the temp buffer in the order
1749 in which they are found, separated by '::'. */
1751 while (qualifiers
-- > 0)
1753 if (*mangled
[0] == '_')
1754 *mangled
= *mangled
+ 1;
1755 if (*mangled
[0] == 't')
1757 success
= demangle_template(work
, mangled
, &temp
, 0);
1758 if (!success
) break;
1762 namelength
= consume_count (mangled
);
1763 if (strlen (*mangled
) < namelength
)
1765 /* Simple sanity check failed */
1769 string_appendn (&temp
, *mangled
, namelength
);
1770 *mangled
+= namelength
;
1774 string_appendn (&temp
, "::", 2);
1778 /* If we are using the result as a function name, we need to append
1779 the appropriate '::' separated constructor or destructor name.
1780 We do this here because this is the most convenient place, where
1781 we already have a pointer to the name and the length of the name. */
1783 if (isfuncname
&& (work
->constructor
& 1 || work
->destructor
& 1))
1785 string_appendn (&temp
, "::", 2);
1786 if (work
-> destructor
& 1)
1788 string_append (&temp
, "~");
1790 string_appendn (&temp
, (*mangled
) - namelength
, namelength
);
1793 /* Now either prepend the temp buffer to the result, or append it,
1794 depending upon the state of the append flag. */
1798 string_appends (result
, &temp
);
1802 if (!STRING_EMPTY (result
))
1804 string_appendn (&temp
, "::", 2);
1806 string_prepends (result
, &temp
);
1809 string_delete (&temp
);
1817 get_count -- convert an ascii count to integer, consuming tokens
1822 get_count (const char **type, int *count)
1826 Return 0 if no conversion is performed, 1 if a string is converted.
1830 get_count (type
, count
)
1837 if (!isdigit (**type
))
1843 *count
= **type
- '0';
1845 if (isdigit (**type
))
1855 while (isdigit (*p
));
1866 /* result will be initialised here; it will be freed on failure */
1869 do_type (work
, mangled
, result
)
1870 struct work_stuff
*work
;
1871 const char **mangled
;
1878 const char *remembered_type
;
1882 string_init (&decl
);
1883 string_init (result
);
1887 while (success
&& !done
)
1893 /* A pointer type */
1897 string_prepend (&decl
, "*");
1900 /* A reference type */
1903 string_prepend (&decl
, "&");
1909 const char *p
= ++(*mangled
);
1911 string_prepend (&decl
, "(");
1912 string_append (&decl
, ")[");
1913 /* Copy anything up until the next underscore (the size of the
1915 while (**mangled
&& **mangled
!= '_')
1917 if (**mangled
== '_')
1919 string_appendn (&decl
, p
, *mangled
- p
);
1920 string_append (&decl
, "]");
1928 /* A back reference to a previously seen type */
1931 if (!get_count (mangled
, &n
) || n
>= work
-> ntypes
)
1937 remembered_type
= work
-> typevec
[n
];
1938 mangled
= &remembered_type
;
1945 if (!STRING_EMPTY (&decl
) && decl
.b
[0] == '*')
1947 string_prepend (&decl
, "(");
1948 string_append (&decl
, ")");
1950 /* After picking off the function args, we expect to either find the
1951 function return type (preceded by an '_') or the end of the
1953 if (!demangle_args (work
, mangled
, &decl
)
1954 || (**mangled
!= '_' && **mangled
!= '\0'))
1958 if (success
&& (**mangled
== '_'))
1970 member
= **mangled
== 'M';
1972 if (!isdigit (**mangled
))
1977 n
= consume_count (mangled
);
1978 if (strlen (*mangled
) < n
)
1983 string_append (&decl
, ")");
1984 string_prepend (&decl
, "::");
1985 string_prependn (&decl
, *mangled
, n
);
1986 string_prepend (&decl
, "(");
1990 if (**mangled
== 'C')
1995 if (**mangled
== 'V')
2000 if (*(*mangled
)++ != 'F')
2006 if ((member
&& !demangle_args (work
, mangled
, &decl
))
2007 || **mangled
!= '_')
2013 if (! PRINT_ANSI_QUALIFIERS
)
2019 APPEND_BLANK (&decl
);
2020 string_append (&decl
, "const");
2024 APPEND_BLANK (&decl
);
2025 string_append (&decl
, "volatile");
2036 if ((*mangled)[1] == 'P')
2039 if (PRINT_ANSI_QUALIFIERS
)
2041 if (!STRING_EMPTY (&decl
))
2043 string_prepend (&decl
, " ");
2045 string_prepend (&decl
, "const");
2061 /* A qualified name, such as "Outer::Inner". */
2063 success
= demangle_qualified (work
, mangled
, result
, 0, 1);
2067 success
= demangle_fund_type (work
, mangled
, result
);
2073 if (!STRING_EMPTY (&decl
))
2075 string_append (result
, " ");
2076 string_appends (result
, &decl
);
2081 string_delete (result
);
2083 string_delete (&decl
);
2087 /* Given a pointer to a type string that represents a fundamental type
2088 argument (int, long, unsigned int, etc) in TYPE, a pointer to the
2089 string in which the demangled output is being built in RESULT, and
2090 the WORK structure, decode the types and add them to the result.
2095 "Sl" => "signed long"
2096 "CUs" => "const unsigned short"
2101 demangle_fund_type (work
, mangled
, result
)
2102 struct work_stuff
*work
;
2103 const char **mangled
;
2109 /* First pick off any type qualifiers. There can be more than one. */
2117 if (PRINT_ANSI_QUALIFIERS
)
2119 APPEND_BLANK (result
);
2120 string_append (result
, "const");
2125 APPEND_BLANK (result
);
2126 string_append (result
, "unsigned");
2128 case 'S': /* signed char only */
2130 APPEND_BLANK (result
);
2131 string_append (result
, "signed");
2135 if (PRINT_ANSI_QUALIFIERS
)
2137 APPEND_BLANK (result
);
2138 string_append (result
, "volatile");
2147 /* Now pick off the fundamental type. There can be only one. */
2156 APPEND_BLANK (result
);
2157 string_append (result
, "void");
2161 APPEND_BLANK (result
);
2162 string_append (result
, "long long");
2166 APPEND_BLANK (result
);
2167 string_append (result
, "long");
2171 APPEND_BLANK (result
);
2172 string_append (result
, "int");
2176 APPEND_BLANK (result
);
2177 string_append (result
, "short");
2181 APPEND_BLANK (result
);
2182 string_append (result
, "bool");
2186 APPEND_BLANK (result
);
2187 string_append (result
, "char");
2191 APPEND_BLANK (result
);
2192 string_append (result
, "wchar_t");
2196 APPEND_BLANK (result
);
2197 string_append (result
, "long double");
2201 APPEND_BLANK (result
);
2202 string_append (result
, "double");
2206 APPEND_BLANK (result
);
2207 string_append (result
, "float");
2211 if (!isdigit (**mangled
))
2217 /* An explicit type, such as "6mytype" or "7integer" */
2228 APPEND_BLANK (result
);
2229 if (!demangle_class_name (work
, mangled
, result
)) {
2235 success
= demangle_template(work
,mangled
, result
, 0);
2245 /* `result' will be initialized in do_type; it will be freed on failure */
2248 do_arg (work
, mangled
, result
)
2249 struct work_stuff
*work
;
2250 const char **mangled
;
2253 const char *start
= *mangled
;
2255 if (!do_type (work
, mangled
, result
))
2261 remember_type (work
, start
, *mangled
- start
);
2267 remember_type (work
, start
, len
)
2268 struct work_stuff
*work
;
2274 if (work
-> ntypes
>= work
-> typevec_size
)
2276 if (work
-> typevec_size
== 0)
2278 work
-> typevec_size
= 3;
2280 (char **) xmalloc (sizeof (char *) * work
-> typevec_size
);
2284 work
-> typevec_size
*= 2;
2286 (char **) xrealloc ((char *)work
-> typevec
,
2287 sizeof (char *) * work
-> typevec_size
);
2290 tem
= xmalloc (len
+ 1);
2291 memcpy (tem
, start
, len
);
2293 work
-> typevec
[work
-> ntypes
++] = tem
;
2296 /* Forget the remembered types, but not the type vector itself. */
2300 struct work_stuff
*work
;
2304 while (work
-> ntypes
> 0)
2306 i
= --(work
-> ntypes
);
2307 if (work
-> typevec
[i
] != NULL
)
2309 free (work
-> typevec
[i
]);
2310 work
-> typevec
[i
] = NULL
;
2315 /* Process the argument list part of the signature, after any class spec
2316 has been consumed, as well as the first 'F' character (if any). For
2319 "__als__3fooRT0" => process "RT0"
2320 "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i"
2322 DECLP must be already initialised, usually non-empty. It won't be freed
2325 Note that g++ differs significantly from ARM and lucid style mangling
2326 with regards to references to previously seen types. For example, given
2327 the source fragment:
2331 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
2334 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
2335 void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
2337 g++ produces the names:
2342 while lcc (and presumably other ARM style compilers as well) produces:
2344 foo__FiR3fooT1T2T1T2
2345 __ct__3fooFiR3fooT1T2T1T2
2347 Note that g++ bases it's type numbers starting at zero and counts all
2348 previously seen types, while lucid/ARM bases it's type numbers starting
2349 at one and only considers types after it has seen the 'F' character
2350 indicating the start of the function args. For lucid/ARM style, we
2351 account for this difference by discarding any previously seen types when
2352 we see the 'F' character, and subtracting one from the type number
2358 demangle_args (work
, mangled
, declp
)
2359 struct work_stuff
*work
;
2360 const char **mangled
;
2370 if (PRINT_ARG_TYPES
)
2372 string_append (declp
, "(");
2373 if (**mangled
== '\0')
2375 string_append (declp
, "void");
2379 while (**mangled
!= '_' && **mangled
!= '\0' && **mangled
!= 'e')
2381 if ((**mangled
== 'N') || (**mangled
== 'T'))
2383 temptype
= *(*mangled
)++;
2385 if (temptype
== 'N')
2387 if (!get_count (mangled
, &r
))
2396 if (ARM_DEMANGLING
&& work
-> ntypes
>= 10)
2398 /* If we have 10 or more types we might have more than a 1 digit
2399 index so we'll have to consume the whole count here. This
2400 will loose if the next thing is a type name preceeded by a
2401 count but it's impossible to demangle that case properly
2402 anyway. Eg if we already have 12 types is T12Pc "(..., type1,
2403 anyway. Eg if we already have 12 types is T12Pc "(..., type1,
2404 Pc, ...)" or "(..., type12, char *, ...)" */
2405 if ((t
= consume_count(mangled
)) == 0)
2412 if (!get_count (mangled
, &t
))
2417 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
2421 /* Validate the type index. Protect against illegal indices from
2422 malformed type strings. */
2423 if ((t
< 0) || (t
>= work
-> ntypes
))
2429 tem
= work
-> typevec
[t
];
2430 if (need_comma
&& PRINT_ARG_TYPES
)
2432 string_append (declp
, ", ");
2434 if (!do_arg (work
, &tem
, &arg
))
2438 if (PRINT_ARG_TYPES
)
2440 string_appends (declp
, &arg
);
2442 string_delete (&arg
);
2448 if (need_comma
& PRINT_ARG_TYPES
)
2450 string_append (declp
, ", ");
2452 if (!do_arg (work
, mangled
, &arg
))
2456 if (PRINT_ARG_TYPES
)
2458 string_appends (declp
, &arg
);
2460 string_delete (&arg
);
2465 if (**mangled
== 'e')
2468 if (PRINT_ARG_TYPES
)
2472 string_append (declp
, ",");
2474 string_append (declp
, "...");
2478 if (PRINT_ARG_TYPES
)
2480 string_append (declp
, ")");
2486 demangle_function_name (work
, mangled
, declp
, scan
)
2487 struct work_stuff
*work
;
2488 const char **mangled
;
2497 string_appendn (declp
, (*mangled
), scan
- (*mangled
));
2498 string_need (declp
, 1);
2499 *(declp
-> p
) = '\0';
2501 /* Consume the function name, including the "__" separating the name
2502 from the signature. We are guaranteed that SCAN points to the
2505 (*mangled
) = scan
+ 2;
2507 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
2510 /* See if we have an ARM style constructor or destructor operator.
2511 If so, then just record it, clear the decl, and return.
2512 We can't build the actual constructor/destructor decl until later,
2513 when we recover the class name from the signature. */
2515 if (strcmp (declp
-> b
, "__ct") == 0)
2517 work
-> constructor
+= 1;
2518 string_clear (declp
);
2521 else if (strcmp (declp
-> b
, "__dt") == 0)
2523 work
-> destructor
+= 1;
2524 string_clear (declp
);
2529 if (declp
->p
- declp
->b
>= 3
2530 && declp
->b
[0] == 'o'
2531 && declp
->b
[1] == 'p'
2532 && strchr (cplus_markers
, declp
->b
[2]) != NULL
)
2534 /* see if it's an assignment expression */
2535 if (declp
->p
- declp
->b
>= 10 /* op$assign_ */
2536 && memcmp (declp
->b
+ 3, "assign_", 7) == 0)
2538 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
2540 len
= declp
->p
- declp
->b
- 10;
2541 if (strlen (optable
[i
].in
) == len
2542 && memcmp (optable
[i
].in
, declp
->b
+ 10, len
) == 0)
2544 string_clear (declp
);
2545 string_append (declp
, "operator");
2546 string_append (declp
, optable
[i
].out
);
2547 string_append (declp
, "=");
2554 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
2556 int len
= declp
->p
- declp
->b
- 3;
2557 if (strlen (optable
[i
].in
) == len
2558 && memcmp (optable
[i
].in
, declp
->b
+ 3, len
) == 0)
2560 string_clear (declp
);
2561 string_append (declp
, "operator");
2562 string_append (declp
, optable
[i
].out
);
2568 else if (declp
->p
- declp
->b
>= 5 && memcmp (declp
->b
, "type", 4) == 0
2569 && strchr (cplus_markers
, declp
->b
[4]) != NULL
)
2571 /* type conversion operator */
2573 if (do_type (work
, &tem
, &type
))
2575 string_clear (declp
);
2576 string_append (declp
, "operator ");
2577 string_appends (declp
, &type
);
2578 string_delete (&type
);
2581 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
2582 && declp
->b
[2] == 'o' && declp
->b
[3] == 'p')
2585 /* type conversion operator. */
2587 if (do_type (work
, &tem
, &type
))
2589 string_clear (declp
);
2590 string_append (declp
, "operator ");
2591 string_appends (declp
, &type
);
2592 string_delete (&type
);
2595 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
2596 && declp
->b
[2] >= 'a' && declp
->b
[2] <= 'z'
2597 && declp
->b
[3] >= 'a' && declp
->b
[3] <= 'z')
2599 if (declp
->b
[4] == '\0')
2602 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
2604 if (strlen (optable
[i
].in
) == 2
2605 && memcmp (optable
[i
].in
, declp
->b
+ 2, 2) == 0)
2607 string_clear (declp
);
2608 string_append (declp
, "operator");
2609 string_append (declp
, optable
[i
].out
);
2616 if (declp
->b
[2] == 'a' && declp
->b
[5] == '\0')
2619 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
2621 if (strlen (optable
[i
].in
) == 3
2622 && memcmp (optable
[i
].in
, declp
->b
+ 2, 3) == 0)
2624 string_clear (declp
);
2625 string_append (declp
, "operator");
2626 string_append (declp
, optable
[i
].out
);
2635 /* a mini string-handling package */
2650 s
->p
= s
->b
= xmalloc (n
);
2653 else if (s
->e
- s
->p
< n
)
2658 s
->b
= xrealloc (s
->b
, n
);
2671 s
->b
= s
->e
= s
->p
= NULL
;
2679 s
->b
= s
->p
= s
->e
= NULL
;
2695 return (s
->b
== s
->p
);
2701 string_append (p
, s
)
2706 if (s
== NULL
|| *s
== '\0')
2710 memcpy (p
->p
, s
, n
);
2715 string_appends (p
, s
)
2724 memcpy (p
->p
, s
->b
, n
);
2730 string_appendn (p
, s
, n
)
2738 memcpy (p
->p
, s
, n
);
2744 string_prepend (p
, s
)
2748 if (s
!= NULL
&& *s
!= '\0')
2750 string_prependn (p
, s
, strlen (s
));
2755 string_prepends (p
, s
)
2760 string_prependn (p
, s
->b
, s
->p
- s
->b
);
2765 string_prependn (p
, s
, n
)
2775 for (q
= p
->p
- 1; q
>= p
->b
; q
--)
2779 memcpy (p
->b
, s
, n
);
2784 /* To generate a standalone demangler program for testing purposes,
2785 just compile and link this file with -DMAIN and libiberty.a. When
2786 run, it demangles each command line arg, or each stdin string, and
2787 prints the result on stdout. */
2792 demangle_it (mangled_name
)
2797 result
= cplus_demangle (mangled_name
, DMGL_PARAMS
| DMGL_ANSI
);
2800 printf ("%s\n", mangled_name
);
2804 printf ("%s\n", result
);
2811 static char *program_name
;
2812 static char *program_version
= VERSION
;
2815 usage (stream
, status
)
2820 Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
2821 [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\
2822 [--help] [--version] [arg...]\n",
2827 #define MBUF_SIZE 512
2828 char mbuffer
[MBUF_SIZE
];
2830 /* Defined in the automatically-generated underscore.c. */
2831 extern int prepends_underscore
;
2833 int strip_underscore
= 0;
2835 static struct option long_options
[] = {
2836 {"strip-underscores", no_argument
, 0, '_'},
2837 {"format", required_argument
, 0, 's'},
2838 {"help", no_argument
, 0, 'h'},
2839 {"no-strip-underscores", no_argument
, 0, 'n'},
2840 {"version", no_argument
, 0, 'v'},
2841 {0, no_argument
, 0, 0}
2852 program_name
= argv
[0];
2854 strip_underscore
= prepends_underscore
;
2856 while ((c
= getopt_long (argc
, argv
, "_ns:", long_options
, (int *) 0)) != EOF
)
2866 strip_underscore
= 0;
2869 printf ("GNU %s version %s\n", program_name
, program_version
);
2872 strip_underscore
= 1;
2875 if (strcmp (optarg
, "gnu") == 0)
2877 current_demangling_style
= gnu_demangling
;
2879 else if (strcmp (optarg
, "lucid") == 0)
2881 current_demangling_style
= lucid_demangling
;
2883 else if (strcmp (optarg
, "arm") == 0)
2885 current_demangling_style
= arm_demangling
;
2889 fprintf (stderr
, "%s: unknown demangling style `%s'\n",
2890 program_name
, optarg
);
2899 for ( ; optind
< argc
; optind
++)
2901 demangle_it (argv
[optind
]);
2910 /* Try to read a label. */
2911 while (c
!= EOF
&& (isalnum(c
) || c
== '_' || c
== '$' || c
== '.'))
2913 if (i
>= MBUF_SIZE
-1)
2922 if (mbuffer
[0] == '.')
2924 if (strip_underscore
&& mbuffer
[skip_first
] == '_')
2932 result
= cplus_demangle (mbuffer
+ skip_first
,
2933 DMGL_PARAMS
| DMGL_ANSI
);
2936 if (mbuffer
[0] == '.')
2938 fputs (result
, stdout
);
2942 fputs (mbuffer
, stdout
);
2959 fprintf (stderr
, "%s: %s\n", program_name
, str
);
2970 register char *value
= (char *) malloc (size
);
2972 fatal ("virtual memory exhausted");
2977 xrealloc (ptr
, size
)
2981 register char *value
= (char *) realloc (ptr
, size
);
2983 fatal ("virtual memory exhausted");