1 /* Demangler for GNU C++
2 Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998 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 typedef struct string
/* Beware: these aren't required to be */
98 { /* '\0' terminated. */
99 char *b
; /* pointer to start of string */
100 char *p
; /* pointer after last character */
101 char *e
; /* pointer after end of allocated space */
104 /* Stuff that is shared between sub-routines.
105 Using a shared structure allows cplus_demangle to be reentrant. */
121 int static_type
; /* A static member function */
122 int const_type
; /* A const member function */
123 int volatile_type
; /* A volatile member function */
124 char **tmpl_argvec
; /* Template function arguments. */
125 int ntmpl_args
; /* The number of template function arguments. */
126 int forgetting_types
; /* Nonzero if we are not remembering the types
128 string
* previous_argument
; /* The last function argument demangled. */
129 int nrepeats
; /* The number of times to repeat the previous
133 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
134 #define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS)
136 static const struct optable
142 {"nw", " new", DMGL_ANSI
}, /* new (1.92, ansi) */
143 {"dl", " delete", DMGL_ANSI
}, /* new (1.92, ansi) */
144 {"new", " new", 0}, /* old (1.91, and 1.x) */
145 {"delete", " delete", 0}, /* old (1.91, and 1.x) */
146 {"vn", " new []", DMGL_ANSI
}, /* GNU, pending ansi */
147 {"vd", " delete []", DMGL_ANSI
}, /* GNU, pending ansi */
148 {"as", "=", DMGL_ANSI
}, /* ansi */
149 {"ne", "!=", DMGL_ANSI
}, /* old, ansi */
150 {"eq", "==", DMGL_ANSI
}, /* old, ansi */
151 {"ge", ">=", DMGL_ANSI
}, /* old, ansi */
152 {"gt", ">", DMGL_ANSI
}, /* old, ansi */
153 {"le", "<=", DMGL_ANSI
}, /* old, ansi */
154 {"lt", "<", DMGL_ANSI
}, /* old, ansi */
155 {"plus", "+", 0}, /* old */
156 {"pl", "+", DMGL_ANSI
}, /* ansi */
157 {"apl", "+=", DMGL_ANSI
}, /* ansi */
158 {"minus", "-", 0}, /* old */
159 {"mi", "-", DMGL_ANSI
}, /* ansi */
160 {"ami", "-=", DMGL_ANSI
}, /* ansi */
161 {"mult", "*", 0}, /* old */
162 {"ml", "*", DMGL_ANSI
}, /* ansi */
163 {"amu", "*=", DMGL_ANSI
}, /* ansi (ARM/Lucid) */
164 {"aml", "*=", DMGL_ANSI
}, /* ansi (GNU/g++) */
165 {"convert", "+", 0}, /* old (unary +) */
166 {"negate", "-", 0}, /* old (unary -) */
167 {"trunc_mod", "%", 0}, /* old */
168 {"md", "%", DMGL_ANSI
}, /* ansi */
169 {"amd", "%=", DMGL_ANSI
}, /* ansi */
170 {"trunc_div", "/", 0}, /* old */
171 {"dv", "/", DMGL_ANSI
}, /* ansi */
172 {"adv", "/=", DMGL_ANSI
}, /* ansi */
173 {"truth_andif", "&&", 0}, /* old */
174 {"aa", "&&", DMGL_ANSI
}, /* ansi */
175 {"truth_orif", "||", 0}, /* old */
176 {"oo", "||", DMGL_ANSI
}, /* ansi */
177 {"truth_not", "!", 0}, /* old */
178 {"nt", "!", DMGL_ANSI
}, /* ansi */
179 {"postincrement","++", 0}, /* old */
180 {"pp", "++", DMGL_ANSI
}, /* ansi */
181 {"postdecrement","--", 0}, /* old */
182 {"mm", "--", DMGL_ANSI
}, /* ansi */
183 {"bit_ior", "|", 0}, /* old */
184 {"or", "|", DMGL_ANSI
}, /* ansi */
185 {"aor", "|=", DMGL_ANSI
}, /* ansi */
186 {"bit_xor", "^", 0}, /* old */
187 {"er", "^", DMGL_ANSI
}, /* ansi */
188 {"aer", "^=", DMGL_ANSI
}, /* ansi */
189 {"bit_and", "&", 0}, /* old */
190 {"ad", "&", DMGL_ANSI
}, /* ansi */
191 {"aad", "&=", DMGL_ANSI
}, /* ansi */
192 {"bit_not", "~", 0}, /* old */
193 {"co", "~", DMGL_ANSI
}, /* ansi */
194 {"call", "()", 0}, /* old */
195 {"cl", "()", DMGL_ANSI
}, /* ansi */
196 {"alshift", "<<", 0}, /* old */
197 {"ls", "<<", DMGL_ANSI
}, /* ansi */
198 {"als", "<<=", DMGL_ANSI
}, /* ansi */
199 {"arshift", ">>", 0}, /* old */
200 {"rs", ">>", DMGL_ANSI
}, /* ansi */
201 {"ars", ">>=", DMGL_ANSI
}, /* ansi */
202 {"component", "->", 0}, /* old */
203 {"pt", "->", DMGL_ANSI
}, /* ansi; Lucid C++ form */
204 {"rf", "->", DMGL_ANSI
}, /* ansi; ARM/GNU form */
205 {"indirect", "*", 0}, /* old */
206 {"method_call", "->()", 0}, /* old */
207 {"addr", "&", 0}, /* old (unary &) */
208 {"array", "[]", 0}, /* old */
209 {"vc", "[]", DMGL_ANSI
}, /* ansi */
210 {"compound", ", ", 0}, /* old */
211 {"cm", ", ", DMGL_ANSI
}, /* ansi */
212 {"cond", "?:", 0}, /* old */
213 {"cn", "?:", DMGL_ANSI
}, /* pseudo-ansi */
214 {"max", ">?", 0}, /* old */
215 {"mx", ">?", DMGL_ANSI
}, /* pseudo-ansi */
216 {"min", "<?", 0}, /* old */
217 {"mn", "<?", DMGL_ANSI
}, /* pseudo-ansi */
218 {"nop", "", 0}, /* old (for operator=) */
219 {"rm", "->*", DMGL_ANSI
}, /* ansi */
220 {"sz", "sizeof ", DMGL_ANSI
} /* pseudo-ansi */
224 #define STRING_EMPTY(str) ((str) -> b == (str) -> p)
225 #define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
226 string_prepend(str, " ");}
227 #define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
228 string_append(str, " ");}
229 #define LEN_STRING(str) ( (STRING_EMPTY(str))?0:((str)->p - (str)->b))
231 /* The scope separator appropriate for the language being demangled. */
232 #define SCOPE_STRING(work) "::"
234 #define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */
235 #define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */
237 /* Prototypes for local functions */
240 mop_up
PARAMS ((struct work_stuff
*, string
*, int));
243 squangle_mop_up
PARAMS ((struct work_stuff
*));
247 demangle_method_args
PARAMS ((struct work_stuff
*, const char **, string
*));
251 internal_cplus_demangle
PARAMS ((struct work_stuff
*, const char *));
254 demangle_template_template_parm
PARAMS ((struct work_stuff
*work
,
255 const char **, string
*));
258 demangle_template
PARAMS ((struct work_stuff
*work
, const char **, string
*,
259 string
*, int, int));
262 arm_pt
PARAMS ((struct work_stuff
*, const char *, int, const char **,
266 demangle_arm_pt
PARAMS ((struct work_stuff
*, const char **, int, string
*));
269 demangle_class_name
PARAMS ((struct work_stuff
*, const char **, string
*));
272 demangle_qualified
PARAMS ((struct work_stuff
*, const char **, string
*,
276 demangle_class
PARAMS ((struct work_stuff
*, const char **, string
*));
279 demangle_fund_type
PARAMS ((struct work_stuff
*, const char **, string
*));
282 demangle_signature
PARAMS ((struct work_stuff
*, const char **, string
*));
285 demangle_prefix
PARAMS ((struct work_stuff
*, const char **, string
*));
288 gnu_special
PARAMS ((struct work_stuff
*, const char **, string
*));
291 arm_special
PARAMS ((const char **, string
*));
294 string_need
PARAMS ((string
*, int));
297 string_delete
PARAMS ((string
*));
300 string_init
PARAMS ((string
*));
303 string_clear
PARAMS ((string
*));
307 string_empty
PARAMS ((string
*));
311 string_append
PARAMS ((string
*, const char *));
314 string_appends
PARAMS ((string
*, string
*));
317 string_appendn
PARAMS ((string
*, const char *, int));
320 string_prepend
PARAMS ((string
*, const char *));
323 string_prependn
PARAMS ((string
*, const char *, int));
326 get_count
PARAMS ((const char **, int *));
329 consume_count
PARAMS ((const char **));
332 consume_count_with_underscores
PARAMS ((const char**));
335 demangle_args
PARAMS ((struct work_stuff
*, const char **, string
*));
338 demangle_nested_args
PARAMS ((struct work_stuff
*, const char**, string
*));
341 do_type
PARAMS ((struct work_stuff
*, const char **, string
*));
344 do_arg
PARAMS ((struct work_stuff
*, const char **, string
*));
347 demangle_function_name
PARAMS ((struct work_stuff
*, const char **, string
*,
351 remember_type
PARAMS ((struct work_stuff
*, const char *, int));
354 remember_Btype
PARAMS ((struct work_stuff
*, const char *, int, int));
357 register_Btype
PARAMS ((struct work_stuff
*));
360 remember_Ktype
PARAMS ((struct work_stuff
*, const char *, int));
363 forget_types
PARAMS ((struct work_stuff
*));
366 forget_B_and_K_types
PARAMS ((struct work_stuff
*));
369 string_prepends
PARAMS ((string
*, string
*));
372 demangle_template_value_parm
PARAMS ((struct work_stuff
*,
373 const char**, string
*));
375 /* Translate count to integer, consuming tokens in the process.
376 Conversion terminates on the first non-digit character.
377 Trying to consume something that isn't a count results in
378 no consumption of input and a return of 0. */
386 while (isdigit (**type
))
389 count
+= **type
- '0';
396 /* Like consume_count, but for counts that are preceded and followed
397 by '_' if they are greater than 10. Also, -1 is returned for
398 failure, since 0 can be a valid value. */
401 consume_count_with_underscores (mangled
)
402 const char **mangled
;
406 if (**mangled
== '_')
409 if (!isdigit (**mangled
))
412 idx
= consume_count (mangled
);
413 if (**mangled
!= '_')
414 /* The trailing underscore was missing. */
421 if (**mangled
< '0' || **mangled
> '9')
424 idx
= **mangled
- '0';
432 cplus_demangle_opname (opname
, result
, options
)
439 struct work_stuff work
[1];
442 len
= strlen(opname
);
445 memset ((char *) work
, 0, sizeof (work
));
446 work
->options
= options
;
448 if (opname
[0] == '_' && opname
[1] == '_'
449 && opname
[2] == 'o' && opname
[3] == 'p')
452 /* type conversion operator. */
454 if (do_type (work
, &tem
, &type
))
456 strcat (result
, "operator ");
457 strncat (result
, type
.b
, type
.p
- type
.b
);
458 string_delete (&type
);
462 else if (opname
[0] == '_' && opname
[1] == '_'
463 && opname
[2] >= 'a' && opname
[2] <= 'z'
464 && opname
[3] >= 'a' && opname
[3] <= 'z')
466 if (opname
[4] == '\0')
470 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
472 if (strlen (optable
[i
].in
) == 2
473 && memcmp (optable
[i
].in
, opname
+ 2, 2) == 0)
475 strcat (result
, "operator");
476 strcat (result
, optable
[i
].out
);
484 if (opname
[2] == 'a' && opname
[5] == '\0')
488 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
490 if (strlen (optable
[i
].in
) == 3
491 && memcmp (optable
[i
].in
, opname
+ 2, 3) == 0)
493 strcat (result
, "operator");
494 strcat (result
, optable
[i
].out
);
505 && strchr (cplus_markers
, opname
[2]) != NULL
)
507 /* see if it's an assignment expression */
508 if (len
>= 10 /* op$assign_ */
509 && memcmp (opname
+ 3, "assign_", 7) == 0)
512 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
515 if (strlen (optable
[i
].in
) == len1
516 && memcmp (optable
[i
].in
, opname
+ 10, len1
) == 0)
518 strcat (result
, "operator");
519 strcat (result
, optable
[i
].out
);
520 strcat (result
, "=");
529 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
532 if (strlen (optable
[i
].in
) == len1
533 && memcmp (optable
[i
].in
, opname
+ 3, len1
) == 0)
535 strcat (result
, "operator");
536 strcat (result
, optable
[i
].out
);
543 else if (len
>= 5 && memcmp (opname
, "type", 4) == 0
544 && strchr (cplus_markers
, opname
[4]) != NULL
)
546 /* type conversion operator */
548 if (do_type (work
, &tem
, &type
))
550 strcat (result
, "operator ");
551 strncat (result
, type
.b
, type
.p
- type
.b
);
552 string_delete (&type
);
556 squangle_mop_up (work
);
560 /* Takes operator name as e.g. "++" and returns mangled
561 operator name (e.g. "postincrement_expr"), or NULL if not found.
563 If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
564 if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */
567 cplus_mangle_opname (opname
, options
)
574 len
= strlen (opname
);
575 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
577 if (strlen (optable
[i
].out
) == len
578 && (options
& DMGL_ANSI
) == (optable
[i
].flags
& DMGL_ANSI
)
579 && memcmp (optable
[i
].out
, opname
, len
) == 0)
580 return optable
[i
].in
;
585 /* char *cplus_demangle (const char *mangled, int options)
587 If MANGLED is a mangled function name produced by GNU C++, then
588 a pointer to a malloced string giving a C++ representation
589 of the name will be returned; otherwise NULL will be returned.
590 It is the caller's responsibility to free the string which
593 The OPTIONS arg may contain one or more of the following bits:
595 DMGL_ANSI ANSI qualifiers such as `const' and `void' are
597 DMGL_PARAMS Function parameters are included.
601 cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)"
602 cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
603 cplus_demangle ("foo__1Ai", 0) => "A::foo"
605 cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)"
606 cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
607 cplus_demangle ("foo__1Afe", 0) => "A::foo"
609 Note that any leading underscores, or other such characters prepended by
610 the compilation system, are presumed to have already been stripped from
614 cplus_demangle (mangled
, options
)
619 struct work_stuff work
[1];
620 memset ((char *) work
, 0, sizeof (work
));
621 work
-> options
= options
;
622 if ((work
-> options
& DMGL_STYLE_MASK
) == 0)
623 work
-> options
|= (int) current_demangling_style
& DMGL_STYLE_MASK
;
625 ret
= internal_cplus_demangle (work
, mangled
);
626 squangle_mop_up (work
);
631 /* This function performs most of what cplus_demangle use to do, but
632 to be able to demangle a name with a B, K or n code, we need to
633 have a longer term memory of what types have been seen. The original
634 now intializes and cleans up the squangle code info, while internal
635 calls go directly to this routine to avoid resetting that info. */
638 internal_cplus_demangle (work
, mangled
)
639 struct work_stuff
*work
;
645 char *demangled
= NULL
;
647 int saved_volatile_type
;
648 s1
= work
->constructor
;
649 s2
= work
->destructor
;
650 s3
= work
->static_type
;
651 s4
= work
->const_type
;
652 saved_volatile_type
= work
->volatile_type
;
653 work
->constructor
= work
->destructor
= 0;
654 work
->static_type
= work
->const_type
= 0;
655 work
->volatile_type
= 0;
657 if ((mangled
!= NULL
) && (*mangled
!= '\0'))
661 /* First check to see if gnu style demangling is active and if the
662 string to be demangled contains a CPLUS_MARKER. If so, attempt to
663 recognize one of the gnu special forms rather than looking for a
664 standard prefix. In particular, don't worry about whether there
665 is a "__" string in the mangled string. Consider "_$_5__foo" for
668 if ((AUTO_DEMANGLING
|| GNU_DEMANGLING
))
670 success
= gnu_special (work
, &mangled
, &decl
);
674 success
= demangle_prefix (work
, &mangled
, &decl
);
676 if (success
&& (*mangled
!= '\0'))
678 success
= demangle_signature (work
, &mangled
, &decl
);
680 if (work
->constructor
== 2)
682 string_prepend (&decl
, "global constructors keyed to ");
683 work
->constructor
= 0;
685 else if (work
->destructor
== 2)
687 string_prepend (&decl
, "global destructors keyed to ");
688 work
->destructor
= 0;
690 demangled
= mop_up (work
, &decl
, success
);
692 work
->constructor
= s1
;
693 work
->destructor
= s2
;
694 work
->static_type
= s3
;
695 work
->const_type
= s4
;
696 work
->volatile_type
= saved_volatile_type
;
701 /* Clear out and squangling related storage */
703 squangle_mop_up (work
)
704 struct work_stuff
*work
;
706 /* clean up the B and K type mangling types. */
707 forget_B_and_K_types (work
);
708 if (work
-> btypevec
!= NULL
)
710 free ((char *) work
-> btypevec
);
712 if (work
-> ktypevec
!= NULL
)
714 free ((char *) work
-> ktypevec
);
718 /* Clear out any mangled storage */
721 mop_up (work
, declp
, success
)
722 struct work_stuff
*work
;
726 char *demangled
= NULL
;
728 /* Discard the remembered types, if any. */
731 if (work
-> typevec
!= NULL
)
733 free ((char *) work
-> typevec
);
734 work
-> typevec
= NULL
;
736 if (work
->tmpl_argvec
)
740 for (i
= 0; i
< work
->ntmpl_args
; i
++)
741 if (work
->tmpl_argvec
[i
])
742 free ((char*) work
->tmpl_argvec
[i
]);
744 free ((char*) work
->tmpl_argvec
);
745 work
->tmpl_argvec
= NULL
;
747 if (work
->previous_argument
)
749 string_delete (work
->previous_argument
);
750 free ((char*) work
->previous_argument
);
753 /* If demangling was successful, ensure that the demangled string is null
754 terminated and return it. Otherwise, free the demangling decl. */
758 string_delete (declp
);
762 string_appendn (declp
, "", 1);
763 demangled
= declp
-> b
;
772 demangle_signature -- demangle the signature part of a mangled name
777 demangle_signature (struct work_stuff *work, const char **mangled,
782 Consume and demangle the signature portion of the mangled name.
784 DECLP is the string where demangled output is being built. At
785 entry it contains the demangled root name from the mangled name
786 prefix. I.E. either a demangled operator name or the root function
787 name. In some special cases, it may contain nothing.
789 *MANGLED points to the current unconsumed location in the mangled
790 name. As tokens are consumed and demangling is performed, the
791 pointer is updated to continuously point at the next token to
794 Demangling GNU style mangled names is nasty because there is no
795 explicit token that marks the start of the outermost function
799 demangle_signature (work
, mangled
, declp
)
800 struct work_stuff
*work
;
801 const char **mangled
;
807 int expect_return_type
= 0;
808 const char *oldmangled
= NULL
;
812 while (success
&& (**mangled
!= '\0'))
817 oldmangled
= *mangled
;
818 success
= demangle_qualified (work
, mangled
, declp
, 1, 0);
820 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
821 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
827 oldmangled
= *mangled
;
828 success
= demangle_qualified (work
, mangled
, declp
, 1, 0);
829 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
837 /* Static member function */
838 if (oldmangled
== NULL
)
840 oldmangled
= *mangled
;
843 work
-> static_type
= 1;
848 if (**mangled
== 'C')
849 work
-> const_type
= 1;
851 work
->volatile_type
= 1;
853 /* a qualified member function */
854 if (oldmangled
== NULL
)
855 oldmangled
= *mangled
;
859 case '0': case '1': case '2': case '3': case '4':
860 case '5': case '6': case '7': case '8': case '9':
861 if (oldmangled
== NULL
)
863 oldmangled
= *mangled
;
865 success
= demangle_class (work
, mangled
, declp
);
868 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
870 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
880 success
= do_type (work
, mangled
, &s
);
883 string_append (&s
, SCOPE_STRING (work
));
884 string_prepends (declp
, &s
);
893 /* ARM style demangling includes a specific 'F' character after
894 the class name. For GNU style, it is just implied. So we can
895 safely just consume any 'F' at this point and be compatible
896 with either style. */
902 /* For lucid/ARM style we have to forget any types we might
903 have remembered up to this point, since they were not argument
904 types. GNU style considers all types seen as available for
905 back references. See comment in demangle_args() */
907 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
911 success
= demangle_args (work
, mangled
, declp
);
916 string_init(&trawname
);
918 if (oldmangled
== NULL
)
920 oldmangled
= *mangled
;
922 success
= demangle_template (work
, mangled
, &tname
,
926 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
928 string_append(&tname
, SCOPE_STRING (work
));
929 string_prepends(declp
, &tname
);
930 if (work
-> destructor
& 1)
932 string_prepend (&trawname
, "~");
933 string_appends (declp
, &trawname
);
934 work
->destructor
-= 1;
936 if ((work
->constructor
& 1) || (work
->destructor
& 1))
938 string_appends (declp
, &trawname
);
939 work
->constructor
-= 1;
941 string_delete(&trawname
);
942 string_delete(&tname
);
948 if (GNU_DEMANGLING
&& expect_return_type
)
950 /* Read the return type. */
952 string_init (&return_type
);
955 success
= do_type (work
, mangled
, &return_type
);
956 APPEND_BLANK (&return_type
);
958 string_prepends (declp
, &return_type
);
959 string_delete (&return_type
);
963 /* At the outermost level, we cannot have a return type specified,
964 so if we run into another '_' at this point we are dealing with
965 a mangled name that is either bogus, or has been mangled by
966 some algorithm we don't know how to deal with. So just
967 reject the entire demangling. */
974 /* A G++ template function. Read the template arguments. */
975 success
= demangle_template (work
, mangled
, declp
, 0, 0,
977 if (!(work
->constructor
& 1))
978 expect_return_type
= 1;
987 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
989 /* Assume we have stumbled onto the first outermost function
990 argument token, and start processing args. */
992 success
= demangle_args (work
, mangled
, declp
);
996 /* Non-GNU demanglers use a specific token to mark the start
997 of the outermost function argument tokens. Typically 'F',
998 for ARM-demangling, for example. So if we find something
999 we are not prepared for, it must be an error. */
1005 if (AUTO_DEMANGLING || GNU_DEMANGLING)
1008 if (success
&& expect_func
)
1011 success
= demangle_args (work
, mangled
, declp
);
1012 /* Since template include the mangling of their return types,
1013 we must set expect_func to 0 so that we don't try do
1014 demangle more arguments the next time we get here. */
1019 if (success
&& !func_done
)
1021 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
1023 /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
1024 bar__3fooi is 'foo::bar(int)'. We get here when we find the
1025 first case, and need to ensure that the '(void)' gets added to
1026 the current declp. Note that with ARM, the first case
1027 represents the name of a static data member 'foo::bar',
1028 which is in the current declp, so we leave it alone. */
1029 success
= demangle_args (work
, mangled
, declp
);
1032 if (success
&& work
-> static_type
&& PRINT_ARG_TYPES
)
1033 string_append (declp
, " static");
1034 if (success
&& work
-> const_type
&& PRINT_ARG_TYPES
)
1035 string_append (declp
, " const");
1036 else if (success
&& work
->volatile_type
&& PRINT_ARG_TYPES
)
1037 string_append (declp
, " volatile");
1045 demangle_method_args (work
, mangled
, declp
)
1046 struct work_stuff
*work
;
1047 const char **mangled
;
1052 if (work
-> static_type
)
1054 string_append (declp
, *mangled
+ 1);
1055 *mangled
+= strlen (*mangled
);
1060 success
= demangle_args (work
, mangled
, declp
);
1068 demangle_template_template_parm (work
, mangled
, tname
)
1069 struct work_stuff
*work
;
1070 const char **mangled
;
1079 string_append (tname
, "template <");
1080 /* get size of template parameter list */
1081 if (get_count (mangled
, &r
))
1083 for (i
= 0; i
< r
; i
++)
1087 string_append (tname
, ", ");
1090 /* Z for type parameters */
1091 if (**mangled
== 'Z')
1094 string_append (tname
, "class");
1096 /* z for template parameters */
1097 else if (**mangled
== 'z')
1101 demangle_template_template_parm (work
, mangled
, tname
);
1109 /* temp is initialized in do_type */
1110 success
= do_type (work
, mangled
, &temp
);
1113 string_appends (tname
, &temp
);
1115 string_delete(&temp
);
1125 if (tname
->p
[-1] == '>')
1126 string_append (tname
, " ");
1127 string_append (tname
, "> class");
1132 demangle_integral_value (work
, mangled
, s
)
1133 struct work_stuff
*work
;
1134 const char** mangled
;
1139 if (**mangled
== 'E')
1141 int need_operator
= 0;
1144 string_appendn (s
, "(", 1);
1146 while (success
&& **mangled
!= 'W' && **mangled
!= '\0')
1155 len
= strlen (*mangled
);
1158 i
< sizeof (optable
) / sizeof (optable
[0]);
1161 size_t l
= strlen (optable
[i
].in
);
1164 && memcmp (optable
[i
].in
, *mangled
, l
) == 0)
1166 string_appendn (s
, " ", 1);
1167 string_append (s
, optable
[i
].out
);
1168 string_appendn (s
, " ", 1);
1181 success
= demangle_template_value_parm (work
, mangled
, s
);
1184 if (**mangled
!= 'W')
1188 string_appendn (s
, ")", 1);
1192 else if (**mangled
== 'Q' || **mangled
== 'K')
1193 success
= demangle_qualified (work
, mangled
, s
, 0, 1);
1198 if (**mangled
== 'm')
1200 string_appendn (s
, "-", 1);
1203 while (isdigit (**mangled
))
1205 string_appendn (s
, *mangled
, 1);
1215 demangle_template_value_parm (work
, mangled
, s
)
1216 struct work_stuff
*work
;
1217 const char **mangled
;
1220 const char *old_p
= *mangled
;
1223 int is_integral
= 0;
1229 while (*old_p
&& !done
)
1236 done
= is_pointer
= 1;
1238 case 'C': /* const */
1239 case 'S': /* explicitly signed [char] */
1240 case 'U': /* unsigned */
1241 case 'V': /* volatile */
1242 case 'F': /* function */
1243 case 'M': /* member function */
1245 case 'J': /* complex */
1248 case 'E': /* expression */
1249 case 'Q': /* qualified name */
1250 case 'K': /* qualified name */
1251 done
= is_integral
= 1;
1253 case 'B': /* remembered type */
1254 case 'T': /* remembered type */
1257 case 'v': /* void */
1260 case 'x': /* long long */
1261 case 'l': /* long */
1263 case 's': /* short */
1264 case 'w': /* wchar_t */
1265 done
= is_integral
= 1;
1267 case 'b': /* bool */
1270 case 'c': /* char */
1273 case 'r': /* long double */
1274 case 'd': /* double */
1275 case 'f': /* float */
1279 /* it's probably user defined type, let's assume
1280 it's integral, it seems hard to figure out
1281 what it really is */
1282 done
= is_integral
= 1;
1285 if (**mangled
== 'Y')
1287 /* The next argument is a template parameter. */
1291 idx
= consume_count_with_underscores (mangled
);
1293 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
1294 || consume_count_with_underscores (mangled
) == -1)
1296 if (work
->tmpl_argvec
)
1297 string_append (s
, work
->tmpl_argvec
[idx
]);
1301 sprintf(buf
, "T%d", idx
);
1302 string_append (s
, buf
);
1305 else if (is_integral
)
1306 success
= demangle_integral_value (work
, mangled
, s
);
1311 if (**mangled
== 'm')
1313 string_appendn (s
, "-", 1);
1316 string_appendn (s
, "'", 1);
1317 val
= consume_count(mangled
);
1322 string_appendn (s
, &tmp
[0], 1);
1323 string_appendn (s
, "'", 1);
1327 int val
= consume_count (mangled
);
1329 string_appendn (s
, "false", 5);
1331 string_appendn (s
, "true", 4);
1337 if (**mangled
== 'm')
1339 string_appendn (s
, "-", 1);
1342 while (isdigit (**mangled
))
1344 string_appendn (s
, *mangled
, 1);
1347 if (**mangled
== '.') /* fraction */
1349 string_appendn (s
, ".", 1);
1351 while (isdigit (**mangled
))
1353 string_appendn (s
, *mangled
, 1);
1357 if (**mangled
== 'e') /* exponent */
1359 string_appendn (s
, "e", 1);
1361 while (isdigit (**mangled
))
1363 string_appendn (s
, *mangled
, 1);
1368 else if (is_pointer
)
1370 int symbol_len
= consume_count (mangled
);
1371 if (symbol_len
== 0)
1373 if (symbol_len
== 0)
1374 string_appendn (s
, "0", 1);
1377 char *p
= xmalloc (symbol_len
+ 1), *q
;
1378 strncpy (p
, *mangled
, symbol_len
);
1379 p
[symbol_len
] = '\0';
1380 q
= internal_cplus_demangle (work
, p
);
1381 string_appendn (s
, "&", 1);
1384 string_append (s
, q
);
1388 string_append (s
, p
);
1391 *mangled
+= symbol_len
;
1397 /* Demangle the template name in MANGLED. The full name of the
1398 template (e.g., S<int>) is placed in TNAME. The name without the
1399 template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is
1400 non-NULL. If IS_TYPE is nonzero, this template is a type template,
1401 not a function template. If both IS_TYPE and REMEMBER are nonzero,
1402 the tmeplate is remembered in the list of back-referenceable
1406 demangle_template (work
, mangled
, tname
, trawname
, is_type
, remember
)
1407 struct work_stuff
*work
;
1408 const char **mangled
;
1426 bindex
= register_Btype (work
);
1428 /* get template name */
1429 if (**mangled
== 'z')
1435 idx
= consume_count_with_underscores (mangled
);
1437 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
1438 || consume_count_with_underscores (mangled
) == -1)
1441 if (work
->tmpl_argvec
)
1443 string_append (tname
, work
->tmpl_argvec
[idx
]);
1445 string_append (trawname
, work
->tmpl_argvec
[idx
]);
1450 sprintf(buf
, "T%d", idx
);
1451 string_append (tname
, buf
);
1453 string_append (trawname
, buf
);
1458 if ((r
= consume_count (mangled
)) == 0 || strlen (*mangled
) < r
)
1462 string_appendn (tname
, *mangled
, r
);
1464 string_appendn (trawname
, *mangled
, r
);
1468 string_append (tname
, "<");
1469 /* get size of template parameter list */
1470 if (!get_count (mangled
, &r
))
1476 /* Create an array for saving the template argument values. */
1477 work
->tmpl_argvec
= (char**) xmalloc (r
* sizeof (char *));
1478 work
->ntmpl_args
= r
;
1479 for (i
= 0; i
< r
; i
++)
1480 work
->tmpl_argvec
[i
] = 0;
1482 for (i
= 0; i
< r
; i
++)
1486 string_append (tname
, ", ");
1488 /* Z for type parameters */
1489 if (**mangled
== 'Z')
1492 /* temp is initialized in do_type */
1493 success
= do_type (work
, mangled
, &temp
);
1496 string_appends (tname
, &temp
);
1500 /* Save the template argument. */
1501 int len
= temp
.p
- temp
.b
;
1502 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1503 memcpy (work
->tmpl_argvec
[i
], temp
.b
, len
);
1504 work
->tmpl_argvec
[i
][len
] = '\0';
1507 string_delete(&temp
);
1513 /* z for template parameters */
1514 else if (**mangled
== 'z')
1518 success
= demangle_template_template_parm (work
, mangled
, tname
);
1521 && (r2
= consume_count (mangled
)) > 0 && strlen (*mangled
) >= r2
)
1523 string_append (tname
, " ");
1524 string_appendn (tname
, *mangled
, r2
);
1527 /* Save the template argument. */
1529 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1530 memcpy (work
->tmpl_argvec
[i
], *mangled
, len
);
1531 work
->tmpl_argvec
[i
][len
] = '\0';
1545 /* otherwise, value parameter */
1547 /* temp is initialized in do_type */
1548 success
= do_type (work
, mangled
, &temp
);
1552 string_appends (s, &temp);
1555 string_delete(&temp
);
1561 string_append (s, "=");
1572 success
= demangle_template_value_parm (work
, mangled
, s
);
1584 int len
= s
->p
- s
->b
;
1585 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1586 memcpy (work
->tmpl_argvec
[i
], s
->b
, len
);
1587 work
->tmpl_argvec
[i
][len
] = '\0';
1589 string_appends (tname
, s
);
1595 if (tname
->p
[-1] == '>')
1596 string_append (tname
, " ");
1597 string_append (tname
, ">");
1599 if (is_type
&& remember
)
1600 remember_Btype (work
, tname
->b
, LEN_STRING (tname
), bindex
);
1603 if (work -> static_type)
1605 string_append (declp, *mangled + 1);
1606 *mangled += strlen (*mangled);
1611 success = demangle_args (work, mangled, declp);
1619 arm_pt (work
, mangled
, n
, anchor
, args
)
1620 struct work_stuff
*work
;
1621 const char *mangled
;
1623 const char **anchor
, **args
;
1626 if (ARM_DEMANGLING
&& (*anchor
= mystrstr (mangled
, "__pt__")))
1629 *args
= *anchor
+ 6;
1630 len
= consume_count (args
);
1631 if (*args
+ len
== mangled
+ n
&& **args
== '_')
1641 demangle_arm_pt (work
, mangled
, n
, declp
)
1642 struct work_stuff
*work
;
1643 const char **mangled
;
1649 const char *e
= *mangled
+ n
;
1652 if (arm_pt (work
, *mangled
, n
, &p
, &args
))
1656 string_appendn (declp
, *mangled
, p
- *mangled
);
1657 string_append (declp
, "<");
1658 /* should do error checking here */
1660 string_clear (&arg
);
1661 do_type (work
, &args
, &arg
);
1662 string_appends (declp
, &arg
);
1663 string_append (declp
, ",");
1665 string_delete (&arg
);
1667 string_append (declp
, ">");
1671 string_appendn (declp
, *mangled
, n
);
1677 demangle_class_name (work
, mangled
, declp
)
1678 struct work_stuff
*work
;
1679 const char **mangled
;
1685 n
= consume_count (mangled
);
1686 if (strlen (*mangled
) >= n
)
1688 demangle_arm_pt (work
, mangled
, n
, declp
);
1699 demangle_class -- demangle a mangled class sequence
1704 demangle_class (struct work_stuff *work, const char **mangled,
1709 DECLP points to the buffer into which demangling is being done.
1711 *MANGLED points to the current token to be demangled. On input,
1712 it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
1713 On exit, it points to the next token after the mangled class on
1714 success, or the first unconsumed token on failure.
1716 If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
1717 we are demangling a constructor or destructor. In this case
1718 we prepend "class::class" or "class::~class" to DECLP.
1720 Otherwise, we prepend "class::" to the current DECLP.
1722 Reset the constructor/destructor flags once they have been
1723 "consumed". This allows demangle_class to be called later during
1724 the same demangling, to do normal class demangling.
1726 Returns 1 if demangling is successful, 0 otherwise.
1731 demangle_class (work
, mangled
, declp
)
1732 struct work_stuff
*work
;
1733 const char **mangled
;
1740 string_init (&class_name
);
1741 btype
= register_Btype (work
);
1742 if (demangle_class_name (work
, mangled
, &class_name
))
1744 if ((work
->constructor
& 1) || (work
->destructor
& 1))
1746 string_prepends (declp
, &class_name
);
1747 if (work
-> destructor
& 1)
1749 string_prepend (declp
, "~");
1750 work
-> destructor
-= 1;
1754 work
-> constructor
-= 1;
1757 remember_Ktype (work
, class_name
.b
, LEN_STRING(&class_name
));
1758 remember_Btype (work
, class_name
.b
, LEN_STRING(&class_name
), btype
);
1759 string_prepend (declp
, SCOPE_STRING (work
));
1760 string_prepends (declp
, &class_name
);
1763 string_delete (&class_name
);
1771 demangle_prefix -- consume the mangled name prefix and find signature
1776 demangle_prefix (struct work_stuff *work, const char **mangled,
1781 Consume and demangle the prefix of the mangled name.
1783 DECLP points to the string buffer into which demangled output is
1784 placed. On entry, the buffer is empty. On exit it contains
1785 the root function name, the demangled operator name, or in some
1786 special cases either nothing or the completely demangled result.
1788 MANGLED points to the current pointer into the mangled name. As each
1789 token of the mangled name is consumed, it is updated. Upon entry
1790 the current mangled name pointer points to the first character of
1791 the mangled name. Upon exit, it should point to the first character
1792 of the signature if demangling was successful, or to the first
1793 unconsumed character if demangling of the prefix was unsuccessful.
1795 Returns 1 on success, 0 otherwise.
1799 demangle_prefix (work
, mangled
, declp
)
1800 struct work_stuff
*work
;
1801 const char **mangled
;
1808 if (strlen(*mangled
) >= 11 && strncmp(*mangled
, "_GLOBAL_", 8) == 0)
1810 char *marker
= strchr (cplus_markers
, (*mangled
)[8]);
1811 if (marker
!= NULL
&& *marker
== (*mangled
)[10])
1813 if ((*mangled
)[9] == 'D')
1815 /* it's a GNU global destructor to be executed at program exit */
1817 work
->destructor
= 2;
1818 if (gnu_special (work
, mangled
, declp
))
1821 else if ((*mangled
)[9] == 'I')
1823 /* it's a GNU global constructor to be executed at program init */
1825 work
->constructor
= 2;
1826 if (gnu_special (work
, mangled
, declp
))
1831 else if (ARM_DEMANGLING
&& strncmp(*mangled
, "__std__", 7) == 0)
1833 /* it's a ARM global destructor to be executed at program exit */
1835 work
->destructor
= 2;
1837 else if (ARM_DEMANGLING
&& strncmp(*mangled
, "__sti__", 7) == 0)
1839 /* it's a ARM global constructor to be executed at program initial */
1841 work
->constructor
= 2;
1844 /* This block of code is a reduction in strength time optimization
1846 scan = mystrstr (*mangled, "__"); */
1852 scan
= strchr (scan
, '_');
1853 } while (scan
!= NULL
&& *++scan
!= '_');
1855 if (scan
!= NULL
) --scan
;
1860 /* We found a sequence of two or more '_', ensure that we start at
1861 the last pair in the sequence. */
1862 i
= strspn (scan
, "_");
1873 else if (work
-> static_type
)
1875 if (!isdigit (scan
[0]) && (scan
[0] != 't'))
1880 else if ((scan
== *mangled
)
1881 && (isdigit (scan
[2]) || (scan
[2] == 'Q') || (scan
[2] == 't')
1882 || (scan
[2] == 'K') || (scan
[2] == 'H')))
1884 /* The ARM says nothing about the mangling of local variables.
1885 But cfront mangles local variables by prepending __<nesting_level>
1886 to them. As an extension to ARM demangling we handle this case. */
1887 if ((LUCID_DEMANGLING
|| ARM_DEMANGLING
) && isdigit (scan
[2]))
1889 *mangled
= scan
+ 2;
1890 consume_count (mangled
);
1891 string_append (declp
, *mangled
);
1892 *mangled
+= strlen (*mangled
);
1897 /* A GNU style constructor starts with __[0-9Qt]. But cfront uses
1898 names like __Q2_3foo3bar for nested type names. So don't accept
1899 this style of constructor for cfront demangling. A GNU
1900 style member-template constructor starts with 'H'. */
1901 if (!(LUCID_DEMANGLING
|| ARM_DEMANGLING
))
1902 work
-> constructor
+= 1;
1903 *mangled
= scan
+ 2;
1906 else if ((scan
== *mangled
) && !isdigit (scan
[2]) && (scan
[2] != 't'))
1908 /* Mangled name starts with "__". Skip over any leading '_' characters,
1909 then find the next "__" that separates the prefix from the signature.
1911 if (!(ARM_DEMANGLING
|| LUCID_DEMANGLING
)
1912 || (arm_special (mangled
, declp
) == 0))
1914 while (*scan
== '_')
1918 if ((scan
= mystrstr (scan
, "__")) == NULL
|| (*(scan
+ 2) == '\0'))
1920 /* No separator (I.E. "__not_mangled"), or empty signature
1921 (I.E. "__not_mangled_either__") */
1926 demangle_function_name (work
, mangled
, declp
, scan
);
1930 else if (ARM_DEMANGLING
&& scan
[2] == 'p' && scan
[3] == 't')
1932 /* Cfront-style parameterized type. Handled later as a signature. */
1936 demangle_arm_pt (work
, mangled
, strlen (*mangled
), declp
);
1938 else if (*(scan
+ 2) != '\0')
1940 /* Mangled name does not start with "__" but does have one somewhere
1941 in there with non empty stuff after it. Looks like a global
1943 demangle_function_name (work
, mangled
, declp
, scan
);
1947 /* Doesn't look like a mangled name */
1951 if (!success
&& (work
->constructor
== 2 || work
->destructor
== 2))
1953 string_append (declp
, *mangled
);
1954 *mangled
+= strlen (*mangled
);
1964 gnu_special -- special handling of gnu mangled strings
1969 gnu_special (struct work_stuff *work, const char **mangled,
1975 Process some special GNU style mangling forms that don't fit
1976 the normal pattern. For example:
1978 _$_3foo (destructor for class foo)
1979 _vt$foo (foo virtual table)
1980 _vt$foo$bar (foo::bar virtual table)
1981 __vt_foo (foo virtual table, new style with thunks)
1982 _3foo$varname (static data member)
1983 _Q22rs2tu$vw (static data member)
1984 __t6vector1Zii (constructor with template)
1985 __thunk_4__$_7ostream (virtual function thunk)
1989 gnu_special (work
, mangled
, declp
)
1990 struct work_stuff
*work
;
1991 const char **mangled
;
1998 if ((*mangled
)[0] == '_'
1999 && strchr (cplus_markers
, (*mangled
)[1]) != NULL
2000 && (*mangled
)[2] == '_')
2002 /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
2004 work
-> destructor
+= 1;
2006 else if ((*mangled
)[0] == '_'
2007 && (((*mangled
)[1] == '_'
2008 && (*mangled
)[2] == 'v'
2009 && (*mangled
)[3] == 't'
2010 && (*mangled
)[4] == '_')
2011 || ((*mangled
)[1] == 'v'
2012 && (*mangled
)[2] == 't'
2013 && strchr (cplus_markers
, (*mangled
)[3]) != NULL
)))
2015 /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
2016 and create the decl. Note that we consume the entire mangled
2017 input string, which means that demangle_signature has no work
2019 if ((*mangled
)[2] == 'v')
2020 (*mangled
) += 5; /* New style, with thunks: "__vt_" */
2022 (*mangled
) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
2023 while (**mangled
!= '\0')
2025 p
= strpbrk (*mangled
, cplus_markers
);
2030 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
2033 success
= demangle_template (work
, mangled
, declp
, 0, 1,
2037 if (isdigit(*mangled
[0]))
2039 n
= consume_count(mangled
);
2040 /* We may be seeing a too-large size, or else a
2041 ".<digits>" indicating a static local symbol. In
2042 any case, declare victory and move on; *don't* try
2043 to use n to allocate. */
2044 if (n
> strlen (*mangled
))
2052 n
= strcspn (*mangled
, cplus_markers
);
2054 string_appendn (declp
, *mangled
, n
);
2058 if (success
&& ((p
== NULL
) || (p
== *mangled
)))
2062 string_append (declp
, SCOPE_STRING (work
));
2073 string_append (declp
, " virtual table");
2075 else if ((*mangled
)[0] == '_'
2076 && (strchr("0123456789Qt", (*mangled
)[1]) != NULL
)
2077 && (p
= strpbrk (*mangled
, cplus_markers
)) != NULL
)
2079 /* static data member, "_3foo$varname" for example */
2085 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
2088 success
= demangle_template (work
, mangled
, declp
, 0, 1, 1);
2091 n
= consume_count (mangled
);
2092 string_appendn (declp
, *mangled
, n
);
2095 if (success
&& (p
== *mangled
))
2097 /* Consumed everything up to the cplus_marker, append the
2100 string_append (declp
, SCOPE_STRING (work
));
2101 n
= strlen (*mangled
);
2102 string_appendn (declp
, *mangled
, n
);
2110 else if (strncmp (*mangled
, "__thunk_", 8) == 0)
2112 int delta
= ((*mangled
) += 8, consume_count (mangled
));
2113 char *method
= internal_cplus_demangle (work
, ++*mangled
);
2117 sprintf (buf
, "virtual function thunk (delta:%d) for ", -delta
);
2118 string_append (declp
, buf
);
2119 string_append (declp
, method
);
2121 n
= strlen (*mangled
);
2129 else if (strncmp (*mangled
, "__t", 3) == 0
2130 && ((*mangled
)[3] == 'i' || (*mangled
)[3] == 'f'))
2132 p
= (*mangled
)[3] == 'i' ? " type_info node" : " type_info function";
2138 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
2141 success
= demangle_template (work
, mangled
, declp
, 0, 1, 1);
2144 success
= demangle_fund_type (work
, mangled
, declp
);
2147 if (success
&& **mangled
!= '\0')
2150 string_append (declp
, p
);
2163 arm_special -- special handling of ARM/lucid mangled strings
2168 arm_special (const char **mangled,
2174 Process some special ARM style mangling forms that don't fit
2175 the normal pattern. For example:
2177 __vtbl__3foo (foo virtual table)
2178 __vtbl__3foo__3bar (bar::foo virtual table)
2183 arm_special (mangled
, declp
)
2184 const char **mangled
;
2191 if (strncmp (*mangled
, ARM_VTABLE_STRING
, ARM_VTABLE_STRLEN
) == 0)
2193 /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
2194 and create the decl. Note that we consume the entire mangled
2195 input string, which means that demangle_signature has no work
2197 scan
= *mangled
+ ARM_VTABLE_STRLEN
;
2198 while (*scan
!= '\0') /* first check it can be demangled */
2200 n
= consume_count (&scan
);
2203 return (0); /* no good */
2206 if (scan
[0] == '_' && scan
[1] == '_')
2211 (*mangled
) += ARM_VTABLE_STRLEN
;
2212 while (**mangled
!= '\0')
2214 n
= consume_count (mangled
);
2215 string_prependn (declp
, *mangled
, n
);
2217 if ((*mangled
)[0] == '_' && (*mangled
)[1] == '_')
2219 string_prepend (declp
, "::");
2223 string_append (declp
, " virtual table");
2236 demangle_qualified -- demangle 'Q' qualified name strings
2241 demangle_qualified (struct work_stuff *, const char *mangled,
2242 string *result, int isfuncname, int append);
2246 Demangle a qualified name, such as "Q25Outer5Inner" which is
2247 the mangled form of "Outer::Inner". The demangled output is
2248 prepended or appended to the result string according to the
2249 state of the append flag.
2251 If isfuncname is nonzero, then the qualified name we are building
2252 is going to be used as a member function name, so if it is a
2253 constructor or destructor function, append an appropriate
2254 constructor or destructor name. I.E. for the above example,
2255 the result for use as a constructor is "Outer::Inner::Inner"
2256 and the result for use as a destructor is "Outer::Inner::~Inner".
2260 Numeric conversion is ASCII dependent (FIXME).
2265 demangle_qualified (work
, mangled
, result
, isfuncname
, append
)
2266 struct work_stuff
*work
;
2267 const char **mangled
;
2278 int bindex
= register_Btype (work
);
2280 /* We only make use of ISFUNCNAME if the entity is a constructor or
2282 isfuncname
= (isfuncname
2283 && ((work
->constructor
& 1) || (work
->destructor
& 1)));
2285 string_init (&temp
);
2286 string_init (&last_name
);
2288 if ((*mangled
)[0] == 'K')
2290 /* Squangling qualified name reuse */
2293 idx
= consume_count_with_underscores (mangled
);
2294 if (idx
== -1 || idx
> work
-> numk
)
2297 string_append (&temp
, work
-> ktypevec
[idx
]);
2300 switch ((*mangled
)[1])
2303 /* GNU mangled name with more than 9 classes. The count is preceded
2304 by an underscore (to distinguish it from the <= 9 case) and followed
2305 by an underscore. */
2307 qualifiers
= atoi (p
);
2308 if (!isdigit (*p
) || *p
== '0')
2311 /* Skip the digits. */
2312 while (isdigit (*p
))
2330 /* The count is in a single digit. */
2331 num
[0] = (*mangled
)[1];
2333 qualifiers
= atoi (num
);
2335 /* If there is an underscore after the digit, skip it. This is
2336 said to be for ARM-qualified names, but the ARM makes no
2337 mention of such an underscore. Perhaps cfront uses one. */
2338 if ((*mangled
)[2] == '_')
2353 /* Pick off the names and collect them in the temp buffer in the order
2354 in which they are found, separated by '::'. */
2356 while (qualifiers
-- > 0)
2359 string_clear (&last_name
);
2361 if (*mangled
[0] == '_')
2364 if (*mangled
[0] == 't')
2366 /* Here we always append to TEMP since we will want to use
2367 the template name without the template parameters as a
2368 constructor or destructor name. The appropriate
2369 (parameter-less) value is returned by demangle_template
2370 in LAST_NAME. We do not remember the template type here,
2371 in order to match the G++ mangling algorithm. */
2372 success
= demangle_template(work
, mangled
, &temp
,
2377 else if (*mangled
[0] == 'K')
2381 idx
= consume_count_with_underscores (mangled
);
2382 if (idx
== -1 || idx
> work
->numk
)
2385 string_append (&temp
, work
->ktypevec
[idx
]);
2388 if (!success
) break;
2392 success
= do_type (work
, mangled
, &last_name
);
2395 string_appends (&temp
, &last_name
);
2399 remember_Ktype (work
, temp
.b
, LEN_STRING (&temp
));
2402 string_append (&temp
, SCOPE_STRING (work
));
2405 remember_Btype (work
, temp
.b
, LEN_STRING (&temp
), bindex
);
2407 /* If we are using the result as a function name, we need to append
2408 the appropriate '::' separated constructor or destructor name.
2409 We do this here because this is the most convenient place, where
2410 we already have a pointer to the name and the length of the name. */
2414 string_append (&temp
, SCOPE_STRING (work
));
2415 if (work
-> destructor
& 1)
2416 string_append (&temp
, "~");
2417 string_appends (&temp
, &last_name
);
2420 /* Now either prepend the temp buffer to the result, or append it,
2421 depending upon the state of the append flag. */
2424 string_appends (result
, &temp
);
2427 if (!STRING_EMPTY (result
))
2428 string_append (&temp
, SCOPE_STRING (work
));
2429 string_prepends (result
, &temp
);
2432 string_delete (&last_name
);
2433 string_delete (&temp
);
2441 get_count -- convert an ascii count to integer, consuming tokens
2446 get_count (const char **type, int *count)
2450 Return 0 if no conversion is performed, 1 if a string is converted.
2454 get_count (type
, count
)
2461 if (!isdigit (**type
))
2467 *count
= **type
- '0';
2469 if (isdigit (**type
))
2479 while (isdigit (*p
));
2490 /* result will be initialised here; it will be freed on failure */
2493 do_type (work
, mangled
, result
)
2494 struct work_stuff
*work
;
2495 const char **mangled
;
2502 const char *remembered_type
;
2507 string_init (&btype
);
2508 string_init (&decl
);
2509 string_init (result
);
2513 while (success
&& !done
)
2519 /* A pointer type */
2523 string_prepend (&decl
, "*");
2526 /* A reference type */
2529 string_prepend (&decl
, "&");
2535 const char *p
= ++(*mangled
);
2537 string_prepend (&decl
, "(");
2538 string_append (&decl
, ")[");
2539 /* Copy anything up until the next underscore (the size of the
2541 while (**mangled
&& **mangled
!= '_')
2543 if (**mangled
== '_')
2545 string_appendn (&decl
, p
, *mangled
- p
);
2546 string_append (&decl
, "]");
2554 /* A back reference to a previously seen type */
2557 if (!get_count (mangled
, &n
) || n
>= work
-> ntypes
)
2563 remembered_type
= work
-> typevec
[n
];
2564 mangled
= &remembered_type
;
2571 if (!STRING_EMPTY (&decl
) && decl
.b
[0] == '*')
2573 string_prepend (&decl
, "(");
2574 string_append (&decl
, ")");
2576 /* After picking off the function args, we expect to either find the
2577 function return type (preceded by an '_') or the end of the
2579 if (!demangle_nested_args (work
, mangled
, &decl
)
2580 || (**mangled
!= '_' && **mangled
!= '\0'))
2585 if (success
&& (**mangled
== '_'))
2595 member
= **mangled
== 'M';
2597 if (!isdigit (**mangled
) && **mangled
!= 't')
2603 string_append (&decl
, ")");
2604 string_prepend (&decl
, SCOPE_STRING (work
));
2605 if (isdigit (**mangled
))
2607 n
= consume_count (mangled
);
2608 if (strlen (*mangled
) < n
)
2613 string_prependn (&decl
, *mangled
, n
);
2619 string_init (&temp
);
2620 success
= demangle_template (work
, mangled
, &temp
,
2624 string_prependn (&decl
, temp
.b
, temp
.p
- temp
.b
);
2625 string_clear (&temp
);
2630 string_prepend (&decl
, "(");
2633 if (**mangled
== 'C')
2638 if (**mangled
== 'V')
2643 if (*(*mangled
)++ != 'F')
2649 if ((member
&& !demangle_nested_args (work
, mangled
, &decl
))
2650 || **mangled
!= '_')
2656 if (! PRINT_ANSI_QUALIFIERS
)
2662 APPEND_BLANK (&decl
);
2663 string_append (&decl
, "const");
2667 APPEND_BLANK (&decl
);
2668 string_append (&decl
, "volatile");
2679 if ((*mangled)[1] == 'P')
2682 if (PRINT_ANSI_QUALIFIERS
)
2684 if (!STRING_EMPTY (&decl
))
2686 string_prepend (&decl
, " ");
2688 string_prepend (&decl
,
2689 (**mangled
) == 'C' ? "const" : "volatile");
2706 /* A qualified name, such as "Outer::Inner". */
2710 success
= demangle_qualified (work
, mangled
, result
, 0, 1);
2714 /* A back reference to a previously seen squangled type */
2717 if (!get_count (mangled
, &n
) || n
>= work
-> numb
)
2721 string_append (result
, work
->btypevec
[n
]);
2727 /* A template parm. We substitute the corresponding argument. */
2732 idx
= consume_count_with_underscores (mangled
);
2735 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
2736 || consume_count_with_underscores (mangled
) == -1)
2742 if (work
->tmpl_argvec
)
2743 string_append (result
, work
->tmpl_argvec
[idx
]);
2747 sprintf(buf
, "T%d", idx
);
2748 string_append (result
, buf
);
2756 success
= demangle_fund_type (work
, mangled
, result
);
2762 if (!STRING_EMPTY (&decl
))
2764 string_append (result
, " ");
2765 string_appends (result
, &decl
);
2770 string_delete (result
);
2772 string_delete (&decl
);
2776 /* Given a pointer to a type string that represents a fundamental type
2777 argument (int, long, unsigned int, etc) in TYPE, a pointer to the
2778 string in which the demangled output is being built in RESULT, and
2779 the WORK structure, decode the types and add them to the result.
2784 "Sl" => "signed long"
2785 "CUs" => "const unsigned short"
2790 demangle_fund_type (work
, mangled
, result
)
2791 struct work_stuff
*work
;
2792 const char **mangled
;
2798 string_init (&btype
);
2800 /* First pick off any type qualifiers. There can be more than one. */
2808 if (PRINT_ANSI_QUALIFIERS
)
2810 APPEND_BLANK (result
);
2811 string_append (result
, "const");
2816 APPEND_BLANK (result
);
2817 string_append (result
, "unsigned");
2819 case 'S': /* signed char only */
2821 APPEND_BLANK (result
);
2822 string_append (result
, "signed");
2826 if (PRINT_ANSI_QUALIFIERS
)
2828 APPEND_BLANK (result
);
2829 string_append (result
, "volatile");
2834 APPEND_BLANK (result
);
2835 string_append (result
, "__complex");
2843 /* Now pick off the fundamental type. There can be only one. */
2852 APPEND_BLANK (result
);
2853 string_append (result
, "void");
2857 APPEND_BLANK (result
);
2858 string_append (result
, "long long");
2862 APPEND_BLANK (result
);
2863 string_append (result
, "long");
2867 APPEND_BLANK (result
);
2868 string_append (result
, "int");
2872 APPEND_BLANK (result
);
2873 string_append (result
, "short");
2877 APPEND_BLANK (result
);
2878 string_append (result
, "bool");
2882 APPEND_BLANK (result
);
2883 string_append (result
, "char");
2887 APPEND_BLANK (result
);
2888 string_append (result
, "wchar_t");
2892 APPEND_BLANK (result
);
2893 string_append (result
, "long double");
2897 APPEND_BLANK (result
);
2898 string_append (result
, "double");
2902 APPEND_BLANK (result
);
2903 string_append (result
, "float");
2907 if (!isdigit (**mangled
))
2913 /* An explicit type, such as "6mytype" or "7integer" */
2925 int bindex
= register_Btype (work
);
2927 string_init (&btype
);
2928 if (demangle_class_name (work
, mangled
, &btype
)) {
2929 remember_Btype (work
, btype
.b
, LEN_STRING (&btype
), bindex
);
2930 APPEND_BLANK (result
);
2931 string_appends (result
, &btype
);
2935 string_delete (&btype
);
2940 success
= demangle_template (work
, mangled
, &btype
, 0, 1, 1);
2941 string_appends (result
, &btype
);
2952 /* Demangle the next argument, given by MANGLED into RESULT, which
2953 *should be an uninitialized* string. It will be initialized here,
2954 and free'd should anything go wrong. */
2957 do_arg (work
, mangled
, result
)
2958 struct work_stuff
*work
;
2959 const char **mangled
;
2962 /* Remember where we started so that we can record the type, for
2963 non-squangling type remembering. */
2964 const char *start
= *mangled
;
2966 string_init (result
);
2968 if (work
->nrepeats
> 0)
2972 if (work
->previous_argument
== 0)
2975 /* We want to reissue the previous type in this argument list. */
2976 string_appends (result
, work
->previous_argument
);
2980 if (**mangled
== 'n')
2982 /* A squangling-style repeat. */
2984 work
->nrepeats
= consume_count(mangled
);
2986 if (work
->nrepeats
== 0)
2987 /* This was not a repeat count after all. */
2990 if (work
->nrepeats
> 9)
2992 if (**mangled
!= '_')
2993 /* The repeat count should be followed by an '_' in this
3000 /* Now, the repeat is all set up. */
3001 return do_arg (work
, mangled
, result
);
3004 /* Save the result in WORK->previous_argument so that we can find it
3005 if it's repeated. Note that saving START is not good enough: we
3006 do not want to add additional types to the back-referenceable
3007 type vector when processing a repeated type. */
3008 if (work
->previous_argument
)
3009 string_clear (work
->previous_argument
);
3012 work
->previous_argument
= (string
*) xmalloc (sizeof (string
));
3013 string_init (work
->previous_argument
);
3016 if (!do_type (work
, mangled
, work
->previous_argument
))
3019 string_appends (result
, work
->previous_argument
);
3021 remember_type (work
, start
, *mangled
- start
);
3026 remember_type (work
, start
, len
)
3027 struct work_stuff
*work
;
3033 if (work
->forgetting_types
)
3036 if (work
-> ntypes
>= work
-> typevec_size
)
3038 if (work
-> typevec_size
== 0)
3040 work
-> typevec_size
= 3;
3042 = (char **) xmalloc (sizeof (char *) * work
-> typevec_size
);
3046 work
-> typevec_size
*= 2;
3048 = (char **) xrealloc ((char *)work
-> typevec
,
3049 sizeof (char *) * work
-> typevec_size
);
3052 tem
= xmalloc (len
+ 1);
3053 memcpy (tem
, start
, len
);
3055 work
-> typevec
[work
-> ntypes
++] = tem
;
3059 /* Remember a K type class qualifier. */
3061 remember_Ktype (work
, start
, len
)
3062 struct work_stuff
*work
;
3068 if (work
-> numk
>= work
-> ksize
)
3070 if (work
-> ksize
== 0)
3074 = (char **) xmalloc (sizeof (char *) * work
-> ksize
);
3080 = (char **) xrealloc ((char *)work
-> ktypevec
,
3081 sizeof (char *) * work
-> ksize
);
3084 tem
= xmalloc (len
+ 1);
3085 memcpy (tem
, start
, len
);
3087 work
-> ktypevec
[work
-> numk
++] = tem
;
3090 /* Register a B code, and get an index for it. B codes are registered
3091 as they are seen, rather than as they are completed, so map<temp<char> >
3092 registers map<temp<char> > as B0, and temp<char> as B1 */
3095 register_Btype (work
)
3096 struct work_stuff
*work
;
3100 if (work
-> numb
>= work
-> bsize
)
3102 if (work
-> bsize
== 0)
3106 = (char **) xmalloc (sizeof (char *) * work
-> bsize
);
3112 = (char **) xrealloc ((char *)work
-> btypevec
,
3113 sizeof (char *) * work
-> bsize
);
3116 ret
= work
-> numb
++;
3117 work
-> btypevec
[ret
] = NULL
;
3121 /* Store a value into a previously registered B code type. */
3124 remember_Btype (work
, start
, len
, index
)
3125 struct work_stuff
*work
;
3131 tem
= xmalloc (len
+ 1);
3132 memcpy (tem
, start
, len
);
3134 work
-> btypevec
[index
] = tem
;
3137 /* Lose all the info related to B and K type codes. */
3139 forget_B_and_K_types (work
)
3140 struct work_stuff
*work
;
3144 while (work
-> numk
> 0)
3146 i
= --(work
-> numk
);
3147 if (work
-> ktypevec
[i
] != NULL
)
3149 free (work
-> ktypevec
[i
]);
3150 work
-> ktypevec
[i
] = NULL
;
3154 while (work
-> numb
> 0)
3156 i
= --(work
-> numb
);
3157 if (work
-> btypevec
[i
] != NULL
)
3159 free (work
-> btypevec
[i
]);
3160 work
-> btypevec
[i
] = NULL
;
3164 /* Forget the remembered types, but not the type vector itself. */
3168 struct work_stuff
*work
;
3172 while (work
-> ntypes
> 0)
3174 i
= --(work
-> ntypes
);
3175 if (work
-> typevec
[i
] != NULL
)
3177 free (work
-> typevec
[i
]);
3178 work
-> typevec
[i
] = NULL
;
3183 /* Process the argument list part of the signature, after any class spec
3184 has been consumed, as well as the first 'F' character (if any). For
3187 "__als__3fooRT0" => process "RT0"
3188 "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i"
3190 DECLP must be already initialised, usually non-empty. It won't be freed
3193 Note that g++ differs significantly from ARM and lucid style mangling
3194 with regards to references to previously seen types. For example, given
3195 the source fragment:
3199 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
3202 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3203 void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3205 g++ produces the names:
3210 while lcc (and presumably other ARM style compilers as well) produces:
3212 foo__FiR3fooT1T2T1T2
3213 __ct__3fooFiR3fooT1T2T1T2
3215 Note that g++ bases its type numbers starting at zero and counts all
3216 previously seen types, while lucid/ARM bases its type numbers starting
3217 at one and only considers types after it has seen the 'F' character
3218 indicating the start of the function args. For lucid/ARM style, we
3219 account for this difference by discarding any previously seen types when
3220 we see the 'F' character, and subtracting one from the type number
3226 demangle_args (work
, mangled
, declp
)
3227 struct work_stuff
*work
;
3228 const char **mangled
;
3238 if (PRINT_ARG_TYPES
)
3240 string_append (declp
, "(");
3241 if (**mangled
== '\0')
3243 string_append (declp
, "void");
3247 while ((**mangled
!= '_' && **mangled
!= '\0' && **mangled
!= 'e')
3248 || work
->nrepeats
> 0)
3250 if ((**mangled
== 'N') || (**mangled
== 'T'))
3252 temptype
= *(*mangled
)++;
3254 if (temptype
== 'N')
3256 if (!get_count (mangled
, &r
))
3265 if (ARM_DEMANGLING
&& work
-> ntypes
>= 10)
3267 /* If we have 10 or more types we might have more than a 1 digit
3268 index so we'll have to consume the whole count here. This
3269 will lose if the next thing is a type name preceded by a
3270 count but it's impossible to demangle that case properly
3271 anyway. Eg if we already have 12 types is T12Pc "(..., type1,
3272 Pc, ...)" or "(..., type12, char *, ...)" */
3273 if ((t
= consume_count(mangled
)) == 0)
3280 if (!get_count (mangled
, &t
))
3285 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
3289 /* Validate the type index. Protect against illegal indices from
3290 malformed type strings. */
3291 if ((t
< 0) || (t
>= work
-> ntypes
))
3295 while (work
->nrepeats
> 0 || --r
>= 0)
3297 tem
= work
-> typevec
[t
];
3298 if (need_comma
&& PRINT_ARG_TYPES
)
3300 string_append (declp
, ", ");
3302 if (!do_arg (work
, &tem
, &arg
))
3306 if (PRINT_ARG_TYPES
)
3308 string_appends (declp
, &arg
);
3310 string_delete (&arg
);
3316 if (need_comma
&& PRINT_ARG_TYPES
)
3317 string_append (declp
, ", ");
3318 if (!do_arg (work
, mangled
, &arg
))
3320 if (PRINT_ARG_TYPES
)
3321 string_appends (declp
, &arg
);
3322 string_delete (&arg
);
3327 if (**mangled
== 'e')
3330 if (PRINT_ARG_TYPES
)
3334 string_append (declp
, ",");
3336 string_append (declp
, "...");
3340 if (PRINT_ARG_TYPES
)
3342 string_append (declp
, ")");
3347 /* Like demangle_args, but for demangling the argument lists of function
3348 and method pointers or references, not top-level declarations. */
3351 demangle_nested_args (work
, mangled
, declp
)
3352 struct work_stuff
*work
;
3353 const char **mangled
;
3356 string
* saved_previous_argument
;
3360 /* The G++ name-mangling algorithm does not remember types on nested
3361 argument lists, unless -fsquangling is used, and in that case the
3362 type vector updated by remember_type is not used. So, we turn
3363 off remembering of types here. */
3364 ++work
->forgetting_types
;
3366 /* For the repeat codes used with -fsquangling, we must keep track of
3367 the last argument. */
3368 saved_previous_argument
= work
->previous_argument
;
3369 saved_nrepeats
= work
->nrepeats
;
3370 work
->previous_argument
= 0;
3373 /* Actually demangle the arguments. */
3374 result
= demangle_args (work
, mangled
, declp
);
3376 /* Restore the previous_argument field. */
3377 if (work
->previous_argument
)
3378 string_delete (work
->previous_argument
);
3379 work
->previous_argument
= saved_previous_argument
;
3380 work
->nrepeats
= saved_nrepeats
;
3386 demangle_function_name (work
, mangled
, declp
, scan
)
3387 struct work_stuff
*work
;
3388 const char **mangled
;
3396 string_appendn (declp
, (*mangled
), scan
- (*mangled
));
3397 string_need (declp
, 1);
3398 *(declp
-> p
) = '\0';
3400 /* Consume the function name, including the "__" separating the name
3401 from the signature. We are guaranteed that SCAN points to the
3404 (*mangled
) = scan
+ 2;
3406 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
3409 /* See if we have an ARM style constructor or destructor operator.
3410 If so, then just record it, clear the decl, and return.
3411 We can't build the actual constructor/destructor decl until later,
3412 when we recover the class name from the signature. */
3414 if (strcmp (declp
-> b
, "__ct") == 0)
3416 work
-> constructor
+= 1;
3417 string_clear (declp
);
3420 else if (strcmp (declp
-> b
, "__dt") == 0)
3422 work
-> destructor
+= 1;
3423 string_clear (declp
);
3428 if (declp
->p
- declp
->b
>= 3
3429 && declp
->b
[0] == 'o'
3430 && declp
->b
[1] == 'p'
3431 && strchr (cplus_markers
, declp
->b
[2]) != NULL
)
3433 /* see if it's an assignment expression */
3434 if (declp
->p
- declp
->b
>= 10 /* op$assign_ */
3435 && memcmp (declp
->b
+ 3, "assign_", 7) == 0)
3437 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3439 int len
= declp
->p
- declp
->b
- 10;
3440 if (strlen (optable
[i
].in
) == len
3441 && memcmp (optable
[i
].in
, declp
->b
+ 10, len
) == 0)
3443 string_clear (declp
);
3444 string_append (declp
, "operator");
3445 string_append (declp
, optable
[i
].out
);
3446 string_append (declp
, "=");
3453 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3455 int len
= declp
->p
- declp
->b
- 3;
3456 if (strlen (optable
[i
].in
) == len
3457 && memcmp (optable
[i
].in
, declp
->b
+ 3, len
) == 0)
3459 string_clear (declp
);
3460 string_append (declp
, "operator");
3461 string_append (declp
, optable
[i
].out
);
3467 else if (declp
->p
- declp
->b
>= 5 && memcmp (declp
->b
, "type", 4) == 0
3468 && strchr (cplus_markers
, declp
->b
[4]) != NULL
)
3470 /* type conversion operator */
3472 if (do_type (work
, &tem
, &type
))
3474 string_clear (declp
);
3475 string_append (declp
, "operator ");
3476 string_appends (declp
, &type
);
3477 string_delete (&type
);
3480 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
3481 && declp
->b
[2] == 'o' && declp
->b
[3] == 'p')
3484 /* type conversion operator. */
3486 if (do_type (work
, &tem
, &type
))
3488 string_clear (declp
);
3489 string_append (declp
, "operator ");
3490 string_appends (declp
, &type
);
3491 string_delete (&type
);
3494 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
3495 && declp
->b
[2] >= 'a' && declp
->b
[2] <= 'z'
3496 && declp
->b
[3] >= 'a' && declp
->b
[3] <= 'z')
3498 if (declp
->b
[4] == '\0')
3501 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3503 if (strlen (optable
[i
].in
) == 2
3504 && memcmp (optable
[i
].in
, declp
->b
+ 2, 2) == 0)
3506 string_clear (declp
);
3507 string_append (declp
, "operator");
3508 string_append (declp
, optable
[i
].out
);
3515 if (declp
->b
[2] == 'a' && declp
->b
[5] == '\0')
3518 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3520 if (strlen (optable
[i
].in
) == 3
3521 && memcmp (optable
[i
].in
, declp
->b
+ 2, 3) == 0)
3523 string_clear (declp
);
3524 string_append (declp
, "operator");
3525 string_append (declp
, optable
[i
].out
);
3534 /* a mini string-handling package */
3549 s
->p
= s
->b
= xmalloc (n
);
3552 else if (s
->e
- s
->p
< n
)
3557 s
->b
= xrealloc (s
->b
, n
);
3570 s
->b
= s
->e
= s
->p
= NULL
;
3578 s
->b
= s
->p
= s
->e
= NULL
;
3594 return (s
->b
== s
->p
);
3600 string_append (p
, s
)
3605 if (s
== NULL
|| *s
== '\0')
3609 memcpy (p
->p
, s
, n
);
3614 string_appends (p
, s
)
3623 memcpy (p
->p
, s
->b
, n
);
3629 string_appendn (p
, s
, n
)
3637 memcpy (p
->p
, s
, n
);
3643 string_prepend (p
, s
)
3647 if (s
!= NULL
&& *s
!= '\0')
3649 string_prependn (p
, s
, strlen (s
));
3654 string_prepends (p
, s
)
3659 string_prependn (p
, s
->b
, s
->p
- s
->b
);
3664 string_prependn (p
, s
, n
)
3674 for (q
= p
->p
- 1; q
>= p
->b
; q
--)
3678 memcpy (p
->b
, s
, n
);
3683 /* To generate a standalone demangler program for testing purposes,
3684 just compile and link this file with -DMAIN and libiberty.a. When
3685 run, it demangles each command line arg, or each stdin string, and
3686 prints the result on stdout. */
3692 static char *program_name
;
3693 static char *program_version
= VERSION
;
3694 static int flags
= DMGL_PARAMS
| DMGL_ANSI
;
3696 static void demangle_it
PARAMS ((char *));
3697 static void usage
PARAMS ((FILE *, int));
3698 static void fatal
PARAMS ((char *));
3701 demangle_it (mangled_name
)
3706 result
= cplus_demangle (mangled_name
, flags
);
3709 printf ("%s\n", mangled_name
);
3713 printf ("%s\n", result
);
3719 usage (stream
, status
)
3724 Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
3725 [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\
3726 [--help] [--version] [arg...]\n",
3731 #define MBUF_SIZE 32767
3732 char mbuffer
[MBUF_SIZE
];
3734 /* Defined in the automatically-generated underscore.c. */
3735 extern int prepends_underscore
;
3737 int strip_underscore
= 0;
3739 static struct option long_options
[] = {
3740 {"strip-underscores", no_argument
, 0, '_'},
3741 {"format", required_argument
, 0, 's'},
3742 {"help", no_argument
, 0, 'h'},
3743 {"no-strip-underscores", no_argument
, 0, 'n'},
3744 {"version", no_argument
, 0, 'v'},
3745 {0, no_argument
, 0, 0}
3748 /* More 'friendly' abort that prints the line and file.
3749 config.h can #define abort fancy_abort if you like that sort of thing. */
3754 fatal ("Internal gcc abort.");
3765 program_name
= argv
[0];
3767 strip_underscore
= prepends_underscore
;
3769 while ((c
= getopt_long (argc
, argv
, "_ns:j", long_options
, (int *) 0)) != EOF
)
3779 strip_underscore
= 0;
3782 printf ("GNU %s version %s\n", program_name
, program_version
);
3785 strip_underscore
= 1;
3788 if (strcmp (optarg
, "gnu") == 0)
3790 current_demangling_style
= gnu_demangling
;
3792 else if (strcmp (optarg
, "lucid") == 0)
3794 current_demangling_style
= lucid_demangling
;
3796 else if (strcmp (optarg
, "arm") == 0)
3798 current_demangling_style
= arm_demangling
;
3802 fprintf (stderr
, "%s: unknown demangling style `%s'\n",
3803 program_name
, optarg
);
3812 for ( ; optind
< argc
; optind
++)
3814 demangle_it (argv
[optind
]);
3823 /* Try to read a label. */
3824 while (c
!= EOF
&& (isalnum(c
) || c
== '_' || c
== '$' || c
== '.'))
3826 if (i
>= MBUF_SIZE
-1)
3835 if (mbuffer
[0] == '.')
3837 if (strip_underscore
&& mbuffer
[skip_first
] == '_')
3845 result
= cplus_demangle (mbuffer
+ skip_first
, flags
);
3848 if (mbuffer
[0] == '.')
3850 fputs (result
, stdout
);
3854 fputs (mbuffer
, stdout
);
3871 fprintf (stderr
, "%s: %s\n", program_name
, str
);
3882 register char *value
= (char *) malloc (size
);
3884 fatal ("virtual memory exhausted");
3889 xrealloc (ptr
, size
)
3893 register char *value
= (char *) realloc (ptr
, size
);
3895 fatal ("virtual memory exhausted");