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 *));
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
)
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')
457 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
459 if (strlen (optable
[i
].in
) == 2
460 && memcmp (optable
[i
].in
, opname
+ 2, 2) == 0)
462 strcat (result
, "operator");
463 strcat (result
, optable
[i
].out
);
471 if (opname
[2] == 'a' && opname
[5] == '\0')
475 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
477 if (strlen (optable
[i
].in
) == 3
478 && memcmp (optable
[i
].in
, opname
+ 2, 3) == 0)
480 strcat (result
, "operator");
481 strcat (result
, optable
[i
].out
);
492 && strchr (cplus_markers
, opname
[2]) != NULL
)
494 /* see if it's an assignment expression */
495 if (len
>= 10 /* op$assign_ */
496 && memcmp (opname
+ 3, "assign_", 7) == 0)
499 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
502 if (strlen (optable
[i
].in
) == len1
503 && memcmp (optable
[i
].in
, opname
+ 10, len1
) == 0)
505 strcat (result
, "operator");
506 strcat (result
, optable
[i
].out
);
507 strcat (result
, "=");
516 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
519 if (strlen (optable
[i
].in
) == len1
520 && memcmp (optable
[i
].in
, opname
+ 3, len1
) == 0)
522 strcat (result
, "operator");
523 strcat (result
, optable
[i
].out
);
530 else if (len
>= 5 && memcmp (opname
, "type", 4) == 0
531 && strchr (cplus_markers
, opname
[4]) != NULL
)
533 /* type conversion operator */
535 if (do_type (work
, &tem
, &type
))
537 strcat (result
, "operator ");
538 strncat (result
, type
.b
, type
.p
- type
.b
);
539 string_delete (&type
);
543 squangle_mop_up (work
);
547 /* Takes operator name as e.g. "++" and returns mangled
548 operator name (e.g. "postincrement_expr"), or NULL if not found.
550 If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
551 if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */
554 cplus_mangle_opname (opname
, options
)
561 len
= strlen (opname
);
562 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
564 if (strlen (optable
[i
].out
) == len
565 && (options
& DMGL_ANSI
) == (optable
[i
].flags
& DMGL_ANSI
)
566 && memcmp (optable
[i
].out
, opname
, len
) == 0)
567 return optable
[i
].in
;
572 /* char *cplus_demangle (const char *mangled, int options)
574 If MANGLED is a mangled function name produced by GNU C++, then
575 a pointer to a malloced string giving a C++ representation
576 of the name will be returned; otherwise NULL will be returned.
577 It is the caller's responsibility to free the string which
580 The OPTIONS arg may contain one or more of the following bits:
582 DMGL_ANSI ANSI qualifiers such as `const' and `void' are
584 DMGL_PARAMS Function parameters are included.
588 cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)"
589 cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
590 cplus_demangle ("foo__1Ai", 0) => "A::foo"
592 cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)"
593 cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
594 cplus_demangle ("foo__1Afe", 0) => "A::foo"
596 Note that any leading underscores, or other such characters prepended by
597 the compilation system, are presumed to have already been stripped from
601 cplus_demangle (mangled
, options
)
606 struct work_stuff work
[1];
607 memset ((char *) work
, 0, sizeof (work
));
608 work
-> options
= options
;
609 if ((work
-> options
& DMGL_STYLE_MASK
) == 0)
610 work
-> options
|= (int) current_demangling_style
& DMGL_STYLE_MASK
;
612 ret
= internal_cplus_demangle (work
, mangled
);
613 squangle_mop_up (work
);
618 /* This function performs most of what cplus_demangle use to do, but
619 to be able to demangle a name with a B, K or n code, we need to
620 have a longer term memory of what types have been seen. The original
621 now intializes and cleans up the squangle code info, while internal
622 calls go directly to this routine to avoid resetting that info. */
625 internal_cplus_demangle (work
, mangled
)
626 struct work_stuff
*work
;
632 char *demangled
= NULL
;
634 s1
= work
->constructor
;
635 s2
= work
->destructor
;
636 s3
= work
->static_type
;
637 s4
= work
->const_type
;
638 work
->constructor
= work
->destructor
= 0;
639 work
->static_type
= work
->const_type
= 0;
641 if ((mangled
!= NULL
) && (*mangled
!= '\0'))
645 /* First check to see if gnu style demangling is active and if the
646 string to be demangled contains a CPLUS_MARKER. If so, attempt to
647 recognize one of the gnu special forms rather than looking for a
648 standard prefix. In particular, don't worry about whether there
649 is a "__" string in the mangled string. Consider "_$_5__foo" for
652 if ((AUTO_DEMANGLING
|| GNU_DEMANGLING
))
654 success
= gnu_special (work
, &mangled
, &decl
);
658 success
= demangle_prefix (work
, &mangled
, &decl
);
660 if (success
&& (*mangled
!= '\0'))
662 success
= demangle_signature (work
, &mangled
, &decl
);
664 if (work
->constructor
== 2)
666 string_prepend (&decl
, "global constructors keyed to ");
667 work
->constructor
= 0;
669 else if (work
->destructor
== 2)
671 string_prepend (&decl
, "global destructors keyed to ");
672 work
->destructor
= 0;
674 demangled
= mop_up (work
, &decl
, success
);
676 work
->constructor
= s1
;
677 work
->destructor
= s2
;
678 work
->static_type
= s3
;
679 work
->const_type
= s4
;
684 /* Clear out and squangling related storage */
686 squangle_mop_up (work
)
687 struct work_stuff
*work
;
689 /* clean up the B and K type mangling types. */
690 forget_B_and_K_types (work
);
691 if (work
-> btypevec
!= NULL
)
693 free ((char *) work
-> btypevec
);
695 if (work
-> ktypevec
!= NULL
)
697 free ((char *) work
-> ktypevec
);
701 /* Clear out any mangled storage */
704 mop_up (work
, declp
, success
)
705 struct work_stuff
*work
;
709 char *demangled
= NULL
;
711 /* Discard the remembered types, if any. */
714 if (work
-> typevec
!= NULL
)
716 free ((char *) work
-> typevec
);
717 work
-> typevec
= NULL
;
719 if (work
->tmpl_argvec
)
723 for (i
= 0; i
< work
->ntmpl_args
; i
++)
724 if (work
->tmpl_argvec
[i
])
725 free ((char*) work
->tmpl_argvec
[i
]);
727 free ((char*) work
->tmpl_argvec
);
728 work
->tmpl_argvec
= NULL
;
731 /* If demangling was successful, ensure that the demangled string is null
732 terminated and return it. Otherwise, free the demangling decl. */
736 string_delete (declp
);
740 string_appendn (declp
, "", 1);
741 demangled
= declp
-> b
;
750 demangle_signature -- demangle the signature part of a mangled name
755 demangle_signature (struct work_stuff *work, const char **mangled,
760 Consume and demangle the signature portion of the mangled name.
762 DECLP is the string where demangled output is being built. At
763 entry it contains the demangled root name from the mangled name
764 prefix. I.E. either a demangled operator name or the root function
765 name. In some special cases, it may contain nothing.
767 *MANGLED points to the current unconsumed location in the mangled
768 name. As tokens are consumed and demangling is performed, the
769 pointer is updated to continuously point at the next token to
772 Demangling GNU style mangled names is nasty because there is no
773 explicit token that marks the start of the outermost function
777 demangle_signature (work
, mangled
, declp
)
778 struct work_stuff
*work
;
779 const char **mangled
;
785 int expect_return_type
= 0;
786 const char *oldmangled
= NULL
;
790 while (success
&& (**mangled
!= '\0'))
795 oldmangled
= *mangled
;
796 success
= demangle_qualified (work
, mangled
, declp
, 1, 0);
799 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
801 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
809 oldmangled
= *mangled
;
810 success
= demangle_qualified (work
, mangled
, declp
, 1, 0);
811 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
819 /* Static member function */
820 if (oldmangled
== NULL
)
822 oldmangled
= *mangled
;
825 work
-> static_type
= 1;
829 /* a const member function */
830 if (oldmangled
== NULL
)
832 oldmangled
= *mangled
;
835 work
-> const_type
= 1;
838 case '0': case '1': case '2': case '3': case '4':
839 case '5': case '6': case '7': case '8': case '9':
840 if (oldmangled
== NULL
)
842 oldmangled
= *mangled
;
844 success
= demangle_class (work
, mangled
, declp
);
847 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
849 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
858 /* ARM style demangling includes a specific 'F' character after
859 the class name. For GNU style, it is just implied. So we can
860 safely just consume any 'F' at this point and be compatible
861 with either style. */
867 /* For lucid/ARM style we have to forget any types we might
868 have remembered up to this point, since they were not argument
869 types. GNU style considers all types seen as available for
870 back references. See comment in demangle_args() */
872 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
876 success
= demangle_args (work
, mangled
, declp
);
881 string_init(&trawname
);
883 if (oldmangled
== NULL
)
885 oldmangled
= *mangled
;
887 success
= demangle_template (work
, mangled
, &tname
, &trawname
, 1);
890 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
892 string_append(&tname
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
893 string_prepends(declp
, &tname
);
894 if (work
-> destructor
& 1)
896 string_prepend (&trawname
, "~");
897 string_appends (declp
, &trawname
);
898 work
->destructor
-= 1;
900 if ((work
->constructor
& 1) || (work
->destructor
& 1))
902 string_appends (declp
, &trawname
);
903 work
->constructor
-= 1;
905 string_delete(&trawname
);
906 string_delete(&tname
);
912 if (GNU_DEMANGLING
&& expect_return_type
)
914 /* Read the return type. */
916 string_init (&return_type
);
919 success
= do_type (work
, mangled
, &return_type
);
920 APPEND_BLANK (&return_type
);
922 string_prepends (declp
, &return_type
);
923 string_delete (&return_type
);
927 /* At the outermost level, we cannot have a return type specified,
928 so if we run into another '_' at this point we are dealing with
929 a mangled name that is either bogus, or has been mangled by
930 some algorithm we don't know how to deal with. So just
931 reject the entire demangling. */
938 /* A G++ template function. Read the template arguments. */
939 success
= demangle_template (work
, mangled
, declp
, 0, 0);
940 if (!(work
->constructor
& 1))
941 expect_return_type
= 1;
950 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
952 /* Assume we have stumbled onto the first outermost function
953 argument token, and start processing args. */
955 success
= demangle_args (work
, mangled
, declp
);
959 /* Non-GNU demanglers use a specific token to mark the start
960 of the outermost function argument tokens. Typically 'F',
961 for ARM-demangling, for example. So if we find something
962 we are not prepared for, it must be an error. */
968 if (AUTO_DEMANGLING || GNU_DEMANGLING)
971 if (success
&& expect_func
)
974 success
= demangle_args (work
, mangled
, declp
);
975 /* Since template include the mangling of their return types,
976 we must set expect_func to 0 so that we don't try do
977 demangle more arguments the next time we get here. */
982 if (success
&& !func_done
)
984 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
986 /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
987 bar__3fooi is 'foo::bar(int)'. We get here when we find the
988 first case, and need to ensure that the '(void)' gets added to
989 the current declp. Note that with ARM, the first case
990 represents the name of a static data member 'foo::bar',
991 which is in the current declp, so we leave it alone. */
992 success
= demangle_args (work
, mangled
, declp
);
995 if (success
&& work
-> static_type
&& PRINT_ARG_TYPES
)
997 string_append (declp
, " static");
999 if (success
&& work
-> const_type
&& PRINT_ARG_TYPES
)
1001 string_append (declp
, " const");
1009 demangle_method_args (work
, mangled
, declp
)
1010 struct work_stuff
*work
;
1011 const char **mangled
;
1016 if (work
-> static_type
)
1018 string_append (declp
, *mangled
+ 1);
1019 *mangled
+= strlen (*mangled
);
1024 success
= demangle_args (work
, mangled
, declp
);
1032 demangle_template_template_parm (work
, mangled
, tname
)
1033 struct work_stuff
*work
;
1034 const char **mangled
;
1043 string_append (tname
, "template <");
1044 /* get size of template parameter list */
1045 if (get_count (mangled
, &r
))
1047 for (i
= 0; i
< r
; i
++)
1051 string_append (tname
, ", ");
1054 /* Z for type parameters */
1055 if (**mangled
== 'Z')
1058 string_append (tname
, "class");
1060 /* z for template parameters */
1061 else if (**mangled
== 'z')
1065 demangle_template_template_parm (work
, mangled
, tname
);
1073 /* temp is initialized in do_type */
1074 success
= do_type (work
, mangled
, &temp
);
1077 string_appends (tname
, &temp
);
1079 string_delete(&temp
);
1089 if (tname
->p
[-1] == '>')
1090 string_append (tname
, " ");
1091 string_append (tname
, "> class");
1096 demangle_integral_value (work
, mangled
, s
)
1097 struct work_stuff
*work
;
1098 const char** mangled
;
1103 if (**mangled
== 'E')
1105 int need_operator
= 0;
1108 string_appendn (s
, "(", 1);
1110 while (success
&& **mangled
!= 'W' && **mangled
!= '\0')
1119 len
= strlen (*mangled
);
1122 i
< sizeof (optable
) / sizeof (optable
[0]);
1125 size_t l
= strlen (optable
[i
].in
);
1128 && memcmp (optable
[i
].in
, *mangled
, l
) == 0)
1130 string_appendn (s
, " ", 1);
1131 string_append (s
, optable
[i
].out
);
1132 string_appendn (s
, " ", 1);
1145 success
= demangle_template_value_parm (work
, mangled
, s
);
1148 if (**mangled
!= 'W')
1152 string_appendn (s
, ")", 1);
1156 else if (**mangled
== 'Q' || **mangled
== 'K')
1157 success
= demangle_qualified (work
, mangled
, s
, 0, 1);
1162 if (**mangled
== 'm')
1164 string_appendn (s
, "-", 1);
1167 while (isdigit (**mangled
))
1169 string_appendn (s
, *mangled
, 1);
1179 demangle_template_value_parm (work
, mangled
, s
)
1180 struct work_stuff
*work
;
1181 const char **mangled
;
1184 const char *old_p
= *mangled
;
1187 int is_integral
= 0;
1193 while (*old_p
&& !done
)
1200 done
= is_pointer
= 1;
1202 case 'C': /* const */
1203 case 'S': /* explicitly signed [char] */
1204 case 'U': /* unsigned */
1205 case 'V': /* volatile */
1206 case 'F': /* function */
1207 case 'M': /* member function */
1209 case 'J': /* complex */
1212 case 'E': /* expression */
1213 case 'Q': /* qualified name */
1214 case 'K': /* qualified name */
1215 done
= is_integral
= 1;
1217 case 'B': /* squangled name */
1218 done
= is_integral
= 1;
1220 case 'T': /* remembered type */
1223 case 'v': /* void */
1226 case 'x': /* long long */
1227 case 'l': /* long */
1229 case 's': /* short */
1230 case 'w': /* wchar_t */
1231 done
= is_integral
= 1;
1233 case 'b': /* bool */
1236 case 'c': /* char */
1239 case 'r': /* long double */
1240 case 'd': /* double */
1241 case 'f': /* float */
1245 /* it's probably user defined type, let's assume
1246 it's integral, it seems hard to figure out
1247 what it really is */
1248 done
= is_integral
= 1;
1251 if (**mangled
== 'Y')
1253 /* The next argument is a template parameter. */
1257 idx
= consume_count_with_underscores (mangled
);
1259 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
1260 || consume_count_with_underscores (mangled
) == -1)
1262 if (work
->tmpl_argvec
)
1263 string_append (s
, work
->tmpl_argvec
[idx
]);
1267 sprintf(buf
, "T%d", idx
);
1268 string_append (s
, buf
);
1271 else if (is_integral
)
1272 success
= demangle_integral_value (work
, mangled
, s
);
1277 if (**mangled
== 'm')
1279 string_appendn (s
, "-", 1);
1282 string_appendn (s
, "'", 1);
1283 val
= consume_count(mangled
);
1288 string_appendn (s
, &tmp
[0], 1);
1289 string_appendn (s
, "'", 1);
1293 int val
= consume_count (mangled
);
1295 string_appendn (s
, "false", 5);
1297 string_appendn (s
, "true", 4);
1303 if (**mangled
== 'm')
1305 string_appendn (s
, "-", 1);
1308 while (isdigit (**mangled
))
1310 string_appendn (s
, *mangled
, 1);
1313 if (**mangled
== '.') /* fraction */
1315 string_appendn (s
, ".", 1);
1317 while (isdigit (**mangled
))
1319 string_appendn (s
, *mangled
, 1);
1323 if (**mangled
== 'e') /* exponent */
1325 string_appendn (s
, "e", 1);
1327 while (isdigit (**mangled
))
1329 string_appendn (s
, *mangled
, 1);
1334 else if (is_pointer
)
1336 int symbol_len
= consume_count (mangled
);
1337 if (symbol_len
== 0)
1339 if (symbol_len
== 0)
1340 string_appendn (s
, "0", 1);
1343 char *p
= xmalloc (symbol_len
+ 1), *q
;
1344 strncpy (p
, *mangled
, symbol_len
);
1345 p
[symbol_len
] = '\0';
1346 q
= internal_cplus_demangle (work
, p
);
1347 string_appendn (s
, "&", 1);
1350 string_append (s
, q
);
1354 string_append (s
, p
);
1357 *mangled
+= symbol_len
;
1364 demangle_template (work
, mangled
, tname
, trawname
, is_type
)
1365 struct work_stuff
*work
;
1366 const char **mangled
;
1376 int is_java_array
= 0;
1383 /* get template name */
1384 if (**mangled
== 'z')
1390 idx
= consume_count_with_underscores (mangled
);
1392 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
1393 || consume_count_with_underscores (mangled
) == -1)
1397 if (work
->tmpl_argvec
)
1399 string_append (tname
, work
->tmpl_argvec
[idx
]);
1401 string_append (trawname
, work
->tmpl_argvec
[idx
]);
1406 sprintf(buf
, "T%d", idx
);
1407 string_append (tname
, buf
);
1409 string_append (trawname
, work
->tmpl_argvec
[idx
]);
1414 if ((r
= consume_count (mangled
)) == 0 || strlen (*mangled
) < r
)
1419 string_appendn (trawname
, *mangled
, r
);
1420 is_java_array
= (work
-> options
& DMGL_JAVA
)
1421 && strncmp (*mangled
, "JArray1Z", 8) == 0;
1422 if (! is_java_array
)
1424 string_appendn (tname
, *mangled
, r
);
1430 string_append (tname
, "<");
1431 /* get size of template parameter list */
1432 if (!get_count (mangled
, &r
))
1438 /* Create an array for saving the template argument values. */
1439 work
->tmpl_argvec
= (char**) xmalloc (r
* sizeof (char *));
1440 work
->ntmpl_args
= r
;
1441 for (i
= 0; i
< r
; i
++)
1442 work
->tmpl_argvec
[i
] = 0;
1444 for (i
= 0; i
< r
; i
++)
1448 string_append (tname
, ", ");
1450 /* Z for type parameters */
1451 if (**mangled
== 'Z')
1454 /* temp is initialized in do_type */
1455 success
= do_type (work
, mangled
, &temp
);
1458 string_appends (tname
, &temp
);
1462 /* Save the template argument. */
1463 int len
= temp
.p
- temp
.b
;
1464 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1465 memcpy (work
->tmpl_argvec
[i
], temp
.b
, len
);
1466 work
->tmpl_argvec
[i
][len
] = '\0';
1469 string_delete(&temp
);
1475 /* z for template parameters */
1476 else if (**mangled
== 'z')
1480 success
= demangle_template_template_parm (work
, mangled
, tname
);
1483 && (r2
= consume_count (mangled
)) > 0 && strlen (*mangled
) >= r2
)
1485 string_append (tname
, " ");
1486 string_appendn (tname
, *mangled
, r2
);
1489 /* Save the template argument. */
1491 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1492 memcpy (work
->tmpl_argvec
[i
], *mangled
, len
);
1493 work
->tmpl_argvec
[i
][len
] = '\0';
1507 /* otherwise, value parameter */
1509 /* temp is initialized in do_type */
1510 success
= do_type (work
, mangled
, &temp
);
1514 string_appends (s, &temp);
1517 string_delete(&temp
);
1523 string_append (s, "=");
1534 success
= demangle_template_value_parm (work
, mangled
, s
);
1546 int len
= s
->p
- s
->b
;
1547 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1548 memcpy (work
->tmpl_argvec
[i
], s
->b
, len
);
1549 work
->tmpl_argvec
[i
][len
] = '\0';
1551 string_appends (tname
, s
);
1559 string_append (tname
, "[]");
1563 if (tname
->p
[-1] == '>')
1564 string_append (tname
, " ");
1565 string_append (tname
, ">");
1569 if (work -> static_type)
1571 string_append (declp, *mangled + 1);
1572 *mangled += strlen (*mangled);
1577 success = demangle_args (work, mangled, declp);
1585 arm_pt (work
, mangled
, n
, anchor
, args
)
1586 struct work_stuff
*work
;
1587 const char *mangled
;
1589 const char **anchor
, **args
;
1592 if (ARM_DEMANGLING
&& (*anchor
= mystrstr (mangled
, "__pt__")))
1595 *args
= *anchor
+ 6;
1596 len
= consume_count (args
);
1597 if (*args
+ len
== mangled
+ n
&& **args
== '_')
1607 demangle_arm_pt (work
, mangled
, n
, declp
)
1608 struct work_stuff
*work
;
1609 const char **mangled
;
1615 const char *e
= *mangled
+ n
;
1618 if (arm_pt (work
, *mangled
, n
, &p
, &args
))
1622 string_appendn (declp
, *mangled
, p
- *mangled
);
1623 string_append (declp
, "<");
1624 /* should do error checking here */
1626 string_clear (&arg
);
1627 do_type (work
, &args
, &arg
);
1628 string_appends (declp
, &arg
);
1629 string_append (declp
, ",");
1631 string_delete (&arg
);
1633 string_append (declp
, ">");
1637 string_appendn (declp
, *mangled
, n
);
1643 demangle_class_name (work
, mangled
, declp
)
1644 struct work_stuff
*work
;
1645 const char **mangled
;
1651 n
= consume_count (mangled
);
1652 if (strlen (*mangled
) >= n
)
1654 demangle_arm_pt (work
, mangled
, n
, declp
);
1665 demangle_class -- demangle a mangled class sequence
1670 demangle_class (struct work_stuff *work, const char **mangled,
1675 DECLP points to the buffer into which demangling is being done.
1677 *MANGLED points to the current token to be demangled. On input,
1678 it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
1679 On exit, it points to the next token after the mangled class on
1680 success, or the first unconsumed token on failure.
1682 If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
1683 we are demangling a constructor or destructor. In this case
1684 we prepend "class::class" or "class::~class" to DECLP.
1686 Otherwise, we prepend "class::" to the current DECLP.
1688 Reset the constructor/destructor flags once they have been
1689 "consumed". This allows demangle_class to be called later during
1690 the same demangling, to do normal class demangling.
1692 Returns 1 if demangling is successful, 0 otherwise.
1697 demangle_class (work
, mangled
, declp
)
1698 struct work_stuff
*work
;
1699 const char **mangled
;
1706 string_init (&class_name
);
1707 btype
= register_Btype (work
);
1708 if (demangle_class_name (work
, mangled
, &class_name
))
1710 if ((work
->constructor
& 1) || (work
->destructor
& 1))
1712 string_prepends (declp
, &class_name
);
1713 if (work
-> destructor
& 1)
1715 string_prepend (declp
, "~");
1716 work
-> destructor
-= 1;
1720 work
-> constructor
-= 1;
1723 remember_Ktype (work
, class_name
.b
, LEN_STRING(&class_name
));
1724 remember_Btype (work
, class_name
.b
, LEN_STRING(&class_name
), btype
);
1725 string_prepend (declp
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
1726 string_prepends (declp
, &class_name
);
1729 string_delete (&class_name
);
1737 demangle_prefix -- consume the mangled name prefix and find signature
1742 demangle_prefix (struct work_stuff *work, const char **mangled,
1747 Consume and demangle the prefix of the mangled name.
1749 DECLP points to the string buffer into which demangled output is
1750 placed. On entry, the buffer is empty. On exit it contains
1751 the root function name, the demangled operator name, or in some
1752 special cases either nothing or the completely demangled result.
1754 MANGLED points to the current pointer into the mangled name. As each
1755 token of the mangled name is consumed, it is updated. Upon entry
1756 the current mangled name pointer points to the first character of
1757 the mangled name. Upon exit, it should point to the first character
1758 of the signature if demangling was successful, or to the first
1759 unconsumed character if demangling of the prefix was unsuccessful.
1761 Returns 1 on success, 0 otherwise.
1765 demangle_prefix (work
, mangled
, declp
)
1766 struct work_stuff
*work
;
1767 const char **mangled
;
1774 if (strlen(*mangled
) >= 11 && strncmp(*mangled
, "_GLOBAL_", 8) == 0)
1776 char *marker
= strchr (cplus_markers
, (*mangled
)[8]);
1777 if (marker
!= NULL
&& *marker
== (*mangled
)[10])
1779 if ((*mangled
)[9] == 'D')
1781 /* it's a GNU global destructor to be executed at program exit */
1783 work
->destructor
= 2;
1784 if (gnu_special (work
, mangled
, declp
))
1787 else if ((*mangled
)[9] == 'I')
1789 /* it's a GNU global constructor to be executed at program init */
1791 work
->constructor
= 2;
1792 if (gnu_special (work
, mangled
, declp
))
1797 else if (ARM_DEMANGLING
&& strncmp(*mangled
, "__std__", 7) == 0)
1799 /* it's a ARM global destructor to be executed at program exit */
1801 work
->destructor
= 2;
1803 else if (ARM_DEMANGLING
&& strncmp(*mangled
, "__sti__", 7) == 0)
1805 /* it's a ARM global constructor to be executed at program initial */
1807 work
->constructor
= 2;
1810 /* This block of code is a reduction in strength time optimization
1812 scan = mystrstr (*mangled, "__"); */
1818 scan
= strchr (scan
, '_');
1819 } while (scan
!= NULL
&& *++scan
!= '_');
1821 if (scan
!= NULL
) --scan
;
1826 /* We found a sequence of two or more '_', ensure that we start at
1827 the last pair in the sequence. */
1828 i
= strspn (scan
, "_");
1839 else if (work
-> static_type
)
1841 if (!isdigit (scan
[0]) && (scan
[0] != 't'))
1846 else if ((scan
== *mangled
)
1847 && (isdigit (scan
[2]) || (scan
[2] == 'Q') || (scan
[2] == 't')
1848 || (scan
[2] == 'K') || (scan
[2] == 'H')))
1850 /* The ARM says nothing about the mangling of local variables.
1851 But cfront mangles local variables by prepending __<nesting_level>
1852 to them. As an extension to ARM demangling we handle this case. */
1853 if ((LUCID_DEMANGLING
|| ARM_DEMANGLING
) && isdigit (scan
[2]))
1855 *mangled
= scan
+ 2;
1856 consume_count (mangled
);
1857 string_append (declp
, *mangled
);
1858 *mangled
+= strlen (*mangled
);
1863 /* A GNU style constructor starts with __[0-9Qt]. But cfront uses
1864 names like __Q2_3foo3bar for nested type names. So don't accept
1865 this style of constructor for cfront demangling. A GNU
1866 style member-template constructor starts with 'H'. */
1867 if (!(LUCID_DEMANGLING
|| ARM_DEMANGLING
))
1868 work
-> constructor
+= 1;
1869 *mangled
= scan
+ 2;
1872 else if ((scan
== *mangled
) && !isdigit (scan
[2]) && (scan
[2] != 't'))
1874 /* Mangled name starts with "__". Skip over any leading '_' characters,
1875 then find the next "__" that separates the prefix from the signature.
1877 if (!(ARM_DEMANGLING
|| LUCID_DEMANGLING
)
1878 || (arm_special (mangled
, declp
) == 0))
1880 while (*scan
== '_')
1884 if ((scan
= mystrstr (scan
, "__")) == NULL
|| (*(scan
+ 2) == '\0'))
1886 /* No separator (I.E. "__not_mangled"), or empty signature
1887 (I.E. "__not_mangled_either__") */
1892 demangle_function_name (work
, mangled
, declp
, scan
);
1896 else if (ARM_DEMANGLING
&& scan
[2] == 'p' && scan
[3] == 't')
1898 /* Cfront-style parameterized type. Handled later as a signature. */
1902 demangle_arm_pt (work
, mangled
, strlen (*mangled
), declp
);
1904 else if (*(scan
+ 2) != '\0')
1906 /* Mangled name does not start with "__" but does have one somewhere
1907 in there with non empty stuff after it. Looks like a global
1909 demangle_function_name (work
, mangled
, declp
, scan
);
1913 /* Doesn't look like a mangled name */
1917 if (!success
&& (work
->constructor
== 2 || work
->destructor
== 2))
1919 string_append (declp
, *mangled
);
1920 *mangled
+= strlen (*mangled
);
1930 gnu_special -- special handling of gnu mangled strings
1935 gnu_special (struct work_stuff *work, const char **mangled,
1941 Process some special GNU style mangling forms that don't fit
1942 the normal pattern. For example:
1944 _$_3foo (destructor for class foo)
1945 _vt$foo (foo virtual table)
1946 _vt$foo$bar (foo::bar virtual table)
1947 __vt_foo (foo virtual table, new style with thunks)
1948 _3foo$varname (static data member)
1949 _Q22rs2tu$vw (static data member)
1950 __t6vector1Zii (constructor with template)
1951 __thunk_4__$_7ostream (virtual function thunk)
1955 gnu_special (work
, mangled
, declp
)
1956 struct work_stuff
*work
;
1957 const char **mangled
;
1964 if ((*mangled
)[0] == '_'
1965 && strchr (cplus_markers
, (*mangled
)[1]) != NULL
1966 && (*mangled
)[2] == '_')
1968 /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
1970 work
-> destructor
+= 1;
1972 else if ((*mangled
)[0] == '_'
1973 && (((*mangled
)[1] == '_'
1974 && (*mangled
)[2] == 'v'
1975 && (*mangled
)[3] == 't'
1976 && (*mangled
)[4] == '_')
1977 || ((*mangled
)[1] == 'v'
1978 && (*mangled
)[2] == 't'
1979 && strchr (cplus_markers
, (*mangled
)[3]) != NULL
)))
1981 /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
1982 and create the decl. Note that we consume the entire mangled
1983 input string, which means that demangle_signature has no work
1985 if ((*mangled
)[2] == 'v')
1986 (*mangled
) += 5; /* New style, with thunks: "__vt_" */
1988 (*mangled
) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
1989 while (**mangled
!= '\0')
1991 p
= strpbrk (*mangled
, cplus_markers
);
1996 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
1999 success
= demangle_template (work
, mangled
, declp
, 0, 1);
2002 if (isdigit(*mangled
[0]))
2004 n
= consume_count(mangled
);
2005 /* We may be seeing a too-large size, or else a
2006 ".<digits>" indicating a static local symbol. In
2007 any case, declare victory and move on; *don't* try
2008 to use n to allocate. */
2009 if (n
> strlen (*mangled
))
2017 n
= strcspn (*mangled
, cplus_markers
);
2019 string_appendn (declp
, *mangled
, n
);
2023 if (success
&& ((p
== NULL
) || (p
== *mangled
)))
2027 string_append (declp
,
2028 (work
-> options
& DMGL_JAVA
) ? "." : "::");
2039 string_append (declp
, " virtual table");
2041 else if ((*mangled
)[0] == '_'
2042 && (strchr("0123456789Qt", (*mangled
)[1]) != NULL
)
2043 && (p
= strpbrk (*mangled
, cplus_markers
)) != NULL
)
2045 /* static data member, "_3foo$varname" for example */
2051 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
2054 success
= demangle_template (work
, mangled
, declp
, 0, 1);
2057 n
= consume_count (mangled
);
2058 string_appendn (declp
, *mangled
, n
);
2061 if (success
&& (p
== *mangled
))
2063 /* Consumed everything up to the cplus_marker, append the
2066 string_append (declp
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
2067 n
= strlen (*mangled
);
2068 string_appendn (declp
, *mangled
, n
);
2076 else if (strncmp (*mangled
, "__thunk_", 8) == 0)
2078 int delta
= ((*mangled
) += 8, consume_count (mangled
));
2079 char *method
= internal_cplus_demangle (work
, ++*mangled
);
2083 sprintf (buf
, "virtual function thunk (delta:%d) for ", -delta
);
2084 string_append (declp
, buf
);
2085 string_append (declp
, method
);
2087 n
= strlen (*mangled
);
2095 else if (strncmp (*mangled
, "__t", 3) == 0
2096 && ((*mangled
)[3] == 'i' || (*mangled
)[3] == 'f'))
2098 p
= (*mangled
)[3] == 'i' ? " type_info node" : " type_info function";
2104 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
2107 success
= demangle_template (work
, mangled
, declp
, 0, 1);
2110 success
= demangle_fund_type (work
, mangled
, declp
);
2113 if (success
&& **mangled
!= '\0')
2116 string_append (declp
, p
);
2129 arm_special -- special handling of ARM/lucid mangled strings
2134 arm_special (const char **mangled,
2140 Process some special ARM style mangling forms that don't fit
2141 the normal pattern. For example:
2143 __vtbl__3foo (foo virtual table)
2144 __vtbl__3foo__3bar (bar::foo virtual table)
2149 arm_special (mangled
, declp
)
2150 const char **mangled
;
2157 if (strncmp (*mangled
, ARM_VTABLE_STRING
, ARM_VTABLE_STRLEN
) == 0)
2159 /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
2160 and create the decl. Note that we consume the entire mangled
2161 input string, which means that demangle_signature has no work
2163 scan
= *mangled
+ ARM_VTABLE_STRLEN
;
2164 while (*scan
!= '\0') /* first check it can be demangled */
2166 n
= consume_count (&scan
);
2169 return (0); /* no good */
2172 if (scan
[0] == '_' && scan
[1] == '_')
2177 (*mangled
) += ARM_VTABLE_STRLEN
;
2178 while (**mangled
!= '\0')
2180 n
= consume_count (mangled
);
2181 string_prependn (declp
, *mangled
, n
);
2183 if ((*mangled
)[0] == '_' && (*mangled
)[1] == '_')
2185 string_prepend (declp
, "::");
2189 string_append (declp
, " virtual table");
2202 demangle_qualified -- demangle 'Q' qualified name strings
2207 demangle_qualified (struct work_stuff *, const char *mangled,
2208 string *result, int isfuncname, int append);
2212 Demangle a qualified name, such as "Q25Outer5Inner" which is
2213 the mangled form of "Outer::Inner". The demangled output is
2214 prepended or appended to the result string according to the
2215 state of the append flag.
2217 If isfuncname is nonzero, then the qualified name we are building
2218 is going to be used as a member function name, so if it is a
2219 constructor or destructor function, append an appropriate
2220 constructor or destructor name. I.E. for the above example,
2221 the result for use as a constructor is "Outer::Inner::Inner"
2222 and the result for use as a destructor is "Outer::Inner::~Inner".
2226 Numeric conversion is ASCII dependent (FIXME).
2231 demangle_qualified (work
, mangled
, result
, isfuncname
, append
)
2232 struct work_stuff
*work
;
2233 const char **mangled
;
2245 string_init (&temp
);
2247 if ((*mangled
)[0] == 'K')
2249 /* Squangling qualified name reuse */
2252 idx
= consume_count_with_underscores (mangled
);
2253 if (idx
== -1 || idx
> work
-> numk
)
2256 string_append (&temp
, work
-> ktypevec
[idx
]);
2259 switch ((*mangled
)[1])
2262 /* GNU mangled name with more than 9 classes. The count is preceded
2263 by an underscore (to distinguish it from the <= 9 case) and followed
2264 by an underscore. */
2266 qualifiers
= atoi (p
);
2267 if (!isdigit (*p
) || *p
== '0')
2270 /* Skip the digits. */
2271 while (isdigit (*p
))
2289 /* The count is in a single digit. */
2290 num
[0] = (*mangled
)[1];
2292 qualifiers
= atoi (num
);
2294 /* If there is an underscore after the digit, skip it. This is
2295 said to be for ARM-qualified names, but the ARM makes no
2296 mention of such an underscore. Perhaps cfront uses one. */
2297 if ((*mangled
)[2] == '_')
2312 /* Pick off the names and collect them in the temp buffer in the order
2313 in which they are found, separated by '::'. */
2315 while (qualifiers
-- > 0)
2318 if (*mangled
[0] == '_')
2319 *mangled
= *mangled
+ 1;
2320 if (*mangled
[0] == 't')
2322 success
= demangle_template(work
, mangled
, &temp
, 0, 1);
2323 if (!success
) break;
2325 else if (*mangled
[0] == 'X')
2327 success
= do_type (work
, mangled
, &temp
);
2328 if (!success
) break;
2330 else if (*mangled
[0] == 'K')
2334 idx
= consume_count_with_underscores (mangled
);
2335 if (idx
== -1 || idx
> work
->numk
)
2338 string_append (&temp
, work
->ktypevec
[idx
]);
2341 if (!success
) break;
2345 namelength
= consume_count (mangled
);
2346 if (strlen (*mangled
) < namelength
)
2348 /* Simple sanity check failed */
2352 string_appendn (&temp
, *mangled
, namelength
);
2353 *mangled
+= namelength
;
2358 remember_Ktype (work
, temp
.b
, LEN_STRING (&temp
));
2363 string_append (&temp
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
2367 /* If we are using the result as a function name, we need to append
2368 the appropriate '::' separated constructor or destructor name.
2369 We do this here because this is the most convenient place, where
2370 we already have a pointer to the name and the length of the name. */
2372 if (isfuncname
&& (work
->constructor
& 1 || work
->destructor
& 1))
2374 string_append (&temp
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
2375 if (work
-> destructor
& 1)
2377 string_append (&temp
, "~");
2379 string_appendn (&temp
, (*mangled
) - namelength
, namelength
);
2382 /* Now either prepend the temp buffer to the result, or append it,
2383 depending upon the state of the append flag. */
2387 string_appends (result
, &temp
);
2391 if (!STRING_EMPTY (result
))
2393 string_append (&temp
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
2395 string_prepends (result
, &temp
);
2398 string_delete (&temp
);
2406 get_count -- convert an ascii count to integer, consuming tokens
2411 get_count (const char **type, int *count)
2415 Return 0 if no conversion is performed, 1 if a string is converted.
2419 get_count (type
, count
)
2426 if (!isdigit (**type
))
2432 *count
= **type
- '0';
2434 if (isdigit (**type
))
2444 while (isdigit (*p
));
2455 /* result will be initialised here; it will be freed on failure */
2458 do_type (work
, mangled
, result
)
2459 struct work_stuff
*work
;
2460 const char **mangled
;
2467 const char *remembered_type
;
2472 string_init (&btype
);
2473 string_init (&decl
);
2474 string_init (result
);
2478 while (success
&& !done
)
2484 /* A pointer type */
2488 if (! (work
-> options
& DMGL_JAVA
))
2489 string_prepend (&decl
, "*");
2492 /* A reference type */
2495 string_prepend (&decl
, "&");
2501 const char *p
= ++(*mangled
);
2503 string_prepend (&decl
, "(");
2504 string_append (&decl
, ")[");
2505 /* Copy anything up until the next underscore (the size of the
2507 while (**mangled
&& **mangled
!= '_')
2509 if (**mangled
== '_')
2511 string_appendn (&decl
, p
, *mangled
- p
);
2512 string_append (&decl
, "]");
2520 /* A back reference to a previously seen type */
2523 if (!get_count (mangled
, &n
) || n
>= work
-> ntypes
)
2529 remembered_type
= work
-> typevec
[n
];
2530 mangled
= &remembered_type
;
2537 if (!STRING_EMPTY (&decl
) && decl
.b
[0] == '*')
2539 string_prepend (&decl
, "(");
2540 string_append (&decl
, ")");
2542 /* After picking off the function args, we expect to either find the
2543 function return type (preceded by an '_') or the end of the
2545 if (!demangle_args (work
, mangled
, &decl
)
2546 || (**mangled
!= '_' && **mangled
!= '\0'))
2550 if (success
&& (**mangled
== '_'))
2562 member
= **mangled
== 'M';
2564 if (!isdigit (**mangled
) && **mangled
!= 't')
2570 string_append (&decl
, ")");
2571 string_prepend (&decl
, (work
-> options
& DMGL_JAVA
) ? "." : "::");
2572 if (isdigit (**mangled
))
2574 n
= consume_count (mangled
);
2575 if (strlen (*mangled
) < n
)
2580 string_prependn (&decl
, *mangled
, n
);
2586 string_init (&temp
);
2587 success
= demangle_template (work
, mangled
, &temp
, NULL
, 1);
2590 string_prependn (&decl
, temp
.b
, temp
.p
- temp
.b
);
2591 string_clear (&temp
);
2596 string_prepend (&decl
, "(");
2599 if (**mangled
== 'C')
2604 if (**mangled
== 'V')
2609 if (*(*mangled
)++ != 'F')
2615 if ((member
&& !demangle_args (work
, mangled
, &decl
))
2616 || **mangled
!= '_')
2622 if (! PRINT_ANSI_QUALIFIERS
)
2628 APPEND_BLANK (&decl
);
2629 string_append (&decl
, "const");
2633 APPEND_BLANK (&decl
);
2634 string_append (&decl
, "volatile");
2645 if ((*mangled)[1] == 'P')
2648 if (PRINT_ANSI_QUALIFIERS
)
2650 if (!STRING_EMPTY (&decl
))
2652 string_prepend (&decl
, " ");
2654 string_prepend (&decl
, "const");
2670 /* A qualified name, such as "Outer::Inner". */
2674 int btype
= register_Btype (work
);
2675 success
= demangle_qualified (work
, mangled
, result
, 0, 1);
2676 remember_Btype (work
, result
->b
, LEN_STRING (result
), btype
);
2681 /* A back reference to a previously seen squangled type */
2684 if (!get_count (mangled
, &n
) || n
>= work
-> numb
)
2688 string_append (result
, work
->btypevec
[n
]);
2694 /* A template parm. We substitute the corresponding argument. */
2699 idx
= consume_count_with_underscores (mangled
);
2702 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
2703 || consume_count_with_underscores (mangled
) == -1)
2709 if (work
->tmpl_argvec
)
2710 string_append (result
, work
->tmpl_argvec
[idx
]);
2714 sprintf(buf
, "T%d", idx
);
2715 string_append (result
, buf
);
2723 success
= demangle_fund_type (work
, mangled
, result
);
2729 if (!STRING_EMPTY (&decl
))
2731 string_append (result
, " ");
2732 string_appends (result
, &decl
);
2737 string_delete (result
);
2739 string_delete (&decl
);
2743 /* Given a pointer to a type string that represents a fundamental type
2744 argument (int, long, unsigned int, etc) in TYPE, a pointer to the
2745 string in which the demangled output is being built in RESULT, and
2746 the WORK structure, decode the types and add them to the result.
2751 "Sl" => "signed long"
2752 "CUs" => "const unsigned short"
2757 demangle_fund_type (work
, mangled
, result
)
2758 struct work_stuff
*work
;
2759 const char **mangled
;
2765 string_init (&btype
);
2767 /* First pick off any type qualifiers. There can be more than one. */
2775 if (PRINT_ANSI_QUALIFIERS
)
2777 APPEND_BLANK (result
);
2778 string_append (result
, "const");
2783 APPEND_BLANK (result
);
2784 string_append (result
, "unsigned");
2786 case 'S': /* signed char only */
2788 APPEND_BLANK (result
);
2789 string_append (result
, "signed");
2793 if (PRINT_ANSI_QUALIFIERS
)
2795 APPEND_BLANK (result
);
2796 string_append (result
, "volatile");
2801 APPEND_BLANK (result
);
2802 string_append (result
, "__complex");
2810 /* Now pick off the fundamental type. There can be only one. */
2819 APPEND_BLANK (result
);
2820 string_append (result
, "void");
2824 APPEND_BLANK (result
);
2825 string_append (result
, "long long");
2829 APPEND_BLANK (result
);
2830 string_append (result
, "long");
2834 APPEND_BLANK (result
);
2835 string_append (result
, "int");
2839 APPEND_BLANK (result
);
2840 string_append (result
, "short");
2844 APPEND_BLANK (result
);
2845 string_append (result
, "bool");
2849 APPEND_BLANK (result
);
2850 string_append (result
, "char");
2854 APPEND_BLANK (result
);
2855 string_append (result
, "wchar_t");
2859 APPEND_BLANK (result
);
2860 string_append (result
, "long double");
2864 APPEND_BLANK (result
);
2865 string_append (result
, "double");
2869 APPEND_BLANK (result
);
2870 string_append (result
, "float");
2874 if (!isdigit (**mangled
))
2880 /* An explicit type, such as "6mytype" or "7integer" */
2892 int bindex
= register_Btype (work
);
2894 string_init (&btype
);
2895 if (demangle_class_name (work
, mangled
, &btype
)) {
2896 remember_Btype (work
, btype
.b
, LEN_STRING (&btype
), bindex
);
2897 APPEND_BLANK (result
);
2898 string_appends (result
, &btype
);
2902 string_delete (&btype
);
2907 int bindex
= register_Btype (work
);
2908 success
= demangle_template (work
, mangled
, &btype
, 0, 1);
2909 remember_Btype (work
, btype
.b
, LEN_STRING (&btype
), bindex
);
2910 string_appends (result
, &btype
);
2921 /* `result' will be initialized in do_type; it will be freed on failure */
2924 do_arg (work
, mangled
, result
)
2925 struct work_stuff
*work
;
2926 const char **mangled
;
2929 const char *start
= *mangled
;
2931 if (!do_type (work
, mangled
, result
))
2937 remember_type (work
, start
, *mangled
- start
);
2943 remember_type (work
, start
, len
)
2944 struct work_stuff
*work
;
2950 if (work
-> ntypes
>= work
-> typevec_size
)
2952 if (work
-> typevec_size
== 0)
2954 work
-> typevec_size
= 3;
2956 = (char **) xmalloc (sizeof (char *) * work
-> typevec_size
);
2960 work
-> typevec_size
*= 2;
2962 = (char **) xrealloc ((char *)work
-> typevec
,
2963 sizeof (char *) * work
-> typevec_size
);
2966 tem
= xmalloc (len
+ 1);
2967 memcpy (tem
, start
, len
);
2969 work
-> typevec
[work
-> ntypes
++] = tem
;
2973 /* Remember a K type class qualifier. */
2975 remember_Ktype (work
, start
, len
)
2976 struct work_stuff
*work
;
2982 if (work
-> numk
>= work
-> ksize
)
2984 if (work
-> ksize
== 0)
2988 = (char **) xmalloc (sizeof (char *) * work
-> ksize
);
2994 = (char **) xrealloc ((char *)work
-> ktypevec
,
2995 sizeof (char *) * work
-> ksize
);
2998 tem
= xmalloc (len
+ 1);
2999 memcpy (tem
, start
, len
);
3001 work
-> ktypevec
[work
-> numk
++] = tem
;
3004 /* Register a B code, and get an index for it. B codes are registered
3005 as they are seen, rather than as they are completed, so map<temp<char> >
3006 registers map<temp<char> > as B0, and temp<char> as B1 */
3009 register_Btype (work
)
3010 struct work_stuff
*work
;
3014 if (work
-> numb
>= work
-> bsize
)
3016 if (work
-> bsize
== 0)
3020 = (char **) xmalloc (sizeof (char *) * work
-> bsize
);
3026 = (char **) xrealloc ((char *)work
-> btypevec
,
3027 sizeof (char *) * work
-> bsize
);
3030 ret
= work
-> numb
++;
3031 work
-> btypevec
[ret
] = NULL
;
3035 /* Store a value into a previously registered B code type. */
3038 remember_Btype (work
, start
, len
, index
)
3039 struct work_stuff
*work
;
3045 tem
= xmalloc (len
+ 1);
3046 memcpy (tem
, start
, len
);
3048 work
-> btypevec
[index
] = tem
;
3051 /* Lose all the info related to B and K type codes. */
3053 forget_B_and_K_types (work
)
3054 struct work_stuff
*work
;
3058 while (work
-> numk
> 0)
3060 i
= --(work
-> numk
);
3061 if (work
-> ktypevec
[i
] != NULL
)
3063 free (work
-> ktypevec
[i
]);
3064 work
-> ktypevec
[i
] = NULL
;
3068 while (work
-> numb
> 0)
3070 i
= --(work
-> numb
);
3071 if (work
-> btypevec
[i
] != NULL
)
3073 free (work
-> btypevec
[i
]);
3074 work
-> btypevec
[i
] = NULL
;
3078 /* Forget the remembered types, but not the type vector itself. */
3082 struct work_stuff
*work
;
3086 while (work
-> ntypes
> 0)
3088 i
= --(work
-> ntypes
);
3089 if (work
-> typevec
[i
] != NULL
)
3091 free (work
-> typevec
[i
]);
3092 work
-> typevec
[i
] = NULL
;
3097 /* Process the argument list part of the signature, after any class spec
3098 has been consumed, as well as the first 'F' character (if any). For
3101 "__als__3fooRT0" => process "RT0"
3102 "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i"
3104 DECLP must be already initialised, usually non-empty. It won't be freed
3107 Note that g++ differs significantly from ARM and lucid style mangling
3108 with regards to references to previously seen types. For example, given
3109 the source fragment:
3113 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
3116 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3117 void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3119 g++ produces the names:
3124 while lcc (and presumably other ARM style compilers as well) produces:
3126 foo__FiR3fooT1T2T1T2
3127 __ct__3fooFiR3fooT1T2T1T2
3129 Note that g++ bases it's type numbers starting at zero and counts all
3130 previously seen types, while lucid/ARM bases it's type numbers starting
3131 at one and only considers types after it has seen the 'F' character
3132 indicating the start of the function args. For lucid/ARM style, we
3133 account for this difference by discarding any previously seen types when
3134 we see the 'F' character, and subtracting one from the type number
3140 demangle_args (work
, mangled
, declp
)
3141 struct work_stuff
*work
;
3142 const char **mangled
;
3152 if (PRINT_ARG_TYPES
)
3154 string_append (declp
, "(");
3155 if (**mangled
== '\0')
3157 string_append (declp
, "void");
3161 while (**mangled
!= '_' && **mangled
!= '\0' && **mangled
!= 'e')
3163 if ((**mangled
== 'N') || (**mangled
== 'T'))
3165 temptype
= *(*mangled
)++;
3167 if (temptype
== 'N')
3169 if (!get_count (mangled
, &r
))
3178 if (ARM_DEMANGLING
&& work
-> ntypes
>= 10)
3180 /* If we have 10 or more types we might have more than a 1 digit
3181 index so we'll have to consume the whole count here. This
3182 will lose if the next thing is a type name preceded by a
3183 count but it's impossible to demangle that case properly
3184 anyway. Eg if we already have 12 types is T12Pc "(..., type1,
3185 Pc, ...)" or "(..., type12, char *, ...)" */
3186 if ((t
= consume_count(mangled
)) == 0)
3193 if (!get_count (mangled
, &t
))
3198 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
3202 /* Validate the type index. Protect against illegal indices from
3203 malformed type strings. */
3204 if ((t
< 0) || (t
>= work
-> ntypes
))
3210 tem
= work
-> typevec
[t
];
3211 if (need_comma
&& PRINT_ARG_TYPES
)
3213 string_append (declp
, ", ");
3215 if (!do_arg (work
, &tem
, &arg
))
3219 if (PRINT_ARG_TYPES
)
3221 string_appends (declp
, &arg
);
3223 string_delete (&arg
);
3229 if (need_comma
& PRINT_ARG_TYPES
)
3231 string_append (declp
, ", ");
3233 if (!do_arg (work
, mangled
, &arg
))
3237 if (PRINT_ARG_TYPES
)
3239 string_appends (declp
, &arg
);
3241 string_delete (&arg
);
3246 if (**mangled
== 'e')
3249 if (PRINT_ARG_TYPES
)
3253 string_append (declp
, ",");
3255 string_append (declp
, "...");
3259 if (PRINT_ARG_TYPES
)
3261 string_append (declp
, ")");
3267 demangle_function_name (work
, mangled
, declp
, scan
)
3268 struct work_stuff
*work
;
3269 const char **mangled
;
3277 string_appendn (declp
, (*mangled
), scan
- (*mangled
));
3278 string_need (declp
, 1);
3279 *(declp
-> p
) = '\0';
3281 /* Consume the function name, including the "__" separating the name
3282 from the signature. We are guaranteed that SCAN points to the
3285 (*mangled
) = scan
+ 2;
3287 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
3290 /* See if we have an ARM style constructor or destructor operator.
3291 If so, then just record it, clear the decl, and return.
3292 We can't build the actual constructor/destructor decl until later,
3293 when we recover the class name from the signature. */
3295 if (strcmp (declp
-> b
, "__ct") == 0)
3297 work
-> constructor
+= 1;
3298 string_clear (declp
);
3301 else if (strcmp (declp
-> b
, "__dt") == 0)
3303 work
-> destructor
+= 1;
3304 string_clear (declp
);
3309 if (declp
->p
- declp
->b
>= 3
3310 && declp
->b
[0] == 'o'
3311 && declp
->b
[1] == 'p'
3312 && strchr (cplus_markers
, declp
->b
[2]) != NULL
)
3314 /* see if it's an assignment expression */
3315 if (declp
->p
- declp
->b
>= 10 /* op$assign_ */
3316 && memcmp (declp
->b
+ 3, "assign_", 7) == 0)
3318 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3320 int len
= declp
->p
- declp
->b
- 10;
3321 if (strlen (optable
[i
].in
) == len
3322 && memcmp (optable
[i
].in
, declp
->b
+ 10, len
) == 0)
3324 string_clear (declp
);
3325 string_append (declp
, "operator");
3326 string_append (declp
, optable
[i
].out
);
3327 string_append (declp
, "=");
3334 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3336 int len
= declp
->p
- declp
->b
- 3;
3337 if (strlen (optable
[i
].in
) == len
3338 && memcmp (optable
[i
].in
, declp
->b
+ 3, len
) == 0)
3340 string_clear (declp
);
3341 string_append (declp
, "operator");
3342 string_append (declp
, optable
[i
].out
);
3348 else if (declp
->p
- declp
->b
>= 5 && memcmp (declp
->b
, "type", 4) == 0
3349 && strchr (cplus_markers
, declp
->b
[4]) != NULL
)
3351 /* type conversion operator */
3353 if (do_type (work
, &tem
, &type
))
3355 string_clear (declp
);
3356 string_append (declp
, "operator ");
3357 string_appends (declp
, &type
);
3358 string_delete (&type
);
3361 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
3362 && declp
->b
[2] == 'o' && declp
->b
[3] == 'p')
3365 /* type conversion operator. */
3367 if (do_type (work
, &tem
, &type
))
3369 string_clear (declp
);
3370 string_append (declp
, "operator ");
3371 string_appends (declp
, &type
);
3372 string_delete (&type
);
3375 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
3376 && declp
->b
[2] >= 'a' && declp
->b
[2] <= 'z'
3377 && declp
->b
[3] >= 'a' && declp
->b
[3] <= 'z')
3379 if (declp
->b
[4] == '\0')
3382 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3384 if (strlen (optable
[i
].in
) == 2
3385 && memcmp (optable
[i
].in
, declp
->b
+ 2, 2) == 0)
3387 string_clear (declp
);
3388 string_append (declp
, "operator");
3389 string_append (declp
, optable
[i
].out
);
3396 if (declp
->b
[2] == 'a' && declp
->b
[5] == '\0')
3399 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3401 if (strlen (optable
[i
].in
) == 3
3402 && memcmp (optable
[i
].in
, declp
->b
+ 2, 3) == 0)
3404 string_clear (declp
);
3405 string_append (declp
, "operator");
3406 string_append (declp
, optable
[i
].out
);
3415 /* a mini string-handling package */
3430 s
->p
= s
->b
= xmalloc (n
);
3433 else if (s
->e
- s
->p
< n
)
3438 s
->b
= xrealloc (s
->b
, n
);
3451 s
->b
= s
->e
= s
->p
= NULL
;
3459 s
->b
= s
->p
= s
->e
= NULL
;
3475 return (s
->b
== s
->p
);
3481 string_append (p
, s
)
3486 if (s
== NULL
|| *s
== '\0')
3490 memcpy (p
->p
, s
, n
);
3495 string_appends (p
, s
)
3504 memcpy (p
->p
, s
->b
, n
);
3510 string_appendn (p
, s
, n
)
3518 memcpy (p
->p
, s
, n
);
3524 string_prepend (p
, s
)
3528 if (s
!= NULL
&& *s
!= '\0')
3530 string_prependn (p
, s
, strlen (s
));
3535 string_prepends (p
, s
)
3540 string_prependn (p
, s
->b
, s
->p
- s
->b
);
3545 string_prependn (p
, s
, n
)
3555 for (q
= p
->p
- 1; q
>= p
->b
; q
--)
3559 memcpy (p
->b
, s
, n
);
3564 /* To generate a standalone demangler program for testing purposes,
3565 just compile and link this file with -DMAIN and libiberty.a. When
3566 run, it demangles each command line arg, or each stdin string, and
3567 prints the result on stdout. */
3573 static char *program_name
;
3574 static char *program_version
= VERSION
;
3575 static int flags
= DMGL_PARAMS
| DMGL_ANSI
;
3577 static void demangle_it
PARAMS ((char *));
3578 static void usage
PARAMS ((FILE *, int));
3579 static void fatal
PARAMS ((char *));
3582 demangle_it (mangled_name
)
3587 result
= cplus_demangle (mangled_name
, flags
);
3590 printf ("%s\n", mangled_name
);
3594 printf ("%s\n", result
);
3600 usage (stream
, status
)
3605 Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
3606 [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\
3607 [--help] [--version] [arg...]\n",
3612 #define MBUF_SIZE 512
3613 char mbuffer
[MBUF_SIZE
];
3615 /* Defined in the automatically-generated underscore.c. */
3616 extern int prepends_underscore
;
3618 int strip_underscore
= 0;
3620 static struct option long_options
[] = {
3621 {"strip-underscores", no_argument
, 0, '_'},
3622 {"format", required_argument
, 0, 's'},
3623 {"help", no_argument
, 0, 'h'},
3624 {"java", no_argument
, 0, 'j'},
3625 {"no-strip-underscores", no_argument
, 0, 'n'},
3626 {"version", no_argument
, 0, 'v'},
3627 {0, no_argument
, 0, 0}
3630 /* More 'friendly' abort that prints the line and file.
3631 config.h can #define abort fancy_abort if you like that sort of thing. */
3636 fatal ("Internal gcc abort.");
3647 program_name
= argv
[0];
3649 strip_underscore
= prepends_underscore
;
3651 while ((c
= getopt_long (argc
, argv
, "_ns:j", long_options
, (int *) 0)) != EOF
)
3661 strip_underscore
= 0;
3664 printf ("GNU %s version %s\n", program_name
, program_version
);
3667 strip_underscore
= 1;
3673 if (strcmp (optarg
, "gnu") == 0)
3675 current_demangling_style
= gnu_demangling
;
3677 else if (strcmp (optarg
, "lucid") == 0)
3679 current_demangling_style
= lucid_demangling
;
3681 else if (strcmp (optarg
, "arm") == 0)
3683 current_demangling_style
= arm_demangling
;
3687 fprintf (stderr
, "%s: unknown demangling style `%s'\n",
3688 program_name
, optarg
);
3697 for ( ; optind
< argc
; optind
++)
3699 demangle_it (argv
[optind
]);
3708 /* Try to read a label. */
3709 while (c
!= EOF
&& (isalnum(c
) || c
== '_' || c
== '$' || c
== '.'))
3711 if (i
>= MBUF_SIZE
-1)
3720 if (mbuffer
[0] == '.')
3722 if (strip_underscore
&& mbuffer
[skip_first
] == '_')
3730 result
= cplus_demangle (mbuffer
+ skip_first
, flags
);
3733 if (mbuffer
[0] == '.')
3735 fputs (result
, stdout
);
3739 fputs (mbuffer
, stdout
);
3756 fprintf (stderr
, "%s: %s\n", program_name
, str
);
3767 register char *value
= (char *) malloc (size
);
3769 fatal ("virtual memory exhausted");
3774 xrealloc (ptr
, size
)
3778 register char *value
= (char *) realloc (ptr
, size
);
3780 fatal ("virtual memory exhausted");