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
244 #define STRING_EMPTY(str) ((str) -> b == (str) -> p)
245 #define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
246 string_prepend(str, " ");}
247 #define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
248 string_append(str, " ");}
249 #define LEN_STRING(str) ( (STRING_EMPTY(str))?0:((str)->p - (str)->b))
251 /* The scope separator appropriate for the language being demangled. */
252 #define SCOPE_STRING(work) "::"
254 #define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */
255 #define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */
257 /* Prototypes for local functions */
260 mop_up PARAMS ((struct work_stuff *, string *, int));
263 squangle_mop_up PARAMS ((struct work_stuff *));
267 demangle_method_args PARAMS ((struct work_stuff *, const char **, string *));
271 internal_cplus_demangle PARAMS ((struct work_stuff *, const char *));
274 demangle_template_template_parm PARAMS ((struct work_stuff *work,
275 const char **, string *));
278 demangle_template PARAMS ((struct work_stuff *work, const char **, string *,
279 string *, int, int));
282 arm_pt PARAMS ((struct work_stuff *, const char *, int, const char **,
286 demangle_arm_pt PARAMS ((struct work_stuff *, const char **, int, string *));
289 demangle_class_name PARAMS ((struct work_stuff *, const char **, string *));
292 demangle_qualified PARAMS ((struct work_stuff *, const char **, string *,
296 demangle_class PARAMS ((struct work_stuff *, const char **, string *));
299 demangle_fund_type PARAMS ((struct work_stuff *, const char **, string *));
302 demangle_signature PARAMS ((struct work_stuff *, const char **, string *));
305 demangle_prefix PARAMS ((struct work_stuff *, const char **, string *));
308 gnu_special PARAMS ((struct work_stuff *, const char **, string *));
311 arm_special PARAMS ((const char **, string *));
314 string_need PARAMS ((string *, int));
317 string_delete PARAMS ((string *));
320 string_init PARAMS ((string *));
323 string_clear PARAMS ((string *));
327 string_empty PARAMS ((string *));
331 string_append PARAMS ((string *, const char *));
334 string_appends PARAMS ((string *, string *));
337 string_appendn PARAMS ((string *, const char *, int));
340 string_prepend PARAMS ((string *, const char *));
343 string_prependn PARAMS ((string *, const char *, int));
346 get_count PARAMS ((const char **, int *));
349 consume_count PARAMS ((const char **));
352 consume_count_with_underscores PARAMS ((const char**));
355 demangle_args PARAMS ((struct work_stuff *, const char **, string *));
358 demangle_nested_args PARAMS ((struct work_stuff*, const char**, string*));
361 do_type PARAMS ((struct work_stuff *, const char **, string *));
364 do_arg PARAMS ((struct work_stuff *, const char **, string *));
367 demangle_function_name PARAMS ((struct work_stuff *, const char **, string *,
371 remember_type PARAMS ((struct work_stuff *, const char *, int));
374 remember_Btype PARAMS ((struct work_stuff *, const char *, int, int));
377 register_Btype PARAMS ((struct work_stuff *));
380 remember_Ktype PARAMS ((struct work_stuff *, const char *, int));
383 forget_types PARAMS ((struct work_stuff *));
386 forget_B_and_K_types PARAMS ((struct work_stuff *));
389 string_prepends PARAMS ((string *, string *));
392 demangle_template_value_parm PARAMS ((struct work_stuff*, const char**,
393 string*, type_kind_t));
395 /* There is a TYPE_QUAL value for each type qualifier. They can be
396 combined by bitwise-or to form the complete set of qualifiers for a
399 #define TYPE_UNQUALIFIED 0x0
400 #define TYPE_QUAL_CONST 0x1
401 #define TYPE_QUAL_VOLATILE 0x2
402 #define TYPE_QUAL_RESTRICT 0x4
405 code_for_qualifier PARAMS ((char));
408 qualifier_string PARAMS ((int));
411 demangle_qualifier PARAMS ((char));
413 /* Translate count to integer, consuming tokens in the process.
414 Conversion terminates on the first non-digit character.
415 Trying to consume something that isn't a count results in
416 no consumption of input and a return of 0. */
424 while (isdigit ((unsigned char)**type))
427 count += **type - '0';
434 /* Like consume_count, but for counts that are preceded and followed
435 by '_' if they are greater than 10. Also, -1 is returned for
436 failure, since 0 can be a valid value. */
439 consume_count_with_underscores (mangled)
440 const char **mangled;
444 if (**mangled == '_')
447 if (!isdigit ((unsigned char)**mangled))
450 idx = consume_count (mangled);
451 if (**mangled != '_')
452 /* The trailing underscore was missing. */
459 if (**mangled < '0' || **mangled > '9')
462 idx = **mangled - '0';
469 /* C is the code for a type-qualifier. Return the TYPE_QUAL
470 corresponding to this qualifier. */
473 code_for_qualifier (c)
479 return TYPE_QUAL_CONST;
482 return TYPE_QUAL_VOLATILE;
485 return TYPE_QUAL_RESTRICT;
491 /* C was an invalid qualifier. */
495 /* Return the string corresponding to the qualifiers given by
499 qualifier_string (type_quals)
504 case TYPE_UNQUALIFIED:
507 case TYPE_QUAL_CONST:
510 case TYPE_QUAL_VOLATILE:
513 case TYPE_QUAL_RESTRICT:
516 case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE:
517 return "const volatile";
519 case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT:
520 return "const __restrict";
522 case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
523 return "volatile __restrict";
525 case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
526 return "const volatile __restrict";
532 /* TYPE_QUALS was an invalid qualifier set. */
536 /* C is the code for a type-qualifier. Return the string
537 corresponding to this qualifier. This function should only be
538 called with a valid qualifier code. */
541 demangle_qualifier (c)
544 return qualifier_string (code_for_qualifier (c));
548 cplus_demangle_opname (opname, result, options)
555 struct work_stuff work[1];
558 len = strlen(opname);
561 memset ((char *) work, 0, sizeof (work));
562 work->options = options;
564 if (opname[0] == '_' && opname[1] == '_'
565 && opname[2] == 'o' && opname[3] == 'p')
568 /* type conversion operator. */
570 if (do_type (work, &tem, &type))
572 strcat (result, "operator ");
573 strncat (result, type.b, type.p - type.b);
574 string_delete (&type);
578 else if (opname[0] == '_' && opname[1] == '_'
579 && opname[2] >= 'a' && opname[2] <= 'z'
580 && opname[3] >= 'a' && opname[3] <= 'z')
582 if (opname[4] == '\0')
586 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
588 if (strlen (optable[i].in) == 2
589 && memcmp (optable[i].in, opname + 2, 2) == 0)
591 strcat (result, "operator");
592 strcat (result, optable[i].out);
600 if (opname[2] == 'a' && opname[5] == '\0')
604 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
606 if (strlen (optable[i].in) == 3
607 && memcmp (optable[i].in, opname + 2, 3) == 0)
609 strcat (result, "operator");
610 strcat (result, optable[i].out);
621 && strchr (cplus_markers, opname[2]) != NULL)
623 /* see if it's an assignment expression */
624 if (len >= 10 /* op$assign_ */
625 && memcmp (opname + 3, "assign_", 7) == 0)
628 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
631 if ((int) strlen (optable[i].in) == len1
632 && memcmp (optable[i].in, opname + 10, len1) == 0)
634 strcat (result, "operator");
635 strcat (result, optable[i].out);
636 strcat (result, "=");
645 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
648 if ((int) strlen (optable[i].in) == len1
649 && memcmp (optable[i].in, opname + 3, len1) == 0)
651 strcat (result, "operator");
652 strcat (result, optable[i].out);
659 else if (len >= 5 && memcmp (opname, "type", 4) == 0
660 && strchr (cplus_markers, opname[4]) != NULL)
662 /* type conversion operator */
664 if (do_type (work, &tem, &type))
666 strcat (result, "operator ");
667 strncat (result, type.b, type.p - type.b);
668 string_delete (&type);
672 squangle_mop_up (work);
676 /* Takes operator name as e.g. "++" and returns mangled
677 operator name (e.g. "postincrement_expr"), or NULL if not found.
679 If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
680 if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */
683 cplus_mangle_opname (opname, options)
690 len = strlen (opname);
691 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
693 if ((int) strlen (optable[i].out) == len
694 && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
695 && memcmp (optable[i].out, opname, len) == 0)
696 return optable[i].in;
701 /* char *cplus_demangle (const char *mangled, int options)
703 If MANGLED is a mangled function name produced by GNU C++, then
704 a pointer to a malloced string giving a C++ representation
705 of the name will be returned; otherwise NULL will be returned.
706 It is the caller's responsibility to free the string which
709 The OPTIONS arg may contain one or more of the following bits:
711 DMGL_ANSI ANSI qualifiers such as `const' and `void' are
713 DMGL_PARAMS Function parameters are included.
717 cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)"
718 cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
719 cplus_demangle ("foo__1Ai", 0) => "A::foo"
721 cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)"
722 cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
723 cplus_demangle ("foo__1Afe", 0) => "A::foo"
725 Note that any leading underscores, or other such characters prepended by
726 the compilation system, are presumed to have already been stripped from
730 cplus_demangle (mangled, options)
735 struct work_stuff work[1];
736 memset ((char *) work, 0, sizeof (work));
737 work -> options = options;
738 if ((work -> options & DMGL_STYLE_MASK) == 0)
739 work -> options |= (int) current_demangling_style & DMGL_STYLE_MASK;
741 ret = internal_cplus_demangle (work, mangled);
742 squangle_mop_up (work);
747 /* This function performs most of what cplus_demangle use to do, but
748 to be able to demangle a name with a B, K or n code, we need to
749 have a longer term memory of what types have been seen. The original
750 now intializes and cleans up the squangle code info, while internal
751 calls go directly to this routine to avoid resetting that info. */
754 internal_cplus_demangle (work, mangled)
755 struct work_stuff *work;
761 char *demangled = NULL;
763 s1 = work->constructor;
764 s2 = work->destructor;
765 s3 = work->static_type;
766 s4 = work->type_quals;
767 work->constructor = work->destructor = 0;
768 work->type_quals = TYPE_UNQUALIFIED;
769 work->dllimported = 0;
771 if ((mangled != NULL) && (*mangled != '\0'))
775 /* First check to see if gnu style demangling is active and if the
776 string to be demangled contains a CPLUS_MARKER. If so, attempt to
777 recognize one of the gnu special forms rather than looking for a
778 standard prefix. In particular, don't worry about whether there
779 is a "__" string in the mangled string. Consider "_$_5__foo" for
782 if ((AUTO_DEMANGLING || GNU_DEMANGLING))
784 success = gnu_special (work, &mangled, &decl);
788 success = demangle_prefix (work, &mangled, &decl);
790 if (success && (*mangled != '\0'))
792 success = demangle_signature (work, &mangled, &decl);
794 if (work->constructor == 2)
796 string_prepend (&decl, "global constructors keyed to ");
797 work->constructor = 0;
799 else if (work->destructor == 2)
801 string_prepend (&decl, "global destructors keyed to ");
802 work->destructor = 0;
804 else if (work->dllimported == 1)
806 string_prepend (&decl, "import stub for ");
807 work->dllimported = 0;
809 demangled = mop_up (work, &decl, success);
811 work->constructor = s1;
812 work->destructor = s2;
813 work->static_type = s3;
814 work->type_quals = s4;
819 /* Clear out and squangling related storage */
821 squangle_mop_up (work)
822 struct work_stuff *work;
824 /* clean up the B and K type mangling types. */
825 forget_B_and_K_types (work);
826 if (work -> btypevec != NULL)
828 free ((char *) work -> btypevec);
830 if (work -> ktypevec != NULL)
832 free ((char *) work -> ktypevec);
836 /* Clear out any mangled storage */
839 mop_up (work, declp, success)
840 struct work_stuff *work;
844 char *demangled = NULL;
846 /* Discard the remembered types, if any. */
849 if (work -> typevec != NULL)
851 free ((char *) work -> typevec);
852 work -> typevec = NULL;
854 if (work->tmpl_argvec)
858 for (i = 0; i < work->ntmpl_args; i++)
859 if (work->tmpl_argvec[i])
860 free ((char*) work->tmpl_argvec[i]);
862 free ((char*) work->tmpl_argvec);
863 work->tmpl_argvec = NULL;
865 if (work->previous_argument)
867 string_delete (work->previous_argument);
868 free ((char*) work->previous_argument);
871 /* If demangling was successful, ensure that the demangled string is null
872 terminated and return it. Otherwise, free the demangling decl. */
876 string_delete (declp);
880 string_appendn (declp, "", 1);
881 demangled = declp -> b;
890 demangle_signature -- demangle the signature part of a mangled name
895 demangle_signature (struct work_stuff *work, const char **mangled,
900 Consume and demangle the signature portion of the mangled name.
902 DECLP is the string where demangled output is being built. At
903 entry it contains the demangled root name from the mangled name
904 prefix. I.E. either a demangled operator name or the root function
905 name. In some special cases, it may contain nothing.
907 *MANGLED points to the current unconsumed location in the mangled
908 name. As tokens are consumed and demangling is performed, the
909 pointer is updated to continuously point at the next token to
912 Demangling GNU style mangled names is nasty because there is no
913 explicit token that marks the start of the outermost function
917 demangle_signature (work, mangled, declp)
918 struct work_stuff *work;
919 const char **mangled;
925 int expect_return_type = 0;
926 const char *oldmangled = NULL;
930 while (success && (**mangled != '\0'))
935 oldmangled = *mangled;
936 success = demangle_qualified (work, mangled, declp, 1, 0);
938 remember_type (work, oldmangled, *mangled - oldmangled);
939 if (AUTO_DEMANGLING || GNU_DEMANGLING)
945 oldmangled = *mangled;
946 success = demangle_qualified (work, mangled, declp, 1, 0);
947 if (AUTO_DEMANGLING || GNU_DEMANGLING)
955 /* Static member function */
956 if (oldmangled == NULL)
958 oldmangled = *mangled;
961 work -> static_type = 1;
967 work->type_quals |= code_for_qualifier (**mangled);
969 /* a qualified member function */
970 if (oldmangled == NULL)
971 oldmangled = *mangled;
975 case '0': case '1': case '2': case '3': case '4':
976 case '5': case '6': case '7': case '8': case '9':
977 if (oldmangled == NULL)
979 oldmangled = *mangled;
981 success = demangle_class (work, mangled, declp);
984 remember_type (work, oldmangled, *mangled - oldmangled);
986 if (AUTO_DEMANGLING || GNU_DEMANGLING)
996 success = do_type (work, mangled, &s);
999 string_append (&s, SCOPE_STRING (work));
1000 string_prepends (declp, &s);
1009 /* ARM style demangling includes a specific 'F' character after
1010 the class name. For GNU style, it is just implied. So we can
1011 safely just consume any 'F' at this point and be compatible
1012 with either style. */
1018 /* For lucid/ARM style we have to forget any types we might
1019 have remembered up to this point, since they were not argument
1020 types. GNU style considers all types seen as available for
1021 back references. See comment in demangle_args() */
1023 if (LUCID_DEMANGLING || ARM_DEMANGLING)
1025 forget_types (work);
1027 success = demangle_args (work, mangled, declp);
1032 string_init(&trawname);
1033 string_init(&tname);
1034 if (oldmangled == NULL)
1036 oldmangled = *mangled;
1038 success = demangle_template (work, mangled, &tname,
1042 remember_type (work, oldmangled, *mangled - oldmangled);
1044 string_append (&tname, SCOPE_STRING (work));
1046 string_prepends(declp, &tname);
1047 if (work -> destructor & 1)
1049 string_prepend (&trawname, "~");
1050 string_appends (declp, &trawname);
1051 work->destructor -= 1;
1053 if ((work->constructor & 1) || (work->destructor & 1))
1055 string_appends (declp, &trawname);
1056 work->constructor -= 1;
1058 string_delete(&trawname);
1059 string_delete(&tname);
1065 if (GNU_DEMANGLING && expect_return_type)
1067 /* Read the return type. */
1069 string_init (&return_type);
1072 success = do_type (work, mangled, &return_type);
1073 APPEND_BLANK (&return_type);
1075 string_prepends (declp, &return_type);
1076 string_delete (&return_type);
1080 /* At the outermost level, we cannot have a return type specified,
1081 so if we run into another '_' at this point we are dealing with
1082 a mangled name that is either bogus, or has been mangled by
1083 some algorithm we don't know how to deal with. So just
1084 reject the entire demangling. */
1091 /* A G++ template function. Read the template arguments. */
1092 success = demangle_template (work, mangled, declp, 0, 0,
1094 if (!(work->constructor & 1))
1095 expect_return_type = 1;
1104 if (AUTO_DEMANGLING || GNU_DEMANGLING)
1106 /* Assume we have stumbled onto the first outermost function
1107 argument token, and start processing args. */
1109 success = demangle_args (work, mangled, declp);
1113 /* Non-GNU demanglers use a specific token to mark the start
1114 of the outermost function argument tokens. Typically 'F',
1115 for ARM-demangling, for example. So if we find something
1116 we are not prepared for, it must be an error. */
1122 if (AUTO_DEMANGLING || GNU_DEMANGLING)
1125 if (success && expect_func)
1128 success = demangle_args (work, mangled, declp);
1129 /* Since template include the mangling of their return types,
1130 we must set expect_func to 0 so that we don't try do
1131 demangle more arguments the next time we get here. */
1136 if (success && !func_done)
1138 if (AUTO_DEMANGLING || GNU_DEMANGLING)
1140 /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
1141 bar__3fooi is 'foo::bar(int)'. We get here when we find the
1142 first case, and need to ensure that the '(void)' gets added to
1143 the current declp. Note that with ARM, the first case
1144 represents the name of a static data member 'foo::bar',
1145 which is in the current declp, so we leave it alone. */
1146 success = demangle_args (work, mangled, declp);
1149 if (success && PRINT_ARG_TYPES)
1151 if (work->static_type)
1152 string_append (declp, " static");
1153 if (work->type_quals != TYPE_UNQUALIFIED)
1155 APPEND_BLANK (declp);
1156 string_append (declp, qualifier_string (work->type_quals));
1166 demangle_method_args (work, mangled, declp)
1167 struct work_stuff *work;
1168 const char **mangled;
1173 if (work -> static_type)
1175 string_append (declp, *mangled + 1);
1176 *mangled += strlen (*mangled);
1181 success = demangle_args (work, mangled, declp);
1189 demangle_template_template_parm (work, mangled, tname)
1190 struct work_stuff *work;
1191 const char **mangled;
1200 string_append (tname, "template <");
1201 /* get size of template parameter list */
1202 if (get_count (mangled, &r))
1204 for (i = 0; i < r; i++)
1208 string_append (tname, ", ");
1211 /* Z for type parameters */
1212 if (**mangled == 'Z')
1215 string_append (tname, "class");
1217 /* z for template parameters */
1218 else if (**mangled == 'z')
1222 demangle_template_template_parm (work, mangled, tname);
1230 /* temp is initialized in do_type */
1231 success = do_type (work, mangled, &temp);
1234 string_appends (tname, &temp);
1236 string_delete(&temp);
1246 if (tname->p[-1] == '>')
1247 string_append (tname, " ");
1248 string_append (tname, "> class");
1253 demangle_integral_value (work, mangled, s)
1254 struct work_stuff *work;
1255 const char** mangled;
1260 if (**mangled == 'E')
1262 int need_operator = 0;
1265 string_appendn (s, "(", 1);
1267 while (success && **mangled != 'W' && **mangled != '\0')
1276 len = strlen (*mangled);
1279 i < sizeof (optable) / sizeof (optable [0]);
1282 size_t l = strlen (optable[i].in);
1285 && memcmp (optable[i].in, *mangled, l) == 0)
1287 string_appendn (s, " ", 1);
1288 string_append (s, optable[i].out);
1289 string_appendn (s, " ", 1);
1302 success = demangle_template_value_parm (work, mangled, s,
1306 if (**mangled != 'W')
1310 string_appendn (s, ")", 1);
1314 else if (**mangled == 'Q' || **mangled == 'K')
1315 success = demangle_qualified (work, mangled, s, 0, 1);
1320 if (**mangled == 'm')
1322 string_appendn (s, "-", 1);
1325 while (isdigit ((unsigned char)**mangled))
1327 string_appendn (s, *mangled, 1);
1337 demangle_template_value_parm (work, mangled, s, tk)
1338 struct work_stuff *work;
1339 const char **mangled;
1345 if (**mangled == 'Y')
1347 /* The next argument is a template parameter. */
1351 idx = consume_count_with_underscores (mangled);
1353 || (work->tmpl_argvec && idx >= work->ntmpl_args)
1354 || consume_count_with_underscores (mangled) == -1)
1356 if (work->tmpl_argvec)
1357 string_append (s, work->tmpl_argvec[idx]);
1361 sprintf(buf, "T%d", idx);
1362 string_append (s, buf);
1365 else if (tk == tk_integral)
1366 success = demangle_integral_value (work, mangled, s);
1367 else if (tk == tk_char)
1371 if (**mangled == 'm')
1373 string_appendn (s, "-", 1);
1376 string_appendn (s, "'", 1);
1377 val = consume_count(mangled);
1382 string_appendn (s, &tmp[0], 1);
1383 string_appendn (s, "'", 1);
1385 else if (tk == tk_bool)
1387 int val = consume_count (mangled);
1389 string_appendn (s, "false", 5);
1391 string_appendn (s, "true", 4);
1395 else if (tk == tk_real)
1397 if (**mangled == 'm')
1399 string_appendn (s, "-", 1);
1402 while (isdigit ((unsigned char)**mangled))
1404 string_appendn (s, *mangled, 1);
1407 if (**mangled == '.') /* fraction */
1409 string_appendn (s, ".", 1);
1411 while (isdigit ((unsigned char)**mangled))
1413 string_appendn (s, *mangled, 1);
1417 if (**mangled == 'e') /* exponent */
1419 string_appendn (s, "e", 1);
1421 while (isdigit ((unsigned char)**mangled))
1423 string_appendn (s, *mangled, 1);
1428 else if (tk == tk_pointer || tk == tk_reference)
1430 int symbol_len = consume_count (mangled);
1431 if (symbol_len == 0)
1433 if (symbol_len == 0)
1434 string_appendn (s, "0", 1);
1437 char *p = xmalloc (symbol_len + 1), *q;
1438 strncpy (p, *mangled, symbol_len);
1439 p [symbol_len] = '\0';
1440 /* We use cplus_demangle here, rather than
1441 internal_cplus_demangle, because the name of the entity
1442 mangled here does not make use of any of the squangling
1443 or type-code information we have built up thus far; it is
1444 mangled independently. */
1445 q = cplus_demangle (p, work->options);
1446 if (tk == tk_pointer)
1447 string_appendn (s, "&", 1);
1448 /* FIXME: Pointer-to-member constants should get a
1449 qualifying class name here. */
1452 string_append (s, q);
1456 string_append (s, p);
1459 *mangled += symbol_len;
1465 /* Demangle the template name in MANGLED. The full name of the
1466 template (e.g., S<int>) is placed in TNAME. The name without the
1467 template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is
1468 non-NULL. If IS_TYPE is nonzero, this template is a type template,
1469 not a function template. If both IS_TYPE and REMEMBER are nonzero,
1470 the tmeplate is remembered in the list of back-referenceable
1474 demangle_template (work, mangled, tname, trawname, is_type, remember)
1475 struct work_stuff *work;
1476 const char **mangled;
1494 bindex = register_Btype (work);
1496 /* get template name */
1497 if (**mangled == 'z')
1503 idx = consume_count_with_underscores (mangled);
1505 || (work->tmpl_argvec && idx >= work->ntmpl_args)
1506 || consume_count_with_underscores (mangled) == -1)
1509 if (work->tmpl_argvec)
1511 string_append (tname, work->tmpl_argvec[idx]);
1513 string_append (trawname, work->tmpl_argvec[idx]);
1518 sprintf(buf, "T%d", idx);
1519 string_append (tname, buf);
1521 string_append (trawname, buf);
1526 if ((r = consume_count (mangled)) == 0
1527 || (int) strlen (*mangled) < r)
1531 string_appendn (tname, *mangled, r);
1533 string_appendn (trawname, *mangled, r);
1537 string_append (tname, "<");
1538 /* get size of template parameter list */
1539 if (!get_count (mangled, &r))
1545 /* Create an array for saving the template argument values. */
1546 work->tmpl_argvec = (char**) xmalloc (r * sizeof (char *));
1547 work->ntmpl_args = r;
1548 for (i = 0; i < r; i++)
1549 work->tmpl_argvec[i] = 0;
1551 for (i = 0; i < r; i++)
1555 string_append (tname, ", ");
1557 /* Z for type parameters */
1558 if (**mangled == 'Z')
1561 /* temp is initialized in do_type */
1562 success = do_type (work, mangled, &temp);
1565 string_appends (tname, &temp);
1569 /* Save the template argument. */
1570 int len = temp.p - temp.b;
1571 work->tmpl_argvec[i] = xmalloc (len + 1);
1572 memcpy (work->tmpl_argvec[i], temp.b, len);
1573 work->tmpl_argvec[i][len] = '\0';
1576 string_delete(&temp);
1582 /* z for template parameters */
1583 else if (**mangled == 'z')
1587 success = demangle_template_template_parm (work, mangled, tname);
1590 && (r2 = consume_count (mangled)) > 0
1591 && (int) strlen (*mangled) >= r2)
1593 string_append (tname, " ");
1594 string_appendn (tname, *mangled, r2);
1597 /* Save the template argument. */
1599 work->tmpl_argvec[i] = xmalloc (len + 1);
1600 memcpy (work->tmpl_argvec[i], *mangled, len);
1601 work->tmpl_argvec[i][len] = '\0';
1615 /* otherwise, value parameter */
1617 /* temp is initialized in do_type */
1618 success = do_type (work, mangled, &temp);
1619 string_delete(&temp);
1631 success = demangle_template_value_parm (work, mangled, s,
1632 (type_kind_t) success);
1644 int len = s->p - s->b;
1645 work->tmpl_argvec[i] = xmalloc (len + 1);
1646 memcpy (work->tmpl_argvec[i], s->b, len);
1647 work->tmpl_argvec[i][len] = '\0';
1649 string_appends (tname, s);
1656 if (tname->p[-1] == '>')
1657 string_append (tname, " ");
1658 string_append (tname, ">");
1661 if (is_type && remember)
1662 remember_Btype (work, tname->b, LEN_STRING (tname), bindex);
1665 if (work -> static_type)
1667 string_append (declp, *mangled + 1);
1668 *mangled += strlen (*mangled);
1673 success = demangle_args (work, mangled, declp);
1681 arm_pt (work, mangled, n, anchor, args)
1682 struct work_stuff *work;
1683 const char *mangled;
1685 const char **anchor, **args;
1688 if (ARM_DEMANGLING && (*anchor = mystrstr (mangled, "__pt__")))
1691 *args = *anchor + 6;
1692 len = consume_count (args);
1693 if (*args + len == mangled + n && **args == '_')
1703 demangle_arm_pt (work, mangled, n, declp)
1704 struct work_stuff *work;
1705 const char **mangled;
1711 const char *e = *mangled + n;
1714 if (arm_pt (work, *mangled, n, &p, &args))
1718 string_appendn (declp, *mangled, p - *mangled);
1719 string_append (declp, "<");
1720 /* should do error checking here */
1722 string_clear (&arg);
1723 do_type (work, &args, &arg);
1724 string_appends (declp, &arg);
1725 string_append (declp, ",");
1727 string_delete (&arg);
1729 string_append (declp, ">");
1731 else if (n>10 && strncmp (*mangled, "_GLOBAL_", 8) == 0
1732 && (*mangled)[9] == 'N'
1733 && (*mangled)[8] == (*mangled)[10]
1734 && strchr (cplus_markers, (*mangled)[8]))
1736 /* A member of the anonymous namespace. */
1737 string_append (declp, "{anonymous}");
1741 string_appendn (declp, *mangled, n);
1747 demangle_class_name (work, mangled, declp)
1748 struct work_stuff *work;
1749 const char **mangled;
1755 n = consume_count (mangled);
1756 if ((int) strlen (*mangled) >= n)
1758 demangle_arm_pt (work, mangled, n, declp);
1769 demangle_class -- demangle a mangled class sequence
1774 demangle_class (struct work_stuff *work, const char **mangled,
1779 DECLP points to the buffer into which demangling is being done.
1781 *MANGLED points to the current token to be demangled. On input,
1782 it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
1783 On exit, it points to the next token after the mangled class on
1784 success, or the first unconsumed token on failure.
1786 If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
1787 we are demangling a constructor or destructor. In this case
1788 we prepend "class::class" or "class::~class" to DECLP.
1790 Otherwise, we prepend "class::" to the current DECLP.
1792 Reset the constructor/destructor flags once they have been
1793 "consumed". This allows demangle_class to be called later during
1794 the same demangling, to do normal class demangling.
1796 Returns 1 if demangling is successful, 0 otherwise.
1801 demangle_class (work, mangled, declp)
1802 struct work_stuff *work;
1803 const char **mangled;
1810 string_init (&class_name);
1811 btype = register_Btype (work);
1812 if (demangle_class_name (work, mangled, &class_name))
1814 if ((work->constructor & 1) || (work->destructor & 1))
1816 string_prepends (declp, &class_name);
1817 if (work -> destructor & 1)
1819 string_prepend (declp, "~");
1820 work -> destructor -= 1;
1824 work -> constructor -= 1;
1827 remember_Ktype (work, class_name.b, LEN_STRING(&class_name));
1828 remember_Btype (work, class_name.b, LEN_STRING(&class_name), btype);
1829 string_prepend (declp, SCOPE_STRING (work));
1830 string_prepends (declp, &class_name);
1833 string_delete (&class_name);
1841 demangle_prefix -- consume the mangled name prefix and find signature
1846 demangle_prefix (struct work_stuff *work, const char **mangled,
1851 Consume and demangle the prefix of the mangled name.
1853 DECLP points to the string buffer into which demangled output is
1854 placed. On entry, the buffer is empty. On exit it contains
1855 the root function name, the demangled operator name, or in some
1856 special cases either nothing or the completely demangled result.
1858 MANGLED points to the current pointer into the mangled name. As each
1859 token of the mangled name is consumed, it is updated. Upon entry
1860 the current mangled name pointer points to the first character of
1861 the mangled name. Upon exit, it should point to the first character
1862 of the signature if demangling was successful, or to the first
1863 unconsumed character if demangling of the prefix was unsuccessful.
1865 Returns 1 on success, 0 otherwise.
1869 demangle_prefix (work, mangled, declp)
1870 struct work_stuff *work;
1871 const char **mangled;
1878 if (strlen(*mangled) > 6
1879 && (strncmp(*mangled, "_imp__", 6) == 0
1880 || strncmp(*mangled, "__imp_", 6) == 0))
1882 /* it's a symbol imported from a PE dynamic library. Check for both
1883 new style prefix _imp__ and legacy __imp_ used by older versions
1886 work->dllimported = 1;
1888 else if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0)
1890 char *marker = strchr (cplus_markers, (*mangled)[8]);
1891 if (marker != NULL && *marker == (*mangled)[10])
1893 if ((*mangled)[9] == 'D')
1895 /* it's a GNU global destructor to be executed at program exit */
1897 work->destructor = 2;
1898 if (gnu_special (work, mangled, declp))
1901 else if ((*mangled)[9] == 'I')
1903 /* it's a GNU global constructor to be executed at program init */
1905 work->constructor = 2;
1906 if (gnu_special (work, mangled, declp))
1911 else if (ARM_DEMANGLING && strncmp(*mangled, "__std__", 7) == 0)
1913 /* it's a ARM global destructor to be executed at program exit */
1915 work->destructor = 2;
1917 else if (ARM_DEMANGLING && strncmp(*mangled, "__sti__", 7) == 0)
1919 /* it's a ARM global constructor to be executed at program initial */
1921 work->constructor = 2;
1924 /* This block of code is a reduction in strength time optimization
1926 scan = mystrstr (*mangled, "__"); */
1932 scan = strchr (scan, '_');
1933 } while (scan != NULL && *++scan != '_');
1935 if (scan != NULL) --scan;
1940 /* We found a sequence of two or more '_', ensure that we start at
1941 the last pair in the sequence. */
1942 i = strspn (scan, "_");
1953 else if (work -> static_type)
1955 if (!isdigit ((unsigned char)scan[0]) && (scan[0] != 't'))
1960 else if ((scan == *mangled)
1961 && (isdigit ((unsigned char)scan[2]) || (scan[2] == 'Q')
1962 || (scan[2] == 't') || (scan[2] == 'K') || (scan[2] == 'H')))
1964 /* The ARM says nothing about the mangling of local variables.
1965 But cfront mangles local variables by prepending __<nesting_level>
1966 to them. As an extension to ARM demangling we handle this case. */
1967 if ((LUCID_DEMANGLING || ARM_DEMANGLING)
1968 && isdigit ((unsigned char)scan[2]))
1970 *mangled = scan + 2;
1971 consume_count (mangled);
1972 string_append (declp, *mangled);
1973 *mangled += strlen (*mangled);
1978 /* A GNU style constructor starts with __[0-9Qt]. But cfront uses
1979 names like __Q2_3foo3bar for nested type names. So don't accept
1980 this style of constructor for cfront demangling. A GNU
1981 style member-template constructor starts with 'H'. */
1982 if (!(LUCID_DEMANGLING || ARM_DEMANGLING))
1983 work -> constructor += 1;
1984 *mangled = scan + 2;
1987 else if ((scan == *mangled) && !isdigit ((unsigned char)scan[2])
1988 && (scan[2] != 't'))
1990 /* Mangled name starts with "__". Skip over any leading '_' characters,
1991 then find the next "__" that separates the prefix from the signature.
1993 if (!(ARM_DEMANGLING || LUCID_DEMANGLING)
1994 || (arm_special (mangled, declp) == 0))
1996 while (*scan == '_')
2000 if ((scan = mystrstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
2002 /* No separator (I.E. "__not_mangled"), or empty signature
2003 (I.E. "__not_mangled_either__") */
2009 /* Look for the LAST occurrence of __, allowing names to have
2010 the '__' sequence embedded in them.*/
2011 while ((tmp = mystrstr (scan+2, "__")) != NULL)
2013 if (*(scan + 2) == '\0')
2016 demangle_function_name (work, mangled, declp, scan);
2020 else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't')
2022 /* Cfront-style parameterized type. Handled later as a signature. */
2026 demangle_arm_pt (work, mangled, strlen (*mangled), declp);
2028 else if (*(scan + 2) != '\0')
2030 /* Mangled name does not start with "__" but does have one somewhere
2031 in there with non empty stuff after it. Looks like a global
2033 demangle_function_name (work, mangled, declp, scan);
2037 /* Doesn't look like a mangled name */
2041 if (!success && (work->constructor == 2 || work->destructor == 2))
2043 string_append (declp, *mangled);
2044 *mangled += strlen (*mangled);
2054 gnu_special -- special handling of gnu mangled strings
2059 gnu_special (struct work_stuff *work, const char **mangled,
2065 Process some special GNU style mangling forms that don't fit
2066 the normal pattern. For example:
2068 _$_3foo (destructor for class foo)
2069 _vt$foo (foo virtual table)
2070 _vt$foo$bar (foo::bar virtual table)
2071 __vt_foo (foo virtual table, new style with thunks)
2072 _3foo$varname (static data member)
2073 _Q22rs2tu$vw (static data member)
2074 __t6vector1Zii (constructor with template)
2075 __thunk_4__$_7ostream (virtual function thunk)
2079 gnu_special (work, mangled, declp)
2080 struct work_stuff *work;
2081 const char **mangled;
2088 if ((*mangled)[0] == '_'
2089 && strchr (cplus_markers, (*mangled)[1]) != NULL
2090 && (*mangled)[2] == '_')
2092 /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
2094 work -> destructor += 1;
2096 else if ((*mangled)[0] == '_'
2097 && (((*mangled)[1] == '_'
2098 && (*mangled)[2] == 'v'
2099 && (*mangled)[3] == 't'
2100 && (*mangled)[4] == '_')
2101 || ((*mangled)[1] == 'v'
2102 && (*mangled)[2] == 't'
2103 && strchr (cplus_markers, (*mangled)[3]) != NULL)))
2105 /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
2106 and create the decl. Note that we consume the entire mangled
2107 input string, which means that demangle_signature has no work
2109 if ((*mangled)[2] == 'v')
2110 (*mangled) += 5; /* New style, with thunks: "__vt_" */
2112 (*mangled) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
2113 while (**mangled != '\0')
2119 success = demangle_qualified (work, mangled, declp, 0, 1);
2122 success = demangle_template (work, mangled, declp, 0, 1,
2126 if (isdigit((unsigned char)*mangled[0]))
2128 n = consume_count(mangled);
2129 /* We may be seeing a too-large size, or else a
2130 ".<digits>" indicating a static local symbol. In
2131 any case, declare victory and move on; *don't* try
2132 to use n to allocate. */
2133 if (n > (int) strlen (*mangled))
2141 n = strcspn (*mangled, cplus_markers);
2143 string_appendn (declp, *mangled, n);
2147 p = strpbrk (*mangled, cplus_markers);
2148 if (success && ((p == NULL) || (p == *mangled)))
2152 string_append (declp, SCOPE_STRING (work));
2163 string_append (declp, " virtual table");
2165 else if ((*mangled)[0] == '_'
2166 && (strchr("0123456789Qt", (*mangled)[1]) != NULL)
2167 && (p = strpbrk (*mangled, cplus_markers)) != NULL)
2169 /* static data member, "_3foo$varname" for example */
2175 success = demangle_qualified (work, mangled, declp, 0, 1);
2178 success = demangle_template (work, mangled, declp, 0, 1, 1);
2181 n = consume_count (mangled);
2182 string_appendn (declp, *mangled, n);
2185 if (success && (p == *mangled))
2187 /* Consumed everything up to the cplus_marker, append the
2190 string_append (declp, SCOPE_STRING (work));
2191 n = strlen (*mangled);
2192 string_appendn (declp, *mangled, n);
2200 else if (strncmp (*mangled, "__thunk_", 8) == 0)
2202 int delta = ((*mangled) += 8, consume_count (mangled));
2203 char *method = internal_cplus_demangle (work, ++*mangled);
2207 sprintf (buf, "virtual function thunk (delta:%d) for ", -delta);
2208 string_append (declp, buf);
2209 string_append (declp, method);
2211 n = strlen (*mangled);
2219 else if (strncmp (*mangled, "__t", 3) == 0
2220 && ((*mangled)[3] == 'i' || (*mangled)[3] == 'f'))
2222 p = (*mangled)[3] == 'i' ? " type_info node" : " type_info function";
2228 success = demangle_qualified (work, mangled, declp, 0, 1);
2231 success = demangle_template (work, mangled, declp, 0, 1, 1);
2234 success = demangle_fund_type (work, mangled, declp);
2237 if (success && **mangled != '\0')
2240 string_append (declp, p);
2253 arm_special -- special handling of ARM/lucid mangled strings
2258 arm_special (const char **mangled,
2264 Process some special ARM style mangling forms that don't fit
2265 the normal pattern. For example:
2267 __vtbl__3foo (foo virtual table)
2268 __vtbl__3foo__3bar (bar::foo virtual table)
2273 arm_special (mangled, declp)
2274 const char **mangled;
2281 if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
2283 /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
2284 and create the decl. Note that we consume the entire mangled
2285 input string, which means that demangle_signature has no work
2287 scan = *mangled + ARM_VTABLE_STRLEN;
2288 while (*scan != '\0') /* first check it can be demangled */
2290 n = consume_count (&scan);
2293 return (0); /* no good */
2296 if (scan[0] == '_' && scan[1] == '_')
2301 (*mangled) += ARM_VTABLE_STRLEN;
2302 while (**mangled != '\0')
2304 n = consume_count (mangled);
2305 string_prependn (declp, *mangled, n);
2307 if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
2309 string_prepend (declp, "::");
2313 string_append (declp, " virtual table");
2326 demangle_qualified -- demangle 'Q' qualified name strings
2331 demangle_qualified (struct work_stuff *, const char *mangled,
2332 string *result, int isfuncname, int append);
2336 Demangle a qualified name, such as "Q25Outer5Inner" which is
2337 the mangled form of "Outer::Inner". The demangled output is
2338 prepended or appended to the result string according to the
2339 state of the append flag.
2341 If isfuncname is nonzero, then the qualified name we are building
2342 is going to be used as a member function name, so if it is a
2343 constructor or destructor function, append an appropriate
2344 constructor or destructor name. I.E. for the above example,
2345 the result for use as a constructor is "Outer::Inner::Inner"
2346 and the result for use as a destructor is "Outer::Inner::~Inner".
2350 Numeric conversion is ASCII dependent (FIXME).
2355 demangle_qualified (work, mangled, result, isfuncname, append)
2356 struct work_stuff *work;
2357 const char **mangled;
2368 int bindex = register_Btype (work);
2370 /* We only make use of ISFUNCNAME if the entity is a constructor or
2372 isfuncname = (isfuncname
2373 && ((work->constructor & 1) || (work->destructor & 1)));
2375 string_init (&temp);
2376 string_init (&last_name);
2378 if ((*mangled)[0] == 'K')
2380 /* Squangling qualified name reuse */
2383 idx = consume_count_with_underscores (mangled);
2384 if (idx == -1 || idx >= work -> numk)
2387 string_append (&temp, work -> ktypevec[idx]);
2390 switch ((*mangled)[1])
2393 /* GNU mangled name with more than 9 classes. The count is preceded
2394 by an underscore (to distinguish it from the <= 9 case) and followed
2395 by an underscore. */
2397 qualifiers = atoi (p);
2398 if (!isdigit ((unsigned char)*p) || *p == '0')
2401 /* Skip the digits. */
2402 while (isdigit ((unsigned char)*p))
2420 /* The count is in a single digit. */
2421 num[0] = (*mangled)[1];
2423 qualifiers = atoi (num);
2425 /* If there is an underscore after the digit, skip it. This is
2426 said to be for ARM-qualified names, but the ARM makes no
2427 mention of such an underscore. Perhaps cfront uses one. */
2428 if ((*mangled)[2] == '_')
2443 /* Pick off the names and collect them in the temp buffer in the order
2444 in which they are found, separated by '::'. */
2446 while (qualifiers-- > 0)
2449 string_clear (&last_name);
2451 if (*mangled[0] == '_')
2454 if (*mangled[0] == 't')
2456 /* Here we always append to TEMP since we will want to use
2457 the template name without the template parameters as a
2458 constructor or destructor name. The appropriate
2459 (parameter-less) value is returned by demangle_template
2460 in LAST_NAME. We do not remember the template type here,
2461 in order to match the G++ mangling algorithm. */
2462 success = demangle_template(work, mangled, &temp,
2467 else if (*mangled[0] == 'K')
2471 idx = consume_count_with_underscores (mangled);
2472 if (idx == -1 || idx >= work->numk)
2475 string_append (&temp, work->ktypevec[idx]);
2478 if (!success) break;
2482 success = do_type (work, mangled, &last_name);
2485 string_appends (&temp, &last_name);
2489 remember_Ktype (work, temp.b, LEN_STRING (&temp));
2492 string_append (&temp, SCOPE_STRING (work));
2495 remember_Btype (work, temp.b, LEN_STRING (&temp), bindex);
2497 /* If we are using the result as a function name, we need to append
2498 the appropriate '::' separated constructor or destructor name.
2499 We do this here because this is the most convenient place, where
2500 we already have a pointer to the name and the length of the name. */
2504 string_append (&temp, SCOPE_STRING (work));
2505 if (work -> destructor & 1)
2506 string_append (&temp, "~");
2507 string_appends (&temp, &last_name);
2510 /* Now either prepend the temp buffer to the result, or append it,
2511 depending upon the state of the append flag. */
2514 string_appends (result, &temp);
2517 if (!STRING_EMPTY (result))
2518 string_append (&temp, SCOPE_STRING (work));
2519 string_prepends (result, &temp);
2522 string_delete (&last_name);
2523 string_delete (&temp);
2531 get_count -- convert an ascii count to integer, consuming tokens
2536 get_count (const char **type, int *count)
2540 Return 0 if no conversion is performed, 1 if a string is converted.
2544 get_count (type, count)
2551 if (!isdigit ((unsigned char)**type))
2557 *count = **type - '0';
2559 if (isdigit ((unsigned char)**type))
2569 while (isdigit ((unsigned char)*p));
2580 /* RESULT will be initialised here; it will be freed on failure. The
2581 value returned is really a type_kind_t. */
2584 do_type (work, mangled, result)
2585 struct work_stuff *work;
2586 const char **mangled;
2593 const char *remembered_type;
2596 type_kind_t tk = tk_none;
2598 string_init (&btype);
2599 string_init (&decl);
2600 string_init (result);
2604 while (success && !done)
2610 /* A pointer type */
2614 string_prepend (&decl, "*");
2619 /* A reference type */
2622 string_prepend (&decl, "&");
2631 if (!STRING_EMPTY (&decl)
2632 && (decl.b[0] == '*' || decl.b[0] == '&'))
2634 string_prepend (&decl, "(");
2635 string_append (&decl, ")");
2637 string_append (&decl, "[");
2638 if (**mangled != '_')
2639 success = demangle_template_value_parm (work, mangled, &decl,
2641 if (**mangled == '_')
2643 string_append (&decl, "]");
2647 /* A back reference to a previously seen type */
2650 if (!get_count (mangled, &n) || n >= work -> ntypes)
2656 remembered_type = work -> typevec[n];
2657 mangled = &remembered_type;
2664 if (!STRING_EMPTY (&decl)
2665 && (decl.b[0] == '*' || decl.b[0] == '&'))
2667 string_prepend (&decl, "(");
2668 string_append (&decl, ")");
2670 /* After picking off the function args, we expect to either find the
2671 function return type (preceded by an '_') or the end of the
2673 if (!demangle_nested_args (work, mangled, &decl)
2674 || (**mangled != '_' && **mangled != '\0'))
2679 if (success && (**mangled == '_'))
2686 type_quals = TYPE_UNQUALIFIED;
2688 member = **mangled == 'M';
2690 if (!isdigit ((unsigned char)**mangled) && **mangled != 't')
2696 string_append (&decl, ")");
2697 string_prepend (&decl, SCOPE_STRING (work));
2698 if (isdigit ((unsigned char)**mangled))
2700 n = consume_count (mangled);
2701 if ((int) strlen (*mangled) < n)
2706 string_prependn (&decl, *mangled, n);
2712 string_init (&temp);
2713 success = demangle_template (work, mangled, &temp,
2717 string_prependn (&decl, temp.b, temp.p - temp.b);
2718 string_clear (&temp);
2723 string_prepend (&decl, "(");
2731 type_quals |= code_for_qualifier (**mangled);
2739 if (*(*mangled)++ != 'F')
2745 if ((member && !demangle_nested_args (work, mangled, &decl))
2746 || **mangled != '_')
2752 if (! PRINT_ANSI_QUALIFIERS)
2756 if (type_quals != TYPE_UNQUALIFIED)
2758 APPEND_BLANK (&decl);
2759 string_append (&decl, qualifier_string (type_quals));
2770 if (PRINT_ANSI_QUALIFIERS)
2772 if (!STRING_EMPTY (&decl))
2773 string_prepend (&decl, " ");
2775 string_prepend (&decl, demangle_qualifier (**mangled));
2790 if (success) switch (**mangled)
2792 /* A qualified name, such as "Outer::Inner". */
2796 success = demangle_qualified (work, mangled, result, 0, 1);
2800 /* A back reference to a previously seen squangled type */
2803 if (!get_count (mangled, &n) || n >= work -> numb)
2806 string_append (result, work->btypevec[n]);
2811 /* A template parm. We substitute the corresponding argument. */
2816 idx = consume_count_with_underscores (mangled);
2819 || (work->tmpl_argvec && idx >= work->ntmpl_args)
2820 || consume_count_with_underscores (mangled) == -1)
2826 if (work->tmpl_argvec)
2827 string_append (result, work->tmpl_argvec[idx]);
2831 sprintf(buf, "T%d", idx);
2832 string_append (result, buf);
2840 success = demangle_fund_type (work, mangled, result);
2842 tk = (type_kind_t) success;
2848 if (!STRING_EMPTY (&decl))
2850 string_append (result, " ");
2851 string_appends (result, &decl);
2855 string_delete (result);
2856 string_delete (&decl);
2859 /* Assume an integral type, if we're not sure. */
2860 return (int) ((tk == tk_none) ? tk_integral : tk);
2865 /* Given a pointer to a type string that represents a fundamental type
2866 argument (int, long, unsigned int, etc) in TYPE, a pointer to the
2867 string in which the demangled output is being built in RESULT, and
2868 the WORK structure, decode the types and add them to the result.
2873 "Sl" => "signed long"
2874 "CUs" => "const unsigned short"
2876 The value returned is really a type_kind_t. */
2879 demangle_fund_type (work, mangled, result)
2880 struct work_stuff *work;
2881 const char **mangled;
2889 type_kind_t tk = tk_integral;
2891 string_init (&btype);
2893 /* First pick off any type qualifiers. There can be more than one. */
2903 if (PRINT_ANSI_QUALIFIERS)
2905 APPEND_BLANK (result);
2906 string_append (result, demangle_qualifier (**mangled));
2911 APPEND_BLANK (result);
2912 string_append (result, "unsigned");
2914 case 'S': /* signed char only */
2916 APPEND_BLANK (result);
2917 string_append (result, "signed");
2921 APPEND_BLANK (result);
2922 string_append (result, "__complex");
2930 /* Now pick off the fundamental type. There can be only one. */
2939 APPEND_BLANK (result);
2940 string_append (result, "void");
2944 APPEND_BLANK (result);
2945 string_append (result, "long long");
2949 APPEND_BLANK (result);
2950 string_append (result, "long");
2954 APPEND_BLANK (result);
2955 string_append (result, "int");
2959 APPEND_BLANK (result);
2960 string_append (result, "short");
2964 APPEND_BLANK (result);
2965 string_append (result, "bool");
2970 APPEND_BLANK (result);
2971 string_append (result, "char");
2976 APPEND_BLANK (result);
2977 string_append (result, "wchar_t");
2982 APPEND_BLANK (result);
2983 string_append (result, "long double");
2988 APPEND_BLANK (result);
2989 string_append (result, "double");
2994 APPEND_BLANK (result);
2995 string_append (result, "float");
3000 if (!isdigit ((unsigned char)**mangled))
3007 if (**mangled == '_')
3011 for (i = 0; **mangled != '_'; ++(*mangled), ++i)
3018 strncpy (buf, *mangled, 2);
3021 sscanf (buf, "%x", &dec);
3022 sprintf (buf, "int%i_t", dec);
3023 APPEND_BLANK (result);
3024 string_append (result, buf);
3028 /* An explicit type, such as "6mytype" or "7integer" */
3040 int bindex = register_Btype (work);
3042 string_init (&btype);
3043 if (demangle_class_name (work, mangled, &btype)) {
3044 remember_Btype (work, btype.b, LEN_STRING (&btype), bindex);
3045 APPEND_BLANK (result);
3046 string_appends (result, &btype);
3050 string_delete (&btype);
3055 success = demangle_template (work, mangled, &btype, 0, 1, 1);
3056 string_appends (result, &btype);
3064 return success ? ((int) tk) : 0;
3067 /* Demangle the next argument, given by MANGLED into RESULT, which
3068 *should be an uninitialized* string. It will be initialized here,
3069 and free'd should anything go wrong. */
3072 do_arg (work, mangled, result)
3073 struct work_stuff *work;
3074 const char **mangled;
3077 /* Remember where we started so that we can record the type, for
3078 non-squangling type remembering. */
3079 const char *start = *mangled;
3081 string_init (result);
3083 if (work->nrepeats > 0)
3087 if (work->previous_argument == 0)
3090 /* We want to reissue the previous type in this argument list. */
3091 string_appends (result, work->previous_argument);
3095 if (**mangled == 'n')
3097 /* A squangling-style repeat. */
3099 work->nrepeats = consume_count(mangled);
3101 if (work->nrepeats == 0)
3102 /* This was not a repeat count after all. */
3105 if (work->nrepeats > 9)
3107 if (**mangled != '_')
3108 /* The repeat count should be followed by an '_' in this
3115 /* Now, the repeat is all set up. */
3116 return do_arg (work, mangled, result);
3119 /* Save the result in WORK->previous_argument so that we can find it
3120 if it's repeated. Note that saving START is not good enough: we
3121 do not want to add additional types to the back-referenceable
3122 type vector when processing a repeated type. */
3123 if (work->previous_argument)
3124 string_clear (work->previous_argument);
3127 work->previous_argument = (string*) xmalloc (sizeof (string));
3128 string_init (work->previous_argument);
3131 if (!do_type (work, mangled, work->previous_argument))
3134 string_appends (result, work->previous_argument);
3136 remember_type (work, start, *mangled - start);
3141 remember_type (work, start, len)
3142 struct work_stuff *work;
3148 if (work->forgetting_types)
3151 if (work -> ntypes >= work -> typevec_size)
3153 if (work -> typevec_size == 0)
3155 work -> typevec_size = 3;
3157 = (char **) xmalloc (sizeof (char *) * work -> typevec_size);
3161 work -> typevec_size *= 2;
3163 = (char **) xrealloc ((char *)work -> typevec,
3164 sizeof (char *) * work -> typevec_size);
3167 tem = xmalloc (len + 1);
3168 memcpy (tem, start, len);
3170 work -> typevec[work -> ntypes++] = tem;
3174 /* Remember a K type class qualifier. */
3176 remember_Ktype (work, start, len)
3177 struct work_stuff *work;
3183 if (work -> numk >= work -> ksize)
3185 if (work -> ksize == 0)
3189 = (char **) xmalloc (sizeof (char *) * work -> ksize);
3195 = (char **) xrealloc ((char *)work -> ktypevec,
3196 sizeof (char *) * work -> ksize);
3199 tem = xmalloc (len + 1);
3200 memcpy (tem, start, len);
3202 work -> ktypevec[work -> numk++] = tem;
3205 /* Register a B code, and get an index for it. B codes are registered
3206 as they are seen, rather than as they are completed, so map<temp<char> >
3207 registers map<temp<char> > as B0, and temp<char> as B1 */
3210 register_Btype (work)
3211 struct work_stuff *work;
3215 if (work -> numb >= work -> bsize)
3217 if (work -> bsize == 0)
3221 = (char **) xmalloc (sizeof (char *) * work -> bsize);
3227 = (char **) xrealloc ((char *)work -> btypevec,
3228 sizeof (char *) * work -> bsize);
3231 ret = work -> numb++;
3232 work -> btypevec[ret] = NULL;
3236 /* Store a value into a previously registered B code type. */
3239 remember_Btype (work, start, len, index)
3240 struct work_stuff *work;
3246 tem = xmalloc (len + 1);
3247 memcpy (tem, start, len);
3249 work -> btypevec[index] = tem;
3252 /* Lose all the info related to B and K type codes. */
3254 forget_B_and_K_types (work)
3255 struct work_stuff *work;
3259 while (work -> numk > 0)
3261 i = --(work -> numk);
3262 if (work -> ktypevec[i] != NULL)
3264 free (work -> ktypevec[i]);
3265 work -> ktypevec[i] = NULL;
3269 while (work -> numb > 0)
3271 i = --(work -> numb);
3272 if (work -> btypevec[i] != NULL)
3274 free (work -> btypevec[i]);
3275 work -> btypevec[i] = NULL;
3279 /* Forget the remembered types, but not the type vector itself. */
3283 struct work_stuff *work;
3287 while (work -> ntypes > 0)
3289 i = --(work -> ntypes);
3290 if (work -> typevec[i] != NULL)
3292 free (work -> typevec[i]);
3293 work -> typevec[i] = NULL;
3298 /* Process the argument list part of the signature, after any class spec
3299 has been consumed, as well as the first 'F' character (if any). For
3302 "__als__3fooRT0" => process "RT0"
3303 "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i"
3305 DECLP must be already initialised, usually non-empty. It won't be freed
3308 Note that g++ differs significantly from ARM and lucid style mangling
3309 with regards to references to previously seen types. For example, given
3310 the source fragment:
3314 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
3317 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3318 void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3320 g++ produces the names:
3325 while lcc (and presumably other ARM style compilers as well) produces:
3327 foo__FiR3fooT1T2T1T2
3328 __ct__3fooFiR3fooT1T2T1T2
3330 Note that g++ bases its type numbers starting at zero and counts all
3331 previously seen types, while lucid/ARM bases its type numbers starting
3332 at one and only considers types after it has seen the 'F' character
3333 indicating the start of the function args. For lucid/ARM style, we
3334 account for this difference by discarding any previously seen types when
3335 we see the 'F' character, and subtracting one from the type number
3341 demangle_args (work, mangled, declp)
3342 struct work_stuff *work;
3343 const char **mangled;
3353 if (PRINT_ARG_TYPES)
3355 string_append (declp, "(");
3356 if (**mangled == '\0')
3358 string_append (declp, "void");
3362 while ((**mangled != '_' && **mangled != '\0' && **mangled != 'e')
3363 || work->nrepeats > 0)
3365 if ((**mangled == 'N') || (**mangled == 'T'))
3367 temptype = *(*mangled)++;
3369 if (temptype == 'N')
3371 if (!get_count (mangled, &r))
3380 if (ARM_DEMANGLING && work -> ntypes >= 10)
3382 /* If we have 10 or more types we might have more than a 1 digit
3383 index so we'll have to consume the whole count here. This
3384 will lose if the next thing is a type name preceded by a
3385 count but it's impossible to demangle that case properly
3386 anyway. Eg if we already have 12 types is T12Pc "(..., type1,
3387 Pc, ...)" or "(..., type12, char *, ...)" */
3388 if ((t = consume_count(mangled)) == 0)
3395 if (!get_count (mangled, &t))
3400 if (LUCID_DEMANGLING || ARM_DEMANGLING)
3404 /* Validate the type index. Protect against illegal indices from
3405 malformed type strings. */
3406 if ((t < 0) || (t >= work -> ntypes))
3410 while (work->nrepeats > 0 || --r >= 0)
3412 tem = work -> typevec[t];
3413 if (need_comma && PRINT_ARG_TYPES)
3415 string_append (declp, ", ");
3417 if (!do_arg (work, &tem, &arg))
3421 if (PRINT_ARG_TYPES)
3423 string_appends (declp, &arg);
3425 string_delete (&arg);
3431 if (need_comma && PRINT_ARG_TYPES)
3432 string_append (declp, ", ");
3433 if (!do_arg (work, mangled, &arg))
3435 if (PRINT_ARG_TYPES)
3436 string_appends (declp, &arg);
3437 string_delete (&arg);
3442 if (**mangled == 'e')
3445 if (PRINT_ARG_TYPES)
3449 string_append (declp, ",");
3451 string_append (declp, "...");
3455 if (PRINT_ARG_TYPES)
3457 string_append (declp, ")");
3462 /* Like demangle_args, but for demangling the argument lists of function
3463 and method pointers or references, not top-level declarations. */
3466 demangle_nested_args (work, mangled, declp)
3467 struct work_stuff *work;
3468 const char **mangled;
3471 string* saved_previous_argument;
3475 /* The G++ name-mangling algorithm does not remember types on nested
3476 argument lists, unless -fsquangling is used, and in that case the
3477 type vector updated by remember_type is not used. So, we turn
3478 off remembering of types here. */
3479 ++work->forgetting_types;
3481 /* For the repeat codes used with -fsquangling, we must keep track of
3482 the last argument. */
3483 saved_previous_argument = work->previous_argument;
3484 saved_nrepeats = work->nrepeats;
3485 work->previous_argument = 0;
3488 /* Actually demangle the arguments. */
3489 result = demangle_args (work, mangled, declp);
3491 /* Restore the previous_argument field. */
3492 if (work->previous_argument)
3493 string_delete (work->previous_argument);
3494 work->previous_argument = saved_previous_argument;
3495 work->nrepeats = saved_nrepeats;
3501 demangle_function_name (work, mangled, declp, scan)
3502 struct work_stuff *work;
3503 const char **mangled;
3511 string_appendn (declp, (*mangled), scan - (*mangled));
3512 string_need (declp, 1);
3513 *(declp -> p) = '\0';
3515 /* Consume the function name, including the "__" separating the name
3516 from the signature. We are guaranteed that SCAN points to the
3519 (*mangled) = scan + 2;
3521 if (LUCID_DEMANGLING || ARM_DEMANGLING)
3524 /* See if we have an ARM style constructor or destructor operator.
3525 If so, then just record it, clear the decl, and return.
3526 We can't build the actual constructor/destructor decl until later,
3527 when we recover the class name from the signature. */
3529 if (strcmp (declp -> b, "__ct") == 0)
3531 work -> constructor += 1;
3532 string_clear (declp);
3535 else if (strcmp (declp -> b, "__dt") == 0)
3537 work -> destructor += 1;
3538 string_clear (declp);
3543 if (declp->p - declp->b >= 3
3544 && declp->b[0] == 'o'
3545 && declp->b[1] == 'p'
3546 && strchr (cplus_markers, declp->b[2]) != NULL)
3548 /* see if it's an assignment expression */
3549 if (declp->p - declp->b >= 10 /* op$assign_ */
3550 && memcmp (declp->b + 3, "assign_", 7) == 0)
3552 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
3554 int len = declp->p - declp->b - 10;
3555 if ((int) strlen (optable[i].in) == len
3556 && memcmp (optable[i].in, declp->b + 10, len) == 0)
3558 string_clear (declp);
3559 string_append (declp, "operator");
3560 string_append (declp, optable[i].out);
3561 string_append (declp, "=");
3568 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
3570 int len = declp->p - declp->b - 3;
3571 if ((int) strlen (optable[i].in) == len
3572 && memcmp (optable[i].in, declp->b + 3, len) == 0)
3574 string_clear (declp);
3575 string_append (declp, "operator");
3576 string_append (declp, optable[i].out);
3582 else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0
3583 && strchr (cplus_markers, declp->b[4]) != NULL)
3585 /* type conversion operator */
3587 if (do_type (work, &tem, &type))
3589 string_clear (declp);
3590 string_append (declp, "operator ");
3591 string_appends (declp, &type);
3592 string_delete (&type);
3595 else if (declp->b[0] == '_' && declp->b[1] == '_'
3596 && declp->b[2] == 'o' && declp->b[3] == 'p')
3599 /* type conversion operator. */
3601 if (do_type (work, &tem, &type))
3603 string_clear (declp);
3604 string_append (declp, "operator ");
3605 string_appends (declp, &type);
3606 string_delete (&type);
3609 else if (declp->b[0] == '_' && declp->b[1] == '_'
3610 && declp->b[2] >= 'a' && declp->b[2] <= 'z'
3611 && declp->b[3] >= 'a' && declp->b[3] <= 'z')
3613 if (declp->b[4] == '\0')
3616 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
3618 if (strlen (optable[i].in) == 2
3619 && memcmp (optable[i].in, declp->b + 2, 2) == 0)
3621 string_clear (declp);
3622 string_append (declp, "operator");
3623 string_append (declp, optable[i].out);
3630 if (declp->b[2] == 'a' && declp->b[5] == '\0')
3633 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
3635 if (strlen (optable[i].in) == 3
3636 && memcmp (optable[i].in, declp->b + 2, 3) == 0)
3638 string_clear (declp);
3639 string_append (declp, "operator");
3640 string_append (declp, optable[i].out);
3649 /* a mini string-handling package */
3664 s->p = s->b = xmalloc (n);
3667 else if (s->e - s->p < n)
3672 s->b = xrealloc (s->b, n);
3685 s->b = s->e = s->p = NULL;
3693 s->b = s->p = s->e = NULL;
3709 return (s->b == s->p);
3715 string_append (p, s)
3720 if (s == NULL || *s == '\0')
3724 memcpy (p->p, s, n);
3729 string_appends (p, s)
3738 memcpy (p->p, s->b, n);
3744 string_appendn (p, s, n)
3752 memcpy (p->p, s, n);
3758 string_prepend (p, s)
3762 if (s != NULL && *s != '\0')
3764 string_prependn (p, s, strlen (s));
3769 string_prepends (p, s)
3774 string_prependn (p, s->b, s->p - s->b);
3779 string_prependn (p, s, n)
3789 for (q = p->p - 1; q >= p->b; q--)
3793 memcpy (p->b, s, n);
3798 /* To generate a standalone demangler program for testing purposes,
3799 just compile and link this file with -DMAIN and libiberty.a. When
3800 run, it demangles each command line arg, or each stdin string, and
3801 prints the result on stdout. */
3807 static char *program_name;
3808 static char *program_version = VERSION;
3809 static int flags = DMGL_PARAMS | DMGL_ANSI;
3811 static void demangle_it PARAMS ((char *));
3812 static void usage PARAMS ((FILE *, int));
3813 static void fatal PARAMS ((char *));
3816 demangle_it (mangled_name)
3821 result = cplus_demangle (mangled_name, flags);
3824 printf ("%s\n", mangled_name);
3828 printf ("%s\n", result);
3834 usage (stream, status)
3839 Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
3840 [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\
3841 [--help] [--version] [arg...]\n",
3846 #define MBUF_SIZE 32767
3847 char mbuffer[MBUF_SIZE];
3849 /* Defined in the automatically-generated underscore.c. */
3850 extern int prepends_underscore;
3852 int strip_underscore = 0;
3854 static struct option long_options[] = {
3855 {"strip-underscores", no_argument, 0, '_'},
3856 {"format", required_argument, 0, 's'},
3857 {"help", no_argument, 0, 'h'},
3858 {"no-strip-underscores", no_argument, 0, 'n'},
3859 {"version", no_argument, 0, 'v'},
3860 {0, no_argument, 0, 0}
3863 /* More 'friendly' abort that prints the line and file.
3864 config.h can #define abort fancy_abort if you like that sort of thing. */
3869 fatal ("Internal gcc abort.");
3880 program_name = argv[0];
3882 strip_underscore = prepends_underscore;
3884 while ((c = getopt_long (argc, argv, "_ns:j", long_options, (int *) 0)) != EOF)
3894 strip_underscore = 0;
3897 printf ("GNU %s version %s\n", program_name, program_version);
3900 strip_underscore = 1;
3903 if (strcmp (optarg, "gnu") == 0)
3905 current_demangling_style = gnu_demangling;
3907 else if (strcmp (optarg, "lucid") == 0)
3909 current_demangling_style = lucid_demangling;
3911 else if (strcmp (optarg, "arm") == 0)
3913 current_demangling_style = arm_demangling;
3917 fprintf (stderr, "%s: unknown demangling style `%s'\n",
3918 program_name, optarg);
3927 for ( ; optind < argc; optind++)
3929 demangle_it (argv[optind]);
3938 /* Try to read a label. */
3939 while (c != EOF && (isalnum(c) || c == '_' || c == '$' || c == '.'))
3941 if (i >= MBUF_SIZE-1)
3950 if (mbuffer[0] == '.')
3952 if (strip_underscore && mbuffer[skip_first] == '_')
3960 result = cplus_demangle (mbuffer + skip_first, flags);
3963 if (mbuffer[0] == '.')
3965 fputs (result, stdout);
3969 fputs (mbuffer, stdout);
3986 fprintf (stderr, "%s: %s\n", program_name, str);
3994 register char *value = (char *) malloc (size);
3996 fatal ("virtual memory exhausted");
4001 xrealloc (ptr, size)
4005 register char *value = (char *) realloc (ptr, size);
4007 fatal ("virtual memory exhausted");