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. */
36 #undef CURRENT_DEMANGLING_STYLE
37 #define CURRENT_DEMANGLING_STYLE work->options
39 extern char *xmalloc
PARAMS((unsigned));
40 extern char *xrealloc
PARAMS((char *, unsigned));
42 static const char *mystrstr
PARAMS ((const char *, const char *));
48 register const char *p
= s1
;
49 register int len
= strlen (s2
);
51 for (; (p
= strchr (p
, *s2
)) != 0; p
++)
53 if (strncmp (p
, s2
, len
) == 0)
61 /* In order to allow a single demangler executable to demangle strings
62 using various common values of CPLUS_MARKER, as well as any specific
63 one set at compile time, we maintain a string containing all the
64 commonly used ones, and check to see if the marker we are looking for
65 is in that string. CPLUS_MARKER is usually '$' on systems where the
66 assembler can deal with that. Where the assembler can't, it's usually
67 '.' (but on many systems '.' is used for other things). We put the
68 current defined CPLUS_MARKER first (which defaults to '$'), followed
69 by the next most common value, followed by an explicit '$' in case
70 the value of CPLUS_MARKER is not '$'.
72 We could avoid this if we could just get g++ to tell us what the actual
73 cplus marker character is as part of the debug information, perhaps by
74 ensuring that it is the character that terminates the gcc<n>_compiled
75 marker symbol (FIXME). */
77 #if !defined (CPLUS_MARKER)
78 #define CPLUS_MARKER '$'
81 enum demangling_styles current_demangling_style
= gnu_demangling
;
83 static char cplus_markers
[] = { CPLUS_MARKER
, '.', '$', '\0' };
86 set_cplus_marker_for_demangling (ch
)
89 cplus_markers
[0] = ch
;
92 /* Stuff that is shared between sub-routines.
93 Using a shared structure allows cplus_demangle to be reentrant. */
103 int static_type
; /* A static member function */
104 int const_type
; /* A const member function */
105 char **tmpl_argvec
; /* Template function arguments. */
106 int ntmpl_args
; /* The number of template function arguments. */
109 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
110 #define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS)
112 static const struct optable
118 {"nw", " new", DMGL_ANSI
}, /* new (1.92, ansi) */
119 {"dl", " delete", DMGL_ANSI
}, /* new (1.92, ansi) */
120 {"new", " new", 0}, /* old (1.91, and 1.x) */
121 {"delete", " delete", 0}, /* old (1.91, and 1.x) */
122 {"vn", " new []", DMGL_ANSI
}, /* GNU, pending ansi */
123 {"vd", " delete []", DMGL_ANSI
}, /* GNU, pending ansi */
124 {"as", "=", DMGL_ANSI
}, /* ansi */
125 {"ne", "!=", DMGL_ANSI
}, /* old, ansi */
126 {"eq", "==", DMGL_ANSI
}, /* old, ansi */
127 {"ge", ">=", DMGL_ANSI
}, /* old, ansi */
128 {"gt", ">", DMGL_ANSI
}, /* old, ansi */
129 {"le", "<=", DMGL_ANSI
}, /* old, ansi */
130 {"lt", "<", DMGL_ANSI
}, /* old, ansi */
131 {"plus", "+", 0}, /* old */
132 {"pl", "+", DMGL_ANSI
}, /* ansi */
133 {"apl", "+=", DMGL_ANSI
}, /* ansi */
134 {"minus", "-", 0}, /* old */
135 {"mi", "-", DMGL_ANSI
}, /* ansi */
136 {"ami", "-=", DMGL_ANSI
}, /* ansi */
137 {"mult", "*", 0}, /* old */
138 {"ml", "*", DMGL_ANSI
}, /* ansi */
139 {"amu", "*=", DMGL_ANSI
}, /* ansi (ARM/Lucid) */
140 {"aml", "*=", DMGL_ANSI
}, /* ansi (GNU/g++) */
141 {"convert", "+", 0}, /* old (unary +) */
142 {"negate", "-", 0}, /* old (unary -) */
143 {"trunc_mod", "%", 0}, /* old */
144 {"md", "%", DMGL_ANSI
}, /* ansi */
145 {"amd", "%=", DMGL_ANSI
}, /* ansi */
146 {"trunc_div", "/", 0}, /* old */
147 {"dv", "/", DMGL_ANSI
}, /* ansi */
148 {"adv", "/=", DMGL_ANSI
}, /* ansi */
149 {"truth_andif", "&&", 0}, /* old */
150 {"aa", "&&", DMGL_ANSI
}, /* ansi */
151 {"truth_orif", "||", 0}, /* old */
152 {"oo", "||", DMGL_ANSI
}, /* ansi */
153 {"truth_not", "!", 0}, /* old */
154 {"nt", "!", DMGL_ANSI
}, /* ansi */
155 {"postincrement","++", 0}, /* old */
156 {"pp", "++", DMGL_ANSI
}, /* ansi */
157 {"postdecrement","--", 0}, /* old */
158 {"mm", "--", DMGL_ANSI
}, /* ansi */
159 {"bit_ior", "|", 0}, /* old */
160 {"or", "|", DMGL_ANSI
}, /* ansi */
161 {"aor", "|=", DMGL_ANSI
}, /* ansi */
162 {"bit_xor", "^", 0}, /* old */
163 {"er", "^", DMGL_ANSI
}, /* ansi */
164 {"aer", "^=", DMGL_ANSI
}, /* ansi */
165 {"bit_and", "&", 0}, /* old */
166 {"ad", "&", DMGL_ANSI
}, /* ansi */
167 {"aad", "&=", DMGL_ANSI
}, /* ansi */
168 {"bit_not", "~", 0}, /* old */
169 {"co", "~", DMGL_ANSI
}, /* ansi */
170 {"call", "()", 0}, /* old */
171 {"cl", "()", DMGL_ANSI
}, /* ansi */
172 {"alshift", "<<", 0}, /* old */
173 {"ls", "<<", DMGL_ANSI
}, /* ansi */
174 {"als", "<<=", DMGL_ANSI
}, /* ansi */
175 {"arshift", ">>", 0}, /* old */
176 {"rs", ">>", DMGL_ANSI
}, /* ansi */
177 {"ars", ">>=", DMGL_ANSI
}, /* ansi */
178 {"component", "->", 0}, /* old */
179 {"pt", "->", DMGL_ANSI
}, /* ansi; Lucid C++ form */
180 {"rf", "->", DMGL_ANSI
}, /* ansi; ARM/GNU form */
181 {"indirect", "*", 0}, /* old */
182 {"method_call", "->()", 0}, /* old */
183 {"addr", "&", 0}, /* old (unary &) */
184 {"array", "[]", 0}, /* old */
185 {"vc", "[]", DMGL_ANSI
}, /* ansi */
186 {"compound", ", ", 0}, /* old */
187 {"cm", ", ", DMGL_ANSI
}, /* ansi */
188 {"cond", "?:", 0}, /* old */
189 {"cn", "?:", DMGL_ANSI
}, /* pseudo-ansi */
190 {"max", ">?", 0}, /* old */
191 {"mx", ">?", DMGL_ANSI
}, /* pseudo-ansi */
192 {"min", "<?", 0}, /* old */
193 {"mn", "<?", DMGL_ANSI
}, /* pseudo-ansi */
194 {"nop", "", 0}, /* old (for operator=) */
195 {"rm", "->*", DMGL_ANSI
} /* ansi */
199 typedef struct string
/* Beware: these aren't required to be */
200 { /* '\0' terminated. */
201 char *b
; /* pointer to start of string */
202 char *p
; /* pointer after last character */
203 char *e
; /* pointer after end of allocated space */
206 #define STRING_EMPTY(str) ((str) -> b == (str) -> p)
207 #define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
208 string_prepend(str, " ");}
209 #define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
210 string_append(str, " ");}
212 #define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */
213 #define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */
215 /* Prototypes for local functions */
218 mop_up
PARAMS ((struct work_stuff
*, string
*, int));
222 demangle_method_args
PARAMS ((struct work_stuff
*work
, const char **, string
*));
226 demangle_template
PARAMS ((struct work_stuff
*work
, const char **, string
*,
230 arm_pt
PARAMS ((struct work_stuff
*, const char *, int, const char **,
234 demangle_arm_pt
PARAMS ((struct work_stuff
*, const char **, int, string
*));
237 demangle_class_name
PARAMS ((struct work_stuff
*, const char **, string
*));
240 demangle_qualified
PARAMS ((struct work_stuff
*, const char **, string
*,
244 demangle_class
PARAMS ((struct work_stuff
*, const char **, string
*));
247 demangle_fund_type
PARAMS ((struct work_stuff
*, const char **, string
*));
250 demangle_signature
PARAMS ((struct work_stuff
*, const char **, string
*));
253 demangle_prefix
PARAMS ((struct work_stuff
*, const char **, string
*));
256 gnu_special
PARAMS ((struct work_stuff
*, const char **, string
*));
259 arm_special
PARAMS ((struct work_stuff
*, const char **, string
*));
262 string_need
PARAMS ((string
*, int));
265 string_delete
PARAMS ((string
*));
268 string_init
PARAMS ((string
*));
271 string_clear
PARAMS ((string
*));
275 string_empty
PARAMS ((string
*));
279 string_append
PARAMS ((string
*, const char *));
282 string_appends
PARAMS ((string
*, string
*));
285 string_appendn
PARAMS ((string
*, const char *, int));
288 string_prepend
PARAMS ((string
*, const char *));
291 string_prependn
PARAMS ((string
*, const char *, int));
294 get_count
PARAMS ((const char **, int *));
297 consume_count
PARAMS ((const char **));
300 consume_count_with_underscores
PARAMS ((const char**));
303 demangle_args
PARAMS ((struct work_stuff
*, const char **, string
*));
306 do_type
PARAMS ((struct work_stuff
*, const char **, string
*));
309 do_arg
PARAMS ((struct work_stuff
*, const char **, string
*));
312 demangle_function_name
PARAMS ((struct work_stuff
*, const char **, string
*,
316 remember_type
PARAMS ((struct work_stuff
*, const char *, int));
319 forget_types
PARAMS ((struct work_stuff
*));
322 string_prepends
PARAMS ((string
*, string
*));
324 /* Translate count to integer, consuming tokens in the process.
325 Conversion terminates on the first non-digit character.
326 Trying to consume something that isn't a count results in
327 no consumption of input and a return of 0. */
335 while (isdigit (**type
))
338 count
+= **type
- '0';
345 /* Like consume_count, but for counts that are preceded and followed
346 by '_' if they are greater than 10. Also, -1 is returned for
347 failure, since 0 can be a valid value. */
350 consume_count_with_underscores (mangled
)
351 const char **mangled
;
355 if (**mangled
== '_')
358 if (!isdigit (**mangled
))
361 idx
= consume_count (mangled
);
362 if (**mangled
!= '_')
363 /* The trailing underscore was missing. */
370 if (**mangled
< '0' || **mangled
> '9')
373 idx
= **mangled
- '0';
381 cplus_demangle_opname (opname
, result
, options
)
386 int len
, i
, len1
, ret
;
388 struct work_stuff work
[1];
391 len
= strlen(opname
);
394 work
->options
= options
;
396 if (opname
[0] == '_' && opname
[1] == '_'
397 && opname
[2] == 'o' && opname
[3] == 'p')
400 /* type conversion operator. */
402 if (do_type (work
, &tem
, &type
))
404 strcat (result
, "operator ");
405 strncat (result
, type
.b
, type
.p
- type
.b
);
406 string_delete (&type
);
410 else if (opname
[0] == '_' && opname
[1] == '_'
411 && opname
[2] >= 'a' && opname
[2] <= 'z'
412 && opname
[3] >= 'a' && opname
[3] <= 'z')
414 if (opname
[4] == '\0')
417 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
419 if (strlen (optable
[i
].in
) == 2
420 && memcmp (optable
[i
].in
, opname
+ 2, 2) == 0)
422 strcat (result
, "operator");
423 strcat (result
, optable
[i
].out
);
431 if (opname
[2] == 'a' && opname
[5] == '\0')
434 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
436 if (strlen (optable
[i
].in
) == 3
437 && memcmp (optable
[i
].in
, opname
+ 2, 3) == 0)
439 strcat (result
, "operator");
440 strcat (result
, optable
[i
].out
);
451 && strchr (cplus_markers
, opname
[2]) != NULL
)
453 /* see if it's an assignment expression */
454 if (len
>= 10 /* op$assign_ */
455 && memcmp (opname
+ 3, "assign_", 7) == 0)
457 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
460 if (strlen (optable
[i
].in
) == len1
461 && memcmp (optable
[i
].in
, opname
+ 10, len1
) == 0)
463 strcat (result
, "operator");
464 strcat (result
, optable
[i
].out
);
465 strcat (result
, "=");
473 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
476 if (strlen (optable
[i
].in
) == len1
477 && memcmp (optable
[i
].in
, opname
+ 3, len1
) == 0)
479 strcat (result
, "operator");
480 strcat (result
, optable
[i
].out
);
487 else if (len
>= 5 && memcmp (opname
, "type", 4) == 0
488 && strchr (cplus_markers
, opname
[4]) != NULL
)
490 /* type conversion operator */
492 if (do_type (work
, &tem
, &type
))
494 strcat (result
, "operator ");
495 strncat (result
, type
.b
, type
.p
- type
.b
);
496 string_delete (&type
);
503 /* Takes operator name as e.g. "++" and returns mangled
504 operator name (e.g. "postincrement_expr"), or NULL if not found.
506 If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
507 if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */
510 cplus_mangle_opname (opname
, options
)
517 len
= strlen (opname
);
518 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
520 if (strlen (optable
[i
].out
) == len
521 && (options
& DMGL_ANSI
) == (optable
[i
].flags
& DMGL_ANSI
)
522 && memcmp (optable
[i
].out
, opname
, len
) == 0)
523 return optable
[i
].in
;
528 /* char *cplus_demangle (const char *mangled, int options)
530 If MANGLED is a mangled function name produced by GNU C++, then
531 a pointer to a malloced string giving a C++ representation
532 of the name will be returned; otherwise NULL will be returned.
533 It is the caller's responsibility to free the string which
536 The OPTIONS arg may contain one or more of the following bits:
538 DMGL_ANSI ANSI qualifiers such as `const' and `void' are
540 DMGL_PARAMS Function parameters are included.
544 cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)"
545 cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
546 cplus_demangle ("foo__1Ai", 0) => "A::foo"
548 cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)"
549 cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
550 cplus_demangle ("foo__1Afe", 0) => "A::foo"
552 Note that any leading underscores, or other such characters prepended by
553 the compilation system, are presumed to have already been stripped from
557 cplus_demangle (mangled
, options
)
563 struct work_stuff work
[1];
564 char *demangled
= NULL
;
566 if ((mangled
!= NULL
) && (*mangled
!= '\0'))
568 memset ((char *) work
, 0, sizeof (work
));
569 work
-> options
= options
;
570 if ((work
->options
& DMGL_STYLE_MASK
) == 0)
571 work
->options
|= (int)current_demangling_style
& DMGL_STYLE_MASK
;
575 /* First check to see if gnu style demangling is active and if the
576 string to be demangled contains a CPLUS_MARKER. If so, attempt to
577 recognize one of the gnu special forms rather than looking for a
578 standard prefix. In particular, don't worry about whether there
579 is a "__" string in the mangled string. Consider "_$_5__foo" for
582 if ((AUTO_DEMANGLING
|| GNU_DEMANGLING
))
584 success
= gnu_special (work
, &mangled
, &decl
);
588 success
= demangle_prefix (work
, &mangled
, &decl
);
590 if (success
&& (*mangled
!= '\0'))
592 success
= demangle_signature (work
, &mangled
, &decl
);
594 if (work
->constructor
== 2)
596 string_prepend(&decl
, "global constructors keyed to ");
597 work
->constructor
= 0;
599 else if (work
->destructor
== 2)
601 string_prepend(&decl
, "global destructors keyed to ");
602 work
->destructor
= 0;
604 demangled
= mop_up (work
, &decl
, success
);
610 mop_up (work
, declp
, success
)
611 struct work_stuff
*work
;
615 char *demangled
= NULL
;
617 /* Discard the remembered types, if any. */
620 if (work
-> typevec
!= NULL
)
622 free ((char *) work
-> typevec
);
624 if (work
->tmpl_argvec
)
628 for (i
= 0; i
< work
->ntmpl_args
; i
++)
629 if (work
->tmpl_argvec
[i
])
630 free ((char*) work
->tmpl_argvec
[i
]);
632 free ((char*) work
->tmpl_argvec
);
635 /* If demangling was successful, ensure that the demangled string is null
636 terminated and return it. Otherwise, free the demangling decl. */
640 string_delete (declp
);
644 string_appendn (declp
, "", 1);
645 demangled
= declp
-> b
;
654 demangle_signature -- demangle the signature part of a mangled name
659 demangle_signature (struct work_stuff *work, const char **mangled,
664 Consume and demangle the signature portion of the mangled name.
666 DECLP is the string where demangled output is being built. At
667 entry it contains the demangled root name from the mangled name
668 prefix. I.E. either a demangled operator name or the root function
669 name. In some special cases, it may contain nothing.
671 *MANGLED points to the current unconsumed location in the mangled
672 name. As tokens are consumed and demangling is performed, the
673 pointer is updated to continuously point at the next token to
676 Demangling GNU style mangled names is nasty because there is no
677 explicit token that marks the start of the outermost function
681 demangle_signature (work
, mangled
, declp
)
682 struct work_stuff
*work
;
683 const char **mangled
;
689 int expect_return_type
= 0;
690 const char *oldmangled
= NULL
;
694 while (success
&& (**mangled
!= '\0'))
699 oldmangled
= *mangled
;
700 success
= demangle_qualified (work
, mangled
, declp
, 1, 0);
703 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
705 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
713 /* Static member function */
714 if (oldmangled
== NULL
)
716 oldmangled
= *mangled
;
719 work
-> static_type
= 1;
723 /* a const member function */
724 if (oldmangled
== NULL
)
726 oldmangled
= *mangled
;
729 work
-> const_type
= 1;
732 case '0': case '1': case '2': case '3': case '4':
733 case '5': case '6': case '7': case '8': case '9':
734 if (oldmangled
== NULL
)
736 oldmangled
= *mangled
;
738 success
= demangle_class (work
, mangled
, declp
);
741 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
743 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
752 /* ARM style demangling includes a specific 'F' character after
753 the class name. For GNU style, it is just implied. So we can
754 safely just consume any 'F' at this point and be compatible
755 with either style. */
761 /* For lucid/ARM style we have to forget any types we might
762 have remembered up to this point, since they were not argument
763 types. GNU style considers all types seen as available for
764 back references. See comment in demangle_args() */
766 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
770 success
= demangle_args (work
, mangled
, declp
);
775 string_init(&trawname
);
777 if (oldmangled
== NULL
)
779 oldmangled
= *mangled
;
781 success
= demangle_template (work
, mangled
, &tname
, &trawname
, 1);
784 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
786 string_append(&tname
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
787 string_prepends(declp
, &tname
);
788 if (work
-> destructor
& 1)
790 string_prepend (&trawname
, "~");
791 string_appends (declp
, &trawname
);
792 work
->destructor
-= 1;
794 if ((work
->constructor
& 1) || (work
->destructor
& 1))
796 string_appends (declp
, &trawname
);
797 work
->constructor
-= 1;
799 string_delete(&trawname
);
800 string_delete(&tname
);
806 if (GNU_DEMANGLING
&& expect_return_type
)
808 /* Read the return type. */
810 string_init (&return_type
);
813 success
= do_type (work
, mangled
, &return_type
);
814 APPEND_BLANK (&return_type
);
816 string_prepends (declp
, &return_type
);
817 string_delete (&return_type
);
821 /* At the outermost level, we cannot have a return type specified,
822 so if we run into another '_' at this point we are dealing with
823 a mangled name that is either bogus, or has been mangled by
824 some algorithm we don't know how to deal with. So just
825 reject the entire demangling. */
832 /* A G++ template function. Read the template arguments. */
833 success
= demangle_template (work
, mangled
, declp
, 0, 0);
834 expect_return_type
= 1;
843 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
845 /* Assume we have stumbled onto the first outermost function
846 argument token, and start processing args. */
848 success
= demangle_args (work
, mangled
, declp
);
852 /* Non-GNU demanglers use a specific token to mark the start
853 of the outermost function argument tokens. Typically 'F',
854 for ARM-demangling, for example. So if we find something
855 we are not prepared for, it must be an error. */
861 if (AUTO_DEMANGLING || GNU_DEMANGLING)
864 if (success
&& expect_func
)
867 success
= demangle_args (work
, mangled
, declp
);
868 /* Since template include the mangling of their return types,
869 we must set expect_func to 0 so that we don't try do
870 demangle more arguments the next time we get here. */
875 if (success
&& !func_done
)
877 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
879 /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
880 bar__3fooi is 'foo::bar(int)'. We get here when we find the
881 first case, and need to ensure that the '(void)' gets added to
882 the current declp. Note that with ARM, the first case
883 represents the name of a static data member 'foo::bar',
884 which is in the current declp, so we leave it alone. */
885 success
= demangle_args (work
, mangled
, declp
);
888 if (success
&& work
-> static_type
&& PRINT_ARG_TYPES
)
890 string_append (declp
, " static");
892 if (success
&& work
-> const_type
&& PRINT_ARG_TYPES
)
894 string_append (declp
, " const");
902 demangle_method_args (work
, mangled
, declp
)
903 struct work_stuff
*work
;
904 const char **mangled
;
909 if (work
-> static_type
)
911 string_append (declp
, *mangled
+ 1);
912 *mangled
+= strlen (*mangled
);
917 success
= demangle_args (work
, mangled
, declp
);
925 demangle_template (work
, mangled
, tname
, trawname
, is_type
)
926 struct work_stuff
*work
;
927 const char **mangled
;
945 int is_java_array
= 0;
952 /* get template name */
953 if ((r
= consume_count (mangled
)) == 0 || strlen (*mangled
) < r
)
958 string_appendn (trawname
, *mangled
, r
);
959 is_java_array
= (work
-> options
& DMGL_JAVA
)
960 && strncmp (*mangled
, "JArray1Z", 8) == 0;
963 string_appendn (tname
, *mangled
, r
);
968 string_append (tname
, "<");
969 /* get size of template parameter list */
970 if (!get_count (mangled
, &r
))
976 /* Create an array for saving the template argument values. */
977 work
->tmpl_argvec
= (char**) xmalloc (r
* sizeof (char *));
978 work
->ntmpl_args
= r
;
979 for (i
= 0; i
< r
; i
++)
980 work
->tmpl_argvec
[i
] = 0;
982 for (i
= 0; i
< r
; i
++)
986 string_append (tname
, ", ");
988 /* Z for type parameters */
989 if (**mangled
== 'Z')
992 /* temp is initialized in do_type */
993 success
= do_type (work
, mangled
, &temp
);
996 string_appends (tname
, &temp
);
1000 /* Save the template argument. */
1001 int len
= temp
.p
- temp
.b
;
1002 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1003 memcpy (work
->tmpl_argvec
[i
], temp
.b
, len
);
1004 work
->tmpl_argvec
[i
][len
] = '\0';
1007 string_delete(&temp
);
1018 /* otherwise, value parameter */
1026 /* temp is initialized in do_type */
1027 success
= do_type (work
, mangled
, &temp
);
1031 string_appends (s, &temp);
1034 string_delete(&temp
);
1040 string_append (s, "=");
1051 while (*old_p
&& !done
)
1058 done
= is_pointer
= 1;
1060 case 'C': /* const */
1061 case 'S': /* explicitly signed [char] */
1062 case 'U': /* unsigned */
1063 case 'V': /* volatile */
1064 case 'F': /* function */
1065 case 'M': /* member function */
1067 case 'J': /* complex */
1070 case 'Q': /* qualified name */
1071 done
= is_integral
= 1;
1073 case 'T': /* remembered type */
1076 case 'v': /* void */
1079 case 'x': /* long long */
1080 case 'l': /* long */
1082 case 's': /* short */
1083 case 'w': /* wchar_t */
1084 done
= is_integral
= 1;
1086 case 'b': /* bool */
1089 case 'c': /* char */
1092 case 'r': /* long double */
1093 case 'd': /* double */
1094 case 'f': /* float */
1098 /* it's probably user defined type, let's assume
1099 it's integral, it seems hard to figure out
1100 what it really is */
1101 done
= is_integral
= 1;
1104 if (**mangled
== 'Y')
1106 /* The next argument is a template parameter. */
1110 idx
= consume_count_with_underscores (mangled
);
1112 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
1113 || consume_count_with_underscores (mangled
) == -1)
1120 if (work
->tmpl_argvec
)
1121 string_append (s
, work
->tmpl_argvec
[idx
]);
1125 sprintf(buf
, "T%d", idx
);
1126 string_append (s
, buf
);
1129 else if (is_integral
)
1131 if (**mangled
== 'm')
1133 string_appendn (s
, "-", 1);
1136 while (isdigit (**mangled
))
1138 string_appendn (s
, *mangled
, 1);
1146 if (**mangled
== 'm')
1148 string_appendn (s
, "-", 1);
1151 string_appendn (s
, "'", 1);
1152 val
= consume_count(mangled
);
1162 string_appendn (s
, &tmp
[0], 1);
1163 string_appendn (s
, "'", 1);
1167 int val
= consume_count (mangled
);
1169 string_appendn (s
, "false", 5);
1171 string_appendn (s
, "true", 4);
1177 if (**mangled
== 'm')
1179 string_appendn (s
, "-", 1);
1182 while (isdigit (**mangled
))
1184 string_appendn (s
, *mangled
, 1);
1187 if (**mangled
== '.') /* fraction */
1189 string_appendn (s
, ".", 1);
1191 while (isdigit (**mangled
))
1193 string_appendn (s
, *mangled
, 1);
1197 if (**mangled
== 'e') /* exponent */
1199 string_appendn (s
, "e", 1);
1201 while (isdigit (**mangled
))
1203 string_appendn (s
, *mangled
, 1);
1208 else if (is_pointer
)
1210 symbol_len
= consume_count (mangled
);
1211 if (symbol_len
== 0)
1218 if (symbol_len
== 0)
1219 string_appendn (s
, "0", 1);
1222 char *p
= xmalloc (symbol_len
+ 1), *q
;
1223 strncpy (p
, *mangled
, symbol_len
);
1224 p
[symbol_len
] = '\0';
1225 q
= cplus_demangle (p
, work
->options
);
1226 string_appendn (s
, "&", 1);
1229 string_append (s
, q
);
1233 string_append (s
, p
);
1236 *mangled
+= symbol_len
;
1240 int len
= s
->p
- s
->b
;
1241 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1242 memcpy (work
->tmpl_argvec
[i
], s
->b
, len
);
1243 work
->tmpl_argvec
[i
][len
] = '\0';
1245 string_appends (tname
, s
);
1253 string_append (tname
, "[]");
1257 if (tname
->p
[-1] == '>')
1258 string_append (tname
, " ");
1259 string_append (tname
, ">");
1263 if (work -> static_type)
1265 string_append (declp, *mangled + 1);
1266 *mangled += strlen (*mangled);
1271 success = demangle_args (work, mangled, declp);
1279 arm_pt (work
, mangled
, n
, anchor
, args
)
1280 struct work_stuff
*work
;
1281 const char *mangled
;
1283 const char **anchor
, **args
;
1286 if (ARM_DEMANGLING
&& (*anchor
= mystrstr (mangled
, "__pt__")))
1289 *args
= *anchor
+ 6;
1290 len
= consume_count (args
);
1291 if (*args
+ len
== mangled
+ n
&& **args
== '_')
1301 demangle_arm_pt (work
, mangled
, n
, declp
)
1302 struct work_stuff
*work
;
1303 const char **mangled
;
1309 const char *e
= *mangled
+ n
;
1312 if (arm_pt (work
, *mangled
, n
, &p
, &args
))
1316 string_appendn (declp
, *mangled
, p
- *mangled
);
1317 string_append (declp
, "<");
1318 /* should do error checking here */
1320 string_clear (&arg
);
1321 do_type (work
, &args
, &arg
);
1322 string_appends (declp
, &arg
);
1323 string_append (declp
, ",");
1325 string_delete (&arg
);
1327 string_append (declp
, ">");
1331 string_appendn (declp
, *mangled
, n
);
1337 demangle_class_name (work
, mangled
, declp
)
1338 struct work_stuff
*work
;
1339 const char **mangled
;
1345 n
= consume_count (mangled
);
1346 if (strlen (*mangled
) >= n
)
1348 demangle_arm_pt (work
, mangled
, n
, declp
);
1359 demangle_class -- demangle a mangled class sequence
1364 demangle_class (struct work_stuff *work, const char **mangled,
1369 DECLP points to the buffer into which demangling is being done.
1371 *MANGLED points to the current token to be demangled. On input,
1372 it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
1373 On exit, it points to the next token after the mangled class on
1374 success, or the first unconsumed token on failure.
1376 If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
1377 we are demangling a constructor or destructor. In this case
1378 we prepend "class::class" or "class::~class" to DECLP.
1380 Otherwise, we prepend "class::" to the current DECLP.
1382 Reset the constructor/destructor flags once they have been
1383 "consumed". This allows demangle_class to be called later during
1384 the same demangling, to do normal class demangling.
1386 Returns 1 if demangling is successful, 0 otherwise.
1391 demangle_class (work
, mangled
, declp
)
1392 struct work_stuff
*work
;
1393 const char **mangled
;
1399 string_init (&class_name
);
1400 if (demangle_class_name (work
, mangled
, &class_name
))
1402 if ((work
->constructor
& 1) || (work
->destructor
& 1))
1404 string_prepends (declp
, &class_name
);
1405 if (work
-> destructor
& 1)
1407 string_prepend (declp
, "~");
1408 work
-> destructor
-= 1;
1412 work
-> constructor
-= 1;
1415 string_prepend (declp
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
1416 string_prepends (declp
, &class_name
);
1419 string_delete (&class_name
);
1427 demangle_prefix -- consume the mangled name prefix and find signature
1432 demangle_prefix (struct work_stuff *work, const char **mangled,
1437 Consume and demangle the prefix of the mangled name.
1439 DECLP points to the string buffer into which demangled output is
1440 placed. On entry, the buffer is empty. On exit it contains
1441 the root function name, the demangled operator name, or in some
1442 special cases either nothing or the completely demangled result.
1444 MANGLED points to the current pointer into the mangled name. As each
1445 token of the mangled name is consumed, it is updated. Upon entry
1446 the current mangled name pointer points to the first character of
1447 the mangled name. Upon exit, it should point to the first character
1448 of the signature if demangling was successful, or to the first
1449 unconsumed character if demangling of the prefix was unsuccessful.
1451 Returns 1 on success, 0 otherwise.
1455 demangle_prefix (work
, mangled
, declp
)
1456 struct work_stuff
*work
;
1457 const char **mangled
;
1464 if (strlen(*mangled
) >= 11 && strncmp(*mangled
, "_GLOBAL_", 8) == 0)
1466 char *marker
= strchr (cplus_markers
, (*mangled
)[8]);
1467 if (marker
!= NULL
&& *marker
== (*mangled
)[10])
1469 if ((*mangled
)[9] == 'D')
1471 /* it's a GNU global destructor to be executed at program exit */
1473 work
->destructor
= 2;
1474 if (gnu_special (work
, mangled
, declp
))
1477 else if ((*mangled
)[9] == 'I')
1479 /* it's a GNU global constructor to be executed at program init */
1481 work
->constructor
= 2;
1482 if (gnu_special (work
, mangled
, declp
))
1487 else if (ARM_DEMANGLING
&& strncmp(*mangled
, "__std__", 7) == 0)
1489 /* it's a ARM global destructor to be executed at program exit */
1491 work
->destructor
= 2;
1493 else if (ARM_DEMANGLING
&& strncmp(*mangled
, "__sti__", 7) == 0)
1495 /* it's a ARM global constructor to be executed at program initial */
1497 work
->constructor
= 2;
1500 /* This block of code is a reduction in strength time optimization
1502 scan = mystrstr (*mangled, "__"); */
1508 scan
= strchr (scan
, '_');
1509 } while (scan
!= NULL
&& *++scan
!= '_');
1511 if (scan
!= NULL
) --scan
;
1516 /* We found a sequence of two or more '_', ensure that we start at
1517 the last pair in the sequence. */
1518 i
= strspn (scan
, "_");
1529 else if (work
-> static_type
)
1531 if (!isdigit (scan
[0]) && (scan
[0] != 't'))
1536 else if ((scan
== *mangled
)
1537 && (isdigit (scan
[2]) || (scan
[2] == 'Q') || (scan
[2] == 't')))
1539 /* The ARM says nothing about the mangling of local variables.
1540 But cfront mangles local variables by prepending __<nesting_level>
1541 to them. As an extension to ARM demangling we handle this case. */
1542 if ((LUCID_DEMANGLING
|| ARM_DEMANGLING
) && isdigit (scan
[2]))
1544 *mangled
= scan
+ 2;
1545 consume_count (mangled
);
1546 string_append (declp
, *mangled
);
1547 *mangled
+= strlen (*mangled
);
1552 /* A GNU style constructor starts with __[0-9Qt]. But cfront uses
1553 names like __Q2_3foo3bar for nested type names. So don't accept
1554 this style of constructor for cfront demangling. */
1555 if (!(LUCID_DEMANGLING
|| ARM_DEMANGLING
))
1556 work
-> constructor
+= 1;
1557 *mangled
= scan
+ 2;
1560 else if ((scan
== *mangled
) && !isdigit (scan
[2]) && (scan
[2] != 't'))
1562 /* Mangled name starts with "__". Skip over any leading '_' characters,
1563 then find the next "__" that separates the prefix from the signature.
1565 if (!(ARM_DEMANGLING
|| LUCID_DEMANGLING
)
1566 || (arm_special (work
, mangled
, declp
) == 0))
1568 while (*scan
== '_')
1572 if ((scan
= mystrstr (scan
, "__")) == NULL
|| (*(scan
+ 2) == '\0'))
1574 /* No separator (I.E. "__not_mangled"), or empty signature
1575 (I.E. "__not_mangled_either__") */
1580 demangle_function_name (work
, mangled
, declp
, scan
);
1584 else if (ARM_DEMANGLING
&& scan
[2] == 'p' && scan
[3] == 't')
1586 /* Cfront-style parameterized type. Handled later as a signature. */
1590 demangle_arm_pt (work
, mangled
, strlen (*mangled
), declp
);
1592 else if (*(scan
+ 2) != '\0')
1594 /* Mangled name does not start with "__" but does have one somewhere
1595 in there with non empty stuff after it. Looks like a global
1597 demangle_function_name (work
, mangled
, declp
, scan
);
1601 /* Doesn't look like a mangled name */
1605 if (!success
&& (work
->constructor
== 2 || work
->destructor
== 2))
1607 string_append (declp
, *mangled
);
1608 *mangled
+= strlen (*mangled
);
1618 gnu_special -- special handling of gnu mangled strings
1623 gnu_special (struct work_stuff *work, const char **mangled,
1629 Process some special GNU style mangling forms that don't fit
1630 the normal pattern. For example:
1632 _$_3foo (destructor for class foo)
1633 _vt$foo (foo virtual table)
1634 _vt$foo$bar (foo::bar virtual table)
1635 __vt_foo (foo virtual table, new style with thunks)
1636 _3foo$varname (static data member)
1637 _Q22rs2tu$vw (static data member)
1638 __t6vector1Zii (constructor with template)
1639 __thunk_4__$_7ostream (virtual function thunk)
1643 gnu_special (work
, mangled
, declp
)
1644 struct work_stuff
*work
;
1645 const char **mangled
;
1652 if ((*mangled
)[0] == '_'
1653 && strchr (cplus_markers
, (*mangled
)[1]) != NULL
1654 && (*mangled
)[2] == '_')
1656 /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
1658 work
-> destructor
+= 1;
1660 else if ((*mangled
)[0] == '_'
1661 && (((*mangled
)[1] == '_'
1662 && (*mangled
)[2] == 'v'
1663 && (*mangled
)[3] == 't'
1664 && (*mangled
)[4] == '_')
1665 || ((*mangled
)[1] == 'v'
1666 && (*mangled
)[2] == 't'
1667 && strchr (cplus_markers
, (*mangled
)[3]) != NULL
)))
1669 /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
1670 and create the decl. Note that we consume the entire mangled
1671 input string, which means that demangle_signature has no work
1673 if ((*mangled
)[2] == 'v')
1674 (*mangled
) += 5; /* New style, with thunks: "__vt_" */
1676 (*mangled
) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
1677 while (**mangled
!= '\0')
1679 p
= strpbrk (*mangled
, cplus_markers
);
1683 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
1686 success
= demangle_template (work
, mangled
, declp
, 0, 1);
1689 if (isdigit(*mangled
[0]))
1691 n
= consume_count(mangled
);
1695 n
= strcspn (*mangled
, cplus_markers
);
1697 string_appendn (declp
, *mangled
, n
);
1701 if (success
&& ((p
== NULL
) || (p
== *mangled
)))
1705 string_append (declp
,
1706 (work
-> options
& DMGL_JAVA
) ? "." : "::");
1717 string_append (declp
, " virtual table");
1719 else if ((*mangled
)[0] == '_'
1720 && (strchr("0123456789Qt", (*mangled
)[1]) != NULL
)
1721 && (p
= strpbrk (*mangled
, cplus_markers
)) != NULL
)
1723 /* static data member, "_3foo$varname" for example */
1728 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
1731 success
= demangle_template (work
, mangled
, declp
, 0, 1);
1734 n
= consume_count (mangled
);
1735 string_appendn (declp
, *mangled
, n
);
1738 if (success
&& (p
== *mangled
))
1740 /* Consumed everything up to the cplus_marker, append the
1743 string_append (declp
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
1744 n
= strlen (*mangled
);
1745 string_appendn (declp
, *mangled
, n
);
1753 else if (strncmp (*mangled
, "__thunk_", 8) == 0)
1755 int delta
= ((*mangled
) += 8, consume_count (mangled
));
1756 char *method
= cplus_demangle (++*mangled
, work
->options
);
1760 sprintf (buf
, "virtual function thunk (delta:%d) for ", -delta
);
1761 string_append (declp
, buf
);
1762 string_append (declp
, method
);
1764 n
= strlen (*mangled
);
1772 else if (strncmp (*mangled
, "__t", 3) == 0
1773 && ((*mangled
)[3] == 'i' || (*mangled
)[3] == 'f'))
1775 p
= (*mangled
)[3] == 'i' ? " type_info node" : " type_info function";
1780 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
1783 success
= demangle_template (work
, mangled
, declp
, 0, 1);
1786 success
= demangle_fund_type (work
, mangled
, declp
);
1789 if (success
&& **mangled
!= '\0')
1792 string_append (declp
, p
);
1805 arm_special -- special handling of ARM/lucid mangled strings
1810 arm_special (struct work_stuff *work, const char **mangled,
1816 Process some special ARM style mangling forms that don't fit
1817 the normal pattern. For example:
1819 __vtbl__3foo (foo virtual table)
1820 __vtbl__3foo__3bar (bar::foo virtual table)
1825 arm_special (work
, mangled
, declp
)
1826 struct work_stuff
*work
;
1827 const char **mangled
;
1834 if (strncmp (*mangled
, ARM_VTABLE_STRING
, ARM_VTABLE_STRLEN
) == 0)
1836 /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
1837 and create the decl. Note that we consume the entire mangled
1838 input string, which means that demangle_signature has no work
1840 scan
= *mangled
+ ARM_VTABLE_STRLEN
;
1841 while (*scan
!= '\0') /* first check it can be demangled */
1843 n
= consume_count (&scan
);
1846 return (0); /* no good */
1849 if (scan
[0] == '_' && scan
[1] == '_')
1854 (*mangled
) += ARM_VTABLE_STRLEN
;
1855 while (**mangled
!= '\0')
1857 n
= consume_count (mangled
);
1858 string_prependn (declp
, *mangled
, n
);
1860 if ((*mangled
)[0] == '_' && (*mangled
)[1] == '_')
1862 string_prepend (declp
, "::");
1866 string_append (declp
, " virtual table");
1879 demangle_qualified -- demangle 'Q' qualified name strings
1884 demangle_qualified (struct work_stuff *, const char *mangled,
1885 string *result, int isfuncname, int append);
1889 Demangle a qualified name, such as "Q25Outer5Inner" which is
1890 the mangled form of "Outer::Inner". The demangled output is
1891 prepended or appended to the result string according to the
1892 state of the append flag.
1894 If isfuncname is nonzero, then the qualified name we are building
1895 is going to be used as a member function name, so if it is a
1896 constructor or destructor function, append an appropriate
1897 constructor or destructor name. I.E. for the above example,
1898 the result for use as a constructor is "Outer::Inner::Inner"
1899 and the result for use as a destructor is "Outer::Inner::~Inner".
1903 Numeric conversion is ASCII dependent (FIXME).
1908 demangle_qualified (work
, mangled
, result
, isfuncname
, append
)
1909 struct work_stuff
*work
;
1910 const char **mangled
;
1922 string_init (&temp
);
1923 switch ((*mangled
)[1])
1926 /* GNU mangled name with more than 9 classes. The count is preceded
1927 by an underscore (to distinguish it from the <= 9 case) and followed
1928 by an underscore. */
1930 qualifiers
= atoi (p
);
1931 if (!isdigit (*p
) || *p
== '0')
1934 /* Skip the digits. */
1935 while (isdigit (*p
))
1953 /* The count is in a single digit. */
1954 num
[0] = (*mangled
)[1];
1956 qualifiers
= atoi (num
);
1958 /* If there is an underscore after the digit, skip it. This is
1959 said to be for ARM-qualified names, but the ARM makes no
1960 mention of such an underscore. Perhaps cfront uses one. */
1961 if ((*mangled
)[2] == '_')
1976 /* Pick off the names and collect them in the temp buffer in the order
1977 in which they are found, separated by '::'. */
1979 while (qualifiers
-- > 0)
1981 if (*mangled
[0] == '_')
1982 *mangled
= *mangled
+ 1;
1983 if (*mangled
[0] == 't')
1985 success
= demangle_template(work
, mangled
, &temp
, 0, 1);
1986 if (!success
) break;
1988 else if (*mangled
[0] == 'X')
1990 success
= do_type (work
, mangled
, &temp
);
1991 if (!success
) break;
1995 namelength
= consume_count (mangled
);
1996 if (strlen (*mangled
) < namelength
)
1998 /* Simple sanity check failed */
2002 string_appendn (&temp
, *mangled
, namelength
);
2003 *mangled
+= namelength
;
2007 string_append (&temp
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
2011 /* If we are using the result as a function name, we need to append
2012 the appropriate '::' separated constructor or destructor name.
2013 We do this here because this is the most convenient place, where
2014 we already have a pointer to the name and the length of the name. */
2016 if (isfuncname
&& (work
->constructor
& 1 || work
->destructor
& 1))
2018 string_append (&temp
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
2019 if (work
-> destructor
& 1)
2021 string_append (&temp
, "~");
2023 string_appendn (&temp
, (*mangled
) - namelength
, namelength
);
2026 /* Now either prepend the temp buffer to the result, or append it,
2027 depending upon the state of the append flag. */
2031 string_appends (result
, &temp
);
2035 if (!STRING_EMPTY (result
))
2037 string_append (&temp
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
2039 string_prepends (result
, &temp
);
2042 string_delete (&temp
);
2050 get_count -- convert an ascii count to integer, consuming tokens
2055 get_count (const char **type, int *count)
2059 Return 0 if no conversion is performed, 1 if a string is converted.
2063 get_count (type
, count
)
2070 if (!isdigit (**type
))
2076 *count
= **type
- '0';
2078 if (isdigit (**type
))
2088 while (isdigit (*p
));
2099 /* result will be initialised here; it will be freed on failure */
2102 do_type (work
, mangled
, result
)
2103 struct work_stuff
*work
;
2104 const char **mangled
;
2111 const char *remembered_type
;
2115 string_init (&decl
);
2116 string_init (result
);
2120 while (success
&& !done
)
2126 /* A pointer type */
2130 if (! (work
-> options
& DMGL_JAVA
))
2131 string_prepend (&decl
, "*");
2134 /* A reference type */
2137 string_prepend (&decl
, "&");
2143 const char *p
= ++(*mangled
);
2145 string_prepend (&decl
, "(");
2146 string_append (&decl
, ")[");
2147 /* Copy anything up until the next underscore (the size of the
2149 while (**mangled
&& **mangled
!= '_')
2151 if (**mangled
== '_')
2153 string_appendn (&decl
, p
, *mangled
- p
);
2154 string_append (&decl
, "]");
2162 /* A back reference to a previously seen type */
2165 if (!get_count (mangled
, &n
) || n
>= work
-> ntypes
)
2171 remembered_type
= work
-> typevec
[n
];
2172 mangled
= &remembered_type
;
2179 if (!STRING_EMPTY (&decl
) && decl
.b
[0] == '*')
2181 string_prepend (&decl
, "(");
2182 string_append (&decl
, ")");
2184 /* After picking off the function args, we expect to either find the
2185 function return type (preceded by an '_') or the end of the
2187 if (!demangle_args (work
, mangled
, &decl
)
2188 || (**mangled
!= '_' && **mangled
!= '\0'))
2192 if (success
&& (**mangled
== '_'))
2204 member
= **mangled
== 'M';
2206 if (!isdigit (**mangled
) && **mangled
!= 't')
2212 string_append (&decl
, ")");
2213 string_prepend (&decl
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
2214 if (isdigit (**mangled
))
2216 n
= consume_count (mangled
);
2217 if (strlen (*mangled
) < n
)
2222 string_prependn (&decl
, *mangled
, n
);
2228 string_init (&temp
);
2229 success
= demangle_template (work
, mangled
, &temp
, NULL
, 1);
2232 string_prependn (&decl
, temp
.b
, temp
.p
- temp
.b
);
2233 string_clear (&temp
);
2238 string_prepend (&decl
, "(");
2241 if (**mangled
== 'C')
2246 if (**mangled
== 'V')
2251 if (*(*mangled
)++ != 'F')
2257 if ((member
&& !demangle_args (work
, mangled
, &decl
))
2258 || **mangled
!= '_')
2264 if (! PRINT_ANSI_QUALIFIERS
)
2270 APPEND_BLANK (&decl
);
2271 string_append (&decl
, "const");
2275 APPEND_BLANK (&decl
);
2276 string_append (&decl
, "volatile");
2287 if ((*mangled)[1] == 'P')
2290 if (PRINT_ANSI_QUALIFIERS
)
2292 if (!STRING_EMPTY (&decl
))
2294 string_prepend (&decl
, " ");
2296 string_prepend (&decl
, "const");
2312 /* A qualified name, such as "Outer::Inner". */
2314 success
= demangle_qualified (work
, mangled
, result
, 0, 1);
2319 /* A template parm. We substitute the corresponding argument. */
2325 idx
= consume_count_with_underscores (mangled
);
2328 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
2329 || consume_count_with_underscores (mangled
) == -1)
2335 if (work
->tmpl_argvec
)
2336 string_append (result
, work
->tmpl_argvec
[idx
]);
2340 sprintf(buf
, "T%d", idx
);
2341 string_append (result
, buf
);
2349 success
= demangle_fund_type (work
, mangled
, result
);
2355 if (!STRING_EMPTY (&decl
))
2357 string_append (result
, " ");
2358 string_appends (result
, &decl
);
2363 string_delete (result
);
2365 string_delete (&decl
);
2369 /* Given a pointer to a type string that represents a fundamental type
2370 argument (int, long, unsigned int, etc) in TYPE, a pointer to the
2371 string in which the demangled output is being built in RESULT, and
2372 the WORK structure, decode the types and add them to the result.
2377 "Sl" => "signed long"
2378 "CUs" => "const unsigned short"
2383 demangle_fund_type (work
, mangled
, result
)
2384 struct work_stuff
*work
;
2385 const char **mangled
;
2391 /* First pick off any type qualifiers. There can be more than one. */
2399 if (PRINT_ANSI_QUALIFIERS
)
2401 APPEND_BLANK (result
);
2402 string_append (result
, "const");
2407 APPEND_BLANK (result
);
2408 string_append (result
, "unsigned");
2410 case 'S': /* signed char only */
2412 APPEND_BLANK (result
);
2413 string_append (result
, "signed");
2417 if (PRINT_ANSI_QUALIFIERS
)
2419 APPEND_BLANK (result
);
2420 string_append (result
, "volatile");
2425 APPEND_BLANK (result
);
2426 string_append (result
, "__complex");
2434 /* Now pick off the fundamental type. There can be only one. */
2443 APPEND_BLANK (result
);
2444 string_append (result
, "void");
2448 APPEND_BLANK (result
);
2449 string_append (result
, "long long");
2453 APPEND_BLANK (result
);
2454 string_append (result
, "long");
2458 APPEND_BLANK (result
);
2459 string_append (result
, "int");
2463 APPEND_BLANK (result
);
2464 string_append (result
, "short");
2468 APPEND_BLANK (result
);
2469 string_append (result
, "bool");
2473 APPEND_BLANK (result
);
2474 string_append (result
, "char");
2478 APPEND_BLANK (result
);
2479 string_append (result
, "wchar_t");
2483 APPEND_BLANK (result
);
2484 string_append (result
, "long double");
2488 APPEND_BLANK (result
);
2489 string_append (result
, "double");
2493 APPEND_BLANK (result
);
2494 string_append (result
, "float");
2498 if (!isdigit (**mangled
))
2504 /* An explicit type, such as "6mytype" or "7integer" */
2515 APPEND_BLANK (result
);
2516 if (!demangle_class_name (work
, mangled
, result
)) {
2522 success
= demangle_template(work
,mangled
, result
, 0, 1);
2532 /* `result' will be initialized in do_type; it will be freed on failure */
2535 do_arg (work
, mangled
, result
)
2536 struct work_stuff
*work
;
2537 const char **mangled
;
2540 const char *start
= *mangled
;
2542 if (!do_type (work
, mangled
, result
))
2548 remember_type (work
, start
, *mangled
- start
);
2554 remember_type (work
, start
, len
)
2555 struct work_stuff
*work
;
2561 if (work
-> ntypes
>= work
-> typevec_size
)
2563 if (work
-> typevec_size
== 0)
2565 work
-> typevec_size
= 3;
2567 = (char **) xmalloc (sizeof (char *) * work
-> typevec_size
);
2571 work
-> typevec_size
*= 2;
2573 = (char **) xrealloc ((char *)work
-> typevec
,
2574 sizeof (char *) * work
-> typevec_size
);
2577 tem
= xmalloc (len
+ 1);
2578 memcpy (tem
, start
, len
);
2580 work
-> typevec
[work
-> ntypes
++] = tem
;
2583 /* Forget the remembered types, but not the type vector itself. */
2587 struct work_stuff
*work
;
2591 while (work
-> ntypes
> 0)
2593 i
= --(work
-> ntypes
);
2594 if (work
-> typevec
[i
] != NULL
)
2596 free (work
-> typevec
[i
]);
2597 work
-> typevec
[i
] = NULL
;
2602 /* Process the argument list part of the signature, after any class spec
2603 has been consumed, as well as the first 'F' character (if any). For
2606 "__als__3fooRT0" => process "RT0"
2607 "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i"
2609 DECLP must be already initialised, usually non-empty. It won't be freed
2612 Note that g++ differs significantly from ARM and lucid style mangling
2613 with regards to references to previously seen types. For example, given
2614 the source fragment:
2618 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
2621 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
2622 void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
2624 g++ produces the names:
2629 while lcc (and presumably other ARM style compilers as well) produces:
2631 foo__FiR3fooT1T2T1T2
2632 __ct__3fooFiR3fooT1T2T1T2
2634 Note that g++ bases it's type numbers starting at zero and counts all
2635 previously seen types, while lucid/ARM bases it's type numbers starting
2636 at one and only considers types after it has seen the 'F' character
2637 indicating the start of the function args. For lucid/ARM style, we
2638 account for this difference by discarding any previously seen types when
2639 we see the 'F' character, and subtracting one from the type number
2645 demangle_args (work
, mangled
, declp
)
2646 struct work_stuff
*work
;
2647 const char **mangled
;
2657 if (PRINT_ARG_TYPES
)
2659 string_append (declp
, "(");
2660 if (**mangled
== '\0')
2662 string_append (declp
, "void");
2666 while (**mangled
!= '_' && **mangled
!= '\0' && **mangled
!= 'e')
2668 if ((**mangled
== 'N') || (**mangled
== 'T'))
2670 temptype
= *(*mangled
)++;
2672 if (temptype
== 'N')
2674 if (!get_count (mangled
, &r
))
2683 if (ARM_DEMANGLING
&& work
-> ntypes
>= 10)
2685 /* If we have 10 or more types we might have more than a 1 digit
2686 index so we'll have to consume the whole count here. This
2687 will lose if the next thing is a type name preceded by a
2688 count but it's impossible to demangle that case properly
2689 anyway. Eg if we already have 12 types is T12Pc "(..., type1,
2690 Pc, ...)" or "(..., type12, char *, ...)" */
2691 if ((t
= consume_count(mangled
)) == 0)
2698 if (!get_count (mangled
, &t
))
2703 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
2707 /* Validate the type index. Protect against illegal indices from
2708 malformed type strings. */
2709 if ((t
< 0) || (t
>= work
-> ntypes
))
2715 tem
= work
-> typevec
[t
];
2716 if (need_comma
&& PRINT_ARG_TYPES
)
2718 string_append (declp
, ", ");
2720 if (!do_arg (work
, &tem
, &arg
))
2724 if (PRINT_ARG_TYPES
)
2726 string_appends (declp
, &arg
);
2728 string_delete (&arg
);
2734 if (need_comma
& PRINT_ARG_TYPES
)
2736 string_append (declp
, ", ");
2738 if (!do_arg (work
, mangled
, &arg
))
2742 if (PRINT_ARG_TYPES
)
2744 string_appends (declp
, &arg
);
2746 string_delete (&arg
);
2751 if (**mangled
== 'e')
2754 if (PRINT_ARG_TYPES
)
2758 string_append (declp
, ",");
2760 string_append (declp
, "...");
2764 if (PRINT_ARG_TYPES
)
2766 string_append (declp
, ")");
2772 demangle_function_name (work
, mangled
, declp
, scan
)
2773 struct work_stuff
*work
;
2774 const char **mangled
;
2783 string_appendn (declp
, (*mangled
), scan
- (*mangled
));
2784 string_need (declp
, 1);
2785 *(declp
-> p
) = '\0';
2787 /* Consume the function name, including the "__" separating the name
2788 from the signature. We are guaranteed that SCAN points to the
2791 (*mangled
) = scan
+ 2;
2793 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
2796 /* See if we have an ARM style constructor or destructor operator.
2797 If so, then just record it, clear the decl, and return.
2798 We can't build the actual constructor/destructor decl until later,
2799 when we recover the class name from the signature. */
2801 if (strcmp (declp
-> b
, "__ct") == 0)
2803 work
-> constructor
+= 1;
2804 string_clear (declp
);
2807 else if (strcmp (declp
-> b
, "__dt") == 0)
2809 work
-> destructor
+= 1;
2810 string_clear (declp
);
2815 if (declp
->p
- declp
->b
>= 3
2816 && declp
->b
[0] == 'o'
2817 && declp
->b
[1] == 'p'
2818 && strchr (cplus_markers
, declp
->b
[2]) != NULL
)
2820 /* see if it's an assignment expression */
2821 if (declp
->p
- declp
->b
>= 10 /* op$assign_ */
2822 && memcmp (declp
->b
+ 3, "assign_", 7) == 0)
2824 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
2826 len
= declp
->p
- declp
->b
- 10;
2827 if (strlen (optable
[i
].in
) == len
2828 && memcmp (optable
[i
].in
, declp
->b
+ 10, len
) == 0)
2830 string_clear (declp
);
2831 string_append (declp
, "operator");
2832 string_append (declp
, optable
[i
].out
);
2833 string_append (declp
, "=");
2840 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
2842 int len
= declp
->p
- declp
->b
- 3;
2843 if (strlen (optable
[i
].in
) == len
2844 && memcmp (optable
[i
].in
, declp
->b
+ 3, len
) == 0)
2846 string_clear (declp
);
2847 string_append (declp
, "operator");
2848 string_append (declp
, optable
[i
].out
);
2854 else if (declp
->p
- declp
->b
>= 5 && memcmp (declp
->b
, "type", 4) == 0
2855 && strchr (cplus_markers
, declp
->b
[4]) != NULL
)
2857 /* type conversion operator */
2859 if (do_type (work
, &tem
, &type
))
2861 string_clear (declp
);
2862 string_append (declp
, "operator ");
2863 string_appends (declp
, &type
);
2864 string_delete (&type
);
2867 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
2868 && declp
->b
[2] == 'o' && declp
->b
[3] == 'p')
2871 /* type conversion operator. */
2873 if (do_type (work
, &tem
, &type
))
2875 string_clear (declp
);
2876 string_append (declp
, "operator ");
2877 string_appends (declp
, &type
);
2878 string_delete (&type
);
2881 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
2882 && declp
->b
[2] >= 'a' && declp
->b
[2] <= 'z'
2883 && declp
->b
[3] >= 'a' && declp
->b
[3] <= 'z')
2885 if (declp
->b
[4] == '\0')
2888 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
2890 if (strlen (optable
[i
].in
) == 2
2891 && memcmp (optable
[i
].in
, declp
->b
+ 2, 2) == 0)
2893 string_clear (declp
);
2894 string_append (declp
, "operator");
2895 string_append (declp
, optable
[i
].out
);
2902 if (declp
->b
[2] == 'a' && declp
->b
[5] == '\0')
2905 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
2907 if (strlen (optable
[i
].in
) == 3
2908 && memcmp (optable
[i
].in
, declp
->b
+ 2, 3) == 0)
2910 string_clear (declp
);
2911 string_append (declp
, "operator");
2912 string_append (declp
, optable
[i
].out
);
2921 /* a mini string-handling package */
2936 s
->p
= s
->b
= xmalloc (n
);
2939 else if (s
->e
- s
->p
< n
)
2944 s
->b
= xrealloc (s
->b
, n
);
2957 s
->b
= s
->e
= s
->p
= NULL
;
2965 s
->b
= s
->p
= s
->e
= NULL
;
2981 return (s
->b
== s
->p
);
2987 string_append (p
, s
)
2992 if (s
== NULL
|| *s
== '\0')
2996 memcpy (p
->p
, s
, n
);
3001 string_appends (p
, s
)
3010 memcpy (p
->p
, s
->b
, n
);
3016 string_appendn (p
, s
, n
)
3024 memcpy (p
->p
, s
, n
);
3030 string_prepend (p
, s
)
3034 if (s
!= NULL
&& *s
!= '\0')
3036 string_prependn (p
, s
, strlen (s
));
3041 string_prepends (p
, s
)
3046 string_prependn (p
, s
->b
, s
->p
- s
->b
);
3051 string_prependn (p
, s
, n
)
3061 for (q
= p
->p
- 1; q
>= p
->b
; q
--)
3065 memcpy (p
->b
, s
, n
);
3070 /* To generate a standalone demangler program for testing purposes,
3071 just compile and link this file with -DMAIN and libiberty.a. When
3072 run, it demangles each command line arg, or each stdin string, and
3073 prints the result on stdout. */
3079 static char *program_name
;
3080 static char *program_version
= VERSION
;
3081 static int flags
= DMGL_PARAMS
| DMGL_ANSI
;
3083 static void demangle_it
PARAMS ((char *));
3084 static void usage
PARAMS ((FILE *, int));
3085 static void fatal
PARAMS ((char *));
3088 demangle_it (mangled_name
)
3093 result
= cplus_demangle (mangled_name
, flags
);
3096 printf ("%s\n", mangled_name
);
3100 printf ("%s\n", result
);
3106 usage (stream
, status
)
3111 Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
3112 [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\
3113 [--help] [--version] [arg...]\n",
3118 #define MBUF_SIZE 512
3119 char mbuffer
[MBUF_SIZE
];
3121 /* Defined in the automatically-generated underscore.c. */
3122 extern int prepends_underscore
;
3124 int strip_underscore
= 0;
3126 static struct option long_options
[] = {
3127 {"strip-underscores", no_argument
, 0, '_'},
3128 {"format", required_argument
, 0, 's'},
3129 {"help", no_argument
, 0, 'h'},
3130 {"java", no_argument
, 0, 'j'},
3131 {"no-strip-underscores", no_argument
, 0, 'n'},
3132 {"version", no_argument
, 0, 'v'},
3133 {0, no_argument
, 0, 0}
3136 /* More 'friendly' abort that prints the line and file.
3137 config.h can #define abort fancy_abort if you like that sort of thing. */
3142 fatal ("Internal gcc abort.");
3153 program_name
= argv
[0];
3155 strip_underscore
= prepends_underscore
;
3157 while ((c
= getopt_long (argc
, argv
, "_ns:j", long_options
, (int *) 0)) != EOF
)
3167 strip_underscore
= 0;
3170 printf ("GNU %s version %s\n", program_name
, program_version
);
3173 strip_underscore
= 1;
3179 if (strcmp (optarg
, "gnu") == 0)
3181 current_demangling_style
= gnu_demangling
;
3183 else if (strcmp (optarg
, "lucid") == 0)
3185 current_demangling_style
= lucid_demangling
;
3187 else if (strcmp (optarg
, "arm") == 0)
3189 current_demangling_style
= arm_demangling
;
3193 fprintf (stderr
, "%s: unknown demangling style `%s'\n",
3194 program_name
, optarg
);
3203 for ( ; optind
< argc
; optind
++)
3205 demangle_it (argv
[optind
]);
3214 /* Try to read a label. */
3215 while (c
!= EOF
&& (isalnum(c
) || c
== '_' || c
== '$' || c
== '.'))
3217 if (i
>= MBUF_SIZE
-1)
3226 if (mbuffer
[0] == '.')
3228 if (strip_underscore
&& mbuffer
[skip_first
] == '_')
3236 result
= cplus_demangle (mbuffer
+ skip_first
, flags
);
3239 if (mbuffer
[0] == '.')
3241 fputs (result
, stdout
);
3245 fputs (mbuffer
, stdout
);
3262 fprintf (stderr
, "%s: %s\n", program_name
, str
);
3273 register char *value
= (char *) malloc (size
);
3275 fatal ("virtual memory exhausted");
3280 xrealloc (ptr
, size
)
3284 register char *value
= (char *) realloc (ptr
, size
);
3286 fatal ("virtual memory exhausted");