1 /* Demangler for GNU C++
2 Copyright 1989, 91, 94, 95, 96, 97, 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. */
36 #include <sys/types.h>
48 #undef CURRENT_DEMANGLING_STYLE
49 #define CURRENT_DEMANGLING_STYLE work->options
51 extern char *xmalloc PARAMS((unsigned));
52 extern char *xrealloc PARAMS((char *, unsigned));
54 static const char *mystrstr PARAMS ((const char *, const char *));
60 register const char *p = s1;
61 register int len = strlen (s2);
63 for (; (p = strchr (p, *s2)) != 0; p++)
65 if (strncmp (p, s2, len) == 0)
73 /* In order to allow a single demangler executable to demangle strings
74 using various common values of CPLUS_MARKER, as well as any specific
75 one set at compile time, we maintain a string containing all the
76 commonly used ones, and check to see if the marker we are looking for
77 is in that string. CPLUS_MARKER is usually '$' on systems where the
78 assembler can deal with that. Where the assembler can't, it's usually
79 '.' (but on many systems '.' is used for other things). We put the
80 current defined CPLUS_MARKER first (which defaults to '$'), followed
81 by the next most common value, followed by an explicit '$' in case
82 the value of CPLUS_MARKER is not '$'.
84 We could avoid this if we could just get g++ to tell us what the actual
85 cplus marker character is as part of the debug information, perhaps by
86 ensuring that it is the character that terminates the gcc<n>_compiled
87 marker symbol (FIXME). */
89 #if !defined (CPLUS_MARKER)
90 #define CPLUS_MARKER '$'
93 enum demangling_styles current_demangling_style = gnu_demangling;
95 static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
98 set_cplus_marker_for_demangling (ch)
101 cplus_markers[0] = ch;
104 typedef struct string /* Beware: these aren't required to be */
105 { /* '\0' terminated. */
106 char *b; /* pointer to start of string */
107 char *p; /* pointer after last character */
108 char *e; /* pointer after end of allocated space */
111 /* Stuff that is shared between sub-routines.
112 Using a shared structure allows cplus_demangle to be reentrant. */
128 int static_type; /* A static member function */
129 int type_quals; /* The type qualifiers. */
130 int dllimported; /* Symbol imported from a PE DLL */
131 char **tmpl_argvec; /* Template function arguments. */
132 int ntmpl_args; /* The number of template function arguments. */
133 int forgetting_types; /* Nonzero if we are not remembering the types
135 string* previous_argument; /* The last function argument demangled. */
136 int nrepeats; /* The number of times to repeat the previous
140 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
141 #define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS)
143 static const struct optable
149 {"nw", " new", DMGL_ANSI}, /* new (1.92, ansi) */
150 {"dl", " delete", DMGL_ANSI}, /* new (1.92, ansi) */
151 {"new", " new", 0}, /* old (1.91, and 1.x) */
152 {"delete", " delete", 0}, /* old (1.91, and 1.x) */
153 {"vn", " new []", DMGL_ANSI}, /* GNU, pending ansi */
154 {"vd", " delete []", DMGL_ANSI}, /* GNU, pending ansi */
155 {"as", "=", DMGL_ANSI}, /* ansi */
156 {"ne", "!=", DMGL_ANSI}, /* old, ansi */
157 {"eq", "==", DMGL_ANSI}, /* old, ansi */
158 {"ge", ">=", DMGL_ANSI}, /* old, ansi */
159 {"gt", ">", DMGL_ANSI}, /* old, ansi */
160 {"le", "<=", DMGL_ANSI}, /* old, ansi */
161 {"lt", "<", DMGL_ANSI}, /* old, ansi */
162 {"plus", "+", 0}, /* old */
163 {"pl", "+", DMGL_ANSI}, /* ansi */
164 {"apl", "+=", DMGL_ANSI}, /* ansi */
165 {"minus", "-", 0}, /* old */
166 {"mi", "-", DMGL_ANSI}, /* ansi */
167 {"ami", "-=", DMGL_ANSI}, /* ansi */
168 {"mult", "*", 0}, /* old */
169 {"ml", "*", DMGL_ANSI}, /* ansi */
170 {"amu", "*=", DMGL_ANSI}, /* ansi (ARM/Lucid) */
171 {"aml", "*=", DMGL_ANSI}, /* ansi (GNU/g++) */
172 {"convert", "+", 0}, /* old (unary +) */
173 {"negate", "-", 0}, /* old (unary -) */
174 {"trunc_mod", "%", 0}, /* old */
175 {"md", "%", DMGL_ANSI}, /* ansi */
176 {"amd", "%=", DMGL_ANSI}, /* ansi */
177 {"trunc_div", "/", 0}, /* old */
178 {"dv", "/", DMGL_ANSI}, /* ansi */
179 {"adv", "/=", DMGL_ANSI}, /* ansi */
180 {"truth_andif", "&&", 0}, /* old */
181 {"aa", "&&", DMGL_ANSI}, /* ansi */
182 {"truth_orif", "||", 0}, /* old */
183 {"oo", "||", DMGL_ANSI}, /* ansi */
184 {"truth_not", "!", 0}, /* old */
185 {"nt", "!", DMGL_ANSI}, /* ansi */
186 {"postincrement","++", 0}, /* old */
187 {"pp", "++", DMGL_ANSI}, /* ansi */
188 {"postdecrement","--", 0}, /* old */
189 {"mm", "--", DMGL_ANSI}, /* ansi */
190 {"bit_ior", "|", 0}, /* old */
191 {"or", "|", DMGL_ANSI}, /* ansi */
192 {"aor", "|=", DMGL_ANSI}, /* ansi */
193 {"bit_xor", "^", 0}, /* old */
194 {"er", "^", DMGL_ANSI}, /* ansi */
195 {"aer", "^=", DMGL_ANSI}, /* ansi */
196 {"bit_and", "&", 0}, /* old */
197 {"ad", "&", DMGL_ANSI}, /* ansi */
198 {"aad", "&=", DMGL_ANSI}, /* ansi */
199 {"bit_not", "~", 0}, /* old */
200 {"co", "~", DMGL_ANSI}, /* ansi */
201 {"call", "()", 0}, /* old */
202 {"cl", "()", DMGL_ANSI}, /* ansi */
203 {"alshift", "<<", 0}, /* old */
204 {"ls", "<<", DMGL_ANSI}, /* ansi */
205 {"als", "<<=", DMGL_ANSI}, /* ansi */
206 {"arshift", ">>", 0}, /* old */
207 {"rs", ">>", DMGL_ANSI}, /* ansi */
208 {"ars", ">>=", DMGL_ANSI}, /* ansi */
209 {"component", "->", 0}, /* old */
210 {"pt", "->", DMGL_ANSI}, /* ansi; Lucid C++ form */
211 {"rf", "->", DMGL_ANSI}, /* ansi; ARM/GNU form */
212 {"indirect", "*", 0}, /* old */
213 {"method_call", "->()", 0}, /* old */
214 {"addr", "&", 0}, /* old (unary &) */
215 {"array", "[]", 0}, /* old */
216 {"vc", "[]", DMGL_ANSI}, /* ansi */
217 {"compound", ", ", 0}, /* old */
218 {"cm", ", ", DMGL_ANSI}, /* ansi */
219 {"cond", "?:", 0}, /* old */
220 {"cn", "?:", DMGL_ANSI}, /* pseudo-ansi */
221 {"max", ">?", 0}, /* old */
222 {"mx", ">?", DMGL_ANSI}, /* pseudo-ansi */
223 {"min", "<?", 0}, /* old */
224 {"mn", "<?", DMGL_ANSI}, /* pseudo-ansi */
225 {"nop", "", 0}, /* old (for operator=) */
226 {"rm", "->*", DMGL_ANSI}, /* ansi */
227 {"sz", "sizeof ", DMGL_ANSI} /* pseudo-ansi */
230 /* These values are used to indicate the various type varieties.
231 They are all non-zero so that they can be used as `success'
233 typedef enum type_kind_t
243 #define STRING_EMPTY(str) ((str) -> b == (str) -> p)
244 #define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
245 string_prepend(str, " ");}
246 #define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
247 string_append(str, " ");}
248 #define LEN_STRING(str) ( (STRING_EMPTY(str))?0:((str)->p - (str)->b))
250 /* The scope separator appropriate for the language being demangled. */
251 #define SCOPE_STRING(work) "::"
253 #define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */
254 #define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */
256 /* Prototypes for local functions */
259 mop_up PARAMS ((struct work_stuff *, string *, int));
262 squangle_mop_up PARAMS ((struct work_stuff *));
266 demangle_method_args PARAMS ((struct work_stuff *, const char **, string *));
270 internal_cplus_demangle PARAMS ((struct work_stuff *, const char *));
273 demangle_template_template_parm PARAMS ((struct work_stuff *work,
274 const char **, string *));
277 demangle_template PARAMS ((struct work_stuff *work, const char **, string *,
278 string *, int, int));
281 arm_pt PARAMS ((struct work_stuff *, const char *, int, const char **,
285 demangle_arm_pt PARAMS ((struct work_stuff *, const char **, int, string *));
288 demangle_class_name PARAMS ((struct work_stuff *, const char **, string *));
291 demangle_qualified PARAMS ((struct work_stuff *, const char **, string *,
295 demangle_class PARAMS ((struct work_stuff *, const char **, string *));
298 demangle_fund_type PARAMS ((struct work_stuff *, const char **, string *));
301 demangle_signature PARAMS ((struct work_stuff *, const char **, string *));
304 demangle_prefix PARAMS ((struct work_stuff *, const char **, string *));
307 gnu_special PARAMS ((struct work_stuff *, const char **, string *));
310 arm_special PARAMS ((const char **, string *));
313 string_need PARAMS ((string *, int));
316 string_delete PARAMS ((string *));
319 string_init PARAMS ((string *));
322 string_clear PARAMS ((string *));
326 string_empty PARAMS ((string *));
330 string_append PARAMS ((string *, const char *));
333 string_appends PARAMS ((string *, string *));
336 string_appendn PARAMS ((string *, const char *, int));
339 string_prepend PARAMS ((string *, const char *));
342 string_prependn PARAMS ((string *, const char *, int));
345 get_count PARAMS ((const char **, int *));
348 consume_count PARAMS ((const char **));
351 consume_count_with_underscores PARAMS ((const char**));
354 demangle_args PARAMS ((struct work_stuff *, const char **, string *));
357 demangle_nested_args PARAMS ((struct work_stuff*, const char**, string*));
360 do_type PARAMS ((struct work_stuff *, const char **, string *));
363 do_arg PARAMS ((struct work_stuff *, const char **, string *));
366 demangle_function_name PARAMS ((struct work_stuff *, const char **, string *,
370 remember_type PARAMS ((struct work_stuff *, const char *, int));
373 remember_Btype PARAMS ((struct work_stuff *, const char *, int, int));
376 register_Btype PARAMS ((struct work_stuff *));
379 remember_Ktype PARAMS ((struct work_stuff *, const char *, int));
382 forget_types PARAMS ((struct work_stuff *));
385 forget_B_and_K_types PARAMS ((struct work_stuff *));
388 string_prepends PARAMS ((string *, string *));
391 demangle_template_value_parm PARAMS ((struct work_stuff*, const char**,
392 string*, type_kind_t));
394 /* There is a TYPE_QUAL value for each type qualifier. They can be
395 combined by bitwise-or to form the complete set of qualifiers for a
398 #define TYPE_UNQUALIFIED 0x0
399 #define TYPE_QUAL_CONST 0x1
400 #define TYPE_QUAL_VOLATILE 0x2
401 #define TYPE_QUAL_RESTRICT 0x4
404 code_for_qualifier PARAMS ((char));
407 qualifier_string PARAMS ((int));
410 demangle_qualifier PARAMS ((char));
412 /* Translate count to integer, consuming tokens in the process.
413 Conversion terminates on the first non-digit character.
414 Trying to consume something that isn't a count results in
415 no consumption of input and a return of 0. */
423 while (isdigit ((unsigned char)**type))
426 count += **type - '0';
433 /* Like consume_count, but for counts that are preceded and followed
434 by '_' if they are greater than 10. Also, -1 is returned for
435 failure, since 0 can be a valid value. */
438 consume_count_with_underscores (mangled)
439 const char **mangled;
443 if (**mangled == '_')
446 if (!isdigit ((unsigned char)**mangled))
449 idx = consume_count (mangled);
450 if (**mangled != '_')
451 /* The trailing underscore was missing. */
458 if (**mangled < '0' || **mangled > '9')
461 idx = **mangled - '0';
468 /* C is the code for a type-qualifier. Return the TYPE_QUAL
469 corresponding to this qualifier. */
472 code_for_qualifier (c)
478 return TYPE_QUAL_CONST;
481 return TYPE_QUAL_VOLATILE;
484 return TYPE_QUAL_RESTRICT;
490 /* C was an invalid qualifier. */
494 /* Return the string corresponding to the qualifiers given by
498 qualifier_string (type_quals)
503 case TYPE_UNQUALIFIED:
506 case TYPE_QUAL_CONST:
509 case TYPE_QUAL_VOLATILE:
512 case TYPE_QUAL_RESTRICT:
515 case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE:
516 return "const volatile";
518 case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT:
519 return "const __restrict";
521 case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
522 return "volatile __restrict";
524 case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
525 return "const volatile __restrict";
531 /* TYPE_QUALS was an invalid qualifier set. */
535 /* C is the code for a type-qualifier. Return the string
536 corresponding to this qualifier. This function should only be
537 called with a valid qualifier code. */
540 demangle_qualifier (c)
543 return qualifier_string (code_for_qualifier (c));
547 cplus_demangle_opname (opname, result, options)
554 struct work_stuff work[1];
557 len = strlen(opname);
560 memset ((char *) work, 0, sizeof (work));
561 work->options = options;
563 if (opname[0] == '_' && opname[1] == '_'
564 && opname[2] == 'o' && opname[3] == 'p')
567 /* type conversion operator. */
569 if (do_type (work, &tem, &type))
571 strcat (result, "operator ");
572 strncat (result, type.b, type.p - type.b);
573 string_delete (&type);
577 else if (opname[0] == '_' && opname[1] == '_'
578 && opname[2] >= 'a' && opname[2] <= 'z'
579 && opname[3] >= 'a' && opname[3] <= 'z')
581 if (opname[4] == '\0')
585 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
587 if (strlen (optable[i].in) == 2
588 && memcmp (optable[i].in, opname + 2, 2) == 0)
590 strcat (result, "operator");
591 strcat (result, optable[i].out);
599 if (opname[2] == 'a' && opname[5] == '\0')
603 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
605 if (strlen (optable[i].in) == 3
606 && memcmp (optable[i].in, opname + 2, 3) == 0)
608 strcat (result, "operator");
609 strcat (result, optable[i].out);
620 && strchr (cplus_markers, opname[2]) != NULL)
622 /* see if it's an assignment expression */
623 if (len >= 10 /* op$assign_ */
624 && memcmp (opname + 3, "assign_", 7) == 0)
627 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
630 if ((int) strlen (optable[i].in) == len1
631 && memcmp (optable[i].in, opname + 10, len1) == 0)
633 strcat (result, "operator");
634 strcat (result, optable[i].out);
635 strcat (result, "=");
644 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
647 if ((int) strlen (optable[i].in) == len1
648 && memcmp (optable[i].in, opname + 3, len1) == 0)
650 strcat (result, "operator");
651 strcat (result, optable[i].out);
658 else if (len >= 5 && memcmp (opname, "type", 4) == 0
659 && strchr (cplus_markers, opname[4]) != NULL)
661 /* type conversion operator */
663 if (do_type (work, &tem, &type))
665 strcat (result, "operator ");
666 strncat (result, type.b, type.p - type.b);
667 string_delete (&type);
671 squangle_mop_up (work);
675 /* Takes operator name as e.g. "++" and returns mangled
676 operator name (e.g. "postincrement_expr"), or NULL if not found.
678 If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
679 if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */
682 cplus_mangle_opname (opname, options)
689 len = strlen (opname);
690 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
692 if ((int) strlen (optable[i].out) == len
693 && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
694 && memcmp (optable[i].out, opname, len) == 0)
695 return optable[i].in;
700 /* char *cplus_demangle (const char *mangled, int options)
702 If MANGLED is a mangled function name produced by GNU C++, then
703 a pointer to a malloced string giving a C++ representation
704 of the name will be returned; otherwise NULL will be returned.
705 It is the caller's responsibility to free the string which
708 The OPTIONS arg may contain one or more of the following bits:
710 DMGL_ANSI ANSI qualifiers such as `const' and `void' are
712 DMGL_PARAMS Function parameters are included.
716 cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)"
717 cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
718 cplus_demangle ("foo__1Ai", 0) => "A::foo"
720 cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)"
721 cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
722 cplus_demangle ("foo__1Afe", 0) => "A::foo"
724 Note that any leading underscores, or other such characters prepended by
725 the compilation system, are presumed to have already been stripped from
729 cplus_demangle (mangled, options)
734 struct work_stuff work[1];
735 memset ((char *) work, 0, sizeof (work));
736 work -> options = options;
737 if ((work -> options & DMGL_STYLE_MASK) == 0)
738 work -> options |= (int) current_demangling_style & DMGL_STYLE_MASK;
740 ret = internal_cplus_demangle (work, mangled);
741 squangle_mop_up (work);
746 /* This function performs most of what cplus_demangle use to do, but
747 to be able to demangle a name with a B, K or n code, we need to
748 have a longer term memory of what types have been seen. The original
749 now intializes and cleans up the squangle code info, while internal
750 calls go directly to this routine to avoid resetting that info. */
753 internal_cplus_demangle (work, mangled)
754 struct work_stuff *work;
760 char *demangled = NULL;
762 s1 = work->constructor;
763 s2 = work->destructor;
764 s3 = work->static_type;
765 s4 = work->type_quals;
766 work->constructor = work->destructor = 0;
767 work->type_quals = TYPE_UNQUALIFIED;
768 work->dllimported = 0;
770 if ((mangled != NULL) && (*mangled != '\0'))
774 /* First check to see if gnu style demangling is active and if the
775 string to be demangled contains a CPLUS_MARKER. If so, attempt to
776 recognize one of the gnu special forms rather than looking for a
777 standard prefix. In particular, don't worry about whether there
778 is a "__" string in the mangled string. Consider "_$_5__foo" for
781 if ((AUTO_DEMANGLING || GNU_DEMANGLING))
783 success = gnu_special (work, &mangled, &decl);
787 success = demangle_prefix (work, &mangled, &decl);
789 if (success && (*mangled != '\0'))
791 success = demangle_signature (work, &mangled, &decl);
793 if (work->constructor == 2)
795 string_prepend (&decl, "global constructors keyed to ");
796 work->constructor = 0;
798 else if (work->destructor == 2)
800 string_prepend (&decl, "global destructors keyed to ");
801 work->destructor = 0;
803 else if (work->dllimported == 1)
805 string_prepend (&decl, "import stub for ");
806 work->dllimported = 0;
808 demangled = mop_up (work, &decl, success);
810 work->constructor = s1;
811 work->destructor = s2;
812 work->static_type = s3;
813 work->type_quals = s4;
818 /* Clear out and squangling related storage */
820 squangle_mop_up (work)
821 struct work_stuff *work;
823 /* clean up the B and K type mangling types. */
824 forget_B_and_K_types (work);
825 if (work -> btypevec != NULL)
827 free ((char *) work -> btypevec);
829 if (work -> ktypevec != NULL)
831 free ((char *) work -> ktypevec);
835 /* Clear out any mangled storage */
838 mop_up (work, declp, success)
839 struct work_stuff *work;
843 char *demangled = NULL;
845 /* Discard the remembered types, if any. */
848 if (work -> typevec != NULL)
850 free ((char *) work -> typevec);
851 work -> typevec = NULL;
853 if (work->tmpl_argvec)
857 for (i = 0; i < work->ntmpl_args; i++)
858 if (work->tmpl_argvec[i])
859 free ((char*) work->tmpl_argvec[i]);
861 free ((char*) work->tmpl_argvec);
862 work->tmpl_argvec = NULL;
864 if (work->previous_argument)
866 string_delete (work->previous_argument);
867 free ((char*) work->previous_argument);
870 /* If demangling was successful, ensure that the demangled string is null
871 terminated and return it. Otherwise, free the demangling decl. */
875 string_delete (declp);
879 string_appendn (declp, "", 1);
880 demangled = declp -> b;
889 demangle_signature -- demangle the signature part of a mangled name
894 demangle_signature (struct work_stuff *work, const char **mangled,
899 Consume and demangle the signature portion of the mangled name.
901 DECLP is the string where demangled output is being built. At
902 entry it contains the demangled root name from the mangled name
903 prefix. I.E. either a demangled operator name or the root function
904 name. In some special cases, it may contain nothing.
906 *MANGLED points to the current unconsumed location in the mangled
907 name. As tokens are consumed and demangling is performed, the
908 pointer is updated to continuously point at the next token to
911 Demangling GNU style mangled names is nasty because there is no
912 explicit token that marks the start of the outermost function
916 demangle_signature (work, mangled, declp)
917 struct work_stuff *work;
918 const char **mangled;
924 int expect_return_type = 0;
925 const char *oldmangled = NULL;
929 while (success && (**mangled != '\0'))
934 oldmangled = *mangled;
935 success = demangle_qualified (work, mangled, declp, 1, 0);
937 remember_type (work, oldmangled, *mangled - oldmangled);
938 if (AUTO_DEMANGLING || GNU_DEMANGLING)
944 oldmangled = *mangled;
945 success = demangle_qualified (work, mangled, declp, 1, 0);
946 if (AUTO_DEMANGLING || GNU_DEMANGLING)
954 /* Static member function */
955 if (oldmangled == NULL)
957 oldmangled = *mangled;
960 work -> static_type = 1;
966 work->type_quals |= code_for_qualifier (**mangled);
968 /* a qualified member function */
969 if (oldmangled == NULL)
970 oldmangled = *mangled;
974 case '0': case '1': case '2': case '3': case '4':
975 case '5': case '6': case '7': case '8': case '9':
976 if (oldmangled == NULL)
978 oldmangled = *mangled;
980 success = demangle_class (work, mangled, declp);
983 remember_type (work, oldmangled, *mangled - oldmangled);
985 if (AUTO_DEMANGLING || GNU_DEMANGLING)
995 success = do_type (work, mangled, &s);
998 string_append (&s, SCOPE_STRING (work));
999 string_prepends (declp, &s);
1008 /* ARM style demangling includes a specific 'F' character after
1009 the class name. For GNU style, it is just implied. So we can
1010 safely just consume any 'F' at this point and be compatible
1011 with either style. */
1017 /* For lucid/ARM style we have to forget any types we might
1018 have remembered up to this point, since they were not argument
1019 types. GNU style considers all types seen as available for
1020 back references. See comment in demangle_args() */
1022 if (LUCID_DEMANGLING || ARM_DEMANGLING)
1024 forget_types (work);
1026 success = demangle_args (work, mangled, declp);
1031 string_init(&trawname);
1032 string_init(&tname);
1033 if (oldmangled == NULL)
1035 oldmangled = *mangled;
1037 success = demangle_template (work, mangled, &tname,
1041 remember_type (work, oldmangled, *mangled - oldmangled);
1043 string_append (&tname, SCOPE_STRING (work));
1045 string_prepends(declp, &tname);
1046 if (work -> destructor & 1)
1048 string_prepend (&trawname, "~");
1049 string_appends (declp, &trawname);
1050 work->destructor -= 1;
1052 if ((work->constructor & 1) || (work->destructor & 1))
1054 string_appends (declp, &trawname);
1055 work->constructor -= 1;
1057 string_delete(&trawname);
1058 string_delete(&tname);
1064 if (GNU_DEMANGLING && expect_return_type)
1066 /* Read the return type. */
1068 string_init (&return_type);
1071 success = do_type (work, mangled, &return_type);
1072 APPEND_BLANK (&return_type);
1074 string_prepends (declp, &return_type);
1075 string_delete (&return_type);
1079 /* At the outermost level, we cannot have a return type specified,
1080 so if we run into another '_' at this point we are dealing with
1081 a mangled name that is either bogus, or has been mangled by
1082 some algorithm we don't know how to deal with. So just
1083 reject the entire demangling. */
1090 /* A G++ template function. Read the template arguments. */
1091 success = demangle_template (work, mangled, declp, 0, 0,
1093 if (!(work->constructor & 1))
1094 expect_return_type = 1;
1103 if (AUTO_DEMANGLING || GNU_DEMANGLING)
1105 /* Assume we have stumbled onto the first outermost function
1106 argument token, and start processing args. */
1108 success = demangle_args (work, mangled, declp);
1112 /* Non-GNU demanglers use a specific token to mark the start
1113 of the outermost function argument tokens. Typically 'F',
1114 for ARM-demangling, for example. So if we find something
1115 we are not prepared for, it must be an error. */
1121 if (AUTO_DEMANGLING || GNU_DEMANGLING)
1124 if (success && expect_func)
1127 success = demangle_args (work, mangled, declp);
1128 /* Since template include the mangling of their return types,
1129 we must set expect_func to 0 so that we don't try do
1130 demangle more arguments the next time we get here. */
1135 if (success && !func_done)
1137 if (AUTO_DEMANGLING || GNU_DEMANGLING)
1139 /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
1140 bar__3fooi is 'foo::bar(int)'. We get here when we find the
1141 first case, and need to ensure that the '(void)' gets added to
1142 the current declp. Note that with ARM, the first case
1143 represents the name of a static data member 'foo::bar',
1144 which is in the current declp, so we leave it alone. */
1145 success = demangle_args (work, mangled, declp);
1148 if (success && PRINT_ARG_TYPES)
1150 if (work->static_type)
1151 string_append (declp, " static");
1152 if (work->type_quals != TYPE_UNQUALIFIED)
1154 APPEND_BLANK (declp);
1155 string_append (declp, qualifier_string (work->type_quals));
1165 demangle_method_args (work, mangled, declp)
1166 struct work_stuff *work;
1167 const char **mangled;
1172 if (work -> static_type)
1174 string_append (declp, *mangled + 1);
1175 *mangled += strlen (*mangled);
1180 success = demangle_args (work, mangled, declp);
1188 demangle_template_template_parm (work, mangled, tname)
1189 struct work_stuff *work;
1190 const char **mangled;
1199 string_append (tname, "template <");
1200 /* get size of template parameter list */
1201 if (get_count (mangled, &r))
1203 for (i = 0; i < r; i++)
1207 string_append (tname, ", ");
1210 /* Z for type parameters */
1211 if (**mangled == 'Z')
1214 string_append (tname, "class");
1216 /* z for template parameters */
1217 else if (**mangled == 'z')
1221 demangle_template_template_parm (work, mangled, tname);
1229 /* temp is initialized in do_type */
1230 success = do_type (work, mangled, &temp);
1233 string_appends (tname, &temp);
1235 string_delete(&temp);
1245 if (tname->p[-1] == '>')
1246 string_append (tname, " ");
1247 string_append (tname, "> class");
1252 demangle_integral_value (work, mangled, s)
1253 struct work_stuff *work;
1254 const char** mangled;
1259 if (**mangled == 'E')
1261 int need_operator = 0;
1264 string_appendn (s, "(", 1);
1266 while (success && **mangled != 'W' && **mangled != '\0')
1275 len = strlen (*mangled);
1278 i < sizeof (optable) / sizeof (optable [0]);
1281 size_t l = strlen (optable[i].in);
1284 && memcmp (optable[i].in, *mangled, l) == 0)
1286 string_appendn (s, " ", 1);
1287 string_append (s, optable[i].out);
1288 string_appendn (s, " ", 1);
1301 success = demangle_template_value_parm (work, mangled, s,
1305 if (**mangled != 'W')
1309 string_appendn (s, ")", 1);
1313 else if (**mangled == 'Q' || **mangled == 'K')
1314 success = demangle_qualified (work, mangled, s, 0, 1);
1319 if (**mangled == 'm')
1321 string_appendn (s, "-", 1);
1324 while (isdigit ((unsigned char)**mangled))
1326 string_appendn (s, *mangled, 1);
1336 demangle_template_value_parm (work, mangled, s, tk)
1337 struct work_stuff *work;
1338 const char **mangled;
1344 if (**mangled == 'Y')
1346 /* The next argument is a template parameter. */
1350 idx = consume_count_with_underscores (mangled);
1352 || (work->tmpl_argvec && idx >= work->ntmpl_args)
1353 || consume_count_with_underscores (mangled) == -1)
1355 if (work->tmpl_argvec)
1356 string_append (s, work->tmpl_argvec[idx]);
1360 sprintf(buf, "T%d", idx);
1361 string_append (s, buf);
1364 else if (tk == tk_integral)
1365 success = demangle_integral_value (work, mangled, s);
1366 else if (tk == tk_char)
1370 if (**mangled == 'm')
1372 string_appendn (s, "-", 1);
1375 string_appendn (s, "'", 1);
1376 val = consume_count(mangled);
1381 string_appendn (s, &tmp[0], 1);
1382 string_appendn (s, "'", 1);
1384 else if (tk == tk_bool)
1386 int val = consume_count (mangled);
1388 string_appendn (s, "false", 5);
1390 string_appendn (s, "true", 4);
1394 else if (tk == tk_real)
1396 if (**mangled == 'm')
1398 string_appendn (s, "-", 1);
1401 while (isdigit ((unsigned char)**mangled))
1403 string_appendn (s, *mangled, 1);
1406 if (**mangled == '.') /* fraction */
1408 string_appendn (s, ".", 1);
1410 while (isdigit ((unsigned char)**mangled))
1412 string_appendn (s, *mangled, 1);
1416 if (**mangled == 'e') /* exponent */
1418 string_appendn (s, "e", 1);
1420 while (isdigit ((unsigned char)**mangled))
1422 string_appendn (s, *mangled, 1);
1427 else if (tk == tk_pointer)
1429 int symbol_len = consume_count (mangled);
1430 if (symbol_len == 0)
1432 if (symbol_len == 0)
1433 string_appendn (s, "0", 1);
1436 char *p = xmalloc (symbol_len + 1), *q;
1437 strncpy (p, *mangled, symbol_len);
1438 p [symbol_len] = '\0';
1439 /* We use cplus_demangle here, rather than
1440 internal_cplus_demangle, because the name of the entity
1441 mangled here does not make use of any of the squangling
1442 or type-code information we have built up thus far; it is
1443 mangled independently. */
1444 q = cplus_demangle (p, work->options);
1445 string_appendn (s, "&", 1);
1446 /* FIXME: Pointer-to-member constants should get a
1447 qualifying class name here. */
1450 string_append (s, q);
1454 string_append (s, p);
1457 *mangled += symbol_len;
1463 /* Demangle the template name in MANGLED. The full name of the
1464 template (e.g., S<int>) is placed in TNAME. The name without the
1465 template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is
1466 non-NULL. If IS_TYPE is nonzero, this template is a type template,
1467 not a function template. If both IS_TYPE and REMEMBER are nonzero,
1468 the tmeplate is remembered in the list of back-referenceable
1472 demangle_template (work, mangled, tname, trawname, is_type, remember)
1473 struct work_stuff *work;
1474 const char **mangled;
1492 bindex = register_Btype (work);
1494 /* get template name */
1495 if (**mangled == 'z')
1501 idx = consume_count_with_underscores (mangled);
1503 || (work->tmpl_argvec && idx >= work->ntmpl_args)
1504 || consume_count_with_underscores (mangled) == -1)
1507 if (work->tmpl_argvec)
1509 string_append (tname, work->tmpl_argvec[idx]);
1511 string_append (trawname, work->tmpl_argvec[idx]);
1516 sprintf(buf, "T%d", idx);
1517 string_append (tname, buf);
1519 string_append (trawname, buf);
1524 if ((r = consume_count (mangled)) == 0
1525 || (int) strlen (*mangled) < r)
1529 string_appendn (tname, *mangled, r);
1531 string_appendn (trawname, *mangled, r);
1535 string_append (tname, "<");
1536 /* get size of template parameter list */
1537 if (!get_count (mangled, &r))
1543 /* Create an array for saving the template argument values. */
1544 work->tmpl_argvec = (char**) xmalloc (r * sizeof (char *));
1545 work->ntmpl_args = r;
1546 for (i = 0; i < r; i++)
1547 work->tmpl_argvec[i] = 0;
1549 for (i = 0; i < r; i++)
1553 string_append (tname, ", ");
1555 /* Z for type parameters */
1556 if (**mangled == 'Z')
1559 /* temp is initialized in do_type */
1560 success = do_type (work, mangled, &temp);
1563 string_appends (tname, &temp);
1567 /* Save the template argument. */
1568 int len = temp.p - temp.b;
1569 work->tmpl_argvec[i] = xmalloc (len + 1);
1570 memcpy (work->tmpl_argvec[i], temp.b, len);
1571 work->tmpl_argvec[i][len] = '\0';
1574 string_delete(&temp);
1580 /* z for template parameters */
1581 else if (**mangled == 'z')
1585 success = demangle_template_template_parm (work, mangled, tname);
1588 && (r2 = consume_count (mangled)) > 0
1589 && (int) strlen (*mangled) >= r2)
1591 string_append (tname, " ");
1592 string_appendn (tname, *mangled, r2);
1595 /* Save the template argument. */
1597 work->tmpl_argvec[i] = xmalloc (len + 1);
1598 memcpy (work->tmpl_argvec[i], *mangled, len);
1599 work->tmpl_argvec[i][len] = '\0';
1613 /* otherwise, value parameter */
1615 /* temp is initialized in do_type */
1616 success = do_type (work, mangled, &temp);
1617 string_delete(&temp);
1629 success = demangle_template_value_parm (work, mangled, s,
1630 (type_kind_t) success);
1642 int len = s->p - s->b;
1643 work->tmpl_argvec[i] = xmalloc (len + 1);
1644 memcpy (work->tmpl_argvec[i], s->b, len);
1645 work->tmpl_argvec[i][len] = '\0';
1647 string_appends (tname, s);
1654 if (tname->p[-1] == '>')
1655 string_append (tname, " ");
1656 string_append (tname, ">");
1659 if (is_type && remember)
1660 remember_Btype (work, tname->b, LEN_STRING (tname), bindex);
1663 if (work -> static_type)
1665 string_append (declp, *mangled + 1);
1666 *mangled += strlen (*mangled);
1671 success = demangle_args (work, mangled, declp);
1679 arm_pt (work, mangled, n, anchor, args)
1680 struct work_stuff *work;
1681 const char *mangled;
1683 const char **anchor, **args;
1686 if (ARM_DEMANGLING && (*anchor = mystrstr (mangled, "__pt__")))
1689 *args = *anchor + 6;
1690 len = consume_count (args);
1691 if (*args + len == mangled + n && **args == '_')
1701 demangle_arm_pt (work, mangled, n, declp)
1702 struct work_stuff *work;
1703 const char **mangled;
1709 const char *e = *mangled + n;
1712 if (arm_pt (work, *mangled, n, &p, &args))
1716 string_appendn (declp, *mangled, p - *mangled);
1717 string_append (declp, "<");
1718 /* should do error checking here */
1720 string_clear (&arg);
1721 do_type (work, &args, &arg);
1722 string_appends (declp, &arg);
1723 string_append (declp, ",");
1725 string_delete (&arg);
1727 string_append (declp, ">");
1729 else if (n>10 && strncmp (*mangled, "_GLOBAL_", 8) == 0
1730 && (*mangled)[9] == 'N'
1731 && (*mangled)[8] == (*mangled)[10]
1732 && strchr (cplus_markers, (*mangled)[8]))
1734 /* A member of the anonymous namespace. */
1735 string_append (declp, "{anonymous}");
1739 string_appendn (declp, *mangled, n);
1745 demangle_class_name (work, mangled, declp)
1746 struct work_stuff *work;
1747 const char **mangled;
1753 n = consume_count (mangled);
1754 if ((int) strlen (*mangled) >= n)
1756 demangle_arm_pt (work, mangled, n, declp);
1767 demangle_class -- demangle a mangled class sequence
1772 demangle_class (struct work_stuff *work, const char **mangled,
1777 DECLP points to the buffer into which demangling is being done.
1779 *MANGLED points to the current token to be demangled. On input,
1780 it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
1781 On exit, it points to the next token after the mangled class on
1782 success, or the first unconsumed token on failure.
1784 If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
1785 we are demangling a constructor or destructor. In this case
1786 we prepend "class::class" or "class::~class" to DECLP.
1788 Otherwise, we prepend "class::" to the current DECLP.
1790 Reset the constructor/destructor flags once they have been
1791 "consumed". This allows demangle_class to be called later during
1792 the same demangling, to do normal class demangling.
1794 Returns 1 if demangling is successful, 0 otherwise.
1799 demangle_class (work, mangled, declp)
1800 struct work_stuff *work;
1801 const char **mangled;
1808 string_init (&class_name);
1809 btype = register_Btype (work);
1810 if (demangle_class_name (work, mangled, &class_name))
1812 if ((work->constructor & 1) || (work->destructor & 1))
1814 string_prepends (declp, &class_name);
1815 if (work -> destructor & 1)
1817 string_prepend (declp, "~");
1818 work -> destructor -= 1;
1822 work -> constructor -= 1;
1825 remember_Ktype (work, class_name.b, LEN_STRING(&class_name));
1826 remember_Btype (work, class_name.b, LEN_STRING(&class_name), btype);
1827 string_prepend (declp, SCOPE_STRING (work));
1828 string_prepends (declp, &class_name);
1831 string_delete (&class_name);
1839 demangle_prefix -- consume the mangled name prefix and find signature
1844 demangle_prefix (struct work_stuff *work, const char **mangled,
1849 Consume and demangle the prefix of the mangled name.
1851 DECLP points to the string buffer into which demangled output is
1852 placed. On entry, the buffer is empty. On exit it contains
1853 the root function name, the demangled operator name, or in some
1854 special cases either nothing or the completely demangled result.
1856 MANGLED points to the current pointer into the mangled name. As each
1857 token of the mangled name is consumed, it is updated. Upon entry
1858 the current mangled name pointer points to the first character of
1859 the mangled name. Upon exit, it should point to the first character
1860 of the signature if demangling was successful, or to the first
1861 unconsumed character if demangling of the prefix was unsuccessful.
1863 Returns 1 on success, 0 otherwise.
1867 demangle_prefix (work, mangled, declp)
1868 struct work_stuff *work;
1869 const char **mangled;
1876 if (strlen(*mangled) > 6
1877 && (strncmp(*mangled, "_imp__", 6) == 0
1878 || strncmp(*mangled, "__imp_", 6) == 0))
1880 /* it's a symbol imported from a PE dynamic library. Check for both
1881 new style prefix _imp__ and legacy __imp_ used by older versions
1884 work->dllimported = 1;
1886 else if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0)
1888 char *marker = strchr (cplus_markers, (*mangled)[8]);
1889 if (marker != NULL && *marker == (*mangled)[10])
1891 if ((*mangled)[9] == 'D')
1893 /* it's a GNU global destructor to be executed at program exit */
1895 work->destructor = 2;
1896 if (gnu_special (work, mangled, declp))
1899 else if ((*mangled)[9] == 'I')
1901 /* it's a GNU global constructor to be executed at program init */
1903 work->constructor = 2;
1904 if (gnu_special (work, mangled, declp))
1909 else if (ARM_DEMANGLING && strncmp(*mangled, "__std__", 7) == 0)
1911 /* it's a ARM global destructor to be executed at program exit */
1913 work->destructor = 2;
1915 else if (ARM_DEMANGLING && strncmp(*mangled, "__sti__", 7) == 0)
1917 /* it's a ARM global constructor to be executed at program initial */
1919 work->constructor = 2;
1922 /* This block of code is a reduction in strength time optimization
1924 scan = mystrstr (*mangled, "__"); */
1930 scan = strchr (scan, '_');
1931 } while (scan != NULL && *++scan != '_');
1933 if (scan != NULL) --scan;
1938 /* We found a sequence of two or more '_', ensure that we start at
1939 the last pair in the sequence. */
1940 i = strspn (scan, "_");
1951 else if (work -> static_type)
1953 if (!isdigit ((unsigned char)scan[0]) && (scan[0] != 't'))
1958 else if ((scan == *mangled)
1959 && (isdigit ((unsigned char)scan[2]) || (scan[2] == 'Q')
1960 || (scan[2] == 't') || (scan[2] == 'K') || (scan[2] == 'H')))
1962 /* The ARM says nothing about the mangling of local variables.
1963 But cfront mangles local variables by prepending __<nesting_level>
1964 to them. As an extension to ARM demangling we handle this case. */
1965 if ((LUCID_DEMANGLING || ARM_DEMANGLING)
1966 && isdigit ((unsigned char)scan[2]))
1968 *mangled = scan + 2;
1969 consume_count (mangled);
1970 string_append (declp, *mangled);
1971 *mangled += strlen (*mangled);
1976 /* A GNU style constructor starts with __[0-9Qt]. But cfront uses
1977 names like __Q2_3foo3bar for nested type names. So don't accept
1978 this style of constructor for cfront demangling. A GNU
1979 style member-template constructor starts with 'H'. */
1980 if (!(LUCID_DEMANGLING || ARM_DEMANGLING))
1981 work -> constructor += 1;
1982 *mangled = scan + 2;
1985 else if ((scan == *mangled) && !isdigit ((unsigned char)scan[2])
1986 && (scan[2] != 't'))
1988 /* Mangled name starts with "__". Skip over any leading '_' characters,
1989 then find the next "__" that separates the prefix from the signature.
1991 if (!(ARM_DEMANGLING || LUCID_DEMANGLING)
1992 || (arm_special (mangled, declp) == 0))
1994 while (*scan == '_')
1998 if ((scan = mystrstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
2000 /* No separator (I.E. "__not_mangled"), or empty signature
2001 (I.E. "__not_mangled_either__") */
2006 demangle_function_name (work, mangled, declp, scan);
2010 else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't')
2012 /* Cfront-style parameterized type. Handled later as a signature. */
2016 demangle_arm_pt (work, mangled, strlen (*mangled), declp);
2018 else if (*(scan + 2) != '\0')
2020 /* Mangled name does not start with "__" but does have one somewhere
2021 in there with non empty stuff after it. Looks like a global
2023 demangle_function_name (work, mangled, declp, scan);
2027 /* Doesn't look like a mangled name */
2031 if (!success && (work->constructor == 2 || work->destructor == 2))
2033 string_append (declp, *mangled);
2034 *mangled += strlen (*mangled);
2044 gnu_special -- special handling of gnu mangled strings
2049 gnu_special (struct work_stuff *work, const char **mangled,
2055 Process some special GNU style mangling forms that don't fit
2056 the normal pattern. For example:
2058 _$_3foo (destructor for class foo)
2059 _vt$foo (foo virtual table)
2060 _vt$foo$bar (foo::bar virtual table)
2061 __vt_foo (foo virtual table, new style with thunks)
2062 _3foo$varname (static data member)
2063 _Q22rs2tu$vw (static data member)
2064 __t6vector1Zii (constructor with template)
2065 __thunk_4__$_7ostream (virtual function thunk)
2069 gnu_special (work, mangled, declp)
2070 struct work_stuff *work;
2071 const char **mangled;
2078 if ((*mangled)[0] == '_'
2079 && strchr (cplus_markers, (*mangled)[1]) != NULL
2080 && (*mangled)[2] == '_')
2082 /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
2084 work -> destructor += 1;
2086 else if ((*mangled)[0] == '_'
2087 && (((*mangled)[1] == '_'
2088 && (*mangled)[2] == 'v'
2089 && (*mangled)[3] == 't'
2090 && (*mangled)[4] == '_')
2091 || ((*mangled)[1] == 'v'
2092 && (*mangled)[2] == 't'
2093 && strchr (cplus_markers, (*mangled)[3]) != NULL)))
2095 /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
2096 and create the decl. Note that we consume the entire mangled
2097 input string, which means that demangle_signature has no work
2099 if ((*mangled)[2] == 'v')
2100 (*mangled) += 5; /* New style, with thunks: "__vt_" */
2102 (*mangled) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
2103 while (**mangled != '\0')
2109 success = demangle_qualified (work, mangled, declp, 0, 1);
2112 success = demangle_template (work, mangled, declp, 0, 1,
2116 if (isdigit((unsigned char)*mangled[0]))
2118 n = consume_count(mangled);
2119 /* We may be seeing a too-large size, or else a
2120 ".<digits>" indicating a static local symbol. In
2121 any case, declare victory and move on; *don't* try
2122 to use n to allocate. */
2123 if (n > (int) strlen (*mangled))
2131 n = strcspn (*mangled, cplus_markers);
2133 string_appendn (declp, *mangled, n);
2137 p = strpbrk (*mangled, cplus_markers);
2138 if (success && ((p == NULL) || (p == *mangled)))
2142 string_append (declp, SCOPE_STRING (work));
2153 string_append (declp, " virtual table");
2155 else if ((*mangled)[0] == '_'
2156 && (strchr("0123456789Qt", (*mangled)[1]) != NULL)
2157 && (p = strpbrk (*mangled, cplus_markers)) != NULL)
2159 /* static data member, "_3foo$varname" for example */
2165 success = demangle_qualified (work, mangled, declp, 0, 1);
2168 success = demangle_template (work, mangled, declp, 0, 1, 1);
2171 n = consume_count (mangled);
2172 string_appendn (declp, *mangled, n);
2175 if (success && (p == *mangled))
2177 /* Consumed everything up to the cplus_marker, append the
2180 string_append (declp, SCOPE_STRING (work));
2181 n = strlen (*mangled);
2182 string_appendn (declp, *mangled, n);
2190 else if (strncmp (*mangled, "__thunk_", 8) == 0)
2192 int delta = ((*mangled) += 8, consume_count (mangled));
2193 char *method = internal_cplus_demangle (work, ++*mangled);
2197 sprintf (buf, "virtual function thunk (delta:%d) for ", -delta);
2198 string_append (declp, buf);
2199 string_append (declp, method);
2201 n = strlen (*mangled);
2209 else if (strncmp (*mangled, "__t", 3) == 0
2210 && ((*mangled)[3] == 'i' || (*mangled)[3] == 'f'))
2212 p = (*mangled)[3] == 'i' ? " type_info node" : " type_info function";
2218 success = demangle_qualified (work, mangled, declp, 0, 1);
2221 success = demangle_template (work, mangled, declp, 0, 1, 1);
2224 success = demangle_fund_type (work, mangled, declp);
2227 if (success && **mangled != '\0')
2230 string_append (declp, p);
2243 arm_special -- special handling of ARM/lucid mangled strings
2248 arm_special (const char **mangled,
2254 Process some special ARM style mangling forms that don't fit
2255 the normal pattern. For example:
2257 __vtbl__3foo (foo virtual table)
2258 __vtbl__3foo__3bar (bar::foo virtual table)
2263 arm_special (mangled, declp)
2264 const char **mangled;
2271 if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
2273 /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
2274 and create the decl. Note that we consume the entire mangled
2275 input string, which means that demangle_signature has no work
2277 scan = *mangled + ARM_VTABLE_STRLEN;
2278 while (*scan != '\0') /* first check it can be demangled */
2280 n = consume_count (&scan);
2283 return (0); /* no good */
2286 if (scan[0] == '_' && scan[1] == '_')
2291 (*mangled) += ARM_VTABLE_STRLEN;
2292 while (**mangled != '\0')
2294 n = consume_count (mangled);
2295 string_prependn (declp, *mangled, n);
2297 if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
2299 string_prepend (declp, "::");
2303 string_append (declp, " virtual table");
2316 demangle_qualified -- demangle 'Q' qualified name strings
2321 demangle_qualified (struct work_stuff *, const char *mangled,
2322 string *result, int isfuncname, int append);
2326 Demangle a qualified name, such as "Q25Outer5Inner" which is
2327 the mangled form of "Outer::Inner". The demangled output is
2328 prepended or appended to the result string according to the
2329 state of the append flag.
2331 If isfuncname is nonzero, then the qualified name we are building
2332 is going to be used as a member function name, so if it is a
2333 constructor or destructor function, append an appropriate
2334 constructor or destructor name. I.E. for the above example,
2335 the result for use as a constructor is "Outer::Inner::Inner"
2336 and the result for use as a destructor is "Outer::Inner::~Inner".
2340 Numeric conversion is ASCII dependent (FIXME).
2345 demangle_qualified (work, mangled, result, isfuncname, append)
2346 struct work_stuff *work;
2347 const char **mangled;
2358 int bindex = register_Btype (work);
2360 /* We only make use of ISFUNCNAME if the entity is a constructor or
2362 isfuncname = (isfuncname
2363 && ((work->constructor & 1) || (work->destructor & 1)));
2365 string_init (&temp);
2366 string_init (&last_name);
2368 if ((*mangled)[0] == 'K')
2370 /* Squangling qualified name reuse */
2373 idx = consume_count_with_underscores (mangled);
2374 if (idx == -1 || idx >= work -> numk)
2377 string_append (&temp, work -> ktypevec[idx]);
2380 switch ((*mangled)[1])
2383 /* GNU mangled name with more than 9 classes. The count is preceded
2384 by an underscore (to distinguish it from the <= 9 case) and followed
2385 by an underscore. */
2387 qualifiers = atoi (p);
2388 if (!isdigit ((unsigned char)*p) || *p == '0')
2391 /* Skip the digits. */
2392 while (isdigit ((unsigned char)*p))
2410 /* The count is in a single digit. */
2411 num[0] = (*mangled)[1];
2413 qualifiers = atoi (num);
2415 /* If there is an underscore after the digit, skip it. This is
2416 said to be for ARM-qualified names, but the ARM makes no
2417 mention of such an underscore. Perhaps cfront uses one. */
2418 if ((*mangled)[2] == '_')
2433 /* Pick off the names and collect them in the temp buffer in the order
2434 in which they are found, separated by '::'. */
2436 while (qualifiers-- > 0)
2439 string_clear (&last_name);
2441 if (*mangled[0] == '_')
2444 if (*mangled[0] == 't')
2446 /* Here we always append to TEMP since we will want to use
2447 the template name without the template parameters as a
2448 constructor or destructor name. The appropriate
2449 (parameter-less) value is returned by demangle_template
2450 in LAST_NAME. We do not remember the template type here,
2451 in order to match the G++ mangling algorithm. */
2452 success = demangle_template(work, mangled, &temp,
2457 else if (*mangled[0] == 'K')
2461 idx = consume_count_with_underscores (mangled);
2462 if (idx == -1 || idx >= work->numk)
2465 string_append (&temp, work->ktypevec[idx]);
2468 if (!success) break;
2472 success = do_type (work, mangled, &last_name);
2475 string_appends (&temp, &last_name);
2479 remember_Ktype (work, temp.b, LEN_STRING (&temp));
2482 string_append (&temp, SCOPE_STRING (work));
2485 remember_Btype (work, temp.b, LEN_STRING (&temp), bindex);
2487 /* If we are using the result as a function name, we need to append
2488 the appropriate '::' separated constructor or destructor name.
2489 We do this here because this is the most convenient place, where
2490 we already have a pointer to the name and the length of the name. */
2494 string_append (&temp, SCOPE_STRING (work));
2495 if (work -> destructor & 1)
2496 string_append (&temp, "~");
2497 string_appends (&temp, &last_name);
2500 /* Now either prepend the temp buffer to the result, or append it,
2501 depending upon the state of the append flag. */
2504 string_appends (result, &temp);
2507 if (!STRING_EMPTY (result))
2508 string_append (&temp, SCOPE_STRING (work));
2509 string_prepends (result, &temp);
2512 string_delete (&last_name);
2513 string_delete (&temp);
2521 get_count -- convert an ascii count to integer, consuming tokens
2526 get_count (const char **type, int *count)
2530 Return 0 if no conversion is performed, 1 if a string is converted.
2534 get_count (type, count)
2541 if (!isdigit ((unsigned char)**type))
2547 *count = **type - '0';
2549 if (isdigit ((unsigned char)**type))
2559 while (isdigit ((unsigned char)*p));
2570 /* RESULT will be initialised here; it will be freed on failure. The
2571 value returned is really a type_kind_t. */
2574 do_type (work, mangled, result)
2575 struct work_stuff *work;
2576 const char **mangled;
2583 const char *remembered_type;
2586 type_kind_t tk = tk_none;
2588 string_init (&btype);
2589 string_init (&decl);
2590 string_init (result);
2594 while (success && !done)
2600 /* A pointer type */
2604 string_prepend (&decl, "*");
2609 /* A reference type */
2612 string_prepend (&decl, "&");
2621 if (!STRING_EMPTY (&decl)
2622 && (decl.b[0] == '*' || decl.b[0] == '&'))
2624 string_prepend (&decl, "(");
2625 string_append (&decl, ")");
2627 string_append (&decl, "[");
2628 if (**mangled != '_')
2629 success = demangle_template_value_parm (work, mangled, &decl,
2631 if (**mangled == '_')
2633 string_append (&decl, "]");
2637 /* A back reference to a previously seen type */
2640 if (!get_count (mangled, &n) || n >= work -> ntypes)
2646 remembered_type = work -> typevec[n];
2647 mangled = &remembered_type;
2654 if (!STRING_EMPTY (&decl)
2655 && (decl.b[0] == '*' || decl.b[0] == '&'))
2657 string_prepend (&decl, "(");
2658 string_append (&decl, ")");
2660 /* After picking off the function args, we expect to either find the
2661 function return type (preceded by an '_') or the end of the
2663 if (!demangle_nested_args (work, mangled, &decl)
2664 || (**mangled != '_' && **mangled != '\0'))
2669 if (success && (**mangled == '_'))
2676 type_quals = TYPE_UNQUALIFIED;
2678 member = **mangled == 'M';
2680 if (!isdigit ((unsigned char)**mangled) && **mangled != 't')
2686 string_append (&decl, ")");
2687 string_prepend (&decl, SCOPE_STRING (work));
2688 if (isdigit ((unsigned char)**mangled))
2690 n = consume_count (mangled);
2691 if ((int) strlen (*mangled) < n)
2696 string_prependn (&decl, *mangled, n);
2702 string_init (&temp);
2703 success = demangle_template (work, mangled, &temp,
2707 string_prependn (&decl, temp.b, temp.p - temp.b);
2708 string_clear (&temp);
2713 string_prepend (&decl, "(");
2721 type_quals |= code_for_qualifier (**mangled);
2729 if (*(*mangled)++ != 'F')
2735 if ((member && !demangle_nested_args (work, mangled, &decl))
2736 || **mangled != '_')
2742 if (! PRINT_ANSI_QUALIFIERS)
2746 if (type_quals != TYPE_UNQUALIFIED)
2748 APPEND_BLANK (&decl);
2749 string_append (&decl, qualifier_string (type_quals));
2760 if (PRINT_ANSI_QUALIFIERS)
2762 if (!STRING_EMPTY (&decl))
2763 string_prepend (&decl, " ");
2765 string_prepend (&decl, demangle_qualifier (**mangled));
2780 if (success) switch (**mangled)
2782 /* A qualified name, such as "Outer::Inner". */
2786 success = demangle_qualified (work, mangled, result, 0, 1);
2790 /* A back reference to a previously seen squangled type */
2793 if (!get_count (mangled, &n) || n >= work -> numb)
2796 string_append (result, work->btypevec[n]);
2801 /* A template parm. We substitute the corresponding argument. */
2806 idx = consume_count_with_underscores (mangled);
2809 || (work->tmpl_argvec && idx >= work->ntmpl_args)
2810 || consume_count_with_underscores (mangled) == -1)
2816 if (work->tmpl_argvec)
2817 string_append (result, work->tmpl_argvec[idx]);
2821 sprintf(buf, "T%d", idx);
2822 string_append (result, buf);
2830 success = demangle_fund_type (work, mangled, result);
2832 tk = (type_kind_t) success;
2838 if (!STRING_EMPTY (&decl))
2840 string_append (result, " ");
2841 string_appends (result, &decl);
2845 string_delete (result);
2846 string_delete (&decl);
2849 /* Assume an integral type, if we're not sure. */
2850 return (int) ((tk == tk_none) ? tk_integral : tk);
2855 /* Given a pointer to a type string that represents a fundamental type
2856 argument (int, long, unsigned int, etc) in TYPE, a pointer to the
2857 string in which the demangled output is being built in RESULT, and
2858 the WORK structure, decode the types and add them to the result.
2863 "Sl" => "signed long"
2864 "CUs" => "const unsigned short"
2866 The value returned is really a type_kind_t. */
2869 demangle_fund_type (work, mangled, result)
2870 struct work_stuff *work;
2871 const char **mangled;
2877 type_kind_t tk = tk_integral;
2879 string_init (&btype);
2881 /* First pick off any type qualifiers. There can be more than one. */
2891 if (PRINT_ANSI_QUALIFIERS)
2893 APPEND_BLANK (result);
2894 string_append (result, demangle_qualifier (**mangled));
2899 APPEND_BLANK (result);
2900 string_append (result, "unsigned");
2902 case 'S': /* signed char only */
2904 APPEND_BLANK (result);
2905 string_append (result, "signed");
2909 APPEND_BLANK (result);
2910 string_append (result, "__complex");
2918 /* Now pick off the fundamental type. There can be only one. */
2927 APPEND_BLANK (result);
2928 string_append (result, "void");
2932 APPEND_BLANK (result);
2933 string_append (result, "long long");
2937 APPEND_BLANK (result);
2938 string_append (result, "long");
2942 APPEND_BLANK (result);
2943 string_append (result, "int");
2947 APPEND_BLANK (result);
2948 string_append (result, "short");
2952 APPEND_BLANK (result);
2953 string_append (result, "bool");
2958 APPEND_BLANK (result);
2959 string_append (result, "char");
2964 APPEND_BLANK (result);
2965 string_append (result, "wchar_t");
2970 APPEND_BLANK (result);
2971 string_append (result, "long double");
2976 APPEND_BLANK (result);
2977 string_append (result, "double");
2982 APPEND_BLANK (result);
2983 string_append (result, "float");
2988 if (!isdigit ((unsigned char)**mangled))
2994 /* An explicit type, such as "6mytype" or "7integer" */
3006 int bindex = register_Btype (work);
3008 string_init (&btype);
3009 if (demangle_class_name (work, mangled, &btype)) {
3010 remember_Btype (work, btype.b, LEN_STRING (&btype), bindex);
3011 APPEND_BLANK (result);
3012 string_appends (result, &btype);
3016 string_delete (&btype);
3021 success = demangle_template (work, mangled, &btype, 0, 1, 1);
3022 string_appends (result, &btype);
3030 return success ? ((int) tk) : 0;
3033 /* Demangle the next argument, given by MANGLED into RESULT, which
3034 *should be an uninitialized* string. It will be initialized here,
3035 and free'd should anything go wrong. */
3038 do_arg (work, mangled, result)
3039 struct work_stuff *work;
3040 const char **mangled;
3043 /* Remember where we started so that we can record the type, for
3044 non-squangling type remembering. */
3045 const char *start = *mangled;
3047 string_init (result);
3049 if (work->nrepeats > 0)
3053 if (work->previous_argument == 0)
3056 /* We want to reissue the previous type in this argument list. */
3057 string_appends (result, work->previous_argument);
3061 if (**mangled == 'n')
3063 /* A squangling-style repeat. */
3065 work->nrepeats = consume_count(mangled);
3067 if (work->nrepeats == 0)
3068 /* This was not a repeat count after all. */
3071 if (work->nrepeats > 9)
3073 if (**mangled != '_')
3074 /* The repeat count should be followed by an '_' in this
3081 /* Now, the repeat is all set up. */
3082 return do_arg (work, mangled, result);
3085 /* Save the result in WORK->previous_argument so that we can find it
3086 if it's repeated. Note that saving START is not good enough: we
3087 do not want to add additional types to the back-referenceable
3088 type vector when processing a repeated type. */
3089 if (work->previous_argument)
3090 string_clear (work->previous_argument);
3093 work->previous_argument = (string*) xmalloc (sizeof (string));
3094 string_init (work->previous_argument);
3097 if (!do_type (work, mangled, work->previous_argument))
3100 string_appends (result, work->previous_argument);
3102 remember_type (work, start, *mangled - start);
3107 remember_type (work, start, len)
3108 struct work_stuff *work;
3114 if (work->forgetting_types)
3117 if (work -> ntypes >= work -> typevec_size)
3119 if (work -> typevec_size == 0)
3121 work -> typevec_size = 3;
3123 = (char **) xmalloc (sizeof (char *) * work -> typevec_size);
3127 work -> typevec_size *= 2;
3129 = (char **) xrealloc ((char *)work -> typevec,
3130 sizeof (char *) * work -> typevec_size);
3133 tem = xmalloc (len + 1);
3134 memcpy (tem, start, len);
3136 work -> typevec[work -> ntypes++] = tem;
3140 /* Remember a K type class qualifier. */
3142 remember_Ktype (work, start, len)
3143 struct work_stuff *work;
3149 if (work -> numk >= work -> ksize)
3151 if (work -> ksize == 0)
3155 = (char **) xmalloc (sizeof (char *) * work -> ksize);
3161 = (char **) xrealloc ((char *)work -> ktypevec,
3162 sizeof (char *) * work -> ksize);
3165 tem = xmalloc (len + 1);
3166 memcpy (tem, start, len);
3168 work -> ktypevec[work -> numk++] = tem;
3171 /* Register a B code, and get an index for it. B codes are registered
3172 as they are seen, rather than as they are completed, so map<temp<char> >
3173 registers map<temp<char> > as B0, and temp<char> as B1 */
3176 register_Btype (work)
3177 struct work_stuff *work;
3181 if (work -> numb >= work -> bsize)
3183 if (work -> bsize == 0)
3187 = (char **) xmalloc (sizeof (char *) * work -> bsize);
3193 = (char **) xrealloc ((char *)work -> btypevec,
3194 sizeof (char *) * work -> bsize);
3197 ret = work -> numb++;
3198 work -> btypevec[ret] = NULL;
3202 /* Store a value into a previously registered B code type. */
3205 remember_Btype (work, start, len, index)
3206 struct work_stuff *work;
3212 tem = xmalloc (len + 1);
3213 memcpy (tem, start, len);
3215 work -> btypevec[index] = tem;
3218 /* Lose all the info related to B and K type codes. */
3220 forget_B_and_K_types (work)
3221 struct work_stuff *work;
3225 while (work -> numk > 0)
3227 i = --(work -> numk);
3228 if (work -> ktypevec[i] != NULL)
3230 free (work -> ktypevec[i]);
3231 work -> ktypevec[i] = NULL;
3235 while (work -> numb > 0)
3237 i = --(work -> numb);
3238 if (work -> btypevec[i] != NULL)
3240 free (work -> btypevec[i]);
3241 work -> btypevec[i] = NULL;
3245 /* Forget the remembered types, but not the type vector itself. */
3249 struct work_stuff *work;
3253 while (work -> ntypes > 0)
3255 i = --(work -> ntypes);
3256 if (work -> typevec[i] != NULL)
3258 free (work -> typevec[i]);
3259 work -> typevec[i] = NULL;
3264 /* Process the argument list part of the signature, after any class spec
3265 has been consumed, as well as the first 'F' character (if any). For
3268 "__als__3fooRT0" => process "RT0"
3269 "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i"
3271 DECLP must be already initialised, usually non-empty. It won't be freed
3274 Note that g++ differs significantly from ARM and lucid style mangling
3275 with regards to references to previously seen types. For example, given
3276 the source fragment:
3280 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
3283 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3284 void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3286 g++ produces the names:
3291 while lcc (and presumably other ARM style compilers as well) produces:
3293 foo__FiR3fooT1T2T1T2
3294 __ct__3fooFiR3fooT1T2T1T2
3296 Note that g++ bases its type numbers starting at zero and counts all
3297 previously seen types, while lucid/ARM bases its type numbers starting
3298 at one and only considers types after it has seen the 'F' character
3299 indicating the start of the function args. For lucid/ARM style, we
3300 account for this difference by discarding any previously seen types when
3301 we see the 'F' character, and subtracting one from the type number
3307 demangle_args (work, mangled, declp)
3308 struct work_stuff *work;
3309 const char **mangled;
3319 if (PRINT_ARG_TYPES)
3321 string_append (declp, "(");
3322 if (**mangled == '\0')
3324 string_append (declp, "void");
3328 while ((**mangled != '_' && **mangled != '\0' && **mangled != 'e')
3329 || work->nrepeats > 0)
3331 if ((**mangled == 'N') || (**mangled == 'T'))
3333 temptype = *(*mangled)++;
3335 if (temptype == 'N')
3337 if (!get_count (mangled, &r))
3346 if (ARM_DEMANGLING && work -> ntypes >= 10)
3348 /* If we have 10 or more types we might have more than a 1 digit
3349 index so we'll have to consume the whole count here. This
3350 will lose if the next thing is a type name preceded by a
3351 count but it's impossible to demangle that case properly
3352 anyway. Eg if we already have 12 types is T12Pc "(..., type1,
3353 Pc, ...)" or "(..., type12, char *, ...)" */
3354 if ((t = consume_count(mangled)) == 0)
3361 if (!get_count (mangled, &t))
3366 if (LUCID_DEMANGLING || ARM_DEMANGLING)
3370 /* Validate the type index. Protect against illegal indices from
3371 malformed type strings. */
3372 if ((t < 0) || (t >= work -> ntypes))
3376 while (work->nrepeats > 0 || --r >= 0)
3378 tem = work -> typevec[t];
3379 if (need_comma && PRINT_ARG_TYPES)
3381 string_append (declp, ", ");
3383 if (!do_arg (work, &tem, &arg))
3387 if (PRINT_ARG_TYPES)
3389 string_appends (declp, &arg);
3391 string_delete (&arg);
3397 if (need_comma && PRINT_ARG_TYPES)
3398 string_append (declp, ", ");
3399 if (!do_arg (work, mangled, &arg))
3401 if (PRINT_ARG_TYPES)
3402 string_appends (declp, &arg);
3403 string_delete (&arg);
3408 if (**mangled == 'e')
3411 if (PRINT_ARG_TYPES)
3415 string_append (declp, ",");
3417 string_append (declp, "...");
3421 if (PRINT_ARG_TYPES)
3423 string_append (declp, ")");
3428 /* Like demangle_args, but for demangling the argument lists of function
3429 and method pointers or references, not top-level declarations. */
3432 demangle_nested_args (work, mangled, declp)
3433 struct work_stuff *work;
3434 const char **mangled;
3437 string* saved_previous_argument;
3441 /* The G++ name-mangling algorithm does not remember types on nested
3442 argument lists, unless -fsquangling is used, and in that case the
3443 type vector updated by remember_type is not used. So, we turn
3444 off remembering of types here. */
3445 ++work->forgetting_types;
3447 /* For the repeat codes used with -fsquangling, we must keep track of
3448 the last argument. */
3449 saved_previous_argument = work->previous_argument;
3450 saved_nrepeats = work->nrepeats;
3451 work->previous_argument = 0;
3454 /* Actually demangle the arguments. */
3455 result = demangle_args (work, mangled, declp);
3457 /* Restore the previous_argument field. */
3458 if (work->previous_argument)
3459 string_delete (work->previous_argument);
3460 work->previous_argument = saved_previous_argument;
3461 work->nrepeats = saved_nrepeats;
3467 demangle_function_name (work, mangled, declp, scan)
3468 struct work_stuff *work;
3469 const char **mangled;
3477 string_appendn (declp, (*mangled), scan - (*mangled));
3478 string_need (declp, 1);
3479 *(declp -> p) = '\0';
3481 /* Consume the function name, including the "__" separating the name
3482 from the signature. We are guaranteed that SCAN points to the
3485 (*mangled) = scan + 2;
3487 if (LUCID_DEMANGLING || ARM_DEMANGLING)
3490 /* See if we have an ARM style constructor or destructor operator.
3491 If so, then just record it, clear the decl, and return.
3492 We can't build the actual constructor/destructor decl until later,
3493 when we recover the class name from the signature. */
3495 if (strcmp (declp -> b, "__ct") == 0)
3497 work -> constructor += 1;
3498 string_clear (declp);
3501 else if (strcmp (declp -> b, "__dt") == 0)
3503 work -> destructor += 1;
3504 string_clear (declp);
3509 if (declp->p - declp->b >= 3
3510 && declp->b[0] == 'o'
3511 && declp->b[1] == 'p'
3512 && strchr (cplus_markers, declp->b[2]) != NULL)
3514 /* see if it's an assignment expression */
3515 if (declp->p - declp->b >= 10 /* op$assign_ */
3516 && memcmp (declp->b + 3, "assign_", 7) == 0)
3518 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
3520 int len = declp->p - declp->b - 10;
3521 if ((int) strlen (optable[i].in) == len
3522 && memcmp (optable[i].in, declp->b + 10, len) == 0)
3524 string_clear (declp);
3525 string_append (declp, "operator");
3526 string_append (declp, optable[i].out);
3527 string_append (declp, "=");
3534 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
3536 int len = declp->p - declp->b - 3;
3537 if ((int) strlen (optable[i].in) == len
3538 && memcmp (optable[i].in, declp->b + 3, len) == 0)
3540 string_clear (declp);
3541 string_append (declp, "operator");
3542 string_append (declp, optable[i].out);
3548 else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0
3549 && strchr (cplus_markers, declp->b[4]) != NULL)
3551 /* type conversion operator */
3553 if (do_type (work, &tem, &type))
3555 string_clear (declp);
3556 string_append (declp, "operator ");
3557 string_appends (declp, &type);
3558 string_delete (&type);
3561 else if (declp->b[0] == '_' && declp->b[1] == '_'
3562 && declp->b[2] == 'o' && declp->b[3] == 'p')
3565 /* type conversion operator. */
3567 if (do_type (work, &tem, &type))
3569 string_clear (declp);
3570 string_append (declp, "operator ");
3571 string_appends (declp, &type);
3572 string_delete (&type);
3575 else if (declp->b[0] == '_' && declp->b[1] == '_'
3576 && declp->b[2] >= 'a' && declp->b[2] <= 'z'
3577 && declp->b[3] >= 'a' && declp->b[3] <= 'z')
3579 if (declp->b[4] == '\0')
3582 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
3584 if (strlen (optable[i].in) == 2
3585 && memcmp (optable[i].in, declp->b + 2, 2) == 0)
3587 string_clear (declp);
3588 string_append (declp, "operator");
3589 string_append (declp, optable[i].out);
3596 if (declp->b[2] == 'a' && declp->b[5] == '\0')
3599 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
3601 if (strlen (optable[i].in) == 3
3602 && memcmp (optable[i].in, declp->b + 2, 3) == 0)
3604 string_clear (declp);
3605 string_append (declp, "operator");
3606 string_append (declp, optable[i].out);
3615 /* a mini string-handling package */
3630 s->p = s->b = xmalloc (n);
3633 else if (s->e - s->p < n)
3638 s->b = xrealloc (s->b, n);
3651 s->b = s->e = s->p = NULL;
3659 s->b = s->p = s->e = NULL;
3675 return (s->b == s->p);
3681 string_append (p, s)
3686 if (s == NULL || *s == '\0')
3690 memcpy (p->p, s, n);
3695 string_appends (p, s)
3704 memcpy (p->p, s->b, n);
3710 string_appendn (p, s, n)
3718 memcpy (p->p, s, n);
3724 string_prepend (p, s)
3728 if (s != NULL && *s != '\0')
3730 string_prependn (p, s, strlen (s));
3735 string_prepends (p, s)
3740 string_prependn (p, s->b, s->p - s->b);
3745 string_prependn (p, s, n)
3755 for (q = p->p - 1; q >= p->b; q--)
3759 memcpy (p->b, s, n);
3764 /* To generate a standalone demangler program for testing purposes,
3765 just compile and link this file with -DMAIN and libiberty.a. When
3766 run, it demangles each command line arg, or each stdin string, and
3767 prints the result on stdout. */
3773 static char *program_name;
3774 static char *program_version = VERSION;
3775 static int flags = DMGL_PARAMS | DMGL_ANSI;
3777 static void demangle_it PARAMS ((char *));
3778 static void usage PARAMS ((FILE *, int));
3779 static void fatal PARAMS ((char *));
3782 demangle_it (mangled_name)
3787 result = cplus_demangle (mangled_name, flags);
3790 printf ("%s\n", mangled_name);
3794 printf ("%s\n", result);
3800 usage (stream, status)
3805 Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
3806 [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\
3807 [--help] [--version] [arg...]\n",
3812 #define MBUF_SIZE 32767
3813 char mbuffer[MBUF_SIZE];
3815 /* Defined in the automatically-generated underscore.c. */
3816 extern int prepends_underscore;
3818 int strip_underscore = 0;
3820 static struct option long_options[] = {
3821 {"strip-underscores", no_argument, 0, '_'},
3822 {"format", required_argument, 0, 's'},
3823 {"help", no_argument, 0, 'h'},
3824 {"no-strip-underscores", no_argument, 0, 'n'},
3825 {"version", no_argument, 0, 'v'},
3826 {0, no_argument, 0, 0}
3829 /* More 'friendly' abort that prints the line and file.
3830 config.h can #define abort fancy_abort if you like that sort of thing. */
3835 fatal ("Internal gcc abort.");
3846 program_name = argv[0];
3848 strip_underscore = prepends_underscore;
3850 while ((c = getopt_long (argc, argv, "_ns:j", long_options, (int *) 0)) != EOF)
3860 strip_underscore = 0;
3863 printf ("GNU %s version %s\n", program_name, program_version);
3866 strip_underscore = 1;
3869 if (strcmp (optarg, "gnu") == 0)
3871 current_demangling_style = gnu_demangling;
3873 else if (strcmp (optarg, "lucid") == 0)
3875 current_demangling_style = lucid_demangling;
3877 else if (strcmp (optarg, "arm") == 0)
3879 current_demangling_style = arm_demangling;
3883 fprintf (stderr, "%s: unknown demangling style `%s'\n",
3884 program_name, optarg);
3893 for ( ; optind < argc; optind++)
3895 demangle_it (argv[optind]);
3904 /* Try to read a label. */
3905 while (c != EOF && (isalnum(c) || c == '_' || c == '$' || c == '.'))
3907 if (i >= MBUF_SIZE-1)
3916 if (mbuffer[0] == '.')
3918 if (strip_underscore && mbuffer[skip_first] == '_')
3926 result = cplus_demangle (mbuffer + skip_first, flags);
3929 if (mbuffer[0] == '.')
3931 fputs (result, stdout);
3935 fputs (mbuffer, stdout);
3952 fprintf (stderr, "%s: %s\n", program_name, str);
3960 register char *value = (char *) malloc (size);
3962 fatal ("virtual memory exhausted");
3967 xrealloc (ptr, size)
3971 register char *value = (char *) realloc (ptr, size);
3973 fatal ("virtual memory exhausted");