1 /* Demangler for GNU C++
2 Copyright 1989, 91, 94, 95, 96, 97, 98, 1999 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
5 Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
7 This file is part of the libiberty library.
8 Libiberty is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
13 Libiberty is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
18 You should have received a copy of the GNU Library General Public
19 License along with libiberty; see the file COPYING.LIB. If
20 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
23 /* This file exports two functions; cplus_mangle_opname and cplus_demangle.
25 This file imports xmalloc and xrealloc, which are like malloc and
26 realloc except that they generate a fatal error if there is no
29 /* This file lives in both GCC and libiberty. When making changes, please
30 try not to break either. */
37 #include <sys/types.h>
49 #undef CURRENT_DEMANGLING_STYLE
50 #define CURRENT_DEMANGLING_STYLE work->options
52 #include "libiberty.h"
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' };
97 static char char_str
[2] = { '\000', '\000' };
100 set_cplus_marker_for_demangling (ch
)
103 cplus_markers
[0] = ch
;
106 typedef struct string
/* Beware: these aren't required to be */
107 { /* '\0' terminated. */
108 char *b
; /* pointer to start of string */
109 char *p
; /* pointer after last character */
110 char *e
; /* pointer after end of allocated space */
113 /* Stuff that is shared between sub-routines.
114 Using a shared structure allows cplus_demangle to be reentrant. */
130 int static_type
; /* A static member function */
131 int temp_start
; /* index in demangled to start of template args */
132 int type_quals
; /* The type qualifiers. */
133 int dllimported
; /* Symbol imported from a PE DLL */
134 char **tmpl_argvec
; /* Template function arguments. */
135 int ntmpl_args
; /* The number of template function arguments. */
136 int forgetting_types
; /* Nonzero if we are not remembering the types
138 string
* previous_argument
; /* The last function argument demangled. */
139 int nrepeats
; /* The number of times to repeat the previous
143 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
144 #define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS)
146 static const struct optable
152 {"nw", " new", DMGL_ANSI
}, /* new (1.92, ansi) */
153 {"dl", " delete", DMGL_ANSI
}, /* new (1.92, ansi) */
154 {"new", " new", 0}, /* old (1.91, and 1.x) */
155 {"delete", " delete", 0}, /* old (1.91, and 1.x) */
156 {"vn", " new []", DMGL_ANSI
}, /* GNU, pending ansi */
157 {"vd", " delete []", DMGL_ANSI
}, /* GNU, pending ansi */
158 {"as", "=", DMGL_ANSI
}, /* ansi */
159 {"ne", "!=", DMGL_ANSI
}, /* old, ansi */
160 {"eq", "==", DMGL_ANSI
}, /* old, ansi */
161 {"ge", ">=", DMGL_ANSI
}, /* old, ansi */
162 {"gt", ">", DMGL_ANSI
}, /* old, ansi */
163 {"le", "<=", DMGL_ANSI
}, /* old, ansi */
164 {"lt", "<", DMGL_ANSI
}, /* old, ansi */
165 {"plus", "+", 0}, /* old */
166 {"pl", "+", DMGL_ANSI
}, /* ansi */
167 {"apl", "+=", DMGL_ANSI
}, /* ansi */
168 {"minus", "-", 0}, /* old */
169 {"mi", "-", DMGL_ANSI
}, /* ansi */
170 {"ami", "-=", DMGL_ANSI
}, /* ansi */
171 {"mult", "*", 0}, /* old */
172 {"ml", "*", DMGL_ANSI
}, /* ansi */
173 {"amu", "*=", DMGL_ANSI
}, /* ansi (ARM/Lucid) */
174 {"aml", "*=", DMGL_ANSI
}, /* ansi (GNU/g++) */
175 {"convert", "+", 0}, /* old (unary +) */
176 {"negate", "-", 0}, /* old (unary -) */
177 {"trunc_mod", "%", 0}, /* old */
178 {"md", "%", DMGL_ANSI
}, /* ansi */
179 {"amd", "%=", DMGL_ANSI
}, /* ansi */
180 {"trunc_div", "/", 0}, /* old */
181 {"dv", "/", DMGL_ANSI
}, /* ansi */
182 {"adv", "/=", DMGL_ANSI
}, /* ansi */
183 {"truth_andif", "&&", 0}, /* old */
184 {"aa", "&&", DMGL_ANSI
}, /* ansi */
185 {"truth_orif", "||", 0}, /* old */
186 {"oo", "||", DMGL_ANSI
}, /* ansi */
187 {"truth_not", "!", 0}, /* old */
188 {"nt", "!", DMGL_ANSI
}, /* ansi */
189 {"postincrement","++", 0}, /* old */
190 {"pp", "++", DMGL_ANSI
}, /* ansi */
191 {"postdecrement","--", 0}, /* old */
192 {"mm", "--", DMGL_ANSI
}, /* ansi */
193 {"bit_ior", "|", 0}, /* old */
194 {"or", "|", DMGL_ANSI
}, /* ansi */
195 {"aor", "|=", DMGL_ANSI
}, /* ansi */
196 {"bit_xor", "^", 0}, /* old */
197 {"er", "^", DMGL_ANSI
}, /* ansi */
198 {"aer", "^=", DMGL_ANSI
}, /* ansi */
199 {"bit_and", "&", 0}, /* old */
200 {"ad", "&", DMGL_ANSI
}, /* ansi */
201 {"aad", "&=", DMGL_ANSI
}, /* ansi */
202 {"bit_not", "~", 0}, /* old */
203 {"co", "~", DMGL_ANSI
}, /* ansi */
204 {"call", "()", 0}, /* old */
205 {"cl", "()", DMGL_ANSI
}, /* ansi */
206 {"alshift", "<<", 0}, /* old */
207 {"ls", "<<", DMGL_ANSI
}, /* ansi */
208 {"als", "<<=", DMGL_ANSI
}, /* ansi */
209 {"arshift", ">>", 0}, /* old */
210 {"rs", ">>", DMGL_ANSI
}, /* ansi */
211 {"ars", ">>=", DMGL_ANSI
}, /* ansi */
212 {"component", "->", 0}, /* old */
213 {"pt", "->", DMGL_ANSI
}, /* ansi; Lucid C++ form */
214 {"rf", "->", DMGL_ANSI
}, /* ansi; ARM/GNU form */
215 {"indirect", "*", 0}, /* old */
216 {"method_call", "->()", 0}, /* old */
217 {"addr", "&", 0}, /* old (unary &) */
218 {"array", "[]", 0}, /* old */
219 {"vc", "[]", DMGL_ANSI
}, /* ansi */
220 {"compound", ", ", 0}, /* old */
221 {"cm", ", ", DMGL_ANSI
}, /* ansi */
222 {"cond", "?:", 0}, /* old */
223 {"cn", "?:", DMGL_ANSI
}, /* pseudo-ansi */
224 {"max", ">?", 0}, /* old */
225 {"mx", ">?", DMGL_ANSI
}, /* pseudo-ansi */
226 {"min", "<?", 0}, /* old */
227 {"mn", "<?", DMGL_ANSI
}, /* pseudo-ansi */
228 {"nop", "", 0}, /* old (for operator=) */
229 {"rm", "->*", DMGL_ANSI
}, /* ansi */
230 {"sz", "sizeof ", DMGL_ANSI
} /* pseudo-ansi */
233 /* These values are used to indicate the various type varieties.
234 They are all non-zero so that they can be used as `success'
236 typedef enum type_kind_t
247 #define STRING_EMPTY(str) ((str) -> b == (str) -> p)
248 #define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
249 string_prepend(str, " ");}
250 #define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
251 string_append(str, " ");}
252 #define LEN_STRING(str) ( (STRING_EMPTY(str))?0:((str)->p - (str)->b))
254 /* The scope separator appropriate for the language being demangled. */
256 #define SCOPE_STRING(work) ((work->options & DMGL_JAVA) ? "." : "::")
258 #define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */
259 #define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */
261 /* Prototypes for local functions */
264 mop_up
PARAMS ((struct work_stuff
*, string
*, int));
267 squangle_mop_up
PARAMS ((struct work_stuff
*));
271 demangle_method_args
PARAMS ((struct work_stuff
*, const char **, string
*));
275 internal_cplus_demangle
PARAMS ((struct work_stuff
*, const char *));
278 demangle_template_template_parm
PARAMS ((struct work_stuff
*work
,
279 const char **, string
*));
282 demangle_template
PARAMS ((struct work_stuff
*work
, const char **, string
*,
283 string
*, int, int));
286 arm_pt
PARAMS ((struct work_stuff
*, const char *, int, const char **,
290 demangle_class_name
PARAMS ((struct work_stuff
*, const char **, string
*));
293 demangle_qualified
PARAMS ((struct work_stuff
*, const char **, string
*,
297 demangle_class
PARAMS ((struct work_stuff
*, const char **, string
*));
300 demangle_fund_type
PARAMS ((struct work_stuff
*, const char **, string
*));
303 demangle_signature
PARAMS ((struct work_stuff
*, const char **, string
*));
306 demangle_prefix
PARAMS ((struct work_stuff
*, const char **, string
*));
309 gnu_special
PARAMS ((struct work_stuff
*, const char **, string
*));
312 arm_special
PARAMS ((const char **, string
*));
315 string_need
PARAMS ((string
*, int));
318 string_delete
PARAMS ((string
*));
321 string_init
PARAMS ((string
*));
324 string_clear
PARAMS ((string
*));
328 string_empty
PARAMS ((string
*));
332 string_append
PARAMS ((string
*, const char *));
335 string_appends
PARAMS ((string
*, string
*));
338 string_appendn
PARAMS ((string
*, const char *, int));
341 string_prepend
PARAMS ((string
*, const char *));
344 string_prependn
PARAMS ((string
*, const char *, int));
347 get_count
PARAMS ((const char **, int *));
350 consume_count
PARAMS ((const char **));
353 consume_count_with_underscores
PARAMS ((const char**));
356 demangle_args
PARAMS ((struct work_stuff
*, const char **, string
*));
359 demangle_nested_args
PARAMS ((struct work_stuff
*, const char**, string
*));
362 do_type
PARAMS ((struct work_stuff
*, const char **, string
*));
365 do_arg
PARAMS ((struct work_stuff
*, const char **, string
*));
368 demangle_function_name
PARAMS ((struct work_stuff
*, const char **, string
*,
372 remember_type
PARAMS ((struct work_stuff
*, const char *, int));
375 remember_Btype
PARAMS ((struct work_stuff
*, const char *, int, int));
378 register_Btype
PARAMS ((struct work_stuff
*));
381 remember_Ktype
PARAMS ((struct work_stuff
*, const char *, int));
384 forget_types
PARAMS ((struct work_stuff
*));
387 forget_B_and_K_types
PARAMS ((struct work_stuff
*));
390 string_prepends
PARAMS ((string
*, string
*));
393 demangle_template_value_parm
PARAMS ((struct work_stuff
*, const char**,
394 string
*, type_kind_t
));
397 do_hpacc_template_const_value
PARAMS ((struct work_stuff
*, const char **, string
*));
400 do_hpacc_template_literal
PARAMS ((struct work_stuff
*, const char **, string
*));
403 snarf_numeric_literal
PARAMS ((const char **, string
*));
405 /* There is a TYPE_QUAL value for each type qualifier. They can be
406 combined by bitwise-or to form the complete set of qualifiers for a
409 #define TYPE_UNQUALIFIED 0x0
410 #define TYPE_QUAL_CONST 0x1
411 #define TYPE_QUAL_VOLATILE 0x2
412 #define TYPE_QUAL_RESTRICT 0x4
415 code_for_qualifier
PARAMS ((int));
418 qualifier_string
PARAMS ((int));
421 demangle_qualifier
PARAMS ((int));
423 /* Translate count to integer, consuming tokens in the process.
424 Conversion terminates on the first non-digit character.
426 Trying to consume something that isn't a count results in no
427 consumption of input and a return of -1.
429 Overflow consumes the rest of the digits, and returns -1. */
437 if (! isdigit ((unsigned char)**type
))
440 while (isdigit ((unsigned char)**type
))
444 /* Check for overflow.
445 We assume that count is represented using two's-complement;
446 no power of two is divisible by ten, so if an overflow occurs
447 when multiplying by ten, the result will not be a multiple of
449 if ((count
% 10) != 0)
451 while (isdigit ((unsigned char) **type
))
456 count
+= **type
- '0';
464 /* Like consume_count, but for counts that are preceded and followed
465 by '_' if they are greater than 10. Also, -1 is returned for
466 failure, since 0 can be a valid value. */
469 consume_count_with_underscores (mangled
)
470 const char **mangled
;
474 if (**mangled
== '_')
477 if (!isdigit ((unsigned char)**mangled
))
480 idx
= consume_count (mangled
);
481 if (**mangled
!= '_')
482 /* The trailing underscore was missing. */
489 if (**mangled
< '0' || **mangled
> '9')
492 idx
= **mangled
- '0';
499 /* C is the code for a type-qualifier. Return the TYPE_QUAL
500 corresponding to this qualifier. */
503 code_for_qualifier (c
)
509 return TYPE_QUAL_CONST
;
512 return TYPE_QUAL_VOLATILE
;
515 return TYPE_QUAL_RESTRICT
;
521 /* C was an invalid qualifier. */
525 /* Return the string corresponding to the qualifiers given by
529 qualifier_string (type_quals
)
534 case TYPE_UNQUALIFIED
:
537 case TYPE_QUAL_CONST
:
540 case TYPE_QUAL_VOLATILE
:
543 case TYPE_QUAL_RESTRICT
:
546 case TYPE_QUAL_CONST
| TYPE_QUAL_VOLATILE
:
547 return "const volatile";
549 case TYPE_QUAL_CONST
| TYPE_QUAL_RESTRICT
:
550 return "const __restrict";
552 case TYPE_QUAL_VOLATILE
| TYPE_QUAL_RESTRICT
:
553 return "volatile __restrict";
555 case TYPE_QUAL_CONST
| TYPE_QUAL_VOLATILE
| TYPE_QUAL_RESTRICT
:
556 return "const volatile __restrict";
562 /* TYPE_QUALS was an invalid qualifier set. */
566 /* C is the code for a type-qualifier. Return the string
567 corresponding to this qualifier. This function should only be
568 called with a valid qualifier code. */
571 demangle_qualifier (c
)
574 return qualifier_string (code_for_qualifier (c
));
578 cplus_demangle_opname (opname
, result
, options
)
585 struct work_stuff work
[1];
588 len
= strlen(opname
);
591 memset ((char *) work
, 0, sizeof (work
));
592 work
->options
= options
;
594 if (opname
[0] == '_' && opname
[1] == '_'
595 && opname
[2] == 'o' && opname
[3] == 'p')
598 /* type conversion operator. */
600 if (do_type (work
, &tem
, &type
))
602 strcat (result
, "operator ");
603 strncat (result
, type
.b
, type
.p
- type
.b
);
604 string_delete (&type
);
608 else if (opname
[0] == '_' && opname
[1] == '_'
609 && opname
[2] >= 'a' && opname
[2] <= 'z'
610 && opname
[3] >= 'a' && opname
[3] <= 'z')
612 if (opname
[4] == '\0')
616 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
618 if (strlen (optable
[i
].in
) == 2
619 && memcmp (optable
[i
].in
, opname
+ 2, 2) == 0)
621 strcat (result
, "operator");
622 strcat (result
, optable
[i
].out
);
630 if (opname
[2] == 'a' && opname
[5] == '\0')
634 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
636 if (strlen (optable
[i
].in
) == 3
637 && memcmp (optable
[i
].in
, opname
+ 2, 3) == 0)
639 strcat (result
, "operator");
640 strcat (result
, optable
[i
].out
);
651 && strchr (cplus_markers
, opname
[2]) != NULL
)
653 /* see if it's an assignment expression */
654 if (len
>= 10 /* op$assign_ */
655 && memcmp (opname
+ 3, "assign_", 7) == 0)
658 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
661 if ((int) strlen (optable
[i
].in
) == len1
662 && memcmp (optable
[i
].in
, opname
+ 10, len1
) == 0)
664 strcat (result
, "operator");
665 strcat (result
, optable
[i
].out
);
666 strcat (result
, "=");
675 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
678 if ((int) strlen (optable
[i
].in
) == len1
679 && memcmp (optable
[i
].in
, opname
+ 3, len1
) == 0)
681 strcat (result
, "operator");
682 strcat (result
, optable
[i
].out
);
689 else if (len
>= 5 && memcmp (opname
, "type", 4) == 0
690 && strchr (cplus_markers
, opname
[4]) != NULL
)
692 /* type conversion operator */
694 if (do_type (work
, &tem
, &type
))
696 strcat (result
, "operator ");
697 strncat (result
, type
.b
, type
.p
- type
.b
);
698 string_delete (&type
);
702 squangle_mop_up (work
);
706 /* Takes operator name as e.g. "++" and returns mangled
707 operator name (e.g. "postincrement_expr"), or NULL if not found.
709 If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
710 if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */
713 cplus_mangle_opname (opname
, options
)
720 len
= strlen (opname
);
721 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
723 if ((int) strlen (optable
[i
].out
) == len
724 && (options
& DMGL_ANSI
) == (optable
[i
].flags
& DMGL_ANSI
)
725 && memcmp (optable
[i
].out
, opname
, len
) == 0)
726 return optable
[i
].in
;
731 /* char *cplus_demangle (const char *mangled, int options)
733 If MANGLED is a mangled function name produced by GNU C++, then
734 a pointer to a malloced string giving a C++ representation
735 of the name will be returned; otherwise NULL will be returned.
736 It is the caller's responsibility to free the string which
739 The OPTIONS arg may contain one or more of the following bits:
741 DMGL_ANSI ANSI qualifiers such as `const' and `void' are
743 DMGL_PARAMS Function parameters are included.
747 cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)"
748 cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
749 cplus_demangle ("foo__1Ai", 0) => "A::foo"
751 cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)"
752 cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
753 cplus_demangle ("foo__1Afe", 0) => "A::foo"
755 Note that any leading underscores, or other such characters prepended by
756 the compilation system, are presumed to have already been stripped from
760 cplus_demangle (mangled
, options
)
765 struct work_stuff work
[1];
766 memset ((char *) work
, 0, sizeof (work
));
767 work
-> options
= options
;
768 if ((work
-> options
& DMGL_STYLE_MASK
) == 0)
769 work
-> options
|= (int) current_demangling_style
& DMGL_STYLE_MASK
;
771 ret
= internal_cplus_demangle (work
, mangled
);
772 squangle_mop_up (work
);
777 /* This function performs most of what cplus_demangle use to do, but
778 to be able to demangle a name with a B, K or n code, we need to
779 have a longer term memory of what types have been seen. The original
780 now intializes and cleans up the squangle code info, while internal
781 calls go directly to this routine to avoid resetting that info. */
784 internal_cplus_demangle (work
, mangled
)
785 struct work_stuff
*work
;
791 char *demangled
= NULL
;
793 s1
= work
->constructor
;
794 s2
= work
->destructor
;
795 s3
= work
->static_type
;
796 s4
= work
->type_quals
;
797 work
->constructor
= work
->destructor
= 0;
798 work
->type_quals
= TYPE_UNQUALIFIED
;
799 work
->dllimported
= 0;
801 if ((mangled
!= NULL
) && (*mangled
!= '\0'))
805 /* First check to see if gnu style demangling is active and if the
806 string to be demangled contains a CPLUS_MARKER. If so, attempt to
807 recognize one of the gnu special forms rather than looking for a
808 standard prefix. In particular, don't worry about whether there
809 is a "__" string in the mangled string. Consider "_$_5__foo" for
812 if ((AUTO_DEMANGLING
|| GNU_DEMANGLING
))
814 success
= gnu_special (work
, &mangled
, &decl
);
818 success
= demangle_prefix (work
, &mangled
, &decl
);
820 if (success
&& (*mangled
!= '\0'))
822 success
= demangle_signature (work
, &mangled
, &decl
);
824 if (work
->constructor
== 2)
826 string_prepend (&decl
, "global constructors keyed to ");
827 work
->constructor
= 0;
829 else if (work
->destructor
== 2)
831 string_prepend (&decl
, "global destructors keyed to ");
832 work
->destructor
= 0;
834 else if (work
->dllimported
== 1)
836 string_prepend (&decl
, "import stub for ");
837 work
->dllimported
= 0;
839 demangled
= mop_up (work
, &decl
, success
);
841 work
->constructor
= s1
;
842 work
->destructor
= s2
;
843 work
->static_type
= s3
;
844 work
->type_quals
= s4
;
849 /* Clear out and squangling related storage */
851 squangle_mop_up (work
)
852 struct work_stuff
*work
;
854 /* clean up the B and K type mangling types. */
855 forget_B_and_K_types (work
);
856 if (work
-> btypevec
!= NULL
)
858 free ((char *) work
-> btypevec
);
860 if (work
-> ktypevec
!= NULL
)
862 free ((char *) work
-> ktypevec
);
866 /* Clear out any mangled storage */
869 mop_up (work
, declp
, success
)
870 struct work_stuff
*work
;
874 char *demangled
= NULL
;
876 /* Discard the remembered types, if any. */
879 if (work
-> typevec
!= NULL
)
881 free ((char *) work
-> typevec
);
882 work
-> typevec
= NULL
;
883 work
-> typevec_size
= 0;
885 if (work
->tmpl_argvec
)
889 for (i
= 0; i
< work
->ntmpl_args
; i
++)
890 if (work
->tmpl_argvec
[i
])
891 free ((char*) work
->tmpl_argvec
[i
]);
893 free ((char*) work
->tmpl_argvec
);
894 work
->tmpl_argvec
= NULL
;
896 if (work
->previous_argument
)
898 string_delete (work
->previous_argument
);
899 free ((char*) work
->previous_argument
);
900 work
->previous_argument
= NULL
;
903 /* If demangling was successful, ensure that the demangled string is null
904 terminated and return it. Otherwise, free the demangling decl. */
908 string_delete (declp
);
912 string_appendn (declp
, "", 1);
913 demangled
= declp
-> b
;
922 demangle_signature -- demangle the signature part of a mangled name
927 demangle_signature (struct work_stuff *work, const char **mangled,
932 Consume and demangle the signature portion of the mangled name.
934 DECLP is the string where demangled output is being built. At
935 entry it contains the demangled root name from the mangled name
936 prefix. I.E. either a demangled operator name or the root function
937 name. In some special cases, it may contain nothing.
939 *MANGLED points to the current unconsumed location in the mangled
940 name. As tokens are consumed and demangling is performed, the
941 pointer is updated to continuously point at the next token to
944 Demangling GNU style mangled names is nasty because there is no
945 explicit token that marks the start of the outermost function
949 demangle_signature (work
, mangled
, declp
)
950 struct work_stuff
*work
;
951 const char **mangled
;
957 int expect_return_type
= 0;
958 const char *oldmangled
= NULL
;
962 while (success
&& (**mangled
!= '\0'))
967 oldmangled
= *mangled
;
968 success
= demangle_qualified (work
, mangled
, declp
, 1, 0);
970 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
971 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
977 oldmangled
= *mangled
;
978 success
= demangle_qualified (work
, mangled
, declp
, 1, 0);
979 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
987 /* Static member function */
988 if (oldmangled
== NULL
)
990 oldmangled
= *mangled
;
993 work
-> static_type
= 1;
999 work
->type_quals
|= code_for_qualifier (**mangled
);
1001 /* a qualified member function */
1002 if (oldmangled
== NULL
)
1003 oldmangled
= *mangled
;
1008 /* Local class name follows after "Lnnn_" */
1011 while (**mangled
&& (**mangled
!= '_'))
1022 case '0': case '1': case '2': case '3': case '4':
1023 case '5': case '6': case '7': case '8': case '9':
1024 if (oldmangled
== NULL
)
1026 oldmangled
= *mangled
;
1028 work
->temp_start
= -1; /* uppermost call to demangle_class */
1029 success
= demangle_class (work
, mangled
, declp
);
1032 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
1034 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
|| EDG_DEMANGLING
)
1036 /* EDG and others will have the "F", so we let the loop cycle
1037 if we are looking at one. */
1038 if (**mangled
!= 'F')
1047 success
= do_type (work
, mangled
, &s
);
1050 string_append (&s
, SCOPE_STRING (work
));
1051 string_prepends (declp
, &s
);
1060 /* ARM/HP style demangling includes a specific 'F' character after
1061 the class name. For GNU style, it is just implied. So we can
1062 safely just consume any 'F' at this point and be compatible
1063 with either style. */
1069 /* For lucid/ARM/HP style we have to forget any types we might
1070 have remembered up to this point, since they were not argument
1071 types. GNU style considers all types seen as available for
1072 back references. See comment in demangle_args() */
1074 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
|| HP_DEMANGLING
|| EDG_DEMANGLING
)
1076 forget_types (work
);
1078 success
= demangle_args (work
, mangled
, declp
);
1079 /* After picking off the function args, we expect to either
1080 find the function return type (preceded by an '_') or the
1081 end of the string. */
1082 if (success
&& (AUTO_DEMANGLING
|| EDG_DEMANGLING
) && **mangled
== '_')
1085 /* At this level, we do not care about the return type. */
1086 success
= do_type (work
, mangled
, &tname
);
1087 string_delete (&tname
);
1094 string_init(&trawname
);
1095 string_init(&tname
);
1096 if (oldmangled
== NULL
)
1098 oldmangled
= *mangled
;
1100 success
= demangle_template (work
, mangled
, &tname
,
1104 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
1106 string_append (&tname
, SCOPE_STRING (work
));
1108 string_prepends(declp
, &tname
);
1109 if (work
-> destructor
& 1)
1111 string_prepend (&trawname
, "~");
1112 string_appends (declp
, &trawname
);
1113 work
->destructor
-= 1;
1115 if ((work
->constructor
& 1) || (work
->destructor
& 1))
1117 string_appends (declp
, &trawname
);
1118 work
->constructor
-= 1;
1120 string_delete(&trawname
);
1121 string_delete(&tname
);
1127 if (GNU_DEMANGLING
&& expect_return_type
)
1129 /* Read the return type. */
1131 string_init (&return_type
);
1134 success
= do_type (work
, mangled
, &return_type
);
1135 APPEND_BLANK (&return_type
);
1137 string_prepends (declp
, &return_type
);
1138 string_delete (&return_type
);
1142 /* At the outermost level, we cannot have a return type specified,
1143 so if we run into another '_' at this point we are dealing with
1144 a mangled name that is either bogus, or has been mangled by
1145 some algorithm we don't know how to deal with. So just
1146 reject the entire demangling. */
1147 /* However, "_nnn" is an expected suffix for alternate entry point
1148 numbered nnn for a function, with HP aCC, so skip over that
1149 without reporting failure. pai/1997-09-04 */
1153 while (**mangled
&& isdigit ((unsigned char)**mangled
))
1163 /* A G++ template function. Read the template arguments. */
1164 success
= demangle_template (work
, mangled
, declp
, 0, 0,
1166 if (!(work
->constructor
& 1))
1167 expect_return_type
= 1;
1176 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
1178 /* Assume we have stumbled onto the first outermost function
1179 argument token, and start processing args. */
1181 success
= demangle_args (work
, mangled
, declp
);
1185 /* Non-GNU demanglers use a specific token to mark the start
1186 of the outermost function argument tokens. Typically 'F',
1187 for ARM/HP-demangling, for example. So if we find something
1188 we are not prepared for, it must be an error. */
1194 if (AUTO_DEMANGLING || GNU_DEMANGLING)
1197 if (success
&& expect_func
)
1200 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
|| EDG_DEMANGLING
)
1202 forget_types (work
);
1204 success
= demangle_args (work
, mangled
, declp
);
1205 /* Since template include the mangling of their return types,
1206 we must set expect_func to 0 so that we don't try do
1207 demangle more arguments the next time we get here. */
1212 if (success
&& !func_done
)
1214 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
1216 /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
1217 bar__3fooi is 'foo::bar(int)'. We get here when we find the
1218 first case, and need to ensure that the '(void)' gets added to
1219 the current declp. Note that with ARM/HP, the first case
1220 represents the name of a static data member 'foo::bar',
1221 which is in the current declp, so we leave it alone. */
1222 success
= demangle_args (work
, mangled
, declp
);
1225 if (success
&& PRINT_ARG_TYPES
)
1227 if (work
->static_type
)
1228 string_append (declp
, " static");
1229 if (work
->type_quals
!= TYPE_UNQUALIFIED
)
1231 APPEND_BLANK (declp
);
1232 string_append (declp
, qualifier_string (work
->type_quals
));
1242 demangle_method_args (work
, mangled
, declp
)
1243 struct work_stuff
*work
;
1244 const char **mangled
;
1249 if (work
-> static_type
)
1251 string_append (declp
, *mangled
+ 1);
1252 *mangled
+= strlen (*mangled
);
1257 success
= demangle_args (work
, mangled
, declp
);
1265 demangle_template_template_parm (work
, mangled
, tname
)
1266 struct work_stuff
*work
;
1267 const char **mangled
;
1276 string_append (tname
, "template <");
1277 /* get size of template parameter list */
1278 if (get_count (mangled
, &r
))
1280 for (i
= 0; i
< r
; i
++)
1284 string_append (tname
, ", ");
1287 /* Z for type parameters */
1288 if (**mangled
== 'Z')
1291 string_append (tname
, "class");
1293 /* z for template parameters */
1294 else if (**mangled
== 'z')
1298 demangle_template_template_parm (work
, mangled
, tname
);
1306 /* temp is initialized in do_type */
1307 success
= do_type (work
, mangled
, &temp
);
1310 string_appends (tname
, &temp
);
1312 string_delete(&temp
);
1322 if (tname
->p
[-1] == '>')
1323 string_append (tname
, " ");
1324 string_append (tname
, "> class");
1329 demangle_integral_value (work
, mangled
, s
)
1330 struct work_stuff
*work
;
1331 const char** mangled
;
1336 if (**mangled
== 'E')
1338 int need_operator
= 0;
1341 string_appendn (s
, "(", 1);
1343 while (success
&& **mangled
!= 'W' && **mangled
!= '\0')
1352 len
= strlen (*mangled
);
1355 i
< sizeof (optable
) / sizeof (optable
[0]);
1358 size_t l
= strlen (optable
[i
].in
);
1361 && memcmp (optable
[i
].in
, *mangled
, l
) == 0)
1363 string_appendn (s
, " ", 1);
1364 string_append (s
, optable
[i
].out
);
1365 string_appendn (s
, " ", 1);
1378 success
= demangle_template_value_parm (work
, mangled
, s
,
1382 if (**mangled
!= 'W')
1386 string_appendn (s
, ")", 1);
1390 else if (**mangled
== 'Q' || **mangled
== 'K')
1391 success
= demangle_qualified (work
, mangled
, s
, 0, 1);
1396 if (**mangled
== 'm')
1398 string_appendn (s
, "-", 1);
1401 while (isdigit ((unsigned char)**mangled
))
1403 string_appendn (s
, *mangled
, 1);
1413 demangle_template_value_parm (work
, mangled
, s
, tk
)
1414 struct work_stuff
*work
;
1415 const char **mangled
;
1421 if (**mangled
== 'Y')
1423 /* The next argument is a template parameter. */
1427 idx
= consume_count_with_underscores (mangled
);
1429 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
1430 || consume_count_with_underscores (mangled
) == -1)
1432 if (work
->tmpl_argvec
)
1433 string_append (s
, work
->tmpl_argvec
[idx
]);
1437 sprintf(buf
, "T%d", idx
);
1438 string_append (s
, buf
);
1441 else if (tk
== tk_integral
)
1442 success
= demangle_integral_value (work
, mangled
, s
);
1443 else if (tk
== tk_char
)
1447 if (**mangled
== 'm')
1449 string_appendn (s
, "-", 1);
1452 string_appendn (s
, "'", 1);
1453 val
= consume_count(mangled
);
1460 string_appendn (s
, &tmp
[0], 1);
1461 string_appendn (s
, "'", 1);
1464 else if (tk
== tk_bool
)
1466 int val
= consume_count (mangled
);
1468 string_appendn (s
, "false", 5);
1470 string_appendn (s
, "true", 4);
1474 else if (tk
== tk_real
)
1476 if (**mangled
== 'm')
1478 string_appendn (s
, "-", 1);
1481 while (isdigit ((unsigned char)**mangled
))
1483 string_appendn (s
, *mangled
, 1);
1486 if (**mangled
== '.') /* fraction */
1488 string_appendn (s
, ".", 1);
1490 while (isdigit ((unsigned char)**mangled
))
1492 string_appendn (s
, *mangled
, 1);
1496 if (**mangled
== 'e') /* exponent */
1498 string_appendn (s
, "e", 1);
1500 while (isdigit ((unsigned char)**mangled
))
1502 string_appendn (s
, *mangled
, 1);
1507 else if (tk
== tk_pointer
|| tk
== tk_reference
)
1509 if (**mangled
== 'Q')
1510 success
= demangle_qualified (work
, mangled
, s
,
1515 int symbol_len
= consume_count (mangled
);
1516 if (symbol_len
== -1)
1518 if (symbol_len
== 0)
1519 string_appendn (s
, "0", 1);
1522 char *p
= xmalloc (symbol_len
+ 1), *q
;
1523 strncpy (p
, *mangled
, symbol_len
);
1524 p
[symbol_len
] = '\0';
1525 /* We use cplus_demangle here, rather than
1526 internal_cplus_demangle, because the name of the entity
1527 mangled here does not make use of any of the squangling
1528 or type-code information we have built up thus far; it is
1529 mangled independently. */
1530 q
= cplus_demangle (p
, work
->options
);
1531 if (tk
== tk_pointer
)
1532 string_appendn (s
, "&", 1);
1533 /* FIXME: Pointer-to-member constants should get a
1534 qualifying class name here. */
1537 string_append (s
, q
);
1541 string_append (s
, p
);
1544 *mangled
+= symbol_len
;
1551 /* Demangle the template name in MANGLED. The full name of the
1552 template (e.g., S<int>) is placed in TNAME. The name without the
1553 template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is
1554 non-NULL. If IS_TYPE is nonzero, this template is a type template,
1555 not a function template. If both IS_TYPE and REMEMBER are nonzero,
1556 the tmeplate is remembered in the list of back-referenceable
1560 demangle_template (work
, mangled
, tname
, trawname
, is_type
, remember
)
1561 struct work_stuff
*work
;
1562 const char **mangled
;
1573 int is_java_array
= 0;
1581 bindex
= register_Btype (work
);
1583 /* get template name */
1584 if (**mangled
== 'z')
1590 idx
= consume_count_with_underscores (mangled
);
1592 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
1593 || consume_count_with_underscores (mangled
) == -1)
1596 if (work
->tmpl_argvec
)
1598 string_append (tname
, work
->tmpl_argvec
[idx
]);
1600 string_append (trawname
, work
->tmpl_argvec
[idx
]);
1605 sprintf(buf
, "T%d", idx
);
1606 string_append (tname
, buf
);
1608 string_append (trawname
, buf
);
1613 if ((r
= consume_count (mangled
)) <= 0
1614 || (int) strlen (*mangled
) < r
)
1618 is_java_array
= (work
-> options
& DMGL_JAVA
)
1619 && strncmp (*mangled
, "JArray1Z", 8) == 0;
1620 if (! is_java_array
)
1622 string_appendn (tname
, *mangled
, r
);
1625 string_appendn (trawname
, *mangled
, r
);
1630 string_append (tname
, "<");
1631 /* get size of template parameter list */
1632 if (!get_count (mangled
, &r
))
1638 /* Create an array for saving the template argument values. */
1639 work
->tmpl_argvec
= (char**) xmalloc (r
* sizeof (char *));
1640 work
->ntmpl_args
= r
;
1641 for (i
= 0; i
< r
; i
++)
1642 work
->tmpl_argvec
[i
] = 0;
1644 for (i
= 0; i
< r
; i
++)
1648 string_append (tname
, ", ");
1650 /* Z for type parameters */
1651 if (**mangled
== 'Z')
1654 /* temp is initialized in do_type */
1655 success
= do_type (work
, mangled
, &temp
);
1658 string_appends (tname
, &temp
);
1662 /* Save the template argument. */
1663 int len
= temp
.p
- temp
.b
;
1664 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1665 memcpy (work
->tmpl_argvec
[i
], temp
.b
, len
);
1666 work
->tmpl_argvec
[i
][len
] = '\0';
1669 string_delete(&temp
);
1675 /* z for template parameters */
1676 else if (**mangled
== 'z')
1680 success
= demangle_template_template_parm (work
, mangled
, tname
);
1683 && (r2
= consume_count (mangled
)) > 0
1684 && (int) strlen (*mangled
) >= r2
)
1686 string_append (tname
, " ");
1687 string_appendn (tname
, *mangled
, r2
);
1690 /* Save the template argument. */
1692 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1693 memcpy (work
->tmpl_argvec
[i
], *mangled
, len
);
1694 work
->tmpl_argvec
[i
][len
] = '\0';
1708 /* otherwise, value parameter */
1710 /* temp is initialized in do_type */
1711 success
= do_type (work
, mangled
, &temp
);
1712 string_delete(&temp
);
1724 success
= demangle_template_value_parm (work
, mangled
, s
,
1725 (type_kind_t
) success
);
1737 int len
= s
->p
- s
->b
;
1738 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1739 memcpy (work
->tmpl_argvec
[i
], s
->b
, len
);
1740 work
->tmpl_argvec
[i
][len
] = '\0';
1742 string_appends (tname
, s
);
1750 string_append (tname
, "[]");
1754 if (tname
->p
[-1] == '>')
1755 string_append (tname
, " ");
1756 string_append (tname
, ">");
1759 if (is_type
&& remember
)
1760 remember_Btype (work
, tname
->b
, LEN_STRING (tname
), bindex
);
1763 if (work -> static_type)
1765 string_append (declp, *mangled + 1);
1766 *mangled += strlen (*mangled);
1771 success = demangle_args (work, mangled, declp);
1779 arm_pt (work
, mangled
, n
, anchor
, args
)
1780 struct work_stuff
*work
;
1781 const char *mangled
;
1783 const char **anchor
, **args
;
1785 /* Check if ARM template with "__pt__" in it ("parameterized type") */
1786 /* Allow HP also here, because HP's cfront compiler follows ARM to some extent */
1787 if ((ARM_DEMANGLING
|| HP_DEMANGLING
) && (*anchor
= mystrstr (mangled
, "__pt__")))
1790 *args
= *anchor
+ 6;
1791 len
= consume_count (args
);
1794 if (*args
+ len
== mangled
+ n
&& **args
== '_')
1800 if (AUTO_DEMANGLING
|| EDG_DEMANGLING
)
1802 if ((*anchor
= mystrstr (mangled
, "__tm__"))
1803 || (*anchor
= mystrstr (mangled
, "__ps__"))
1804 || (*anchor
= mystrstr (mangled
, "__pt__")))
1807 *args
= *anchor
+ 6;
1808 len
= consume_count (args
);
1811 if (*args
+ len
== mangled
+ n
&& **args
== '_')
1817 else if ((*anchor
= mystrstr (mangled
, "__S")))
1820 *args
= *anchor
+ 3;
1821 len
= consume_count (args
);
1824 if (*args
+ len
== mangled
+ n
&& **args
== '_')
1836 demangle_arm_hp_template (work
, mangled
, n
, declp
)
1837 struct work_stuff
*work
;
1838 const char **mangled
;
1844 const char *e
= *mangled
+ n
;
1847 /* Check for HP aCC template spec: classXt1t2 where t1, t2 are
1849 if (HP_DEMANGLING
&& ((*mangled
)[n
] == 'X'))
1851 char *start_spec_args
= NULL
;
1853 /* First check for and omit template specialization pseudo-arguments,
1854 such as in "Spec<#1,#1.*>" */
1855 start_spec_args
= strchr (*mangled
, '<');
1856 if (start_spec_args
&& (start_spec_args
- *mangled
< n
))
1857 string_appendn (declp
, *mangled
, start_spec_args
- *mangled
);
1859 string_appendn (declp
, *mangled
, n
);
1860 (*mangled
) += n
+ 1;
1862 if (work
->temp_start
== -1) /* non-recursive call */
1863 work
->temp_start
= declp
->p
- declp
->b
;
1864 string_append (declp
, "<");
1867 string_clear (&arg
);
1871 /* 'T' signals a type parameter */
1873 if (!do_type (work
, mangled
, &arg
))
1874 goto hpacc_template_args_done
;
1879 /* 'U' or 'S' signals an integral value */
1880 if (!do_hpacc_template_const_value (work
, mangled
, &arg
))
1881 goto hpacc_template_args_done
;
1885 /* 'A' signals a named constant expression (literal) */
1886 if (!do_hpacc_template_literal (work
, mangled
, &arg
))
1887 goto hpacc_template_args_done
;
1891 /* Today, 1997-09-03, we have only the above types
1892 of template parameters */
1893 /* FIXME: maybe this should fail and return null */
1894 goto hpacc_template_args_done
;
1896 string_appends (declp
, &arg
);
1897 /* Check if we're at the end of template args.
1898 0 if at end of static member of template class,
1899 _ if done with template args for a function */
1900 if ((**mangled
== '\000') || (**mangled
== '_'))
1903 string_append (declp
, ",");
1905 hpacc_template_args_done
:
1906 string_append (declp
, ">");
1907 string_delete (&arg
);
1908 if (**mangled
== '_')
1912 /* ARM template? (Also handles HP cfront extensions) */
1913 else if (arm_pt (work
, *mangled
, n
, &p
, &args
))
1918 string_appendn (declp
, *mangled
, p
- *mangled
);
1919 if (work
->temp_start
== -1) /* non-recursive call */
1920 work
->temp_start
= declp
->p
- declp
->b
;
1921 string_append (declp
, "<");
1922 /* should do error checking here */
1924 string_clear (&arg
);
1926 /* Check for type or literal here */
1929 /* HP cfront extensions to ARM for template args */
1930 /* spec: Xt1Lv1 where t1 is a type, v1 is a literal value */
1931 /* FIXME: We handle only numeric literals for HP cfront */
1933 /* A typed constant value follows */
1935 if (!do_type (work
, &args
, &type_str
))
1936 goto cfront_template_args_done
;
1937 string_append (&arg
, "(");
1938 string_appends (&arg
, &type_str
);
1939 string_append (&arg
, ")");
1941 goto cfront_template_args_done
;
1943 /* Now snarf a literal value following 'L' */
1944 if (!snarf_numeric_literal (&args
, &arg
))
1945 goto cfront_template_args_done
;
1949 /* Snarf a literal following 'L' */
1951 if (!snarf_numeric_literal (&args
, &arg
))
1952 goto cfront_template_args_done
;
1955 /* Not handling other HP cfront stuff */
1956 if (!do_type (work
, &args
, &arg
))
1957 goto cfront_template_args_done
;
1959 string_appends (declp
, &arg
);
1960 string_append (declp
, ",");
1962 cfront_template_args_done
:
1963 string_delete (&arg
);
1965 --declp
->p
; /* remove extra comma */
1966 string_append (declp
, ">");
1968 else if (n
>10 && strncmp (*mangled
, "_GLOBAL_", 8) == 0
1969 && (*mangled
)[9] == 'N'
1970 && (*mangled
)[8] == (*mangled
)[10]
1971 && strchr (cplus_markers
, (*mangled
)[8]))
1973 /* A member of the anonymous namespace. */
1974 string_append (declp
, "{anonymous}");
1978 if (work
->temp_start
== -1) /* non-recursive call only */
1979 work
->temp_start
= 0; /* disable in recursive calls */
1980 string_appendn (declp
, *mangled
, n
);
1985 /* Extract a class name, possibly a template with arguments, from the
1986 mangled string; qualifiers, local class indicators, etc. have
1987 already been dealt with */
1990 demangle_class_name (work
, mangled
, declp
)
1991 struct work_stuff
*work
;
1992 const char **mangled
;
1998 n
= consume_count (mangled
);
2001 if ((int) strlen (*mangled
) >= n
)
2003 demangle_arm_hp_template (work
, mangled
, n
, declp
);
2014 demangle_class -- demangle a mangled class sequence
2019 demangle_class (struct work_stuff *work, const char **mangled,
2024 DECLP points to the buffer into which demangling is being done.
2026 *MANGLED points to the current token to be demangled. On input,
2027 it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
2028 On exit, it points to the next token after the mangled class on
2029 success, or the first unconsumed token on failure.
2031 If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
2032 we are demangling a constructor or destructor. In this case
2033 we prepend "class::class" or "class::~class" to DECLP.
2035 Otherwise, we prepend "class::" to the current DECLP.
2037 Reset the constructor/destructor flags once they have been
2038 "consumed". This allows demangle_class to be called later during
2039 the same demangling, to do normal class demangling.
2041 Returns 1 if demangling is successful, 0 otherwise.
2046 demangle_class (work
, mangled
, declp
)
2047 struct work_stuff
*work
;
2048 const char **mangled
;
2054 char *save_class_name_end
= 0;
2056 string_init (&class_name
);
2057 btype
= register_Btype (work
);
2058 if (demangle_class_name (work
, mangled
, &class_name
))
2060 save_class_name_end
= class_name
.p
;
2061 if ((work
->constructor
& 1) || (work
->destructor
& 1))
2063 /* adjust so we don't include template args */
2064 if (work
->temp_start
&& (work
->temp_start
!= -1))
2066 class_name
.p
= class_name
.b
+ work
->temp_start
;
2068 string_prepends (declp
, &class_name
);
2069 if (work
-> destructor
& 1)
2071 string_prepend (declp
, "~");
2072 work
-> destructor
-= 1;
2076 work
-> constructor
-= 1;
2079 class_name
.p
= save_class_name_end
;
2080 remember_Ktype (work
, class_name
.b
, LEN_STRING(&class_name
));
2081 remember_Btype (work
, class_name
.b
, LEN_STRING(&class_name
), btype
);
2082 string_prepend (declp
, SCOPE_STRING (work
));
2083 string_prepends (declp
, &class_name
);
2086 string_delete (&class_name
);
2094 demangle_prefix -- consume the mangled name prefix and find signature
2099 demangle_prefix (struct work_stuff *work, const char **mangled,
2104 Consume and demangle the prefix of the mangled name.
2106 DECLP points to the string buffer into which demangled output is
2107 placed. On entry, the buffer is empty. On exit it contains
2108 the root function name, the demangled operator name, or in some
2109 special cases either nothing or the completely demangled result.
2111 MANGLED points to the current pointer into the mangled name. As each
2112 token of the mangled name is consumed, it is updated. Upon entry
2113 the current mangled name pointer points to the first character of
2114 the mangled name. Upon exit, it should point to the first character
2115 of the signature if demangling was successful, or to the first
2116 unconsumed character if demangling of the prefix was unsuccessful.
2118 Returns 1 on success, 0 otherwise.
2122 demangle_prefix (work
, mangled
, declp
)
2123 struct work_stuff
*work
;
2124 const char **mangled
;
2131 if (strlen(*mangled
) > 6
2132 && (strncmp(*mangled
, "_imp__", 6) == 0
2133 || strncmp(*mangled
, "__imp_", 6) == 0))
2135 /* it's a symbol imported from a PE dynamic library. Check for both
2136 new style prefix _imp__ and legacy __imp_ used by older versions
2139 work
->dllimported
= 1;
2141 else if (strlen(*mangled
) >= 11 && strncmp(*mangled
, "_GLOBAL_", 8) == 0)
2143 char *marker
= strchr (cplus_markers
, (*mangled
)[8]);
2144 if (marker
!= NULL
&& *marker
== (*mangled
)[10])
2146 if ((*mangled
)[9] == 'D')
2148 /* it's a GNU global destructor to be executed at program exit */
2150 work
->destructor
= 2;
2151 if (gnu_special (work
, mangled
, declp
))
2154 else if ((*mangled
)[9] == 'I')
2156 /* it's a GNU global constructor to be executed at program init */
2158 work
->constructor
= 2;
2159 if (gnu_special (work
, mangled
, declp
))
2164 else if ((ARM_DEMANGLING
|| HP_DEMANGLING
|| EDG_DEMANGLING
) && strncmp(*mangled
, "__std__", 7) == 0)
2166 /* it's a ARM global destructor to be executed at program exit */
2168 work
->destructor
= 2;
2170 else if ((ARM_DEMANGLING
|| HP_DEMANGLING
|| EDG_DEMANGLING
) && strncmp(*mangled
, "__sti__", 7) == 0)
2172 /* it's a ARM global constructor to be executed at program initial */
2174 work
->constructor
= 2;
2177 /* This block of code is a reduction in strength time optimization
2179 scan = mystrstr (*mangled, "__"); */
2185 scan
= strchr (scan
, '_');
2186 } while (scan
!= NULL
&& *++scan
!= '_');
2188 if (scan
!= NULL
) --scan
;
2193 /* We found a sequence of two or more '_', ensure that we start at
2194 the last pair in the sequence. */
2195 i
= strspn (scan
, "_");
2206 else if (work
-> static_type
)
2208 if (!isdigit ((unsigned char)scan
[0]) && (scan
[0] != 't'))
2213 else if ((scan
== *mangled
)
2214 && (isdigit ((unsigned char)scan
[2]) || (scan
[2] == 'Q')
2215 || (scan
[2] == 't') || (scan
[2] == 'K') || (scan
[2] == 'H')))
2217 /* The ARM says nothing about the mangling of local variables.
2218 But cfront mangles local variables by prepending __<nesting_level>
2219 to them. As an extension to ARM demangling we handle this case. */
2220 if ((LUCID_DEMANGLING
|| ARM_DEMANGLING
|| HP_DEMANGLING
)
2221 && isdigit ((unsigned char)scan
[2]))
2223 *mangled
= scan
+ 2;
2224 consume_count (mangled
);
2225 string_append (declp
, *mangled
);
2226 *mangled
+= strlen (*mangled
);
2231 /* A GNU style constructor starts with __[0-9Qt]. But cfront uses
2232 names like __Q2_3foo3bar for nested type names. So don't accept
2233 this style of constructor for cfront demangling. A GNU
2234 style member-template constructor starts with 'H'. */
2235 if (!(LUCID_DEMANGLING
|| ARM_DEMANGLING
|| HP_DEMANGLING
|| EDG_DEMANGLING
))
2236 work
-> constructor
+= 1;
2237 *mangled
= scan
+ 2;
2240 else if (ARM_DEMANGLING
&& scan
[2] == 'p' && scan
[3] == 't')
2242 /* Cfront-style parameterized type. Handled later as a signature. */
2246 demangle_arm_hp_template (work
, mangled
, strlen (*mangled
), declp
);
2248 else if (EDG_DEMANGLING
&& ((scan
[2] == 't' && scan
[3] == 'm')
2249 || (scan
[2] == 'p' && scan
[3] == 's')
2250 || (scan
[2] == 'p' && scan
[3] == 't')))
2252 /* EDG-style parameterized type. Handled later as a signature. */
2256 demangle_arm_hp_template (work
, mangled
, strlen (*mangled
), declp
);
2258 else if ((scan
== *mangled
) && !isdigit ((unsigned char)scan
[2])
2259 && (scan
[2] != 't'))
2261 /* Mangled name starts with "__". Skip over any leading '_' characters,
2262 then find the next "__" that separates the prefix from the signature.
2264 if (!(ARM_DEMANGLING
|| LUCID_DEMANGLING
|| HP_DEMANGLING
|| EDG_DEMANGLING
)
2265 || (arm_special (mangled
, declp
) == 0))
2267 while (*scan
== '_')
2271 if ((scan
= mystrstr (scan
, "__")) == NULL
|| (*(scan
+ 2) == '\0'))
2273 /* No separator (I.E. "__not_mangled"), or empty signature
2274 (I.E. "__not_mangled_either__") */
2281 /* Look for the LAST occurrence of __, allowing names to
2282 have the '__' sequence embedded in them. */
2283 if (!(ARM_DEMANGLING
|| HP_DEMANGLING
))
2285 while ((tmp
= mystrstr (scan
+ 2, "__")) != NULL
)
2288 if (*(scan
+ 2) == '\0')
2291 demangle_function_name (work
, mangled
, declp
, scan
);
2295 else if (*(scan
+ 2) != '\0')
2297 /* Mangled name does not start with "__" but does have one somewhere
2298 in there with non empty stuff after it. Looks like a global
2300 demangle_function_name (work
, mangled
, declp
, scan
);
2304 /* Doesn't look like a mangled name */
2308 if (!success
&& (work
->constructor
== 2 || work
->destructor
== 2))
2310 string_append (declp
, *mangled
);
2311 *mangled
+= strlen (*mangled
);
2321 gnu_special -- special handling of gnu mangled strings
2326 gnu_special (struct work_stuff *work, const char **mangled,
2332 Process some special GNU style mangling forms that don't fit
2333 the normal pattern. For example:
2335 _$_3foo (destructor for class foo)
2336 _vt$foo (foo virtual table)
2337 _vt$foo$bar (foo::bar virtual table)
2338 __vt_foo (foo virtual table, new style with thunks)
2339 _3foo$varname (static data member)
2340 _Q22rs2tu$vw (static data member)
2341 __t6vector1Zii (constructor with template)
2342 __thunk_4__$_7ostream (virtual function thunk)
2346 gnu_special (work
, mangled
, declp
)
2347 struct work_stuff
*work
;
2348 const char **mangled
;
2355 if ((*mangled
)[0] == '_'
2356 && strchr (cplus_markers
, (*mangled
)[1]) != NULL
2357 && (*mangled
)[2] == '_')
2359 /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
2361 work
-> destructor
+= 1;
2363 else if ((*mangled
)[0] == '_'
2364 && (((*mangled
)[1] == '_'
2365 && (*mangled
)[2] == 'v'
2366 && (*mangled
)[3] == 't'
2367 && (*mangled
)[4] == '_')
2368 || ((*mangled
)[1] == 'v'
2369 && (*mangled
)[2] == 't'
2370 && strchr (cplus_markers
, (*mangled
)[3]) != NULL
)))
2372 /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
2373 and create the decl. Note that we consume the entire mangled
2374 input string, which means that demangle_signature has no work
2376 if ((*mangled
)[2] == 'v')
2377 (*mangled
) += 5; /* New style, with thunks: "__vt_" */
2379 (*mangled
) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
2380 while (**mangled
!= '\0')
2386 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
2389 success
= demangle_template (work
, mangled
, declp
, 0, 1,
2393 if (isdigit((unsigned char)*mangled
[0]))
2395 n
= consume_count(mangled
);
2396 /* We may be seeing a too-large size, or else a
2397 ".<digits>" indicating a static local symbol. In
2398 any case, declare victory and move on; *don't* try
2399 to use n to allocate. */
2400 if (n
> (int) strlen (*mangled
))
2408 n
= strcspn (*mangled
, cplus_markers
);
2410 string_appendn (declp
, *mangled
, n
);
2414 p
= strpbrk (*mangled
, cplus_markers
);
2415 if (success
&& ((p
== NULL
) || (p
== *mangled
)))
2419 string_append (declp
, SCOPE_STRING (work
));
2430 string_append (declp
, " virtual table");
2432 else if ((*mangled
)[0] == '_'
2433 && (strchr("0123456789Qt", (*mangled
)[1]) != NULL
)
2434 && (p
= strpbrk (*mangled
, cplus_markers
)) != NULL
)
2436 /* static data member, "_3foo$varname" for example */
2442 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
2445 success
= demangle_template (work
, mangled
, declp
, 0, 1, 1);
2448 n
= consume_count (mangled
);
2449 if (n
< 0 || n
> strlen (*mangled
))
2454 string_appendn (declp
, *mangled
, n
);
2457 if (success
&& (p
== *mangled
))
2459 /* Consumed everything up to the cplus_marker, append the
2462 string_append (declp
, SCOPE_STRING (work
));
2463 n
= strlen (*mangled
);
2464 string_appendn (declp
, *mangled
, n
);
2472 else if (strncmp (*mangled
, "__thunk_", 8) == 0)
2477 delta
= consume_count (mangled
);
2482 char *method
= internal_cplus_demangle (work
, ++*mangled
);
2487 sprintf (buf
, "virtual function thunk (delta:%d) for ", -delta
);
2488 string_append (declp
, buf
);
2489 string_append (declp
, method
);
2491 n
= strlen (*mangled
);
2500 else if (strncmp (*mangled
, "__t", 3) == 0
2501 && ((*mangled
)[3] == 'i' || (*mangled
)[3] == 'f'))
2503 p
= (*mangled
)[3] == 'i' ? " type_info node" : " type_info function";
2509 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
2512 success
= demangle_template (work
, mangled
, declp
, 0, 1, 1);
2515 success
= demangle_fund_type (work
, mangled
, declp
);
2518 if (success
&& **mangled
!= '\0')
2521 string_append (declp
, p
);
2531 recursively_demangle(work
, mangled
, result
, namelength
)
2532 struct work_stuff
*work
;
2533 const char **mangled
;
2537 char * recurse
= (char *)NULL
;
2538 char * recurse_dem
= (char *)NULL
;
2540 recurse
= (char *) xmalloc (namelength
+ 1);
2541 memcpy (recurse
, *mangled
, namelength
);
2542 recurse
[namelength
] = '\000';
2544 recurse_dem
= cplus_demangle (recurse
, work
->options
);
2548 string_append (result
, recurse_dem
);
2553 string_appendn (result
, *mangled
, namelength
);
2556 *mangled
+= namelength
;
2563 arm_special -- special handling of ARM/lucid mangled strings
2568 arm_special (const char **mangled,
2574 Process some special ARM style mangling forms that don't fit
2575 the normal pattern. For example:
2577 __vtbl__3foo (foo virtual table)
2578 __vtbl__3foo__3bar (bar::foo virtual table)
2583 arm_special (mangled
, declp
)
2584 const char **mangled
;
2591 if (strncmp (*mangled
, ARM_VTABLE_STRING
, ARM_VTABLE_STRLEN
) == 0)
2593 /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
2594 and create the decl. Note that we consume the entire mangled
2595 input string, which means that demangle_signature has no work
2597 scan
= *mangled
+ ARM_VTABLE_STRLEN
;
2598 while (*scan
!= '\0') /* first check it can be demangled */
2600 n
= consume_count (&scan
);
2603 return (0); /* no good */
2606 if (scan
[0] == '_' && scan
[1] == '_')
2611 (*mangled
) += ARM_VTABLE_STRLEN
;
2612 while (**mangled
!= '\0')
2614 n
= consume_count (mangled
);
2616 || n
> strlen (*mangled
))
2618 string_prependn (declp
, *mangled
, n
);
2620 if ((*mangled
)[0] == '_' && (*mangled
)[1] == '_')
2622 string_prepend (declp
, "::");
2626 string_append (declp
, " virtual table");
2639 demangle_qualified -- demangle 'Q' qualified name strings
2644 demangle_qualified (struct work_stuff *, const char *mangled,
2645 string *result, int isfuncname, int append);
2649 Demangle a qualified name, such as "Q25Outer5Inner" which is
2650 the mangled form of "Outer::Inner". The demangled output is
2651 prepended or appended to the result string according to the
2652 state of the append flag.
2654 If isfuncname is nonzero, then the qualified name we are building
2655 is going to be used as a member function name, so if it is a
2656 constructor or destructor function, append an appropriate
2657 constructor or destructor name. I.E. for the above example,
2658 the result for use as a constructor is "Outer::Inner::Inner"
2659 and the result for use as a destructor is "Outer::Inner::~Inner".
2663 Numeric conversion is ASCII dependent (FIXME).
2668 demangle_qualified (work
, mangled
, result
, isfuncname
, append
)
2669 struct work_stuff
*work
;
2670 const char **mangled
;
2681 int bindex
= register_Btype (work
);
2683 /* We only make use of ISFUNCNAME if the entity is a constructor or
2685 isfuncname
= (isfuncname
2686 && ((work
->constructor
& 1) || (work
->destructor
& 1)));
2688 string_init (&temp
);
2689 string_init (&last_name
);
2691 if ((*mangled
)[0] == 'K')
2693 /* Squangling qualified name reuse */
2696 idx
= consume_count_with_underscores (mangled
);
2697 if (idx
== -1 || idx
>= work
-> numk
)
2700 string_append (&temp
, work
-> ktypevec
[idx
]);
2703 switch ((*mangled
)[1])
2706 /* GNU mangled name with more than 9 classes. The count is preceded
2707 by an underscore (to distinguish it from the <= 9 case) and followed
2708 by an underscore. */
2710 qualifiers
= atoi (p
);
2711 if (!isdigit ((unsigned char)*p
) || *p
== '0')
2714 /* Skip the digits. */
2715 while (isdigit ((unsigned char)*p
))
2733 /* The count is in a single digit. */
2734 num
[0] = (*mangled
)[1];
2736 qualifiers
= atoi (num
);
2738 /* If there is an underscore after the digit, skip it. This is
2739 said to be for ARM-qualified names, but the ARM makes no
2740 mention of such an underscore. Perhaps cfront uses one. */
2741 if ((*mangled
)[2] == '_')
2756 /* Pick off the names and collect them in the temp buffer in the order
2757 in which they are found, separated by '::'. */
2759 while (qualifiers
-- > 0)
2762 string_clear (&last_name
);
2764 if (*mangled
[0] == '_')
2767 if (*mangled
[0] == 't')
2769 /* Here we always append to TEMP since we will want to use
2770 the template name without the template parameters as a
2771 constructor or destructor name. The appropriate
2772 (parameter-less) value is returned by demangle_template
2773 in LAST_NAME. We do not remember the template type here,
2774 in order to match the G++ mangling algorithm. */
2775 success
= demangle_template(work
, mangled
, &temp
,
2780 else if (*mangled
[0] == 'K')
2784 idx
= consume_count_with_underscores (mangled
);
2785 if (idx
== -1 || idx
>= work
->numk
)
2788 string_append (&temp
, work
->ktypevec
[idx
]);
2791 if (!success
) break;
2798 /* Now recursively demangle the qualifier
2799 * This is necessary to deal with templates in
2800 * mangling styles like EDG */
2801 namelength
= consume_count (mangled
);
2802 if (namelength
== -1)
2807 recursively_demangle(work
, mangled
, &temp
, namelength
);
2811 success
= do_type (work
, mangled
, &last_name
);
2814 string_appends (&temp
, &last_name
);
2819 remember_Ktype (work
, temp
.b
, LEN_STRING (&temp
));
2822 string_append (&temp
, SCOPE_STRING (work
));
2825 remember_Btype (work
, temp
.b
, LEN_STRING (&temp
), bindex
);
2827 /* If we are using the result as a function name, we need to append
2828 the appropriate '::' separated constructor or destructor name.
2829 We do this here because this is the most convenient place, where
2830 we already have a pointer to the name and the length of the name. */
2834 string_append (&temp
, SCOPE_STRING (work
));
2835 if (work
-> destructor
& 1)
2836 string_append (&temp
, "~");
2837 string_appends (&temp
, &last_name
);
2840 /* Now either prepend the temp buffer to the result, or append it,
2841 depending upon the state of the append flag. */
2844 string_appends (result
, &temp
);
2847 if (!STRING_EMPTY (result
))
2848 string_append (&temp
, SCOPE_STRING (work
));
2849 string_prepends (result
, &temp
);
2852 string_delete (&last_name
);
2853 string_delete (&temp
);
2861 get_count -- convert an ascii count to integer, consuming tokens
2866 get_count (const char **type, int *count)
2870 Assume that *type points at a count in a mangled name; set
2871 *count to its value, and set *type to the next character after
2872 the count. There are some weird rules in effect here.
2874 If *type does not point at a string of digits, return zero.
2876 If *type points at a string of digits followed by an
2877 underscore, set *count to their value as an integer, advance
2878 *type to point *after the underscore, and return 1.
2880 If *type points at a string of digits not followed by an
2881 underscore, consume only the first digit. Set *count to its
2882 value as an integer, leave *type pointing after that digit,
2885 The excuse for this odd behavior: in the ARM and HP demangling
2886 styles, a type can be followed by a repeat count of the form
2889 `x' is a single digit specifying how many additional copies
2890 of the type to append to the argument list, and
2892 `y' is one or more digits, specifying the zero-based index of
2893 the first repeated argument in the list. Yes, as you're
2894 unmangling the name you can figure this out yourself, but
2897 So, for example, in `bar__3fooFPiN51', the first argument is a
2898 pointer to an integer (`Pi'), and then the next five arguments
2899 are the same (`N5'), and the first repeat is the function's
2900 second argument (`1').
2904 get_count (type
, count
)
2911 if (!isdigit ((unsigned char)**type
))
2917 *count
= **type
- '0';
2919 if (isdigit ((unsigned char)**type
))
2929 while (isdigit ((unsigned char)*p
));
2940 /* RESULT will be initialised here; it will be freed on failure. The
2941 value returned is really a type_kind_t. */
2944 do_type (work
, mangled
, result
)
2945 struct work_stuff
*work
;
2946 const char **mangled
;
2953 const char *remembered_type
;
2956 type_kind_t tk
= tk_none
;
2958 string_init (&btype
);
2959 string_init (&decl
);
2960 string_init (result
);
2964 while (success
&& !done
)
2970 /* A pointer type */
2974 if (! (work
-> options
& DMGL_JAVA
))
2975 string_prepend (&decl
, "*");
2980 /* A reference type */
2983 string_prepend (&decl
, "&");
2992 if (!STRING_EMPTY (&decl
)
2993 && (decl
.b
[0] == '*' || decl
.b
[0] == '&'))
2995 string_prepend (&decl
, "(");
2996 string_append (&decl
, ")");
2998 string_append (&decl
, "[");
2999 if (**mangled
!= '_')
3000 success
= demangle_template_value_parm (work
, mangled
, &decl
,
3002 if (**mangled
== '_')
3004 string_append (&decl
, "]");
3008 /* A back reference to a previously seen type */
3011 if (!get_count (mangled
, &n
) || n
>= work
-> ntypes
)
3017 remembered_type
= work
-> typevec
[n
];
3018 mangled
= &remembered_type
;
3025 if (!STRING_EMPTY (&decl
)
3026 && (decl
.b
[0] == '*' || decl
.b
[0] == '&'))
3028 string_prepend (&decl
, "(");
3029 string_append (&decl
, ")");
3031 /* After picking off the function args, we expect to either find the
3032 function return type (preceded by an '_') or the end of the
3034 if (!demangle_nested_args (work
, mangled
, &decl
)
3035 || (**mangled
!= '_' && **mangled
!= '\0'))
3040 if (success
&& (**mangled
== '_'))
3047 type_quals
= TYPE_UNQUALIFIED
;
3049 member
= **mangled
== 'M';
3052 string_append (&decl
, ")");
3053 string_prepend (&decl
, SCOPE_STRING (work
));
3054 if (isdigit ((unsigned char)**mangled
))
3056 n
= consume_count (mangled
);
3058 || (int) strlen (*mangled
) < n
)
3063 string_prependn (&decl
, *mangled
, n
);
3066 else if (**mangled
== 'X' || **mangled
== 'Y')
3069 do_type (work
, mangled
, &temp
);
3070 string_prepends (&decl
, &temp
);
3072 else if (**mangled
== 't')
3075 string_init (&temp
);
3076 success
= demangle_template (work
, mangled
, &temp
,
3080 string_prependn (&decl
, temp
.b
, temp
.p
- temp
.b
);
3081 string_clear (&temp
);
3092 string_prepend (&decl
, "(");
3100 type_quals
|= code_for_qualifier (**mangled
);
3108 if (*(*mangled
)++ != 'F')
3114 if ((member
&& !demangle_nested_args (work
, mangled
, &decl
))
3115 || **mangled
!= '_')
3121 if (! PRINT_ANSI_QUALIFIERS
)
3125 if (type_quals
!= TYPE_UNQUALIFIED
)
3127 APPEND_BLANK (&decl
);
3128 string_append (&decl
, qualifier_string (type_quals
));
3139 if (PRINT_ANSI_QUALIFIERS
)
3141 if (!STRING_EMPTY (&decl
))
3142 string_prepend (&decl
, " ");
3144 string_prepend (&decl
, demangle_qualifier (**mangled
));
3159 if (success
) switch (**mangled
)
3161 /* A qualified name, such as "Outer::Inner". */
3165 success
= demangle_qualified (work
, mangled
, result
, 0, 1);
3169 /* A back reference to a previously seen squangled type */
3172 if (!get_count (mangled
, &n
) || n
>= work
-> numb
)
3175 string_append (result
, work
->btypevec
[n
]);
3180 /* A template parm. We substitute the corresponding argument. */
3185 idx
= consume_count_with_underscores (mangled
);
3188 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
3189 || consume_count_with_underscores (mangled
) == -1)
3195 if (work
->tmpl_argvec
)
3196 string_append (result
, work
->tmpl_argvec
[idx
]);
3200 sprintf(buf
, "T%d", idx
);
3201 string_append (result
, buf
);
3209 success
= demangle_fund_type (work
, mangled
, result
);
3211 tk
= (type_kind_t
) success
;
3217 if (!STRING_EMPTY (&decl
))
3219 string_append (result
, " ");
3220 string_appends (result
, &decl
);
3224 string_delete (result
);
3225 string_delete (&decl
);
3228 /* Assume an integral type, if we're not sure. */
3229 return (int) ((tk
== tk_none
) ? tk_integral
: tk
);
3234 /* Given a pointer to a type string that represents a fundamental type
3235 argument (int, long, unsigned int, etc) in TYPE, a pointer to the
3236 string in which the demangled output is being built in RESULT, and
3237 the WORK structure, decode the types and add them to the result.
3242 "Sl" => "signed long"
3243 "CUs" => "const unsigned short"
3245 The value returned is really a type_kind_t. */
3248 demangle_fund_type (work
, mangled
, result
)
3249 struct work_stuff
*work
;
3250 const char **mangled
;
3258 type_kind_t tk
= tk_integral
;
3260 string_init (&btype
);
3262 /* First pick off any type qualifiers. There can be more than one. */
3271 if (PRINT_ANSI_QUALIFIERS
)
3273 if (!STRING_EMPTY (result
))
3274 string_prepend (result
, " ");
3275 string_prepend (result
, demangle_qualifier (**mangled
));
3281 APPEND_BLANK (result
);
3282 string_append (result
, "unsigned");
3284 case 'S': /* signed char only */
3286 APPEND_BLANK (result
);
3287 string_append (result
, "signed");
3291 APPEND_BLANK (result
);
3292 string_append (result
, "__complex");
3300 /* Now pick off the fundamental type. There can be only one. */
3309 APPEND_BLANK (result
);
3310 string_append (result
, "void");
3314 APPEND_BLANK (result
);
3315 string_append (result
, "long long");
3319 APPEND_BLANK (result
);
3320 string_append (result
, "long");
3324 APPEND_BLANK (result
);
3325 string_append (result
, "int");
3329 APPEND_BLANK (result
);
3330 string_append (result
, "short");
3334 APPEND_BLANK (result
);
3335 string_append (result
, "bool");
3340 APPEND_BLANK (result
);
3341 string_append (result
, "char");
3346 APPEND_BLANK (result
);
3347 string_append (result
, "wchar_t");
3352 APPEND_BLANK (result
);
3353 string_append (result
, "long double");
3358 APPEND_BLANK (result
);
3359 string_append (result
, "double");
3364 APPEND_BLANK (result
);
3365 string_append (result
, "float");
3370 if (!isdigit ((unsigned char)**mangled
))
3377 if (**mangled
== '_')
3382 (i
< sizeof (buf
) - 1 && **mangled
&& **mangled
!= '_');
3385 if (**mangled
!= '_')
3395 strncpy (buf
, *mangled
, 2);
3399 sscanf (buf
, "%x", &dec
);
3400 sprintf (buf
, "int%i_t", dec
);
3401 APPEND_BLANK (result
);
3402 string_append (result
, buf
);
3406 /* An explicit type, such as "6mytype" or "7integer" */
3418 int bindex
= register_Btype (work
);
3420 string_init (&btype
);
3421 if (demangle_class_name (work
, mangled
, &btype
)) {
3422 remember_Btype (work
, btype
.b
, LEN_STRING (&btype
), bindex
);
3423 APPEND_BLANK (result
);
3424 string_appends (result
, &btype
);
3428 string_delete (&btype
);
3433 success
= demangle_template (work
, mangled
, &btype
, 0, 1, 1);
3434 string_appends (result
, &btype
);
3442 return success
? ((int) tk
) : 0;
3446 /* Handle a template's value parameter for HP aCC (extension from ARM)
3447 **mangled points to 'S' or 'U' */
3450 do_hpacc_template_const_value (work
, mangled
, result
)
3451 struct work_stuff
*work
;
3452 const char **mangled
;
3457 if (**mangled
!= 'U' && **mangled
!= 'S')
3460 unsigned_const
= (**mangled
== 'U');
3467 string_append (result
, "-");
3473 /* special case for -2^31 */
3474 string_append (result
, "-2147483648");
3481 /* We have to be looking at an integer now */
3482 if (!(isdigit ((unsigned char)**mangled
)))
3485 /* We only deal with integral values for template
3486 parameters -- so it's OK to look only for digits */
3487 while (isdigit ((unsigned char)**mangled
))
3489 char_str
[0] = **mangled
;
3490 string_append (result
, char_str
);
3495 string_append (result
, "U");
3497 /* FIXME? Some day we may have 64-bit (or larger :-) ) constants
3498 with L or LL suffixes. pai/1997-09-03 */
3500 return 1; /* success */
3503 /* Handle a template's literal parameter for HP aCC (extension from ARM)
3504 **mangled is pointing to the 'A' */
3507 do_hpacc_template_literal (work
, mangled
, result
)
3508 struct work_stuff
*work
;
3509 const char **mangled
;
3512 int literal_len
= 0;
3516 if (**mangled
!= 'A')
3521 literal_len
= consume_count (mangled
);
3523 if (literal_len
<= 0)
3526 /* Literal parameters are names of arrays, functions, etc. and the
3527 canonical representation uses the address operator */
3528 string_append (result
, "&");
3530 /* Now recursively demangle the literal name */
3531 recurse
= (char *) xmalloc (literal_len
+ 1);
3532 memcpy (recurse
, *mangled
, literal_len
);
3533 recurse
[literal_len
] = '\000';
3535 recurse_dem
= cplus_demangle (recurse
, work
->options
);
3539 string_append (result
, recurse_dem
);
3544 string_appendn (result
, *mangled
, literal_len
);
3546 (*mangled
) += literal_len
;
3553 snarf_numeric_literal (args
, arg
)
3560 string_append (arg
, char_str
);
3563 else if (**args
== '+')
3566 if (!isdigit ((unsigned char)**args
))
3569 while (isdigit ((unsigned char)**args
))
3571 char_str
[0] = **args
;
3572 string_append (arg
, char_str
);
3579 /* Demangle the next argument, given by MANGLED into RESULT, which
3580 *should be an uninitialized* string. It will be initialized here,
3581 and free'd should anything go wrong. */
3584 do_arg (work
, mangled
, result
)
3585 struct work_stuff
*work
;
3586 const char **mangled
;
3589 /* Remember where we started so that we can record the type, for
3590 non-squangling type remembering. */
3591 const char *start
= *mangled
;
3593 string_init (result
);
3595 if (work
->nrepeats
> 0)
3599 if (work
->previous_argument
== 0)
3602 /* We want to reissue the previous type in this argument list. */
3603 string_appends (result
, work
->previous_argument
);
3607 if (**mangled
== 'n')
3609 /* A squangling-style repeat. */
3611 work
->nrepeats
= consume_count(mangled
);
3613 if (work
->nrepeats
<= 0)
3614 /* This was not a repeat count after all. */
3617 if (work
->nrepeats
> 9)
3619 if (**mangled
!= '_')
3620 /* The repeat count should be followed by an '_' in this
3627 /* Now, the repeat is all set up. */
3628 return do_arg (work
, mangled
, result
);
3631 /* Save the result in WORK->previous_argument so that we can find it
3632 if it's repeated. Note that saving START is not good enough: we
3633 do not want to add additional types to the back-referenceable
3634 type vector when processing a repeated type. */
3635 if (work
->previous_argument
)
3636 string_clear (work
->previous_argument
);
3639 work
->previous_argument
= (string
*) xmalloc (sizeof (string
));
3640 string_init (work
->previous_argument
);
3643 if (!do_type (work
, mangled
, work
->previous_argument
))
3646 string_appends (result
, work
->previous_argument
);
3648 remember_type (work
, start
, *mangled
- start
);
3653 remember_type (work
, start
, len
)
3654 struct work_stuff
*work
;
3660 if (work
->forgetting_types
)
3663 if (work
-> ntypes
>= work
-> typevec_size
)
3665 if (work
-> typevec_size
== 0)
3667 work
-> typevec_size
= 3;
3669 = (char **) xmalloc (sizeof (char *) * work
-> typevec_size
);
3673 work
-> typevec_size
*= 2;
3675 = (char **) xrealloc ((char *)work
-> typevec
,
3676 sizeof (char *) * work
-> typevec_size
);
3679 tem
= xmalloc (len
+ 1);
3680 memcpy (tem
, start
, len
);
3682 work
-> typevec
[work
-> ntypes
++] = tem
;
3686 /* Remember a K type class qualifier. */
3688 remember_Ktype (work
, start
, len
)
3689 struct work_stuff
*work
;
3695 if (work
-> numk
>= work
-> ksize
)
3697 if (work
-> ksize
== 0)
3701 = (char **) xmalloc (sizeof (char *) * work
-> ksize
);
3707 = (char **) xrealloc ((char *)work
-> ktypevec
,
3708 sizeof (char *) * work
-> ksize
);
3711 tem
= xmalloc (len
+ 1);
3712 memcpy (tem
, start
, len
);
3714 work
-> ktypevec
[work
-> numk
++] = tem
;
3717 /* Register a B code, and get an index for it. B codes are registered
3718 as they are seen, rather than as they are completed, so map<temp<char> >
3719 registers map<temp<char> > as B0, and temp<char> as B1 */
3722 register_Btype (work
)
3723 struct work_stuff
*work
;
3727 if (work
-> numb
>= work
-> bsize
)
3729 if (work
-> bsize
== 0)
3733 = (char **) xmalloc (sizeof (char *) * work
-> bsize
);
3739 = (char **) xrealloc ((char *)work
-> btypevec
,
3740 sizeof (char *) * work
-> bsize
);
3743 ret
= work
-> numb
++;
3744 work
-> btypevec
[ret
] = NULL
;
3748 /* Store a value into a previously registered B code type. */
3751 remember_Btype (work
, start
, len
, index
)
3752 struct work_stuff
*work
;
3758 tem
= xmalloc (len
+ 1);
3759 memcpy (tem
, start
, len
);
3761 work
-> btypevec
[index
] = tem
;
3764 /* Lose all the info related to B and K type codes. */
3766 forget_B_and_K_types (work
)
3767 struct work_stuff
*work
;
3771 while (work
-> numk
> 0)
3773 i
= --(work
-> numk
);
3774 if (work
-> ktypevec
[i
] != NULL
)
3776 free (work
-> ktypevec
[i
]);
3777 work
-> ktypevec
[i
] = NULL
;
3781 while (work
-> numb
> 0)
3783 i
= --(work
-> numb
);
3784 if (work
-> btypevec
[i
] != NULL
)
3786 free (work
-> btypevec
[i
]);
3787 work
-> btypevec
[i
] = NULL
;
3791 /* Forget the remembered types, but not the type vector itself. */
3795 struct work_stuff
*work
;
3799 while (work
-> ntypes
> 0)
3801 i
= --(work
-> ntypes
);
3802 if (work
-> typevec
[i
] != NULL
)
3804 free (work
-> typevec
[i
]);
3805 work
-> typevec
[i
] = NULL
;
3810 /* Process the argument list part of the signature, after any class spec
3811 has been consumed, as well as the first 'F' character (if any). For
3814 "__als__3fooRT0" => process "RT0"
3815 "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i"
3817 DECLP must be already initialised, usually non-empty. It won't be freed
3820 Note that g++ differs significantly from ARM and lucid style mangling
3821 with regards to references to previously seen types. For example, given
3822 the source fragment:
3826 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
3829 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3830 void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3832 g++ produces the names:
3837 while lcc (and presumably other ARM style compilers as well) produces:
3839 foo__FiR3fooT1T2T1T2
3840 __ct__3fooFiR3fooT1T2T1T2
3842 Note that g++ bases its type numbers starting at zero and counts all
3843 previously seen types, while lucid/ARM bases its type numbers starting
3844 at one and only considers types after it has seen the 'F' character
3845 indicating the start of the function args. For lucid/ARM style, we
3846 account for this difference by discarding any previously seen types when
3847 we see the 'F' character, and subtracting one from the type number
3853 demangle_args (work
, mangled
, declp
)
3854 struct work_stuff
*work
;
3855 const char **mangled
;
3865 if (PRINT_ARG_TYPES
)
3867 string_append (declp
, "(");
3868 if (**mangled
== '\0')
3870 string_append (declp
, "void");
3874 while ((**mangled
!= '_' && **mangled
!= '\0' && **mangled
!= 'e')
3875 || work
->nrepeats
> 0)
3877 if ((**mangled
== 'N') || (**mangled
== 'T'))
3879 temptype
= *(*mangled
)++;
3881 if (temptype
== 'N')
3883 if (!get_count (mangled
, &r
))
3892 if ((HP_DEMANGLING
|| ARM_DEMANGLING
|| EDG_DEMANGLING
) && work
-> ntypes
>= 10)
3894 /* If we have 10 or more types we might have more than a 1 digit
3895 index so we'll have to consume the whole count here. This
3896 will lose if the next thing is a type name preceded by a
3897 count but it's impossible to demangle that case properly
3898 anyway. Eg if we already have 12 types is T12Pc "(..., type1,
3899 Pc, ...)" or "(..., type12, char *, ...)" */
3900 if ((t
= consume_count(mangled
)) <= 0)
3907 if (!get_count (mangled
, &t
))
3912 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
|| HP_DEMANGLING
|| EDG_DEMANGLING
)
3916 /* Validate the type index. Protect against illegal indices from
3917 malformed type strings. */
3918 if ((t
< 0) || (t
>= work
-> ntypes
))
3922 while (work
->nrepeats
> 0 || --r
>= 0)
3924 tem
= work
-> typevec
[t
];
3925 if (need_comma
&& PRINT_ARG_TYPES
)
3927 string_append (declp
, ", ");
3929 if (!do_arg (work
, &tem
, &arg
))
3933 if (PRINT_ARG_TYPES
)
3935 string_appends (declp
, &arg
);
3937 string_delete (&arg
);
3943 if (need_comma
&& PRINT_ARG_TYPES
)
3944 string_append (declp
, ", ");
3945 if (!do_arg (work
, mangled
, &arg
))
3947 if (PRINT_ARG_TYPES
)
3948 string_appends (declp
, &arg
);
3949 string_delete (&arg
);
3954 if (**mangled
== 'e')
3957 if (PRINT_ARG_TYPES
)
3961 string_append (declp
, ",");
3963 string_append (declp
, "...");
3967 if (PRINT_ARG_TYPES
)
3969 string_append (declp
, ")");
3974 /* Like demangle_args, but for demangling the argument lists of function
3975 and method pointers or references, not top-level declarations. */
3978 demangle_nested_args (work
, mangled
, declp
)
3979 struct work_stuff
*work
;
3980 const char **mangled
;
3983 string
* saved_previous_argument
;
3987 /* The G++ name-mangling algorithm does not remember types on nested
3988 argument lists, unless -fsquangling is used, and in that case the
3989 type vector updated by remember_type is not used. So, we turn
3990 off remembering of types here. */
3991 ++work
->forgetting_types
;
3993 /* For the repeat codes used with -fsquangling, we must keep track of
3994 the last argument. */
3995 saved_previous_argument
= work
->previous_argument
;
3996 saved_nrepeats
= work
->nrepeats
;
3997 work
->previous_argument
= 0;
4000 /* Actually demangle the arguments. */
4001 result
= demangle_args (work
, mangled
, declp
);
4003 /* Restore the previous_argument field. */
4004 if (work
->previous_argument
)
4005 string_delete (work
->previous_argument
);
4006 work
->previous_argument
= saved_previous_argument
;
4007 --work
->forgetting_types
;
4008 work
->nrepeats
= saved_nrepeats
;
4014 demangle_function_name (work
, mangled
, declp
, scan
)
4015 struct work_stuff
*work
;
4016 const char **mangled
;
4024 string_appendn (declp
, (*mangled
), scan
- (*mangled
));
4025 string_need (declp
, 1);
4026 *(declp
-> p
) = '\0';
4028 /* Consume the function name, including the "__" separating the name
4029 from the signature. We are guaranteed that SCAN points to the
4032 (*mangled
) = scan
+ 2;
4033 /* We may be looking at an instantiation of a template function:
4034 foo__Xt1t2_Ft3t4, where t1, t2, ... are template arguments and a
4035 following _F marks the start of the function arguments. Handle
4036 the template arguments first. */
4038 if (HP_DEMANGLING
&& (**mangled
== 'X'))
4040 demangle_arm_hp_template (work
, mangled
, 0, declp
);
4041 /* This leaves MANGLED pointing to the 'F' marking func args */
4044 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
|| HP_DEMANGLING
|| EDG_DEMANGLING
)
4047 /* See if we have an ARM style constructor or destructor operator.
4048 If so, then just record it, clear the decl, and return.
4049 We can't build the actual constructor/destructor decl until later,
4050 when we recover the class name from the signature. */
4052 if (strcmp (declp
-> b
, "__ct") == 0)
4054 work
-> constructor
+= 1;
4055 string_clear (declp
);
4058 else if (strcmp (declp
-> b
, "__dt") == 0)
4060 work
-> destructor
+= 1;
4061 string_clear (declp
);
4066 if (declp
->p
- declp
->b
>= 3
4067 && declp
->b
[0] == 'o'
4068 && declp
->b
[1] == 'p'
4069 && strchr (cplus_markers
, declp
->b
[2]) != NULL
)
4071 /* see if it's an assignment expression */
4072 if (declp
->p
- declp
->b
>= 10 /* op$assign_ */
4073 && memcmp (declp
->b
+ 3, "assign_", 7) == 0)
4075 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
4077 int len
= declp
->p
- declp
->b
- 10;
4078 if ((int) strlen (optable
[i
].in
) == len
4079 && memcmp (optable
[i
].in
, declp
->b
+ 10, len
) == 0)
4081 string_clear (declp
);
4082 string_append (declp
, "operator");
4083 string_append (declp
, optable
[i
].out
);
4084 string_append (declp
, "=");
4091 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
4093 int len
= declp
->p
- declp
->b
- 3;
4094 if ((int) strlen (optable
[i
].in
) == len
4095 && memcmp (optable
[i
].in
, declp
->b
+ 3, len
) == 0)
4097 string_clear (declp
);
4098 string_append (declp
, "operator");
4099 string_append (declp
, optable
[i
].out
);
4105 else if (declp
->p
- declp
->b
>= 5 && memcmp (declp
->b
, "type", 4) == 0
4106 && strchr (cplus_markers
, declp
->b
[4]) != NULL
)
4108 /* type conversion operator */
4110 if (do_type (work
, &tem
, &type
))
4112 string_clear (declp
);
4113 string_append (declp
, "operator ");
4114 string_appends (declp
, &type
);
4115 string_delete (&type
);
4118 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
4119 && declp
->b
[2] == 'o' && declp
->b
[3] == 'p')
4122 /* type conversion operator. */
4124 if (do_type (work
, &tem
, &type
))
4126 string_clear (declp
);
4127 string_append (declp
, "operator ");
4128 string_appends (declp
, &type
);
4129 string_delete (&type
);
4132 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
4133 && declp
->b
[2] >= 'a' && declp
->b
[2] <= 'z'
4134 && declp
->b
[3] >= 'a' && declp
->b
[3] <= 'z')
4136 if (declp
->b
[4] == '\0')
4139 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
4141 if (strlen (optable
[i
].in
) == 2
4142 && memcmp (optable
[i
].in
, declp
->b
+ 2, 2) == 0)
4144 string_clear (declp
);
4145 string_append (declp
, "operator");
4146 string_append (declp
, optable
[i
].out
);
4153 if (declp
->b
[2] == 'a' && declp
->b
[5] == '\0')
4156 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
4158 if (strlen (optable
[i
].in
) == 3
4159 && memcmp (optable
[i
].in
, declp
->b
+ 2, 3) == 0)
4161 string_clear (declp
);
4162 string_append (declp
, "operator");
4163 string_append (declp
, optable
[i
].out
);
4172 /* a mini string-handling package */
4187 s
->p
= s
->b
= xmalloc (n
);
4190 else if (s
->e
- s
->p
< n
)
4195 s
->b
= xrealloc (s
->b
, n
);
4208 s
->b
= s
->e
= s
->p
= NULL
;
4216 s
->b
= s
->p
= s
->e
= NULL
;
4232 return (s
->b
== s
->p
);
4238 string_append (p
, s
)
4243 if (s
== NULL
|| *s
== '\0')
4247 memcpy (p
->p
, s
, n
);
4252 string_appends (p
, s
)
4261 memcpy (p
->p
, s
->b
, n
);
4267 string_appendn (p
, s
, n
)
4275 memcpy (p
->p
, s
, n
);
4281 string_prepend (p
, s
)
4285 if (s
!= NULL
&& *s
!= '\0')
4287 string_prependn (p
, s
, strlen (s
));
4292 string_prepends (p
, s
)
4297 string_prependn (p
, s
->b
, s
->p
- s
->b
);
4302 string_prependn (p
, s
, n
)
4312 for (q
= p
->p
- 1; q
>= p
->b
; q
--)
4316 memcpy (p
->b
, s
, n
);
4321 /* To generate a standalone demangler program for testing purposes,
4322 just compile and link this file with -DMAIN and libiberty.a. When
4323 run, it demangles each command line arg, or each stdin string, and
4324 prints the result on stdout. */
4330 static char *program_name
;
4331 static char *program_version
= VERSION
;
4332 static int flags
= DMGL_PARAMS
| DMGL_ANSI
;
4334 static void demangle_it
PARAMS ((char *));
4335 static void usage
PARAMS ((FILE *, int));
4336 static void fatal
PARAMS ((char *));
4339 demangle_it (mangled_name
)
4344 result
= cplus_demangle (mangled_name
, flags
);
4347 printf ("%s\n", mangled_name
);
4351 printf ("%s\n", result
);
4357 usage (stream
, status
)
4362 Usage: %s [-_] [-n] [-s {gnu,lucid,arm,hp,edg}] [--strip-underscores]\n\
4363 [--no-strip-underscores] [--format={gnu,lucid,arm,hp,edg}]\n\
4364 [--help] [--version] [arg...]\n",
4369 #define MBUF_SIZE 32767
4370 char mbuffer
[MBUF_SIZE
];
4372 /* Defined in the automatically-generated underscore.c. */
4373 extern int prepends_underscore
;
4375 int strip_underscore
= 0;
4377 static struct option long_options
[] = {
4378 {"strip-underscores", no_argument
, 0, '_'},
4379 {"format", required_argument
, 0, 's'},
4380 {"help", no_argument
, 0, 'h'},
4381 {"java", no_argument
, 0, 'j'},
4382 {"no-strip-underscores", no_argument
, 0, 'n'},
4383 {"version", no_argument
, 0, 'v'},
4384 {0, no_argument
, 0, 0}
4387 /* More 'friendly' abort that prints the line and file.
4388 config.h can #define abort fancy_abort if you like that sort of thing. */
4393 fatal ("Internal gcc abort.");
4397 /* Fill in TABLE so that TABLE[C] is true iff C (as an unsigned char)
4398 is a valid symbol component, in the standard assembler symbol
4401 standard_symbol_alphabet (char *table
)
4405 for (c
= 0; c
< 256; c
++)
4406 table
[c
] = isalnum(c
);
4414 /* Fill in TABLE so that TABLE[C] is true iff C (as an unsigned char)
4415 is a valid symbol name component in an HP object file.
4417 Note that, since HP's compiler generates object code straight from
4418 C++ source, without going through an assembler, its mangled
4419 identifiers can use all sorts of characters that no assembler would
4420 tolerate, so the alphabet this function creates is a little odd.
4421 Here are some sample mangled identifiers offered by HP:
4423 typeid*__XT24AddressIndExpClassMember_
4424 [Vftptr]key:__dt__32OrdinaryCompareIndExpClassMemberFv
4425 __ct__Q2_9Elf64_Dyn18{unnamed.union.#1}Fv
4427 This still seems really weird to me, since nowhere else in this
4428 file is there anything to recognize curly brackets, parens, etc.
4429 I've talked with Srikanth <srikanth@cup.hp.com>, and he assures me
4430 this is right, but I still strongly suspect that there's a
4431 misunderstanding here.
4433 If we decide it's better for c++filt to use HP's assembler syntax
4434 to scrape identifiers out of its input, here's the definition of
4435 the symbol name syntax from the HP assembler manual:
4437 Symbols are composed of uppercase and lowercase letters, decimal
4438 digits, dollar symbol, period (.), ampersand (&), pound sign(#) and
4439 underscore (_). A symbol can begin with a letter, digit underscore or
4440 dollar sign. If a symbol begins with a digit, it must contain a
4441 non-digit character.
4445 hp_symbol_alphabet (char *table
)
4449 standard_symbol_alphabet (table
);
4451 for (c
= "<>#,*&[]:(){}"; *c
; c
++)
4452 table
[(unsigned char) *c
] = 1;
4463 char symbol_alphabet
[256];
4465 program_name
= argv
[0];
4467 strip_underscore
= prepends_underscore
;
4469 while ((c
= getopt_long (argc
, argv
, "_ns:j", long_options
, (int *) 0)) != EOF
)
4479 strip_underscore
= 0;
4482 printf ("GNU %s (C++ demangler), version %s\n", program_name
, program_version
);
4485 strip_underscore
= 1;
4491 if (strcmp (optarg
, "gnu") == 0)
4493 current_demangling_style
= gnu_demangling
;
4495 else if (strcmp (optarg
, "lucid") == 0)
4497 current_demangling_style
= lucid_demangling
;
4499 else if (strcmp (optarg
, "arm") == 0)
4501 current_demangling_style
= arm_demangling
;
4503 else if (strcmp (optarg
, "hp") == 0)
4505 current_demangling_style
= hp_demangling
;
4507 else if (strcmp (optarg
, "edg") == 0)
4509 current_demangling_style
= edg_demangling
;
4513 fprintf (stderr
, "%s: unknown demangling style `%s'\n",
4514 program_name
, optarg
);
4523 for ( ; optind
< argc
; optind
++)
4525 demangle_it (argv
[optind
]);
4530 switch (current_demangling_style
)
4532 case gnu_demangling
:
4533 case lucid_demangling
:
4534 case arm_demangling
:
4535 case edg_demangling
:
4536 standard_symbol_alphabet (symbol_alphabet
);
4539 hp_symbol_alphabet (symbol_alphabet
);
4542 /* Folks should explicitly indicate the appropriate alphabet for
4543 each demangling. Providing a default would allow the
4544 question to go unconsidered. */
4552 /* Try to read a label. */
4553 while (c
!= EOF
&& symbol_alphabet
[c
])
4555 if (i
>= MBUF_SIZE
-1)
4564 if (mbuffer
[0] == '.')
4566 if (strip_underscore
&& mbuffer
[skip_first
] == '_')
4574 result
= cplus_demangle (mbuffer
+ skip_first
, flags
);
4577 if (mbuffer
[0] == '.')
4579 fputs (result
, stdout
);
4583 fputs (mbuffer
, stdout
);
4600 fprintf (stderr
, "%s: %s\n", program_name
, str
);
4608 register PTR value
= (PTR
) malloc (size
);
4610 fatal ("virtual memory exhausted");
4615 xrealloc (ptr
, size
)
4619 register PTR value
= (PTR
) realloc (ptr
, size
);
4621 fatal ("virtual memory exhausted");