1 /* Demangler for GNU C++
2 Copyright 1989, 1991, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
3 Written by James Clark (jjc@jclark.uucp)
4 Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
6 This file is part of the libiberty library.
7 Libiberty is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
12 Libiberty is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public
18 License along with libiberty; see the file COPYING.LIB. If
19 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* This file exports two functions; cplus_mangle_opname and cplus_demangle.
24 This file imports xmalloc and xrealloc, which are like malloc and
25 realloc except that they generate a fatal error if there is no
28 /* This file lives in both GCC and libiberty. When making changes, please
29 try not to break either. */
32 #include <sys/types.h>
41 #undef CURRENT_DEMANGLING_STYLE
42 #define CURRENT_DEMANGLING_STYLE work->options
44 extern char *xmalloc
PARAMS((unsigned));
45 extern char *xrealloc
PARAMS((char *, unsigned));
47 static const char *mystrstr
PARAMS ((const char *, const char *));
53 register const char *p
= s1
;
54 register int len
= strlen (s2
);
56 for (; (p
= strchr (p
, *s2
)) != 0; p
++)
58 if (strncmp (p
, s2
, len
) == 0)
66 /* In order to allow a single demangler executable to demangle strings
67 using various common values of CPLUS_MARKER, as well as any specific
68 one set at compile time, we maintain a string containing all the
69 commonly used ones, and check to see if the marker we are looking for
70 is in that string. CPLUS_MARKER is usually '$' on systems where the
71 assembler can deal with that. Where the assembler can't, it's usually
72 '.' (but on many systems '.' is used for other things). We put the
73 current defined CPLUS_MARKER first (which defaults to '$'), followed
74 by the next most common value, followed by an explicit '$' in case
75 the value of CPLUS_MARKER is not '$'.
77 We could avoid this if we could just get g++ to tell us what the actual
78 cplus marker character is as part of the debug information, perhaps by
79 ensuring that it is the character that terminates the gcc<n>_compiled
80 marker symbol (FIXME). */
82 #if !defined (CPLUS_MARKER)
83 #define CPLUS_MARKER '$'
86 enum demangling_styles current_demangling_style
= gnu_demangling
;
88 static char cplus_markers
[] = { CPLUS_MARKER
, '.', '$', '\0' };
91 set_cplus_marker_for_demangling (ch
)
94 cplus_markers
[0] = ch
;
97 /* Stuff that is shared between sub-routines.
98 Using a shared structure allows cplus_demangle to be reentrant. */
114 int static_type
; /* A static member function */
115 int const_type
; /* A const member function */
116 char **tmpl_argvec
; /* Template function arguments. */
117 int ntmpl_args
; /* The number of template function arguments. */
120 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
121 #define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS)
123 static const struct optable
129 {"nw", " new", DMGL_ANSI
}, /* new (1.92, ansi) */
130 {"dl", " delete", DMGL_ANSI
}, /* new (1.92, ansi) */
131 {"new", " new", 0}, /* old (1.91, and 1.x) */
132 {"delete", " delete", 0}, /* old (1.91, and 1.x) */
133 {"vn", " new []", DMGL_ANSI
}, /* GNU, pending ansi */
134 {"vd", " delete []", DMGL_ANSI
}, /* GNU, pending ansi */
135 {"as", "=", DMGL_ANSI
}, /* ansi */
136 {"ne", "!=", DMGL_ANSI
}, /* old, ansi */
137 {"eq", "==", DMGL_ANSI
}, /* old, ansi */
138 {"ge", ">=", DMGL_ANSI
}, /* old, ansi */
139 {"gt", ">", DMGL_ANSI
}, /* old, ansi */
140 {"le", "<=", DMGL_ANSI
}, /* old, ansi */
141 {"lt", "<", DMGL_ANSI
}, /* old, ansi */
142 {"plus", "+", 0}, /* old */
143 {"pl", "+", DMGL_ANSI
}, /* ansi */
144 {"apl", "+=", DMGL_ANSI
}, /* ansi */
145 {"minus", "-", 0}, /* old */
146 {"mi", "-", DMGL_ANSI
}, /* ansi */
147 {"ami", "-=", DMGL_ANSI
}, /* ansi */
148 {"mult", "*", 0}, /* old */
149 {"ml", "*", DMGL_ANSI
}, /* ansi */
150 {"amu", "*=", DMGL_ANSI
}, /* ansi (ARM/Lucid) */
151 {"aml", "*=", DMGL_ANSI
}, /* ansi (GNU/g++) */
152 {"convert", "+", 0}, /* old (unary +) */
153 {"negate", "-", 0}, /* old (unary -) */
154 {"trunc_mod", "%", 0}, /* old */
155 {"md", "%", DMGL_ANSI
}, /* ansi */
156 {"amd", "%=", DMGL_ANSI
}, /* ansi */
157 {"trunc_div", "/", 0}, /* old */
158 {"dv", "/", DMGL_ANSI
}, /* ansi */
159 {"adv", "/=", DMGL_ANSI
}, /* ansi */
160 {"truth_andif", "&&", 0}, /* old */
161 {"aa", "&&", DMGL_ANSI
}, /* ansi */
162 {"truth_orif", "||", 0}, /* old */
163 {"oo", "||", DMGL_ANSI
}, /* ansi */
164 {"truth_not", "!", 0}, /* old */
165 {"nt", "!", DMGL_ANSI
}, /* ansi */
166 {"postincrement","++", 0}, /* old */
167 {"pp", "++", DMGL_ANSI
}, /* ansi */
168 {"postdecrement","--", 0}, /* old */
169 {"mm", "--", DMGL_ANSI
}, /* ansi */
170 {"bit_ior", "|", 0}, /* old */
171 {"or", "|", DMGL_ANSI
}, /* ansi */
172 {"aor", "|=", DMGL_ANSI
}, /* ansi */
173 {"bit_xor", "^", 0}, /* old */
174 {"er", "^", DMGL_ANSI
}, /* ansi */
175 {"aer", "^=", DMGL_ANSI
}, /* ansi */
176 {"bit_and", "&", 0}, /* old */
177 {"ad", "&", DMGL_ANSI
}, /* ansi */
178 {"aad", "&=", DMGL_ANSI
}, /* ansi */
179 {"bit_not", "~", 0}, /* old */
180 {"co", "~", DMGL_ANSI
}, /* ansi */
181 {"call", "()", 0}, /* old */
182 {"cl", "()", DMGL_ANSI
}, /* ansi */
183 {"alshift", "<<", 0}, /* old */
184 {"ls", "<<", DMGL_ANSI
}, /* ansi */
185 {"als", "<<=", DMGL_ANSI
}, /* ansi */
186 {"arshift", ">>", 0}, /* old */
187 {"rs", ">>", DMGL_ANSI
}, /* ansi */
188 {"ars", ">>=", DMGL_ANSI
}, /* ansi */
189 {"component", "->", 0}, /* old */
190 {"pt", "->", DMGL_ANSI
}, /* ansi; Lucid C++ form */
191 {"rf", "->", DMGL_ANSI
}, /* ansi; ARM/GNU form */
192 {"indirect", "*", 0}, /* old */
193 {"method_call", "->()", 0}, /* old */
194 {"addr", "&", 0}, /* old (unary &) */
195 {"array", "[]", 0}, /* old */
196 {"vc", "[]", DMGL_ANSI
}, /* ansi */
197 {"compound", ", ", 0}, /* old */
198 {"cm", ", ", DMGL_ANSI
}, /* ansi */
199 {"cond", "?:", 0}, /* old */
200 {"cn", "?:", DMGL_ANSI
}, /* pseudo-ansi */
201 {"max", ">?", 0}, /* old */
202 {"mx", ">?", DMGL_ANSI
}, /* pseudo-ansi */
203 {"min", "<?", 0}, /* old */
204 {"mn", "<?", DMGL_ANSI
}, /* pseudo-ansi */
205 {"nop", "", 0}, /* old (for operator=) */
206 {"rm", "->*", DMGL_ANSI
}, /* ansi */
207 {"sz", "sizeof ", DMGL_ANSI
} /* pseudo-ansi */
211 typedef struct string
/* Beware: these aren't required to be */
212 { /* '\0' terminated. */
213 char *b
; /* pointer to start of string */
214 char *p
; /* pointer after last character */
215 char *e
; /* pointer after end of allocated space */
218 #define STRING_EMPTY(str) ((str) -> b == (str) -> p)
219 #define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
220 string_prepend(str, " ");}
221 #define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
222 string_append(str, " ");}
223 #define LEN_STRING(str) ( (STRING_EMPTY(str))?0:((str)->p - (str)->b))
225 #define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */
226 #define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */
228 /* Prototypes for local functions */
231 mop_up
PARAMS ((struct work_stuff
*, string
*, int));
234 squangle_mop_up
PARAMS ((struct work_stuff
*));
238 demangle_method_args
PARAMS ((struct work_stuff
*, const char **, string
*));
242 internal_cplus_demangle
PARAMS ((struct work_stuff
*, const char *, int));
245 demangle_template_template_parm
PARAMS ((struct work_stuff
*work
,
246 const char **, string
*));
249 demangle_template
PARAMS ((struct work_stuff
*work
, const char **, string
*,
253 arm_pt
PARAMS ((struct work_stuff
*, const char *, int, const char **,
257 demangle_arm_pt
PARAMS ((struct work_stuff
*, const char **, int, string
*));
260 demangle_class_name
PARAMS ((struct work_stuff
*, const char **, string
*));
263 demangle_qualified
PARAMS ((struct work_stuff
*, const char **, string
*,
267 demangle_class
PARAMS ((struct work_stuff
*, const char **, string
*));
270 demangle_fund_type
PARAMS ((struct work_stuff
*, const char **, string
*));
273 demangle_signature
PARAMS ((struct work_stuff
*, const char **, string
*));
276 demangle_prefix
PARAMS ((struct work_stuff
*, const char **, string
*));
279 gnu_special
PARAMS ((struct work_stuff
*, const char **, string
*));
282 arm_special
PARAMS ((const char **, string
*));
285 string_need
PARAMS ((string
*, int));
288 string_delete
PARAMS ((string
*));
291 string_init
PARAMS ((string
*));
294 string_clear
PARAMS ((string
*));
298 string_empty
PARAMS ((string
*));
302 string_append
PARAMS ((string
*, const char *));
305 string_appends
PARAMS ((string
*, string
*));
308 string_appendn
PARAMS ((string
*, const char *, int));
311 string_prepend
PARAMS ((string
*, const char *));
314 string_prependn
PARAMS ((string
*, const char *, int));
317 get_count
PARAMS ((const char **, int *));
320 consume_count
PARAMS ((const char **));
323 consume_count_with_underscores
PARAMS ((const char**));
326 demangle_args
PARAMS ((struct work_stuff
*, const char **, string
*));
329 do_type
PARAMS ((struct work_stuff
*, const char **, string
*));
332 do_arg
PARAMS ((struct work_stuff
*, const char **, string
*));
335 demangle_function_name
PARAMS ((struct work_stuff
*, const char **, string
*,
339 remember_type
PARAMS ((struct work_stuff
*, const char *, int));
342 remember_Btype
PARAMS ((struct work_stuff
*, const char *, int, int));
345 register_Btype
PARAMS ((struct work_stuff
*));
348 remember_Ktype
PARAMS ((struct work_stuff
*, const char *, int));
351 forget_types
PARAMS ((struct work_stuff
*));
354 forget_B_and_K_types
PARAMS ((struct work_stuff
*));
357 string_prepends
PARAMS ((string
*, string
*));
360 demangle_template_value_parm
PARAMS ((struct work_stuff
*,
361 const char**, string
*));
363 /* Translate count to integer, consuming tokens in the process.
364 Conversion terminates on the first non-digit character.
365 Trying to consume something that isn't a count results in
366 no consumption of input and a return of 0. */
374 while (isdigit (**type
))
377 count
+= **type
- '0';
384 /* Like consume_count, but for counts that are preceded and followed
385 by '_' if they are greater than 10. Also, -1 is returned for
386 failure, since 0 can be a valid value. */
389 consume_count_with_underscores (mangled
)
390 const char **mangled
;
394 if (**mangled
== '_')
397 if (!isdigit (**mangled
))
400 idx
= consume_count (mangled
);
401 if (**mangled
!= '_')
402 /* The trailing underscore was missing. */
409 if (**mangled
< '0' || **mangled
> '9')
412 idx
= **mangled
- '0';
420 cplus_demangle_opname (opname
, result
, options
)
425 int len
, i
, len1
, ret
;
427 struct work_stuff work
[1];
430 len
= strlen(opname
);
433 work
->options
= options
;
435 if (opname
[0] == '_' && opname
[1] == '_'
436 && opname
[2] == 'o' && opname
[3] == 'p')
439 /* type conversion operator. */
441 if (do_type (work
, &tem
, &type
))
443 strcat (result
, "operator ");
444 strncat (result
, type
.b
, type
.p
- type
.b
);
445 string_delete (&type
);
449 else if (opname
[0] == '_' && opname
[1] == '_'
450 && opname
[2] >= 'a' && opname
[2] <= 'z'
451 && opname
[3] >= 'a' && opname
[3] <= 'z')
453 if (opname
[4] == '\0')
456 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
458 if (strlen (optable
[i
].in
) == 2
459 && memcmp (optable
[i
].in
, opname
+ 2, 2) == 0)
461 strcat (result
, "operator");
462 strcat (result
, optable
[i
].out
);
470 if (opname
[2] == 'a' && opname
[5] == '\0')
473 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
475 if (strlen (optable
[i
].in
) == 3
476 && memcmp (optable
[i
].in
, opname
+ 2, 3) == 0)
478 strcat (result
, "operator");
479 strcat (result
, optable
[i
].out
);
490 && strchr (cplus_markers
, opname
[2]) != NULL
)
492 /* see if it's an assignment expression */
493 if (len
>= 10 /* op$assign_ */
494 && memcmp (opname
+ 3, "assign_", 7) == 0)
496 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
499 if (strlen (optable
[i
].in
) == len1
500 && memcmp (optable
[i
].in
, opname
+ 10, len1
) == 0)
502 strcat (result
, "operator");
503 strcat (result
, optable
[i
].out
);
504 strcat (result
, "=");
512 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
515 if (strlen (optable
[i
].in
) == len1
516 && memcmp (optable
[i
].in
, opname
+ 3, len1
) == 0)
518 strcat (result
, "operator");
519 strcat (result
, optable
[i
].out
);
526 else if (len
>= 5 && memcmp (opname
, "type", 4) == 0
527 && strchr (cplus_markers
, opname
[4]) != NULL
)
529 /* type conversion operator */
531 if (do_type (work
, &tem
, &type
))
533 strcat (result
, "operator ");
534 strncat (result
, type
.b
, type
.p
- type
.b
);
535 string_delete (&type
);
539 squangle_mop_up (work
);
543 /* Takes operator name as e.g. "++" and returns mangled
544 operator name (e.g. "postincrement_expr"), or NULL if not found.
546 If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
547 if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */
550 cplus_mangle_opname (opname
, options
)
557 len
= strlen (opname
);
558 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
560 if (strlen (optable
[i
].out
) == len
561 && (options
& DMGL_ANSI
) == (optable
[i
].flags
& DMGL_ANSI
)
562 && memcmp (optable
[i
].out
, opname
, len
) == 0)
563 return optable
[i
].in
;
568 /* char *cplus_demangle (const char *mangled, int options)
570 If MANGLED is a mangled function name produced by GNU C++, then
571 a pointer to a malloced string giving a C++ representation
572 of the name will be returned; otherwise NULL will be returned.
573 It is the caller's responsibility to free the string which
576 The OPTIONS arg may contain one or more of the following bits:
578 DMGL_ANSI ANSI qualifiers such as `const' and `void' are
580 DMGL_PARAMS Function parameters are included.
584 cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)"
585 cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
586 cplus_demangle ("foo__1Ai", 0) => "A::foo"
588 cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)"
589 cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
590 cplus_demangle ("foo__1Afe", 0) => "A::foo"
592 Note that any leading underscores, or other such characters prepended by
593 the compilation system, are presumed to have already been stripped from
597 cplus_demangle (mangled
, options
)
602 struct work_stuff work
[1];
603 memset ((char *) work
, 0, sizeof (work
));
604 work
-> options
= options
;
605 if ((work
-> options
& DMGL_STYLE_MASK
) == 0)
606 work
-> options
|= (int) current_demangling_style
& DMGL_STYLE_MASK
;
608 ret
= internal_cplus_demangle (work
, mangled
, options
);
609 squangle_mop_up (work
);
614 /* This function performs most of what cplus_demangle use to do, but
615 to be able to demangle a name with a B, K or n code, we need to
616 have a longer term memory of what types have been seen. The original
617 now intializes and cleans up the squangle code info, while internal
618 calls go directly to this routine to avoid resetting that info. */
621 internal_cplus_demangle (work
, mangled
, options
)
622 struct work_stuff
*work
;
629 char *demangled
= NULL
;
631 s1
= work
->constructor
;
632 s2
= work
->destructor
;
633 s3
= work
->static_type
;
634 s4
= work
->const_type
;
635 work
->constructor
= work
->destructor
= 0;
636 work
->static_type
= work
->const_type
= 0;
638 if ((mangled
!= NULL
) && (*mangled
!= '\0'))
642 /* First check to see if gnu style demangling is active and if the
643 string to be demangled contains a CPLUS_MARKER. If so, attempt to
644 recognize one of the gnu special forms rather than looking for a
645 standard prefix. In particular, don't worry about whether there
646 is a "__" string in the mangled string. Consider "_$_5__foo" for
649 if ((AUTO_DEMANGLING
|| GNU_DEMANGLING
))
651 success
= gnu_special (work
, &mangled
, &decl
);
655 success
= demangle_prefix (work
, &mangled
, &decl
);
657 if (success
&& (*mangled
!= '\0'))
659 success
= demangle_signature (work
, &mangled
, &decl
);
661 if (work
->constructor
== 2)
663 string_prepend (&decl
, "global constructors keyed to ");
664 work
->constructor
= 0;
666 else if (work
->destructor
== 2)
668 string_prepend (&decl
, "global destructors keyed to ");
669 work
->destructor
= 0;
671 demangled
= mop_up (work
, &decl
, success
);
673 work
->constructor
= s1
;
674 work
->destructor
= s2
;
675 work
->static_type
= s3
;
676 work
->const_type
= s4
;
681 /* Clear out and squangling related storage */
683 squangle_mop_up (work
)
684 struct work_stuff
*work
;
686 /* clean up the B and K type mangling types. */
687 forget_B_and_K_types (work
);
688 if (work
-> btypevec
!= NULL
)
690 free ((char *) work
-> btypevec
);
692 if (work
-> ktypevec
!= NULL
)
694 free ((char *) work
-> ktypevec
);
698 /* Clear out any mangled storage */
701 mop_up (work
, declp
, success
)
702 struct work_stuff
*work
;
706 char *demangled
= NULL
;
708 /* Discard the remembered types, if any. */
711 if (work
-> typevec
!= NULL
)
713 free ((char *) work
-> typevec
);
714 work
-> typevec
= NULL
;
716 if (work
->tmpl_argvec
)
720 for (i
= 0; i
< work
->ntmpl_args
; i
++)
721 if (work
->tmpl_argvec
[i
])
722 free ((char*) work
->tmpl_argvec
[i
]);
724 free ((char*) work
->tmpl_argvec
);
725 work
->tmpl_argvec
= NULL
;
728 /* If demangling was successful, ensure that the demangled string is null
729 terminated and return it. Otherwise, free the demangling decl. */
733 string_delete (declp
);
737 string_appendn (declp
, "", 1);
738 demangled
= declp
-> b
;
747 demangle_signature -- demangle the signature part of a mangled name
752 demangle_signature (struct work_stuff *work, const char **mangled,
757 Consume and demangle the signature portion of the mangled name.
759 DECLP is the string where demangled output is being built. At
760 entry it contains the demangled root name from the mangled name
761 prefix. I.E. either a demangled operator name or the root function
762 name. In some special cases, it may contain nothing.
764 *MANGLED points to the current unconsumed location in the mangled
765 name. As tokens are consumed and demangling is performed, the
766 pointer is updated to continuously point at the next token to
769 Demangling GNU style mangled names is nasty because there is no
770 explicit token that marks the start of the outermost function
774 demangle_signature (work
, mangled
, declp
)
775 struct work_stuff
*work
;
776 const char **mangled
;
782 int expect_return_type
= 0;
783 const char *oldmangled
= NULL
;
787 while (success
&& (**mangled
!= '\0'))
792 oldmangled
= *mangled
;
793 success
= demangle_qualified (work
, mangled
, declp
, 1, 0);
796 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
798 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
806 oldmangled
= *mangled
;
807 success
= demangle_qualified (work
, mangled
, declp
, 1, 0);
808 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
816 /* Static member function */
817 if (oldmangled
== NULL
)
819 oldmangled
= *mangled
;
822 work
-> static_type
= 1;
826 /* a const member function */
827 if (oldmangled
== NULL
)
829 oldmangled
= *mangled
;
832 work
-> const_type
= 1;
835 case '0': case '1': case '2': case '3': case '4':
836 case '5': case '6': case '7': case '8': case '9':
837 if (oldmangled
== NULL
)
839 oldmangled
= *mangled
;
841 success
= demangle_class (work
, mangled
, declp
);
844 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
846 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
855 /* ARM style demangling includes a specific 'F' character after
856 the class name. For GNU style, it is just implied. So we can
857 safely just consume any 'F' at this point and be compatible
858 with either style. */
864 /* For lucid/ARM style we have to forget any types we might
865 have remembered up to this point, since they were not argument
866 types. GNU style considers all types seen as available for
867 back references. See comment in demangle_args() */
869 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
873 success
= demangle_args (work
, mangled
, declp
);
878 string_init(&trawname
);
880 if (oldmangled
== NULL
)
882 oldmangled
= *mangled
;
884 success
= demangle_template (work
, mangled
, &tname
, &trawname
, 1);
887 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
889 string_append(&tname
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
890 string_prepends(declp
, &tname
);
891 if (work
-> destructor
& 1)
893 string_prepend (&trawname
, "~");
894 string_appends (declp
, &trawname
);
895 work
->destructor
-= 1;
897 if ((work
->constructor
& 1) || (work
->destructor
& 1))
899 string_appends (declp
, &trawname
);
900 work
->constructor
-= 1;
902 string_delete(&trawname
);
903 string_delete(&tname
);
909 if (GNU_DEMANGLING
&& expect_return_type
)
911 /* Read the return type. */
913 string_init (&return_type
);
916 success
= do_type (work
, mangled
, &return_type
);
917 APPEND_BLANK (&return_type
);
919 string_prepends (declp
, &return_type
);
920 string_delete (&return_type
);
924 /* At the outermost level, we cannot have a return type specified,
925 so if we run into another '_' at this point we are dealing with
926 a mangled name that is either bogus, or has been mangled by
927 some algorithm we don't know how to deal with. So just
928 reject the entire demangling. */
935 /* A G++ template function. Read the template arguments. */
936 success
= demangle_template (work
, mangled
, declp
, 0, 0);
937 if (!(work
->constructor
& 1))
938 expect_return_type
= 1;
947 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
949 /* Assume we have stumbled onto the first outermost function
950 argument token, and start processing args. */
952 success
= demangle_args (work
, mangled
, declp
);
956 /* Non-GNU demanglers use a specific token to mark the start
957 of the outermost function argument tokens. Typically 'F',
958 for ARM-demangling, for example. So if we find something
959 we are not prepared for, it must be an error. */
965 if (AUTO_DEMANGLING || GNU_DEMANGLING)
968 if (success
&& expect_func
)
971 success
= demangle_args (work
, mangled
, declp
);
972 /* Since template include the mangling of their return types,
973 we must set expect_func to 0 so that we don't try do
974 demangle more arguments the next time we get here. */
979 if (success
&& !func_done
)
981 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
983 /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
984 bar__3fooi is 'foo::bar(int)'. We get here when we find the
985 first case, and need to ensure that the '(void)' gets added to
986 the current declp. Note that with ARM, the first case
987 represents the name of a static data member 'foo::bar',
988 which is in the current declp, so we leave it alone. */
989 success
= demangle_args (work
, mangled
, declp
);
992 if (success
&& work
-> static_type
&& PRINT_ARG_TYPES
)
994 string_append (declp
, " static");
996 if (success
&& work
-> const_type
&& PRINT_ARG_TYPES
)
998 string_append (declp
, " const");
1006 demangle_method_args (work
, mangled
, declp
)
1007 struct work_stuff
*work
;
1008 const char **mangled
;
1013 if (work
-> static_type
)
1015 string_append (declp
, *mangled
+ 1);
1016 *mangled
+= strlen (*mangled
);
1021 success
= demangle_args (work
, mangled
, declp
);
1029 demangle_template_template_parm (work
, mangled
, tname
)
1030 struct work_stuff
*work
;
1031 const char **mangled
;
1040 string_append (tname
, "template <");
1041 /* get size of template parameter list */
1042 if (get_count (mangled
, &r
))
1044 for (i
= 0; i
< r
; i
++)
1048 string_append (tname
, ", ");
1051 /* Z for type parameters */
1052 if (**mangled
== 'Z')
1055 string_append (tname
, "class");
1057 /* z for template parameters */
1058 else if (**mangled
== 'z')
1062 demangle_template_template_parm (work
, mangled
, tname
);
1070 /* temp is initialized in do_type */
1071 success
= do_type (work
, mangled
, &temp
);
1074 string_appends (tname
, &temp
);
1076 string_delete(&temp
);
1086 if (tname
->p
[-1] == '>')
1087 string_append (tname
, " ");
1088 string_append (tname
, "> class");
1093 demangle_integral_value (work
, mangled
, s
)
1094 struct work_stuff
*work
;
1095 const char** mangled
;
1100 if (**mangled
== 'E')
1102 int need_operator
= 0;
1105 string_appendn (s
, "(", 1);
1107 while (success
&& **mangled
!= 'W' && **mangled
!= '\0')
1116 len
= strlen (*mangled
);
1119 i
< sizeof (optable
) / sizeof (optable
[0]);
1122 size_t l
= strlen (optable
[i
].in
);
1125 && memcmp (optable
[i
].in
, *mangled
, l
) == 0)
1127 string_appendn (s
, " ", 1);
1128 string_append (s
, optable
[i
].out
);
1129 string_appendn (s
, " ", 1);
1142 success
= demangle_template_value_parm (work
, mangled
, s
);
1145 if (**mangled
!= 'W')
1149 string_appendn (s
, ")", 1);
1153 else if (**mangled
== 'Q' || **mangled
== 'K')
1154 success
= demangle_qualified (work
, mangled
, s
, 0, 1);
1159 if (**mangled
== 'm')
1161 string_appendn (s
, "-", 1);
1164 while (isdigit (**mangled
))
1166 string_appendn (s
, *mangled
, 1);
1176 demangle_template_value_parm (work
, mangled
, s
)
1177 struct work_stuff
*work
;
1178 const char **mangled
;
1181 const char *old_p
= *mangled
;
1184 int is_integral
= 0;
1190 while (*old_p
&& !done
)
1197 done
= is_pointer
= 1;
1199 case 'C': /* const */
1200 case 'S': /* explicitly signed [char] */
1201 case 'U': /* unsigned */
1202 case 'V': /* volatile */
1203 case 'F': /* function */
1204 case 'M': /* member function */
1206 case 'J': /* complex */
1209 case 'E': /* expression */
1210 case 'Q': /* qualified name */
1211 case 'K': /* qualified name */
1212 done
= is_integral
= 1;
1214 case 'B': /* squangled name */
1215 done
= is_integral
= 1;
1217 case 'T': /* remembered type */
1220 case 'v': /* void */
1223 case 'x': /* long long */
1224 case 'l': /* long */
1226 case 's': /* short */
1227 case 'w': /* wchar_t */
1228 done
= is_integral
= 1;
1230 case 'b': /* bool */
1233 case 'c': /* char */
1236 case 'r': /* long double */
1237 case 'd': /* double */
1238 case 'f': /* float */
1242 /* it's probably user defined type, let's assume
1243 it's integral, it seems hard to figure out
1244 what it really is */
1245 done
= is_integral
= 1;
1248 if (**mangled
== 'Y')
1250 /* The next argument is a template parameter. */
1254 idx
= consume_count_with_underscores (mangled
);
1256 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
1257 || consume_count_with_underscores (mangled
) == -1)
1259 if (work
->tmpl_argvec
)
1260 string_append (s
, work
->tmpl_argvec
[idx
]);
1264 sprintf(buf
, "T%d", idx
);
1265 string_append (s
, buf
);
1268 else if (is_integral
)
1269 success
= demangle_integral_value (work
, mangled
, s
);
1274 if (**mangled
== 'm')
1276 string_appendn (s
, "-", 1);
1279 string_appendn (s
, "'", 1);
1280 val
= consume_count(mangled
);
1285 string_appendn (s
, &tmp
[0], 1);
1286 string_appendn (s
, "'", 1);
1290 int val
= consume_count (mangled
);
1292 string_appendn (s
, "false", 5);
1294 string_appendn (s
, "true", 4);
1300 if (**mangled
== 'm')
1302 string_appendn (s
, "-", 1);
1305 while (isdigit (**mangled
))
1307 string_appendn (s
, *mangled
, 1);
1310 if (**mangled
== '.') /* fraction */
1312 string_appendn (s
, ".", 1);
1314 while (isdigit (**mangled
))
1316 string_appendn (s
, *mangled
, 1);
1320 if (**mangled
== 'e') /* exponent */
1322 string_appendn (s
, "e", 1);
1324 while (isdigit (**mangled
))
1326 string_appendn (s
, *mangled
, 1);
1331 else if (is_pointer
)
1333 int symbol_len
= consume_count (mangled
);
1334 if (symbol_len
== 0)
1336 if (symbol_len
== 0)
1337 string_appendn (s
, "0", 1);
1340 char *p
= xmalloc (symbol_len
+ 1), *q
;
1341 strncpy (p
, *mangled
, symbol_len
);
1342 p
[symbol_len
] = '\0';
1343 q
= internal_cplus_demangle (work
, p
, work
->options
);
1344 string_appendn (s
, "&", 1);
1347 string_append (s
, q
);
1351 string_append (s
, p
);
1354 *mangled
+= symbol_len
;
1361 demangle_template (work
, mangled
, tname
, trawname
, is_type
)
1362 struct work_stuff
*work
;
1363 const char **mangled
;
1373 int is_java_array
= 0;
1380 /* get template name */
1381 if (**mangled
== 'z')
1387 idx
= consume_count_with_underscores (mangled
);
1389 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
1390 || consume_count_with_underscores (mangled
) == -1)
1394 if (work
->tmpl_argvec
)
1396 string_append (tname
, work
->tmpl_argvec
[idx
]);
1398 string_append (trawname
, work
->tmpl_argvec
[idx
]);
1403 sprintf(buf
, "T%d", idx
);
1404 string_append (tname
, buf
);
1406 string_append (trawname
, work
->tmpl_argvec
[idx
]);
1411 if ((r
= consume_count (mangled
)) == 0 || strlen (*mangled
) < r
)
1416 string_appendn (trawname
, *mangled
, r
);
1417 is_java_array
= (work
-> options
& DMGL_JAVA
)
1418 && strncmp (*mangled
, "JArray1Z", 8) == 0;
1419 if (! is_java_array
)
1421 string_appendn (tname
, *mangled
, r
);
1427 string_append (tname
, "<");
1428 /* get size of template parameter list */
1429 if (!get_count (mangled
, &r
))
1435 /* Create an array for saving the template argument values. */
1436 work
->tmpl_argvec
= (char**) xmalloc (r
* sizeof (char *));
1437 work
->ntmpl_args
= r
;
1438 for (i
= 0; i
< r
; i
++)
1439 work
->tmpl_argvec
[i
] = 0;
1441 for (i
= 0; i
< r
; i
++)
1445 string_append (tname
, ", ");
1447 /* Z for type parameters */
1448 if (**mangled
== 'Z')
1451 /* temp is initialized in do_type */
1452 success
= do_type (work
, mangled
, &temp
);
1455 string_appends (tname
, &temp
);
1459 /* Save the template argument. */
1460 int len
= temp
.p
- temp
.b
;
1461 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1462 memcpy (work
->tmpl_argvec
[i
], temp
.b
, len
);
1463 work
->tmpl_argvec
[i
][len
] = '\0';
1466 string_delete(&temp
);
1472 /* z for template parameters */
1473 else if (**mangled
== 'z')
1477 success
= demangle_template_template_parm (work
, mangled
, tname
);
1480 && (r2
= consume_count (mangled
)) > 0 && strlen (*mangled
) >= r2
)
1482 string_append (tname
, " ");
1483 string_appendn (tname
, *mangled
, r2
);
1486 /* Save the template argument. */
1488 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1489 memcpy (work
->tmpl_argvec
[i
], *mangled
, len
);
1490 work
->tmpl_argvec
[i
][len
] = '\0';
1504 /* otherwise, value parameter */
1506 /* temp is initialized in do_type */
1507 success
= do_type (work
, mangled
, &temp
);
1511 string_appends (s, &temp);
1514 string_delete(&temp
);
1520 string_append (s, "=");
1531 success
= demangle_template_value_parm (work
, mangled
, s
);
1543 int len
= s
->p
- s
->b
;
1544 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1545 memcpy (work
->tmpl_argvec
[i
], s
->b
, len
);
1546 work
->tmpl_argvec
[i
][len
] = '\0';
1548 string_appends (tname
, s
);
1556 string_append (tname
, "[]");
1560 if (tname
->p
[-1] == '>')
1561 string_append (tname
, " ");
1562 string_append (tname
, ">");
1566 if (work -> static_type)
1568 string_append (declp, *mangled + 1);
1569 *mangled += strlen (*mangled);
1574 success = demangle_args (work, mangled, declp);
1582 arm_pt (work
, mangled
, n
, anchor
, args
)
1583 struct work_stuff
*work
;
1584 const char *mangled
;
1586 const char **anchor
, **args
;
1589 if (ARM_DEMANGLING
&& (*anchor
= mystrstr (mangled
, "__pt__")))
1592 *args
= *anchor
+ 6;
1593 len
= consume_count (args
);
1594 if (*args
+ len
== mangled
+ n
&& **args
== '_')
1604 demangle_arm_pt (work
, mangled
, n
, declp
)
1605 struct work_stuff
*work
;
1606 const char **mangled
;
1612 const char *e
= *mangled
+ n
;
1615 if (arm_pt (work
, *mangled
, n
, &p
, &args
))
1619 string_appendn (declp
, *mangled
, p
- *mangled
);
1620 string_append (declp
, "<");
1621 /* should do error checking here */
1623 string_clear (&arg
);
1624 do_type (work
, &args
, &arg
);
1625 string_appends (declp
, &arg
);
1626 string_append (declp
, ",");
1628 string_delete (&arg
);
1630 string_append (declp
, ">");
1634 string_appendn (declp
, *mangled
, n
);
1640 demangle_class_name (work
, mangled
, declp
)
1641 struct work_stuff
*work
;
1642 const char **mangled
;
1648 n
= consume_count (mangled
);
1649 if (strlen (*mangled
) >= n
)
1651 demangle_arm_pt (work
, mangled
, n
, declp
);
1662 demangle_class -- demangle a mangled class sequence
1667 demangle_class (struct work_stuff *work, const char **mangled,
1672 DECLP points to the buffer into which demangling is being done.
1674 *MANGLED points to the current token to be demangled. On input,
1675 it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
1676 On exit, it points to the next token after the mangled class on
1677 success, or the first unconsumed token on failure.
1679 If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
1680 we are demangling a constructor or destructor. In this case
1681 we prepend "class::class" or "class::~class" to DECLP.
1683 Otherwise, we prepend "class::" to the current DECLP.
1685 Reset the constructor/destructor flags once they have been
1686 "consumed". This allows demangle_class to be called later during
1687 the same demangling, to do normal class demangling.
1689 Returns 1 if demangling is successful, 0 otherwise.
1694 demangle_class (work
, mangled
, declp
)
1695 struct work_stuff
*work
;
1696 const char **mangled
;
1703 string_init (&class_name
);
1704 btype
= register_Btype (work
);
1705 if (demangle_class_name (work
, mangled
, &class_name
))
1707 if ((work
->constructor
& 1) || (work
->destructor
& 1))
1709 string_prepends (declp
, &class_name
);
1710 if (work
-> destructor
& 1)
1712 string_prepend (declp
, "~");
1713 work
-> destructor
-= 1;
1717 work
-> constructor
-= 1;
1720 remember_Ktype (work
, class_name
.b
, LEN_STRING(&class_name
));
1721 remember_Btype (work
, class_name
.b
, LEN_STRING(&class_name
), btype
);
1722 string_prepend (declp
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
1723 string_prepends (declp
, &class_name
);
1726 string_delete (&class_name
);
1734 demangle_prefix -- consume the mangled name prefix and find signature
1739 demangle_prefix (struct work_stuff *work, const char **mangled,
1744 Consume and demangle the prefix of the mangled name.
1746 DECLP points to the string buffer into which demangled output is
1747 placed. On entry, the buffer is empty. On exit it contains
1748 the root function name, the demangled operator name, or in some
1749 special cases either nothing or the completely demangled result.
1751 MANGLED points to the current pointer into the mangled name. As each
1752 token of the mangled name is consumed, it is updated. Upon entry
1753 the current mangled name pointer points to the first character of
1754 the mangled name. Upon exit, it should point to the first character
1755 of the signature if demangling was successful, or to the first
1756 unconsumed character if demangling of the prefix was unsuccessful.
1758 Returns 1 on success, 0 otherwise.
1762 demangle_prefix (work
, mangled
, declp
)
1763 struct work_stuff
*work
;
1764 const char **mangled
;
1771 if (strlen(*mangled
) >= 11 && strncmp(*mangled
, "_GLOBAL_", 8) == 0)
1773 char *marker
= strchr (cplus_markers
, (*mangled
)[8]);
1774 if (marker
!= NULL
&& *marker
== (*mangled
)[10])
1776 if ((*mangled
)[9] == 'D')
1778 /* it's a GNU global destructor to be executed at program exit */
1780 work
->destructor
= 2;
1781 if (gnu_special (work
, mangled
, declp
))
1784 else if ((*mangled
)[9] == 'I')
1786 /* it's a GNU global constructor to be executed at program init */
1788 work
->constructor
= 2;
1789 if (gnu_special (work
, mangled
, declp
))
1794 else if (ARM_DEMANGLING
&& strncmp(*mangled
, "__std__", 7) == 0)
1796 /* it's a ARM global destructor to be executed at program exit */
1798 work
->destructor
= 2;
1800 else if (ARM_DEMANGLING
&& strncmp(*mangled
, "__sti__", 7) == 0)
1802 /* it's a ARM global constructor to be executed at program initial */
1804 work
->constructor
= 2;
1807 /* This block of code is a reduction in strength time optimization
1809 scan = mystrstr (*mangled, "__"); */
1815 scan
= strchr (scan
, '_');
1816 } while (scan
!= NULL
&& *++scan
!= '_');
1818 if (scan
!= NULL
) --scan
;
1823 /* We found a sequence of two or more '_', ensure that we start at
1824 the last pair in the sequence. */
1825 i
= strspn (scan
, "_");
1836 else if (work
-> static_type
)
1838 if (!isdigit (scan
[0]) && (scan
[0] != 't'))
1843 else if ((scan
== *mangled
)
1844 && (isdigit (scan
[2]) || (scan
[2] == 'Q') || (scan
[2] == 't')
1845 || (scan
[2] == 'K') || (scan
[2] == 'H')))
1847 /* The ARM says nothing about the mangling of local variables.
1848 But cfront mangles local variables by prepending __<nesting_level>
1849 to them. As an extension to ARM demangling we handle this case. */
1850 if ((LUCID_DEMANGLING
|| ARM_DEMANGLING
) && isdigit (scan
[2]))
1852 *mangled
= scan
+ 2;
1853 consume_count (mangled
);
1854 string_append (declp
, *mangled
);
1855 *mangled
+= strlen (*mangled
);
1860 /* A GNU style constructor starts with __[0-9Qt]. But cfront uses
1861 names like __Q2_3foo3bar for nested type names. So don't accept
1862 this style of constructor for cfront demangling. A GNU
1863 style member-template constructor starts with 'H'. */
1864 if (!(LUCID_DEMANGLING
|| ARM_DEMANGLING
))
1865 work
-> constructor
+= 1;
1866 *mangled
= scan
+ 2;
1869 else if ((scan
== *mangled
) && !isdigit (scan
[2]) && (scan
[2] != 't'))
1871 /* Mangled name starts with "__". Skip over any leading '_' characters,
1872 then find the next "__" that separates the prefix from the signature.
1874 if (!(ARM_DEMANGLING
|| LUCID_DEMANGLING
)
1875 || (arm_special (mangled
, declp
) == 0))
1877 while (*scan
== '_')
1881 if ((scan
= mystrstr (scan
, "__")) == NULL
|| (*(scan
+ 2) == '\0'))
1883 /* No separator (I.E. "__not_mangled"), or empty signature
1884 (I.E. "__not_mangled_either__") */
1889 demangle_function_name (work
, mangled
, declp
, scan
);
1893 else if (ARM_DEMANGLING
&& scan
[2] == 'p' && scan
[3] == 't')
1895 /* Cfront-style parameterized type. Handled later as a signature. */
1899 demangle_arm_pt (work
, mangled
, strlen (*mangled
), declp
);
1901 else if (*(scan
+ 2) != '\0')
1903 /* Mangled name does not start with "__" but does have one somewhere
1904 in there with non empty stuff after it. Looks like a global
1906 demangle_function_name (work
, mangled
, declp
, scan
);
1910 /* Doesn't look like a mangled name */
1914 if (!success
&& (work
->constructor
== 2 || work
->destructor
== 2))
1916 string_append (declp
, *mangled
);
1917 *mangled
+= strlen (*mangled
);
1927 gnu_special -- special handling of gnu mangled strings
1932 gnu_special (struct work_stuff *work, const char **mangled,
1938 Process some special GNU style mangling forms that don't fit
1939 the normal pattern. For example:
1941 _$_3foo (destructor for class foo)
1942 _vt$foo (foo virtual table)
1943 _vt$foo$bar (foo::bar virtual table)
1944 __vt_foo (foo virtual table, new style with thunks)
1945 _3foo$varname (static data member)
1946 _Q22rs2tu$vw (static data member)
1947 __t6vector1Zii (constructor with template)
1948 __thunk_4__$_7ostream (virtual function thunk)
1952 gnu_special (work
, mangled
, declp
)
1953 struct work_stuff
*work
;
1954 const char **mangled
;
1961 if ((*mangled
)[0] == '_'
1962 && strchr (cplus_markers
, (*mangled
)[1]) != NULL
1963 && (*mangled
)[2] == '_')
1965 /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
1967 work
-> destructor
+= 1;
1969 else if ((*mangled
)[0] == '_'
1970 && (((*mangled
)[1] == '_'
1971 && (*mangled
)[2] == 'v'
1972 && (*mangled
)[3] == 't'
1973 && (*mangled
)[4] == '_')
1974 || ((*mangled
)[1] == 'v'
1975 && (*mangled
)[2] == 't'
1976 && strchr (cplus_markers
, (*mangled
)[3]) != NULL
)))
1978 /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
1979 and create the decl. Note that we consume the entire mangled
1980 input string, which means that demangle_signature has no work
1982 if ((*mangled
)[2] == 'v')
1983 (*mangled
) += 5; /* New style, with thunks: "__vt_" */
1985 (*mangled
) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
1986 while (**mangled
!= '\0')
1988 p
= strpbrk (*mangled
, cplus_markers
);
1993 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
1996 success
= demangle_template (work
, mangled
, declp
, 0, 1);
1999 if (isdigit(*mangled
[0]))
2001 n
= consume_count(mangled
);
2002 /* We may be seeing a too-large size, or else a
2003 ".<digits>" indicating a static local symbol. In
2004 any case, declare victory and move on; *don't* try
2005 to use n to allocate. */
2006 if (n
>= strlen (*mangled
))
2014 n
= strcspn (*mangled
, cplus_markers
);
2016 string_appendn (declp
, *mangled
, n
);
2020 if (success
&& ((p
== NULL
) || (p
== *mangled
)))
2024 string_append (declp
,
2025 (work
-> options
& DMGL_JAVA
) ? "." : "::");
2036 string_append (declp
, " virtual table");
2038 else if ((*mangled
)[0] == '_'
2039 && (strchr("0123456789Qt", (*mangled
)[1]) != NULL
)
2040 && (p
= strpbrk (*mangled
, cplus_markers
)) != NULL
)
2042 /* static data member, "_3foo$varname" for example */
2048 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
2051 success
= demangle_template (work
, mangled
, declp
, 0, 1);
2054 n
= consume_count (mangled
);
2055 string_appendn (declp
, *mangled
, n
);
2058 if (success
&& (p
== *mangled
))
2060 /* Consumed everything up to the cplus_marker, append the
2063 string_append (declp
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
2064 n
= strlen (*mangled
);
2065 string_appendn (declp
, *mangled
, n
);
2073 else if (strncmp (*mangled
, "__thunk_", 8) == 0)
2075 int delta
= ((*mangled
) += 8, consume_count (mangled
));
2076 char *method
= internal_cplus_demangle (work
, ++*mangled
, work
->options
);
2080 sprintf (buf
, "virtual function thunk (delta:%d) for ", -delta
);
2081 string_append (declp
, buf
);
2082 string_append (declp
, method
);
2084 n
= strlen (*mangled
);
2092 else if (strncmp (*mangled
, "__t", 3) == 0
2093 && ((*mangled
)[3] == 'i' || (*mangled
)[3] == 'f'))
2095 p
= (*mangled
)[3] == 'i' ? " type_info node" : " type_info function";
2101 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
2104 success
= demangle_template (work
, mangled
, declp
, 0, 1);
2107 success
= demangle_fund_type (work
, mangled
, declp
);
2110 if (success
&& **mangled
!= '\0')
2113 string_append (declp
, p
);
2126 arm_special -- special handling of ARM/lucid mangled strings
2131 arm_special (const char **mangled,
2137 Process some special ARM style mangling forms that don't fit
2138 the normal pattern. For example:
2140 __vtbl__3foo (foo virtual table)
2141 __vtbl__3foo__3bar (bar::foo virtual table)
2146 arm_special (mangled
, declp
)
2147 const char **mangled
;
2154 if (strncmp (*mangled
, ARM_VTABLE_STRING
, ARM_VTABLE_STRLEN
) == 0)
2156 /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
2157 and create the decl. Note that we consume the entire mangled
2158 input string, which means that demangle_signature has no work
2160 scan
= *mangled
+ ARM_VTABLE_STRLEN
;
2161 while (*scan
!= '\0') /* first check it can be demangled */
2163 n
= consume_count (&scan
);
2166 return (0); /* no good */
2169 if (scan
[0] == '_' && scan
[1] == '_')
2174 (*mangled
) += ARM_VTABLE_STRLEN
;
2175 while (**mangled
!= '\0')
2177 n
= consume_count (mangled
);
2178 string_prependn (declp
, *mangled
, n
);
2180 if ((*mangled
)[0] == '_' && (*mangled
)[1] == '_')
2182 string_prepend (declp
, "::");
2186 string_append (declp
, " virtual table");
2199 demangle_qualified -- demangle 'Q' qualified name strings
2204 demangle_qualified (struct work_stuff *, const char *mangled,
2205 string *result, int isfuncname, int append);
2209 Demangle a qualified name, such as "Q25Outer5Inner" which is
2210 the mangled form of "Outer::Inner". The demangled output is
2211 prepended or appended to the result string according to the
2212 state of the append flag.
2214 If isfuncname is nonzero, then the qualified name we are building
2215 is going to be used as a member function name, so if it is a
2216 constructor or destructor function, append an appropriate
2217 constructor or destructor name. I.E. for the above example,
2218 the result for use as a constructor is "Outer::Inner::Inner"
2219 and the result for use as a destructor is "Outer::Inner::~Inner".
2223 Numeric conversion is ASCII dependent (FIXME).
2228 demangle_qualified (work
, mangled
, result
, isfuncname
, append
)
2229 struct work_stuff
*work
;
2230 const char **mangled
;
2242 string_init (&temp
);
2244 if ((*mangled
)[0] == 'K')
2246 /* Squangling qualified name reuse */
2249 idx
= consume_count_with_underscores (mangled
);
2250 if (idx
== -1 || idx
> work
-> numk
)
2253 string_append (&temp
, work
-> ktypevec
[idx
]);
2256 switch ((*mangled
)[1])
2259 /* GNU mangled name with more than 9 classes. The count is preceded
2260 by an underscore (to distinguish it from the <= 9 case) and followed
2261 by an underscore. */
2263 qualifiers
= atoi (p
);
2264 if (!isdigit (*p
) || *p
== '0')
2267 /* Skip the digits. */
2268 while (isdigit (*p
))
2286 /* The count is in a single digit. */
2287 num
[0] = (*mangled
)[1];
2289 qualifiers
= atoi (num
);
2291 /* If there is an underscore after the digit, skip it. This is
2292 said to be for ARM-qualified names, but the ARM makes no
2293 mention of such an underscore. Perhaps cfront uses one. */
2294 if ((*mangled
)[2] == '_')
2309 /* Pick off the names and collect them in the temp buffer in the order
2310 in which they are found, separated by '::'. */
2312 while (qualifiers
-- > 0)
2315 if (*mangled
[0] == '_')
2316 *mangled
= *mangled
+ 1;
2317 if (*mangled
[0] == 't')
2319 success
= demangle_template(work
, mangled
, &temp
, 0, 1);
2320 if (!success
) break;
2322 else if (*mangled
[0] == 'X')
2324 success
= do_type (work
, mangled
, &temp
);
2325 if (!success
) break;
2327 if (*mangled
[0] == 'K')
2331 idx
= consume_count_with_underscores (mangled
);
2332 if (idx
== -1 || idx
> work
->numk
)
2335 string_append (&temp
, work
->ktypevec
[idx
]);
2338 if (!success
) break;
2342 namelength
= consume_count (mangled
);
2343 if (strlen (*mangled
) < namelength
)
2345 /* Simple sanity check failed */
2349 string_appendn (&temp
, *mangled
, namelength
);
2350 *mangled
+= namelength
;
2355 remember_Ktype (work
, temp
.b
, LEN_STRING (&temp
));
2360 string_append (&temp
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
2364 /* If we are using the result as a function name, we need to append
2365 the appropriate '::' separated constructor or destructor name.
2366 We do this here because this is the most convenient place, where
2367 we already have a pointer to the name and the length of the name. */
2369 if (isfuncname
&& (work
->constructor
& 1 || work
->destructor
& 1))
2371 string_append (&temp
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
2372 if (work
-> destructor
& 1)
2374 string_append (&temp
, "~");
2376 string_appendn (&temp
, (*mangled
) - namelength
, namelength
);
2379 /* Now either prepend the temp buffer to the result, or append it,
2380 depending upon the state of the append flag. */
2384 string_appends (result
, &temp
);
2388 if (!STRING_EMPTY (result
))
2390 string_append (&temp
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
2392 string_prepends (result
, &temp
);
2395 string_delete (&temp
);
2403 get_count -- convert an ascii count to integer, consuming tokens
2408 get_count (const char **type, int *count)
2412 Return 0 if no conversion is performed, 1 if a string is converted.
2416 get_count (type
, count
)
2423 if (!isdigit (**type
))
2429 *count
= **type
- '0';
2431 if (isdigit (**type
))
2441 while (isdigit (*p
));
2452 /* result will be initialised here; it will be freed on failure */
2455 do_type (work
, mangled
, result
)
2456 struct work_stuff
*work
;
2457 const char **mangled
;
2464 const char *remembered_type
;
2469 string_init (&btype
);
2470 string_init (&decl
);
2471 string_init (result
);
2475 while (success
&& !done
)
2481 /* A pointer type */
2485 if (! (work
-> options
& DMGL_JAVA
))
2486 string_prepend (&decl
, "*");
2489 /* A reference type */
2492 string_prepend (&decl
, "&");
2498 const char *p
= ++(*mangled
);
2500 string_prepend (&decl
, "(");
2501 string_append (&decl
, ")[");
2502 /* Copy anything up until the next underscore (the size of the
2504 while (**mangled
&& **mangled
!= '_')
2506 if (**mangled
== '_')
2508 string_appendn (&decl
, p
, *mangled
- p
);
2509 string_append (&decl
, "]");
2517 /* A back reference to a previously seen type */
2520 if (!get_count (mangled
, &n
) || n
>= work
-> ntypes
)
2526 remembered_type
= work
-> typevec
[n
];
2527 mangled
= &remembered_type
;
2534 if (!STRING_EMPTY (&decl
) && decl
.b
[0] == '*')
2536 string_prepend (&decl
, "(");
2537 string_append (&decl
, ")");
2539 /* After picking off the function args, we expect to either find the
2540 function return type (preceded by an '_') or the end of the
2542 if (!demangle_args (work
, mangled
, &decl
)
2543 || (**mangled
!= '_' && **mangled
!= '\0'))
2547 if (success
&& (**mangled
== '_'))
2559 member
= **mangled
== 'M';
2561 if (!isdigit (**mangled
) && **mangled
!= 't')
2567 string_append (&decl
, ")");
2568 string_prepend (&decl
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
2569 if (isdigit (**mangled
))
2571 n
= consume_count (mangled
);
2572 if (strlen (*mangled
) < n
)
2577 string_prependn (&decl
, *mangled
, n
);
2583 string_init (&temp
);
2584 success
= demangle_template (work
, mangled
, &temp
, NULL
, 1);
2587 string_prependn (&decl
, temp
.b
, temp
.p
- temp
.b
);
2588 string_clear (&temp
);
2593 string_prepend (&decl
, "(");
2596 if (**mangled
== 'C')
2601 if (**mangled
== 'V')
2606 if (*(*mangled
)++ != 'F')
2612 if ((member
&& !demangle_args (work
, mangled
, &decl
))
2613 || **mangled
!= '_')
2619 if (! PRINT_ANSI_QUALIFIERS
)
2625 APPEND_BLANK (&decl
);
2626 string_append (&decl
, "const");
2630 APPEND_BLANK (&decl
);
2631 string_append (&decl
, "volatile");
2642 if ((*mangled)[1] == 'P')
2645 if (PRINT_ANSI_QUALIFIERS
)
2647 if (!STRING_EMPTY (&decl
))
2649 string_prepend (&decl
, " ");
2651 string_prepend (&decl
, "const");
2667 /* A qualified name, such as "Outer::Inner". */
2671 int btype
= register_Btype (work
);
2672 success
= demangle_qualified (work
, mangled
, result
, 0, 1);
2673 remember_Btype (work
, result
->b
, LEN_STRING (result
), btype
);
2678 /* A back reference to a previously seen squangled type */
2681 if (!get_count (mangled
, &n
) || n
>= work
-> numb
)
2685 string_append (result
, work
->btypevec
[n
]);
2691 /* A template parm. We substitute the corresponding argument. */
2696 idx
= consume_count_with_underscores (mangled
);
2699 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
2700 || consume_count_with_underscores (mangled
) == -1)
2706 if (work
->tmpl_argvec
)
2707 string_append (result
, work
->tmpl_argvec
[idx
]);
2711 sprintf(buf
, "T%d", idx
);
2712 string_append (result
, buf
);
2720 success
= demangle_fund_type (work
, mangled
, result
);
2726 if (!STRING_EMPTY (&decl
))
2728 string_append (result
, " ");
2729 string_appends (result
, &decl
);
2734 string_delete (result
);
2736 string_delete (&decl
);
2740 /* Given a pointer to a type string that represents a fundamental type
2741 argument (int, long, unsigned int, etc) in TYPE, a pointer to the
2742 string in which the demangled output is being built in RESULT, and
2743 the WORK structure, decode the types and add them to the result.
2748 "Sl" => "signed long"
2749 "CUs" => "const unsigned short"
2754 demangle_fund_type (work
, mangled
, result
)
2755 struct work_stuff
*work
;
2756 const char **mangled
;
2762 string_init (&btype
);
2764 /* First pick off any type qualifiers. There can be more than one. */
2772 if (PRINT_ANSI_QUALIFIERS
)
2774 APPEND_BLANK (result
);
2775 string_append (result
, "const");
2780 APPEND_BLANK (result
);
2781 string_append (result
, "unsigned");
2783 case 'S': /* signed char only */
2785 APPEND_BLANK (result
);
2786 string_append (result
, "signed");
2790 if (PRINT_ANSI_QUALIFIERS
)
2792 APPEND_BLANK (result
);
2793 string_append (result
, "volatile");
2798 APPEND_BLANK (result
);
2799 string_append (result
, "__complex");
2807 /* Now pick off the fundamental type. There can be only one. */
2816 APPEND_BLANK (result
);
2817 string_append (result
, "void");
2821 APPEND_BLANK (result
);
2822 string_append (result
, "long long");
2826 APPEND_BLANK (result
);
2827 string_append (result
, "long");
2831 APPEND_BLANK (result
);
2832 string_append (result
, "int");
2836 APPEND_BLANK (result
);
2837 string_append (result
, "short");
2841 APPEND_BLANK (result
);
2842 string_append (result
, "bool");
2846 APPEND_BLANK (result
);
2847 string_append (result
, "char");
2851 APPEND_BLANK (result
);
2852 string_append (result
, "wchar_t");
2856 APPEND_BLANK (result
);
2857 string_append (result
, "long double");
2861 APPEND_BLANK (result
);
2862 string_append (result
, "double");
2866 APPEND_BLANK (result
);
2867 string_append (result
, "float");
2871 if (!isdigit (**mangled
))
2877 /* An explicit type, such as "6mytype" or "7integer" */
2889 int bindex
= register_Btype (work
);
2891 string_init (&btype
);
2892 if (demangle_class_name (work
, mangled
, &btype
)) {
2893 remember_Btype (work
, btype
.b
, LEN_STRING (&btype
), bindex
);
2894 APPEND_BLANK (result
);
2895 string_appends (result
, &btype
);
2899 string_delete (&btype
);
2904 int bindex
= register_Btype (work
);
2905 success
= demangle_template (work
, mangled
, &btype
, 0, 1);
2906 remember_Btype (work
, btype
.b
, LEN_STRING (&btype
), bindex
);
2907 string_appends (result
, &btype
);
2918 /* `result' will be initialized in do_type; it will be freed on failure */
2921 do_arg (work
, mangled
, result
)
2922 struct work_stuff
*work
;
2923 const char **mangled
;
2926 const char *start
= *mangled
;
2928 if (!do_type (work
, mangled
, result
))
2934 remember_type (work
, start
, *mangled
- start
);
2940 remember_type (work
, start
, len
)
2941 struct work_stuff
*work
;
2947 if (work
-> ntypes
>= work
-> typevec_size
)
2949 if (work
-> typevec_size
== 0)
2951 work
-> typevec_size
= 3;
2953 = (char **) xmalloc (sizeof (char *) * work
-> typevec_size
);
2957 work
-> typevec_size
*= 2;
2959 = (char **) xrealloc ((char *)work
-> typevec
,
2960 sizeof (char *) * work
-> typevec_size
);
2963 tem
= xmalloc (len
+ 1);
2964 memcpy (tem
, start
, len
);
2966 work
-> typevec
[work
-> ntypes
++] = tem
;
2970 /* Remember a K type class qualifier. */
2972 remember_Ktype (work
, start
, len
)
2973 struct work_stuff
*work
;
2979 if (work
-> numk
>= work
-> ksize
)
2981 if (work
-> ksize
== 0)
2985 = (char **) xmalloc (sizeof (char *) * work
-> ksize
);
2991 = (char **) xrealloc ((char *)work
-> ktypevec
,
2992 sizeof (char *) * work
-> ksize
);
2995 tem
= xmalloc (len
+ 1);
2996 memcpy (tem
, start
, len
);
2998 work
-> ktypevec
[work
-> numk
++] = tem
;
3001 /* Register a B code, and get an index for it. B codes are registered
3002 as they are seen, rather than as they are completed, so map<temp<char> >
3003 registers map<temp<char> > as B0, and temp<char> as B1 */
3006 register_Btype (work
)
3007 struct work_stuff
*work
;
3011 if (work
-> numb
>= work
-> bsize
)
3013 if (work
-> bsize
== 0)
3017 = (char **) xmalloc (sizeof (char *) * work
-> bsize
);
3023 = (char **) xrealloc ((char *)work
-> btypevec
,
3024 sizeof (char *) * work
-> bsize
);
3027 ret
= work
-> numb
++;
3028 work
-> btypevec
[ret
] = NULL
;
3032 /* Store a value into a previously registered B code type. */
3035 remember_Btype (work
, start
, len
, index
)
3036 struct work_stuff
*work
;
3042 tem
= xmalloc (len
+ 1);
3043 memcpy (tem
, start
, len
);
3045 work
-> btypevec
[index
] = tem
;
3048 /* Lose all the info related to B and K type codes. */
3050 forget_B_and_K_types (work
)
3051 struct work_stuff
*work
;
3055 while (work
-> numk
> 0)
3057 i
= --(work
-> numk
);
3058 if (work
-> ktypevec
[i
] != NULL
)
3060 free (work
-> ktypevec
[i
]);
3061 work
-> ktypevec
[i
] = NULL
;
3065 while (work
-> numb
> 0)
3067 i
= --(work
-> numb
);
3068 if (work
-> btypevec
[i
] != NULL
)
3070 free (work
-> btypevec
[i
]);
3071 work
-> btypevec
[i
] = NULL
;
3075 /* Forget the remembered types, but not the type vector itself. */
3079 struct work_stuff
*work
;
3083 while (work
-> ntypes
> 0)
3085 i
= --(work
-> ntypes
);
3086 if (work
-> typevec
[i
] != NULL
)
3088 free (work
-> typevec
[i
]);
3089 work
-> typevec
[i
] = NULL
;
3094 /* Process the argument list part of the signature, after any class spec
3095 has been consumed, as well as the first 'F' character (if any). For
3098 "__als__3fooRT0" => process "RT0"
3099 "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i"
3101 DECLP must be already initialised, usually non-empty. It won't be freed
3104 Note that g++ differs significantly from ARM and lucid style mangling
3105 with regards to references to previously seen types. For example, given
3106 the source fragment:
3110 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
3113 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3114 void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3116 g++ produces the names:
3121 while lcc (and presumably other ARM style compilers as well) produces:
3123 foo__FiR3fooT1T2T1T2
3124 __ct__3fooFiR3fooT1T2T1T2
3126 Note that g++ bases it's type numbers starting at zero and counts all
3127 previously seen types, while lucid/ARM bases it's type numbers starting
3128 at one and only considers types after it has seen the 'F' character
3129 indicating the start of the function args. For lucid/ARM style, we
3130 account for this difference by discarding any previously seen types when
3131 we see the 'F' character, and subtracting one from the type number
3137 demangle_args (work
, mangled
, declp
)
3138 struct work_stuff
*work
;
3139 const char **mangled
;
3149 if (PRINT_ARG_TYPES
)
3151 string_append (declp
, "(");
3152 if (**mangled
== '\0')
3154 string_append (declp
, "void");
3158 while (**mangled
!= '_' && **mangled
!= '\0' && **mangled
!= 'e')
3160 if ((**mangled
== 'N') || (**mangled
== 'T'))
3162 temptype
= *(*mangled
)++;
3164 if (temptype
== 'N')
3166 if (!get_count (mangled
, &r
))
3175 if (ARM_DEMANGLING
&& work
-> ntypes
>= 10)
3177 /* If we have 10 or more types we might have more than a 1 digit
3178 index so we'll have to consume the whole count here. This
3179 will lose if the next thing is a type name preceded by a
3180 count but it's impossible to demangle that case properly
3181 anyway. Eg if we already have 12 types is T12Pc "(..., type1,
3182 Pc, ...)" or "(..., type12, char *, ...)" */
3183 if ((t
= consume_count(mangled
)) == 0)
3190 if (!get_count (mangled
, &t
))
3195 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
3199 /* Validate the type index. Protect against illegal indices from
3200 malformed type strings. */
3201 if ((t
< 0) || (t
>= work
-> ntypes
))
3207 tem
= work
-> typevec
[t
];
3208 if (need_comma
&& PRINT_ARG_TYPES
)
3210 string_append (declp
, ", ");
3212 if (!do_arg (work
, &tem
, &arg
))
3216 if (PRINT_ARG_TYPES
)
3218 string_appends (declp
, &arg
);
3220 string_delete (&arg
);
3226 if (need_comma
& PRINT_ARG_TYPES
)
3228 string_append (declp
, ", ");
3230 if (!do_arg (work
, mangled
, &arg
))
3234 if (PRINT_ARG_TYPES
)
3236 string_appends (declp
, &arg
);
3238 string_delete (&arg
);
3243 if (**mangled
== 'e')
3246 if (PRINT_ARG_TYPES
)
3250 string_append (declp
, ",");
3252 string_append (declp
, "...");
3256 if (PRINT_ARG_TYPES
)
3258 string_append (declp
, ")");
3264 demangle_function_name (work
, mangled
, declp
, scan
)
3265 struct work_stuff
*work
;
3266 const char **mangled
;
3274 string_appendn (declp
, (*mangled
), scan
- (*mangled
));
3275 string_need (declp
, 1);
3276 *(declp
-> p
) = '\0';
3278 /* Consume the function name, including the "__" separating the name
3279 from the signature. We are guaranteed that SCAN points to the
3282 (*mangled
) = scan
+ 2;
3284 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
3287 /* See if we have an ARM style constructor or destructor operator.
3288 If so, then just record it, clear the decl, and return.
3289 We can't build the actual constructor/destructor decl until later,
3290 when we recover the class name from the signature. */
3292 if (strcmp (declp
-> b
, "__ct") == 0)
3294 work
-> constructor
+= 1;
3295 string_clear (declp
);
3298 else if (strcmp (declp
-> b
, "__dt") == 0)
3300 work
-> destructor
+= 1;
3301 string_clear (declp
);
3306 if (declp
->p
- declp
->b
>= 3
3307 && declp
->b
[0] == 'o'
3308 && declp
->b
[1] == 'p'
3309 && strchr (cplus_markers
, declp
->b
[2]) != NULL
)
3311 /* see if it's an assignment expression */
3312 if (declp
->p
- declp
->b
>= 10 /* op$assign_ */
3313 && memcmp (declp
->b
+ 3, "assign_", 7) == 0)
3315 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3317 int len
= declp
->p
- declp
->b
- 10;
3318 if (strlen (optable
[i
].in
) == len
3319 && memcmp (optable
[i
].in
, declp
->b
+ 10, len
) == 0)
3321 string_clear (declp
);
3322 string_append (declp
, "operator");
3323 string_append (declp
, optable
[i
].out
);
3324 string_append (declp
, "=");
3331 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3333 int len
= declp
->p
- declp
->b
- 3;
3334 if (strlen (optable
[i
].in
) == len
3335 && memcmp (optable
[i
].in
, declp
->b
+ 3, len
) == 0)
3337 string_clear (declp
);
3338 string_append (declp
, "operator");
3339 string_append (declp
, optable
[i
].out
);
3345 else if (declp
->p
- declp
->b
>= 5 && memcmp (declp
->b
, "type", 4) == 0
3346 && strchr (cplus_markers
, declp
->b
[4]) != NULL
)
3348 /* type conversion operator */
3350 if (do_type (work
, &tem
, &type
))
3352 string_clear (declp
);
3353 string_append (declp
, "operator ");
3354 string_appends (declp
, &type
);
3355 string_delete (&type
);
3358 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
3359 && declp
->b
[2] == 'o' && declp
->b
[3] == 'p')
3362 /* type conversion operator. */
3364 if (do_type (work
, &tem
, &type
))
3366 string_clear (declp
);
3367 string_append (declp
, "operator ");
3368 string_appends (declp
, &type
);
3369 string_delete (&type
);
3372 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
3373 && declp
->b
[2] >= 'a' && declp
->b
[2] <= 'z'
3374 && declp
->b
[3] >= 'a' && declp
->b
[3] <= 'z')
3376 if (declp
->b
[4] == '\0')
3379 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3381 if (strlen (optable
[i
].in
) == 2
3382 && memcmp (optable
[i
].in
, declp
->b
+ 2, 2) == 0)
3384 string_clear (declp
);
3385 string_append (declp
, "operator");
3386 string_append (declp
, optable
[i
].out
);
3393 if (declp
->b
[2] == 'a' && declp
->b
[5] == '\0')
3396 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3398 if (strlen (optable
[i
].in
) == 3
3399 && memcmp (optable
[i
].in
, declp
->b
+ 2, 3) == 0)
3401 string_clear (declp
);
3402 string_append (declp
, "operator");
3403 string_append (declp
, optable
[i
].out
);
3412 /* a mini string-handling package */
3427 s
->p
= s
->b
= xmalloc (n
);
3430 else if (s
->e
- s
->p
< n
)
3435 s
->b
= xrealloc (s
->b
, n
);
3448 s
->b
= s
->e
= s
->p
= NULL
;
3456 s
->b
= s
->p
= s
->e
= NULL
;
3472 return (s
->b
== s
->p
);
3478 string_append (p
, s
)
3483 if (s
== NULL
|| *s
== '\0')
3487 memcpy (p
->p
, s
, n
);
3492 string_appends (p
, s
)
3501 memcpy (p
->p
, s
->b
, n
);
3507 string_appendn (p
, s
, n
)
3515 memcpy (p
->p
, s
, n
);
3521 string_prepend (p
, s
)
3525 if (s
!= NULL
&& *s
!= '\0')
3527 string_prependn (p
, s
, strlen (s
));
3532 string_prepends (p
, s
)
3537 string_prependn (p
, s
->b
, s
->p
- s
->b
);
3542 string_prependn (p
, s
, n
)
3552 for (q
= p
->p
- 1; q
>= p
->b
; q
--)
3556 memcpy (p
->b
, s
, n
);
3561 /* To generate a standalone demangler program for testing purposes,
3562 just compile and link this file with -DMAIN and libiberty.a. When
3563 run, it demangles each command line arg, or each stdin string, and
3564 prints the result on stdout. */
3570 static char *program_name
;
3571 static char *program_version
= VERSION
;
3572 static int flags
= DMGL_PARAMS
| DMGL_ANSI
;
3574 static void demangle_it
PARAMS ((char *));
3575 static void usage
PARAMS ((FILE *, int));
3576 static void fatal
PARAMS ((char *));
3579 demangle_it (mangled_name
)
3584 result
= cplus_demangle (mangled_name
, flags
);
3587 printf ("%s\n", mangled_name
);
3591 printf ("%s\n", result
);
3597 usage (stream
, status
)
3602 Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
3603 [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\
3604 [--help] [--version] [arg...]\n",
3609 #define MBUF_SIZE 512
3610 char mbuffer
[MBUF_SIZE
];
3612 /* Defined in the automatically-generated underscore.c. */
3613 extern int prepends_underscore
;
3615 int strip_underscore
= 0;
3617 static struct option long_options
[] = {
3618 {"strip-underscores", no_argument
, 0, '_'},
3619 {"format", required_argument
, 0, 's'},
3620 {"help", no_argument
, 0, 'h'},
3621 {"java", no_argument
, 0, 'j'},
3622 {"no-strip-underscores", no_argument
, 0, 'n'},
3623 {"version", no_argument
, 0, 'v'},
3624 {0, no_argument
, 0, 0}
3627 /* More 'friendly' abort that prints the line and file.
3628 config.h can #define abort fancy_abort if you like that sort of thing. */
3633 fatal ("Internal gcc abort.");
3644 program_name
= argv
[0];
3646 strip_underscore
= prepends_underscore
;
3648 while ((c
= getopt_long (argc
, argv
, "_ns:j", long_options
, (int *) 0)) != EOF
)
3658 strip_underscore
= 0;
3661 printf ("GNU %s version %s\n", program_name
, program_version
);
3664 strip_underscore
= 1;
3670 if (strcmp (optarg
, "gnu") == 0)
3672 current_demangling_style
= gnu_demangling
;
3674 else if (strcmp (optarg
, "lucid") == 0)
3676 current_demangling_style
= lucid_demangling
;
3678 else if (strcmp (optarg
, "arm") == 0)
3680 current_demangling_style
= arm_demangling
;
3684 fprintf (stderr
, "%s: unknown demangling style `%s'\n",
3685 program_name
, optarg
);
3694 for ( ; optind
< argc
; optind
++)
3696 demangle_it (argv
[optind
]);
3705 /* Try to read a label. */
3706 while (c
!= EOF
&& (isalnum(c
) || c
== '_' || c
== '$' || c
== '.'))
3708 if (i
>= MBUF_SIZE
-1)
3717 if (mbuffer
[0] == '.')
3719 if (strip_underscore
&& mbuffer
[skip_first
] == '_')
3727 result
= cplus_demangle (mbuffer
+ skip_first
, flags
);
3730 if (mbuffer
[0] == '.')
3732 fputs (result
, stdout
);
3736 fputs (mbuffer
, stdout
);
3753 fprintf (stderr
, "%s: %s\n", program_name
, str
);
3764 register char *value
= (char *) malloc (size
);
3766 fatal ("virtual memory exhausted");
3771 xrealloc (ptr
, size
)
3775 register char *value
= (char *) realloc (ptr
, size
);
3777 fatal ("virtual memory exhausted");